{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "ac1a007d",
   "metadata": {},
   "source": [
    "# R in Seeq Data Lab\n",
    "\n",
    "Seeq Data Lab now provides an R environment to leverage the R language for exploring and manipulating time series and industrial process data!"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fb3ef539-f86d-4813-9718-a09352629a4f",
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "# Get current R version\n",
    "R.version.string"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9289ba33",
   "metadata": {},
   "source": [
    "## Preloaded R packages\n",
    "\n",
    "Although Seeq Data Lab's **SPy** library is built using Python, it can be accessed in an R kernel of a Jupyter notebook with the help of the R package [reticulate](https://cran.r-project.org/web/packages/reticulate/index.html) which is a library that handles automatic R to Python conversion.\n",
    "\n",
    "Seeq Data Lab's R environment preloads the `reticulate` library behind the scenes whenver an R notebook is opened. Also preloaded is the [IRdisplay](https://cran.r-project.org/web/packages/IRdisplay/index.html) library which is a Jupyter front end interface for rich displays in an R kernel. By preloading these R packages, you do not have to execute `library(reticulate)` and `library(IRdisplay)` in a code cell. You can confirm these packages are loaded by executing `(.packages())` to list the currently loaded R packages"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d5fbd6cd",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Show loaded R libraries/packages\n",
    "print(.packages())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "301f3d4a",
   "metadata": {},
   "source": [
    "## Installing R packages\n",
    "\n",
    "Just as Seeq Data Lab's Python environment allows installation of Python packages to a local Data Lab project or globally for all Data Lab Projects (adminstrators only), R packages can also be installed locally and globally. \n",
    "\n",
    "To install an R package in a notebook cell, execute `install.packages('<pkg')` where \\<pkg\\> is the name of the R package. To install an R package in a Data Lab terminal, open a terminal and execute `R -e \"install.packages('<pkg>')\"`.\n",
    "\n",
    "To install an R package globally for all Data Lab projects (administrators only), in a notebook cell execute `install.packages('<pkg>', lib=Sys.getenv('R_LIBS_GLOBAL'))` or in a terminal: `R -e \"install.packages('<pkg>', lib=Sys.getenv('R_LIBS_GLOBAL'))\"`. The environment variable `R_LIBS_GLOBAL` stores the actual location of globally installed R packages: `/seeq/python/global-packages/R/global-library/4.0`\n",
    "\n",
    "\n",
    "The respective order of precedence for R library paths is the same as for Python: \n",
    "\n",
    "* local user install in a Data Lab project\n",
    "* global install across all Data Lab projects\n",
    "* local system (packages preinstalled by Seeq)\n",
    "\n",
    "The order and location of R package paths can be listed:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8662cadb",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Show order of library paths\n",
    "print(.libPaths())"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "12edcb2c",
   "metadata": {},
   "source": [
    "## Importing the SPy Module\n",
    "\n",
    "Although **SPy** is imported by default and you are pre-authenticated just as in a Seeq Data Lab Python notebook, you can optinally import it by executing: `spy <- import('seeq.spy')`.\n",
    "\n",
    "## SPy Commands\n",
    "\n",
    "Unlike a Seeq Data Lab Python environment where results from SPy commands are output in HTML format automatically, in the R environment, HTML responses can only be generated if the SPy status message is contained in the `display_html` method from the `IRDisplay` package. The examples below for the various SPy comamnds include the steps to create a SPy status object, supply it as a parameter in a SPy command, and wrap the status message in the `display_html` method. \n",
    "\n",
    "### SPy Status"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a44775a2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# SPy Import\n",
    "spy <- import('seeq.spy')\n",
    "\n",
    "# Set a SPy Status object to get back status string.\n",
    "status <- spy$Status()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a41fe13f",
   "metadata": {},
   "source": [
    "### SPy Login"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a6a76bb2",
   "metadata": {},
   "outputs": [],
   "source": [
    "# SPy Login\n",
    "spy$login(url='http://localhost:34216', credentials_file='../credentials.key', force=FALSE, status=status)\n",
    "\n",
    "# SPy status messages must be wrapped in display_html(status$message) to render in html\n",
    "display_html(status$message)\n",
    "\n",
    "# Confirm login by checking SPy user object is not NULL\n",
    "spy$user"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1d596811",
   "metadata": {},
   "source": [
    "### SPy Search"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ad30e313",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create Python dictinary object to store our search criteria\n",
    "py_search_dict <- dict('Name'='Compressor','Path'='Example >> Cooling Tower 1 >> Area A')\n",
    "\n",
    "# Run SPy.search query (named query parameter optional) and store into R data frame\n",
    "search_results <- spy$search(query=py_search_dict, status=status)\n",
    "\n",
    "# Display search status and results\n",
    "display_html(status$message)\n",
    "search_results\n",
    "\n",
    "# Summary of returned results\n",
    "str(search_results)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5e1ccb3c",
   "metadata": {},
   "source": [
    "### SPy Pull"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "93ff8989",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Pull data with SPy.pull using the search results and filtering on start and end dates, store into R data frame\n",
    "pull_results <- spy$pull(search_results, start='2019-01-01', end='2019-01-07', header='Name', status=status)\n",
    "\n",
    "# Display pull status and results\n",
    "display_html(status$message)\n",
    "head(pull_results,10)\n",
    "\n",
    "# Display values of first 5 rows of 'Compressor Power' column. Use backticks to access a column with space in its name \n",
    "head(pull_results$`Compressor Power`,5)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cc19d078",
   "metadata": {},
   "source": [
    "### SPy Push"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1c7d443f",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create an R vector for each row of capsule data\n",
    "operator <- c('Mark','Hedwig')\n",
    "cap_tz <- 'UTC'#'America/New_York'\n",
    "cap_start <- c(as.POSIXct('2019-01-01 09:00:00.000', tz=cap_tz), as.POSIXct('2019-01-02 09:00:00.000', tz=cap_tz))\n",
    "cap_end <- c(as.POSIXct('2019-01-01 17:00:00.000', tz=cap_tz), as.POSIXct('2019-01-02 17:00:00.000', tz=cap_tz))\n",
    "\n",
    "# Alternatively, create an R vector for each row of capsule data using pandas datetimes\n",
    "# pd <- import('pandas')\n",
    "# cap_start <- c(pd$to_datetime('2019-01-01T09:00:00.000Z'), pd$to_datetime('2019-01-02T09:00:00.000Z'))\n",
    "# cap_end <- c(pd$to_datetime('2019-01-01T17:00:00.000Z'), pd$to_datetime('2019-01-02T17:00:00.000Z'))\n",
    "\n",
    "# Create capsule data frame from the vectors\n",
    "capsule_data <- data.frame(cap_start, cap_end, operator)\n",
    "\n",
    "# Add column names to data frame\n",
    "colnames(capsule_data) <- c('Capsule Start', 'Capsule End', 'Operator On Duty')\n",
    "capsule_data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "33653ec0",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create an R data frame for capsule metadata values\n",
    "capsule_metadata <- data.frame('Operator Shifts3', 'Condition', '2d')\n",
    "\n",
    "# Add column names to metadata data frame\n",
    "colnames(capsule_metadata) = c('Name', 'Type', 'Maximum Duration')\n",
    "capsule_metadata"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0d11c892",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Push data with SPy.push supplying capsule data, its metadata and a Status object\n",
    "push_results <- spy$push(data=capsule_data, metadata=capsule_metadata, status=status)\n",
    "\n",
    "# Show push results and status message\n",
    "display_html(status$message)\n",
    "push_results"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a7e7d7af",
   "metadata": {},
   "source": [
    "### SPy Jobs"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6fc57b9e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Schedule this notebook for execution\n",
    "job_results <- spy$jobs$schedule('every 15 minutes', status=status)\n",
    "\n",
    "# # Show job results and status message\n",
    "display_html(status$message)\n",
    "job_results"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "df0eeabe",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Unschedule this notebook for execution\n",
    "spy$jobs$unschedule(status=status)\n",
    "\n",
    "# # Show job results and status message\n",
    "display_html(status$message)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "46be3312",
   "metadata": {},
   "source": [
    "### SPy Trees"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e32e5dfa",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Create a tree with a root asset\n",
    "my_tree = spy$assets$Tree('My Tree', workbook='My Workbook', status=status)\n",
    "\n",
    "# Show status message, results and assets as a dataframe\n",
    "display_html(status$message)\n",
    "my_tree\n",
    "my_tree$items()\n",
    "\n",
    "# Creating a Tree using CSV Files\n",
    "my_csv_tree = spy$assets$Tree('~/SPy Documentation/Support Files/spy_tree_example.csv', workbook='My Workbook', status=status)\n",
    "\n",
    "# Show status message, results and assets as a dataframe\n",
    "display_html(status$message)\n",
    "my_csv_tree\n",
    "my_csv_tree$items()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ddf0c1b6",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Insert an asset into a tree\n",
    "my_tree$insert(children='Cooling Tower 1', parent='My Tree', status=status)\n",
    "\n",
    "# Show status message, results, and dataframe\n",
    "display_html(status$message)\n",
    "my_tree\n",
    "my_tree$items()\n",
    "\n",
    "# Insert list of assets\n",
    "my_tree$insert(children=list('Area A', 'Area B', 'Area C'), parent='Cooling Tower 1', status=status)\n",
    "\n",
    "# Show status message, results, and dataframe\n",
    "display_html(status$message)\n",
    "my_tree\n",
    "my_tree$items()\n",
    "\n",
    "# Create Python dictinary object to store our search criteria\n",
    "py_search_dict <- dict('Name'='Area A_Temperature','Datasource Name'='Example Data')\n",
    "tree_search_results <- spy$search(py_search_dict, status=status)\n",
    "\n",
    "# Insert the assets from the search results into the tree\n",
    "my_tree$insert(children=tree_search_results, friendly_name='Temperature', parent='Area A', status=status)\n",
    "\n",
    "# Show status message, results, and dataframe\n",
    "display_html(status$message)\n",
    "my_tree\n",
    "my_tree$items()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "c94b0897",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Remove an asset\n",
    "my_tree$remove('Area B_Compressor Stage')\n",
    "\n",
    "# Show tree summary and visualization\n",
    "cat(my_tree$summarize())\n",
    "cat(my_tree$visualize())\n",
    "\n",
    "# Remove an asset with children\n",
    "my_tree$remove('Area B')\n",
    "cat(my_tree$visualize())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "532ef151",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Accidentally insert \"Area C_Temperature\" into Area A of My Tree.\n",
    "my_tree$insert(children=spy$search(dict('Name'='Area C_Temperature','Datasource Name'='Example Data')), \n",
    "               parent='Area A', status=status)\n",
    "display_html(status$message)\n",
    "cat(my_tree$visualize())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ffd8518e",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Move the tree\n",
    "my_tree$move(source='Area A >> Area C_Temperature', destination='Area C', status=status)\n",
    "display_html(status$message)\n",
    "cat(my_tree$visualize())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "900a7bbe",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Push the tree\n",
    "my_tree$push(status=status)\n",
    "display_html(status$message)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "66945a5c",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Push the CSV tree\n",
    "my_csv_tree$push(status=status)\n",
    "display_html(status$message)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9bc0274f",
   "metadata": {},
   "source": [
    "## Utilities\n",
    "\n",
    "Reticulate supports running Python code as a string using [py_run_string](https://rstudio.github.io/reticulate/reference/py_run.html) command. SPy commands can be run similarly."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "17c7e63d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Run arbitrary Python code \n",
    "py_run_string(\"from seeq import spy; user=spy.user;\")\n",
    "py$user"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2760e218",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Print documentation on SPy or any Python object\n",
    "py_help(spy$search)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "76cfea87",
   "metadata": {},
   "outputs": [],
   "source": [
    "# list installed packages\n",
    "installed.packages()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e218c3ef",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Get the installation path of an R package\n",
    "find.package(\"reticulate\")\n",
    "\n",
    "# Get the installed version of an R package\n",
    "packageVersion(\"reticulate\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "R",
   "language": "R",
   "name": "ir"
  },
  "language_info": {
   "codemirror_mode": "r",
   "file_extension": ".r",
   "mimetype": "text/x-r-source",
   "name": "R",
   "pygments_lexer": "r",
   "version": "4.2.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
