.. _`F(x)`: .. _`org.sysess.sympathy.data.fx`: F(x) ~~~~ .. image:: fx.svg :width: 48 The F(x) nodes have a similar role as the :ref:`Calculator` node. But where the :ref:`Calculator` node shines when the calculations are simple expressions, the F(x) nodes are better suited for more advanced calculations since the code may span multiple lines, include statements and may even be kept in a separate python file. You can place this python file anywhere, but it might be a good idea to keep it in the same folder as your workflow or in a subfolder to that folder. Defining a function =================== The python function that should be called by the node needs to be decorated with ``fx.decorator``. The function should also take exactly two positional arguments representing the input and output ports respectively. It is recommended to name the arguments ``arg`` and ``res``. These variables are of the same type as the input on port2. Consult the :ref:`API` for that type to figure out relevant operations. The argument to ``fx.decorator`` is a list of types (as shown in port tooltips) that you intend your script to support. When selecting functions from a file, each function is only available if the port type matches one of its types. Example:: from sympathy.api import fx @fx.decorator(['table']) def my_calculation(arg, res): spam = arg['spam'] # My advanced calculation: more_spam = spam + 1 res['more spam'] = more_spam A quick way to get the skeleton for a function is to use the function wizard that is started by clicking *File->Wizards->New Function*. Script without separate file ============================ For short scripts that are not intended to be shared between different nodes it can convenient not having to create an external file. To enable this feature, the datasource port first needs to be deleted. Once there is no datasource port, the node will show a code editor when configured. The format is the same, the only exception is that all calculations (matching input type) will be executed. Debugging your functions ======================== When the functions are in a separate file they can be debugged using PyCharm. The process is same as when debugging nodes. See :ref:`pycharm_debug` for instructions. List behavior ============= The same function can be used with both :ref:`F(x)` and :ref:`F(x) List` nodes. For example a function specified to run for type 'table' can be used with an F(x) node connected to a single table or with an F(x) List node connected to a list of tables. In the latter case the function will be executed once per item in the list. Configuration ============= When *Copy input* is disabled (the default) the output table will be empty when the functions are run. When the *Copy input* setting is enabled the entire input table will get copied to the output before running the functions in the file. This is useful when your functions should only add a few columns to a data table, but in this case you must make sure that the output has the same number of rows as the input. Alternative function definition =============================== Another syntax for writing a "function" is to define a class which inherits from ``fx.Fx``. The ``fx.Fx`` class provides access to the input and output with ``self.arg`` and ``self.res`` respectively. These variables are of the same type as the input on port2. The field ``arg_types`` should contain the list of types that you intend your script to support. Example:: from sympathy.api import fx class MyCalculation(fx.Fx): arg_types = ['table'] def execute(self): spam = self.arg['spam'] # My advanced calculation: more_spam = spam + 1 self.res['more spam'] = more_spam This syntax is available mostly for backwards compatibility. For new functions it is recommended to use the syntax with decorated functions. *Input ports*: :port1: datasource Path to Python file with scripted functions. :port2: Item with data to apply functions on *Output ports*: :port3: Item with the results from the applied functions *Configuration*: **Copy input** (copy_input) If enabled the incoming data will be copied to the output before running the nodes. **Select functions** (selected_functions) Choose one or many of the listed functions to apply to the content of the incoming item. **Python code** (code) Python code block, input is called arg, output res. .. automodule:: node_fx_selector .. class:: Fx Example flows ############# * :download:`Functions.syx `