Repository navigation
Analysis functions
This example describes the way in which analysis functions are added to a node. Analysis functions can be either (1) class methods, (2) separate functions or (3) functions in a separate module (in which case that module must be imported into the node). An analysis function is added to the node by appending it to the array self.metric_functions.
Analysis functions can be written as class methods. Using the example code on the page Creating-new-nodes, an example of this is, e.g.,
def metric_b(self, x):
""" Dummy function that returns a random number regardless of the input """
y = random.random()
print('sending message')
self.message_queue.put('A calculating metric_b')
return yIn this example, the analysis function metric_b is a class method of the node and hence has access to all of the methods belonging to the class MidasNodeExample. This is required, e.g., when one wants to publish messages, which is described next. Publishing messages requires that the analysis function has access to the node's message_queue. Such an analysis function must therefore be written as class methods.
If analysis functions are defined in an external file, it is not necessary to add each analysis function separately to the metric_functions array.
First, the external module with the analysis functions along with the inspect module is imported:
import MyAnalysisFunctions
import inspectThen, the following code can be used in the node's init-function to automatically import all analysis functions in the module into the node.
self.metric_functions = [i[1] for i in inspect.getmembers(MyAnalysisFunctions, inspect.isfunction)]The data to be used by an analysis function is passed as the first positional argument. Note, however, that if the analysis function is a class method the data variable is actually the second positional argument due to self always being the first argument.
The data container is a dict with the keys 'data' and 'time'. Both dictionary items contain arrays with data and the correspnding time points for those channels that were specified in the metric request (see Calling analysis functions). Below is a toy example of how to access data from two channels. This function would naturally throw an exception if the request for the metric contained only one channel. The order of the channels in the data container is the same as in the HTTP-request.
def test_metric(self,x):
data_from_first_channel = x['data'][0]
data_from_second_channel = x['data'][1]
time_stamps_from_first = x['time'][0]
time_stamps_from_second = x['time'][1]
return 0It is essential that each analysis function is documented using a docstring. The first line of the docstring is extracted from the function when the method self.generate_metric_lists() is called, and it is reported as a description of the analysis function, accessible through the API. In short, the first line of the docstring should be a short description of the analysis function that provides information to the user regarding the analysis function.
An analysis function is called through the API using the following syntax:
http://midas_dispatcher/node_name/metric/{"type":"metric_b", "channels":["Ch1"], "time_window":[10, 6], "arguments":[1,3]}
Please refer to the API for details.
In brief, in this API call, the analysis function metric_b is called with the parameters bstart=1, bstop=3, using data from channel Ch1 and a time window starting 10 seconds ago with a length of 6 seconds.