Calculator¶
The Calculator nodes can perform calculations on any given input. Any type can by used as input and it is accessed by the keyword arg.
These nodes do not support the ${} notation of older Calculator Table nodes.
Tuples can be used either with the same datatypes e.g.,
(Table, Table), (ADAF, ADAF, ADAF),
etc, or with different datatypes e.g., (Table, ADAF),
(ADAF, ADAFs, Tables). Any combination is possible.
The items in a tuple are accessed by index,
like so: arg[0]
, arg[1]
, etc.
Calculated signals can be accessed with the res keyword in the same way.
Some examples:
- Table - ``arg.col('signal1').data``
- Tables - ``arg[0].col('signal1').data``
- ADAF - ``arg.sys['system0']['raster0']['signal0'].y``
for signal values and
``arg.sys['system0']['raster0']['signal0'].t`` for the
timeseries
- ADAFs - ``arg[0].sys['system0']['raster0']['signal0'].y`` for
signal values and
``arg[0].sys['system0']['raster0']['signal0'].t`` for the
timeseries
- Text - ``arg.dtext`` for the text
- Texts - ``arg[0].dtext`` for the text
- Datasource - ``arg`` for Datasource object
- Datasources - ``arg[0]`` for Datasource in Datasources
- Tuple - Objects are accessed as ``arg[0]``, ``arg[1]``, ...
Example calculations:
New signal = arg.col('Old signal').data + 1
area = arg.col('width').data * arg.col('height').data
result = (arg.col('signal0').data == 2) &
ca.change_up(arg.col('signal1).data)
index = np.arange(len(arg.col('some signal').data))
sine = np.sin(arg.col('angle').data)
The API of the incoming data type can be used in the calculator. For example you can use Table API to get a list of a table’s column names:
table_names = arg.column_names()
Note that a dependency on a column is only created when a string literal is
used, for example, arg.col('signal_name').data
. Iterating through a
table’s columns, like np.array([arg.col(name) for name in arg.column_names()]),
does not. In the first expression, if ‘signal_name’ is missing, the node
will fail with an error. The second one will run even if there are no columns
in the input.
- Input ports:
port0: <a>
Generic Input
- Output ports:
port1: table
Table with results from the calculations.
- Configuration:
- List of calculations (calc_list)
- List of calculations.
- (no label) (calc_attrs_dict)
- Calculation attributes as json dict-list-string!
- Copy input (copy_input)
- If enabled the incoming data will be copied to the output before running the calculations. This requires that the results will all have the same length. An exception will be raised if the lengths of the outgoing results differ.
- Action on calculation failure (fail_strategy)
- Decide how a failed calculation should be handled
The calculator node can apply calculations on each data column in a list. The calculations are written as Python code and can consist of simple arithmetic calculations, Python function calls, or calls to functions defined in plugins.
Calculations¶
You declare each calculation by typing a name in the text line labeled Signal name and entering the calculation in the textfield labeled Calculation. You can use any of the signals in the list Signal names in your calculation.
To use a signal from an incoming table type simply drag-and-drop the signal name from the list of available signals to the calculation field. To use a signal from the incoming generic data use arg in a way that fits the data format as can be seen below:
To add a function, drag-and-drop it from the Avaliable functions tree structure. Note that any signal that you reference in the calculation must exist in all incoming data structures.
To add a new calculation, press the New button and the Calculation field as well as Signal name will be cleared. If you want to edit a calculation simply click on the calculation in the List of calculations. The signal name will then appear under Signal name and the calculation will appear in the Calculation field. The calculation will be updated in the Calculation field, List of calculations and preview simultaneously. To remove a calculation, mark a calculation in List of calculations and press the Remove button. The result of your calculation is written to a column in an outgoing table.
If something goes wrong when you define the calculations you will get an error or warning message in the preview window and at the top of the window.
Some commonly used operators and functions can be found under the function tree structure (labeled Common functions) and can be added to a calculation by double-clicking or dragging the function name to the calculation area. If you want more information about a function, hover its name and its documentation will appear as a tooltip.
The signals that you access in the calculations are returned as numpy arrays,
the same as if you had called get_column_to_array()
from the
Table API. This means that simple arithmetics and the functions from
numpy and pandas work out of the box. But if you want to apply some other
function which only works on a single element of the column you may need to use
Python list comprehensions. For (the contrived) example:
filenames = np.array([value + value for value in signal])
where signal is a table column.
Calculation Attributes¶
Each calculation can have any number of custom associated attributes. These are, at least for now, much more limited than calculations. Each attribute has a string for its name and another string for its value and both are treated as text and are not evaluated as python expressions. The use for these is being able to associate metadata to output columns created by calculations. For example:
Name | Value |
---|---|
unit | ms |
will attach milliseconds for unit to a specific column.
Output¶
Each column of the output will have a calculation attribute with a string representation of the calculation used to create that column.
In the configuration, there is an option on how to handle exceptions (Action on calculation failure) produced by the node, for example missing signals or erroneous calculations.
In the list of calculations there is also the option to disable individual calculations, i.e., exclude them from the output. This makes it possible to make intermediary calculations that does not have the same lengths as the the calculations that are actually output by the node. This could for example be useful for constants.
Compatibility¶
Under python 2 the calculations are evaluated with future imports division
and unicode_literals
activated. This means that in both python 2 and python
3 the calculation 1/2 will give 0.5 as result, and the calculation ‘hello’
will result in a unicode-aware text object (unicode in python 2 and str in
python 3). To get floor division use the operator //
and to get a binary
string (str in python 2 and bytes in python 3) use the syntax b'hello'
.