{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "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,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Logged in to <strong>http://localhost:34216</strong> as <strong>agent_api_key</strong>.<br>Seeq Server Version: <strong>R66.0.0-SNAPSHOT</strong><br>Seeq SDK Module Version: <strong>66.0.0</strong> @ C:\\git\\crab\\sdk\\pypi\\seeq\\sdk<br>Seeq SPy Module Version: <strong>193.0</strong> @ C:\\git\\crab\\sdk\\pypi\\seeq\\spy</div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Log into Seeq Server if you're not using Seeq Data Lab:\n",
    "spy.login(url='http://localhost:34216', credentials_file='../credentials.key', force=False)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# spy.pull\n",
    "\n",
    "Retrieves data for the specified items over a given time range.\n",
    "\n",
    "Once you have searched for signals, conditions or scalars and have a DataFrame with an `ID` column, you can execute `spy.pull` to retrieve data for those items.\n",
    "\n",
    "Alternatively, you can execute `spy.pull('worksheet_url')` if you want to pull all the items loaded in an Analysis \n",
    "worksheet by supplying the URL of the Seeq worksheet. You can copy the value of worksheet_url directly out of your \n",
    "browser's address bar without further modification."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Time interval\n",
    "\n",
    "You must specify `start` and `end`, which can be any data type or format that is recognized by the Pandas function `pandas.to_datetime()`.\n",
    "\n",
    "Let's create a DataFrame of signals to retrieve data for:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "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;\">Path</td><td style=\"background-color: #EEFFEE; text-align: left;\">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;\">Example >> Cooling Tower 1 >> Area A</td><td style=\"text-align: left; vertical-align: top;\">Compressor</td><td style=\"vertical-align: top;\">00:00:00.07</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: 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>Path</th>\n",
       "      <th>Asset</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-8762-F910-A3F7-157C1D6689FB</td>\n",
       "      <td>Example &gt;&gt; Cooling Tower 1</td>\n",
       "      <td>Area A</td>\n",
       "      <td>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-8CFB-EAC0-A6FA-3B586A7AEA13</td>\n",
       "      <td>Example &gt;&gt; Cooling Tower 1</td>\n",
       "      <td>Area A</td>\n",
       "      <td>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",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                     ID                        Path   Asset  \\\n",
       "0  0EF58FC2-8762-F910-A3F7-157C1D6689FB  Example >> Cooling Tower 1  Area A   \n",
       "1  0EF58FC2-8CFB-EAC0-A6FA-3B586A7AEA13  Example >> Cooling Tower 1  Area A   \n",
       "\n",
       "               Name  Description          Type Value Unit Of Measure  \\\n",
       "0  Compressor Power          NaN  StoredSignal                    kW   \n",
       "1  Compressor Stage          NaN  StoredSignal                string   \n",
       "\n",
       "  Datasource Name  Archived  \n",
       "0    Example Data     False  \n",
       "1    Example Data     False  "
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "items = spy.search({\n",
    "    'Path': 'Example >> Cooling Tower 1 >> Area A',\n",
    "    'Name': 'Compressor'\n",
    "})\n",
    "\n",
    "items"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we will retrieve that data for a specified time interval:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Pull successful from <strong>2019-01-01 00:00:00+00:00</strong> to <strong>2019-01-07 00:00:00+00:00</strong></div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: left;\">ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">Path</td><td style=\"background-color: #EEFFEE; text-align: left;\">Asset</td><td style=\"background-color: #EEFFEE; text-align: left;\">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;\">Data Processed</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;\">0EF58FC2-8762-F910-A3F7-157C1D6689FB</td><td style=\"text-align: left; vertical-align: top;\">StoredSignal</td><td style=\"text-align: left; vertical-align: top;\">Example >> Cooling Tower 1</td><td style=\"text-align: left; vertical-align: top;\">Area A</td><td style=\"text-align: left; vertical-align: top;\">Compressor Power</td><td style=\"vertical-align: top;\">00:00:00.09</td><td style=\"text-align: right; vertical-align: top;\">577</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">69 KB</td><td style=\"text-align: left; vertical-align: top;\">Success</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">1</td><td style=\"text-align: left; vertical-align: top;\">0EF58FC2-8CFB-EAC0-A6FA-3B586A7AEA13</td><td style=\"text-align: left; vertical-align: top;\">StoredSignal</td><td style=\"text-align: left; vertical-align: top;\">Example >> Cooling Tower 1</td><td style=\"text-align: left; vertical-align: top;\">Area A</td><td style=\"text-align: left; vertical-align: top;\">Compressor Stage</td><td style=\"vertical-align: top;\">00:00:00.13</td><td style=\"text-align: right; vertical-align: top;\">577</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">69 KB</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>Example &gt;&gt; Cooling Tower 1 &gt;&gt; Area A &gt;&gt; Compressor Power</th>\n",
       "      <th>Example &gt;&gt; Cooling Tower 1 &gt;&gt; Area A &gt;&gt; Compressor Stage</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2019-01-01 00:00:00+00:00</th>\n",
       "      <td>39.189300</td>\n",
       "      <td>STAGE 2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 00:15:00+00:00</th>\n",
       "      <td>39.842881</td>\n",
       "      <td>STAGE 2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 00:30:00+00:00</th>\n",
       "      <td>39.949065</td>\n",
       "      <td>STAGE 2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 00:45:00+00:00</th>\n",
       "      <td>39.424393</td>\n",
       "      <td>STAGE 2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 01:00:00+00:00</th>\n",
       "      <td>39.326496</td>\n",
       "      <td>STAGE 2</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-06 23:00:00+00:00</th>\n",
       "      <td>16.848487</td>\n",
       "      <td>STAGE 1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-06 23:15:00+00:00</th>\n",
       "      <td>16.870912</td>\n",
       "      <td>STAGE 1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-06 23:30:00+00:00</th>\n",
       "      <td>16.829447</td>\n",
       "      <td>STAGE 1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-06 23:45:00+00:00</th>\n",
       "      <td>17.096314</td>\n",
       "      <td>STAGE 1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-07 00:00:00+00:00</th>\n",
       "      <td>16.864826</td>\n",
       "      <td>STAGE 1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>577 rows × 2 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                           Example >> Cooling Tower 1 >> Area A >> Compressor Power  \\\n",
       "2019-01-01 00:00:00+00:00                                          39.189300          \n",
       "2019-01-01 00:15:00+00:00                                          39.842881          \n",
       "2019-01-01 00:30:00+00:00                                          39.949065          \n",
       "2019-01-01 00:45:00+00:00                                          39.424393          \n",
       "2019-01-01 01:00:00+00:00                                          39.326496          \n",
       "...                                                                      ...          \n",
       "2019-01-06 23:00:00+00:00                                          16.848487          \n",
       "2019-01-06 23:15:00+00:00                                          16.870912          \n",
       "2019-01-06 23:30:00+00:00                                          16.829447          \n",
       "2019-01-06 23:45:00+00:00                                          17.096314          \n",
       "2019-01-07 00:00:00+00:00                                          16.864826          \n",
       "\n",
       "                          Example >> Cooling Tower 1 >> Area A >> Compressor Stage  \n",
       "2019-01-01 00:00:00+00:00                                            STAGE 2        \n",
       "2019-01-01 00:15:00+00:00                                            STAGE 2        \n",
       "2019-01-01 00:30:00+00:00                                            STAGE 2        \n",
       "2019-01-01 00:45:00+00:00                                            STAGE 2        \n",
       "2019-01-01 01:00:00+00:00                                            STAGE 2        \n",
       "...                                                                      ...        \n",
       "2019-01-06 23:00:00+00:00                                            STAGE 1        \n",
       "2019-01-06 23:15:00+00:00                                            STAGE 1        \n",
       "2019-01-06 23:30:00+00:00                                            STAGE 1        \n",
       "2019-01-06 23:45:00+00:00                                            STAGE 1        \n",
       "2019-01-07 00:00:00+00:00                                            STAGE 1        \n",
       "\n",
       "[577 rows x 2 columns]"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "spy.pull(items, start='2019-01-01', end='2019-01-07')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The index of the returned DataFrame is `pd.Timestamp` objects with the timezone that is set for the workstation or server that is running Jupyter. Each signal is in a separate column.\n",
    "\n",
    "Alternatively, you can request a specific timezone for both the input and output (and they can be different):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Pull successful from <strong>2019-01-01 00:00:00-08:00</strong> to <strong>2019-01-07 00:00:00-08:00</strong></div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: left;\">ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">Path</td><td style=\"background-color: #EEFFEE; text-align: left;\">Asset</td><td style=\"background-color: #EEFFEE; text-align: left;\">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;\">Data Processed</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;\">0EF58FC2-8762-F910-A3F7-157C1D6689FB</td><td style=\"text-align: left; vertical-align: top;\">StoredSignal</td><td style=\"text-align: left; vertical-align: top;\">Example >> Cooling Tower 1</td><td style=\"text-align: left; vertical-align: top;\">Area A</td><td style=\"text-align: left; vertical-align: top;\">Compressor Power</td><td style=\"vertical-align: top;\">00:00:00.05</td><td style=\"text-align: right; vertical-align: top;\">577</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">12 KB</td><td style=\"text-align: left; vertical-align: top;\">Success</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">1</td><td style=\"text-align: left; vertical-align: top;\">0EF58FC2-8CFB-EAC0-A6FA-3B586A7AEA13</td><td style=\"text-align: left; vertical-align: top;\">StoredSignal</td><td style=\"text-align: left; vertical-align: top;\">Example >> Cooling Tower 1</td><td style=\"text-align: left; vertical-align: top;\">Area A</td><td style=\"text-align: left; vertical-align: top;\">Compressor Stage</td><td style=\"vertical-align: top;\">00:00:00.05</td><td style=\"text-align: right; vertical-align: top;\">577</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">12 KB</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>Example &gt;&gt; Cooling Tower 1 &gt;&gt; Area A &gt;&gt; Compressor Power</th>\n",
       "      <th>Example &gt;&gt; Cooling Tower 1 &gt;&gt; Area A &gt;&gt; Compressor Stage</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2019-01-01 03:00:00-05:00</th>\n",
       "      <td>0.002923</td>\n",
       "      <td>OFF</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 03:15:00-05:00</th>\n",
       "      <td>0.002923</td>\n",
       "      <td>OFF</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 03:30:00-05:00</th>\n",
       "      <td>0.002923</td>\n",
       "      <td>OFF</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 03:45:00-05:00</th>\n",
       "      <td>0.002924</td>\n",
       "      <td>OFF</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 04:00:00-05:00</th>\n",
       "      <td>0.002923</td>\n",
       "      <td>OFF</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-07 02:00:00-05:00</th>\n",
       "      <td>0.002923</td>\n",
       "      <td>OFF</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-07 02:15:00-05:00</th>\n",
       "      <td>0.002923</td>\n",
       "      <td>OFF</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-07 02:30:00-05:00</th>\n",
       "      <td>0.002923</td>\n",
       "      <td>OFF</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-07 02:45:00-05:00</th>\n",
       "      <td>0.002923</td>\n",
       "      <td>OFF</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-07 03:00:00-05:00</th>\n",
       "      <td>0.002923</td>\n",
       "      <td>OFF</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>577 rows × 2 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                           Example >> Cooling Tower 1 >> Area A >> Compressor Power  \\\n",
       "2019-01-01 03:00:00-05:00                                           0.002923          \n",
       "2019-01-01 03:15:00-05:00                                           0.002923          \n",
       "2019-01-01 03:30:00-05:00                                           0.002923          \n",
       "2019-01-01 03:45:00-05:00                                           0.002924          \n",
       "2019-01-01 04:00:00-05:00                                           0.002923          \n",
       "...                                                                      ...          \n",
       "2019-01-07 02:00:00-05:00                                           0.002923          \n",
       "2019-01-07 02:15:00-05:00                                           0.002923          \n",
       "2019-01-07 02:30:00-05:00                                           0.002923          \n",
       "2019-01-07 02:45:00-05:00                                           0.002923          \n",
       "2019-01-07 03:00:00-05:00                                           0.002923          \n",
       "\n",
       "                          Example >> Cooling Tower 1 >> Area A >> Compressor Stage  \n",
       "2019-01-01 03:00:00-05:00                                                OFF        \n",
       "2019-01-01 03:15:00-05:00                                                OFF        \n",
       "2019-01-01 03:30:00-05:00                                                OFF        \n",
       "2019-01-01 03:45:00-05:00                                                OFF        \n",
       "2019-01-01 04:00:00-05:00                                                OFF        \n",
       "...                                                                      ...        \n",
       "2019-01-07 02:00:00-05:00                                                OFF        \n",
       "2019-01-07 02:15:00-05:00                                                OFF        \n",
       "2019-01-07 02:30:00-05:00                                                OFF        \n",
       "2019-01-07 02:45:00-05:00                                                OFF        \n",
       "2019-01-07 03:00:00-05:00                                                OFF        \n",
       "\n",
       "[577 rows x 2 columns]"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "spy.pull(items,\n",
    "         start=pd.Timestamp('2019-01-01', tz='US/Pacific'),\n",
    "         end=pd.Timestamp('2019-01-07', tz='US/Pacific'),\n",
    "         tz_convert='US/Eastern')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you are pulling items from an Analysis worksheet URL, `start` and `end` are selected  by default from the start \n",
    "and end of the Display Range in the Trend view of the worksheet. \n",
    "\n",
    "`worksheet_url = 'http://localhost:34216/workbook/<workbookID>/worksheet/<worksheetID>'`\n",
    "\n",
    "`spy.pull(url)`\n",
    "\n",
    "However, you can always specify a different `start` or `end` when executing `spy.pull` \n",
    "\n",
    "`spy.pull(worksheet_url, start='2019-01-01', end='2019-01-07')`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Gridding\n",
    "\n",
    "By default, SPy Pull will interpolate data onto a _grid_ at 15 minute intervals. This is often desirable for computation within matrices, and Seeq goes to great lengths to ensure that interpolation is done correctly.\n",
    "\n",
    "You can change spacing by specifying a `grid` parameter with units of `s`, `min`, `h` or `d`. For example, `grid='1h'` will cause samples to be spaced every hour. For dense data, specifying a larger grid interval can significantly reduce the amount of data transferred to Python, which can reduce time taken to pull data.\n",
    "\n",
    "You can also specify a time zone for alignment: `grid=\"12h, 'Canada/Pacific'\"`. To align samples to an offset, include\n",
    "both a timezone and a date or timestamp formatted as YYYY-MM-DD,\n",
    "YYYY-MM-DDTHH:MM:SS, or ISO8601. For example, to align samples every day at every 7:17 AM\n",
    "and 7:17 PM in Vancouver, even across daylight savings time changes: `grid=\"12h,'Canada/Pacific','2020-06-01T07:17:00'\"`.\n",
    "\n",
    "Alternatively, specifying `grid='auto'` will automatically estimate a grid value. The grid can be determined in either of two ways:\n",
    "\n",
    "1. If the column `Estimated Sample Period` exists in the query DataFrame, the grid value will be the median of the \n",
    "sample periods in the query DataFrame. Note that in this case the sample period is determined for the specified time \n",
    "period issued by `spy.search(estimate_sample_period=dict(Start='<sampling_start_time>', \n",
    "End='<sampling_end_time>'))`.\n",
    "2. If the column `Estimated Sample Period` does not exist in the query DataFrame, the grid will be determined by running the `estimateSamplePeriod()` Formula function on each signal in the query DataFrame for the specified time period with the `start` and `end` parameters and then taking the median of all the sample periods. It is highly recommended to estimate the sample period using `spy.search` first and to validate the estimates since the time taken to pull data can significantly increase for dense data and queries with a large number of signals. \n",
    "\n",
    "All signals in Seeq honor their `Maximum Interpolation` property. If the gap between two adjacent samples is larger than `Maximum Interpolation`, then no interpolation is performed and you may see `NaN` entries in the DataFrame, which indicates that there is no appropriate value for that cell. This concept of `Maximum Interpolation` has both a functional purpose and performance implications. It can prevent a process variable like a temperature reading from \"flatlining\" inappropriately if no data is collected for a period of time. It is also constrains the amount of data that must be retrieved from a source system in order to interpolate correctly to the edges of a request interval.\n",
    "\n",
    "Specifying `grid=None` retrieves the data with _raw_ timestamps and no interpolation. On rows where signals don't happen to all have values at a particular timestamp, you will see `NaN` entries.\n",
    "\n",
    "**NaN vs None**: `spy.pull()` uses `NaN` to represent a _missing value_, consistent with Pandas idioms. `None`, on other hand, represents an _invalid_ value, which in Seeq Workbench will break interpolation if one or more invalid samples are located between two valid samples."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Column headers\n",
    "\n",
    "By default, column headers will contain the full path to the item (if it's part of an asset tree) or just the name of the item (if it's not in an asset tree).\n",
    "\n",
    "You can force the column headers to be populated with a particular property using the `header` argument. In this example, the column header will use just the `Name` property:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Pull successful from <strong>2019-01-01 12:00:00+00:00</strong> to <strong>2019-01-01 13:00:00+00:00</strong></div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: left;\">ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">Path</td><td style=\"background-color: #EEFFEE; text-align: left;\">Asset</td><td style=\"background-color: #EEFFEE; text-align: left;\">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;\">Data Processed</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;\">0EF58FC2-8762-F910-A3F7-157C1D6689FB</td><td style=\"text-align: left; vertical-align: top;\">StoredSignal</td><td style=\"text-align: left; vertical-align: top;\">Example >> Cooling Tower 1</td><td style=\"text-align: left; vertical-align: top;\">Area A</td><td style=\"text-align: left; vertical-align: top;\">Compressor Power</td><td style=\"vertical-align: top;\">00:00:00.01</td><td style=\"text-align: right; vertical-align: top;\">5</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">80 B</td><td style=\"text-align: left; vertical-align: top;\">Success</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">1</td><td style=\"text-align: left; vertical-align: top;\">0EF58FC2-8CFB-EAC0-A6FA-3B586A7AEA13</td><td style=\"text-align: left; vertical-align: top;\">StoredSignal</td><td style=\"text-align: left; vertical-align: top;\">Example >> Cooling Tower 1</td><td style=\"text-align: left; vertical-align: top;\">Area A</td><td style=\"text-align: left; vertical-align: top;\">Compressor Stage</td><td style=\"vertical-align: top;\">00:00:00.02</td><td style=\"text-align: right; vertical-align: top;\">5</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">80 B</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>Compressor Power</th>\n",
       "      <th>Compressor Stage</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2019-01-01 12:00:00+00:00</th>\n",
       "      <td>0.002923</td>\n",
       "      <td>OFF</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 12:15:00+00:00</th>\n",
       "      <td>0.002971</td>\n",
       "      <td>OFF</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 12:30:00+00:00</th>\n",
       "      <td>0.002923</td>\n",
       "      <td>OFF</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 12:45:00+00:00</th>\n",
       "      <td>0.002923</td>\n",
       "      <td>OFF</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 13:00:00+00:00</th>\n",
       "      <td>0.002923</td>\n",
       "      <td>OFF</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                           Compressor Power Compressor Stage\n",
       "2019-01-01 12:00:00+00:00          0.002923              OFF\n",
       "2019-01-01 12:15:00+00:00          0.002971              OFF\n",
       "2019-01-01 12:30:00+00:00          0.002923              OFF\n",
       "2019-01-01 12:45:00+00:00          0.002923              OFF\n",
       "2019-01-01 13:00:00+00:00          0.002923              OFF"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "spy.pull(items, start='2019-01-01T12:00:00', end='2019-01-01T13:00:00', header='Name')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Alternatively, you can supply a `Header` column in the `items` DataFrame whose values indicate the column headers you would like to be used for each item that is pulled."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Applying a Seeq Formula\n",
    "\n",
    "You can leverage Seeq's time series calculation engine easily by adding a `calculation` argument to `spy.pull()`. For example, let's say we want calculate an hourly average and represent it as a step-interpolated signal. You can figure out what to put as the `calculation` argument by experimenting in Seeq Workbench and going to the _Item Properties_ pane to look at the formula for a particular calculated item in Seeq. Then you copy and paste that _Formula_ property into your notebook, taking care to use either `$signal`, `$condition` or `$scalar` (as appropriate) for the variable name.\n",
    "\n",
    "Now when we fetch the data, it will have the formula applied to the output:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Pull successful from <strong>2019-01-01 00:00:00+00:00</strong> to <strong>2019-01-01 03:00:00+00:00</strong></div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: left;\">ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">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;\">Data Processed</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;\">0EF58FC2-8206-77F0-8519-ECD251B886A6</td><td style=\"text-align: left; vertical-align: top;\">StoredSignal</td><td style=\"text-align: left; vertical-align: top;\">Area A_Temperature</td><td style=\"vertical-align: top;\">00:00:00.13</td><td style=\"text-align: right; vertical-align: top;\">4</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">4 KB</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>Area A_Temperature</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2019-01-01 00:00:00+00:00</th>\n",
       "      <td>95.605355</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 01:00:00+00:00</th>\n",
       "      <td>96.929129</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 02:00:00+00:00</th>\n",
       "      <td>97.176269</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 03:00:00+00:00</th>\n",
       "      <td>96.347881</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                           Area A_Temperature\n",
       "2019-01-01 00:00:00+00:00           95.605355\n",
       "2019-01-01 01:00:00+00:00           96.929129\n",
       "2019-01-01 02:00:00+00:00           97.176269\n",
       "2019-01-01 03:00:00+00:00           96.347881"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "signal_with_calc = spy.search({'Name': 'Area A_Temperature', 'Datasource Name': 'Example Data'})\n",
    "\n",
    "spy.pull(signal_with_calc,\n",
    "         start='2019-01-01T00:00:00',\n",
    "         end='2019-01-01T03:00:00',\n",
    "         calculation='$signal.aggregate(average(), hours(), startKey())',\n",
    "         grid=None)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Alternatively, you can supply a `Calculation` column in the `items` DataFrame and specify the formula for each item independently. Here we specify both a `Calculation` and a `Header` column to retrieve the same signal with different formulas:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Pull successful from <strong>2019-01-01 00:00:00+00:00</strong> to <strong>2019-01-01 05:00:00+00:00</strong></div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: left;\">ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">Path</td><td style=\"background-color: #EEFFEE; text-align: left;\">Asset</td><td style=\"background-color: #EEFFEE; text-align: left;\">Name</td><td style=\"background-color: #EEFFEE; text-align: left;\">Header</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;\">Data Processed</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;\">0EF58FC2-7E6E-7160-ACE8-E1D5408B23E1</td><td style=\"text-align: left; vertical-align: top;\">CalculatedSignal</td><td style=\"text-align: left; vertical-align: top;\">Example >> Cooling Tower 1</td><td style=\"text-align: left; vertical-align: top;\">Area A</td><td style=\"text-align: left; vertical-align: top;\">Relative Humidity</td><td style=\"text-align: left; vertical-align: top;\">1-hour Average</td><td style=\"vertical-align: top;\">00:00:00.06</td><td style=\"text-align: right; vertical-align: top;\">6</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">5 KB</td><td style=\"text-align: left; vertical-align: top;\">Success</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">1</td><td style=\"text-align: left; vertical-align: top;\">0EF58FC2-7E6E-7160-ACE8-E1D5408B23E1</td><td style=\"text-align: left; vertical-align: top;\">CalculatedSignal</td><td style=\"text-align: left; vertical-align: top;\">Example >> Cooling Tower 1</td><td style=\"text-align: left; vertical-align: top;\">Area A</td><td style=\"text-align: left; vertical-align: top;\">Relative Humidity</td><td style=\"text-align: left; vertical-align: top;\">2-hour Average</td><td style=\"vertical-align: top;\">00:00:00.08</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;\">6 KB</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>1-hour Average</th>\n",
       "      <th>2-hour Average</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2019-01-01 00:00:00+00:00</th>\n",
       "      <td>40.243403</td>\n",
       "      <td>38.644717</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 01:00:00+00:00</th>\n",
       "      <td>37.046031</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 02:00:00+00:00</th>\n",
       "      <td>34.629467</td>\n",
       "      <td>34.165053</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 03:00:00+00:00</th>\n",
       "      <td>33.700638</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 04:00:00+00:00</th>\n",
       "      <td>33.695556</td>\n",
       "      <td>34.327242</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 05:00:00+00:00</th>\n",
       "      <td>34.958928</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                           1-hour Average  2-hour Average\n",
       "2019-01-01 00:00:00+00:00       40.243403       38.644717\n",
       "2019-01-01 01:00:00+00:00       37.046031             NaN\n",
       "2019-01-01 02:00:00+00:00       34.629467       34.165053\n",
       "2019-01-01 03:00:00+00:00       33.700638             NaN\n",
       "2019-01-01 04:00:00+00:00       33.695556       34.327242\n",
       "2019-01-01 05:00:00+00:00       34.958928             NaN"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "area_a_rel_humidity = spy.search({\n",
    "    'Path': 'Example >> Cooling Tower 1',\n",
    "    'Asset': 'Area A',\n",
    "    'Name': 'Relative Humidity',\n",
    "    'Datasource Name': 'Example Data'\n",
    "})\n",
    "two_calcs = pd.concat([area_a_rel_humidity, area_a_rel_humidity]).reset_index()\n",
    "two_calcs['Calculation'] = pd.Series([\n",
    "    '$signal.aggregate(average(), hours(), startKey())',\n",
    "    '$signal.aggregate(average(), periods(2h), startKey())'\n",
    "])\n",
    "two_calcs['Header'] = pd.Series([\n",
    "    '1-hour Average',\n",
    "    '2-hour Average'\n",
    "])\n",
    "\n",
    "spy.pull(two_calcs, start='2019-01-01T00:00:00', end='2019-01-01T05:00:00', grid=None)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Applying a Seeq Formula Across Assets\n",
    "\n",
    "If you have an asset tree (say, from OSIsoft Asset Framework), you can apply a calculation across assets as long as those assets have the necessary attributes (signals, conditions or scalars) with identical names.\n",
    "\n",
    "To get started, it's easiest to create the calculation in Seeq Workbench using a single asset first. You can \"swap\" to other assets by finding an asset in the Data tab and clicking the \"swap\" button. In this example, we're going to use spy.push() to create a calculated signal for use later."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "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>0EF5BF13-0348-F910-81FC-319F8D739929</strong><br>Click the following link to see what you pushed in Seeq:<br><a href=\"http://localhost:34216/0EF5BE2D-2738-FFA0-81E0-D2B058859C4D/workbook/0EF5BF13-0348-F910-81FC-319F8D739929/worksheet/0EF5BF13-0385-F9A0-AF11-E92255C4E645\" target=\"_blank\">http://localhost:34216/0EF5BE2D-2738-FFA0-81E0-D2B058859C4D/workbook/0EF5BF13-0348-F910-81FC-319F8D739929/worksheet/0EF5BF13-0385-F9A0-AF11-E92255C4E645</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>Type</th>\n",
       "      <th>Name</th>\n",
       "      <th>Formula</th>\n",
       "      <th>Formula Parameters</th>\n",
       "      <th>Scoped To</th>\n",
       "      <th>Datasource Class</th>\n",
       "      <th>Datasource ID</th>\n",
       "      <th>Data ID</th>\n",
       "      <th>ID</th>\n",
       "      <th>Push Result</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>CalculatedSignal</td>\n",
       "      <td>Dew Point</td>\n",
       "      <td>$T - ((100 - $RH.setUnits(''))/5)</td>\n",
       "      <td>[RH=0EF58FC2-7E6E-7160-ACE8-E1D5408B23E1, T=0E...</td>\n",
       "      <td>0EF5BF13-0348-F910-81FC-319F8D739929</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5BF13-0348-F910-81FC-319F8D739929] {Signal...</td>\n",
       "      <td>0EF5BF13-06B9-EEA0-ABBB-0A9F1F9D60FB</td>\n",
       "      <td>Success</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "               Type       Name                            Formula  \\\n",
       "0  CalculatedSignal  Dew Point  $T - ((100 - $RH.setUnits(''))/5)   \n",
       "\n",
       "                                  Formula Parameters  \\\n",
       "0  [RH=0EF58FC2-7E6E-7160-ACE8-E1D5408B23E1, T=0E...   \n",
       "\n",
       "                              Scoped To Datasource Class  Datasource ID  \\\n",
       "0  0EF5BF13-0348-F910-81FC-319F8D739929    Seeq Data Lab  Seeq Data Lab   \n",
       "\n",
       "                                             Data ID  \\\n",
       "0  [0EF5BF13-0348-F910-81FC-319F8D739929] {Signal...   \n",
       "\n",
       "                                     ID Push Result  \n",
       "0  0EF5BF13-06B9-EEA0-ABBB-0A9F1F9D60FB     Success  "
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "area_a_signals = spy.search({\n",
    "    'Path': 'Example >> Cooling Tower 1 >> Area A'\n",
    "})\n",
    "\n",
    "dew_point_calc = spy.push(metadata=pd.DataFrame([{\n",
    "    'Type': 'Signal',\n",
    "    'Name': 'Dew Point',\n",
    "    # From https://iridl.ldeo.columbia.edu/dochelp/QA/Basic/dewpoint.html\n",
    "    'Formula': \"$T - ((100 - $RH.setUnits(''))/5)\",\n",
    "    'Formula Parameters': {\n",
    "        '$T': area_a_signals[area_a_signals['Name'] == 'Temperature'],\n",
    "        '$RH': area_a_signals[area_a_signals['Name'] == 'Relative Humidity']\n",
    "    }\n",
    "}]), workbook='SPy Documentation Examples >> spy.pull')\n",
    "\n",
    "dew_point_calc"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now you can search for all the assets you want to apply this calculation to, and use the `calculation` argument in `spy.pull()` to retrieve data for the various assets."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Pull successful from <strong>2024-08-16 16:01:33.403858+00:00</strong> to <strong>2024-08-16 17:01:33.403858+00:00</strong></div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: left;\">ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">Path</td><td style=\"background-color: #EEFFEE; text-align: left;\">Asset</td><td style=\"background-color: #EEFFEE; text-align: left;\">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;\">Data Processed</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;\">0EF58FC2-90AC-77F0-85F2-91128B10372A</td><td style=\"text-align: left; vertical-align: top;\">CalculatedSignal</td><td style=\"text-align: left; vertical-align: top;\">Example</td><td style=\"text-align: left; vertical-align: top;\">Cooling Tower 1</td><td style=\"text-align: left; vertical-align: top;\">Area A</td><td style=\"vertical-align: top;\">00:00:00.52</td><td style=\"text-align: right; vertical-align: top;\">4</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">992 B</td><td style=\"text-align: left; vertical-align: top;\">Success</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">1</td><td style=\"text-align: left; vertical-align: top;\">0EF58FC2-90AA-60E0-94F7-29D4E89DC2F9</td><td style=\"text-align: left; vertical-align: top;\">CalculatedSignal</td><td style=\"text-align: left; vertical-align: top;\">Example</td><td style=\"text-align: left; vertical-align: top;\">Cooling Tower 1</td><td style=\"text-align: left; vertical-align: top;\">Area B</td><td style=\"vertical-align: top;\">00:00:00.52</td><td style=\"text-align: right; vertical-align: top;\">4</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">992 B</td><td style=\"text-align: left; vertical-align: top;\">Success</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">2</td><td style=\"text-align: left; vertical-align: top;\">0EF58FC2-90AA-60E0-846C-0711E3BCB468</td><td style=\"text-align: left; vertical-align: top;\">CalculatedSignal</td><td style=\"text-align: left; vertical-align: top;\">Example</td><td style=\"text-align: left; vertical-align: top;\">Cooling Tower 1</td><td style=\"text-align: left; vertical-align: top;\">Area C</td><td style=\"vertical-align: top;\">00:00:00.51</td><td style=\"text-align: right; vertical-align: top;\">4</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">992 B</td><td style=\"text-align: left; vertical-align: top;\">Success</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">3</td><td style=\"text-align: left; vertical-align: top;\">0EF58FC2-90AC-77F0-ADA9-570BE8320694</td><td style=\"text-align: left; vertical-align: top;\">CalculatedSignal</td><td style=\"text-align: left; vertical-align: top;\">Example</td><td style=\"text-align: left; vertical-align: top;\">Cooling Tower 1</td><td style=\"text-align: left; vertical-align: top;\">Area G</td><td style=\"vertical-align: top;\">00:00:00.52</td><td style=\"text-align: right; vertical-align: top;\">4</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">992 B</td><td style=\"text-align: left; vertical-align: top;\">Success</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">4</td><td style=\"text-align: left; vertical-align: top;\">0EF58FC2-90AA-60E0-914C-BA4C89AD8CDB</td><td style=\"text-align: left; vertical-align: top;\">CalculatedSignal</td><td style=\"text-align: left; vertical-align: top;\">Example</td><td style=\"text-align: left; vertical-align: top;\">Cooling Tower 1</td><td style=\"text-align: left; vertical-align: top;\">Area H</td><td style=\"vertical-align: top;\">00:00:00.51</td><td style=\"text-align: right; vertical-align: top;\">4</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">992 B</td><td style=\"text-align: left; vertical-align: top;\">Success</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">5</td><td style=\"text-align: left; vertical-align: top;\">0EF58FC2-90AA-60E0-AC5F-539EFD1C4108</td><td style=\"text-align: left; vertical-align: top;\">CalculatedSignal</td><td style=\"text-align: left; vertical-align: top;\">Example</td><td style=\"text-align: left; vertical-align: top;\">Cooling Tower 1</td><td style=\"text-align: left; vertical-align: top;\">Area I</td><td style=\"vertical-align: top;\">00:00:00.50</td><td style=\"text-align: right; vertical-align: top;\">4</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">992 B</td><td style=\"text-align: left; vertical-align: top;\">Success</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">6</td><td style=\"text-align: left; vertical-align: top;\">0EF58FC2-90A7-F9D0-A519-4BB719820A3F</td><td style=\"text-align: left; vertical-align: top;\">CalculatedSignal</td><td style=\"text-align: left; vertical-align: top;\">Example</td><td style=\"text-align: left; vertical-align: top;\">Cooling Tower 1</td><td style=\"text-align: left; vertical-align: top;\">Area J</td><td style=\"vertical-align: top;\">00:00:00.51</td><td style=\"text-align: right; vertical-align: top;\">4</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">992 B</td><td style=\"text-align: left; vertical-align: top;\">Success</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">7</td><td style=\"text-align: left; vertical-align: top;\">0EF58FC2-90A7-F9D0-90F1-BA89D4852085</td><td style=\"text-align: left; vertical-align: top;\">CalculatedSignal</td><td style=\"text-align: left; vertical-align: top;\">Example</td><td style=\"text-align: left; vertical-align: top;\">Cooling Tower 1</td><td style=\"text-align: left; vertical-align: top;\">Area K</td><td style=\"vertical-align: top;\">00:00:00.49</td><td style=\"text-align: right; vertical-align: top;\">4</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">992 B</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>Example &gt;&gt; Cooling Tower 1 &gt;&gt; Area A</th>\n",
       "      <th>Example &gt;&gt; Cooling Tower 1 &gt;&gt; Area B</th>\n",
       "      <th>Example &gt;&gt; Cooling Tower 1 &gt;&gt; Area C</th>\n",
       "      <th>Example &gt;&gt; Cooling Tower 1 &gt;&gt; Area G</th>\n",
       "      <th>Example &gt;&gt; Cooling Tower 1 &gt;&gt; Area H</th>\n",
       "      <th>Example &gt;&gt; Cooling Tower 1 &gt;&gt; Area I</th>\n",
       "      <th>Example &gt;&gt; Cooling Tower 1 &gt;&gt; Area J</th>\n",
       "      <th>Example &gt;&gt; Cooling Tower 1 &gt;&gt; Area K</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2024-08-16 16:15:00+00:00</th>\n",
       "      <td>50.798338</td>\n",
       "      <td>54.140696</td>\n",
       "      <td>49.810592</td>\n",
       "      <td>64.241942</td>\n",
       "      <td>56.713197</td>\n",
       "      <td>65.494262</td>\n",
       "      <td>59.615899</td>\n",
       "      <td>71.098165</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2024-08-16 16:30:00+00:00</th>\n",
       "      <td>50.634327</td>\n",
       "      <td>53.236205</td>\n",
       "      <td>49.476706</td>\n",
       "      <td>63.574725</td>\n",
       "      <td>56.619293</td>\n",
       "      <td>65.506675</td>\n",
       "      <td>59.687074</td>\n",
       "      <td>71.020064</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2024-08-16 16:45:00+00:00</th>\n",
       "      <td>50.308455</td>\n",
       "      <td>53.015179</td>\n",
       "      <td>49.728350</td>\n",
       "      <td>63.712202</td>\n",
       "      <td>56.341640</td>\n",
       "      <td>65.220495</td>\n",
       "      <td>59.567813</td>\n",
       "      <td>71.045078</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2024-08-16 17:00:00+00:00</th>\n",
       "      <td>50.136478</td>\n",
       "      <td>52.452233</td>\n",
       "      <td>49.614424</td>\n",
       "      <td>63.946073</td>\n",
       "      <td>56.032253</td>\n",
       "      <td>64.870019</td>\n",
       "      <td>58.423700</td>\n",
       "      <td>71.137121</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                           Example >> Cooling Tower 1 >> Area A  \\\n",
       "2024-08-16 16:15:00+00:00                             50.798338   \n",
       "2024-08-16 16:30:00+00:00                             50.634327   \n",
       "2024-08-16 16:45:00+00:00                             50.308455   \n",
       "2024-08-16 17:00:00+00:00                             50.136478   \n",
       "\n",
       "                           Example >> Cooling Tower 1 >> Area B  \\\n",
       "2024-08-16 16:15:00+00:00                             54.140696   \n",
       "2024-08-16 16:30:00+00:00                             53.236205   \n",
       "2024-08-16 16:45:00+00:00                             53.015179   \n",
       "2024-08-16 17:00:00+00:00                             52.452233   \n",
       "\n",
       "                           Example >> Cooling Tower 1 >> Area C  \\\n",
       "2024-08-16 16:15:00+00:00                             49.810592   \n",
       "2024-08-16 16:30:00+00:00                             49.476706   \n",
       "2024-08-16 16:45:00+00:00                             49.728350   \n",
       "2024-08-16 17:00:00+00:00                             49.614424   \n",
       "\n",
       "                           Example >> Cooling Tower 1 >> Area G  \\\n",
       "2024-08-16 16:15:00+00:00                             64.241942   \n",
       "2024-08-16 16:30:00+00:00                             63.574725   \n",
       "2024-08-16 16:45:00+00:00                             63.712202   \n",
       "2024-08-16 17:00:00+00:00                             63.946073   \n",
       "\n",
       "                           Example >> Cooling Tower 1 >> Area H  \\\n",
       "2024-08-16 16:15:00+00:00                             56.713197   \n",
       "2024-08-16 16:30:00+00:00                             56.619293   \n",
       "2024-08-16 16:45:00+00:00                             56.341640   \n",
       "2024-08-16 17:00:00+00:00                             56.032253   \n",
       "\n",
       "                           Example >> Cooling Tower 1 >> Area I  \\\n",
       "2024-08-16 16:15:00+00:00                             65.494262   \n",
       "2024-08-16 16:30:00+00:00                             65.506675   \n",
       "2024-08-16 16:45:00+00:00                             65.220495   \n",
       "2024-08-16 17:00:00+00:00                             64.870019   \n",
       "\n",
       "                           Example >> Cooling Tower 1 >> Area J  \\\n",
       "2024-08-16 16:15:00+00:00                             59.615899   \n",
       "2024-08-16 16:30:00+00:00                             59.687074   \n",
       "2024-08-16 16:45:00+00:00                             59.567813   \n",
       "2024-08-16 17:00:00+00:00                             58.423700   \n",
       "\n",
       "                           Example >> Cooling Tower 1 >> Area K  \n",
       "2024-08-16 16:15:00+00:00                             71.098165  \n",
       "2024-08-16 16:30:00+00:00                             71.020064  \n",
       "2024-08-16 16:45:00+00:00                             71.045078  \n",
       "2024-08-16 17:00:00+00:00                             71.137121  "
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "all_areas = spy.search({\n",
    "    'Path': 'Example >> Cooling Tower 1'\n",
    "}, recursive=False)\n",
    "\n",
    "spy.pull(all_areas, calculation=dew_point_calc)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Conditions\n",
    "\n",
    "Conditions capture time intervals of interest as _capsules_, which have a start time and an end time. They will not have an end time if they are _uncertain_ (aka _in progress_), and they may not have a start or end time if it lies outside of the time interval (see below for more information)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "In order to illustrate how condition data can be pulled, we must first push a simple condition into Seeq. (Don't worry-- this condition will be scoped to a workbook that only you can see.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "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>0EF5BF13-0348-F910-81FC-319F8D739929</strong><br>Click the following link to see what you pushed in Seeq:<br><a href=\"http://localhost:34216/0EF5BE2D-2738-FFA0-81E0-D2B058859C4D/workbook/0EF5BF13-0348-F910-81FC-319F8D739929/worksheet/0EF5BF13-0385-F9A0-AF11-E92255C4E645\" target=\"_blank\">http://localhost:34216/0EF5BE2D-2738-FFA0-81E0-D2B058859C4D/workbook/0EF5BF13-0348-F910-81FC-319F8D739929/worksheet/0EF5BF13-0385-F9A0-AF11-E92255C4E645</a></div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Name</th>\n",
       "      <th>Type</th>\n",
       "      <th>Formula Parameters</th>\n",
       "      <th>Formula</th>\n",
       "      <th>Scoped To</th>\n",
       "      <th>Datasource Class</th>\n",
       "      <th>Datasource ID</th>\n",
       "      <th>Data ID</th>\n",
       "      <th>ID</th>\n",
       "      <th>Push Result</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>CalculatedCondition</td>\n",
       "      <td>[cp=0EF58FC2-8762-F910-A3F7-157C1D6689FB]</td>\n",
       "      <td>$cp.valueSearch(isGreaterThan(25kW))</td>\n",
       "      <td>0EF5BF13-0348-F910-81FC-319F8D739929</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[0EF5BF13-0348-F910-81FC-319F8D739929] {Condit...</td>\n",
       "      <td>0EF5BF13-2032-EE90-B3F9-EF5D74B1E75D</td>\n",
       "      <td>Success</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                 Name                 Type  \\\n",
       "0  Compressor on High  CalculatedCondition   \n",
       "\n",
       "                          Formula Parameters  \\\n",
       "0  [cp=0EF58FC2-8762-F910-A3F7-157C1D6689FB]   \n",
       "\n",
       "                                Formula                             Scoped To  \\\n",
       "0  $cp.valueSearch(isGreaterThan(25kW))  0EF5BF13-0348-F910-81FC-319F8D739929   \n",
       "\n",
       "  Datasource Class  Datasource ID  \\\n",
       "0    Seeq Data Lab  Seeq Data Lab   \n",
       "\n",
       "                                             Data ID  \\\n",
       "0  [0EF5BF13-0348-F910-81FC-319F8D739929] {Condit...   \n",
       "\n",
       "                                     ID Push Result  \n",
       "0  0EF5BF13-2032-EE90-B3F9-EF5D74B1E75D     Success  "
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "compressor_on_high = spy.push(metadata=pd.DataFrame([{\n",
    "    'Name': 'Compressor on High',\n",
    "    'Type': 'Condition',\n",
    "\n",
    "    'Formula Parameters': {\n",
    "        # Note here that we are just using a row from our search results. The SPy module will figure\n",
    "        # out that it contains an identifier that we can use.\n",
    "        '$cp': items[items['Name'] == 'Compressor Power']\n",
    "    },\n",
    "\n",
    "    # This formula specifies capsules to be created when Compressor Power is above 25 kW\n",
    "    'Formula': '$cp.valueSearch(isGreaterThan(25kW))'\n",
    "}]), workbook='SPy Documentation Examples >> spy.pull')\n",
    "\n",
    "compressor_on_high"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can now pull data for a particular time period for that condition:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Pull successful from <strong>2019-01-01 04:00:00+00:00</strong> to <strong>2019-01-09 02:00:00+00:00</strong></div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: left;\">ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">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;\">Data Processed</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;\">0EF5BF13-2032-EE90-B3F9-EF5D74B1E75D</td><td style=\"text-align: left; vertical-align: top;\">CalculatedCondition</td><td style=\"text-align: left; vertical-align: top;\">Compressor on High</td><td style=\"vertical-align: top;\">00:00:00.13</td><td style=\"text-align: right; vertical-align: top;\">9</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">91 KB</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>Condition</th>\n",
       "      <th>Capsule Start</th>\n",
       "      <th>Capsule End</th>\n",
       "      <th>Capsule Is Uncertain</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>NaT</td>\n",
       "      <td>2019-01-01 05:01:31.176600146+00:00</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>2019-01-02 00:16:37.331031739+00:00</td>\n",
       "      <td>2019-01-02 05:00:33.238973103+00:00</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>2019-01-03 00:13:18.731947840+00:00</td>\n",
       "      <td>2019-01-03 02:55:03.027869976+00:00</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>2019-01-03 17:28:04.251451273+00:00</td>\n",
       "      <td>2019-01-03 18:21:58.603314005+00:00</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>2019-01-04 17:20:33.782090068+00:00</td>\n",
       "      <td>2019-01-04 18:46:41.571969511+00:00</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>2019-01-05 02:18:11.253715409+00:00</td>\n",
       "      <td>2019-01-05 05:01:23.108876186+00:00</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>2019-01-05 17:20:29.256597642+00:00</td>\n",
       "      <td>2019-01-05 18:43:39.192264349+00:00</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>2019-01-07 17:21:18.826407749+00:00</td>\n",
       "      <td>2019-01-07 18:40:09.983726541+00:00</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>2019-01-09 00:13:55.007784046+00:00</td>\n",
       "      <td>NaT</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            Condition                       Capsule Start  \\\n",
       "0  Compressor on High                                 NaT   \n",
       "1  Compressor on High 2019-01-02 00:16:37.331031739+00:00   \n",
       "2  Compressor on High 2019-01-03 00:13:18.731947840+00:00   \n",
       "3  Compressor on High 2019-01-03 17:28:04.251451273+00:00   \n",
       "4  Compressor on High 2019-01-04 17:20:33.782090068+00:00   \n",
       "5  Compressor on High 2019-01-05 02:18:11.253715409+00:00   \n",
       "6  Compressor on High 2019-01-05 17:20:29.256597642+00:00   \n",
       "7  Compressor on High 2019-01-07 17:21:18.826407749+00:00   \n",
       "8  Compressor on High 2019-01-09 00:13:55.007784046+00:00   \n",
       "\n",
       "                          Capsule End  Capsule Is Uncertain  \n",
       "0 2019-01-01 05:01:31.176600146+00:00                 False  \n",
       "1 2019-01-02 05:00:33.238973103+00:00                 False  \n",
       "2 2019-01-03 02:55:03.027869976+00:00                 False  \n",
       "3 2019-01-03 18:21:58.603314005+00:00                 False  \n",
       "4 2019-01-04 18:46:41.571969511+00:00                 False  \n",
       "5 2019-01-05 05:01:23.108876186+00:00                 False  \n",
       "6 2019-01-05 18:43:39.192264349+00:00                 False  \n",
       "7 2019-01-07 18:40:09.983726541+00:00                 False  \n",
       "8                                 NaT                 False  "
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "spy.pull(compressor_on_high, start='2019-01-01T04:00:00Z', end='2019-01-09T02:00:00Z')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If there were multiple conditions, the `Condition` field would show other conditions further down.\n",
    "\n",
    "Notice that the first capsule (at index 0) has no start time. That's because it starts outside the supplied time interval. Similarly, the last capsule (at index 8) has no end time because it ends outside the supplied time interval.\n",
    "\n",
    "`Capsule Is Uncertain` will be `True` for capsules whose exit criteria has not yet been satisfied and may change as a result of new data arriving in the system. In Seeq Workbench, such capsules are \"hollowed out\" in the Gantt bars at the top of the trend.\n",
    "\n",
    "If we want to know the start and end time even if they're outside our time interval, we can specify a `calculation` argument that applies the `removeLongerThan()` function, which allows the Seeq calculation engine to retrieve start/end times.\n",
    "\n",
    "For example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Pull successful from <strong>2019-01-01 04:00:00+00:00</strong> to <strong>2019-01-09 02:00:00+00:00</strong></div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: left;\">ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">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;\">Data Processed</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;\">0EF5BF13-2032-EE90-B3F9-EF5D74B1E75D</td><td style=\"text-align: left; vertical-align: top;\">CalculatedCondition</td><td style=\"text-align: left; vertical-align: top;\">Compressor on High</td><td style=\"vertical-align: top;\">00:00:00.10</td><td style=\"text-align: right; vertical-align: top;\">9</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">23 KB</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>Condition</th>\n",
       "      <th>Capsule Start</th>\n",
       "      <th>Capsule End</th>\n",
       "      <th>Capsule Is Uncertain</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>2018-12-31 17:19:18.871250820+00:00</td>\n",
       "      <td>2019-01-01 05:01:31.176600146+00:00</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>2019-01-02 00:16:37.331031739+00:00</td>\n",
       "      <td>2019-01-02 05:00:33.238973103+00:00</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>2019-01-03 00:13:18.731947840+00:00</td>\n",
       "      <td>2019-01-03 02:55:03.027869976+00:00</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>2019-01-03 17:28:04.251451273+00:00</td>\n",
       "      <td>2019-01-03 18:21:58.603314005+00:00</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>2019-01-04 17:20:33.782090068+00:00</td>\n",
       "      <td>2019-01-04 18:46:41.571969511+00:00</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>2019-01-05 02:18:11.253715409+00:00</td>\n",
       "      <td>2019-01-05 05:01:23.108876186+00:00</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>2019-01-05 17:20:29.256597642+00:00</td>\n",
       "      <td>2019-01-05 18:43:39.192264349+00:00</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>2019-01-07 17:21:18.826407749+00:00</td>\n",
       "      <td>2019-01-07 18:40:09.983726541+00:00</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>2019-01-09 00:13:55.007784046+00:00</td>\n",
       "      <td>2019-01-09 04:29:12.815103591+00:00</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            Condition                       Capsule Start  \\\n",
       "0  Compressor on High 2018-12-31 17:19:18.871250820+00:00   \n",
       "1  Compressor on High 2019-01-02 00:16:37.331031739+00:00   \n",
       "2  Compressor on High 2019-01-03 00:13:18.731947840+00:00   \n",
       "3  Compressor on High 2019-01-03 17:28:04.251451273+00:00   \n",
       "4  Compressor on High 2019-01-04 17:20:33.782090068+00:00   \n",
       "5  Compressor on High 2019-01-05 02:18:11.253715409+00:00   \n",
       "6  Compressor on High 2019-01-05 17:20:29.256597642+00:00   \n",
       "7  Compressor on High 2019-01-07 17:21:18.826407749+00:00   \n",
       "8  Compressor on High 2019-01-09 00:13:55.007784046+00:00   \n",
       "\n",
       "                          Capsule End  Capsule Is Uncertain  \n",
       "0 2019-01-01 05:01:31.176600146+00:00                 False  \n",
       "1 2019-01-02 05:00:33.238973103+00:00                 False  \n",
       "2 2019-01-03 02:55:03.027869976+00:00                 False  \n",
       "3 2019-01-03 18:21:58.603314005+00:00                 False  \n",
       "4 2019-01-04 18:46:41.571969511+00:00                 False  \n",
       "5 2019-01-05 05:01:23.108876186+00:00                 False  \n",
       "6 2019-01-05 18:43:39.192264349+00:00                 False  \n",
       "7 2019-01-07 18:40:09.983726541+00:00                 False  \n",
       "8 2019-01-09 04:29:12.815103591+00:00                 False  "
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "spy.pull(compressor_on_high,\n",
    "         start='2019-01-01T04:00:00Z',\n",
    "         end='2019-01-09T02:00:00Z',\n",
    "         calculation='$condition.removeLongerThan(1d)')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now the first and last capsules have both starts and ends.\n",
    "\n",
    "It's important to note that setting the _Maximum Duration_ for a Condition to something high can have major performance implications because the Seeq calculation engine is required to potentially evaluate significant amounts of data before/after the query interval to \"find\" the start/end of the capsule."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Conditions as signals\n",
    "\n",
    "You can also request the condition data to be represented as a signal with a value of `1` if a capsule is present at a particular timestamp or `0` if not. Use `shape='samples'` like so:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Pull successful from <strong>2019-01-01 00:00:00+00:00</strong> to <strong>2019-01-01 12:00:00+00:00</strong></div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: left;\">ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">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;\">Data Processed</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;\">0EF5BF13-2032-EE90-B3F9-EF5D74B1E75D</td><td style=\"text-align: left; vertical-align: top;\">CalculatedCondition</td><td style=\"text-align: left; vertical-align: top;\">Compressor on High</td><td style=\"vertical-align: top;\">00:00:00.02</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;\">128 B</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>Compressor on High</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2019-01-01 00:00:00+00:00</th>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 01:00:00+00:00</th>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 02:00:00+00:00</th>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 03:00:00+00:00</th>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 04:00:00+00:00</th>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 05:00:00+00:00</th>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 06:00:00+00:00</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 07:00:00+00:00</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 08:00:00+00:00</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 09:00:00+00:00</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 10:00:00+00:00</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 11:00:00+00:00</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 12:00:00+00:00</th>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                           Compressor on High\n",
       "2019-01-01 00:00:00+00:00                 1.0\n",
       "2019-01-01 01:00:00+00:00                 1.0\n",
       "2019-01-01 02:00:00+00:00                 1.0\n",
       "2019-01-01 03:00:00+00:00                 1.0\n",
       "2019-01-01 04:00:00+00:00                 1.0\n",
       "2019-01-01 05:00:00+00:00                 1.0\n",
       "2019-01-01 06:00:00+00:00                 0.0\n",
       "2019-01-01 07:00:00+00:00                 0.0\n",
       "2019-01-01 08:00:00+00:00                 0.0\n",
       "2019-01-01 09:00:00+00:00                 0.0\n",
       "2019-01-01 10:00:00+00:00                 0.0\n",
       "2019-01-01 11:00:00+00:00                 0.0\n",
       "2019-01-01 12:00:00+00:00                 0.0"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "spy.pull(compressor_on_high, start='2019-01-01T00:00:00Z', end='2019-01-01T12:00:00Z', shape='samples', grid='1h')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Mixing conditions with signals\n",
    "\n",
    "If the DataFrame that you pass into the `spy.pull()` function contains a mix of signals and conditions, `shape='samples'` will be automatically applied:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Pull successful from <strong>2019-01-01 00:00:00+00:00</strong> to <strong>2019-01-01 12:00:00+00:00</strong></div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: left;\">ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">Path</td><td style=\"background-color: #EEFFEE; text-align: left;\">Asset</td><td style=\"background-color: #EEFFEE; text-align: left;\">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;\">Data Processed</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;\">0EF58FC2-8762-F910-A3F7-157C1D6689FB</td><td style=\"text-align: left; vertical-align: top;\">StoredSignal</td><td style=\"text-align: left; vertical-align: top;\">Example >> Cooling Tower 1</td><td style=\"text-align: left; vertical-align: top;\">Area A</td><td style=\"text-align: left; vertical-align: top;\">Compressor Power</td><td style=\"vertical-align: top;\">00:00:00.02</td><td style=\"text-align: right; vertical-align: top;\">13</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">5 KB</td><td style=\"text-align: left; vertical-align: top;\">Success</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">1</td><td style=\"text-align: left; vertical-align: top;\">0EF5BF13-2032-EE90-B3F9-EF5D74B1E75D</td><td style=\"text-align: left; vertical-align: top;\">CalculatedCondition</td><td style=\"text-align: right; vertical-align: top;\">nan</td><td style=\"text-align: right; vertical-align: top;\">nan</td><td style=\"text-align: left; vertical-align: top;\">Compressor on High</td><td style=\"vertical-align: top;\">00:00:00.01</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;\">128 B</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>Compressor Power</th>\n",
       "      <th>Compressor on High</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2019-01-01 00:00:00+00:00</th>\n",
       "      <td>39.189300</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 01:00:00+00:00</th>\n",
       "      <td>39.326496</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 02:00:00+00:00</th>\n",
       "      <td>40.223175</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 03:00:00+00:00</th>\n",
       "      <td>39.431483</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 04:00:00+00:00</th>\n",
       "      <td>39.139759</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 05:00:00+00:00</th>\n",
       "      <td>39.154395</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 06:00:00+00:00</th>\n",
       "      <td>0.002923</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 07:00:00+00:00</th>\n",
       "      <td>0.002923</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 08:00:00+00:00</th>\n",
       "      <td>0.002923</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 09:00:00+00:00</th>\n",
       "      <td>0.002923</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 10:00:00+00:00</th>\n",
       "      <td>0.002923</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 11:00:00+00:00</th>\n",
       "      <td>0.002923</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2019-01-01 12:00:00+00:00</th>\n",
       "      <td>0.002923</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                           Compressor Power  Compressor on High\n",
       "2019-01-01 00:00:00+00:00         39.189300                 1.0\n",
       "2019-01-01 01:00:00+00:00         39.326496                 1.0\n",
       "2019-01-01 02:00:00+00:00         40.223175                 1.0\n",
       "2019-01-01 03:00:00+00:00         39.431483                 1.0\n",
       "2019-01-01 04:00:00+00:00         39.139759                 1.0\n",
       "2019-01-01 05:00:00+00:00         39.154395                 1.0\n",
       "2019-01-01 06:00:00+00:00          0.002923                 0.0\n",
       "2019-01-01 07:00:00+00:00          0.002923                 0.0\n",
       "2019-01-01 08:00:00+00:00          0.002923                 0.0\n",
       "2019-01-01 09:00:00+00:00          0.002923                 0.0\n",
       "2019-01-01 10:00:00+00:00          0.002923                 0.0\n",
       "2019-01-01 11:00:00+00:00          0.002923                 0.0\n",
       "2019-01-01 12:00:00+00:00          0.002923                 0.0"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "compressor_signal_and_condition = pd.concat([spy.search({\n",
    "    'Path': 'Example >> Cooling Tower 1 >> Area A',\n",
    "    'Name': 'Compressor Power',\n",
    "    'Datasource Name': 'Example Data'\n",
    "}), spy.search({\n",
    "    'Name': 'Compressor*High',\n",
    "}, workbook='SPy Documentation Examples >> spy.pull')], sort=False, ignore_index=True)\n",
    "\n",
    "spy.pull(compressor_signal_and_condition,\n",
    "         start='2019-01-01T00:00:00Z', end='2019-01-01T12:00:00Z',\n",
    "         header='Name', grid='1h')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can supply `shape='capsules'` to force the output to capsules. In such a case, the signals within the DataFrame will be aggregated within the interval of each capsule according to a statistic. By default, that statistic is `average`, but you can add a `Statistic` column to the passed-in DataFrame to control which statistic is used. To return multiple statistics for the same signal, add additional signal rows to your DataFrame that only vary by the `Statistic` column. The possible statistic function names you can specify are documented in Seeq Workbench's Formula tool documentation under the heading _Signal Value Statistics_.\n",
    "\n",
    "Let's try this example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "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",
       "      <th>Path</th>\n",
       "      <th>Asset</th>\n",
       "      <th>Statistic</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0EF5BF13-2032-EE90-B3F9-EF5D74B1E75D</td>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>NaN</td>\n",
       "      <td>CalculatedCondition</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>False</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0EF58FC2-8762-F910-A3F7-157C1D6689FB</td>\n",
       "      <td>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",
       "      <td>Example &gt;&gt; Cooling Tower 1</td>\n",
       "      <td>Area A</td>\n",
       "      <td>maximum</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0EF58FC2-8762-F910-A3F7-157C1D6689FB</td>\n",
       "      <td>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",
       "      <td>Example &gt;&gt; Cooling Tower 1</td>\n",
       "      <td>Area A</td>\n",
       "      <td>totalized</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                     ID                Name  Description  \\\n",
       "0  0EF5BF13-2032-EE90-B3F9-EF5D74B1E75D  Compressor on High          NaN   \n",
       "1  0EF58FC2-8762-F910-A3F7-157C1D6689FB    Compressor Power          NaN   \n",
       "2  0EF58FC2-8762-F910-A3F7-157C1D6689FB    Compressor Power          NaN   \n",
       "\n",
       "                  Type Value Unit Of Measure Datasource Name  Archived  \\\n",
       "0  CalculatedCondition                   NaN   Seeq Data Lab     False   \n",
       "1         StoredSignal                    kW    Example Data     False   \n",
       "2         StoredSignal                    kW    Example Data     False   \n",
       "\n",
       "                         Path   Asset  Statistic  \n",
       "0                         NaN     NaN        NaN  \n",
       "1  Example >> Cooling Tower 1  Area A    maximum  \n",
       "2  Example >> Cooling Tower 1  Area A  totalized  "
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "area_a_compressor_power = spy.search({\n",
    "    'Path': 'Example >> Cooling Tower 1 >> Area A',\n",
    "    'Name': 'Compressor Power',\n",
    "    'Datasource Name': 'Example Data'\n",
    "}, quiet=True)\n",
    "\n",
    "compressor_on_high = spy.search({\n",
    "    'Name': 'Compressor*High',\n",
    "}, workbook='SPy Documentation Examples >> spy.pull', quiet=True).iloc[0]\n",
    "\n",
    "area_a_compressor_power_max = area_a_compressor_power.iloc[0].copy()\n",
    "area_a_compressor_power_max['Statistic'] = 'maximum'\n",
    "\n",
    "area_a_compressor_power_delta = area_a_compressor_power.iloc[0].copy()\n",
    "area_a_compressor_power_delta['Statistic'] = 'totalized'\n",
    "\n",
    "conditions_with_stats = pd.DataFrame([\n",
    "    compressor_on_high,\n",
    "    area_a_compressor_power_max,\n",
    "    area_a_compressor_power_delta\n",
    "]).reset_index(drop=True)\n",
    "\n",
    "conditions_with_stats"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Notice that the `Compressor Power` signal appears twice in this DataFrame but has a different value in the `Statistic` column. If we pull with this DataFrame and the `shape='capsules'` argument, we'll get columns for these aggregates:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Pull successful from <strong>2019-01-01 00:00:00+00:00</strong> to <strong>2019-01-07 00:00:00+00:00</strong></div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: left;\">ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">Path</td><td style=\"background-color: #EEFFEE; text-align: left;\">Asset</td><td style=\"background-color: #EEFFEE; text-align: left;\">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;\">Data Processed</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;\">0EF5BF13-2032-EE90-B3F9-EF5D74B1E75D</td><td style=\"text-align: left; vertical-align: top;\">CalculatedCondition</td><td style=\"text-align: right; vertical-align: top;\">nan</td><td style=\"text-align: right; vertical-align: top;\">nan</td><td style=\"text-align: left; vertical-align: top;\">Compressor on High</td><td style=\"vertical-align: top;\">00:00:00.21</td><td style=\"text-align: right; vertical-align: top;\">7</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">43 KB</td><td style=\"text-align: left; vertical-align: top;\">Success</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">1</td><td style=\"text-align: left; vertical-align: top;\">0EF58FC2-8762-F910-A3F7-157C1D6689FB</td><td style=\"text-align: left; vertical-align: top;\">StoredSignal</td><td style=\"text-align: left; vertical-align: top;\">Example >> Cooling Tower 1</td><td style=\"text-align: left; vertical-align: top;\">Area A</td><td style=\"text-align: left; vertical-align: top;\">Compressor Power</td><td style=\"vertical-align: top;\">00:00:00.21</td><td style=\"text-align: right; vertical-align: top;\">7</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">43 KB</td><td style=\"text-align: left; vertical-align: top;\">Success</td></tr><tr style=\"background-color: #EEFFEE;\"><td style=\"vertical-align: top;\">2</td><td style=\"text-align: left; vertical-align: top;\">0EF58FC2-8762-F910-A3F7-157C1D6689FB</td><td style=\"text-align: left; vertical-align: top;\">StoredSignal</td><td style=\"text-align: left; vertical-align: top;\">Example >> Cooling Tower 1</td><td style=\"text-align: left; vertical-align: top;\">Area A</td><td style=\"text-align: left; vertical-align: top;\">Compressor Power</td><td style=\"vertical-align: top;\">00:00:00.21</td><td style=\"text-align: right; vertical-align: top;\">7</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">43 KB</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>Condition</th>\n",
       "      <th>Capsule Start</th>\n",
       "      <th>Capsule End</th>\n",
       "      <th>Compressor Power (maximum)</th>\n",
       "      <th>Compressor Power (totalized)</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>NaT</td>\n",
       "      <td>2019-01-01 05:01:31.176600146+00:00</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>2019-01-02 00:16:37.331031739+00:00</td>\n",
       "      <td>2019-01-02 05:00:33.238973103+00:00</td>\n",
       "      <td>37.337571</td>\n",
       "      <td>621836.085754</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>2019-01-03 00:13:18.731947840+00:00</td>\n",
       "      <td>2019-01-03 02:55:03.027869976+00:00</td>\n",
       "      <td>38.346637</td>\n",
       "      <td>355158.928285</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>2019-01-03 17:28:04.251451273+00:00</td>\n",
       "      <td>2019-01-03 18:21:58.603314005+00:00</td>\n",
       "      <td>34.499000</td>\n",
       "      <td>109815.164071</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>2019-01-04 17:20:33.782090068+00:00</td>\n",
       "      <td>2019-01-04 18:46:41.571969511+00:00</td>\n",
       "      <td>35.749304</td>\n",
       "      <td>181575.891856</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>2019-01-05 02:18:11.253715409+00:00</td>\n",
       "      <td>2019-01-05 05:01:23.108876186+00:00</td>\n",
       "      <td>39.769103</td>\n",
       "      <td>378094.380825</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>2019-01-05 17:20:29.256597642+00:00</td>\n",
       "      <td>2019-01-05 18:43:39.192264349+00:00</td>\n",
       "      <td>35.700364</td>\n",
       "      <td>174524.224726</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "            Condition                       Capsule Start  \\\n",
       "0  Compressor on High                                 NaT   \n",
       "1  Compressor on High 2019-01-02 00:16:37.331031739+00:00   \n",
       "2  Compressor on High 2019-01-03 00:13:18.731947840+00:00   \n",
       "3  Compressor on High 2019-01-03 17:28:04.251451273+00:00   \n",
       "4  Compressor on High 2019-01-04 17:20:33.782090068+00:00   \n",
       "5  Compressor on High 2019-01-05 02:18:11.253715409+00:00   \n",
       "6  Compressor on High 2019-01-05 17:20:29.256597642+00:00   \n",
       "\n",
       "                          Capsule End  Compressor Power (maximum)  \\\n",
       "0 2019-01-01 05:01:31.176600146+00:00                         NaN   \n",
       "1 2019-01-02 05:00:33.238973103+00:00                   37.337571   \n",
       "2 2019-01-03 02:55:03.027869976+00:00                   38.346637   \n",
       "3 2019-01-03 18:21:58.603314005+00:00                   34.499000   \n",
       "4 2019-01-04 18:46:41.571969511+00:00                   35.749304   \n",
       "5 2019-01-05 05:01:23.108876186+00:00                   39.769103   \n",
       "6 2019-01-05 18:43:39.192264349+00:00                   35.700364   \n",
       "\n",
       "   Compressor Power (totalized)  \n",
       "0                           NaN  \n",
       "1                 621836.085754  \n",
       "2                 355158.928285  \n",
       "3                 109815.164071  \n",
       "4                 181575.891856  \n",
       "5                 378094.380825  \n",
       "6                 174524.224726  "
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pull_results = spy.pull(conditions_with_stats,\n",
    "                        start='2019-01-01T00:00:00Z', end='2019-01-07T00:00:00Z',\n",
    "                        shape='capsules', header='Name', grid='1h')\n",
    "\n",
    "# For brevity, drop uncertainty column\n",
    "pull_results.drop(columns=['Capsule Is Uncertain'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Scalars\n",
    "\n",
    "Scalars represent a constant value across all time. Let's push one into Seeq to see how it looks when we retrieve it:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "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>0EF5BF13-0348-F910-81FC-319F8D739929</strong><br>Click the following link to see what you pushed in Seeq:<br><a href=\"http://localhost:34216/0EF5BE2D-2738-FFA0-81E0-D2B058859C4D/workbook/0EF5BF13-0348-F910-81FC-319F8D739929/worksheet/0EF5BF13-0385-F9A0-AF11-E92255C4E645\" target=\"_blank\">http://localhost:34216/0EF5BE2D-2738-FFA0-81E0-D2B058859C4D/workbook/0EF5BF13-0348-F910-81FC-319F8D739929/worksheet/0EF5BF13-0385-F9A0-AF11-E92255C4E645</a></div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Name</th>\n",
       "      <th>Type</th>\n",
       "      <th>Formula</th>\n",
       "      <th>Scoped To</th>\n",
       "      <th>Datasource Class</th>\n",
       "      <th>Datasource ID</th>\n",
       "      <th>Formula Parameters</th>\n",
       "      <th>Data ID</th>\n",
       "      <th>ID</th>\n",
       "      <th>Push Result</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Compressor Power Limit</td>\n",
       "      <td>CalculatedScalar</td>\n",
       "      <td>50kW</td>\n",
       "      <td>0EF5BF13-0348-F910-81FC-319F8D739929</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[]</td>\n",
       "      <td>[0EF5BF13-0348-F910-81FC-319F8D739929] {Scalar...</td>\n",
       "      <td>0EF5BF13-322C-FF60-9C3D-A7BBBF38E2E6</td>\n",
       "      <td>Success</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                     Name              Type Formula  \\\n",
       "0  Compressor Power Limit  CalculatedScalar    50kW   \n",
       "\n",
       "                              Scoped To Datasource Class  Datasource ID  \\\n",
       "0  0EF5BF13-0348-F910-81FC-319F8D739929    Seeq Data Lab  Seeq Data Lab   \n",
       "\n",
       "  Formula Parameters                                            Data ID  \\\n",
       "0                 []  [0EF5BF13-0348-F910-81FC-319F8D739929] {Scalar...   \n",
       "\n",
       "                                     ID Push Result  \n",
       "0  0EF5BF13-322C-FF60-9C3D-A7BBBF38E2E6     Success  "
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "compressor_power_limit = spy.push(metadata=pd.DataFrame([{\n",
    "    'Name': 'Compressor Power Limit',\n",
    "    'Type': 'Scalar',\n",
    "    'Formula': '50kW'\n",
    "}]), workbook='SPy Documentation Examples >> spy.pull', errors='raise')\n",
    "\n",
    "compressor_power_limit"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Pull successful from <strong>2024-08-16 16:01:37.854509+00:00</strong> to <strong>2024-08-16 17:01:37.854509+00:00</strong></div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: left;\">ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">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;\">Data Processed</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;\">0EF5BF13-322C-FF60-9C3D-A7BBBF38E2E6</td><td style=\"text-align: left; vertical-align: top;\">CalculatedScalar</td><td style=\"text-align: left; vertical-align: top;\">Compressor Power Limit</td><td style=\"vertical-align: top;\">00:00:00.01</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 B</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>Compressor Power Limit</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>50</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   Compressor Power Limit\n",
       "0                      50"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "spy.pull(compressor_power_limit)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Pickling\n",
    "Sometimes a pull is \"expensive\" and takes a long time to complete, and the data likely hasn't changed.\n",
    "In that case, it is common to \"pickle\" the resulting DataFrame for later use, like so:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [],
   "source": [
    "pull_results.to_pickle('pickled_pull.pkl')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now you can \"unpickle\" the DataFrame and use it without incurring the cost of re-executing the pull:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [],
   "source": [
    "unpickled_pull = pd.read_pickle('pickled_pull.pkl')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can access some of the original context of the search via the `spy` attribute of the unpickled\n",
    "DataFrame. For example, the `spy.status` tells you what queries were successful and what queries failed."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "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>Type</th>\n",
       "      <th>Path</th>\n",
       "      <th>Asset</th>\n",
       "      <th>Name</th>\n",
       "      <th>Time</th>\n",
       "      <th>Count</th>\n",
       "      <th>Pages</th>\n",
       "      <th>Data Processed</th>\n",
       "      <th>Result</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0EF5BF13-2032-EE90-B3F9-EF5D74B1E75D</td>\n",
       "      <td>CalculatedCondition</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Compressor on High</td>\n",
       "      <td>0 days 00:00:00.213521</td>\n",
       "      <td>7</td>\n",
       "      <td>1</td>\n",
       "      <td>43 KB</td>\n",
       "      <td>Success</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0EF58FC2-8762-F910-A3F7-157C1D6689FB</td>\n",
       "      <td>StoredSignal</td>\n",
       "      <td>Example &gt;&gt; Cooling Tower 1</td>\n",
       "      <td>Area A</td>\n",
       "      <td>Compressor Power</td>\n",
       "      <td>0 days 00:00:00.213521</td>\n",
       "      <td>7</td>\n",
       "      <td>1</td>\n",
       "      <td>43 KB</td>\n",
       "      <td>Success</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0EF58FC2-8762-F910-A3F7-157C1D6689FB</td>\n",
       "      <td>StoredSignal</td>\n",
       "      <td>Example &gt;&gt; Cooling Tower 1</td>\n",
       "      <td>Area A</td>\n",
       "      <td>Compressor Power</td>\n",
       "      <td>0 days 00:00:00.213521</td>\n",
       "      <td>7</td>\n",
       "      <td>1</td>\n",
       "      <td>43 KB</td>\n",
       "      <td>Success</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                     ID                 Type  \\\n",
       "0  0EF5BF13-2032-EE90-B3F9-EF5D74B1E75D  CalculatedCondition   \n",
       "1  0EF58FC2-8762-F910-A3F7-157C1D6689FB         StoredSignal   \n",
       "2  0EF58FC2-8762-F910-A3F7-157C1D6689FB         StoredSignal   \n",
       "\n",
       "                         Path   Asset                Name  \\\n",
       "0                         NaN     NaN  Compressor on High   \n",
       "1  Example >> Cooling Tower 1  Area A    Compressor Power   \n",
       "2  Example >> Cooling Tower 1  Area A    Compressor Power   \n",
       "\n",
       "                    Time  Count  Pages Data Processed   Result  \n",
       "0 0 days 00:00:00.213521      7      1          43 KB  Success  \n",
       "1 0 days 00:00:00.213521      7      1          43 KB  Success  \n",
       "2 0 days 00:00:00.213521      7      1          43 KB  Success  "
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "unpickled_pull.spy.status.df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Performance Metrics\n",
    "\n",
    "If your pull operation takes a long time to complete, you can take a look at the timing information for data processing by inspecting the \"Data Processed\" cell in the status DataFrame like so:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black; text-align: left;\">Pull successful from <strong>2019-01-01 00:00:00+00:00</strong> to <strong>2019-03-01 00:00:00+00:00</strong></div><table class=\"tex2jax_ignore\" style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE; text-align: left;\">ID</td><td style=\"background-color: #EEFFEE; text-align: left;\">Type</td><td style=\"background-color: #EEFFEE; text-align: left;\">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;\">Data Processed</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;\">0EF58FC2-85A1-7590-AA5F-C66CA82059F8</td><td style=\"text-align: left; vertical-align: top;\">StoredSignal</td><td style=\"text-align: left; vertical-align: top;\">Area B_Compressor Power</td><td style=\"vertical-align: top;\">00:00:00.37</td><td style=\"text-align: right; vertical-align: top;\">42481</td><td style=\"text-align: right; vertical-align: top;\">1</td><td style=\"text-align: right; vertical-align: top;\">679 KB</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": [
    "# Pull two months of data\n",
    "pull_results = spy.pull(spy.search({'Name': 'Area B_Compressor Power'}), start='2019-01-01', end='2019-03-01', grid=None)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {
    "keep_output_in_docs": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Time spent in Request Queue:           0:00:00.000520\n",
       "Time spent reading Metadata:           0:00:00.003270\n",
       "Time spent waiting for Datasource(s):  0:00:00\n",
       "Time spent reading from Seeq Cache:    0:00:00\n",
       "Time spent in Calc Engine Queue:       0:00:00\n",
       "Time spent in Calc Engine:             0:00:00.291160\n",
       "Time spent reclaiming Memory:          0:00:00\n",
       "\n",
       "Metadata items read:                                3\n",
       "Metadata relationships read:                        0\n",
       "Samples read from Datasource(s):                42482\n",
       "Samples read from Persistent Cache:                 0\n",
       "Samples read from In-Memory Cache:                  0\n",
       "Capsules read from Datasource(s):                   0\n",
       "Capsules read from Persistent Cache:                0\n",
       "Capsules read from In-Memory Cache:                 0\n",
       "Total bytes processed:                         679712"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Inspect the 'Data Processed' column in the first row of the status DataFrame\n",
    "pull_results.spy.status.df.iloc[0]['Data Processed']"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that the \"Time spent\" values here are inclusive of the time spent within the Seeq service. They are _exclusive_ of time spent transmitting the data from the Seeq service to SPy, and the time spent by SPy organizing the data into a Pandas DataFrame."
   ]
  },
  {
   "cell_type": "markdown",
   "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": 25,
   "metadata": {
    "pycharm": {
     "name": "#%% \n"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Help on function pull in module seeq.spy._pull:\n",
      "\n",
      "pull(items, *, start=None, end=None, grid='15min', header='__auto__', group_by=None, shape: 'Union[str, Callable]' = 'auto', capsule_properties=None, tz_convert=None, calculation=None, bounding_values=False, invalid_values_as=nan, enums_as='string', errors=None, quiet=None, status: 'Status' = None, session: 'Optional[Session]' = None, capsules_as=None)\n",
      "    Retrieves signal, condition or scalar data from Seeq Server and returns it\n",
      "    in a DataFrame.\n",
      "    \n",
      "    Parameters\n",
      "    ----------\n",
      "    items : {str, pd.DataFrame, pd.Series}\n",
      "        A DataFrame or Series containing ID and Type columns that can be used\n",
      "        to identify the items to pull. This is usually created via a call to\n",
      "        spy.search(). Alternatively, you can supply URL of a Seeq Workbench\n",
      "        worksheet as a str.\n",
      "    \n",
      "        If a 'Calculation' column is present, the formula specified in that\n",
      "        column will be applied to the item in that row \"on-the-fly\" while\n",
      "        data is retrieved. The formula must utilize a $signal, $condition\n",
      "        or $scalar variable to reference the item in that row. Note that\n",
      "        the results of these \"on-the-fly\" calculations are not cacheable.\n",
      "        If you want to utilize caching, explicitly push such calculated\n",
      "        items and use them without this \"on-the-fly\" method.\n",
      "    \n",
      "    start : {str, pd.Timestamp}, optional\n",
      "        The starting time for which to pull data. This argument must be a\n",
      "        string that pandas.to_datetime() can parse, or a pandas.Timestamp.\n",
      "        If not provided, 'start' will default to 'end' minus 1 hour. Note\n",
      "        that Seeq will potentially return one additional row that is earlier\n",
      "        than this time (if it exists), as a \"bounding value\" for interpolation\n",
      "        purposes. If both 'start' and 'end' are not provided and items\n",
      "        is a str, 'start' will default to the start of the display range\n",
      "        in Seeq Trend View.\n",
      "    \n",
      "    end : {str, pd.Timestamp}, optional\n",
      "        The end time for which to pull data. This argument must be a string\n",
      "        that pandas.to_datetime() can parse, or a pandas.Timestamp.\n",
      "        If not provided, 'end' will default to now. Note that Seeq will\n",
      "        potentially return one additional row that is later than this time\n",
      "        (if it exists), as a \"bounding value\" for interpolation purposes.\n",
      "        If both 'start' and 'end' are not provided and items is a str,\n",
      "        'end' will default to the end of the display range in Seeq Trend View.\n",
      "    \n",
      "    grid : {str, 'auto', None}, default '15min'\n",
      "        A period to use for interpolation such that all returned samples\n",
      "        have the same timestamps. Interpolation will be applied at the server\n",
      "        to achieve this. To align samples to a different time zone and/or date\n",
      "        and time, append a valid time zone and/or timestamp in ISO8601,\n",
      "        YYYY-MM-DD, or YYYY-MM-DDTHH:MM:SS form. If grid=None is specified,\n",
      "        no interpolation will occur and each signal's samples will be returned\n",
      "        untouched. Where timestamps don't match, NaNs will be present within a\n",
      "        row. If grid='auto', the period used for interpolation will be the median\n",
      "        of the sample periods from the 'Estimated Sample Period' column in 'items'.\n",
      "        If grid='auto' and the 'Estimated Sample Period' column does not exist\n",
      "        in 'items', additional queries will be made to estimate the sample period\n",
      "        which could potentially impact performance for large pulls. Interpolation\n",
      "        is either linear or step and is set per signal at the time of the signal's\n",
      "        creation. To change the interpolation type for a given signal, change the\n",
      "        signal's interpolation or use the appropriate 'calculation' argument.\n",
      "    \n",
      "    header : str, default '__auto__'\n",
      "        The metadata property to use as the header of each column. Common\n",
      "        values would be 'ID' or 'Name'. '__auto__' concatenates Path and Name\n",
      "        if they are present. If a 'Header\" column is present in the metadata,\n",
      "        '__auto__' will use that instead.\n",
      "    \n",
      "    group_by : {str, list(str)}, optional\n",
      "        The name of a column or list of columns for which to group by. Often\n",
      "        necessary when pulling data across assets: When you want header='Name',\n",
      "        you typically need group_by=['Path', 'Asset']\n",
      "    \n",
      "    shape : {'auto', 'samples', 'capsules'}, default 'auto'\n",
      "        If 'auto', returns capsules as a time series of 0 or 1 when signals are\n",
      "        also present in the items argument, or returns capsules as individual\n",
      "        rows if no signals are present. 'samples' or 'capsules' forces the\n",
      "        output to the former or the latter, if possible.\n",
      "    \n",
      "        You may also provide a callback function as the shape argument. When\n",
      "        you do so, the callback function will receive the results as they\n",
      "        are returned by the Seeq service, and they will not accumulate into\n",
      "        a final DataFrame (and therefore spy.pull() will return None).\n",
      "        The callback function must take two arguments: The row that the result\n",
      "        corresponds to; the result DataFrame itself. In this scenario, you\n",
      "        may also provide 'Start' and 'End' columns in the items DataFrame to\n",
      "        indicate the time range to pull for that particular row. This scenario\n",
      "        is useful when you are pulling a lot of data, potentially at different\n",
      "        time ranges, and it is not possible/practical to accumulate it all\n",
      "        into a single DataFrame.\n",
      "    \n",
      "    capsule_properties : list(str), optional\n",
      "        A list of capsule properties to retrieve when shape='capsules'.\n",
      "        By default, if no signals are present in the items DataFrame, then all\n",
      "        properties found on a capsule are automatically returned (because\n",
      "        the nature of the query allows them to be returned \"for free\").\n",
      "        Otherwise, you must provide a list of names of properties to retrieve.\n",
      "    \n",
      "    tz_convert : {str, datetime.tzinfo}, optional\n",
      "        The time zone in which to return all timestamps. If the time zone\n",
      "        string is not recognized, the list of supported time zone strings will\n",
      "        be returned in the exception text.\n",
      "    \n",
      "    calculation : {str, pandas.Series, pandas.DataFrame}, optional\n",
      "        When applying a calculation across assets, the 'calculation' argument\n",
      "        must be a one-row DataFrame (or a Series) and the 'items' argument must\n",
      "        be full of assets. When applying a calculation to a signal/condition/\n",
      "        scalar, calculation must be a string with a single variable in it:\n",
      "        $signal, $condition or $scalar.\n",
      "    \n",
      "    bounding_values : bool, default False\n",
      "        If True, extra 'bounding values' will be returned before/after the\n",
      "        specified query range for the purposes of assisting with interpolation\n",
      "        to the edges of the range or, in the case of Step or PILinear\n",
      "        interpolation methods, interpolating to 'now' when appropriate.\n",
      "    \n",
      "    invalid_values_as : {str, int, float}, default np.nan\n",
      "        Invalid samples and scalars will appear in the returned DataFrame as\n",
      "        specified in this argument. By default, invalid values will be returned\n",
      "        as NaNs. Note that specifying a string for this argument (e.g,\n",
      "        'INVALID') can have significant performance implications on numeric\n",
      "        signals. You may wish to use a \"magic\" number like -999999999 if you\n",
      "        want to be able to discern invalid values but preserve algorithmic\n",
      "        performance.\n",
      "    \n",
      "    enums_as : {'tuple', 'string', 'numeric', None}, default 'string'\n",
      "        Enumerations, also known as digital states, are numbers that have an\n",
      "        associated human-readable name with meaning in the applicable domain\n",
      "        (e.g., an ON or OFF machine state that is encoded as 1 or 0).\n",
      "        If enums_as='string', the signal's column in the returned DataFrame\n",
      "        will be a string value (e.g., 'ON' or 'OFF'). If enums_as='numeric',\n",
      "        the signal's column will be an integer (e.g. 1 or 0). If enums_as='tuple',\n",
      "        both the integer and string will be supplied as a tuple\n",
      "        (e.g., (1, 'ON') or (0, 'OFF')).\n",
      "    \n",
      "    errors : {'raise', 'catalog'}, default 'raise'\n",
      "        If 'raise', any errors encountered will cause an exception. If\n",
      "        'catalog', errors will be added to a 'Result' column in the status.df\n",
      "        DataFrame.\n",
      "    \n",
      "    quiet : bool, default False\n",
      "        If True, suppresses progress output. Note that when status is\n",
      "        provided, the quiet setting of the Status object that is passed\n",
      "        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",
      "    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",
      "    capsules_as : str\n",
      "        Deprecated, use shape argument instead.\n",
      "    \n",
      "    Returns\n",
      "    -------\n",
      "    pandas.DataFrame\n",
      "        A DataFrame with the requested data. Additionally, the following\n",
      "        properties are stored on the \"spy\" attribute of the output DataFrame:\n",
      "    \n",
      "        =================== ===================================================\n",
      "        Property            Description\n",
      "        =================== ===================================================\n",
      "        func                A str value of 'spy.pull'\n",
      "        kwargs              A dict with the values of the input parameters\n",
      "                            passed to spy.pull to get the output DataFrame\n",
      "        query_df            A DataFrame with the actual query made to the\n",
      "                            Seeq server\n",
      "        start               A pd.Timestamp with the effective start time\n",
      "                            of the data pulled\n",
      "        end                 A pd.Timestamp with the effective end time\n",
      "                            of the data pulled\n",
      "        grid                A string with the effective grid of the data\n",
      "                            pulled\n",
      "        tz_convert          A datetime.tzinfo of the time zone in which\n",
      "                            the timestamps were returned\n",
      "        status              A spy.Status object with the status of the\n",
      "                            spy.pull call\n",
      "        =================== ===================================================\n",
      "    \n",
      "    Examples\n",
      "    --------\n",
      "    Pull a list of signals and convert the timezone to another timezone\n",
      "    \n",
      "    >>> items = pd.DataFrame([{'ID': '8543F427-2963-4B4E-9825-220D9FDCAD4E', 'Type': 'CalculatedSignal'}])\n",
      "    >>> my_signals = spy.pull(items=items, grid='15min', calculation='$signal.toStep()',\n",
      "    >>>          start='2019-10-5T02:53:45.567Z', end='2019-10-6', tz_convert='US/Eastern')\n",
      "    \n",
      "    To access the stored properties\n",
      "    >>> my_signals.spy.kwargs\n",
      "    >>> my_signals.spy.query_df\n",
      "    >>> my_signals.spy.start\n",
      "    >>> my_signals.spy.end\n",
      "    >>> my_signals.spy.grid\n",
      "    >>> my_signals.spy.status.df\n",
      "    \n",
      "    Pull a list of signals with an auto-calculated grid\n",
      "    >>> signals = spy.search({'Name': 'Area ?_*', 'Datasource Name': 'Example Data'},\n",
      "    >>>                        estimate_sample_period=dict(Start='2018-01-01T00:00:00Z',\n",
      "    >>>                        End='2018-01-01T12:00:00Z'))\n",
      "    >>> spy.pull(signals,\n",
      "    >>>          start='2018-01-01T00:00:00Z',\n",
      "    >>>          end='2018-01-01T23:00:00Z',\n",
      "    >>>          grid='auto')\n",
      "    \n",
      "    Pull a list of signals, conditions or scalars from a Seeq worksheet with an auto-calculated grid\n",
      "    >>> my_worksheet_items = spy.pull(\n",
      "    >>> 'https://seeq.com/workbook/17F31703-F0B6-4C8E-B7FD-E20897BD4819/worksheet/CE6A0B92-EE00-45FC-9EB3-D162632DBB48',\n",
      "    >>>  grid='auto')\n",
      "    \n",
      "    Pull a list of capsules\n",
      "    \n",
      "    >>> compressor_on_high = spy.search({'Name': 'Compressor Power on High', 'Workbook': 'Folder 1 >> Workbook 8'})\n",
      "    >>> spy.pull(compressor_on_high, start='2019-01-01T04:00:00Z', end='2019-01-09T02:00:00Z')\n",
      "    \n",
      "    Pull a list of capsules but apply a condition function in formula first\n",
      "    \n",
      "    >>> comp_high = spy.search({'Name': 'Compressor Power on High', 'Workbook': 'Folder 1 >> Workbook 8'})\n",
      "    >>> spy.pull(comp_high, start='2019-01-01', end='2019-01-09', calculation='$condition.setMaximumDuration(1d)')\n",
      "    \n",
      "    Pull capsules as a binary signal at the specified grid. 1 when a capsule is\n",
      "    present, 0 otherwise\n",
      "    \n",
      "    >>> comp_high = spy.search({'Name': 'Compressor Power on High', 'Workbook': 'Folder 1 >> Workbook 8'})\n",
      "    >>> spy.pull(comp_high, start='2019-01-01T00:00:00Z', end='2019-01-01T12:00:00Z', shape='samples', grid='1h')\n",
      "    \n",
      "    Pull a scalar\n",
      "    \n",
      "    >>> compressor_power_limit = spy.push(\n",
      "    >>>     metadata=pd.DataFrame(\n",
      "    >>>         [{ 'Name': 'Compressor Power Limit', 'Type': 'Scalar', 'Formula': '50kW' }]), errors='raise')\n",
      "    >>> spy.pull(compressor_power_limit)\n",
      "    \n",
      "    Apply a calculation to a signal using the 'calculation' argument\n",
      "    \n",
      "    >>> signal_with_calc = spy.search({'Name': 'Area A_Temperature', 'Datasource Name': 'Example Data'})\n",
      "    >>> spy.pull(signal_with_calc,\n",
      "    >>>          start='2019-01-01T00:00:00',\n",
      "    >>>          end='2019-01-01T03:00:00',\n",
      "    >>>          calculation='$signal.aggregate(average(), hours(), startKey())', grid=None)\n",
      "    \n",
      "    Convert a linearly interpolated signal into a step interpolated signal\n",
      "    using the 'calculation' argument:\n",
      "    \n",
      "    >>> items = pd.DataFrame([{'ID': '8543F427-2963-4B4E-9825-220D9FDCAD4E', 'Type': 'CalculatedSignal'}])\n",
      "    >>> pull(items=items, start='2019-10-5', end='2019-10-6', grid='15min', calculation='$signal.toStep()')\n",
      "    \n",
      "    Interpolate data using the pandas.DataFrame.interpolate method with a\n",
      "    second order polynomial, with the signal name as the header. Warning:\n",
      "    pandas.interpolate can be considerably slower than Seeq's interpolation\n",
      "    functions for large datasets, especially when using complex interpolation\n",
      "    methods\n",
      "    \n",
      "    >>> search_df = pd.concat((spy.search({'ID': '6A5E44D4-C6C5-463F-827B-474AB051B2F5'}),\n",
      "    >>>                        spy.search({'ID': '937449C1-16E5-4E20-AC2E-632C5CECC24B'})), ignore_index=True)\n",
      "    >>> data_df = pull(search_df, grid=None, start='2019-10-5', end='2019-10-6', header='Name')\n",
      "    >>> data_df.interpolate(method='quadratic')\n",
      "\n"
     ]
    }
   ],
   "source": [
    "help(spy.pull)"
   ]
  }
 ],
 "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"
  },
  "pycharm": {
   "stem_cell": {
    "cell_type": "raw",
    "metadata": {
     "collapsed": false
    },
    "source": []
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
