{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import pandas as pd\n",
    "\n",
    "from seeq import spy\n",
    "\n",
    "# Set the compatibility option so that you maximize the chance that SPy will remain compatible with your notebook/script\n",
    "spy.options.compatibility = 193"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Parameterized Jobs\n",
    "\n",
    "The simple scheduling methods described in [spy.jobs](../spy.jobs.ipynb) will often be adequate for your purposes.\n",
    "\n",
    "But in some scenarios, you may wish to run a suite of jobs across an asset group or some other set of items. For this you will use the `spy.jobs.push()` command.\n",
    "\n",
    "**This feature is only available for scheduling notebooks in Seeq Data Lab. You cannot use SPy to schedule content in Anaconda, AWS SageMaker, or any other Python environment.**"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Assemble a DataFrame with the Parameters\n",
    "\n",
    "Let's take the most common example, which is to schedule a series of jobs across a group of assets.\n",
    "\n",
    "Search for the assets:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black;text-align: left;\">Query successful</div><table style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE;\">Path</td><td style=\"background-color: #EEFFEE;\">Type</td><td style=\"background-color: #EEFFEE;\">Time</td><td style=\"background-color: #EEFFEE;\">Count</td><td style=\"background-color: #EEFFEE;\">Result</td></tr><tr style=\"background-color: #EEFFEE;\"><td>0</td><td>Example >> Cooling Tower 1</td><td>Asset</td><td>00:00:00.06</td><td>8</td><td>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>9604F1A2-83DC-4CC2-9E19-E2C440107376</td>\n",
       "      <td>Example</td>\n",
       "      <td>Cooling Tower 1</td>\n",
       "      <td>Area B</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Asset</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Example Data</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>3746E42D-E908-43E9-817D-5EC2E967B556</td>\n",
       "      <td>Example</td>\n",
       "      <td>Cooling Tower 1</td>\n",
       "      <td>Area C</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Asset</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Example Data</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>B37F77CF-8A7E-47E2-9C9E-EACF1A6913B3</td>\n",
       "      <td>Example</td>\n",
       "      <td>Cooling Tower 1</td>\n",
       "      <td>Area K</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Asset</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Example Data</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>870941BC-44F7-431E-9A88-AE6F00F02943</td>\n",
       "      <td>Example</td>\n",
       "      <td>Cooling Tower 1</td>\n",
       "      <td>Area H</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Asset</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Example Data</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>313873A3-0663-4211-8395-ED6E45F3BE0D</td>\n",
       "      <td>Example</td>\n",
       "      <td>Cooling Tower 1</td>\n",
       "      <td>Area J</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Asset</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Example Data</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>74C5B89C-B6C1-47D8-9D97-07F713D6B878</td>\n",
       "      <td>Example</td>\n",
       "      <td>Cooling Tower 1</td>\n",
       "      <td>Area A</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Asset</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Example Data</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>314FD40B-6AE2-4048-8E50-AA3948007CFF</td>\n",
       "      <td>Example</td>\n",
       "      <td>Cooling Tower 1</td>\n",
       "      <td>Area I</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Asset</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Example Data</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>E833113C-A16F-4128-B550-267A553AA026</td>\n",
       "      <td>Example</td>\n",
       "      <td>Cooling Tower 1</td>\n",
       "      <td>Area G</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Asset</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Example Data</td>\n",
       "      <td>False</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                     ID     Path            Asset    Name  \\\n",
       "0  9604F1A2-83DC-4CC2-9E19-E2C440107376  Example  Cooling Tower 1  Area B   \n",
       "1  3746E42D-E908-43E9-817D-5EC2E967B556  Example  Cooling Tower 1  Area C   \n",
       "2  B37F77CF-8A7E-47E2-9C9E-EACF1A6913B3  Example  Cooling Tower 1  Area K   \n",
       "3  870941BC-44F7-431E-9A88-AE6F00F02943  Example  Cooling Tower 1  Area H   \n",
       "4  313873A3-0663-4211-8395-ED6E45F3BE0D  Example  Cooling Tower 1  Area J   \n",
       "5  74C5B89C-B6C1-47D8-9D97-07F713D6B878  Example  Cooling Tower 1  Area A   \n",
       "6  314FD40B-6AE2-4048-8E50-AA3948007CFF  Example  Cooling Tower 1  Area I   \n",
       "7  E833113C-A16F-4128-B550-267A553AA026  Example  Cooling Tower 1  Area G   \n",
       "\n",
       "   Description   Type  Value Unit Of Measure Datasource Name  Archived  \n",
       "0          NaN  Asset                    NaN    Example Data     False  \n",
       "1          NaN  Asset                    NaN    Example Data     False  \n",
       "2          NaN  Asset                    NaN    Example Data     False  \n",
       "3          NaN  Asset                    NaN    Example Data     False  \n",
       "4          NaN  Asset                    NaN    Example Data     False  \n",
       "5          NaN  Asset                    NaN    Example Data     False  \n",
       "6          NaN  Asset                    NaN    Example Data     False  \n",
       "7          NaN  Asset                    NaN    Example Data     False  "
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "schedule_df = spy.search({\n",
    "    'Path': 'Example >> Cooling Tower 1',\n",
    "    'Type': 'Asset'\n",
    "})\n",
    "schedule_df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now add a `Schedule` column, which will dictate how often the script will run.\n",
    "\n",
    "For intervals more frequent than 1 hour, it is highly recommended that you use intervals for which an hour is cleanly divisible like '15 minutes', '20 minutes' or '30 minutes'."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "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>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",
       "      <th>Schedule</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>9604F1A2-83DC-4CC2-9E19-E2C440107376</td>\n",
       "      <td>Example</td>\n",
       "      <td>Cooling Tower 1</td>\n",
       "      <td>Area B</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Asset</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Example Data</td>\n",
       "      <td>False</td>\n",
       "      <td>every 6 hours</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>3746E42D-E908-43E9-817D-5EC2E967B556</td>\n",
       "      <td>Example</td>\n",
       "      <td>Cooling Tower 1</td>\n",
       "      <td>Area C</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Asset</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Example Data</td>\n",
       "      <td>False</td>\n",
       "      <td>every 6 hours</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>B37F77CF-8A7E-47E2-9C9E-EACF1A6913B3</td>\n",
       "      <td>Example</td>\n",
       "      <td>Cooling Tower 1</td>\n",
       "      <td>Area K</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Asset</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Example Data</td>\n",
       "      <td>False</td>\n",
       "      <td>every 6 hours</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>870941BC-44F7-431E-9A88-AE6F00F02943</td>\n",
       "      <td>Example</td>\n",
       "      <td>Cooling Tower 1</td>\n",
       "      <td>Area H</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Asset</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Example Data</td>\n",
       "      <td>False</td>\n",
       "      <td>every 6 hours</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>313873A3-0663-4211-8395-ED6E45F3BE0D</td>\n",
       "      <td>Example</td>\n",
       "      <td>Cooling Tower 1</td>\n",
       "      <td>Area J</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Asset</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Example Data</td>\n",
       "      <td>False</td>\n",
       "      <td>every 6 hours</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>74C5B89C-B6C1-47D8-9D97-07F713D6B878</td>\n",
       "      <td>Example</td>\n",
       "      <td>Cooling Tower 1</td>\n",
       "      <td>Area A</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Asset</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Example Data</td>\n",
       "      <td>False</td>\n",
       "      <td>every 6 hours</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>314FD40B-6AE2-4048-8E50-AA3948007CFF</td>\n",
       "      <td>Example</td>\n",
       "      <td>Cooling Tower 1</td>\n",
       "      <td>Area I</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Asset</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Example Data</td>\n",
       "      <td>False</td>\n",
       "      <td>every 6 hours</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>E833113C-A16F-4128-B550-267A553AA026</td>\n",
       "      <td>Example</td>\n",
       "      <td>Cooling Tower 1</td>\n",
       "      <td>Area G</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Asset</td>\n",
       "      <td>NaN</td>\n",
       "      <td>Example Data</td>\n",
       "      <td>False</td>\n",
       "      <td>every 6 hours</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                     ID     Path            Asset    Name  \\\n",
       "0  9604F1A2-83DC-4CC2-9E19-E2C440107376  Example  Cooling Tower 1  Area B   \n",
       "1  3746E42D-E908-43E9-817D-5EC2E967B556  Example  Cooling Tower 1  Area C   \n",
       "2  B37F77CF-8A7E-47E2-9C9E-EACF1A6913B3  Example  Cooling Tower 1  Area K   \n",
       "3  870941BC-44F7-431E-9A88-AE6F00F02943  Example  Cooling Tower 1  Area H   \n",
       "4  313873A3-0663-4211-8395-ED6E45F3BE0D  Example  Cooling Tower 1  Area J   \n",
       "5  74C5B89C-B6C1-47D8-9D97-07F713D6B878  Example  Cooling Tower 1  Area A   \n",
       "6  314FD40B-6AE2-4048-8E50-AA3948007CFF  Example  Cooling Tower 1  Area I   \n",
       "7  E833113C-A16F-4128-B550-267A553AA026  Example  Cooling Tower 1  Area G   \n",
       "\n",
       "   Description   Type  Value Unit Of Measure Datasource Name  Archived  \\\n",
       "0          NaN  Asset                    NaN    Example Data     False   \n",
       "1          NaN  Asset                    NaN    Example Data     False   \n",
       "2          NaN  Asset                    NaN    Example Data     False   \n",
       "3          NaN  Asset                    NaN    Example Data     False   \n",
       "4          NaN  Asset                    NaN    Example Data     False   \n",
       "5          NaN  Asset                    NaN    Example Data     False   \n",
       "6          NaN  Asset                    NaN    Example Data     False   \n",
       "7          NaN  Asset                    NaN    Example Data     False   \n",
       "\n",
       "        Schedule  \n",
       "0  every 6 hours  \n",
       "1  every 6 hours  \n",
       "2  every 6 hours  \n",
       "3  every 6 hours  \n",
       "4  every 6 hours  \n",
       "5  every 6 hours  \n",
       "6  every 6 hours  \n",
       "7  every 6 hours  "
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "schedule_df['Schedule'] = 'every 6 hours'\n",
    "schedule_df"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can also use Quartz Cron expressions in place of the natural language phrasing above by using the [Online Cron Expression Generator](https://www.freeformatter.com/cron-expression-generator-quartz.html). As an example, the equivalent Quartz Cron expression for \"every 6 hours\" is `0 0 0/6 ? * * *`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Sort your Schedule DataFrame\n",
    "\n",
    "It's important to sort the DataFrame so that the ordering of the items is not dependent on how the constituent data happened to be returned by Seeq or any other data source."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "# If you have an ID column, it's easiest to sort by that. Otherwise pick something that\n",
    "# will result in consistent ordering\n",
    "schedule_df.sort_values('ID', inplace=True, ignore_index=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Push the jobs to Seeq\n",
    "\n",
    "The final step is to push the schedule DataFrame to Seeq so that it can schedule the jobs.\n",
    "\n",
    "It's often desirable to \"spread out\" the execution of the jobs so that they don't all execute simultaneously. In this example, we're executing the jobs every 6 hours and we've asked `spy.jobs.push()` to spread them out evenly over those 6 hours. (In general, the `spread` parameter is the same as the frequency of your schedule since you want all the jobs to execute within the time interval allocated.)\n",
    "\n",
    "Execute the following cell (only) to schedule the set of jobs."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black;text-align: left;\">Scheduled the notebook <strong>SPy Documentation/Parameterized Jobs.ipynb</strong> successfully.<br>Current context is <strong>INTERACTIVE</strong>.<br>Parameters returned are for DataFrame row index <strong>1</strong>. To change the DataFrame row returned in the INTERACTIVE context, add/change the <code>interactive_index</code> argument.</div><table style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE;\">ID</td><td style=\"background-color: #EEFFEE;\">Path</td><td style=\"background-color: #EEFFEE;\">Asset</td><td style=\"background-color: #EEFFEE;\">Name</td><td style=\"background-color: #EEFFEE;\">Description</td><td style=\"background-color: #EEFFEE;\">Type</td><td style=\"background-color: #EEFFEE;\">Value Unit Of Measure</td><td style=\"background-color: #EEFFEE;\">Datasource Name</td><td style=\"background-color: #EEFFEE;\">Archived</td><td style=\"background-color: #EEFFEE;\">Schedule</td><td style=\"background-color: #EEFFEE;\">Scheduled</td><td style=\"background-color: #EEFFEE;\">Next Run</td></tr><tr style=\"background-color: #EEFFEE;\"><td>0</td><td>313873A3-0663-4211-8395-ED6E45F3BE0D</td><td>Example</td><td>Cooling Tower 1</td><td>Area J</td><td>nan</td><td>Asset</td><td>nan</td><td>Example Data</td><td>False</td><td>every 6 hours</td><td>Every 6 hours</td><td>2021-01-30 12:00:00 PST</td></tr><tr style=\"background-color: #EEFFEE;\"><td>1</td><td>314FD40B-6AE2-4048-8E50-AA3948007CFF</td><td>Example</td><td>Cooling Tower 1</td><td>Area I</td><td>nan</td><td>Asset</td><td>nan</td><td>Example Data</td><td>False</td><td>every 6 hours</td><td>At 45 minutes past the hour, every 6 hours</td><td>2021-01-30 12:45:00 PST</td></tr><tr style=\"background-color: #EEFFEE;\"><td>2</td><td>3746E42D-E908-43E9-817D-5EC2E967B556</td><td>Example</td><td>Cooling Tower 1</td><td>Area C</td><td>nan</td><td>Asset</td><td>nan</td><td>Example Data</td><td>False</td><td>every 6 hours</td><td>At 30 minutes past the hour, every 6 hours, starting at 01:00 AM</td><td>2021-01-30 13:30:00 PST</td></tr><tr style=\"background-color: #EEFFEE;\"><td>3</td><td>74C5B89C-B6C1-47D8-9D97-07F713D6B878</td><td>Example</td><td>Cooling Tower 1</td><td>Area A</td><td>nan</td><td>Asset</td><td>nan</td><td>Example Data</td><td>False</td><td>every 6 hours</td><td>At 15 minutes past the hour, every 6 hours, starting at 02:00 AM</td><td>2021-01-30 14:15:00 PST</td></tr><tr style=\"background-color: #EEFFEE;\"><td>4</td><td>870941BC-44F7-431E-9A88-AE6F00F02943</td><td>Example</td><td>Cooling Tower 1</td><td>Area H</td><td>nan</td><td>Asset</td><td>nan</td><td>Example Data</td><td>False</td><td>every 6 hours</td><td>Every 6 hours, starting at 03:00 AM</td><td>2021-01-30 15:00:00 PST</td></tr><tr style=\"background-color: #EEFFEE;\"><td>5</td><td>9604F1A2-83DC-4CC2-9E19-E2C440107376</td><td>Example</td><td>Cooling Tower 1</td><td>Area B</td><td>nan</td><td>Asset</td><td>nan</td><td>Example Data</td><td>False</td><td>every 6 hours</td><td>At 45 minutes past the hour, every 6 hours, starting at 03:00 AM</td><td>2021-01-30 15:45:00 PST</td></tr><tr style=\"background-color: #EEFFEE;\"><td>6</td><td>B37F77CF-8A7E-47E2-9C9E-EACF1A6913B3</td><td>Example</td><td>Cooling Tower 1</td><td>Area K</td><td>nan</td><td>Asset</td><td>nan</td><td>Example Data</td><td>False</td><td>every 6 hours</td><td>At 30 minutes past the hour, every 6 hours, starting at 04:00 AM</td><td>2021-01-30 16:30:00 PST</td></tr><tr style=\"background-color: #EEFFEE;\"><td>7</td><td>E833113C-A16F-4128-B550-267A553AA026</td><td>Example</td><td>Cooling Tower 1</td><td>Area G</td><td>nan</td><td>Asset</td><td>nan</td><td>Example Data</td><td>False</td><td>every 6 hours</td><td>At 15 minutes past the hour, every 6 hours, starting at 05:00 AM</td><td>2021-01-30 17:15:00 PST</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "parameters = spy.jobs.push(schedule_df, spread='6 hours', interactive_index=1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you are a Seeq administrator, you can view these jobs by going to the _Administration_ page and clicking on the _Jobs_ tab. You will need to clear the _Groups_ filter to see the Notebook jobs.\n",
    "\n",
    "In the output of the cell above, you'll notice that the current context is **INTERACTIVE**, which is the term we use for the scenario where you are executing cells in the workbook yourself via the Seeq Data Lab user interface. When you open an HTML file in the `_Job Results` folder, you'll see that the same cell shows the current context as **JOB**. \n",
    "\n",
    "In the JOB context, `parameters` will be the row of the DataFrame that pertains to that job instance. In the INTERACTIVE context, `parameters` will be the row that corresponds to `interactive_index`."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "***We unschedule the jobs here so that your Seeq Data Lab isn't loaded down with executing this tutorial.***"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div style=\"background-color: #EEFFEE;color:black;text-align: left;\">Unscheduled the notebook <strong>SPy Documentation/Parameterized Jobs.ipynb</strong> successfully.</div>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "spy.jobs.unschedule()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Do something cool\n",
    "\n",
    "Now, based on the parameters in `parameters`, you can do something interesting. In this example we'll push a condition to a new (small) asset tree."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "ID                       314FD40B-6AE2-4048-8E50-AA3948007CFF\n",
       "Path                                                  Example\n",
       "Asset                                         Cooling Tower 1\n",
       "Name                                                   Area I\n",
       "Description                                               NaN\n",
       "Type                                                    Asset\n",
       "Value Unit Of Measure                                     NaN\n",
       "Datasource Name                                  Example Data\n",
       "Archived                                                False\n",
       "Schedule                                        every 6 hours\n",
       "Name: 1, dtype: object"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "parameters"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's pretend that we have a spiffy algorithm that can determine the health of our asset by looking at a couple of signals.\n"
   ]
  },
  {
   "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>2021-01-30 18:37:54.029697+00:00</strong> to <strong>2021-01-30 19:37:54.029697+00:00</strong></div><table style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE;\">ID</td><td style=\"background-color: #EEFFEE;\">Path</td><td style=\"background-color: #EEFFEE;\">Asset</td><td style=\"background-color: #EEFFEE;\">Name</td><td style=\"background-color: #EEFFEE;\">Count</td><td style=\"background-color: #EEFFEE;\">Time</td><td style=\"background-color: #EEFFEE;\">Result</td></tr><tr style=\"background-color: #EEFFEE;\"><td>0</td><td>2465C53D-13C6-4052-B1EC-F07EDF4C1BCA</td><td>Example >> Cooling Tower 1</td><td>Area I</td><td>Temperature</td><td>4</td><td>00:00:00.05</td><td>Success</td></tr></table>"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "health_data_df = spy.pull(spy.search({\n",
    "    'Asset': parameters['ID'],\n",
    "    'Name': 'Temperature'\n",
    "}), header='Name')\n",
    "\n",
    "health_indicator = health_data_df.mean()['Temperature']\n",
    "health_status = 'HEALTHY' if health_indicator > 80 else 'UNHEALTHY'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "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>Path</th>\n",
       "      <th>Asset</th>\n",
       "      <th>Name</th>\n",
       "      <th>Type</th>\n",
       "      <th>Maximum Duration</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Parameterized Jobs Tutorial</td>\n",
       "      <td>Area I</td>\n",
       "      <td>Job Executions</td>\n",
       "      <td>Condition</td>\n",
       "      <td>1h</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                          Path   Asset            Name       Type  \\\n",
       "0  Parameterized Jobs Tutorial  Area I  Job Executions  Condition   \n",
       "\n",
       "  Maximum Duration  \n",
       "0               1h  "
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "metadata_df = pd.DataFrame([{\n",
    "    'Path': 'Parameterized Jobs Tutorial',\n",
    "    'Asset': f'{parameters[\"Name\"]}',\n",
    "    'Name': 'Job Executions',\n",
    "    'Type': 'Condition',\n",
    "    'Maximum Duration': '1h'\n",
    "}])\n",
    "metadata_df"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "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>Capsule Start</th>\n",
       "      <th>Capsule End</th>\n",
       "      <th>Health</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>2021-01-30 19:37:54.193108</td>\n",
       "      <td>2021-01-30 19:42:54.193187</td>\n",
       "      <td>UNHEALTHY</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "               Capsule Start                Capsule End     Health\n",
       "0 2021-01-30 19:37:54.193108 2021-01-30 19:42:54.193187  UNHEALTHY"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import datetime\n",
    "\n",
    "start = datetime.datetime.now().isoformat()\n",
    "end = (datetime.datetime.now() + datetime.timedelta(minutes=5)).isoformat()\n",
    "capsule_data = pd.DataFrame([{\n",
    "    'Capsule Start': pd.to_datetime(start),\n",
    "    'Capsule End': pd.to_datetime(end),\n",
    "    'Health': health_status\n",
    "}])\n",
    "capsule_data"
   ]
  },
  {
   "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>68AFB173-CE9D-4D7A-92C0-A1D1C800C0B7</strong><br>Click the following link to see what you pushed in Seeq:<br><a href=\"http://172.17.0.1:34216/6CA557A9-2E1A-44C7-91DB-2E7452EFEA6D/workbook/68AFB173-CE9D-4D7A-92C0-A1D1C800C0B7/worksheet/5D7F9FC9-5411-496D-90BE-8648600F6AA7\" target=\"_new\">http://172.17.0.1:34216/6CA557A9-2E1A-44C7-91DB-2E7452EFEA6D/workbook/68AFB173-CE9D-4D7A-92C0-A1D1C800C0B7/worksheet/5D7F9FC9-5411-496D-90BE-8648600F6AA7</a></div><table style=\"color:black;\"><tr><td style=\"background-color: #EEFFEE;\"></td><td style=\"background-color: #EEFFEE;\">ID</td><td style=\"background-color: #EEFFEE;\">Path</td><td style=\"background-color: #EEFFEE;\">Asset</td><td style=\"background-color: #EEFFEE;\">Name</td><td style=\"background-color: #EEFFEE;\">Count</td><td style=\"background-color: #EEFFEE;\">Time</td><td style=\"background-color: #EEFFEE;\">Result</td></tr><tr style=\"background-color: #EEFFEE;\"><td>0</td><td>B8275661-1F3A-412A-9DC3-81CEE3A4F545</td><td>Parameterized Jobs Tutorial</td><td>Area I</td><td>Job Executions</td><td>1</td><td>00:00:00.01</td><td>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>Path</th>\n",
       "      <th>Asset</th>\n",
       "      <th>Name</th>\n",
       "      <th>Type</th>\n",
       "      <th>Maximum Duration</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",
       "      <th>Push Count</th>\n",
       "      <th>Push Time</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>Parameterized Jobs Tutorial</td>\n",
       "      <td>Area I</td>\n",
       "      <td>Job Executions</td>\n",
       "      <td>StoredCondition</td>\n",
       "      <td>1h</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>Seeq Data Lab</td>\n",
       "      <td>[68AFB173-CE9D-4D7A-92C0-A1D1C800C0B7] {Condit...</td>\n",
       "      <td>B8275661-1F3A-412A-9DC3-81CEE3A4F545</td>\n",
       "      <td>Success</td>\n",
       "      <td>1</td>\n",
       "      <td>0:00:00.014904</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                          Path   Asset            Name             Type  \\\n",
       "0  Parameterized Jobs Tutorial  Area I  Job Executions  StoredCondition   \n",
       "\n",
       "  Maximum Duration Datasource Class  Datasource ID  \\\n",
       "0               1h    Seeq Data Lab  Seeq Data Lab   \n",
       "\n",
       "                                             Data ID  \\\n",
       "0  [68AFB173-CE9D-4D7A-92C0-A1D1C800C0B7] {Condit...   \n",
       "\n",
       "                                     ID Push Result  Push Count  \\\n",
       "0  B8275661-1F3A-412A-9DC3-81CEE3A4F545     Success           1   \n",
       "\n",
       "        Push Time  \n",
       "0  0:00:00.014904  "
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "spy.push(capsule_data, metadata=metadata_df)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Scheduling from a separate notebook\n",
    "\n",
    "The `spy.jobs.push()` function accepts a `datalab_notebook_url` parameter, so that a job can be pushed to another notebook to which you have access.  A common use case for this would be to enable a user of an Add-on Mode notebook to configure a scheduled notebook through form input.  In such a scenario, the parameters specified by completion of the form would need to be passed to the scheduled notebook."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "path_to_here = '/notebooks/SPy%20Documentation/Advanced%20Scheduling/Parameterized%20Jobs.ipynb'\n",
    "this_notebook_url = f'{spy.utils.get_data_lab_project_url()}{path_to_here}'\n",
    "spy.jobs.push(schedule_df, spread='6 hours', datalab_notebook_url=this_notebook_url)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "No additional work is needed to ensure the parameters are available in the target Notebook. The `schedule_df` used in the call to `spy.jobs.push()` is automatically pickled to a .pkl file in the `_Job DataFrames` folder of the Notebook being scheduled.  To retrieve the parameters for a specific job in the jobs DataFrame from the scheduled Notebook, just call `spy.jobs.pull()`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "parameters = spy.jobs.pull(interactive_index=1)\n",
    "parameters"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The **JOB** and **INTERACTIVE** contexts still apply as described earlier in this tutorial. Use the `interactive_index` to control which row is returned by `spy.jobs.pull()` in the interactive context."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The `push` and `pull` methods can both be used with an additional `label` argument, which is useful for enabling reuse of a single Notebook with different parameters.  For example, if it is desired to have one schedule per user for a given notebook, the user's ID could be used as a label.  This will ensure that two distinct users can schedule the same notebook, possibly with distinct parameters created from a separate notebook or from another application, without unscheduling the other user's jobs.\n",
    "\n",
    "Another use for a label would be enabling the scheduling of a single notebook from different Workbench Analyses using\n",
    " an Add-on Tool.  In this case, a convenient label would be an encoding of the Workbook and Worksheet IDs of the origin\n",
    " worksheet, e.g., `workbookId=77953A64-0675-47AE-826F-DEE1FD7AB4C5&worksheetId=5C83DF79-D725-4756-BBE6-4D2D1525D4FF`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.11",
   "language": "python",
   "name": "python311"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
