Analysis Classes - Unified Interface to Analysis Results

MVG comes with a set of analysis classes which provide a unified interface to analysis results irrespective of the specific feature. Note that the analysis classes are helper classes, as such the mvg class does not depend on them.

Except for step (1) requesting the specific feature analysis, the following generic workflow holds:

  1. Request a specific analysis

  2. Retrieve results and parse them into an analysis_class object

  3. Use generic methods like plot(), summary() or to_df()

One application is to use the analysis classes interactively from a Python REPL session.

Or in (pseudo) code

result = parse_results(session.get_analysis_results(request_id))  # call API to get results
result.plot() # plot results
result.summary() # print summary table
df = result.to_df() # convert to DataFrame
result.save_pkl() # save to pickle file

Prerequisites

For running the examples in this notebook:

  1. Installed mvg package

  2. A token for API access from Viking Analytics

  3. The database needs to be populated with our example assets. This can be achieved by running the “Sources and Measurement” example.

Importing the required packages, classes and functions

[1]:
import os

from mvg import MVG, analysis_classes  # mvg library with python bindings to mvg-API
from mvg.analysis_classes import parse_results  # analysis classes

Create a Session and test API access

Note

Each token is used for Authorization AND Authentication. Thus, each unique token represents a unique user, each user has it own, unique database on the VA-MVG’ service.

You need to insert your token received from Viking Analytics here: Just replace "os.environ['TEST_TOKEN']" by your token as a string.

[2]:
# Replace by your own Token
TOKEN = os.environ["TEST_TOKEN"] # use our own token
ENDPOINT = "https://api.beta.multiviz.com"
[3]:
session = MVG(ENDPOINT, TOKEN)
session.check_version() # Check if API is accessible
[3]:
{'api_version': '0.3.3',
 'mvg_highest_tested_version': '0.3.3',
 'mvg_version': '0.12.2'}

Request an analysis

Once the API session is live, we start by checking if the source u0001 we will use is available in the database:

[4]:
SOURCE_ID = "u0001"
session.get_source(SOURCE_ID)
[4]:
{'source_id': 'u0001',
 'meta': {'assetId': 'assetJ',
  'measPoint': 'mloc01',
  'location': 'cancun',
  'timezone': 'Europe/Stockholm'},
 'properties': {'data_class': 'waveform', 'channels': ['acc']}}

We will now request an analysis (first two lines, uncomment one of them) and wait for the results to become available.

The results as returned will be stored in a dictionary named raw_result. The raw results are shown in the results cell, mainly to show that they are not optimized for readability or interpretation.

[5]:
# Specifc part : Select one of two analysis here by un/commenting
selected_feature = "KPIDemo"
# selected_feature = "ModeId"

# Generic Part: request analysis and wait for results
analysis_request = session.request_analysis(SOURCE_ID, selected_feature)
print(f"Waiting for {analysis_request}")
session.wait_for_analyses([analysis_request["request_id"]])

# Generic Part: Retrieve unparsed results
raw_result = session.get_analysis_results(analysis_request["request_id"])

Waiting for {'request_id': '9fa506fd651f10b05401840edf9f33cb', 'request_status': 'queued'}

Parse Results

Showing and Browsing the results using analysis_classes

To make the results more accessible, we’ll use the analysis_classes. The parse_results function will take the raw_results of (any) analysis and represent them in a python object with a number of convenience methods for summarising, plotting and exporting. For the full list of provided methods check the documentation.

The parse function will automatically determine the kind (feature) of analysis based on the raw_results. Once the results are parsed, we can summarize them using the summary() method irrespective of which analysis they stem from. To verify this you can rerun the cell above by selecting another feature for the analysis.

Timestamps

The Vibration API requires timestamps to be represented in EPOCH time. To display human interpertable timestamps, one needs a timezone and a time unit (specifying if the timestamps are seconds ‘s’ or milliseconds ‘ms’ from EPOCH). This information can be given in the parse_results calls (2nd and 3rd argument). If they are left blank EPOCH times are kept. When exporting the results to a DataFrame, a column called “datetime” will be appended to show the human interpretable times.

[6]:
# Parse
result = parse_results(raw_result, "Europe/Stockholm", "s")
# result = parse_results(raw_result) # show only raw timestamps
# Show summary
summary = result.summary()
=== KPIDemo ===
request_id 9fa506fd651f10b05401840edf9f33cb
from 20191004-13:01.00 to 20191122-13:01.00

+-------+--------------+------------+------------+-----------------+----------------+--------------------+-------------------+--------------------+
|       |   timestamps |    rms_acc |   peak_acc |   peak2peak_acc |   variance_acc |   crest_factor_acc |   utilization_acc |   dc_component_acc |
|-------+--------------+------------+------------+-----------------+----------------+--------------------+-------------------+--------------------|
| count | 50           | 50         |  50        |       50        |     50         |          50        |                50 |         50         |
| mean  |  1.57231e+09 |  0.611691  |   2.81764  |        5.40059  |      0.377299  |           4.62976  |                 1 |         -0.120874  |
| std   |  1.26105e+06 |  0.0565414 |   0.278079 |        0.378225 |      0.0636172 |           0.333367 |                 0 |          0.0141936 |
| min   |  1.57019e+09 |  0.484564  |   2.26056  |        4.55438  |      0.234802  |           4.12339  |                 1 |         -0.140524  |
| 25%   |  1.57125e+09 |  0.627912  |   2.68338  |        5.31364  |      0.394273  |           4.20402  |                 1 |         -0.140196  |
| 50%   |  1.57231e+09 |  0.628307  |   2.84999  |        5.52634  |      0.39477   |           4.80641  |                 1 |         -0.112316  |
| 75%   |  1.57337e+09 |  0.64684   |   3.06661  |        5.69377  |      0.418402  |           4.89065  |                 1 |         -0.10966   |
| max   |  1.57442e+09 |  0.647694  |   3.13609  |        5.79639  |      0.419507  |           4.99256  |                 1 |         -0.109065  |
+-------+--------------+------------+------------+-----------------+----------------+--------------------+-------------------+--------------------+

Use Generic Methods

Plotting

For visual representation of the results, there is the ‘plot’ method.

Please not that when plotting the results for the KPIDemo feature, one selects the KPI to be displayed by passing the parameter "kpi". If this parameter is not included, the plot function will display the results of the first column after the timestamps, which is the RMS value of the first channel.

[7]:
result.plot()
../../_images/content_examples_5-analysis_classes_13_0.png
[7]:
''

Export results to DataFrame

The to_df() method will export results to a DataFrame. Note that the format of the DataFrame depends on the specific analysis and that not all of the results can be represented as a data frame.

[8]:
result.to_df()
[8]:
timestamps rms_acc peak_acc peak2peak_acc variance_acc crest_factor_acc utilization_acc dc_component_acc datetime
0 1570186860 0.647086 2.686563 5.313293 0.418720 4.151786 1 -0.140237 2019-10-04 13:01:00+02:00
1 1570273260 0.647123 2.691750 5.367004 0.418769 4.159563 1 -0.140420 2019-10-05 13:01:00+02:00
2 1570359660 0.646619 2.715251 5.414856 0.418116 4.199152 1 -0.140239 2019-10-06 13:01:00+02:00
3 1570446060 0.646873 2.685147 5.351562 0.418445 4.150966 1 -0.140347 2019-10-07 13:01:00+02:00
4 1570532460 0.646643 2.726605 5.395325 0.418147 4.216556 1 -0.140423 2019-10-08 13:01:00+02:00
5 1570618860 0.646717 2.697001 5.310974 0.418243 4.170294 1 -0.140055 2019-10-09 13:01:00+02:00
6 1570705260 0.647093 2.711733 5.314697 0.418729 4.190640 1 -0.140505 2019-10-10 13:01:00+02:00
7 1570791660 0.647422 2.681256 5.325928 0.419155 4.141435 1 -0.140363 2019-10-11 13:01:00+02:00
8 1570878060 0.646890 2.667379 5.271362 0.418467 4.123387 1 -0.140524 2019-10-12 13:01:00+02:00
9 1570964460 0.647694 2.678755 5.379150 0.419507 4.169247 1 -0.140486 2019-10-13 13:01:00+02:00
10 1571050860 0.647081 2.722979 5.499878 0.418714 4.291424 1 -0.139850 2019-10-14 13:01:00+02:00
11 1571137260 0.647205 2.682736 5.299072 0.418874 4.145110 1 -0.140317 2019-10-15 13:01:00+02:00
12 1571223660 0.646743 2.682785 5.278564 0.418276 4.148148 1 -0.140365 2019-10-16 13:01:00+02:00
13 1571310060 0.647322 2.700798 5.424622 0.419026 4.207834 1 -0.140312 2019-10-17 13:01:00+02:00
14 1571396460 0.647434 2.721002 5.374634 0.419170 4.202750 1 -0.140069 2019-10-18 13:01:00+02:00
15 1571482860 0.647621 2.738182 5.366699 0.419413 4.228060 1 -0.140403 2019-10-19 13:01:00+02:00
16 1571569260 0.647111 2.692440 5.362610 0.418753 4.160706 1 -0.140071 2019-10-20 13:01:00+02:00
17 1571655660 0.484892 2.372010 4.607971 0.235120 4.891831 1 -0.114442 2019-10-21 13:01:00+02:00
18 1571742060 0.484841 2.273428 4.554382 0.235071 4.704542 1 -0.114736 2019-10-22 13:01:00+02:00
19 1571828460 0.484752 2.356562 4.664490 0.234984 4.861379 1 -0.114924 2019-10-23 13:01:00+02:00
20 1571914860 0.484564 2.367471 4.701599 0.234802 4.885779 1 -0.114846 2019-10-24 13:01:00+02:00
21 1572001260 0.485001 2.260560 4.652771 0.235226 4.932384 1 -0.114624 2019-10-25 13:01:00+02:00
22 1572087660 0.485013 2.301963 4.591980 0.235237 4.746192 1 -0.114586 2019-10-26 13:01:00+02:00
23 1572177660 0.485254 2.260858 4.618774 0.235472 4.859134 1 -0.114862 2019-10-27 13:01:00+01:00
24 1572264060 0.485157 2.336525 4.584412 0.235377 4.816021 1 -0.114540 2019-10-28 13:01:00+01:00
25 1572350460 0.627895 3.037107 5.601013 0.394252 4.836969 1 -0.109921 2019-10-29 13:01:00+01:00
26 1572436860 0.628139 3.069790 5.720886 0.394559 4.887119 1 -0.110074 2019-10-30 13:01:00+01:00
27 1572523260 0.628308 3.103501 5.754272 0.394771 4.939456 1 -0.109604 2019-10-31 13:01:00+01:00
28 1572609660 0.628020 3.032668 5.694519 0.394409 4.828938 1 -0.109878 2019-11-01 13:01:00+01:00
29 1572696060 0.628019 2.969318 5.649292 0.394408 4.728068 1 -0.109149 2019-11-02 13:01:00+01:00
30 1572782460 0.628283 3.029716 5.675476 0.394740 4.822214 1 -0.109794 2019-11-03 13:01:00+01:00
31 1572868860 0.628152 3.136087 5.711792 0.394575 4.992559 1 -0.109659 2019-11-04 13:01:00+01:00
32 1572955260 0.627966 3.123363 5.723633 0.394341 4.973780 1 -0.109508 2019-11-05 13:01:00+01:00
33 1573041660 0.627735 3.047385 5.654846 0.394052 4.854570 1 -0.110191 2019-11-06 13:01:00+01:00
34 1573128060 0.627870 3.134621 5.796387 0.394221 4.992468 1 -0.109597 2019-11-07 13:01:00+01:00
35 1573214460 0.628681 3.098128 5.695251 0.395239 4.927984 1 -0.109786 2019-11-08 13:01:00+01:00
36 1573300860 0.628127 3.069387 5.691528 0.394543 4.886571 1 -0.109670 2019-11-09 13:01:00+01:00
37 1573387260 0.628122 2.961798 5.575195 0.394537 4.715324 1 -0.110052 2019-11-10 13:01:00+01:00
38 1573473660 0.627780 3.072126 5.696533 0.394108 4.893636 1 -0.109663 2019-11-11 13:01:00+01:00
39 1573560060 0.627846 3.011650 5.716858 0.394191 4.796795 1 -0.109611 2019-11-12 13:01:00+01:00
40 1573646460 0.628536 2.978442 5.552795 0.395058 4.738696 1 -0.109851 2019-11-13 13:01:00+01:00
41 1573732860 0.628397 3.106778 5.705566 0.394883 4.943972 1 -0.109341 2019-11-14 13:01:00+01:00
42 1573819260 0.628307 3.093943 5.683105 0.394769 4.924257 1 -0.109263 2019-11-15 13:01:00+01:00
43 1573905660 0.628142 2.996528 5.589905 0.394563 4.770460 1 -0.109992 2019-11-16 13:01:00+01:00
44 1573992060 0.628540 3.012680 5.602417 0.395063 4.793137 1 -0.110092 2019-11-17 13:01:00+01:00
45 1574078460 0.628118 3.103921 5.717590 0.394532 4.941623 1 -0.109658 2019-11-18 13:01:00+01:00
46 1574164860 0.628429 3.058288 5.590271 0.394922 4.866564 1 -0.109374 2019-11-19 13:01:00+01:00
47 1574251260 0.628441 3.085465 5.767273 0.394938 4.909715 1 -0.109269 2019-11-20 13:01:00+01:00
48 1574337660 0.628601 3.049571 5.659180 0.395139 4.851366 1 -0.109081 2019-11-21 13:01:00+01:00
49 1574424060 0.627963 3.088068 5.777344 0.394337 4.917596 1 -0.109065 2019-11-22 13:01:00+01:00

Full results

In case the full server results are needed in the raw form they were returned, we can obtain them with the results() method:

[9]:
result.results();

Black Sheep Analysis example

The BlackSheep is a population analysis and has a somewhat different call signature as it requires a number of assets to be submitted to analysis.

[ ]:
# Specific signature for BlackSheep
POPULATION_SOURCES = ["u0001","u0002","u0003","u0004"]
analysis_request = session.request_population_analysis(POPULATION_SOURCES, "BlackSheep", parameters={"atypical_threshold": 0.15})

# Generic part to request analysis, same as above
print(f"Waiting for {analysis_request}")
session.wait_for_analyses([analysis_request["request_id"]])
raw_result = session.get_analysis_results(analysis_request["request_id"])
Waiting for {'request_id': 'e6a0938e5dd9128550f710ad0180d015', 'request_status': 'queued'}

Using the analysis classes

We use exactly the same code as above to inspect the results:

[ ]:
# Parse
blacksheep_result = analysis_classes.parse_results(raw_result, "Europe/Stockholm", "s")
# Show summary
blacksheep_result.summary()
blacksheep_result.plot()

Serializing

Finally, we can save the object including the results to pickle. If no name is given it is saved under the name "<request_id>.pkl".

[13]:
blacksheep_result.save_pkl()

Saving BlackSheep object to 9895be09684f27257096bd9d517a9680.pkl
[13]:
'9895be09684f27257096bd9d517a9680.pkl'