Skip to content
Snippets Groups Projects
Commit 228b36a0 authored by Stefano Di Frischia's avatar Stefano Di Frischia
Browse files

Merge branch 'L2SS-235-Archive-PCC-attribute' into 'master'

Resolve L2SS-235 "Archive pcc attribute"

Closes L2SS-235 and L2SS-236

See merge request !108
parents 8f3a8dd7 e3e8a68c
Branches
Tags
1 merge request!108Resolve L2SS-235 "Archive pcc attribute"
# Tango Archiving Framework
The Archiver class in archiver.py defines the methods to manage the device attributes archiving allowed by Tango.
The main components (and the relative Docker containers) are:
- Configuration Manager (container: hdbpp-cm): Device server that assists in adding, modifying, moving, deleting an Attribute to/from the archiving system
- Event Subscriber (container: hdbpp-es): The EventSubscriber TANGO device server, is the archiving system engine. On typical usage, it will subscribe to archive events on request by the ConfigurationManager device. The EventSubscriber is designed to start archiving all the already configured Attributes, even if the ConfigurationManager is not running. Moreover, being a TANGO device, the EventSubscriber configuration can be managed with Jive.
- Archiving DBMS (container: archiver-maria-db): Specific Database devoted to storing attribute values.
- (Optional) HDB++ Viewer (container: hdbpp-viewer): Standalone JAVA application designed to monitor signals coming from database
## Archiver creation
When an Archiver object is created, we can define three of its properties:
- the ConfigurationManager name (Tango namespace)
- at least one EventSubscriber name (Tango namespace)
- the default context archiving for the subscribers. This means that a default archiving strategy will be applied to
all the attributes. Of course this strategy can be tuned individually for each attribute if needed.
Archiving strategies are ['ALWAYS','RUN','SHUTDOWN','SERVICE']
- ALWAYS:always stored
- RUN:stored during run
- SHUTDOWN:stored during shutdown
- SERVICE:stored during maintenance activities
## Add an attribute
When adding an attribute to the archiving framework, we must define the following properties:
- the EventSubscriber name that will take charge of the attribute
- the archiving strategy (4 options defined above)
- the attribute polling period (it should have been already defined in TangoDB)
- the archive event period (MOST IMPORTANT, it defines the frequency rate at which an attribute is archived in the DBMS)
It is important to understand that, when an attribute is successfully added to the EventSubscriber list, the archiving begins without an explicit 'Start' command, rather it follows the archiving strategy already defined.
The 'Start' command is used instead during a session when an attribute has been paused/stopped for any reason, or it has raised some kind of issue.
## Difference between Stop and Remove an attribute
When stopping an attribute archiving, the framework does not remove it from the list.
This means that archiving is stopped for the current session, but if the device is restarted, the attribute archiving will be restarted as well.
In order to definitely stop the archiving, the attribute must be removed from the attribute list.
## Update an attribute
If we want to update the archiving properties of an attribute (e.g. the archive event period), there is a relative method.
It must be noted that the updating is not istantaneous because, following the framework architecture, an attribute must be first removed from the EventSubscriber list and then re-added with the new properties.
#! /usr/bin/env python3 #! /usr/bin/env python3
from logging import raiseExceptions
import traceback
from clients.attribute_wrapper import attribute_wrapper from clients.attribute_wrapper import attribute_wrapper
from tango import DeviceProxy from tango import DeviceProxy, AttributeProxy
from datetime import datetime, timedelta from datetime import datetime, timedelta
import time
from sqlalchemy import create_engine, and_ from sqlalchemy import create_engine, and_
from sqlalchemy.orm import sessionmaker from sqlalchemy.orm import sessionmaker
from .archiver_base import * from .archiver_base import *
...@@ -12,32 +15,216 @@ class Archiver(): ...@@ -12,32 +15,216 @@ class Archiver():
""" """
The Archiver class implements the basic operations to perform attributes archiving The Archiver class implements the basic operations to perform attributes archiving
""" """
def __init__(self, cm_name: str = 'archiving/hdbpp/confmanager01', es_name: str = 'archiving/hdbpp/eventsubscriber01'): def __init__(self, cm_name: str = 'archiving/hdbpp/confmanager01', es_name: str = 'archiving/hdbpp/eventsubscriber01', context: str = 'RUN'):
self.cm_name = cm_name self.cm_name = cm_name
self.cm = DeviceProxy(cm_name) self.cm = DeviceProxy(cm_name)
try:
cm_state = self.cm.state() # ping the device server
if cm_state is 'FAULT':
print('Configuration Manager is in FAULT state')
print(self.cm.status())
return
except:
print(traceback.format_exc())
return
self.es_name = es_name self.es_name = es_name
self.es = DeviceProxy(es_name) self.es = DeviceProxy(es_name)
self.cm.write_attribute('Context',context) # Set default Context Archiving for all the subscribers
def add_attribute_to_archiver(self, attribute: str, polling_period: float = 1000, event_period: float = 1000, strategy: str = 'ALWAYS'): def add_attribute_to_archiver(self, attribute_name: str, polling_period: int = 1000, event_period: int = 1000, strategy: str = 'RUN'):
""" """
Takes as input the attribute name, polling period (ms), event period (ms) and archiving strategy, Takes as input the attribute name, polling period (ms), event period (ms) and archiving strategy,
and adds the selected attribute to the subscriber's list of archiving attributes. and adds the selected attribute to the subscriber's list of archiving attributes.
The ConfigurationManager and EventSubscriber devices must be already up and running. The ConfigurationManager and EventSubscriber devices must be already up and running.
The archiving-DBMS must be already properly configured. The archiving-DBMS must be already properly configured.
""" """
self.cm.write_attribute('SetAttributeName', attribute) if (len(attribute_name.split('/'))!=4):
self.cm.write_attribute('SetArchiver', self.es_name) raise AttributeFormatException
self.cm.write_attribute('SetStrategy', strategy) try:
self.cm.write_attribute('SetPollingPeriod', int(polling_period)) self.cm.write_attribute('SetAttributeName', attribute_name)
self.cm.write_attribute('SetPeriodEvent', int(event_period)) self.cm.write_attribute('SetArchiver', self.es_name)
self.cm.AttributeAdd() self.cm.write_attribute('SetStrategy', strategy)
self.cm.write_attribute('SetPollingPeriod', polling_period)
self.cm.write_attribute('SetPeriodEvent', event_period)
self.cm.AttributeAdd()
print('Attribute %s added to archiving list!' % attribute_name)
except Exception as e:
if 'already archived' not in str(e).lower():
traceback.format_exc()
else:
print('Attribute %s already in archiving list!' % attribute_name)
def remove_attribute_from_archiver(self, attribute: str): def add_attributes_to_archiver(self,device_name,global_archive_period:int = None, exclude:list = ['Status','State']):
"""
Add sequentially all the attributes of the selected device in the event subscriber list, if not already present
"""
d = DeviceProxy(device_name)
attrs_list = list(d.get_attribute_list()) # cast to list otherwise removal is not allowed
try:
for a in exclude: attrs_list.remove(a)
except:
pass
for a in attrs_list:
attr_fullname = str(device_name+'/'+a).lower()
attr_proxy = AttributeProxy(attr_fullname)
if attr_proxy.is_polled() is True: # if not polled attribute is also not archived
try:
if self.es.AttributeList is None or not(self.cm.AttributeSearch(a)):
polling_period = attr_proxy.get_poll_period()
archive_period = global_archive_period or int(attr_proxy.get_property('archive_period')['archive_period'][0])
self.add_attribute_to_archiver(attr_fullname,polling_period=polling_period,
event_period=archive_period)
#time.sleep(0.5)
except:
print(traceback.format_exc())
def remove_attribute_from_archiver(self, attribute_name:str):
""" """
Stops the data archiving of the attribute passed as input, and remove it from the subscriber's list. Stops the data archiving of the attribute passed as input, and remove it from the subscriber's list.
""" """
self.cm.AttributeStop(attribute) if (len(attribute_name.split('/'))!=4):
self.cm.AttributeRemove(attribute) raise AttributeFormatException
try:
self.cm.AttributeStop(attribute_name)
self.cm.AttributeRemove(attribute_name)
print('Attribute %s removed!' % attribute_name)
except Exception as e:
if 'attribute not found' not in str(e).lower():
traceback.format_exc()
else:
print('Attribute %s not found!' % attribute_name)
def remove_attributes_by_device(self,device_name:str):
"""
Stops the data archiving of all the attributes of the selected device, and remove them from the
subscriber's list
"""
d = DeviceProxy(device_name)
attrs_list = d.get_attribute_list()
for a in attrs_list:
try:
attr_fullname = str(device_name+'/'+a).lower()
self.remove_attribute_from_archiver(attr_fullname)
except:
print(traceback.format_exc())
def start_archiving_attribute(self, attribute_name:str):
"""
Starts the archiving of the attribute passed as input.
The attribute must be already present in the subscriber's list
"""
if (len(attribute_name.split('/'))!=4):
raise AttributeFormatException
try:
self.cm.AttributeStart(attribute_name)
except Exception as e:
if 'attribute not found' not in str(e).lower():
traceback.format_exc()
else:
print('Attribute %s not found!' % attribute_name)
def stop_archiving_attribute(self, attribute_name:str):
"""
Stops the archiving of the attribute passed as input.
The attribute must be already present in the subscriber's list
"""
if (len(attribute_name.split('/'))!=4):
raise AttributeFormatException
try:
self.cm.AttributeStop(attribute_name)
except Exception as e:
if 'attribute not found' not in str(e).lower():
traceback.format_exc()
else:
print('Attribute %s not found!' % attribute_name)
def check_and_add_attribute_in_archiving_list(self, attribute_name:str):
"""
Check if an attribute is in the archiving list
"""
if (len(attribute_name.split('/'))!=4):
raise AttributeFormatException
# Add attribute if not present in event subscriber list
try:
if self.es.AttributeList is None or not(self.cm.AttributeSearch(attribute_name)):
self.add_attribute_to_archiver(attribute_name)
except:
print(traceback.format_exc())
return attribute_name
def update_archiving_attribute(self, attribute_name: str, polling_period: int = 1000, event_period: int = 1000, strategy: str = 'RUN'):
"""
Update the archiving properties of an attribute already in a subscriber list
"""
try:
self.remove_attribute_from_archiver(attribute_name)
time.sleep(1)
self.add_attribute_to_archiver(attribute_name,polling_period,event_period,strategy)
time.sleep(1)
self.start_archiving_attribute(attribute_name)
except:
print(traceback.format_exc())
def get_subscriber_attributes(self,es_name:str = None):
"""
Return the list of attributes managed by the event subscriber
"""
if es_name is not None:
es = DeviceProxy(es_name)
else:
es = self.es
attrs = es.AttributeList or []
return attrs
def get_subscriber_errors(self,es_name:str = None):
"""
Return a dictionary of the attributes currently in error, defined as AttributeName -> AttributeError
"""
if es_name is not None:
es = DeviceProxy(es_name)
else:
es = self.es
try:
attrs = es.AttributeList or []
errs = es.AttributeErrorList or []
return dict((a,e) for a,e in zip(attrs,errs) if e)
except:
print('No attribute errors in the subscriber')
return {}
def get_attribute_errors(self,attribute_name:str):
"""
Return the error related to the attribute
"""
if (len(attribute_name.split('/'))!=4):
raise AttributeFormatException
errs_dict = self.get_subscriber_errors()
for e in errs_dict:
if attribute_name in e:
return errs_dict.get(e)
return None
def get_subscriber_load(self,use_freq:bool=True,es_name:str = None):
"""
Return the estimated load of an archiver, in frequency of records or number
of attributes
"""
if es_name is not None:
es = DeviceProxy(es_name)
else:
es = self.es
if use_freq:
return str(es.AttributeRecordFreq)+(' events/period' )
else:
return len(es.AttributeList or [])
class AttributeFormatException(Exception):
"""
Exception that handles wrong attribute naming
"""
def __init__(self, message="Wrong Tango attribute format! Try: domain/family/member/attribute (e.g. LTS/PCC/1/temperature)"):
self.message = message
super().__init__(self.message)
class Retriever(): class Retriever():
""" """
......
...@@ -2,3 +2,5 @@ opcua >= 0.98.9 ...@@ -2,3 +2,5 @@ opcua >= 0.98.9
astropy astropy
python-logstash-async python-logstash-async
gitpython gitpython
PyMySQL[rsa]
sqlalchemy
%% Cell type:code id:3191bdf1 tags:
``` python
import sys, time
import numpy as np
sys.path.append('/hosthome/tango/devices')
from toolkit.archiver import Archiver,Retriever
from toolkit.archiver_base import *
from matplotlib import pyplot as plt
```
%% Cell type:code id:e2d12232 tags:
``` python
from common.lofar_environment import isProduction
print(isProduction())
```
%% Output
True
%% Cell type:code id:81e08b9f tags:
``` python
archiver = Archiver()
archiver.get_subscriber_attributes()
```
%% Output
[]
%% Cell type:code id:884ff1ff tags:
``` python
device_name = 'LTS/PCC/1'
d=DeviceProxy(device_name)
state = str(d.state())
print(state)
```
%% Output
OFF
%% Cell type:code id:0f6e65b0 tags:
``` python
# Start the device
if state == "OFF":
if isProduction():
archiver.add_attributes_to_archiver(device_name,global_archive_period=1000)
else:
archiver.remove_attributes_by_device(device_name)
time.sleep(1)
d.initialise()
time.sleep(1)
state = str(d.state())
if state == "STANDBY":
d.on()
state = str(d.state())
if state == "ON":
print("Device is now in ON state")
```
%% Output
Attribute lts/pcc/1/ant_mask_rw added to archiving list!
Attribute lts/pcc/1/clk_enable_pwr_r added to archiving list!
Attribute lts/pcc/1/clk_i2c_status_r added to archiving list!
Attribute lts/pcc/1/clk_pll_error_r added to archiving list!
Attribute lts/pcc/1/clk_pll_locked_r added to archiving list!
Attribute lts/pcc/1/clk_monitor_rate_rw added to archiving list!
Attribute lts/pcc/1/clk_translator_busy_r added to archiving list!
Attribute lts/pcc/1/hba_element_beamformer_delays_r added to archiving list!
Attribute lts/pcc/1/hba_element_beamformer_delays_rw added to archiving list!
Attribute lts/pcc/1/hba_element_led_r added to archiving list!
Attribute lts/pcc/1/hba_element_led_rw added to archiving list!
Attribute lts/pcc/1/hba_element_lna_pwr_r added to archiving list!
Attribute lts/pcc/1/hba_element_lna_pwr_rw added to archiving list!
Attribute lts/pcc/1/hba_element_pwr_r added to archiving list!
Attribute lts/pcc/1/hba_element_pwr_rw added to archiving list!
Attribute lts/pcc/1/rcu_adc_lock_r added to archiving list!
Attribute lts/pcc/1/rcu_attenuator_r added to archiving list!
Attribute lts/pcc/1/rcu_attenuator_rw added to archiving list!
Attribute lts/pcc/1/rcu_band_r added to archiving list!
Attribute lts/pcc/1/rcu_band_rw added to archiving list!
Attribute lts/pcc/1/rcu_i2c_status_r added to archiving list!
Attribute lts/pcc/1/rcu_id_r added to archiving list!
Attribute lts/pcc/1/rcu_led0_r added to archiving list!
Attribute lts/pcc/1/rcu_led0_rw added to archiving list!
Attribute lts/pcc/1/rcu_led1_r added to archiving list!
Attribute lts/pcc/1/rcu_led1_rw added to archiving list!
Attribute lts/pcc/1/rcu_mask_rw added to archiving list!
Attribute lts/pcc/1/rcu_monitor_rate_rw added to archiving list!
Attribute lts/pcc/1/rcu_pwr_dig_r added to archiving list!
Attribute lts/pcc/1/rcu_temperature_r added to archiving list!
Attribute lts/pcc/1/rcu_translator_busy_r added to archiving list!
Attribute lts/pcc/1/rcu_version_r added to archiving list!
Device is now in ON state
%% Cell type:code id:8efd3dc1 tags:
``` python
archiver.get_subscriber_attributes()
```
%% Output
('tango://databaseds:10000/lts/pcc/1/ant_mask_rw',
'tango://databaseds:10000/lts/pcc/1/clk_enable_pwr_r',
'tango://databaseds:10000/lts/pcc/1/clk_i2c_status_r',
'tango://databaseds:10000/lts/pcc/1/clk_pll_error_r',
'tango://databaseds:10000/lts/pcc/1/clk_pll_locked_r',
'tango://databaseds:10000/lts/pcc/1/clk_monitor_rate_rw',
'tango://databaseds:10000/lts/pcc/1/clk_translator_busy_r',
'tango://databaseds:10000/lts/pcc/1/hba_element_beamformer_delays_r',
'tango://databaseds:10000/lts/pcc/1/hba_element_beamformer_delays_rw',
'tango://databaseds:10000/lts/pcc/1/hba_element_led_r',
'tango://databaseds:10000/lts/pcc/1/hba_element_led_rw',
'tango://databaseds:10000/lts/pcc/1/hba_element_lna_pwr_r',
'tango://databaseds:10000/lts/pcc/1/hba_element_lna_pwr_rw',
'tango://databaseds:10000/lts/pcc/1/hba_element_pwr_r',
'tango://databaseds:10000/lts/pcc/1/hba_element_pwr_rw',
'tango://databaseds:10000/lts/pcc/1/rcu_adc_lock_r',
'tango://databaseds:10000/lts/pcc/1/rcu_attenuator_r',
'tango://databaseds:10000/lts/pcc/1/rcu_attenuator_rw',
'tango://databaseds:10000/lts/pcc/1/rcu_band_r',
'tango://databaseds:10000/lts/pcc/1/rcu_band_rw',
'tango://databaseds:10000/lts/pcc/1/rcu_i2c_status_r',
'tango://databaseds:10000/lts/pcc/1/rcu_id_r',
'tango://databaseds:10000/lts/pcc/1/rcu_led0_r',
'tango://databaseds:10000/lts/pcc/1/rcu_led0_rw',
'tango://databaseds:10000/lts/pcc/1/rcu_led1_r',
'tango://databaseds:10000/lts/pcc/1/rcu_led1_rw',
'tango://databaseds:10000/lts/pcc/1/rcu_mask_rw',
'tango://databaseds:10000/lts/pcc/1/rcu_monitor_rate_rw',
'tango://databaseds:10000/lts/pcc/1/rcu_pwr_dig_r',
'tango://databaseds:10000/lts/pcc/1/rcu_temperature_r',
'tango://databaseds:10000/lts/pcc/1/rcu_translator_busy_r',
'tango://databaseds:10000/lts/pcc/1/rcu_version_r')
%% Cell type:code id:a1222d19 tags:
``` python
# Archiver managing methods
archiver.get_subscriber_errors()
#e = archiver.get_attribute_errors('lts/pcc/1/rcu_temperature_r')
#print(e)
```
%% Output
{'tango://databaseds:10000/lts/pcc/1/clk_enable_pwr_r': 'Read value for attribute CLK_Enable_PWR_R has not been updated',
'tango://databaseds:10000/lts/pcc/1/clk_i2c_status_r': 'Read value for attribute CLK_I2C_STATUS_R has not been updated',
'tango://databaseds:10000/lts/pcc/1/clk_pll_error_r': 'Read value for attribute CLK_PLL_error_R has not been updated',
'tango://databaseds:10000/lts/pcc/1/clk_pll_locked_r': 'Read value for attribute CLK_PLL_locked_R has not been updated',
'tango://databaseds:10000/lts/pcc/1/clk_translator_busy_r': 'Read value for attribute CLK_translator_busy_R has not been updated',
'tango://databaseds:10000/lts/pcc/1/rcu_version_r': 'Storing Error: mysql_stmt_bind_param() failed, err=Buffer type is not supported'}
%% Cell type:code id:174bbcdb tags:
``` python
l = archiver.get_subscriber_load()
print(l," -> Number of archiving events per minute")
```
%% Output
1586.0 events/period -> Number of archiving events per minute
%% Cell type:code id:f060b0b6 tags:
``` python
#archiver.update_archiving_attribute('lts/pcc/1/rcu_pwr_dig_r')
```
%% Cell type:code id:f626d029 tags:
``` python
# Turn off the device
d.off()
# Leave commented by default
archiver.remove_attributes_by_device(device_name)
```
%% Cell type:code id:13c3b97d tags:
``` python
# Initialise the retriever object and print the archived attributes in the database
retriever = Retriever()
#retriever.get_all_archived_attributes()
```
%% Cell type:code id:f176c20e tags:
``` python
# Retrieve records in the last n hours (works even with decimals)
# Use alternatively one of the following two methods to retrieve data (last n hours or interval)
records= retriever.get_attribute_value_by_hours(attr_fq_name,hours=0.1)
#records = retriever.get_attribute_value_by_interval(attr_fq_name,'2021-09-01 16:00:00', '2021-09-01 16:03:00')
if not records:
print('Empty result!')
else:
# Convert DB Array records into Python lists
data = build_array_from_record(records,records[0].dim_x_r)
# Extract only the value from the array
array_values = get_values_from_record(data)
#records
#data
#array_values
```
%% Cell type:code id:42e7f25a tags:
``` python
import sys, time
import numpy as np
sys.path.append('/hosthome/tango/devices')
from toolkit.archiver import Archiver,Retriever
from toolkit.archiver_base import *
from matplotlib import pyplot as plt
```
%% Cell type:code id:1f025912 tags:
``` python
from common.lofar_environment import isProduction
print(isProduction())
```
%% Cell type:code id:e0656e2d tags:
``` python
# Define an attribute for archiving
device_name = 'LTS/PCC/1'
d=DeviceProxy(device_name)
state = str(d.state())
print(device_name,'is',state)
archiver = Archiver()
# Attribute chosen to be archived
attr_name = 'rcu_temperature_r'
attr_fq_name = str(device_name+'/'+attr_name).lower()
```
%% Cell type:code id:153d9420 tags:
``` python
# Print the list of the attributes in the event subscriber
# If any attribute is present, its archiving will begin when device will reach ON state,
# Otherwise, attribute will be added to the list at the device initializing phase only in PRODUCTION mode
archiver.get_subscriber_attributes()
```
%% Cell type:code id:2ebb00f8 tags:
``` python
# Start the device
if state == "OFF":
if isProduction():
archiver.check_and_add_attribute_in_archiving_list(attr_fq_name)
else:
archiver.remove_attribute_from_archiver(attr_fq_name)
time.sleep(1)
d.initialise()
time.sleep(1)
state = str(d.state())
if state == "STANDBY":
d.on()
state = str(d.state())
if state == "ON":
print("Device is now in ON state")
```
%% Cell type:code id:75163627 tags:
``` python
# Modify attribute archiving features
archiver.update_archiving_attribute(attr_fq_name,polling_period=1000,event_period=5000,strategy='RUN')
```
%% Cell type:code id:7814715e tags:
``` python
# Add attribute to the archiving list (starts the archiving if device is running)
# Archiving strategies are ['ALWAYS','RUN','SHUTDOWN','SERVICE']
#Read [0] ALWAYS:always stored
#Read [1] RUN:stored during run
#Read [2] SHUTDOWN:stored during shutdown
#Read [3] SERVICE:stored during maintenance activities
archiver.add_attribute_to_archiver(attr_fq_name, polling_period=1000, event_period=1000, strategy='RUN')
```
%% Cell type:code id:52a27abb tags:
``` python
# Stop the attribute archiving but do not remove it from the list
# This means that archiving is stopped for the current session, but if the device is restarted,
# the attribute archiving will be restarted as well
# In order to definitely stop the archiving, the attribute must be removed from the attribute list (go to last cell)
archiver.stop_archiving_attribute(attr_fq_name)
```
%% Cell type:code id:c064e337 tags:
``` python
# Starts the attribute archiving if it was stopped
archiver.start_archiving_attribute(attr_fq_name)
```
%% Cell type:code id:d199916c tags:
``` python
# Initialise the retriever object and print the archived attributes in the database
retriever = Retriever()
retriever.get_all_archived_attributes()
```
%% Cell type:code id:80e2a560 tags:
``` python
# Retrieve records in the last n hours (works even with decimals)
# Use alternatively one of the following two methods to retrieve data (last n hours or interval)
records= retriever.get_attribute_value_by_hours(attr_fq_name,hours=0.1)
#records = retriever.get_attribute_value_by_interval(attr_fq_name,'2021-09-01 16:00:00', '2021-09-01 16:03:00')
if not records:
print('Empty result!')
else:
# Convert DB Array records into Python lists
data = build_array_from_record(records,records[0].dim_x_r)
# Extract only the value from the array
array_values = get_values_from_record(data)
#records
#data
#array_values
```
%% Cell type:code id:64c8e060 tags:
``` python
# Extract and process timestamps for plotting purposes
def get_timestamps(data,strformat):
timestamps = []
for i in range(len(data)):
timestamps.append(data[i][0].recv_time.strftime(strformat))
return timestamps
timestamps = get_timestamps(data,"%Y-%m-%d %X")
```
%% Cell type:code id:59a0c05c tags:
``` python
# Plot of array values
heatmap = np.array(array_values,dtype=np.float)
fig = plt.figure()
plt.rcParams['figure.figsize'] = [128, 64]
#plt.rcParams['figure.dpi'] = 128
ax = fig.add_subplot(111)
im = ax.imshow(heatmap, interpolation='nearest',cmap='coolwarm')
ax.set_xlabel('Array index')
ax.set_ylabel('Timestamp')
ax.set_xlim([0,(records[0].dim_x_r)-1])
ax.set_xticks(np.arange(0,records[0].dim_x_r))
ax.set_yticks(range(0,len(timestamps)))
ax.set_yticklabels(timestamps,fontsize=4)
# Comment the previous two lines and uncomment the following line if there are too many timestamp labels
#ax.set_yticks(range(0,len(timestamps),10))
ax.set_title('Archived data for '+ attr_fq_name)
ax.grid()
cbar = fig.colorbar(ax=ax, mappable=im, orientation='horizontal')
plt.show()
```
%% Cell type:code id:1c753ed9 tags:
``` python
# Count number of archive events per minute
archiver.get_subscriber_load()
```
%% Cell type:code id:a0e8dcab tags:
``` python
# Turn off the device
d.off()
# Remove attribute from archiving list
#archiver.remove_attribute_from_archiver(attr_fq_name)
#archiver.remove_attributes_by_device(device_name)
```
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment