{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "portuguese-morris",
   "metadata": {},
   "outputs": [],
   "source": [
    "from seeq import spy\n",
    "import pandas as pd\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": "logical-skill",
   "metadata": {},
   "outputs": [],
   "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, quiet=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bound-vault",
   "metadata": {},
   "source": [
    "# Asset Trees 1: Introduction\n",
    "\n",
    "Asset trees are a foundational tool that can be used to wrangle the full analytic capabilities of Seeq's software. They sort physical locations, pieces of equipment, and data on that equipment into a hierarchical structure. Organizing your data into an asset tree allows you to:\n",
    "- Utilize asset swapping to rapidly create identical visualizations for different pieces of equipment\n",
    "- Write high-value calculations for your components and scale them across all components in your tree\n",
    "- Automatically generate scalable content and custom analyses\n",
    "- Use your tree as a starting point for roll-ups, calculations, displays, dashboards, and reports\n",
    "\n",
    "In this notebook we will show how to define an asset tree using the SPy library, modify it to your liking, and push the resulting tree to Seeq Server."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fixed-authorization",
   "metadata": {},
   "source": [
    "## Defining an Asset Tree\n",
    "\n",
    "There are multiple ways to define an asset tree in SPy. All use the same function: `spy.assets.Tree()`. We summarize each way here before taking a further look in the subsections below.\n",
    "1. To create an empty tree, give a name for your new tree as input: `spy.assets.Tree('My Tree')`\n",
    "2. To create a tree with custom structure defined by a CSV (comma-separated values) file, give the filename as input: `spy.assets.Tree('my_folder/my_tree_template.csv')`\n",
    "3. To use an existing asset tree from Seeq as a starting point for your tree, give the name of that asset tree as input: `spy.assets.Tree('Facility 12_Asset Tree')`"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "convertible-fraud",
   "metadata": {},
   "source": [
    "### 1. Creating an Empty Tree\n",
    "\n",
    "In many cases, the easiest and most efficient way to build an asset tree is to start with the name of your root asset and insert your items later."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "cutting-petersburg",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">No existing root found. Tree created using new root \"My Tree\". The tree \"My Tree\" has height 1 and contains 1 asset.</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: right;\">Assets Created</td><td style=\"background-color: #EEFFEE; text-align: right;\">Signals Created</td><td style=\"background-color: #EEFFEE; text-align: right;\">Conditions Created</td><td style=\"background-color: #EEFFEE; text-align: right;\">Scalars Created</td><td style=\"background-color: #EEFFEE; text-align: right;\">Metrics Created</td><td style=\"background-color: #EEFFEE; text-align: right;\">Displays Created</td><td style=\"background-color: #EEFFEE; text-align: right;\">Total Items Created</td><td style=\"background-color: #EEFFEE; text-align: right;\">Items Pulled From Seeq</td><td style=\"background-color: #EEFFEE; text-align: right;\">Errors Encountered</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">Status</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "my_tree = spy.assets.Tree('My Tree', workbook='My Workbook')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "western-passage",
   "metadata": {},
   "source": [
    "This tree will contain a single asset named \"My Tree\" to begin with. It is scoped to a new workbook named \"My Workbook\" that will be created when the tree is pushed to Seeq. Underneath the root asset, we will be able to freely insert more assets, signals, conditions, and scalars as we need.\n",
    "\n",
    "In the code example above, `spy.assets.Tree` is a *function*. The two pieces of text `'My Tree'` and `'My Workbook'` inside the parentheses are *inputs* to that function. In return, the function *outputs* a tree object, which we assign to a *variable* called `my_tree`. This variable allows us to refer to the newly defined tree in future code. "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "outside-karaoke",
   "metadata": {},
   "source": [
    "### 2. Creating a Tree using CSV Files\n",
    "\n",
    "Defining asset trees using CSV template files is a great option for those seeking to create large asset trees using minimal Python code, or for those who already have pre-defined hierarchies for their items that can be exported to CSV format.\n",
    "\n",
    "The file `spy_tree_example.csv` in the `SPy Documentation/Support Files` directory contains the following data:\n",
    "\n",
    "| Name                     | Level 1     | Level 2         | Level 3 | Friendly Name     |\n",
    "|--------------------------|-------------|-----------------|---------|-------------------|\n",
    "| Area A_Temperature       | My CSV Tree | Cooling Tower 1 | Area A  | Temperature       |\n",
    "| Area A_Relative Humidity |             |                 |         | Relative Humidity |\n",
    "| Area B_Temperature       |             |                 | Area B  | Temperature       |\n",
    "| Area B_Relative Humidity |             |                 |         | Relative Humidity |\n",
    "| Area D_Temperature       |             | Cooling Tower 2 | Area D  | Temperature       |\n",
    "| Area D_Relative Humidity |             |                 |         | Relative Humidity |\n",
    "| Area E_Temperature       |             |                 | Area E  | Temperature       |\n",
    "| Area E_Relative Humidity |             |                 |         | Relative Humidity |\n",
    "\n",
    "When this file is given as input to `spy.assets.Tree`, SPy will look at each row in the file, find an item in Seeq corresponding to the row, and place it into a newly created asset tree at the specified location. The columns of the file give SPy information about where to find the item and how to put it in your tree:\n",
    "- The **Name** column tells SPy what item to pull from Seeq Server.\n",
    "- The **Level** columns tell SPy where in the tree to put the item.\n",
    "  - If a level column is empty for a particular row, then the rows above are referred to. For example, the third row above has levels *My CSV Tree*, *Cooling Tower 1*, and *Area B*.\n",
    "- The **Friendly Name** column tells SPy what what to call the item after putting it in the tree.\n",
    "- An optional **ID** column can help SPy find items from Seeq Server that don't have unique names.\n",
    "\n",
    "For example, the first row tells SPy to take the data from the existing signal \"Area A_Temperature\" in Seeq, create a new signal called \"Temperature\" containing the same data, and insert the new signal into the tree underneath the asset \"Area A\". The asset \"Area A\" will subsequently be underneath \"Cooling Tower 1\", which is underneath the root asset \"My CSV Tree\".\n",
    "\n",
    "Below we create a tree from this CSV file, and then use the `visualize()` function to look at what the end result is."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "weird-study",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Tree successfully created from DataFrame. The tree \"My CSV Tree\" has height 4 and contains 8 signals and 7 assets.</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: right;\">Assets Created</td><td style=\"background-color: #EEFFEE; text-align: right;\">Signals Created</td><td style=\"background-color: #EEFFEE; text-align: right;\">Conditions Created</td><td style=\"background-color: #EEFFEE; text-align: right;\">Scalars Created</td><td style=\"background-color: #EEFFEE; text-align: right;\">Metrics Created</td><td style=\"background-color: #EEFFEE; text-align: right;\">Displays Created</td><td style=\"background-color: #EEFFEE; text-align: right;\">Total Items Created</td><td style=\"background-color: #EEFFEE; text-align: right;\">Items Pulled From Seeq</td><td style=\"background-color: #EEFFEE; text-align: right;\">Errors Encountered</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">Status</td><td style=\"text-align: right; vertical-align: top;\">7</td><td style=\"text-align: right; vertical-align: top;\">8</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">15</td><td style=\"text-align: right; vertical-align: top;\">8</td><td style=\"text-align: right; vertical-align: top;\">0</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "My CSV Tree\n",
      "|-- Cooling Tower 1\n",
      "|   |-- Area A\n",
      "|   |   |-- Relative Humidity\n",
      "|   |   |-- Temperature\n",
      "|   |-- Area B\n",
      "|       |-- Relative Humidity\n",
      "|       |-- Temperature\n",
      "|-- Cooling Tower 2\n",
      "    |-- Area D\n",
      "    |   |-- Relative Humidity\n",
      "    |   |-- Temperature\n",
      "    |-- Area E\n",
      "        |-- Relative Humidity\n",
      "        |-- Temperature\n"
     ]
    }
   ],
   "source": [
    "my_csv_tree = spy.assets.Tree('Support Files/spy_tree_example.csv', workbook='My Workbook')\n",
    "my_csv_tree.visualize()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "preliminary-gilbert",
   "metadata": {},
   "source": [
    "### 3. Working with an Existing Asset Tree\n",
    "\n",
    "Say you have an existing asset tree in Seeq, perhaps from an external datasource like OSIsoft PI AF, and you wish to clean up the tree or add calculations to it for further analysis. You can define a tree in SPy using this existing tree as a starting point by referring to it by name in the `spy.assets.Tree` input. \n",
    "\n",
    "For instance, let's pull in the asset tree that organizes Seeq's example data. Its root asset is named `'Example'`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "exempt-belgium",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Recursively pulled SPy-created asset tree. The tree \"Example\" has height 4 and contains 94 signals and 19 assets.</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: right;\">Assets Created</td><td style=\"background-color: #EEFFEE; text-align: right;\">Signals Created</td><td style=\"background-color: #EEFFEE; text-align: right;\">Conditions Created</td><td style=\"background-color: #EEFFEE; text-align: right;\">Scalars Created</td><td style=\"background-color: #EEFFEE; text-align: right;\">Metrics Created</td><td style=\"background-color: #EEFFEE; text-align: right;\">Displays Created</td><td style=\"background-color: #EEFFEE; text-align: right;\">Total Items Created</td><td style=\"background-color: #EEFFEE; text-align: right;\">Items Pulled From Seeq</td><td style=\"background-color: #EEFFEE; text-align: right;\">Errors Encountered</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">Status</td><td style=\"text-align: right; vertical-align: top;\">19</td><td style=\"text-align: right; vertical-align: top;\">94</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">113</td><td style=\"text-align: right; vertical-align: top;\">113</td><td style=\"text-align: right; vertical-align: top;\">0</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "example_data_tree = spy.assets.Tree('Example', \n",
    "                                    workbook='My Workbook',\n",
    "                                    description='My custom copy of Example Data')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "lesbian-distance",
   "metadata": {},
   "source": [
    "This creates a tree that is a full copy of the example tree, with an added description so you can tell your new tree apart from the old tree. Therefore, when we make modifications and push them to Seeq, the original tree will remain unaltered. The only time a copy will not be made is if the tree we choose to work with was also created by SPy.\n",
    "\n",
    "An existing asset tree or subtree can also be pulled into SPy using the ID of its root asset...\n",
    "```python\n",
    "example_data_tree = spy.assets.Tree('656B88EC-E71F-44B6-B2A1-D60202B3B0CD')\n",
    "```\n",
    "...or by using `spy.search` results.\n",
    "```python\n",
    "search_results = spy.search({'Name': 'Example',\n",
    "                             'Type': 'Asset',\n",
    "                             'Datasource Name': 'Example Data'})\n",
    "example_data_tree = spy.assets.Tree(search_results)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "large-gibson",
   "metadata": {},
   "source": [
    "## Inserting Items into the Tree\n",
    "\n",
    "The next step to building your asset tree is to add more items to it. Inserting the data that makes up your tree can be broken down into roughly three distinct substeps:\n",
    "1. Insert assets to give the tree structure\n",
    "2. Add signals, conditions, and scalars from Seeq server into your new asset hierarchy\n",
    "3. Insert calculations\n",
    "\n",
    "Each of these steps is done using the `insert()` function. The `insert()` function can be called directly on your tree like this: `my_tree.insert(...inputs...)`. Your tree will be updated accordingly."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "complicated-joyce",
   "metadata": {},
   "source": [
    "### 1. Inserting Assets\n",
    "\n",
    "Assets are logical groups of signals, conditions, scalars, or even other assets. In most use cases, they represent physical locations, pieces of equipment, or organizational collections of other assets. The assets of our tree will form its backbone, while other items will usually be at the bottom of our tree, farthest from the root asset.\n",
    "\n",
    "To insert anything into the tree, we need to specify (1) what we are inserting and (2) where we want to insert it. We will always specify where we are inserting using the `parent` input – for example, write `parent='Area A'` as input to insert your data directly underneath the asset in your tree with name \"Area A\".\n",
    "\n",
    "To insert assets into the tree, give a name to the `children` input. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "magnetic-stock",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Successfully inserted items into the tree. The tree \"My Tree\" has height 2 and contains 2 assets.</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: right;\">Assets Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Signals Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Conditions Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Scalars Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Metrics Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Displays Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Total Items Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Items Pulled From Seeq</td><td style=\"background-color: #EEFFEE; text-align: right;\">Errors Encountered</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">Status</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "My Tree\n",
      "|-- Cooling Tower 1\n"
     ]
    }
   ],
   "source": [
    "my_tree.insert(children='Cooling Tower 1',\n",
    "               parent='My Tree')\n",
    "my_tree.visualize()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "offensive-federation",
   "metadata": {},
   "source": [
    "You can also give a list of names to create multiple assets at once."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "cathedral-engagement",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Successfully inserted items into the tree. The tree \"My Tree\" has height 3 and contains 5 assets.</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: right;\">Assets Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Signals Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Conditions Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Scalars Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Metrics Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Displays Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Total Items Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Items Pulled From Seeq</td><td style=\"background-color: #EEFFEE; text-align: right;\">Errors Encountered</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">Status</td><td style=\"text-align: right; vertical-align: top;\">3</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">3</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "My Tree\n",
      "|-- Cooling Tower 1\n",
      "    |-- Area A\n",
      "    |-- Area B\n",
      "    |-- Area C\n"
     ]
    }
   ],
   "source": [
    "my_tree.insert(children=['Area A', 'Area B', 'Area C'],\n",
    "               parent='Cooling Tower 1')\n",
    "my_tree.visualize()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "missing-mediterranean",
   "metadata": {},
   "source": [
    "Now we're ready to organize our data in the tree hierarchy we have created."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "honey-development",
   "metadata": {},
   "source": [
    "### 2. Inserting Signals, Conditions, and Scalars from Seeq Server\n",
    "\n",
    "To insert items from the server, we will need to give our tree information on where to find those items. One practical way to find this information is to query items from Seeq by name using the `spy.search` function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "agricultural-romantic",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Query successful</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: left;\">Name</td><td style=\"background-color: #EEFFEE; text-align: left;\">Datasource Name</td><td style=\"background-color: #EEFFEE; text-align: right;\">Time</td><td style=\"background-color: #EEFFEE; text-align: right;\">Count</td><td style=\"background-color: #EEFFEE; text-align: right;\">Pages</td><td style=\"background-color: #EEFFEE; text-align: left;\">Result</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">0</td><td style=\"text-align: left; vertical-align: top;\">Area A_Temperature</td><td style=\"text-align: left; vertical-align: top;\">Example Data</td><td style=\"vertical-align: top;\">00:00:00.10</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: left; vertical-align: top;\">Success</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "search_results = spy.search({'Name': 'Area A_Temperature',\n",
    "                             'Datasource Name': 'Example Data'})"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cosmetic-wilderness",
   "metadata": {},
   "source": [
    "We can pass these search results directly to the `children` input of the `insert()` function. Additionally, we can use the `friendly_name` input to rename the signal as we insert it."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "sufficient-insurance",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Successfully inserted items into the tree. The tree \"My Tree\" has height 4 and contains 5 assets and 1 signal.</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: right;\">Assets Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Signals Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Conditions Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Scalars Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Metrics Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Displays Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Total Items Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Items Pulled From Seeq</td><td style=\"background-color: #EEFFEE; text-align: right;\">Errors Encountered</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">Status</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">0</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "My Tree\n",
      "|-- Cooling Tower 1\n",
      "    |-- Area A\n",
      "    |   |-- Temperature\n",
      "    |-- Area B\n",
      "    |-- Area C\n"
     ]
    }
   ],
   "source": [
    "search_results = spy.search({'Name': 'Area A_Temperature',\n",
    "                             'Datasource Name': 'Example Data'})\n",
    "\n",
    "my_tree.insert(children=search_results,\n",
    "               friendly_name='Temperature',\n",
    "               parent='Area A')\n",
    "my_tree.visualize()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "monthly-reviewer",
   "metadata": {},
   "source": [
    "The new signal \"Temperature\" we see underneath \"Area A\" is a copy of the existing signal \"Area A_Temperature\" from Seeq. \n",
    "\n",
    "\n",
    "The [example notebook for spy.search](spy.search.ipynb) contains many more examples of how to query the server for the items you want to put in your tree. For instance, we can use [wildcards](https://telemetry.seeq.com/support-link/kb/latest/cloud/basic-item-search-and-filtering) to search for and insert many signals at once underneath Area B."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "greenhouse-zoning",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Successfully inserted items into the tree. The tree \"My Tree\" has height 4 and contains 7 signals and 5 assets.</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: right;\">Assets Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Signals Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Conditions Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Scalars Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Metrics Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Displays Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Total Items Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Items Pulled From Seeq</td><td style=\"background-color: #EEFFEE; text-align: right;\">Errors Encountered</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">Status</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">6</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">6</td><td style=\"text-align: right; vertical-align: top;\">6</td><td style=\"text-align: right; vertical-align: top;\">0</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "My Tree\n",
      "|-- Cooling Tower 1\n",
      "    |-- Area A\n",
      "    |   |-- Temperature\n",
      "    |-- Area B\n",
      "    |   |-- Area B_Compressor Power\n",
      "    |   |-- Area B_Compressor Stage\n",
      "    |   |-- Area B_Optimizer\n",
      "    |   |-- Area B_Relative Humidity\n",
      "    |   |-- Area B_Temperature\n",
      "    |   |-- Area B_Wet Bulb\n",
      "    |-- Area C\n"
     ]
    }
   ],
   "source": [
    "search_results = spy.search({'Name': 'Area B_*',\n",
    "                             'Type': 'Signal',\n",
    "                             'Datasource Name': 'Example Data'})\n",
    "\n",
    "my_tree.insert(children=search_results,\n",
    "               parent='Cooling Tower 1 >> Area B')\n",
    "my_tree.visualize()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "expired-sugar",
   "metadata": {},
   "source": [
    "Note that we included part of the path of \"Area B\" in the `parent` input – if there were multiple assets in the tree named \"Area B\", the function would then know to insert under the Area B that lies underneath Cooling Tower 1.\n",
    "\n",
    "Using `spy.search`, we can add hundreds or thousands of items to the tree in an organized manner. In addition to `visualize()`, you can use the function `missing_items()` to verify that your tree is balanced. For example, it flags to us that the asset \"Area F\" in the example data is missing signals that other assets in Cooling Tower 2 have."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "muslim-feeding",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "The following elements appear to be missing:\n",
      "Example >> Cooling Tower 2 >> Area F is missing: Compressor Stage, Optimizer, Relative Humidity, Temperature, Wet Bulb\n"
     ]
    }
   ],
   "source": [
    "example_data_tree.missing_items()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "composed-reach",
   "metadata": {},
   "source": [
    "Other attributes and functions helpful for understanding your tree include `my_tree.size`, `my_tree.height`, `my_tree.name`, and `my_tree.summarize()`."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "straight-howard",
   "metadata": {},
   "source": [
    "An alternative to using `spy.search` when inserting a single item is to copy the item's ID in Workbench and pass that ID to the `children` input.\n",
    "```python\n",
    "my_tree.insert(children='219C06CC-67C5-4512-9242-2271596CEF56',\n",
    "\t\t\t   parent='Area A')\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "friendly-entity",
   "metadata": {},
   "source": [
    "### 3. Inserting Calculations\n",
    "\n",
    "At this point our tree gives organization to pre-existing data. When we push it to Seeq, we can navigate around the tree and find the data grouped together by asset. While this functionality alone can enable powerful analytics in Seeq Server, we can further our analysis by creating *calculations* based upon the data items in our tree.\n",
    "\n",
    "A calculation requires a name, a formula, and a collection of formula parameters. The formula is written in [Seeq Formula Language](https://telemetry.seeq.com/support-link/kb/latest/cloud/formula), and the formula parameters assign variables in the formula to items in your tree."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "scientific-transportation",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Successfully inserted items into the tree. The tree \"My Tree\" has height 4 and contains 7 signals, 5 assets, and 1 calculation whose type has not yet been determined.</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: right;\">Assets Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Signals Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Conditions Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Scalars Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Metrics Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Displays Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Total Items Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Items Pulled From Seeq</td><td style=\"background-color: #EEFFEE; text-align: right;\">Errors Encountered</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">Status</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "My Tree\n",
      "|-- Cooling Tower 1\n",
      "    |-- Area A\n",
      "    |   |-- Temperature\n",
      "    |   |-- Too Hot\n",
      "    |-- Area B\n",
      "    |   |-- Area B_Compressor Power\n",
      "    |   |-- Area B_Compressor Stage\n",
      "    |   |-- Area B_Optimizer\n",
      "    |   |-- Area B_Relative Humidity\n",
      "    |   |-- Area B_Temperature\n",
      "    |   |-- Area B_Wet Bulb\n",
      "    |-- Area C\n"
     ]
    }
   ],
   "source": [
    "my_tree.insert(name='Too Hot',\n",
    "               formula='$temp > 100',\n",
    "               formula_parameters={'$temp': 'Temperature'},\n",
    "               parent='Area A')\n",
    "my_tree.visualize()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "developing-claim",
   "metadata": {},
   "source": [
    "It's often handy to create the same calculation for many assets across your tree that contain similarly named signals. This can be done by using [wildcards](https://telemetry.seeq.com/support-link/kb/latest/cloud/basic-item-search-and-filtering) in the `parent` input, just like when using `spy.search()`. Children will be inserted underneath every asset in the tree that matches the query given to `parent`.\n",
    "\n",
    "Let's try adding a \"Dew Point\" calculation underneath every area in a tree. Note that we'll use `my_csv_tree` for this example instead of `my_tree` because its signals have more uniform names across the tree."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "educated-davis",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Successfully inserted items into the tree. The tree \"My CSV Tree\" has height 4 and contains 8 signals, 7 assets, and 4 calculations whose types have not yet been determined.</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: right;\">Assets Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Signals Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Conditions Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Scalars Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Metrics Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Displays Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Total Items Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Items Pulled From Seeq</td><td style=\"background-color: #EEFFEE; text-align: right;\">Errors Encountered</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">Status</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">4</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "My CSV Tree\n",
      "|-- Cooling Tower 1\n",
      "|   |-- Area A\n",
      "|   |   |-- Dew Point\n",
      "|   |   |-- Relative Humidity\n",
      "|   |   |-- Temperature\n",
      "|   |-- Area B\n",
      "|       |-- Dew Point\n",
      "|       |-- Relative Humidity\n",
      "|       |-- Temperature\n",
      "|-- Cooling Tower 2\n",
      "    |-- Area D\n",
      "    |   |-- Dew Point\n",
      "    |   |-- Relative Humidity\n",
      "    |   |-- Temperature\n",
      "    |-- Area E\n",
      "        |-- Dew Point\n",
      "        |-- Relative Humidity\n",
      "        |-- Temperature\n"
     ]
    }
   ],
   "source": [
    "my_csv_tree.insert(name='Dew Point',\n",
    "                   formula='$t - ((100 - $rh.setUnits(\"\"))/5)', # From https://iridl.ldeo.columbia.edu/dochelp/QA/Basic/dewpoint.html\n",
    "                   formula_parameters={'$t': 'Temperature', '$rh': 'Relative Humidity'},\n",
    "                   parent='Area ?')\n",
    "my_csv_tree.visualize()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "prerequisite-beijing",
   "metadata": {},
   "source": [
    "Because there are signals \"Temperature\" and \"Relative Humidity\" under each parent asset, the calculations can successfully be inserted, with their formula parameters referring to the respective signals under their parent asset.\n",
    "\n",
    "The `parent` parameter will also accept `spy.search` results, an ID, or [regular expressions](https://docs.python.org/3/howto/regex.html) for more advanced querying, though we won't show examples here."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "jewish-armenia",
   "metadata": {},
   "source": [
    "## Removing and Moving Items\n",
    "\n",
    "After working with your new tree, you may find that you need to make adjustments. You can use the `remove()` and `move()` functions to do this. These functions may also be useful for narrowing the focus of a large asset tree you have copied from Seeq.\n",
    "\n",
    "The `remove()` function takes a single input that specifies which items in the tree to remove. Let's start by removing a single signal from `my_tree`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "chronic-assignment",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Successfully removed items from the tree. The tree \"My Tree\" has height 4 and contains 6 signals, 5 assets, and 1 calculation whose type has not yet been determined.</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: right;\">Assets Removed</td><td style=\"background-color: #EEFFEE; text-align: right;\">Signals Removed</td><td style=\"background-color: #EEFFEE; text-align: right;\">Conditions Removed</td><td style=\"background-color: #EEFFEE; text-align: right;\">Scalars Removed</td><td style=\"background-color: #EEFFEE; text-align: right;\">Metrics Removed</td><td style=\"background-color: #EEFFEE; text-align: right;\">Displays Removed</td><td style=\"background-color: #EEFFEE; text-align: right;\">Total Items Removed</td><td style=\"background-color: #EEFFEE; text-align: right;\">Items Pulled From Seeq</td><td style=\"background-color: #EEFFEE; text-align: right;\">Errors Encountered</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">Status</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "My Tree\n",
      "|-- Cooling Tower 1\n",
      "    |-- Area A\n",
      "    |   |-- Temperature\n",
      "    |   |-- Too Hot\n",
      "    |-- Area B\n",
      "    |   |-- Area B_Compressor Power\n",
      "    |   |-- Area B_Optimizer\n",
      "    |   |-- Area B_Relative Humidity\n",
      "    |   |-- Area B_Temperature\n",
      "    |   |-- Area B_Wet Bulb\n",
      "    |-- Area C\n"
     ]
    }
   ],
   "source": [
    "my_tree.remove('Area B_Compressor Stage')\n",
    "my_tree.visualize()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "republican-likelihood",
   "metadata": {},
   "source": [
    "Note that if an asset is removed, then all of its children will be removed as well:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "employed-distribution",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Successfully removed items from the tree. The tree \"My Tree\" has height 4 and contains 4 assets, 1 signal, and 1 calculation whose type has not yet been determined.</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: right;\">Assets Removed</td><td style=\"background-color: #EEFFEE; text-align: right;\">Signals Removed</td><td style=\"background-color: #EEFFEE; text-align: right;\">Conditions Removed</td><td style=\"background-color: #EEFFEE; text-align: right;\">Scalars Removed</td><td style=\"background-color: #EEFFEE; text-align: right;\">Metrics Removed</td><td style=\"background-color: #EEFFEE; text-align: right;\">Displays Removed</td><td style=\"background-color: #EEFFEE; text-align: right;\">Total Items Removed</td><td style=\"background-color: #EEFFEE; text-align: right;\">Items Pulled From Seeq</td><td style=\"background-color: #EEFFEE; text-align: right;\">Errors Encountered</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">Status</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">5</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">6</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "My Tree\n",
      "|-- Cooling Tower 1\n",
      "    |-- Area A\n",
      "    |   |-- Temperature\n",
      "    |   |-- Too Hot\n",
      "    |-- Area C\n"
     ]
    }
   ],
   "source": [
    "my_tree.remove('Area B')\n",
    "my_tree.visualize()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "equivalent-commons",
   "metadata": {},
   "source": [
    "The input for `remove()` also supports paths, wildcards, and `spy.search` results.\n",
    "\n",
    "```python\n",
    "example_data_tree.remove('Area A >> Temperature')\n",
    "example_data_tree.remove('Cooling Tower 2 >> Area ? >> Optimizer')\n",
    "example_data_tree.remove(spy.search({'Path': 'Example >> Cooling Tower 1', 'Asset': 'Area C'}))\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "sudden-travel",
   "metadata": {},
   "source": [
    "The `move()` function pops data out of the tree and inserts it back in at another location. It takes two inputs: `source` and `destination`. The `source` is what is being removed, and the `destination` is the new parent it should have when re-inserted into the tree.\n",
    "\n",
    "Let's say that we accidentally insert \"Area C_Temperature\" into Area A of My Tree."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "objective-desire",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Successfully inserted items into the tree. The tree \"My Tree\" has height 4 and contains 4 assets, 2 signals, and 1 calculation whose type has not yet been determined.</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: right;\">Assets Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Signals Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Conditions Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Scalars Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Metrics Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Displays Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Total Items Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Items Pulled From Seeq</td><td style=\"background-color: #EEFFEE; text-align: right;\">Errors Encountered</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">Status</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">0</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "My Tree\n",
      "|-- Cooling Tower 1\n",
      "    |-- Area A\n",
      "    |   |-- Area C_Temperature\n",
      "    |   |-- Temperature\n",
      "    |   |-- Too Hot\n",
      "    |-- Area C\n"
     ]
    }
   ],
   "source": [
    "my_tree.insert(children=spy.search({'Name': 'Area C_Temperature', 'Datasource Name': 'Example Data'}),\n",
    "               parent='Area A')\n",
    "my_tree.visualize()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "breathing-vision",
   "metadata": {},
   "source": [
    "Then we can easily amend our issue without starting over or rerunning commands by using the `move()` function:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "changed-coating",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Successfully moved items within the tree. The tree \"My Tree\" has height 4 and contains 4 assets, 2 signals, and 1 calculation whose type has not yet been determined.</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: right;\">Assets Moved</td><td style=\"background-color: #EEFFEE; text-align: right;\">Signals Moved</td><td style=\"background-color: #EEFFEE; text-align: right;\">Conditions Moved</td><td style=\"background-color: #EEFFEE; text-align: right;\">Scalars Moved</td><td style=\"background-color: #EEFFEE; text-align: right;\">Metrics Moved</td><td style=\"background-color: #EEFFEE; text-align: right;\">Displays Moved</td><td style=\"background-color: #EEFFEE; text-align: right;\">Total Items Moved</td><td style=\"background-color: #EEFFEE; text-align: right;\">Items Pulled From Seeq</td><td style=\"background-color: #EEFFEE; text-align: right;\">Errors Encountered</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">Status</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "My Tree\n",
      "|-- Cooling Tower 1\n",
      "    |-- Area A\n",
      "    |   |-- Temperature\n",
      "    |   |-- Too Hot\n",
      "    |-- Area C\n",
      "        |-- Area C_Temperature\n"
     ]
    }
   ],
   "source": [
    "my_tree.move(source='Area A >> Area C_Temperature',\n",
    "             destination='Area C')\n",
    "my_tree.visualize()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "instructional-secretariat",
   "metadata": {},
   "source": [
    "## Pushing a Tree\n",
    "\n",
    "The last step to working with an asset tree in SPy is to push your changes to Seeq! Up until now, all of our operations have only modified objects in Python — in order to view your tree in Workbench and share it with others, use the `push()` function to send it to the server."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "fluid-winner",
   "metadata": {
    "scrolled": true
   },
   "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>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</strong><br>Click the following link to see what you pushed in Seeq:<br><a href=\"http://localhost:34216/0EF5B5AA-5216-EC30-84D2-A83933EB8DAC/workbook/0EF5B5AA-AFD0-EE70-91E5-375B6D291908/worksheet/0EF5B5AA-B0C2-F9A0-8463-D211A4CA236C\" target=\"_blank\">http://localhost:34216/0EF5B5AA-5216-EC30-84D2-A83933EB8DAC/workbook/0EF5B5AA-AFD0-EE70-91E5-375B6D291908/worksheet/0EF5B5AA-B0C2-F9A0-8463-D211A4CA236C</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>ID</th>\n",
       "      <th>Referenced ID</th>\n",
       "      <th>Path</th>\n",
       "      <th>Name</th>\n",
       "      <th>Type</th>\n",
       "      <th>Depth</th>\n",
       "      <th>Description</th>\n",
       "      <th>Formula</th>\n",
       "      <th>Formula Parameters</th>\n",
       "      <th>Roll Up Statistic</th>\n",
       "      <th>...</th>\n",
       "      <th>Period</th>\n",
       "      <th>Process Type</th>\n",
       "      <th>Thresholds</th>\n",
       "      <th>Template ID</th>\n",
       "      <th>Scoped To</th>\n",
       "      <th>Datasource Class</th>\n",
       "      <th>Datasource ID</th>\n",
       "      <th>Data ID</th>\n",
       "      <th>Push Result</th>\n",
       "      <th>Cache Enabled</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0EF5B5AA-E307-6410-9271-3D4333038FBB</td>\n",
       "      <td>NaN</td>\n",
       "      <td></td>\n",
       "      <td>My CSV Tree</td>\n",
       "      <td>Asset</td>\n",
       "      <td>1</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0EF5B5AA-E30E-F940-BD05-CA42A4BD4FD8</td>\n",
       "      <td>NaN</td>\n",
       "      <td>My CSV Tree</td>\n",
       "      <td>Cooling Tower 1</td>\n",
       "      <td>Asset</td>\n",
       "      <td>2</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0EF5B5AA-E311-6050-AD69-554C2FB44C0B</td>\n",
       "      <td>NaN</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 1</td>\n",
       "      <td>Area A</td>\n",
       "      <td>Asset</td>\n",
       "      <td>3</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0EF5B5AA-E72F-FB50-A975-225BD5462C77</td>\n",
       "      <td>NaN</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 1 &gt;&gt; Area A</td>\n",
       "      <td>Dew Point</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$t - ((100 - $rh.setUnits(\"\"))/5)</td>\n",
       "      <td>[rh=0EF5B5AA-DE84-7780-9CF0-CA5956D31731, t=0E...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0EF5B5AA-DE84-7780-9CF0-CA5956D31731</td>\n",
       "      <td>0EF58FC2-83AA-66B0-8B9F-E021808A2620</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 1 &gt;&gt; Area A</td>\n",
       "      <td>Relative Humidity</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$signal</td>\n",
       "      <td>[signal=0EF58FC2-83AA-66B0-8B9F-E021808A2620]</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>0EF5B5AA-DF16-FF40-9946-B49C349B8702</td>\n",
       "      <td>0EF58FC2-8206-77F0-8519-ECD251B886A6</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 1 &gt;&gt; Area A</td>\n",
       "      <td>Temperature</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$signal</td>\n",
       "      <td>[signal=0EF58FC2-8206-77F0-8519-ECD251B886A6]</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>0EF5B5AA-E313-7760-B233-2B83515A65C7</td>\n",
       "      <td>NaN</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 1</td>\n",
       "      <td>Area B</td>\n",
       "      <td>Asset</td>\n",
       "      <td>3</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>0EF5B5AA-E7AE-EA90-87F4-A3CE0E4AC4E5</td>\n",
       "      <td>NaN</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 1 &gt;&gt; Area B</td>\n",
       "      <td>Dew Point</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$t - ((100 - $rh.setUnits(\"\"))/5)</td>\n",
       "      <td>[rh=0EF5B5AA-DFB0-EC30-B590-6EA50D38D6FE, t=0E...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>0EF5B5AA-DFB0-EC30-B590-6EA50D38D6FE</td>\n",
       "      <td>0EF58FC2-8348-EC30-874B-C093508CCDF8</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 1 &gt;&gt; Area B</td>\n",
       "      <td>Relative Humidity</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$signal</td>\n",
       "      <td>[signal=0EF58FC2-8348-EC30-874B-C093508CCDF8]</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>0EF5B5AA-E05B-EA90-B8FA-BADD579E9B67</td>\n",
       "      <td>0EF58FC2-82AC-E830-9324-CD3E38A9EB6E</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 1 &gt;&gt; Area B</td>\n",
       "      <td>Temperature</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$signal</td>\n",
       "      <td>[signal=0EF58FC2-82AC-E830-9324-CD3E38A9EB6E]</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>0EF5B5AA-E315-EE70-8552-04D354DD32B2</td>\n",
       "      <td>NaN</td>\n",
       "      <td>My CSV Tree</td>\n",
       "      <td>Cooling Tower 2</td>\n",
       "      <td>Asset</td>\n",
       "      <td>2</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>0EF5B5AA-E315-EE70-81F6-77F31DFC9881</td>\n",
       "      <td>NaN</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 2</td>\n",
       "      <td>Area D</td>\n",
       "      <td>Asset</td>\n",
       "      <td>3</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>0EF5B5AA-E826-64A0-9B03-3EF5DEFE914C</td>\n",
       "      <td>NaN</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 2 &gt;&gt; Area D</td>\n",
       "      <td>Dew Point</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$t - ((100 - $rh.setUnits(\"\"))/5)</td>\n",
       "      <td>[rh=0EF5B5AA-E0D3-64A0-9A71-A082E94842D4, t=0E...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>0EF5B5AA-E0D3-64A0-9A71-A082E94842D4</td>\n",
       "      <td>0EF58FC2-8294-7190-BE8D-EBBDC689A86E</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 2 &gt;&gt; Area D</td>\n",
       "      <td>Relative Humidity</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$signal</td>\n",
       "      <td>[signal=0EF58FC2-8294-7190-BE8D-EBBDC689A86E]</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>0EF5B5AA-E12D-F9F0-8FE4-6DCA0FB341E5</td>\n",
       "      <td>0EF58FC2-8B7C-75F0-99A3-B0D0420939F3</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 2 &gt;&gt; Area D</td>\n",
       "      <td>Temperature</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$signal</td>\n",
       "      <td>[signal=0EF58FC2-8B7C-75F0-99A3-B0D0420939F3]</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>0EF5B5AA-E31A-EC90-B179-74D6CDBCC0F2</td>\n",
       "      <td>NaN</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 2</td>\n",
       "      <td>Area E</td>\n",
       "      <td>Asset</td>\n",
       "      <td>3</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>0EF5B5AA-E8AA-6200-9756-4365981B5FEE</td>\n",
       "      <td>NaN</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 2 &gt;&gt; Area E</td>\n",
       "      <td>Dew Point</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$t - ((100 - $rh.setUnits(\"\"))/5)</td>\n",
       "      <td>[rh=0EF5B5AA-E1B6-7570-8256-731ED67AB9F2, t=0E...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>0EF5B5AA-E1B6-7570-8256-731ED67AB9F2</td>\n",
       "      <td>0EF58FC2-89B3-FD40-B547-C17F8D1C2503</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 2 &gt;&gt; Area E</td>\n",
       "      <td>Relative Humidity</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$signal</td>\n",
       "      <td>[signal=0EF58FC2-89B3-FD40-B547-C17F8D1C2503]</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>0EF5B5AA-E243-FF10-A297-50D876D72C44</td>\n",
       "      <td>0EF58FC2-8D14-7160-9EE1-1EC3CA6EFB2C</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 2 &gt;&gt; Area E</td>\n",
       "      <td>Temperature</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$signal</td>\n",
       "      <td>[signal=0EF58FC2-8D14-7160-9EE1-1EC3CA6EFB2C]</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>19 rows × 29 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                                      ID  \\\n",
       "0   0EF5B5AA-E307-6410-9271-3D4333038FBB   \n",
       "1   0EF5B5AA-E30E-F940-BD05-CA42A4BD4FD8   \n",
       "2   0EF5B5AA-E311-6050-AD69-554C2FB44C0B   \n",
       "3   0EF5B5AA-E72F-FB50-A975-225BD5462C77   \n",
       "4   0EF5B5AA-DE84-7780-9CF0-CA5956D31731   \n",
       "5   0EF5B5AA-DF16-FF40-9946-B49C349B8702   \n",
       "6   0EF5B5AA-E313-7760-B233-2B83515A65C7   \n",
       "7   0EF5B5AA-E7AE-EA90-87F4-A3CE0E4AC4E5   \n",
       "8   0EF5B5AA-DFB0-EC30-B590-6EA50D38D6FE   \n",
       "9   0EF5B5AA-E05B-EA90-B8FA-BADD579E9B67   \n",
       "10  0EF5B5AA-E315-EE70-8552-04D354DD32B2   \n",
       "11  0EF5B5AA-E315-EE70-81F6-77F31DFC9881   \n",
       "12  0EF5B5AA-E826-64A0-9B03-3EF5DEFE914C   \n",
       "13  0EF5B5AA-E0D3-64A0-9A71-A082E94842D4   \n",
       "14  0EF5B5AA-E12D-F9F0-8FE4-6DCA0FB341E5   \n",
       "15  0EF5B5AA-E31A-EC90-B179-74D6CDBCC0F2   \n",
       "16  0EF5B5AA-E8AA-6200-9756-4365981B5FEE   \n",
       "17  0EF5B5AA-E1B6-7570-8256-731ED67AB9F2   \n",
       "18  0EF5B5AA-E243-FF10-A297-50D876D72C44   \n",
       "\n",
       "                           Referenced ID  \\\n",
       "0                                    NaN   \n",
       "1                                    NaN   \n",
       "2                                    NaN   \n",
       "3                                    NaN   \n",
       "4   0EF58FC2-83AA-66B0-8B9F-E021808A2620   \n",
       "5   0EF58FC2-8206-77F0-8519-ECD251B886A6   \n",
       "6                                    NaN   \n",
       "7                                    NaN   \n",
       "8   0EF58FC2-8348-EC30-874B-C093508CCDF8   \n",
       "9   0EF58FC2-82AC-E830-9324-CD3E38A9EB6E   \n",
       "10                                   NaN   \n",
       "11                                   NaN   \n",
       "12                                   NaN   \n",
       "13  0EF58FC2-8294-7190-BE8D-EBBDC689A86E   \n",
       "14  0EF58FC2-8B7C-75F0-99A3-B0D0420939F3   \n",
       "15                                   NaN   \n",
       "16                                   NaN   \n",
       "17  0EF58FC2-89B3-FD40-B547-C17F8D1C2503   \n",
       "18  0EF58FC2-8D14-7160-9EE1-1EC3CA6EFB2C   \n",
       "\n",
       "                                        Path               Name  \\\n",
       "0                                                   My CSV Tree   \n",
       "1                                My CSV Tree    Cooling Tower 1   \n",
       "2             My CSV Tree >> Cooling Tower 1             Area A   \n",
       "3   My CSV Tree >> Cooling Tower 1 >> Area A          Dew Point   \n",
       "4   My CSV Tree >> Cooling Tower 1 >> Area A  Relative Humidity   \n",
       "5   My CSV Tree >> Cooling Tower 1 >> Area A        Temperature   \n",
       "6             My CSV Tree >> Cooling Tower 1             Area B   \n",
       "7   My CSV Tree >> Cooling Tower 1 >> Area B          Dew Point   \n",
       "8   My CSV Tree >> Cooling Tower 1 >> Area B  Relative Humidity   \n",
       "9   My CSV Tree >> Cooling Tower 1 >> Area B        Temperature   \n",
       "10                               My CSV Tree    Cooling Tower 2   \n",
       "11            My CSV Tree >> Cooling Tower 2             Area D   \n",
       "12  My CSV Tree >> Cooling Tower 2 >> Area D          Dew Point   \n",
       "13  My CSV Tree >> Cooling Tower 2 >> Area D  Relative Humidity   \n",
       "14  My CSV Tree >> Cooling Tower 2 >> Area D        Temperature   \n",
       "15            My CSV Tree >> Cooling Tower 2             Area E   \n",
       "16  My CSV Tree >> Cooling Tower 2 >> Area E          Dew Point   \n",
       "17  My CSV Tree >> Cooling Tower 2 >> Area E  Relative Humidity   \n",
       "18  My CSV Tree >> Cooling Tower 2 >> Area E        Temperature   \n",
       "\n",
       "                Type  Depth  Description                            Formula  \\\n",
       "0              Asset      1          NaN                                NaN   \n",
       "1              Asset      2          NaN                                NaN   \n",
       "2              Asset      3          NaN                                NaN   \n",
       "3   CalculatedSignal      4          NaN  $t - ((100 - $rh.setUnits(\"\"))/5)   \n",
       "4   CalculatedSignal      4          NaN                            $signal   \n",
       "5   CalculatedSignal      4          NaN                            $signal   \n",
       "6              Asset      3          NaN                                NaN   \n",
       "7   CalculatedSignal      4          NaN  $t - ((100 - $rh.setUnits(\"\"))/5)   \n",
       "8   CalculatedSignal      4          NaN                            $signal   \n",
       "9   CalculatedSignal      4          NaN                            $signal   \n",
       "10             Asset      2          NaN                                NaN   \n",
       "11             Asset      3          NaN                                NaN   \n",
       "12  CalculatedSignal      4          NaN  $t - ((100 - $rh.setUnits(\"\"))/5)   \n",
       "13  CalculatedSignal      4          NaN                            $signal   \n",
       "14  CalculatedSignal      4          NaN                            $signal   \n",
       "15             Asset      3          NaN                                NaN   \n",
       "16  CalculatedSignal      4          NaN  $t - ((100 - $rh.setUnits(\"\"))/5)   \n",
       "17  CalculatedSignal      4          NaN                            $signal   \n",
       "18  CalculatedSignal      4          NaN                            $signal   \n",
       "\n",
       "                                   Formula Parameters  Roll Up Statistic  ...  \\\n",
       "0                                                 NaN                NaN  ...   \n",
       "1                                                 NaN                NaN  ...   \n",
       "2                                                 NaN                NaN  ...   \n",
       "3   [rh=0EF5B5AA-DE84-7780-9CF0-CA5956D31731, t=0E...                NaN  ...   \n",
       "4       [signal=0EF58FC2-83AA-66B0-8B9F-E021808A2620]                NaN  ...   \n",
       "5       [signal=0EF58FC2-8206-77F0-8519-ECD251B886A6]                NaN  ...   \n",
       "6                                                 NaN                NaN  ...   \n",
       "7   [rh=0EF5B5AA-DFB0-EC30-B590-6EA50D38D6FE, t=0E...                NaN  ...   \n",
       "8       [signal=0EF58FC2-8348-EC30-874B-C093508CCDF8]                NaN  ...   \n",
       "9       [signal=0EF58FC2-82AC-E830-9324-CD3E38A9EB6E]                NaN  ...   \n",
       "10                                                NaN                NaN  ...   \n",
       "11                                                NaN                NaN  ...   \n",
       "12  [rh=0EF5B5AA-E0D3-64A0-9A71-A082E94842D4, t=0E...                NaN  ...   \n",
       "13      [signal=0EF58FC2-8294-7190-BE8D-EBBDC689A86E]                NaN  ...   \n",
       "14      [signal=0EF58FC2-8B7C-75F0-99A3-B0D0420939F3]                NaN  ...   \n",
       "15                                                NaN                NaN  ...   \n",
       "16  [rh=0EF5B5AA-E1B6-7570-8256-731ED67AB9F2, t=0E...                NaN  ...   \n",
       "17      [signal=0EF58FC2-89B3-FD40-B547-C17F8D1C2503]                NaN  ...   \n",
       "18      [signal=0EF58FC2-8D14-7160-9EE1-1EC3CA6EFB2C]                NaN  ...   \n",
       "\n",
       "    Period  Process Type  Thresholds  Template ID  \\\n",
       "0      NaN           NaN         NaN          NaN   \n",
       "1      NaN           NaN         NaN          NaN   \n",
       "2      NaN           NaN         NaN          NaN   \n",
       "3      NaN           NaN         NaN          NaN   \n",
       "4      NaN           NaN         NaN          NaN   \n",
       "5      NaN           NaN         NaN          NaN   \n",
       "6      NaN           NaN         NaN          NaN   \n",
       "7      NaN           NaN         NaN          NaN   \n",
       "8      NaN           NaN         NaN          NaN   \n",
       "9      NaN           NaN         NaN          NaN   \n",
       "10     NaN           NaN         NaN          NaN   \n",
       "11     NaN           NaN         NaN          NaN   \n",
       "12     NaN           NaN         NaN          NaN   \n",
       "13     NaN           NaN         NaN          NaN   \n",
       "14     NaN           NaN         NaN          NaN   \n",
       "15     NaN           NaN         NaN          NaN   \n",
       "16     NaN           NaN         NaN          NaN   \n",
       "17     NaN           NaN         NaN          NaN   \n",
       "18     NaN           NaN         NaN          NaN   \n",
       "\n",
       "                               Scoped To  Datasource Class  Datasource ID  \\\n",
       "0   0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "1   0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "2   0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "3   0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "4   0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "5   0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "6   0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "7   0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "8   0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "9   0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "10  0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "11  0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "12  0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "13  0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "14  0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "15  0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "16  0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "17  0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "18  0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "\n",
       "                                              Data ID  Push Result  \\\n",
       "0   [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...      Success   \n",
       "1   [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...      Success   \n",
       "2   [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...      Success   \n",
       "3   [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "4   [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "5   [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "6   [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...      Success   \n",
       "7   [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "8   [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "9   [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "10  [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...      Success   \n",
       "11  [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...      Success   \n",
       "12  [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "13  [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "14  [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "15  [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...      Success   \n",
       "16  [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "17  [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "18  [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "\n",
       "    Cache Enabled  \n",
       "0             NaN  \n",
       "1             NaN  \n",
       "2             NaN  \n",
       "3             NaN  \n",
       "4           False  \n",
       "5           False  \n",
       "6             NaN  \n",
       "7             NaN  \n",
       "8           False  \n",
       "9           False  \n",
       "10            NaN  \n",
       "11            NaN  \n",
       "12            NaN  \n",
       "13          False  \n",
       "14          False  \n",
       "15            NaN  \n",
       "16            NaN  \n",
       "17          False  \n",
       "18          False  \n",
       "\n",
       "[19 rows x 29 columns]"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "my_tree.push()\n",
    "my_csv_tree.push()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "loose-large",
   "metadata": {},
   "source": [
    "Tada! The link displayed in the output will take you to the workbook that now contains your asset tree."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "246162a9",
   "metadata": {},
   "source": [
    "## Detailed Help\n",
    "\n",
    "All SPy functions have detailed documentation to help you use them. Just execute `help(spy.<func>)` like\n",
    "you see below.\n",
    "\n",
    "**Make sure you re-execute the cell below to see the latest documentation. It otherwise might be from an\n",
    "earlier version of SPy.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "9af4a31a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on class Tree in module seeq.spy.assets._trees._tree:\n",
      "\n",
      "class Tree(builtins.object)\n",
      " |  Tree(data, *, friendly_name=None, description=None, workbook='Data Lab >> Data Lab Analysis', datasource=None, convert_displays_to_sdl=True, quiet=None, errors=None, status=None, session: 'Optional[Session]' = None)\n",
      " |  \n",
      " |  Manages an asset tree as a collection of item definitions in the form of\n",
      " |  a metadata DataFrame. Allows users to manipulate the tree using various functions.\n",
      " |  \n",
      " |  Parameters\n",
      " |  ----------\n",
      " |  data : {pandas.DataFrame, str}\n",
      " |      Defines which element will be inserted at the root.\n",
      " |      If an existing tree already exists in Seeq, the entire tree will be pulled recursively.\n",
      " |      If this tree doesn't already within the scope of the workbook, new tree elements\n",
      " |      will be created (by deep-copy or reference if applicable).\n",
      " |  \n",
      " |      The following options are allowed:\n",
      " |  \n",
      " |      1) A name string. If an existing tree with that name (case-insensitive) is found,\n",
      " |         all children will be recursively pulled in.\n",
      " |      2) An ID string of an existing item in Seeq. If that item is in a tree, all\n",
      " |         children will be recursively pulled in.\n",
      " |      3) spy.search results or other custom dataframes. The 'Path' column must be present\n",
      " |         and represent a single tree structure.\n",
      " |      4) A filename or relative file path to a CSV file. The CSV file should have either\n",
      " |         a complete Name column or a complete ID column, and should specify the tree\n",
      " |         path for each item either in a 'Path' column formatted as \"Root >> Next Level\":\n",
      " |  \n",
      " |         +--------------------+-----------+\n",
      " |         | Path               | Name      |\n",
      " |         +--------------------+-----------+\n",
      " |         | Root >> Next Level | Item_Name |\n",
      " |         +--------------------+-----------+\n",
      " |  \n",
      " |         or as a series of 'Levels' columns, e.g. \"Level 1\" and \"Level 2\" columns,\n",
      " |         where \"Level 1\" would be \"Root\" and \"Level 2\" would be \"Next Level\":\n",
      " |  \n",
      " |         +---------+------------+-----------+\n",
      " |         | Level 1 | Level 2    | Name      |\n",
      " |         +---------+------------+-----------+\n",
      " |         | Root    | Next Level | Item_Name |\n",
      " |         +---------+------------+-----------+\n",
      " |  \n",
      " |        The 'Level' columns will be forward-filled.\n",
      " |  \n",
      " |  friendly_name : str, optional\n",
      " |      Use this specified name rather than the referenced item's original name.\n",
      " |  \n",
      " |  description : str, optional\n",
      " |      The description to set on the root-level asset.\n",
      " |  \n",
      " |  workbook : str, default 'Data Lab >> Data Lab Analysis'\n",
      " |      The path to a workbook (in the form of 'Folder >> Path >> Workbook Name')\n",
      " |      or an ID that all pushed items will be 'scoped to'. You can\n",
      " |      push to the Corporate folder by using the following pattern:\n",
      " |      '__Corporate__ >> Folder >> Path >> Workbook Name'. Scoped items will not\n",
      " |      be visible/searchable using the data panel in other workbooks.\n",
      " |      A Tree can be globally scoped (and therefore visible across all\n",
      " |      workbooks) by specifying workbook=None.\n",
      " |  \n",
      " |  datasource : str, optional, default 'Seeq Data Lab'\n",
      " |      The name of the datasource within which to contain all the pushed items.\n",
      " |      Items inherit access control permissions from their datasource unless it\n",
      " |      has been overridden at a lower level. If you specify a datasource using\n",
      " |      this argument, you can later manage access control (using spy.acl functions)\n",
      " |      at the datasource level for all the items you have pushed.\n",
      " |  \n",
      " |      If you instead want access control for your items to be inherited from the\n",
      " |      workbook they are scoped to, specify `spy.INHERIT_FROM_WORKBOOK`.\n",
      " |  \n",
      " |  convert_displays_to_sdl : bool, default True\n",
      " |      If True, then if displays from a non-Seeq Data Lab datasource are found in\n",
      " |      a tree that is otherwise from a Seeq Data Lab datasource, then they will\n",
      " |      be replaced by displays from a Seeq Data Lab datasource when this tree\n",
      " |      is pushed.\n",
      " |  \n",
      " |  quiet : bool, default False\n",
      " |      If True, suppresses progress output. This setting will be the default for all\n",
      " |      operations on this Tree. This option can be changed later using\n",
      " |      `tree.quiet = True` or by specifying the option for individual function calls.\n",
      " |      Note that when status is provided, the quiet setting of the Status object\n",
      " |      that is passed in takes precedence.\n",
      " |  \n",
      " |  errors : {'raise', 'catalog'}, default 'raise'\n",
      " |      If 'raise', any errors encountered will cause an exception. If 'catalog',\n",
      " |      errors will be added to a 'Result' column in the status.df DataFrame. The\n",
      " |      option chosen here will be the default for all other operations on this Tree.\n",
      " |      This option can be changed later using `tree.errors = 'catalog'` or by\n",
      " |      specifying the option for individual function calls.\n",
      " |  \n",
      " |  status : spy.Status, optional\n",
      " |      If specified, the supplied Status object will be updated as the command\n",
      " |      progresses. It gets filled in with the same information you would see\n",
      " |      in Jupyter in the blue/green/red table below your code while the\n",
      " |      command is executed. The table itself is accessible as a DataFrame via\n",
      " |      the status.df property.\n",
      " |  \n",
      " |  session : spy.Session, optional\n",
      " |      If supplied, the Session object (and its Options) will be used to\n",
      " |      store the login session state. This is useful to log in to different\n",
      " |      Seeq servers at the same time or with different credentials.\n",
      " |  \n",
      " |  Methods defined here:\n",
      " |  \n",
      " |  __init__(self, data, *, friendly_name=None, description=None, workbook='Data Lab >> Data Lab Analysis', datasource=None, convert_displays_to_sdl=True, quiet=None, errors=None, status=None, session: 'Optional[Session]' = None)\n",
      " |      Initialize self.  See help(type(self)) for accurate signature.\n",
      " |  \n",
      " |  __iter__(self)\n",
      " |  \n",
      " |  __len__(self)\n",
      " |  \n",
      " |  __repr__(self, *args, **kwargs)\n",
      " |      Return repr(self).\n",
      " |  \n",
      " |  count(self, item_type=None)\n",
      " |      Count the number of elements in the tree of each Seeq type. If item_type\n",
      " |      is not specified, then returns a dictionary with keys 'Asset', 'Signal',\n",
      " |      'Condition', 'Scalar', and 'Unknown'. If item_type is specified, then\n",
      " |      returns an int.\n",
      " |      \n",
      " |      Parameters\n",
      " |      ----------\n",
      " |      item_type : {'Asset', 'Signal', 'Condition', 'Scalar', 'Uncompiled Formula'}, optional\n",
      " |          If specified, then the method will return an int representing the\n",
      " |          number of elements with Type item_type. Otherwise, a dict will be\n",
      " |          returned.\n",
      " |  \n",
      " |  insert(self, children=None, parent=None, *, name=None, formula=None, formula_parameters=None, roll_up_statistic=None, roll_up_parameters=None, friendly_name=None, errors=None, quiet=None, status=None)\n",
      " |      Insert the specified elements into the tree.\n",
      " |      \n",
      " |      Parameters\n",
      " |      ----------\n",
      " |      children : {pandas.DataFrame, pandas.Series, dict, str, list, Tree}, optional\n",
      " |          Defines which element or elements will be inserted below each parent. If an existing\n",
      " |          node already existed at the level in the tree with that name (case-insensitive),\n",
      " |          it will be updated. If it doesn't already exist, a new node will be created\n",
      " |          (by deep-copy or reference if applicable).\n",
      " |      \n",
      " |          The following options are allowed:\n",
      " |      \n",
      " |          1) A basic string or list of strings to create a new asset.\n",
      " |          2) Another SPy Tree.\n",
      " |          3) spy.search results or other custom dataframes.\n",
      " |      \n",
      " |      parent : {pandas.DataFrame, str, int, list}, optional\n",
      " |          Defines which element or elements the children will be inserted below.\n",
      " |      \n",
      " |          The following options are allowed:\n",
      " |      \n",
      " |          1) No parent specified will insert directly to the root of the tree.\n",
      " |          2) String name match (case-insensitive equality, globbing, regex, column\n",
      " |             values) will find any existing nodes in the tree that match.\n",
      " |          3) String path match, including partial path matches.\n",
      " |          4) ID. This can either be the actual ID of the tree.push()ed node or the\n",
      " |             ID of the source item.\n",
      " |          5) Number specifying tree level. This will add the children below every\n",
      " |             node at the specified level in the tree (1 being the root node).\n",
      " |          6) spy.search results or other custom dataframe.\n",
      " |      \n",
      " |      name: str, optional\n",
      " |          An alternative to the `children` parameter for specifying a single name\n",
      " |          for an asset or calculation to be inserted.\n",
      " |      \n",
      " |      formula : str, optional\n",
      " |          The formula for a calculated item. The `formula` and `formula_parameters` are\n",
      " |          used in place of the `children` argument.\n",
      " |      \n",
      " |      formula_parameters : dict, optional\n",
      " |          The parameters used in the specified `formula`. The following options are allowed:\n",
      " |      \n",
      " |          1) The name of an item that is an asset sibling of this calculation.\n",
      " |          2) The relative path to an item in this Tree (E.G. '.. >> Area E >> Temperature').\n",
      " |          3) The absolute path to an item in this Tree (E.G. 'Example >> Cooling Tower 2 >> Area E >> Temperature').\n",
      " |          4) The ID of an item (including ones not in the Tree).\n",
      " |      \n",
      " |      roll_up_statistic : str, optional\n",
      " |          The statistic to use when inserting a roll-up calculation. Valid options are\n",
      " |          Average, Maximum, Minimum, Range, Sum, Multiply, Union, Intersect, Counts,\n",
      " |          Count Overlaps, Combine With.\n",
      " |      \n",
      " |      roll_up_parameters : str, optional\n",
      " |          A wildcard or regex string that matches all of the parameters for a roll-up\n",
      " |          calculation. The roll-up calculation will apply the function specified by\n",
      " |          `roll_up_statistic` to all parameters that match this string. For example,\n",
      " |          `roll_up_statistic='Average', roll_up_parameters='Area ? >> Temperature'`\n",
      " |          will calculate the average of all signals with path 'Area ? >> Temperature'\n",
      " |          relative to the location of the roll-up in the tree.\n",
      " |      \n",
      " |      friendly_name : str, optional\n",
      " |          Use this specified name rather than the referenced item's original name.\n",
      " |      \n",
      " |      errors : {'raise', 'catalog'}, optional\n",
      " |          If 'raise', any errors encountered will cause an exception. If 'catalog',\n",
      " |          errors will be added to a 'Result' column in the status.df DataFrame. This\n",
      " |          input will be used only for the duration of this function; it will default\n",
      " |          to the setting on the Tree if not specified.\n",
      " |      \n",
      " |      quiet : bool, optional\n",
      " |          If True, suppresses progress output. This input will be used only for the\n",
      " |          duration of this function; it will default to the setting on the Tree if\n",
      " |          not specified. Note that when status is provided, the quiet setting of\n",
      " |          the Status object that is passed in takes precedence.\n",
      " |      \n",
      " |      status : spy.Status, optional\n",
      " |          If specified, the supplied Status object will be updated as the command\n",
      " |          progresses. It gets filled in with the same information you would see\n",
      " |          in Jupyter in the blue/green/red table below your code while the\n",
      " |          command is executed. The table itself is accessible as a DataFrame via\n",
      " |          the status.df property.\n",
      " |  \n",
      " |  items(self)\n",
      " |  \n",
      " |  missing_items(self, return_type='print')\n",
      " |      Identify elements that may be missing child elements based on the contents of other sibling nodes.\n",
      " |      \n",
      " |      Parameters\n",
      " |      ----------\n",
      " |      return_type : {'print', 'string', 'dict'}, default 'print'\n",
      " |          If 'print', then a string that enumerates the missing items will be\n",
      " |          printed. If 'string', then that same string will be returned and not\n",
      " |          printed. If 'dict', then a dictionary that maps element paths to lists\n",
      " |          of their potential missing children will be returned.\n",
      " |  \n",
      " |  move(self, source, destination=None, *, errors=None, quiet=None, status=None)\n",
      " |      Move the specified elements (and all children) from one location in\n",
      " |      the tree to another.\n",
      " |      \n",
      " |      Parameters\n",
      " |      ----------\n",
      " |      source : {pandas.DataFrame, str}\n",
      " |          Defines which element or elements will be moved.\n",
      " |      \n",
      " |          1) String path match.\n",
      " |          2) ID. This can either be the actual ID of the tree.push()ed node or the\n",
      " |             ID of the source item.\n",
      " |          3) spy.search results or other custom dataframe.\n",
      " |      \n",
      " |      destination : {pandas.DataFrame, str}; optional\n",
      " |          Defines the new parent for the source elements.\n",
      " |      \n",
      " |          1) No destination specified will move the elements to just below\n",
      " |             the root of the tree.\n",
      " |          2) String path match.\n",
      " |          3) ID. This can either be the actual ID of the tree.push()ed node or the\n",
      " |             ID of the source item.\n",
      " |          4) spy.search results or other custom dataframe.\n",
      " |      \n",
      " |      errors : {'raise', 'catalog'}, optional\n",
      " |          If 'raise', any errors encountered will cause an exception. If 'catalog',\n",
      " |          errors will be added to a 'Result' column in the status.df DataFrame. This\n",
      " |          input will be used only for the duration of this function; it will default\n",
      " |          to the setting on the Tree if not specified.\n",
      " |      \n",
      " |      quiet : bool, optional\n",
      " |          If True, suppresses progress output. This input will be used only for the\n",
      " |          duration of this function; it will default to the setting on the Tree if\n",
      " |          not specified. Note that when status is provided, the quiet setting of\n",
      " |          the Status object that is passed in takes precedence.\n",
      " |      \n",
      " |      status : spy.Status, optional\n",
      " |          If specified, the supplied Status object will be updated as the command\n",
      " |          progresses. It gets filled in with the same information you would see\n",
      " |          in Jupyter in the blue/green/red table below your code while the\n",
      " |          command is executed. The table itself is accessible as a DataFrame via\n",
      " |          the status.df property.\n",
      " |  \n",
      " |  push(self, *, metadata_state_file: 'Optional[str]' = None, errors: 'Optional[str]' = None, quiet: 'Optional[bool]' = None, status: 'Optional[Status]' = None) -> 'pd.DataFrame'\n",
      " |      Imports the tree into Seeq Server.\n",
      " |      \n",
      " |      metadata_state_file : str, optional\n",
      " |          The file name (with full path, if desired) to a \"metadata state file\"\n",
      " |          to use for \"incremental\" pushing, which can dramatically speed up\n",
      " |          pushing of a large asset tree. If supplied, the metadata push\n",
      " |          operation uses the state file to determine what changed since the\n",
      " |          last time the metadata was pushed and it will only act on those\n",
      " |          changes.\n",
      " |      \n",
      " |      errors : {'raise', 'catalog'}, optional\n",
      " |          If 'raise', any errors encountered will cause an exception. If 'catalog',\n",
      " |          errors will be added to a 'Result' column in the status.df DataFrame. This\n",
      " |          input will be used only for the duration of this function; it will default\n",
      " |          to the setting on the Tree if not specified.\n",
      " |      \n",
      " |      quiet : bool, optional\n",
      " |          If True, suppresses progress output. This input will be used only for the\n",
      " |          duration of this function; it will default to the setting on the Tree if\n",
      " |          not specified. Note that when status is provided, the quiet setting of\n",
      " |          the Status object that is passed in takes precedence.\n",
      " |      \n",
      " |      status : spy.Status, optional\n",
      " |          If specified, the supplied Status object will be updated as the command\n",
      " |          progresses. It gets filled in with the same information you would see\n",
      " |          in Jupyter in the blue/green/red table below your code while the\n",
      " |          command is executed. The table itself is accessible as a DataFrame via\n",
      " |          the status.df property.\n",
      " |      \n",
      " |      Returns\n",
      " |      -------\n",
      " |      pandas.DataFrame\n",
      " |          A DataFrame with the metadata for the items pushed, along with any\n",
      " |          errors and statistics about the operation. See spy.push()\n",
      " |          documentation for further details on this returned DataFrame.\n",
      " |  \n",
      " |  remove(self, elements, *, errors=None, quiet=None, status=None)\n",
      " |      Remove the specified elements from the tree recursively.\n",
      " |      \n",
      " |      Parameters\n",
      " |      ----------\n",
      " |      elements : {pandas.DataFrame, str, int}\n",
      " |          Defines which element or elements will be removed.\n",
      " |      \n",
      " |          1) String name match (case-insensitive equality, globbing, regex, column\n",
      " |             values) will find any existing nodes in the tree that match.\n",
      " |          2) String path match, including partial path matches.\n",
      " |          3) ID. This can either be the actual ID of the tree.push()ed node or the\n",
      " |             ID of the source item.\n",
      " |          4) Number specifying tree level. This will add the children below every\n",
      " |             node at the specified level in the tree (1 being the root node).\n",
      " |          5) spy.search results or other custom dataframe.\n",
      " |      \n",
      " |      errors : {'raise', 'catalog'}, optional\n",
      " |          If 'raise', any errors encountered will cause an exception. If 'catalog',\n",
      " |          errors will be added to a 'Result' column in the status.df DataFrame. This\n",
      " |          input will be used only for the duration of this function; it will default\n",
      " |          to the setting on the Tree if not specified.\n",
      " |      \n",
      " |      quiet : bool, optional\n",
      " |          If True, suppresses progress output. This input will be used only for the\n",
      " |          duration of this function; it will default to the setting on the Tree if\n",
      " |          not specified. Note that when status is provided, the quiet setting of\n",
      " |          the Status object that is passed in takes precedence.\n",
      " |      \n",
      " |      status : spy.Status, optional\n",
      " |          If specified, the supplied Status object will be updated as the command\n",
      " |          progresses. It gets filled in with the same information you would see\n",
      " |          in Jupyter in the blue/green/red table below your code while the\n",
      " |          command is executed. The table itself is accessible as a DataFrame via\n",
      " |          the status.df property.\n",
      " |  \n",
      " |  select(self, within=None, *, condition=None, start=None, end=None, errors=None, quiet=None, status=None) -> 'Tree'\n",
      " |      Select a subtree based on the specified parameters.\n",
      " |      Selects nodes of this Tree - creating a sub-tree - based on one or more Seeq Conditions present in the tree\n",
      " |      and evaluated during the given date range.  If the within argument is given, then only the related nodes are\n",
      " |      evaluated and possibly selected.\n",
      " |      \n",
      " |      Parameters\n",
      " |      ----------\n",
      " |      within : {pandas.DataFrame, list, str}, optional\n",
      " |          Specifies a pattern by which to select elements from the tree. If an element of the tree matches this\n",
      " |          pattern, then itself, its descendants, and its ancestors will be included in the resulting subtree\n",
      " |      \n",
      " |          The following rules apply:\n",
      " |      \n",
      " |          1) If not specified, the selection will return all items matching the given `condition`, `start`,\n",
      " |          and `end` criterion.\n",
      " |          2) String name match (case-insensitive equality, globbing, regex) will find any existing\n",
      " |          nodes in the tree that match.\n",
      " |          3) String path match, including partial path matches.\n",
      " |          4) ID. This can either be the actual ID of the pushed node or the ID of the source item.\n",
      " |          5) spy.search results or other custom dataframe.\n",
      " |      \n",
      " |      condition : {pandas.DataFrame, list, str}, optional\n",
      " |          If specified, then only assets that contain a condition matching this argument that have at least one\n",
      " |          capsule present in the start-end range specified will be included in the subtree.\n",
      " |      \n",
      " |      start: {str, pd.Timestamp}, optional\n",
      " |          The start date for which to evaluate the specified condition(s).\n",
      " |      \n",
      " |      end: {str, pd.Timestamp}, optional\n",
      " |          The end date for which to evaluate the specified condition(s).\n",
      " |      \n",
      " |      errors : {'raise', 'catalog'}, optional - default 'catalog'\n",
      " |          If 'raise', any errors encountered will cause an exception. If 'catalog',\n",
      " |          errors will be added to a 'Result' column in the status.df DataFrame. This\n",
      " |          input will be used only for the duration of this function; it will default\n",
      " |          to the setting on the Tree if not specified.\n",
      " |      \n",
      " |      quiet : bool, optional\n",
      " |          If True, suppresses progress output. This input will be used only for the\n",
      " |          duration of this function; it will default to the setting on the Tree if\n",
      " |          not specified. Note that when status is provided, the quiet setting of\n",
      " |          the Status object that is passed in takes precedence.\n",
      " |      \n",
      " |      status : spy.Status, optional\n",
      " |          If specified, the supplied Status object will be updated as the command\n",
      " |          progresses. It gets filled in with the same information you would see\n",
      " |          in Jupyter in the blue/green/red table below your code while the\n",
      " |          command is executed. The table itself is accessible as a DataFrame via\n",
      " |          the status.df property.\n",
      " |      \n",
      " |      Returns\n",
      " |      -------\n",
      " |      Tree\n",
      " |          A new Tree containing the items matching the given selection criterion.\n",
      " |  \n",
      " |  summarize(self, ret=False)\n",
      " |      Generate a human-readable summary of the tree.\n",
      " |      \n",
      " |      Parameters\n",
      " |      ----------\n",
      " |      ret : bool, default False\n",
      " |          If True, then this method returns a string summary of the tree. If\n",
      " |          False, then this method prints the summary and returns nothing.\n",
      " |  \n",
      " |  visualize(self, subtree=None, print_tree=True)\n",
      " |      Prints an ASCII visualization of this tree to stdout.\n",
      " |      \n",
      " |      subtree : str, optional\n",
      " |          Specifies an asset in the tree. Only the part of the tree below this asset\n",
      " |          will be visualized.\n",
      " |      print_tree: bool, optional\n",
      " |          True (default) to print the tree visualization, False to return it as a string\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Readonly properties defined here:\n",
      " |  \n",
      " |  df\n",
      " |  \n",
      " |  height\n",
      " |      Property that gives the current height of the tree. This is the length\n",
      " |      of the longest item path within the tree.\n",
      " |  \n",
      " |  size\n",
      " |      Property that gives the number of elements currently in the tree.\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Data descriptors defined here:\n",
      " |  \n",
      " |  __dict__\n",
      " |      dictionary for instance variables\n",
      " |  \n",
      " |  __weakref__\n",
      " |      list of weak references to the object\n",
      " |  \n",
      " |  name\n",
      " |  \n",
      " |  workbook\n",
      " |      Property that gives the current workbook of the tree. Returns None if tree is globally scoped\n",
      " |  \n",
      " |  ----------------------------------------------------------------------\n",
      " |  Data and other attributes defined here:\n",
      " |  \n",
      " |  __annotations__ = {'session': 'Session', 'status': 'Status'}\n",
      " |  \n",
      " |  is_dirty = False\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(spy.assets.Tree)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "square-surveillance",
   "metadata": {},
   "source": [
    "## Advanced Features\n",
    "\n",
    "### Inserting with Custom DataFrames\n",
    "\n",
    "For even more flexible insertions, you can provide any [Pandas DataFrame](https://pandas.pydata.org/pandas-docs/stable/user_guide/dsintro.html#dataframe) as input to the `children` argument. The features of the Pandas library can be harnessed to customize the path, name, formula, and properties of every item you are inserting into your tree."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "paperback-egyptian",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Successfully inserted items into the tree. The tree \"My Tree\" has height 4 and contains 4 assets, 3 signals, 1 calculation whose type has not yet been determined, and 1 condition.</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: right;\">Assets Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Signals Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Conditions Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Scalars Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Metrics Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Displays Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Total Items Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Items Pulled From Seeq</td><td style=\"background-color: #EEFFEE; text-align: right;\">Errors Encountered</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">Status</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">2</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">0</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "new_signals = pd.DataFrame([{\n",
    "    'Name': 'Relative Humidity',\n",
    "    'ID': spy.search({'Name': 'Area A_Relative Humidity', 'Datasource Name': 'Example Data'}).ID.squeeze(),\n",
    "    'Parent': 'Area A'\n",
    "}, {\n",
    "    'Name': 'Dew Point',\n",
    "    'Formula': '$t - ((100 - $RH.setUnits(\"\"))/5)',\n",
    "    'Formula Parameters': {'$t': 'Temperature', '$rh': 'Relative Humidity'},\n",
    "    'Parent': 'Area A'\n",
    "}])\n",
    "\n",
    "my_tree.insert(new_signals)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "similar-reflex",
   "metadata": {},
   "source": [
    "### Inserting Metrics\n",
    "\n",
    "Once your tree is defined with the data items you're interested in, you can add metrics to create tabular calculations.\n",
    "\n",
    "Metrics usually have more inputs than other types of tree items and therefore must be defined using a DataFrame. The required properties are the Name, Type ('Metric'), and a Measured Item. Like formula parameters for calculations, the Measured Item, Bounding Condition, and Thresholds can refer to other items in your tree.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "sweet-justice",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Successfully inserted items into the tree. The tree \"My Tree\" has height 4 and contains 4 assets, 3 signals, 2 metrics, 1 calculation whose type has not yet been determined, and 1 condition.</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: right;\">Assets Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Signals Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Conditions Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Scalars Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Metrics Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Displays Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Total Items Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Items Pulled From Seeq</td><td style=\"background-color: #EEFFEE; text-align: right;\">Errors Encountered</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">Status</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">2</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">2</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "new_metrics = pd.DataFrame([{\n",
    "    'Name': 'Dew Point Hourly Average',\n",
    "    'Type': 'Metric',\n",
    "    'Parent': 'Area A',\n",
    "    'Measured Item': 'Dew Point',\n",
    "    'Statistic': 'Average',\n",
    "    'Duration': '1h',\n",
    "    'Period': '1h',\n",
    "}, {\n",
    "    'Name': 'Overheating Severity',\n",
    "    'Type': 'Metric',\n",
    "    'Parent': 'Area A',\n",
    "    'Measured Item': 'Dew Point',\n",
    "    'Aggregation Function': 'percentile(95)',\n",
    "    'Bounding Condition': 'Too Hot',\n",
    "    'Bounding Condition Maximum Duration': '48h',\n",
    "    'Metric Neutral Color': '#FFFFFF',\n",
    "    'Thresholds': {\n",
    "        'HiHiHi#FF0000': 95,\n",
    "        'HiHi': 'Temperature',\n",
    "        'Hi': 85\n",
    "    }\n",
    "}])\n",
    "\n",
    "my_tree.insert(new_metrics)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fallen-uganda",
   "metadata": {},
   "source": [
    "### Inserting Roll-up Calculations\n",
    "\n",
    "*Roll-up calculations* are a great way to evaluate summary statistics across multiple assets in your tree in order to monitor the health and performance of your assets. To insert a roll-up calculation, use the `roll_up_statistic` and `roll_up_parameters` inputs to the `insert()` function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "discrete-differential",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Successfully inserted items into the tree. The tree \"My CSV Tree\" has height 4 and contains 12 signals, 7 assets, and 2 calculations whose types have not yet been determined.</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: right;\">Assets Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Signals Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Conditions Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Scalars Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Metrics Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Displays Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Total Items Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Items Pulled From Seeq</td><td style=\"background-color: #EEFFEE; text-align: right;\">Errors Encountered</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">Status</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">2</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "My CSV Tree\n",
      "|-- Cooling Tower 1\n",
      "|   |-- Area A\n",
      "|   |   |-- Dew Point\n",
      "|   |   |-- Relative Humidity\n",
      "|   |   |-- Temperature\n",
      "|   |-- Area B\n",
      "|   |   |-- Dew Point\n",
      "|   |   |-- Relative Humidity\n",
      "|   |   |-- Temperature\n",
      "|   |-- Average Temperature of All Areas\n",
      "|-- Cooling Tower 2\n",
      "    |-- Area D\n",
      "    |   |-- Dew Point\n",
      "    |   |-- Relative Humidity\n",
      "    |   |-- Temperature\n",
      "    |-- Area E\n",
      "    |   |-- Dew Point\n",
      "    |   |-- Relative Humidity\n",
      "    |   |-- Temperature\n",
      "    |-- Average Temperature of All Areas\n"
     ]
    }
   ],
   "source": [
    "my_csv_tree.insert(name='Average Temperature of All Areas',\n",
    "                   roll_up_statistic='Average',\n",
    "                   roll_up_parameters='Area ? >> Temperature',\n",
    "                   parent='Cooling Tower ?')\n",
    "my_csv_tree"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "western-laptop",
   "metadata": {},
   "source": [
    "The resulting calculation is created by applying the function specified by `roll_up_statistic` to all parameters that match the string given by `roll_up_parameters`. In this case, the roll-up `Cooling Tower 1 >> Average Temperature of All Areas` calculates the average of `Area A >> Temperature` and `Area B >> Temperature`, and similarly for Cooling Tower 2, Area D, and Area E respectively."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "alone-gates",
   "metadata": {},
   "source": [
    "### Inserting with References\n",
    "\n",
    "When inserting many items into a tree at once, you may want each item you are inserting to have a different friendly name and a different parent. To achieve this quickly, you can pass references to DataFrame columns to the arguments `friendly_name` and `parent` of the `insert()` function.\n",
    "\n",
    "In the Seeq example data, there are a collection of signals with names of the format `'Area A_Temperature'`. Column references allows you to insert all of these signals at once, where the signal `'Area A_Temperature'` has parent `'Area A'` with friendly name `'Temperature'`, while the signal `'Area D_Compressor Power'` has parent `'Area D'` and friendly name `'Compressor Power'`, and so on. First let's remove all existing signals from `my_tree`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "effective-headline",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Successfully removed items from the tree. The tree \"My Tree\" has height 3 and contains 4 assets.</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: right;\">Assets Removed</td><td style=\"background-color: #EEFFEE; text-align: right;\">Signals Removed</td><td style=\"background-color: #EEFFEE; text-align: right;\">Conditions Removed</td><td style=\"background-color: #EEFFEE; text-align: right;\">Scalars Removed</td><td style=\"background-color: #EEFFEE; text-align: right;\">Metrics Removed</td><td style=\"background-color: #EEFFEE; text-align: right;\">Displays Removed</td><td style=\"background-color: #EEFFEE; text-align: right;\">Total Items Removed</td><td style=\"background-color: #EEFFEE; text-align: right;\">Items Pulled From Seeq</td><td style=\"background-color: #EEFFEE; text-align: right;\">Errors Encountered</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">Status</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">3</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">2</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">7</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "my_tree.remove('Area ? >> *')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "indonesian-running",
   "metadata": {},
   "source": [
    "Then let's grab the signals from Seeq:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "guided-animation",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Query successful</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: left;\">Name</td><td style=\"background-color: #EEFFEE; text-align: left;\">Datasource Name</td><td style=\"background-color: #EEFFEE; text-align: right;\">Time</td><td style=\"background-color: #EEFFEE; text-align: right;\">Count</td><td style=\"background-color: #EEFFEE; text-align: right;\">Pages</td><td style=\"background-color: #EEFFEE; text-align: left;\">Result</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">0</td><td style=\"text-align: left; vertical-align: top;\">Area ?_*</td><td style=\"text-align: left; vertical-align: top;\">Example Data</td><td style=\"vertical-align: top;\">00:00:00.32</td><td style=\"text-align: right; vertical-align: top;\">68</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: left; vertical-align: top;\">Success</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>Description</th>\n",
       "      <th>Type</th>\n",
       "      <th>Value Unit Of Measure</th>\n",
       "      <th>Datasource Name</th>\n",
       "      <th>Archived</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0EF58FC2-8C7F-6290-BEE8-1BE39219249E</td>\n",
       "      <td>Area A_Compressor Power</td>\n",
       "      <td>NaN</td>\n",
       "      <td>StoredSignal</td>\n",
       "      <td>kW</td>\n",
       "      <td>Example Data</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0EF58FC2-85EA-F970-941E-20CF2C149E2D</td>\n",
       "      <td>Area A_Compressor Stage</td>\n",
       "      <td>NaN</td>\n",
       "      <td>StoredSignal</td>\n",
       "      <td>string</td>\n",
       "      <td>Example Data</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0EF58FC2-82CE-FB10-95A4-EFA2E6D878DB</td>\n",
       "      <td>Area A_Optimizer</td>\n",
       "      <td>NaN</td>\n",
       "      <td>StoredSignal</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Example Data</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0EF58FC2-83AA-66B0-8B9F-E021808A2620</td>\n",
       "      <td>Area A_Relative Humidity</td>\n",
       "      <td>NaN</td>\n",
       "      <td>StoredSignal</td>\n",
       "      <td>%</td>\n",
       "      <td>Example Data</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0EF58FC2-8206-77F0-8519-ECD251B886A6</td>\n",
       "      <td>Area A_Temperature</td>\n",
       "      <td>NaN</td>\n",
       "      <td>StoredSignal</td>\n",
       "      <td>°F</td>\n",
       "      <td>Example Data</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                     ID                      Name  \\\n",
       "0  0EF58FC2-8C7F-6290-BEE8-1BE39219249E   Area A_Compressor Power   \n",
       "1  0EF58FC2-85EA-F970-941E-20CF2C149E2D   Area A_Compressor Stage   \n",
       "2  0EF58FC2-82CE-FB10-95A4-EFA2E6D878DB          Area A_Optimizer   \n",
       "3  0EF58FC2-83AA-66B0-8B9F-E021808A2620  Area A_Relative Humidity   \n",
       "4  0EF58FC2-8206-77F0-8519-ECD251B886A6        Area A_Temperature   \n",
       "\n",
       "   Description          Type Value Unit Of Measure Datasource Name  Archived  \n",
       "0          NaN  StoredSignal                    kW    Example Data     False  \n",
       "1          NaN  StoredSignal                string    Example Data     False  \n",
       "2          NaN  StoredSignal                   NaN    Example Data     False  \n",
       "3          NaN  StoredSignal                     %    Example Data     False  \n",
       "4          NaN  StoredSignal                    °F    Example Data     False  "
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "search_results = spy.search({'Name': 'Area ?_*',\n",
    "                             'Datasource Name': 'Example Data'}, order_by='Name')\n",
    "search_results.head(5)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "frozen-mission",
   "metadata": {},
   "source": [
    "A column value reference has the following syntax: `{{ ... } ... }`. The substring within the inner braces specifies which column of the above DataFrame to look for data in. If nothing is provided where the second ellipsis is, then the data from that column will be returned. For example the first row seen above would return `kW` when queried with `{{Value Unit Of Measure}}`. However, if we only want some of the data in the column, then we can provide an expression with wildcards that matches the data and has parentheses surrounding the substring we wish to extract. For example, `{{Name}Area ?_(*)}` will return `Compressor Power` in the first row.\n",
    "\n",
    "Let's see it in action:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "id": "false-olive",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Successfully inserted items into the tree. The tree \"My Tree\" has height 4 and contains 12 signals and 4 assets.</div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: right;\">Assets Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Signals Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Conditions Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Scalars Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Metrics Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Displays Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Total Items Inserted</td><td style=\"background-color: #EEFFEE; text-align: right;\">Items Pulled From Seeq</td><td style=\"background-color: #EEFFEE; text-align: right;\">Errors Encountered</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">Status</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">12</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">0</td><td style=\"text-align: right; vertical-align: top;\">12</td><td style=\"text-align: right; vertical-align: top;\">68</td><td style=\"text-align: right; vertical-align: top;\">0</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "My Tree\n",
      "|-- Cooling Tower 1\n",
      "    |-- Area A\n",
      "    |   |-- Compressor Power\n",
      "    |   |-- Compressor Stage\n",
      "    |   |-- Optimizer\n",
      "    |   |-- Relative Humidity\n",
      "    |   |-- Temperature\n",
      "    |   |-- Wet Bulb\n",
      "    |-- Area C\n",
      "        |-- Compressor Power\n",
      "        |-- Compressor Stage\n",
      "        |-- Optimizer\n",
      "        |-- Relative Humidity\n",
      "        |-- Temperature\n",
      "        |-- Wet Bulb\n"
     ]
    }
   ],
   "source": [
    "my_tree.insert(children=search_results,\n",
    "               friendly_name='{{Name}Area ?_(*)}',\n",
    "               parent='{{Name}(Area ?)_*}')\n",
    "my_tree.visualize()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "aging-cliff",
   "metadata": {},
   "source": [
    "Below are more examples of column value extraction syntax, with the following input `children` DataFrame:\n",
    "\n",
    "| ID                                   | Name         | Unit  | Facility Type     |\n",
    "| ------------------------------------ | ------------ | ----- | ----------------- |\n",
    "| B8FA62DA-5C42-4CA3-9C3F-E80E6E5AE990 | Site A_Temp  | °F    | Research Facility |\n",
    "| 51D52461-A667-413A-AD9E-548FE16E601B | Site B_Flow  | gal/s | Factory           |\n",
    "\n",
    "\n",
    "\n",
    "| Syntax                                                      | Syntax Description                                                                                                                                                                                                                                                                                                 | Output for first row        | Output for second row          |   |\n",
    "|-------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------|--------------------------------|---|\n",
    "| {{Name}}                                                    | Get the value of the \"Name\" column for that row.                                                                                                                                                                                                                                                                   | Site A_Temp                 | Site B_Flow                    |   |\n",
    "| {{Name}Site ?_(*)}                                          | From the \"Name\" column, get the value of the wildcard match after \"Site ?_\".                                                                                                                                                                                                                                       | Temp                        | Flow                           |   |\n",
    "| {{Name}(*_Temp)}                                            | Get the entire value of the \"Name\" column for that row if it matches \"*_Temp\". Note: this pattern does not match the second row. If such a pattern is used for `parent`, then the row would not be inserted under any parent. If such a pattern is used for `friendly_name`, its original name will be used.                                                                                          | Site A_Temp                 | N/A        |   |\n",
    "| {{Facility Type}} {{Name}Site (?)_*}                        | Get the value of the \"Facility Type\" column for that row. Then a literal \" \" character. Then from the \"Name\" column, get the value of the single-char wildcard between \"Site \" and \"_\".                                                                                                                            | Research Facility A         | Factory B                      |   |\n",
    "| Average of {{Name}(Site ?)_*} {{Name}Site ?_(*)} ({{Unit}}) | A literal \"Average of \". Then from the \"Name\" column, get the value of the substring matching \"Site ?\" before the \"_\". Then a literal \" \" character. Then from the \"Name\" column, get the value of the wildcard match after \"Site ?_\". Then a literal \" (\". Get the value of the \"Unit\" column. Then a literal \")\". | Average of Site A Temp (°F) | Average of Site B Flow (gal/s) |   |"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0137ac2a",
   "metadata": {},
   "source": [
    "### Pushing Large Trees\n",
    "If you've created a large tree, it can take significant time to execute the `push()` command. You can speed it\n",
    "up by making use of a _metadata state file_. You just need to specify a unique filename like so:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "ca4728b1",
   "metadata": {},
   "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>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</strong><br>Click the following link to see what you pushed in Seeq:<br><a href=\"http://localhost:34216/0EF5B5AA-5216-EC30-84D2-A83933EB8DAC/workbook/0EF5B5AA-AFD0-EE70-91E5-375B6D291908/worksheet/0EF5B5AA-B0C2-F9A0-8463-D211A4CA236C\" target=\"_blank\">http://localhost:34216/0EF5B5AA-5216-EC30-84D2-A83933EB8DAC/workbook/0EF5B5AA-AFD0-EE70-91E5-375B6D291908/worksheet/0EF5B5AA-B0C2-F9A0-8463-D211A4CA236C</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>ID</th>\n",
       "      <th>Referenced ID</th>\n",
       "      <th>Path</th>\n",
       "      <th>Name</th>\n",
       "      <th>Type</th>\n",
       "      <th>Depth</th>\n",
       "      <th>Description</th>\n",
       "      <th>Formula</th>\n",
       "      <th>Formula Parameters</th>\n",
       "      <th>Roll Up Statistic</th>\n",
       "      <th>...</th>\n",
       "      <th>Period</th>\n",
       "      <th>Process Type</th>\n",
       "      <th>Thresholds</th>\n",
       "      <th>Template ID</th>\n",
       "      <th>Scoped To</th>\n",
       "      <th>Datasource Class</th>\n",
       "      <th>Datasource ID</th>\n",
       "      <th>Data ID</th>\n",
       "      <th>Push Result</th>\n",
       "      <th>Cache Enabled</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0EF5B5AA-E307-6410-9271-3D4333038FBB</td>\n",
       "      <td>NaN</td>\n",
       "      <td></td>\n",
       "      <td>My CSV Tree</td>\n",
       "      <td>Asset</td>\n",
       "      <td>1</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0EF5B5AA-E30E-F940-BD05-CA42A4BD4FD8</td>\n",
       "      <td>NaN</td>\n",
       "      <td>My CSV Tree</td>\n",
       "      <td>Cooling Tower 1</td>\n",
       "      <td>Asset</td>\n",
       "      <td>2</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0EF5B5AA-E311-6050-AD69-554C2FB44C0B</td>\n",
       "      <td>NaN</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 1</td>\n",
       "      <td>Area A</td>\n",
       "      <td>Asset</td>\n",
       "      <td>3</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0EF5B5AA-E72F-FB50-A975-225BD5462C77</td>\n",
       "      <td>NaN</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 1 &gt;&gt; Area A</td>\n",
       "      <td>Dew Point</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$t - ((100 - $rh.setUnits(\"\"))/5)</td>\n",
       "      <td>[rh=0EF5B5AA-DE84-7780-9CF0-CA5956D31731, t=0E...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0EF5B5AA-DE84-7780-9CF0-CA5956D31731</td>\n",
       "      <td>0EF58FC2-83AA-66B0-8B9F-E021808A2620</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 1 &gt;&gt; Area A</td>\n",
       "      <td>Relative Humidity</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$signal</td>\n",
       "      <td>[signal=0EF58FC2-83AA-66B0-8B9F-E021808A2620]</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>0EF5B5AA-DF16-FF40-9946-B49C349B8702</td>\n",
       "      <td>0EF58FC2-8206-77F0-8519-ECD251B886A6</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 1 &gt;&gt; Area A</td>\n",
       "      <td>Temperature</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$signal</td>\n",
       "      <td>[signal=0EF58FC2-8206-77F0-8519-ECD251B886A6]</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>0EF5B5AA-E313-7760-B233-2B83515A65C7</td>\n",
       "      <td>NaN</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 1</td>\n",
       "      <td>Area B</td>\n",
       "      <td>Asset</td>\n",
       "      <td>3</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>0EF5B5AA-E7AE-EA90-87F4-A3CE0E4AC4E5</td>\n",
       "      <td>NaN</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 1 &gt;&gt; Area B</td>\n",
       "      <td>Dew Point</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$t - ((100 - $rh.setUnits(\"\"))/5)</td>\n",
       "      <td>[rh=0EF5B5AA-DFB0-EC30-B590-6EA50D38D6FE, t=0E...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>0EF5B5AA-DFB0-EC30-B590-6EA50D38D6FE</td>\n",
       "      <td>0EF58FC2-8348-EC30-874B-C093508CCDF8</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 1 &gt;&gt; Area B</td>\n",
       "      <td>Relative Humidity</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$signal</td>\n",
       "      <td>[signal=0EF58FC2-8348-EC30-874B-C093508CCDF8]</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>0EF5B5AA-E05B-EA90-B8FA-BADD579E9B67</td>\n",
       "      <td>0EF58FC2-82AC-E830-9324-CD3E38A9EB6E</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 1 &gt;&gt; Area B</td>\n",
       "      <td>Temperature</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$signal</td>\n",
       "      <td>[signal=0EF58FC2-82AC-E830-9324-CD3E38A9EB6E]</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>0EF5B5AB-2478-62F0-96F5-AC05FDA7EB48</td>\n",
       "      <td>NaN</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 1</td>\n",
       "      <td>Average Temperature of All Areas</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>3</td>\n",
       "      <td>NaN</td>\n",
       "      <td>average($p0, $p1)</td>\n",
       "      <td>[p0=0EF5B5AA-DF16-FF40-9946-B49C349B8702, p1=0...</td>\n",
       "      <td>Average</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>0EF5B5AA-E315-EE70-8552-04D354DD32B2</td>\n",
       "      <td>NaN</td>\n",
       "      <td>My CSV Tree</td>\n",
       "      <td>Cooling Tower 2</td>\n",
       "      <td>Asset</td>\n",
       "      <td>2</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>0EF5B5AA-E315-EE70-81F6-77F31DFC9881</td>\n",
       "      <td>NaN</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 2</td>\n",
       "      <td>Area D</td>\n",
       "      <td>Asset</td>\n",
       "      <td>3</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>0EF5B5AA-E826-64A0-9B03-3EF5DEFE914C</td>\n",
       "      <td>NaN</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 2 &gt;&gt; Area D</td>\n",
       "      <td>Dew Point</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$t - ((100 - $rh.setUnits(\"\"))/5)</td>\n",
       "      <td>[rh=0EF5B5AA-E0D3-64A0-9A71-A082E94842D4, t=0E...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>0EF5B5AA-E0D3-64A0-9A71-A082E94842D4</td>\n",
       "      <td>0EF58FC2-8294-7190-BE8D-EBBDC689A86E</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 2 &gt;&gt; Area D</td>\n",
       "      <td>Relative Humidity</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$signal</td>\n",
       "      <td>[signal=0EF58FC2-8294-7190-BE8D-EBBDC689A86E]</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>0EF5B5AA-E12D-F9F0-8FE4-6DCA0FB341E5</td>\n",
       "      <td>0EF58FC2-8B7C-75F0-99A3-B0D0420939F3</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 2 &gt;&gt; Area D</td>\n",
       "      <td>Temperature</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$signal</td>\n",
       "      <td>[signal=0EF58FC2-8B7C-75F0-99A3-B0D0420939F3]</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>16</th>\n",
       "      <td>0EF5B5AA-E31A-EC90-B179-74D6CDBCC0F2</td>\n",
       "      <td>NaN</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 2</td>\n",
       "      <td>Area E</td>\n",
       "      <td>Asset</td>\n",
       "      <td>3</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>17</th>\n",
       "      <td>0EF5B5AA-E8AA-6200-9756-4365981B5FEE</td>\n",
       "      <td>NaN</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 2 &gt;&gt; Area E</td>\n",
       "      <td>Dew Point</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$t - ((100 - $rh.setUnits(\"\"))/5)</td>\n",
       "      <td>[rh=0EF5B5AA-E1B6-7570-8256-731ED67AB9F2, t=0E...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>18</th>\n",
       "      <td>0EF5B5AA-E1B6-7570-8256-731ED67AB9F2</td>\n",
       "      <td>0EF58FC2-89B3-FD40-B547-C17F8D1C2503</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 2 &gt;&gt; Area E</td>\n",
       "      <td>Relative Humidity</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$signal</td>\n",
       "      <td>[signal=0EF58FC2-89B3-FD40-B547-C17F8D1C2503]</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>19</th>\n",
       "      <td>0EF5B5AA-E243-FF10-A297-50D876D72C44</td>\n",
       "      <td>0EF58FC2-8D14-7160-9EE1-1EC3CA6EFB2C</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 2 &gt;&gt; Area E</td>\n",
       "      <td>Temperature</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>4</td>\n",
       "      <td>NaN</td>\n",
       "      <td>$signal</td>\n",
       "      <td>[signal=0EF58FC2-8D14-7160-9EE1-1EC3CA6EFB2C]</td>\n",
       "      <td>NaN</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>20</th>\n",
       "      <td>0EF5B5AB-24B7-EA90-B899-A37109462B1C</td>\n",
       "      <td>NaN</td>\n",
       "      <td>My CSV Tree &gt;&gt; Cooling Tower 2</td>\n",
       "      <td>Average Temperature of All Areas</td>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>3</td>\n",
       "      <td>NaN</td>\n",
       "      <td>average($p0, $p1)</td>\n",
       "      <td>[p0=0EF5B5AA-E12D-F9F0-8FE4-6DCA0FB341E5, p1=0...</td>\n",
       "      <td>Average</td>\n",
       "      <td>...</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0EF5B5AA-AFD0-EE70-91E5-375B6D291908</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...</td>\n",
       "      <td>Success</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>21 rows × 29 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                                      ID  \\\n",
       "0   0EF5B5AA-E307-6410-9271-3D4333038FBB   \n",
       "1   0EF5B5AA-E30E-F940-BD05-CA42A4BD4FD8   \n",
       "2   0EF5B5AA-E311-6050-AD69-554C2FB44C0B   \n",
       "3   0EF5B5AA-E72F-FB50-A975-225BD5462C77   \n",
       "4   0EF5B5AA-DE84-7780-9CF0-CA5956D31731   \n",
       "5   0EF5B5AA-DF16-FF40-9946-B49C349B8702   \n",
       "6   0EF5B5AA-E313-7760-B233-2B83515A65C7   \n",
       "7   0EF5B5AA-E7AE-EA90-87F4-A3CE0E4AC4E5   \n",
       "8   0EF5B5AA-DFB0-EC30-B590-6EA50D38D6FE   \n",
       "9   0EF5B5AA-E05B-EA90-B8FA-BADD579E9B67   \n",
       "10  0EF5B5AB-2478-62F0-96F5-AC05FDA7EB48   \n",
       "11  0EF5B5AA-E315-EE70-8552-04D354DD32B2   \n",
       "12  0EF5B5AA-E315-EE70-81F6-77F31DFC9881   \n",
       "13  0EF5B5AA-E826-64A0-9B03-3EF5DEFE914C   \n",
       "14  0EF5B5AA-E0D3-64A0-9A71-A082E94842D4   \n",
       "15  0EF5B5AA-E12D-F9F0-8FE4-6DCA0FB341E5   \n",
       "16  0EF5B5AA-E31A-EC90-B179-74D6CDBCC0F2   \n",
       "17  0EF5B5AA-E8AA-6200-9756-4365981B5FEE   \n",
       "18  0EF5B5AA-E1B6-7570-8256-731ED67AB9F2   \n",
       "19  0EF5B5AA-E243-FF10-A297-50D876D72C44   \n",
       "20  0EF5B5AB-24B7-EA90-B899-A37109462B1C   \n",
       "\n",
       "                           Referenced ID  \\\n",
       "0                                    NaN   \n",
       "1                                    NaN   \n",
       "2                                    NaN   \n",
       "3                                    NaN   \n",
       "4   0EF58FC2-83AA-66B0-8B9F-E021808A2620   \n",
       "5   0EF58FC2-8206-77F0-8519-ECD251B886A6   \n",
       "6                                    NaN   \n",
       "7                                    NaN   \n",
       "8   0EF58FC2-8348-EC30-874B-C093508CCDF8   \n",
       "9   0EF58FC2-82AC-E830-9324-CD3E38A9EB6E   \n",
       "10                                   NaN   \n",
       "11                                   NaN   \n",
       "12                                   NaN   \n",
       "13                                   NaN   \n",
       "14  0EF58FC2-8294-7190-BE8D-EBBDC689A86E   \n",
       "15  0EF58FC2-8B7C-75F0-99A3-B0D0420939F3   \n",
       "16                                   NaN   \n",
       "17                                   NaN   \n",
       "18  0EF58FC2-89B3-FD40-B547-C17F8D1C2503   \n",
       "19  0EF58FC2-8D14-7160-9EE1-1EC3CA6EFB2C   \n",
       "20                                   NaN   \n",
       "\n",
       "                                        Path  \\\n",
       "0                                              \n",
       "1                                My CSV Tree   \n",
       "2             My CSV Tree >> Cooling Tower 1   \n",
       "3   My CSV Tree >> Cooling Tower 1 >> Area A   \n",
       "4   My CSV Tree >> Cooling Tower 1 >> Area A   \n",
       "5   My CSV Tree >> Cooling Tower 1 >> Area A   \n",
       "6             My CSV Tree >> Cooling Tower 1   \n",
       "7   My CSV Tree >> Cooling Tower 1 >> Area B   \n",
       "8   My CSV Tree >> Cooling Tower 1 >> Area B   \n",
       "9   My CSV Tree >> Cooling Tower 1 >> Area B   \n",
       "10            My CSV Tree >> Cooling Tower 1   \n",
       "11                               My CSV Tree   \n",
       "12            My CSV Tree >> Cooling Tower 2   \n",
       "13  My CSV Tree >> Cooling Tower 2 >> Area D   \n",
       "14  My CSV Tree >> Cooling Tower 2 >> Area D   \n",
       "15  My CSV Tree >> Cooling Tower 2 >> Area D   \n",
       "16            My CSV Tree >> Cooling Tower 2   \n",
       "17  My CSV Tree >> Cooling Tower 2 >> Area E   \n",
       "18  My CSV Tree >> Cooling Tower 2 >> Area E   \n",
       "19  My CSV Tree >> Cooling Tower 2 >> Area E   \n",
       "20            My CSV Tree >> Cooling Tower 2   \n",
       "\n",
       "                                Name              Type  Depth  Description  \\\n",
       "0                        My CSV Tree             Asset      1          NaN   \n",
       "1                    Cooling Tower 1             Asset      2          NaN   \n",
       "2                             Area A             Asset      3          NaN   \n",
       "3                          Dew Point  CalculatedSignal      4          NaN   \n",
       "4                  Relative Humidity  CalculatedSignal      4          NaN   \n",
       "5                        Temperature  CalculatedSignal      4          NaN   \n",
       "6                             Area B             Asset      3          NaN   \n",
       "7                          Dew Point  CalculatedSignal      4          NaN   \n",
       "8                  Relative Humidity  CalculatedSignal      4          NaN   \n",
       "9                        Temperature  CalculatedSignal      4          NaN   \n",
       "10  Average Temperature of All Areas  CalculatedSignal      3          NaN   \n",
       "11                   Cooling Tower 2             Asset      2          NaN   \n",
       "12                            Area D             Asset      3          NaN   \n",
       "13                         Dew Point  CalculatedSignal      4          NaN   \n",
       "14                 Relative Humidity  CalculatedSignal      4          NaN   \n",
       "15                       Temperature  CalculatedSignal      4          NaN   \n",
       "16                            Area E             Asset      3          NaN   \n",
       "17                         Dew Point  CalculatedSignal      4          NaN   \n",
       "18                 Relative Humidity  CalculatedSignal      4          NaN   \n",
       "19                       Temperature  CalculatedSignal      4          NaN   \n",
       "20  Average Temperature of All Areas  CalculatedSignal      3          NaN   \n",
       "\n",
       "                              Formula  \\\n",
       "0                                 NaN   \n",
       "1                                 NaN   \n",
       "2                                 NaN   \n",
       "3   $t - ((100 - $rh.setUnits(\"\"))/5)   \n",
       "4                             $signal   \n",
       "5                             $signal   \n",
       "6                                 NaN   \n",
       "7   $t - ((100 - $rh.setUnits(\"\"))/5)   \n",
       "8                             $signal   \n",
       "9                             $signal   \n",
       "10                  average($p0, $p1)   \n",
       "11                                NaN   \n",
       "12                                NaN   \n",
       "13  $t - ((100 - $rh.setUnits(\"\"))/5)   \n",
       "14                            $signal   \n",
       "15                            $signal   \n",
       "16                                NaN   \n",
       "17  $t - ((100 - $rh.setUnits(\"\"))/5)   \n",
       "18                            $signal   \n",
       "19                            $signal   \n",
       "20                  average($p0, $p1)   \n",
       "\n",
       "                                   Formula Parameters Roll Up Statistic  ...  \\\n",
       "0                                                 NaN               NaN  ...   \n",
       "1                                                 NaN               NaN  ...   \n",
       "2                                                 NaN               NaN  ...   \n",
       "3   [rh=0EF5B5AA-DE84-7780-9CF0-CA5956D31731, t=0E...               NaN  ...   \n",
       "4       [signal=0EF58FC2-83AA-66B0-8B9F-E021808A2620]               NaN  ...   \n",
       "5       [signal=0EF58FC2-8206-77F0-8519-ECD251B886A6]               NaN  ...   \n",
       "6                                                 NaN               NaN  ...   \n",
       "7   [rh=0EF5B5AA-DFB0-EC30-B590-6EA50D38D6FE, t=0E...               NaN  ...   \n",
       "8       [signal=0EF58FC2-8348-EC30-874B-C093508CCDF8]               NaN  ...   \n",
       "9       [signal=0EF58FC2-82AC-E830-9324-CD3E38A9EB6E]               NaN  ...   \n",
       "10  [p0=0EF5B5AA-DF16-FF40-9946-B49C349B8702, p1=0...           Average  ...   \n",
       "11                                                NaN               NaN  ...   \n",
       "12                                                NaN               NaN  ...   \n",
       "13  [rh=0EF5B5AA-E0D3-64A0-9A71-A082E94842D4, t=0E...               NaN  ...   \n",
       "14      [signal=0EF58FC2-8294-7190-BE8D-EBBDC689A86E]               NaN  ...   \n",
       "15      [signal=0EF58FC2-8B7C-75F0-99A3-B0D0420939F3]               NaN  ...   \n",
       "16                                                NaN               NaN  ...   \n",
       "17  [rh=0EF5B5AA-E1B6-7570-8256-731ED67AB9F2, t=0E...               NaN  ...   \n",
       "18      [signal=0EF58FC2-89B3-FD40-B547-C17F8D1C2503]               NaN  ...   \n",
       "19      [signal=0EF58FC2-8D14-7160-9EE1-1EC3CA6EFB2C]               NaN  ...   \n",
       "20  [p0=0EF5B5AA-E12D-F9F0-8FE4-6DCA0FB341E5, p1=0...           Average  ...   \n",
       "\n",
       "   Period  Process Type  Thresholds  Template ID  \\\n",
       "0     NaN           NaN         NaN          NaN   \n",
       "1     NaN           NaN         NaN          NaN   \n",
       "2     NaN           NaN         NaN          NaN   \n",
       "3     NaN           NaN         NaN          NaN   \n",
       "4     NaN           NaN         NaN          NaN   \n",
       "5     NaN           NaN         NaN          NaN   \n",
       "6     NaN           NaN         NaN          NaN   \n",
       "7     NaN           NaN         NaN          NaN   \n",
       "8     NaN           NaN         NaN          NaN   \n",
       "9     NaN           NaN         NaN          NaN   \n",
       "10    NaN           NaN         NaN          NaN   \n",
       "11    NaN           NaN         NaN          NaN   \n",
       "12    NaN           NaN         NaN          NaN   \n",
       "13    NaN           NaN         NaN          NaN   \n",
       "14    NaN           NaN         NaN          NaN   \n",
       "15    NaN           NaN         NaN          NaN   \n",
       "16    NaN           NaN         NaN          NaN   \n",
       "17    NaN           NaN         NaN          NaN   \n",
       "18    NaN           NaN         NaN          NaN   \n",
       "19    NaN           NaN         NaN          NaN   \n",
       "20    NaN           NaN         NaN          NaN   \n",
       "\n",
       "                               Scoped To  Datasource Class  Datasource ID  \\\n",
       "0   0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "1   0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "2   0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "3   0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "4   0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "5   0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "6   0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "7   0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "8   0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "9   0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "10  0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "11  0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "12  0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "13  0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "14  0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "15  0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "16  0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "17  0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "18  0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "19  0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "20  0EF5B5AA-AFD0-EE70-91E5-375B6D291908     Seeq Data Lab  Seeq Data Lab   \n",
       "\n",
       "                                              Data ID  Push Result  \\\n",
       "0   [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...      Success   \n",
       "1   [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...      Success   \n",
       "2   [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...      Success   \n",
       "3   [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "4   [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "5   [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "6   [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...      Success   \n",
       "7   [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "8   [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "9   [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "10  [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "11  [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...      Success   \n",
       "12  [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...      Success   \n",
       "13  [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "14  [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "15  [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "16  [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Asset}...      Success   \n",
       "17  [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "18  [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "19  [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "20  [0EF5B5AA-AFD0-EE70-91E5-375B6D291908] {Signal...      Success   \n",
       "\n",
       "    Cache Enabled  \n",
       "0             NaN  \n",
       "1             NaN  \n",
       "2             NaN  \n",
       "3             NaN  \n",
       "4           False  \n",
       "5           False  \n",
       "6             NaN  \n",
       "7             NaN  \n",
       "8           False  \n",
       "9           False  \n",
       "10            NaN  \n",
       "11            NaN  \n",
       "12            NaN  \n",
       "13            NaN  \n",
       "14          False  \n",
       "15          False  \n",
       "16            NaN  \n",
       "17            NaN  \n",
       "18          False  \n",
       "19          False  \n",
       "20            NaN  \n",
       "\n",
       "[21 rows x 29 columns]"
      ]
     },
     "execution_count": 26,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "my_csv_tree.push(metadata_state_file='Output/asset_tree_tutorial_metadata_state_file.pickle.zip')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "810b7953",
   "metadata": {},
   "source": [
    "The second time you execute the cell above, you'll notice that the `Push Result` column includes `Success: Unchanged`,\n",
    "which means SPy didn't bother sending anything to the Seeq Server since nothing had changed."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "intimate-measure",
   "metadata": {},
   "source": [
    "### The `spy.assets` Submodule and Asset Tree Templates\n",
    "\n",
    "Read on to the [next tutorial notebook on asset trees in SPy](Asset%20Trees%202%20-%20Templates.ipynb) to learn how to use the `spy.assets` submodule to build asset trees out of templates."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4d699275",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "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.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
