from seeq import spy
import pandas as pd
# Set the compatibility option so that you maximize the chance that SPy will remain compatible with your notebook/script
spy.options.compatibility = 193
# Log into Seeq Server if you're not using Seeq Data Lab:
spy.login(url='http://localhost:34216', credentials_file='../credentials.key', force=False)
spy.search
Finds signals (tags), conditions (with capsules), scalars (constants), assets or any other type of item that Seeq indexes or keeps track of.
You will generally use this command before executing spy.pull()
.
spy.search(query, all_properties=False, workbook='Data Lab >> Data Lab Analysis')
Query Syntax
The query
parameter is a dictionary of 'Property': 'Filter'
values that are applied using AND logic by Seeq Server. Let’s use the
following examples to illustrate the important parts:
spy.search({
'Name': 'Humid',
'Path': 'Example >> Cooling Tower 1'
})
This query returns anything with Humid
in its Name
property that
also lives somewhere under Example >> Cooling Tower 1
in an asset
tree.
There are several capabilities and some constraints associated with querying:
The
Name
andDescription
properties are queried upon with the same wildcard and RegEx support as the Data tab in Seeq Workbench.The
Path
property is a virtual property that specifies the path through an asset tree from its root, with>>
as delimiters for each level in the asset tree.The returned
Asset
property is just the leaf asset node in the tree. It can only be used in tandem with thePath
property.For the
Type
property, you can specify justSignal
,Condition
orScalar
if you want to return both stored and calculated items.You can specify
Datasource Name
or you can specify bothDatasource ID
andDatasource Class
to differentiate between datasources with the same name.You can filter on
Data ID
, which is a unique identifier that is generally the same across instances of Seeq Server.You can filter on
Archived
andCache Enabled
using eitherTrue
orFalse
Python boolean values.
Retrieving all properties
spy.search()
only returns a subset of item properties as can be seen
in the output above. If you want to retrieve all properties, use
all_properties=True
. Note that when interfacing with Seeq Server
version R61 and earlier, this can be an expensive (slow) operation for
queries that return many rows. In R62 and later, this query has been
optimized to be much faster.
spy.search({
'Name': 'Area A_*Humid*',
'Datasource Name': 'Example Data'
}, all_properties=True)
You can also use the
include_properties=['Property Name 1', 'Property Name 2']
argument
if you want to explicitly return certain properties.
Estimating signal sample period
The estimate_sample_period
parameter adds an
Estimated Sample Period
column with a value for each signal returned
in search query for a specified time frame. This period is calculated
using the estimateSamplePeriod()
Formula function.
spy.search({
'Name': 'Area ?_Compressor Stage',
'Datasource Name': 'Example Data'
}, estimate_sample_period=dict(Start='2019-01-01', End='2019-01-30'))
Workbook scoping
The workbook=<workbook_path>
parameter allows you to include items
in your results that are scoped to a particular workbook. If you exclude
the argument, then by default your search results will include both
globally-scoped items and workbook-scoped items from the Data Lab >>
Data Lab Analysis workbook (folder path delimiter by >>
, workbook
name at the end). This workbook generally will only exist if you have
previous called spy.push()
. This default behavior forces your
spy.push()
and subsequent spy.search()
activities to be
sandboxed, meaning that they will only be visible to you within a
particular workbook.
If you want all items regardless of scope, specify
workbook=spy.GLOBALS_AND_ALL_WORKBOOKS
.
If you want only globally-scoped items, specify
workbook=spy.GLOBALS_ONLY
.
Another option is to specify Scoped To
within your query block. You
must supply a Workbook ID – not a workbook path like the workbook
parameter. This approach will limit your search to just those items
scoped to a particular workbook (it will exclude globally-scoped
items).
DataFrame as input
Instead of a Python dictionary for the query
parameter, you can
supply a Pandas DataFrame.
This is generally useful when you have a DataFrame full of tag names but
don’t know the Seeq ID
value and therefore can’t retrieve data via
spy.pull()
. Calling spy.search(data_frame)
effectively “fills
in” the ID
field for you wherever possible.
The column headers specify the properties to search on and the column values specify the match criteria.
If you don’t specify wildcards or use a RegEx, the match must be exact.
(This behavior is in contrast to the dictionary case, where the
non-wildcard/RegEx match is a “contains” comparison.) It is assumed that
your DataFrame property values should match exactly so that you can have
a large set of items to query for and there won’t be ambiguity between
item names like F1843CC
and F1843CC.SP
.
my_items = pd.DataFrame({
'Name': [
'Area A_Temperature',
'Area B_Compressor Power',
'Optimize'
],
'Datasource Name': 'Example Data'
})
my_items
spy.search(my_items)
Notice that there are no results with Optimize
in the name because
it does not exactly match any items.
Workbench Analysis URL as input
Alternatively, you can supply the URL of a Workbench Analysis worksheet
to the query
parameter. The URL must be provided as a str
.
This is generally useful when you already have an Analysis worksheet loaded with signals, scalars or conditions and want to programmatically know what is loaded in that particular worksheet from Seeq Data Lab. A common scenario is that you want to pull all signals or conditions from a worksheet into the Data Lab notebook but you want to see first how many or which signals and conditions are loaded in that worksheet.
spy.search('http://localhost:34216/workbook/<workbookID>/worksheet/<worksheetID>')
Pickling
Sometimes a search is “expensive” and takes a long time to complete. In that case, it is common to “pickle” the resulting DataFrame for later use, like so:
my_items = spy.search({
'Name': 'Area ?_Compressor Stage',
'Datasource Name': 'Example Data'
}, estimate_sample_period=dict(Start='2019-01-01', End='2019-01-30'))
my_items.to_pickle('pickled_search.pkl')
Now you can “unpickle” the DataFrame and use it for a pull without incurring the cost of re-executing the search:
unpickled_search = pd.read_pickle('pickled_search.pkl')
You can access some of the original context of the search via the
spy
attribute of the unpickled DataFrame. For example, the
spy.status
tells you what queries were successful and what queries
failed.
unpickled_search.spy.status.df
Detailed Help
All SPy functions have detailed documentation to help you use them. Just
execute help(spy.<func>)
like you see below.
help(spy.search)