{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "d3a1c534",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "from seeq import spy\n",
    "\n",
    "# Set the compatibility option so that you maximize the chance that SPy will remain compatible with your notebook/script\n",
    "spy.options.compatibility = 193"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "f4146468",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Logged in to <strong>http://localhost:34216</strong> as <strong>agent_api_key</strong>.<br>Seeq Server Version: <strong>R66.0.0-SNAPSHOT</strong><br>Seeq SDK Module Version: <strong>66.0.0</strong> @ C:\\git\\crab\\sdk\\pypi\\seeq\\sdk<br>Seeq SPy Module Version: <strong>193.0</strong> @ C:\\git\\crab\\sdk\\pypi\\seeq\\spy</div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Log into Seeq Server if you're not using Seeq Data Lab:\n",
    "spy.login(url='http://localhost:34216', credentials_file='../credentials.key', force=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6de9eed7",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "# Workbook Templates\n",
    "\n",
    "A _workbook_ is either a Workbench Analysis or an Organizer Topic. You create workbooks in SPy in a variety of ways:\n",
    "\n",
    "- When you execute [spy.push()](spy.push.ipynb), a workbook will be created and the signals/conditions pushed will be scoped to that workbook.\n",
    "- You can execute [spy.workbooks.push()](spy.workbooks.ipynb) to push workbooks that have been saved to disk.\n",
    "- You can associate workbooks with asset trees that have been defined using [spy.assets](Asset%20Trees%202%20-%20Templates.ipynb).\n",
    "\n",
    "The easiest way to define the configuration and content of a workbook is by using the Workbench and Organizer user interface to create _template workbooks_."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e5d97620",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "## Creating a Template\n",
    "\n",
    "To create an Analysis template, you simply go into Workbench and create a workbook and as many worksheets as you need to define the template. Add \"placeholder\" items to the worksheet and arrange/configure the worksheet in whatever way makes sense for your use case. You can make entries in the worksheet's journal as well, including images and workstep links.\n",
    "\n",
    "The `sinusoid()` function (using the Formula Tool) is a great way to create placeholders, because you can easily tailor it to the range and units you expect to see after you've substituted in real data in the steps that follow.\n",
    "\n",
    "Once you're finished configuring the workbooks and worksheets, you will use SPy to save the workbook to disk so that you can later use it as a template. Just copy the URL from the browser's address bar and replace the value of the `url` variable in the code below:\n",
    "\n",
    "```\n",
    "url = 'http://localhost:34216/workbook/3EA21D97-782B-472B-B065-2DC76ECC152F/worksheet/4ED5F9B9-D82F-4017-ACEE-0EBBD1CC4E13'\n",
    "\n",
    "workbooks = spy.workbooks.pull(url)\n",
    "spy.workbooks.save(workbooks, 'My First Workbook Template')\n",
    "```\n",
    "\n",
    "This will save the workbook files to a folder on disk called `My First Workbook Template` and you'll see how we load it below."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "664472e2-ea89-4412-a34e-c2bced5e037b",
   "metadata": {},
   "source": [
    "### Installing Template Requirements\n",
    "\n",
    "From SPy 193.0 on, SPy core does not install requirements needed for Templates by default. You may need to execute the install command below to use Templates in your python environment."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "37eaf977-4ec5-440a-8966-03b4710badb5",
   "metadata": {},
   "outputs": [],
   "source": [
    "# pip install seeq-spy[templates]"
   ]
  },
  {
   "attachments": {
    "AnalysisTemplateScreenshot.jpg": {
     "image/jpeg": "[encoded data, 181028 characters]"
    }
   },
   "cell_type": "markdown",
   "id": "c7eccd3a",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "## Loading a Template\n",
    "\n",
    "Now let's say you want to use the template to control the workbook that is created when you call `spy.push()`.\n",
    "\n",
    "In this example, we'll use a template that's built into this SPy documentation notebook. As you can see in the screenshot below, the workbook has been configured with several worksheets. The first is called \"Trend Template\" and has three items in it.\n",
    "\n",
    "Notice how the Journal entry has text that is surrounded by double-curly-braces, like `{{favorite color}}`. This is referred to as a _mustache variable_ (named after the popular [Mustache templating system](https://en.wikipedia.org/wiki/Mustache_(template_system))). These variables can be replaced by values you specify in Python before you push, as you will see further below.\n",
    "\n",
    "![AnalysisTemplateScreenshot.jpg](attachment:AnalysisTemplateScreenshot.jpg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "6930bae3",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Success</div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/plain": [
       "Worksheet \"Trend Template\" (C9BAE059-F996-46B8-AEC2-6FB62A45400A agent_api_key Workbook Template Example 1)"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Load the template shown above (included in SPy for the purposes of this example).\n",
    "# Note how the `as_template_with_label` argument is used here, which is the key to establishing the loaded\n",
    "# workbooks as templates instead of regular workbook objects. The specified label must be set to something\n",
    "# unique across the entire Seeq service so that there aren't any identifier conflicts when pushing. If\n",
    "# you're unsure, just include your name and that will usually be unique. For convenience in this example,\n",
    "# we will use the logged-in user's name.\n",
    "workbooks = spy.workbooks.load('./Support Files/Workbook Templates.zip',\n",
    "                               as_template_with_label=f'{spy.user.username} Workbook Template Example 1')\n",
    "\n",
    "\n",
    "# Grab the Analysis Workbook from the list\n",
    "analysis_template = workbooks['Analysis Template']\n",
    "\n",
    "# Retrieve a specific analysis worksheet from the list of returned workbooks\n",
    "worksheet = analysis_template.worksheets['Trend Template']\n",
    "\n",
    "worksheet"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "c6b81030",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Workbook \"Users >> mark.derbecker@seeq.com >> Workbook Templates >> Analysis Template\" (F01FD57A-1112-4020-9430-CF27C2847D1B agent_api_key Workbook Template Example 1),\n",
       " Workbook \"Users >> mark.derbecker@seeq.com >> Workbook Templates >> Asset Selector Analysis Template\" (0EF59E6B-546A-6230-8251-02C2AE9EE8C1 agent_api_key Workbook Template Example 1),\n",
       " Workbook \"Users >> mark.derbecker@seeq.com >> Workbook Templates >> Asset Selector Topic Template\" (0EF59E6D-EE87-60A0-A4E3-AA13C6B2FE18 agent_api_key Workbook Template Example 1),\n",
       " Workbook \"Users >> mark.derbecker@seeq.com >> Workbook Templates >> Data Lab Visualization Example\" (6BAED6F7-3DF3-4238-AB18-7A9ABE284581 agent_api_key Workbook Template Example 1),\n",
       " Workbook \"Users >> mark.derbecker@seeq.com >> Workbook Templates >> Topic Template\" (90931EF8-D80B-4F22-8568-3683DD806D50 agent_api_key Workbook Template Example 1)]"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "workbooks"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b934ba1f",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "When you load a workbook as a template, it exposes a `code` attribute that tells you how to plug specific items into the template. These are referred to as the _parameters_."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "adb25e8e",
   "metadata": {
    "keep_output_in_docs": true,
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "worksheet.parameters = {\n",
      "    \"9564A6B8-8A8F-4F6D-AC63-00EA38962B7A [Signal] Area A_Temperature\": None,\n",
      "    \"D2C089B6-CE85-46FC-8392-E11CC0C08336 [Signal] Area A_Compressor Stage\": None,\n",
      "    \"DCED9C36-A4BE-4783-9216-DC06B3F57D8C [Signal] Area A_Compressor Power\": None,\n",
      "    \"Temperature Journal Link Text\": None,\n",
      "    \"Compressor Power Journal Link Text\": None,\n",
      "    \"Compressor Stage Journal Link Text\": None,\n",
      "    \"favorite color\": None\n",
      "}\n"
     ]
    }
   ],
   "source": [
    "print(worksheet.code)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1dec3bdd",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "This worksheet contains three display items that can be replaced by items of our choosing, as well as several Mustache variables from the Journal.\n",
    "\n",
    "You will see below how we replace the `None` values with the items we want."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "91e72394",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "## Pushing with a Template Worksheet\n",
    "\n",
    "First let's create a metadata DataFrame with some sinusoids:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "4c9e319d",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "metadata_df = pd.DataFrame([{\n",
    "    'Name': 'Sinusoid 1',\n",
    "    'Type': 'Signal',\n",
    "    'Formula': 'sinusoid(1h)'\n",
    "}, {\n",
    "    'Name': 'Sinusoid 2',\n",
    "    'Type': 'Signal',\n",
    "    'Formula': 'sinusoid(2h)'\n",
    "}, {\n",
    "    'Name': 'Sinusoid 3',\n",
    "    'Type': 'Signal',\n",
    "    'Formula': 'sinusoid(3h)'\n",
    "}])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "801e42e1",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "Next, we will copy and paste the code block that we printed earlier into a real code cell so that we can set the parameters appropriately. In this example, we're just specifying the `Name` of the signals (replacing the `None` placeholders), but we could have supplied `ID`, `Type`, `Path` and/or `Asset` values that correspond to the row being pushed. (It can also be a one-row DataFrame instead of a dictionary.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "431c4e06",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "worksheet.parameters = {\n",
    "    \"9564A6B8-8A8F-4F6D-AC63-00EA38962B7A [Signal] Area A_Temperature\": {'Name': 'Sinusoid 1'},\n",
    "    \"DCED9C36-A4BE-4783-9216-DC06B3F57D8C [Signal] Area A_Compressor Power\": {'Name': 'Sinusoid 2'},\n",
    "    \"D2C089B6-CE85-46FC-8392-E11CC0C08336 [Signal] Area A_Compressor Stage\": {'Name': 'Sinusoid 3'},\n",
    "    \"Temperature Journal Link Text\": 'SINUSOID 1',\n",
    "    \"Compressor Power Journal Link Text\": 'SINUSOID 2',\n",
    "    \"Compressor Stage Journal Link Text\": 'SINUSOID 3',\n",
    "    \"favorite color\": 'blue'\n",
    "}\n",
    "\n",
    "# Give the worksheet a different name than \"Trend Template\"\n",
    "worksheet.name = 'My Trend!'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "dd820cb8",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "Now we push the metadata DataFrame and pass in the worksheet argument:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "80286f9e",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Pushed successfully to datasource <strong>Seeq Data Lab [Datasource ID: Seeq Data Lab]</strong> and scoped to workbook ID <strong>0EF5A987-CA96-75E0-A06A-903E9F4EB5C9</strong><br>Click the following link to see what you pushed in Seeq:<br><a href=\"http://localhost:34216/0EF5A972-6BC7-6060-B9B4-D9E33D738E94/workbook/0EF5A987-CA96-75E0-A06A-903E9F4EB5C9/worksheet/0EF5A987-CF9C-FFD0-BB33-79A32C060E78\" target=\"_blank\">http://localhost:34216/0EF5A972-6BC7-6060-B9B4-D9E33D738E94/workbook/0EF5A987-CA96-75E0-A06A-903E9F4EB5C9/worksheet/0EF5A987-CF9C-FFD0-BB33-79A32C060E78</a></div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Name</th>\n",
       "      <th>Type</th>\n",
       "      <th>Formula</th>\n",
       "      <th>Scoped To</th>\n",
       "      <th>Datasource Class</th>\n",
       "      <th>Datasource ID</th>\n",
       "      <th>Formula Parameters</th>\n",
       "      <th>Data ID</th>\n",
       "      <th>ID</th>\n",
       "      <th>Push Result</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Sinusoid 1</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>sinusoid(1h)</td>\n",
       "      <td>0EF5A987-CA96-75E0-A06A-903E9F4EB5C9</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[]</td>\n",
       "      <td>[0EF5A987-CA96-75E0-A06A-903E9F4EB5C9] {Signal...</td>\n",
       "      <td>0EF5A987-CB88-7110-B9D7-E3F3BA958562</td>\n",
       "      <td>Success</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Sinusoid 2</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>sinusoid(2h)</td>\n",
       "      <td>0EF5A987-CA96-75E0-A06A-903E9F4EB5C9</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[]</td>\n",
       "      <td>[0EF5A987-CA96-75E0-A06A-903E9F4EB5C9] {Signal...</td>\n",
       "      <td>0EF5A987-CBB4-6030-9B9C-F9475973ADD2</td>\n",
       "      <td>Success</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Sinusoid 3</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>sinusoid(3h)</td>\n",
       "      <td>0EF5A987-CA96-75E0-A06A-903E9F4EB5C9</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[]</td>\n",
       "      <td>[0EF5A987-CA96-75E0-A06A-903E9F4EB5C9] {Signal...</td>\n",
       "      <td>0EF5A987-CBCC-66D0-B8AC-1C8604FA0540</td>\n",
       "      <td>Success</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "         Name              Type       Formula  \\\n",
       "0  Sinusoid 1  CalculatedSignal  sinusoid(1h)   \n",
       "1  Sinusoid 2  CalculatedSignal  sinusoid(2h)   \n",
       "2  Sinusoid 3  CalculatedSignal  sinusoid(3h)   \n",
       "\n",
       "                              Scoped To Datasource Class  Datasource ID  \\\n",
       "0  0EF5A987-CA96-75E0-A06A-903E9F4EB5C9    Seeq Data Lab  Seeq Data Lab   \n",
       "1  0EF5A987-CA96-75E0-A06A-903E9F4EB5C9    Seeq Data Lab  Seeq Data Lab   \n",
       "2  0EF5A987-CA96-75E0-A06A-903E9F4EB5C9    Seeq Data Lab  Seeq Data Lab   \n",
       "\n",
       "  Formula Parameters                                            Data ID  \\\n",
       "0                 []  [0EF5A987-CA96-75E0-A06A-903E9F4EB5C9] {Signal...   \n",
       "1                 []  [0EF5A987-CA96-75E0-A06A-903E9F4EB5C9] {Signal...   \n",
       "2                 []  [0EF5A987-CA96-75E0-A06A-903E9F4EB5C9] {Signal...   \n",
       "\n",
       "                                     ID Push Result  \n",
       "0  0EF5A987-CB88-7110-B9D7-E3F3BA958562     Success  \n",
       "1  0EF5A987-CBB4-6030-9B9C-F9475973ADD2     Success  \n",
       "2  0EF5A987-CBCC-66D0-B8AC-1C8604FA0540     Success  "
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "spy.push(metadata=metadata_df, workbook='Workbook Template Example 1', worksheet=worksheet)"
   ]
  },
  {
   "attachments": {
    "AnalysisTemplateScreenshot2.jpg": {
     "image/jpeg": "[encoded data, 202824 characters]"
    }
   },
   "cell_type": "markdown",
   "id": "42d5b31b",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "When you click on the link to the workbook/worksheet above, you should see the following:\n",
    "\n",
    "![AnalysisTemplateScreenshot2.jpg](attachment:AnalysisTemplateScreenshot2.jpg)\n",
    "\n",
    "Notice that all of the items have been replaced with the things we pushed, and the mustache variables in the Journal have been replaced by the values we specified in the `worksheet.parameters` above.\n",
    "\n",
    "Note: Both Journals and Organizer Topics are backed by HTML markup. If you want to supply HTML as a parameter for one of the mustache variables, you must declare the variable as `{{&Variable Name}}`. That way the HTML will not be \"escaped\" and be shown to the user literally."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0cc9586d",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "## Pushing with a Template Workbook\n",
    "\n",
    "You can also push an entire workbook instead of just a single worksheet. Following much the same pattern, you will print the parameters code for the workbook like so:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "0c0ada40",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Success</div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "workbooks = spy.workbooks.load('./Support Files/Workbook Templates.zip',\n",
    "                               as_template_with_label=f'{spy.user.username} Workbook Template Example 2')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "e9a8feeb",
   "metadata": {
    "keep_output_in_docs": true,
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "workbook.parameters = {\n",
      "    \"9564A6B8-8A8F-4F6D-AC63-00EA38962B7A [Signal] Area A_Temperature\": None,\n",
      "    \"D2C089B6-CE85-46FC-8392-E11CC0C08336 [Signal] Area A_Compressor Stage\": None,\n",
      "    \"DCED9C36-A4BE-4783-9216-DC06B3F57D8C [Signal] Area A_Compressor Power\": None,\n",
      "    \"Temperature Journal Link Text\": None,\n",
      "    \"Compressor Power Journal Link Text\": None,\n",
      "    \"Compressor Stage Journal Link Text\": None,\n",
      "    \"favorite color\": None,\n",
      "    \"07F3161F-6644-4505-BC33-16D6155B004E [Condition] Hot\": None,\n",
      "    \"D16FC368-AE8E-47B4-B1A3-9C2A3FBA2BB6 [Asset] Example >> Cooling Tower 1\": None,\n",
      "    \"4B40EAFC-91ED-4AB0-8199-F21AF40A8350 [Asset] Example >> Cooling Tower 1 >> Area A\": None,\n",
      "    \"8A4F0E26-8A0C-4127-9E11-B67E031C6049 [Signal] Example >> Cooling Tower 1 >> Area A >> Temperature\": None\n",
      "}\n"
     ]
    }
   ],
   "source": [
    "# Retrieve a specific workbook from the list of returned workbooks\n",
    "workbook = workbooks['Analysis Template']\n",
    "\n",
    "print(workbook.code)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "93136dff",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "Again, we will create a DataFrame full of signals, but this time we'll put them in an asset tree so we can illustrate how to properly populate a Treemap template."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "f8da2513",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "metadata_df = pd.DataFrame([\n",
    "    {'Path': 'Waveforms', 'Asset': 'Waveforms 1', 'Name': 'Sinusoid', 'Type': 'Signal', 'Formula': 'sinusoid(1h)'},\n",
    "    {'Path': 'Waveforms', 'Asset': 'Waveforms 1', 'Name': 'Sawtooth', 'Type': 'Signal', 'Formula': 'sawtooth(1h)'},\n",
    "    {'Path': 'Waveforms', 'Asset': 'Waveforms 1', 'Name': 'Square', 'Type': 'Signal', 'Formula': 'squareWave(1h)'},\n",
    "    {'Path': 'Waveforms', 'Asset': 'Waveforms 1', 'Name': 'Hours', 'Type': 'Condition', 'Formula': 'hours()'},\n",
    "    {'Path': 'Waveforms', 'Asset': 'Waveforms 2', 'Name': 'Sinusoid', 'Type': 'Signal',\n",
    "     'Formula': 'sinusoid(12h, 15V)'},\n",
    "    {'Path': 'Waveforms', 'Asset': 'Waveforms 2', 'Name': 'Sawtooth', 'Type': 'Signal',\n",
    "     'Formula': 'sawtooth(12h, 15V)'},\n",
    "    {'Path': 'Waveforms', 'Asset': 'Waveforms 2', 'Name': 'Square', 'Type': 'Signal',\n",
    "     'Formula': 'squareWave(12h, 15V)'},\n",
    "    {'Path': 'Waveforms', 'Asset': 'Waveforms 2', 'Name': 'Hours', 'Type': 'Condition', 'Formula': 'hours()'},\n",
    "])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "2e52e11a",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "# Provide a name for the pushed workbook. Unlike the previous example where the workbook name was specified\n",
    "# as part of the push arguments, in this case we override it on the template object. You can override any\n",
    "# property of a workbook/worksheet prior to pushing.\n",
    "workbook.name = 'Workbook Template Example 2'\n",
    "\n",
    "workbook.parameters = {\n",
    "    \"DCED9C36-A4BE-4783-9216-DC06B3F57D8C [Signal] Area A_Compressor Power\": {'Asset': 'Waveforms 1',\n",
    "                                                                              'Name': 'Sinusoid'},\n",
    "    \"9564A6B8-8A8F-4F6D-AC63-00EA38962B7A [Signal] Area A_Temperature\": {'Asset': 'Waveforms 1', 'Name': 'Sawtooth'},\n",
    "    \"D2C089B6-CE85-46FC-8392-E11CC0C08336 [Signal] Area A_Compressor Stage\": {'Asset': 'Waveforms 1', 'Name': 'Square'},\n",
    "    \"Temperature Journal Link Text\": 'Sawtooth',\n",
    "    \"Compressor Power Journal Link Text\": 'Sinusoid',\n",
    "    \"Compressor Stage Journal Link Text\": 'Square',\n",
    "    \"favorite color\": 'beige',\n",
    "\n",
    "    # This is the condition used to color the treemap\n",
    "    \"07F3161F-6644-4505-BC33-16D6155B004E [Condition] Hot\": {'Asset': 'Waveforms 1', 'Name': 'Hours'},\n",
    "\n",
    "    # This is the signal used for the Maximum statistic in the treemap and its parent assent\n",
    "    \"8A4F0E26-8A0C-4127-9E11-B67E031C6049 [Signal] Example >> Cooling Tower 1 >> Area A >> Temperature\":\n",
    "        {'Asset': 'Waveforms 1', 'Name': 'Sawtooth'},\n",
    "    \"4B40EAFC-91ED-4AB0-8199-F21AF40A8350 [Asset] Example >> Area A\": {'Asset': 'Waveforms 1', 'Type': 'Asset'},\n",
    "\n",
    "    # This is the parent asset that will be used in the Treemap worksheet\n",
    "    \"D16FC368-AE8E-47B4-B1A3-9C2A3FBA2BB6 [Asset] Cooling Tower 1\": {'Asset': 'Waveforms', 'Type': 'Asset'}\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0d7435a5",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "Now when we push, we'll pass the `workbook` argument instead of the `worksheet` argument."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "04835241",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Pushed successfully to datasource <strong>Seeq Data Lab [Datasource ID: Seeq Data Lab]</strong> and scoped to workbook ID <strong>0EF5A987-D5CD-7760-8866-CEF1777B9415</strong><br>Click the following link to see what you pushed in Seeq:<br><a href=\"http://localhost:34216/0EF5A972-6BC7-6060-B9B4-D9E33D738E94/workbook/0EF5A987-D5CD-7760-8866-CEF1777B9415/worksheet/0EF5A987-D8C7-62E0-829C-50618567C325\" target=\"_blank\">http://localhost:34216/0EF5A972-6BC7-6060-B9B4-D9E33D738E94/workbook/0EF5A987-D5CD-7760-8866-CEF1777B9415/worksheet/0EF5A987-D8C7-62E0-829C-50618567C325</a></div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "pushed_df = spy.push(metadata=metadata_df, workbook=workbook)"
   ]
  },
  {
   "attachments": {
    "AnalysisTemplateScreenshot3.jpg": {
     "image/jpeg": "[encoded data, 276364 characters]"
    }
   },
   "cell_type": "markdown",
   "id": "9246bb0f",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "After pushing, the link will take you to a workbook that has four worksheets whose contents correspond to the template parameters specified above:\n",
    "\n",
    "![AnalysisTemplateScreenshot3.jpg](attachment:AnalysisTemplateScreenshot3.jpg)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d83c196f",
   "metadata": {},
   "source": [
    "### Using Pre-existing Signals/Conditions/Scalars etc\n",
    "\n",
    "In the examples above, we are both creating items (signals/conditions/scalars/etc) and using them in a template -- all in one call to `spy.push()`.\n",
    "\n",
    "If the items are already created, then you can use `spy.workbooks.push()` instead, like so:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "34839059",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Push successful</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: left;\">ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">Name</td><td style=\"background-color: #EEFFEE; text-align: left;\">Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">Workbook Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">Count</td><td style=\"background-color: #EEFFEE; text-align: left;\">Time</td><td style=\"background-color: #EEFFEE; text-align: left;\">Errors</td><td style=\"background-color: #EEFFEE; text-align: left;\">Result</td><td style=\"background-color: #EEFFEE; text-align: left;\">Pushed Workbook ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">URL</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">0</td><td style=\"text-align: left; vertical-align: top;\">F01FD57A-1112-4020-9430-CF27C2847D1B agent_api_key Workbook Template Example 2.1</td><td style=\"text-align: left; vertical-align: top;\">Workbook Template Example 2.1</td><td style=\"text-align: left; vertical-align: top;\">Workbook</td><td style=\"text-align: left; vertical-align: top;\">Analysis</td><td style=\"text-align: right; vertical-align: top;\">13</td><td style=\"vertical-align: top;\">00:00:00.63</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: left; vertical-align: top;\">Success</td><td style=\"text-align: left; vertical-align: top;\">0EF5A987-E447-E840-BF03-A3E65C9ED79D</td><td style=\"text-align: left; vertical-align: top;\"><a target=\"_blank\" href=\"http://localhost:34216/workbook/0EF5A987-E447-E840-BF03-A3E65C9ED79D/worksheet/0EF5A987-E493-7330-86B1-DD61FA4430B5\">link</a></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>ID</th>\n",
       "      <th>Name</th>\n",
       "      <th>Type</th>\n",
       "      <th>Workbook Type</th>\n",
       "      <th>Count</th>\n",
       "      <th>Time</th>\n",
       "      <th>Errors</th>\n",
       "      <th>Result</th>\n",
       "      <th>Pushed Workbook ID</th>\n",
       "      <th>URL</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>F01FD57A-1112-4020-9430-CF27C2847D1B agent_api...</td>\n",
       "      <td>Workbook Template Example 2.1</td>\n",
       "      <td>Workbook</td>\n",
       "      <td>Analysis</td>\n",
       "      <td>13</td>\n",
       "      <td>0:00:00.630423</td>\n",
       "      <td>0</td>\n",
       "      <td>Success</td>\n",
       "      <td>0EF5A987-E447-E840-BF03-A3E65C9ED79D</td>\n",
       "      <td>http://localhost:34216/workbook/0EF5A987-E447-...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                  ID  \\\n",
       "0  F01FD57A-1112-4020-9430-CF27C2847D1B agent_api...   \n",
       "\n",
       "                            Name      Type Workbook Type Count  \\\n",
       "0  Workbook Template Example 2.1  Workbook      Analysis    13   \n",
       "\n",
       "             Time Errors   Result                    Pushed Workbook ID  \\\n",
       "0  0:00:00.630423      0  Success  0EF5A987-E447-E840-BF03-A3E65C9ED79D   \n",
       "\n",
       "                                                 URL  \n",
       "0  http://localhost:34216/workbook/0EF5A987-E447-...  "
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Retrieve Area B items from the Example Data asset tree\n",
    "area_b_signals = spy.search({'Path': 'Example >> Cooling Tower 1', 'Asset': 'Area B'})\n",
    "\n",
    "workbooks = spy.workbooks.load('./Support Files/Workbook Templates.zip',\n",
    "                               as_template_with_label=f'{spy.user.username} Workbook Template Example 2.1')\n",
    "\n",
    "workbook = workbooks['Analysis Template']\n",
    "\n",
    "workbook.name = 'Workbook Template Example 2.1'\n",
    "\n",
    "workbook.parameters = {\n",
    "    \"DCED9C36-A4BE-4783-9216-DC06B3F57D8C [Signal] Area A_Compressor Power\":\n",
    "        # You can specify a (single) DataFrame row as long as it contains a valid ID column\n",
    "        area_b_signals[area_b_signals['Name'] == 'Compressor Power'],\n",
    "    \"9564A6B8-8A8F-4F6D-AC63-00EA38962B7A [Signal] Area A_Temperature\":\n",
    "        area_b_signals[area_b_signals['Name'] == 'Temperature'],\n",
    "    \"D2C089B6-CE85-46FC-8392-E11CC0C08336 [Signal] Area A_Compressor Stage\":\n",
    "        # You can specify an ID directly as a string\n",
    "        area_b_signals[area_b_signals['Name'] == 'Compressor Stage'].iloc[0]['ID']\n",
    "}\n",
    "\n",
    "spy.workbooks.push(workbook)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0006522c",
   "metadata": {},
   "source": [
    "When you click the link to examine the pushed workbook, you'll see that the `Area A_Xxxxx` signals have been replaced with equivalent `Example >> Cooling Tower 1 >> Area B` signals."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3ac556fb",
   "metadata": {},
   "source": [
    "## Modifying the Display Items\n",
    "\n",
    "In some cases, you need to have more dynamic control over what items are displayed in your worksheet and how. An efficient course of action is to create a worksheet/workbook template that is set up the way you want it with a handful of placeholder items. Then you can completely replace those items with a different set that may be larger or smaller than what's in the template.\n",
    "\n",
    "You can change the elements of a worksheet by making function calls and manipulating attributes of the worksheet object. Documentation on the various attributes of a worksheet is available in the [spy.workbooks.AnalysisWorksheet](https://python-docs.seeq.com/reference/submodules/workbooks.html#seeq.spy.workbooks.AnalysisWorksheet) online documentation.\n",
    "\n",
    "Here's an example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "ce626442",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Push successful</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: left;\">ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">Name</td><td style=\"background-color: #EEFFEE; text-align: left;\">Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">Workbook Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">Count</td><td style=\"background-color: #EEFFEE; text-align: left;\">Time</td><td style=\"background-color: #EEFFEE; text-align: left;\">Errors</td><td style=\"background-color: #EEFFEE; text-align: left;\">Result</td><td style=\"background-color: #EEFFEE; text-align: left;\">Pushed Workbook ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">URL</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">0</td><td style=\"text-align: left; vertical-align: top;\">F01FD57A-1112-4020-9430-CF27C2847D1B agent_api_key Workbook Template Example 2.2</td><td style=\"text-align: left; vertical-align: top;\">Workbook Template Example 2.2</td><td style=\"text-align: left; vertical-align: top;\">Workbook</td><td style=\"text-align: left; vertical-align: top;\">Analysis</td><td style=\"text-align: right; vertical-align: top;\">8</td><td style=\"vertical-align: top;\">00:00:00.32</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: left; vertical-align: top;\">Success</td><td style=\"text-align: left; vertical-align: top;\">0EF5A987-F546-71A0-8B3E-82DB3BBF0022</td><td style=\"text-align: left; vertical-align: top;\"><a target=\"_blank\" href=\"http://localhost:34216/workbook/0EF5A987-F546-71A0-8B3E-82DB3BBF0022/worksheet/0EF5A987-F58C-EE70-B6C9-57966CF53C9B\">link</a></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>ID</th>\n",
       "      <th>Name</th>\n",
       "      <th>Type</th>\n",
       "      <th>Workbook Type</th>\n",
       "      <th>Count</th>\n",
       "      <th>Time</th>\n",
       "      <th>Errors</th>\n",
       "      <th>Result</th>\n",
       "      <th>Pushed Workbook ID</th>\n",
       "      <th>URL</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>F01FD57A-1112-4020-9430-CF27C2847D1B agent_api...</td>\n",
       "      <td>Workbook Template Example 2.2</td>\n",
       "      <td>Workbook</td>\n",
       "      <td>Analysis</td>\n",
       "      <td>8</td>\n",
       "      <td>0:00:00.319439</td>\n",
       "      <td>0</td>\n",
       "      <td>Success</td>\n",
       "      <td>0EF5A987-F546-71A0-8B3E-82DB3BBF0022</td>\n",
       "      <td>http://localhost:34216/workbook/0EF5A987-F546-...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                  ID  \\\n",
       "0  F01FD57A-1112-4020-9430-CF27C2847D1B agent_api...   \n",
       "\n",
       "                            Name      Type Workbook Type Count  \\\n",
       "0  Workbook Template Example 2.2  Workbook      Analysis     8   \n",
       "\n",
       "             Time Errors   Result                    Pushed Workbook ID  \\\n",
       "0  0:00:00.319439      0  Success  0EF5A987-F546-71A0-8B3E-82DB3BBF0022   \n",
       "\n",
       "                                                 URL  \n",
       "0  http://localhost:34216/workbook/0EF5A987-F546-...  "
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "template_label = 'Workbook Template Example 2.2'\n",
    "workbooks = spy.workbooks.load('./Support Files/Workbook Templates.zip',\n",
    "                               as_template_with_label=f'{spy.user.username} {template_label}')\n",
    "\n",
    "workbook = workbooks['Analysis Template']\n",
    "workbook.name = template_label\n",
    "\n",
    "worksheet = workbook.worksheets['Trend Template']\n",
    "worksheet.name = 'Cooling Tower 1'\n",
    "\n",
    "# Grab all Temperature signals under Cooling Tower 1\n",
    "areas_to_add = spy.search({'Path': 'Example >> Cooling Tower 1', 'Name': 'Temperature'})\n",
    "\n",
    "# Copy this into a variable where each row is indexed by Path/Asset/Name for easy manipulation\n",
    "display_items = areas_to_add.set_index(['Path', 'Asset', 'Name'])\n",
    "\n",
    "# See \"Manipulating Worksheets\" section of spy.workbooks.ipynb for more info on these display item attributes\n",
    "display_items.at[('Example >> Cooling Tower 1', 'Area A', 'Temperature'), 'Color'] = '#FF0000'\n",
    "display_items.at[('Example >> Cooling Tower 1', 'Area B', 'Temperature'), 'Lane'] = 2\n",
    "display_items.at[('Example >> Cooling Tower 1', 'Area B', 'Temperature'), 'Axis Group'] = 'B'\n",
    "display_items.at[('Example >> Cooling Tower 1', 'Area C', 'Temperature'), 'Lane'] = 2\n",
    "display_items.at[('Example >> Cooling Tower 1', 'Area C', 'Temperature'), 'Axis Group'] = 'B'\n",
    "display_items.at[('Example >> Cooling Tower 1', 'Area J', 'Temperature'), 'Line Style'] = 'Short Dash-Dot'\n",
    "display_items.at[('Example >> Cooling Tower 1', 'Area J', 'Temperature'), 'Line Width'] = 5\n",
    "\n",
    "# Sort by the index so that they appear in order (Area A, then Area B etc)\n",
    "display_items.sort_index(inplace=True)\n",
    "\n",
    "# Reset the index since the worksheet expects a Name column\n",
    "display_items.reset_index(inplace=True)\n",
    "\n",
    "# Assign the manipulated DataFrame to the worksheet\n",
    "worksheet.display_items = display_items\n",
    "\n",
    "# Create another worksheet with Cooling Tower 2 items. We must supply a unique label to the copy() function for\n",
    "# bookkeeping purposes.\n",
    "worksheet2 = worksheet.copy(f'{spy.user.username} {template_label} - Cooling Tower 2')\n",
    "worksheet2.name = 'Cooling Tower 2'\n",
    "\n",
    "areas_to_add = spy.search({'Path': 'Example >> Cooling Tower 2', 'Name': 'Temperature'})\n",
    "worksheet2.display_items = areas_to_add\n",
    "\n",
    "# Remove other worksheets\n",
    "workbook.worksheets = [w for w in workbook.worksheets if 'Cooling Tower' in w.name]\n",
    "\n",
    "spy.workbooks.push(workbook)"
   ]
  },
  {
   "attachments": {
    "DisplayItemsManipulated2.jpg": {
     "image/jpeg": "[encoded data, 294696 characters]"
    }
   },
   "cell_type": "markdown",
   "id": "a98a45df",
   "metadata": {},
   "source": [
    "The resulting worksheet/workbook should look like this:\n",
    "\n",
    "![DisplayItemsManipulated2.jpg](attachment:DisplayItemsManipulated2.jpg)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cb586d71",
   "metadata": {},
   "source": [
    "You can also combine the use of template parameters with manipulation of the display items. Specify the template parameters and then add/remove/modify rows in the Worksheet's `display_items` DataFrame. Added rows will need to have valid `ID`, `Name` and `Type` fields, which naturally come from `spy.search()` calls as you see in the example above."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "11562872",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "## Pushing a Template Organizer Topic\n",
    "\n",
    "A template Organizer Topic can also be pushed, with specific content that you specify using a method that builds upon what you learned above.\n",
    "\n",
    "Since Organizer Topics are nearly always paired with a Workbench Analysis workbook that contains its content, you will be loading and pushing both in this example.\n",
    "\n",
    "We are going to re-use the template objects from the previous example, but this time we will push all of them instead of just the Workbench Analysis."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a0d1b425",
   "metadata": {},
   "source": [
    "### A Single Topic Document with Multiple Assets\n",
    "\n",
    "In this first example, we will create a single Topic Document that has a separate _section_ for each asset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "fee7f2a6",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Success</div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "workbooks = spy.workbooks.load('./Support Files/Workbook Templates.zip',\n",
    "                               as_template_with_label=f'{spy.user.username} Workbook Template Example 3')\n",
    "\n",
    "topic = workbooks['Topic Template']\n",
    "analysis = workbooks['Analysis Template']"
   ]
  },
  {
   "attachments": {
    "TopicTemplateScreenshot1.png": {
     "image/png": "[encoded data, 586624 characters]"
    }
   },
   "cell_type": "markdown",
   "id": "b57ad288",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "This Topic template looks like so in the Organizer user interface:\n",
    "\n",
    "![TopicTemplateScreenshot1.png](attachment:TopicTemplateScreenshot1.png)\n",
    "\n",
    "Notice that there is some embedded content and there are some mustache variables. In particular, you can see an `{{#Assets}}` mustache designation, and if you were to scroll to the bottom, you would also see an `{{/Assets}}` entry too. This is a mustache _section_, which allows us to repeat a block of the document several times.\n",
    "\n",
    "(Note that if you want to exert more precise control over how your section is rendered -- for example, if you want each section to be rendered by a `<tr>` row in a table instead of as separate tables -- you can use the `pretty_print_html=True` argument when you save the workbook templates, and then you can manually go into the saved HTML files and tweak where the Mustache tokens are placed.)\n",
    "\n",
    "As you'll see below, we are going to have a block for each asset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "9aa6ea09",
   "metadata": {
    "keep_output_in_docs": true,
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "document.parameters = {\n",
      "    \"Document Name\": None,\n",
      "    \"Assets\": [\n",
      "        {\n",
      "            \"Asset Name\": None,\n",
      "            \"25AF462C-602A-4E13-B50D-5DEB92CB37B5 [Embedded Content] Users >> mark-derbecker@seeq-com >> Workbook Templates >> Analysis Template >> Trend Template\": None,\n",
      "            \"76B4412D-3B08-48B7-ABF9-ED8432DAA5CE [Embedded Content] Users >> mark-derbecker@seeq-com >> Workbook Templates >> Analysis Template >> XY Plot Template\": None,\n",
      "            \"44392AAB-D443-4D2D-ACF0-055869875558 [Embedded Content] Users >> mark-derbecker@seeq-com >> Workbook Templates >> Analysis Template >> Treemap Template\": None,\n",
      "            \"D4F167B3-E8BA-4FAA-86B3-05877E2D4250 [Embedded Content] Users >> mark-derbecker@seeq-com >> Workbook Templates >> Analysis Template >> Table Template\": None\n",
      "        }\n",
      "    ]\n",
      "}\n"
     ]
    }
   ],
   "source": [
    "document = topic.documents['Doc Template']\n",
    "\n",
    "print(document.code)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6bc11f41",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "Notice that the parameters code for the document contains an `Assets` entry, and it's a list that includes entries for each of the pieces of embedded content (as well as for the mustache variable `Asset Name`). We will specify a list of entries that are specific to each asset. First we need to create a set of content entries in the form of worksheet templates. Let's look at the code for each worksheet:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "9e191078",
   "metadata": {
    "keep_output_in_docs": true,
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "worksheet.parameters = {\n",
      "    \"9564A6B8-8A8F-4F6D-AC63-00EA38962B7A [Signal] Area A_Temperature\": None,\n",
      "    \"D2C089B6-CE85-46FC-8392-E11CC0C08336 [Signal] Area A_Compressor Stage\": None,\n",
      "    \"DCED9C36-A4BE-4783-9216-DC06B3F57D8C [Signal] Area A_Compressor Power\": None,\n",
      "    \"Temperature Journal Link Text\": None,\n",
      "    \"Compressor Power Journal Link Text\": None,\n",
      "    \"Compressor Stage Journal Link Text\": None,\n",
      "    \"favorite color\": None\n",
      "}\n",
      "worksheet.parameters = {\n",
      "    \"9564A6B8-8A8F-4F6D-AC63-00EA38962B7A [Signal] Area A_Temperature\": None,\n",
      "    \"DCED9C36-A4BE-4783-9216-DC06B3F57D8C [Signal] Area A_Compressor Power\": None\n",
      "}\n",
      "worksheet.parameters = {\n",
      "    \"07F3161F-6644-4505-BC33-16D6155B004E [Condition] Hot\": None,\n",
      "    \"D16FC368-AE8E-47B4-B1A3-9C2A3FBA2BB6 [Asset] Example >> Cooling Tower 1\": None,\n",
      "    \"4B40EAFC-91ED-4AB0-8199-F21AF40A8350 [Asset] Example >> Cooling Tower 1 >> Area A\": None,\n",
      "    \"8A4F0E26-8A0C-4127-9E11-B67E031C6049 [Signal] Example >> Cooling Tower 1 >> Area A >> Temperature\": None\n",
      "}\n",
      "worksheet.parameters = {\n",
      "    \"9564A6B8-8A8F-4F6D-AC63-00EA38962B7A [Signal] Area A_Temperature\": None,\n",
      "    \"D2C089B6-CE85-46FC-8392-E11CC0C08336 [Signal] Area A_Compressor Stage\": None,\n",
      "    \"DCED9C36-A4BE-4783-9216-DC06B3F57D8C [Signal] Area A_Compressor Power\": None\n",
      "}\n"
     ]
    }
   ],
   "source": [
    "trend_template = analysis.worksheets['Trend Template']\n",
    "xy_plot_template = analysis.worksheets['XY Plot Template']\n",
    "treemap_template = analysis.worksheets['Treemap Template']\n",
    "table_template = analysis.worksheets['Table Template']\n",
    "\n",
    "print(trend_template.code)\n",
    "print(xy_plot_template.code)\n",
    "print(treemap_template.code)\n",
    "print(table_template.code)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a8112db1",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "We're going to create a separate set of worksheets _per asset_. We'll do that by making a copy of each worksheet template in a `for` loop, and we'll store them in a dictionary for later use."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "ffb07d6f",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "# We're going to reuse this code a couple of times, so we'll put it in a function\n",
    "def create_worksheets(analysis):\n",
    "    trend_template = analysis.worksheets['Trend Template']\n",
    "    xy_plot_template = analysis.worksheets['XY Plot Template']\n",
    "    treemap_template = analysis.worksheets['Treemap Template']\n",
    "    table_template = analysis.worksheets['Table Template']\n",
    "\n",
    "    worksheet_templates = dict()\n",
    "    for asset in ['Waveforms 1', 'Waveforms 2']:\n",
    "        # We create a copy of the worksheets for each asset, and it must have a unique label. So we incorporate\n",
    "        # the asset name into the label.\n",
    "        unique_label = f'{spy.user.username} Workbook Template Example 3 - {asset}'\n",
    "\n",
    "        trend_worksheet = trend_template.copy(unique_label)\n",
    "        trend_worksheet.name = f'{asset} Trend'\n",
    "        trend_worksheet.parameters = {\n",
    "            \"DCED9C36-A4BE-4783-9216-DC06B3F57D8C [Signal] Area A_Compressor Power\": {'Asset': asset, 'Name': 'Sinusoid'},\n",
    "            \"9564A6B8-8A8F-4F6D-AC63-00EA38962B7A [Signal] Area A_Temperature\": {'Asset': asset, 'Name': 'Sawtooth'},\n",
    "            \"D2C089B6-CE85-46FC-8392-E11CC0C08336 [Signal] Area A_Compressor Stage\": {'Asset': asset, 'Name': 'Square'},\n",
    "            \"Temperature Journal Link Text\": 'Sawtooth',\n",
    "            \"Compressor Power Journal Link Text\": 'Sinusoid',\n",
    "            \"Compressor Stage Journal Link Text\": 'Square',\n",
    "            \"favorite color\": 'eggshell' if asset.endswith('1') else 'violet'\n",
    "        }\n",
    "\n",
    "        xy_plot_worksheet = xy_plot_template.copy(unique_label)\n",
    "        xy_plot_worksheet.name = f'{asset} XY Plot'\n",
    "        xy_plot_worksheet.parameters = {\n",
    "            \"DCED9C36-A4BE-4783-9216-DC06B3F57D8C [Signal] Area A_Compressor Power\": {'Asset': asset, 'Name': 'Sinusoid'},\n",
    "            \"9564A6B8-8A8F-4F6D-AC63-00EA38962B7A [Signal] Area A_Temperature\": {'Asset': asset, 'Name': 'Sawtooth'}\n",
    "        }\n",
    "\n",
    "        treemap_worksheet = treemap_template.copy(unique_label)\n",
    "        treemap_worksheet.name = f'{asset} Treemap'\n",
    "        treemap_worksheet.parameters = {\n",
    "            \"8A4F0E26-8A0C-4127-9E11-B67E031C6049 [Signal] Example >> Cooling Tower 1 >> Area A >> Temperature\": {\n",
    "                'Asset': asset, 'Name': 'Sawtooth'},\n",
    "            \"07F3161F-6644-4505-BC33-16D6155B004E [Condition] Hot\": {'Asset': asset, 'Name': 'Hours'},\n",
    "            \"D16FC368-AE8E-47B4-B1A3-9C2A3FBA2BB6 [Asset] Cooling Tower 1\": {'Asset': 'Waveforms', 'Type': 'Asset'},\n",
    "            \"4B40EAFC-91ED-4AB0-8199-F21AF40A8350 [Asset] Example >> Area A\": {'Asset': asset, 'Type': 'Asset'}\n",
    "        }\n",
    "\n",
    "        table_worksheet = table_template.copy(unique_label)\n",
    "        table_worksheet.name = f'{asset} Table'\n",
    "        table_worksheet.parameters = {\n",
    "            \"DCED9C36-A4BE-4783-9216-DC06B3F57D8C [Signal] Area A_Compressor Power\": {'Asset': asset, 'Name': 'Sinusoid'},\n",
    "            \"D2C089B6-CE85-46FC-8392-E11CC0C08336 [Signal] Area A_Compressor Stage\": {'Asset': asset, 'Name': 'Square'},\n",
    "            \"9564A6B8-8A8F-4F6D-AC63-00EA38962B7A [Signal] Area A_Temperature\": {'Asset': asset, 'Name': 'Sawtooth'}\n",
    "        }\n",
    "\n",
    "        worksheet_templates[asset] = {\n",
    "            'Trend': trend_worksheet,\n",
    "            'XY Plot': xy_plot_worksheet,\n",
    "            'Treemap': treemap_worksheet,\n",
    "            'Table': table_worksheet,\n",
    "        }\n",
    "        \n",
    "    return worksheet_templates\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7510e971",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "Now we will fill in the Organizer Topic document's template parameters by using the worksheet templates that we assembled above. Note below that we are using a [list comprehension](https://www.w3schools.com/python/python_lists_comprehension.asp) to create the `Assets` list of each Waveform asset."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "d5ceea8e",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "worksheet_templates = create_worksheets(analysis)\n",
    "\n",
    "document.name = \"Workbook Template Example 3\"\n",
    "\n",
    "document.parameters = {\n",
    "    \"Document Name\": \"Waveform Monitoring and Diagnostics\",\n",
    "    \"Assets\": [\n",
    "        {\n",
    "            \"Asset Name\": asset,\n",
    "            \"25AF462C-602A-4E13-B50D-5DEB92CB37B5 [Embedded Content] Users >> mark.derbecker@seeq.com >> Workbook Templates >> Analysis Template >> Trend Template\":\n",
    "                worksheet_templates[asset]['Trend'],\n",
    "            \"76B4412D-3B08-48B7-ABF9-ED8432DAA5CE [Embedded Content] Users >> mark.derbecker@seeq.com >> Workbook Templates >> Analysis Template >> XY Plot Template\":\n",
    "                worksheet_templates[asset]['XY Plot'],\n",
    "            \"44392AAB-D443-4D2D-ACF0-055869875558 [Embedded Content] Users >> mark.derbecker@seeq.com >> Workbook Templates >> Analysis Template >> Treemap Template\":\n",
    "                worksheet_templates[asset]['Treemap'],\n",
    "            \"D4F167B3-E8BA-4FAA-86B3-05877E2D4250 [Embedded Content] Users >> mark.derbecker@seeq.com >> Workbook Templates >> Analysis Template >> Table Template\":\n",
    "                worksheet_templates[asset]['Table']\n",
    "        }\n",
    "        for asset in ['Waveforms 1', 'Waveforms 2']\n",
    "    ]\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f5ec9ef3",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "Now we do some final bookkeeping to tidy things up and push. Click on the link that corresponds to the Topic to see it in Organizer."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "d844ef07",
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Push successful</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: left;\">ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">Name</td><td style=\"background-color: #EEFFEE; text-align: left;\">Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">Workbook Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">Count</td><td style=\"background-color: #EEFFEE; text-align: left;\">Time</td><td style=\"background-color: #EEFFEE; text-align: left;\">Errors</td><td style=\"background-color: #EEFFEE; text-align: left;\">Result</td><td style=\"background-color: #EEFFEE; text-align: left;\">Pushed Workbook ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">URL</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">0</td><td style=\"text-align: left; vertical-align: top;\">F01FD57A-1112-4020-9430-CF27C2847D1B agent_api_key Workbook Template Example 3</td><td style=\"text-align: left; vertical-align: top;\">Workbook Template Example 3</td><td style=\"text-align: left; vertical-align: top;\">Workbook</td><td style=\"text-align: left; vertical-align: top;\">Analysis</td><td style=\"text-align: right; vertical-align: top;\">39</td><td style=\"vertical-align: top;\">00:00:01.97</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: left; vertical-align: top;\">Success</td><td style=\"text-align: left; vertical-align: top;\">0EF5A988-0214-EE90-9DD4-36652A590462</td><td style=\"text-align: left; vertical-align: top;\"><a target=\"_blank\" href=\"http://localhost:34216/workbook/0EF5A988-0214-EE90-9DD4-36652A590462/worksheet/0EF5A988-0AC5-6080-A04D-1DB45B98F31F\">link</a></td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">1</td><td style=\"text-align: left; vertical-align: top;\">90931EF8-D80B-4F22-8568-3683DD806D50 agent_api_key Workbook Template Example 3</td><td style=\"text-align: left; vertical-align: top;\">Workbook Template Example 3</td><td style=\"text-align: left; vertical-align: top;\">Workbook</td><td style=\"text-align: left; vertical-align: top;\">Topic</td><td style=\"text-align: right; vertical-align: top;\">2</td><td style=\"vertical-align: top;\">00:00:00.30</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: left; vertical-align: top;\">Success</td><td style=\"text-align: left; vertical-align: top;\">0EF5A988-026A-75C0-B303-ECD1EC50AFE9</td><td style=\"text-align: left; vertical-align: top;\"><a target=\"_blank\" href=\"http://localhost:34216/workbook/0EF5A988-026A-75C0-B303-ECD1EC50AFE9/worksheet/0EF5A988-1812-ECB0-BAB8-8D4F98C3D117\">link</a></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Give the topic and analysis a specific name\n",
    "topic.name = 'Workbook Template Example 3'\n",
    "analysis.name = 'Workbook Template Example 3'\n",
    "\n",
    "# Since each of the worksheets we created above is a copy of the template, the template\n",
    "# worksheets will show separately from the \"Waveforms\" worksheets. We want to \"hide\" the\n",
    "# template worksheets because it's often not interesting and perhaps confusing\n",
    "# for the user to see the templates. So we set the \"Archived\" property to True -- they\n",
    "# will still be pushed, but they'll be in the trash and the user won't see them.\n",
    "analysis.worksheets['Trend Template']['Archived'] = True\n",
    "analysis.worksheets['XY Plot Template']['Archived'] = True\n",
    "analysis.worksheets['Treemap Template']['Archived'] = True\n",
    "analysis.worksheets['Table Template']['Archived'] = True\n",
    "\n",
    "# Note that we pass in a list that includes the Analysis and the Topic\n",
    "pushed_df = spy.push(metadata=metadata_df, workbook=[topic, analysis])\n",
    "\n",
    "# Show the inner Push Workbooks status object's display instead of the metadata push status,\n",
    "# since it has links to the Topic.\n",
    "pushed_df.spy.status.inner['Push Workbooks'].display()"
   ]
  },
  {
   "attachments": {
    "TopicTemplateScreenshot2.png": {
     "image/png": "[encoded data, 252504 characters]"
    }
   },
   "cell_type": "markdown",
   "id": "3b6415b9",
   "metadata": {
    "pycharm": {
     "name": "#%% md\n"
    }
   },
   "source": [
    "The Organizer Topic should have two sections, one for each Waveform asset, the second of which should look something like this:\n",
    "\n",
    "![TopicTemplateScreenshot2.png](attachment:TopicTemplateScreenshot2.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1e53144b",
   "metadata": {},
   "source": [
    "### A Topic with a Document for each Asset\n",
    "\n",
    "Now let's see how it would look if you wanted a separate Topic Document for each Asset instead of putting them all in one Document.\n",
    "\n",
    "It looks very similar, but you'll see that we use the `copy()` function to make separate documents."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "ca90ef13",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Push successful</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: left;\">ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">Name</td><td style=\"background-color: #EEFFEE; text-align: left;\">Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">Workbook Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">Count</td><td style=\"background-color: #EEFFEE; text-align: left;\">Time</td><td style=\"background-color: #EEFFEE; text-align: left;\">Errors</td><td style=\"background-color: #EEFFEE; text-align: left;\">Result</td><td style=\"background-color: #EEFFEE; text-align: left;\">Pushed Workbook ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">URL</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">0</td><td style=\"text-align: left; vertical-align: top;\">F01FD57A-1112-4020-9430-CF27C2847D1B agent_api_key Workbook Template Example 4</td><td style=\"text-align: left; vertical-align: top;\">Workbook Template Example 4</td><td style=\"text-align: left; vertical-align: top;\">Workbook</td><td style=\"text-align: left; vertical-align: top;\">Analysis</td><td style=\"text-align: right; vertical-align: top;\">39</td><td style=\"vertical-align: top;\">00:00:02.64</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: left; vertical-align: top;\">Success</td><td style=\"text-align: left; vertical-align: top;\">0EF5C014-9C38-FDD0-8C6E-671A8F9D8C54</td><td style=\"text-align: left; vertical-align: top;\"><a target=\"_blank\" href=\"http://localhost:34216/workbook/0EF5C014-9C38-FDD0-8C6E-671A8F9D8C54/worksheet/0EF5C014-A0F8-EAF0-8940-3E32633E79F6\">link</a></td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">1</td><td style=\"text-align: left; vertical-align: top;\">90931EF8-D80B-4F22-8568-3683DD806D50 agent_api_key Workbook Template Example 4</td><td style=\"text-align: left; vertical-align: top;\">Workbook Template Example 4</td><td style=\"text-align: left; vertical-align: top;\">Workbook</td><td style=\"text-align: left; vertical-align: top;\">Topic</td><td style=\"text-align: right; vertical-align: top;\">6</td><td style=\"vertical-align: top;\">00:00:00.72</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: left; vertical-align: top;\">Success</td><td style=\"text-align: left; vertical-align: top;\">0EF5C014-9CC1-F950-93CC-78A73CCE27AA</td><td style=\"text-align: left; vertical-align: top;\"><a target=\"_blank\" href=\"http://localhost:34216/workbook/0EF5C014-9CC1-F950-93CC-78A73CCE27AA/worksheet/0EF5C014-BC1C-EED0-987F-072BB78EF986\">link</a></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "workbooks = spy.workbooks.load('./Support Files/Workbook Templates.zip',\n",
    "                               as_template_with_label=f'{spy.user.username} Workbook Template Example 4')\n",
    "\n",
    "topic = workbooks['Topic Template']\n",
    "analysis = workbooks['Analysis Template']\n",
    "\n",
    "worksheet_templates = create_worksheets(analysis)\n",
    "\n",
    "topic.name = 'Workbook Template Example 4'\n",
    "analysis.name = 'Workbook Template Example 4'\n",
    "\n",
    "# Grab the one and only document as a template. Note that it's name is left over from the previous example.\n",
    "doc_template = topic.documents['Doc Template']\n",
    "\n",
    "for asset in ['Waveforms 1', 'Waveforms 2']:\n",
    "    document = doc_template.copy(label=f'Document for {asset}')\n",
    "    document.name = asset\n",
    "\n",
    "    document.parameters = {\n",
    "        \"Document Name\": \"Waveform Monitoring and Diagnostics - v2\",\n",
    "        \n",
    "        # This time, the Assets list is only one item long, since we're putting the Assets in different documents.\n",
    "        \"Assets\": [\n",
    "            {\n",
    "                \"Asset Name\": asset,\n",
    "                \"25AF462C-602A-4E13-B50D-5DEB92CB37B5 [Embedded Content] Users >> mark.derbecker@seeq.com >> Workbook Templates >> Analysis Template >> Trend Template\":\n",
    "                    worksheet_templates[asset]['Trend'],\n",
    "                \"76B4412D-3B08-48B7-ABF9-ED8432DAA5CE [Embedded Content] Users >> mark.derbecker@seeq.com >> Workbook Templates >> Analysis Template >> XY Plot Template\":\n",
    "                    worksheet_templates[asset]['XY Plot'],\n",
    "                \"44392AAB-D443-4D2D-ACF0-055869875558 [Embedded Content] Users >> mark.derbecker@seeq.com >> Workbook Templates >> Analysis Template >> Treemap Template\":\n",
    "                    worksheet_templates[asset]['Treemap'],\n",
    "                \"D4F167B3-E8BA-4FAA-86B3-05877E2D4250 [Embedded Content] Users >> mark.derbecker@seeq.com >> Workbook Templates >> Analysis Template >> Table Template\":\n",
    "                    worksheet_templates[asset]['Table']\n",
    "            }\n",
    "        ]\n",
    "    }\n",
    "\n",
    "# Since we have created a separate document for each asset, we don't want to see the template doc in the Topic\n",
    "doc_template['Archived'] = True\n",
    "\n",
    "pushed_df = spy.push(metadata=metadata_df, workbook=[topic, analysis])\n",
    "pushed_df.spy.status.inner['Push Workbooks'].display()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "891f4692-f588-436d-bfbb-e182edd85bde",
   "metadata": {},
   "source": [
    "#### Alternative Method: Using Asset Selections\n",
    "\n",
    "You may have a Topic Document that contains an Asset Selection, and you simply want to create separate documents and \"pre-select\" that asset, and often because you want to have each separate document update on a schedule so that all of the content loads quickly when you try to view it.\n",
    "\n",
    "You can accomplish this by using the Topic Document's parameters to set an Asset for the Asset Selection.\n",
    "\n",
    "To illustrate, first we push some workbooks that would be representative of your starting point: A Workbench Analysis and an Organizer Topic that references it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "8c78ee2d-ad42-4dd7-b78b-44546df8dd46",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Push successful</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: left;\">ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">Name</td><td style=\"background-color: #EEFFEE; text-align: left;\">Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">Workbook Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">Count</td><td style=\"background-color: #EEFFEE; text-align: left;\">Time</td><td style=\"background-color: #EEFFEE; text-align: left;\">Errors</td><td style=\"background-color: #EEFFEE; text-align: left;\">Result</td><td style=\"background-color: #EEFFEE; text-align: left;\">Pushed Workbook ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">URL</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">0</td><td style=\"text-align: left; vertical-align: top;\">0EF59E6B-546A-6230-8251-02C2AE9EE8C1</td><td style=\"text-align: left; vertical-align: top;\">Asset Selector Analysis Template</td><td style=\"text-align: left; vertical-align: top;\">Workbook</td><td style=\"text-align: left; vertical-align: top;\">Analysis</td><td style=\"text-align: right; vertical-align: top;\">13</td><td style=\"vertical-align: top;\">00:00:00.62</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: left; vertical-align: top;\">Success</td><td style=\"text-align: left; vertical-align: top;\">0EF5A97D-AA93-EAE0-A973-567A663D716A</td><td style=\"text-align: left; vertical-align: top;\"><a target=\"_blank\" href=\"http://localhost:34216/workbook/0EF5A97D-AA93-EAE0-A973-567A663D716A/worksheet/0EF5A97D-ADAF-F940-A4FB-BEF4D48CF257\">link</a></td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">1</td><td style=\"text-align: left; vertical-align: top;\">0EF59E6D-EE87-60A0-A4E3-AA13C6B2FE18</td><td style=\"text-align: left; vertical-align: top;\">Asset Selector Topic Template</td><td style=\"text-align: left; vertical-align: top;\">Workbook</td><td style=\"text-align: left; vertical-align: top;\">Topic</td><td style=\"text-align: right; vertical-align: top;\">2</td><td style=\"vertical-align: top;\">00:00:00.29</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: left; vertical-align: top;\">Success</td><td style=\"text-align: left; vertical-align: top;\">0EF5A97D-B036-E8D0-A7C6-B15F8201D867</td><td style=\"text-align: left; vertical-align: top;\"><a target=\"_blank\" href=\"http://localhost:34216/workbook/0EF5A97D-B036-E8D0-A7C6-B15F8201D867/worksheet/0EF5A97D-B08C-6000-BC3F-DEBE68C2DACC\">link</a></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Load and push the basis for this example.\n",
    "workbooks = spy.workbooks.load('./Support Files/Workbook Templates.zip')\n",
    "\n",
    "pushed_workbooks_df = spy.workbooks.push([\n",
    "    workbooks['Asset Selector Analysis Template'],\n",
    "    workbooks['Asset Selector Topic Template']\n",
    "], label=f'{spy.user.username} Workbook Template Example 4 - Example Basis')\n",
    "\n",
    "# Construct a DataFrame of the pushed workbooks for use below\n",
    "workbooks_to_pull_df = pushed_workbooks_df[pushed_workbooks_df['Workbook Type'] == 'Topic'].copy()\n",
    "workbooks_to_pull_df.drop(columns=['ID'], inplace=True)\n",
    "workbooks_to_pull_df.rename(columns={'Pushed Workbook ID': 'ID'}, inplace=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "24cba6fe-2c71-4244-bb30-2cc6db62e954",
   "metadata": {},
   "source": [
    "Now that we have the basis for our example, we'll pull these workbooks as a template."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "ca8bb43b-2b4b-4713-922e-2e3a9b12a334",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Pull successful</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: left;\">ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">Name</td><td style=\"background-color: #EEFFEE; text-align: left;\">Workbook Type</td><td style=\"background-color: #EEFFEE; text-align: right;\">Count</td><td style=\"background-color: #EEFFEE; text-align: right;\">Time</td><td style=\"background-color: #EEFFEE; text-align: right;\">Errors</td><td style=\"background-color: #EEFFEE; text-align: left;\">Result</td><td style=\"background-color: #EEFFEE; text-align: left;\">Path</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">0</td><td style=\"text-align: left; vertical-align: top;\">0EF5A97D-B036-E8D0-A7C6-B15F8201D867</td><td style=\"text-align: left; vertical-align: top;\">Asset Selector Topic Template</td><td style=\"text-align: left; vertical-align: top;\">Topic</td><td style=\"text-align: right; vertical-align: top;\">4</td><td style=\"vertical-align: top;\">00:00:00.20</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: left; vertical-align: top;\">Success</td><td style=\"text-align: right; vertical-align: top;\">nan</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">1</td><td style=\"text-align: left; vertical-align: top;\">0EF5A97D-AA93-EAE0-A973-567A663D716A</td><td style=\"text-align: left; vertical-align: top;\">Asset Selector Analysis Template</td><td style=\"text-align: left; vertical-align: top;\">Analysis</td><td style=\"text-align: right; vertical-align: top;\">13</td><td style=\"vertical-align: top;\">00:00:00.34</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: left; vertical-align: top;\">Success</td><td style=\"text-align: left; vertical-align: top;\">My Folder</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Pull the workbooks with a template label\n",
    "templates = spy.workbooks.pull(workbooks_to_pull_df, as_template_with_label=f'{spy.user.username} Workbook Template Example 4')\n",
    "\n",
    "topic_template = templates['Asset Selector Topic Template']\n",
    "doc_template = topic_template.documents[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5dd19544-2570-4a1e-af3a-b7b1af7a1bf0",
   "metadata": {},
   "source": [
    "The following code finds all the assets under Cooling Tower 1 and then, in a loop, adds separate document for each.\n",
    "\n",
    "It also takes the opportunity to \"spread out\" the background schedule by ten minutes so that they aren't all being done simultaneously."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "a3d1108f-a9e9-4e09-9e13-7b9691b2fb57",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Push successful</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: left;\">ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">Name</td><td style=\"background-color: #EEFFEE; text-align: left;\">Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">Workbook Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">Count</td><td style=\"background-color: #EEFFEE; text-align: left;\">Time</td><td style=\"background-color: #EEFFEE; text-align: left;\">Errors</td><td style=\"background-color: #EEFFEE; text-align: left;\">Result</td><td style=\"background-color: #EEFFEE; text-align: left;\">Pushed Workbook ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">URL</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">0</td><td style=\"text-align: left; vertical-align: top;\">0EF5A97D-B036-E8D0-A7C6-B15F8201D867 agent_api_key Workbook Template Example 4</td><td style=\"text-align: left; vertical-align: top;\">Scale Across Assets with Asset Selections</td><td style=\"text-align: left; vertical-align: top;\">Workbook</td><td style=\"text-align: left; vertical-align: top;\">Topic</td><td style=\"text-align: right; vertical-align: top;\">8</td><td style=\"vertical-align: top;\">00:00:01.99</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: left; vertical-align: top;\">Success</td><td style=\"text-align: left; vertical-align: top;\">0EF5A97E-7C58-FDA0-BD3E-7A843D25C152</td><td style=\"text-align: left; vertical-align: top;\"><a target=\"_blank\" href=\"http://localhost:34216/workbook/0EF5A97E-7C58-FDA0-BD3E-7A843D25C152/worksheet/0EF5A97E-7CA4-E890-B06F-6008BEB73EF5\">link</a></td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>ID</th>\n",
       "      <th>Name</th>\n",
       "      <th>Type</th>\n",
       "      <th>Workbook Type</th>\n",
       "      <th>Count</th>\n",
       "      <th>Time</th>\n",
       "      <th>Errors</th>\n",
       "      <th>Result</th>\n",
       "      <th>Pushed Workbook ID</th>\n",
       "      <th>URL</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0EF5A97D-B036-E8D0-A7C6-B15F8201D867 agent_api...</td>\n",
       "      <td>Scale Across Assets with Asset Selections</td>\n",
       "      <td>Workbook</td>\n",
       "      <td>Topic</td>\n",
       "      <td>8</td>\n",
       "      <td>0:00:01.986297</td>\n",
       "      <td>0</td>\n",
       "      <td>Success</td>\n",
       "      <td>0EF5A97E-7C58-FDA0-BD3E-7A843D25C152</td>\n",
       "      <td>http://localhost:34216/workbook/0EF5A97E-7C58-...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                  ID  \\\n",
       "0  0EF5A97D-B036-E8D0-A7C6-B15F8201D867 agent_api...   \n",
       "\n",
       "                                        Name      Type Workbook Type Count  \\\n",
       "0  Scale Across Assets with Asset Selections  Workbook         Topic     8   \n",
       "\n",
       "             Time Errors   Result                    Pushed Workbook ID  \\\n",
       "0  0:00:01.986297      0  Success  0EF5A97E-7C58-FDA0-BD3E-7A843D25C152   \n",
       "\n",
       "                                                 URL  \n",
       "0  http://localhost:34216/workbook/0EF5A97E-7C58-...  "
      ]
     },
     "execution_count": 25,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Find all the assets we want\n",
    "areas = spy.search({'Path': 'Example >> Cooling Tower 1', 'Type': 'Asset'}, old_asset_format=False, recursive=False)\n",
    "\n",
    "hour = 2\n",
    "minute = 17\n",
    "for _, area in areas.iterrows():\n",
    "    area_doc = doc_template.copy(area['ID'])\n",
    "    area_doc.parameters = {\n",
    "        \"[Asset Selection] Example >> Cooling Tower 1 >> Area A\": area,\n",
    "\n",
    "        # The name of each doc in the template is \"Asset: {{Asset Name}}\", which causes \"Asset Name\" to be available\n",
    "        # for substitution in the template parameters.\n",
    "        \"Asset Name\": area['Name']\n",
    "    }\n",
    "\n",
    "    # Spread out the background schedule. We use a convenience method that turns an English-language string\n",
    "    # into a Cron string. If you want more precise control, the format of the Cron string is documented here:\n",
    "    # http://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html\n",
    "    cron_string = spy.utils.parse_schedule_string(f'Every day at {hour}:{minute}')\n",
    "    area_doc.schedule['Cron Schedule'] = [cron_string]\n",
    "    \n",
    "    minute += 10\n",
    "    if minute >= 60:\n",
    "        minute -= 60\n",
    "        hour += 1\n",
    "\n",
    "# Remove the template doc so it doesn't get pushed\n",
    "topic_template.documents.remove(doc_template)\n",
    "\n",
    "topic_template.name = 'Scale Across Assets with Asset Selections'\n",
    "\n",
    "# We're only pushing the Topic template (and excluding the Analysis template). We do this because the Analysis\n",
    "# (that we want to use) already exists on the server, and we have no interest in creating a second (duplicate)\n",
    "# Analysis. So the assume_dependencies_exist=True argument is important because otherwise you would get errors\n",
    "# about dependencies not being found, and these errors would prevent the push from completing.\n",
    "spy.workbooks.push(topic_template, assume_dependencies_exist=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9e548e44-c3be-4e53-858c-3638dbdb21c7",
   "metadata": {},
   "source": [
    "Click the \"link\" in the far right of the green box and take a look at the pushed Topic, you should see a separate document for each asset, and the schedule is slightly different for each."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d04efadf",
   "metadata": {},
   "source": [
    "### A Topic Document with an Image\n",
    "\n",
    "In the examples above, you saw how to use syntax like `{{Asset Name}}` as a placeholder in the template that became a parameter you could specify in your SPy code.\n",
    "\n",
    "You can do a similar thing with pictures/images in your document. The most common use for this capability is to push a custom visualization (that you created in Python) into your document, and typically you'll want to do that on a schedule. A separate [Data Lab Visualizations](Data%20Lab%20Visualizations.ipynb) notebook walks you through how to accomplish that."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.11",
   "language": "python",
   "name": "python311"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
