Inputs and outputs¶
The possible inputs (to generate events) and possible outputs (such as lights) for each system are defined when creating a state transition matrix. In general, the list of inputs and outputs for a rig does not change, so we defined them globally in the settings/rigsettings.py
file.
Below we show how these inputs/outputs can be defined manually or taken from the settings.
Inputs are defined by a Python dictionary such as {'C':0, 'L':1, 'R':2}
(for center, left and right detectors), which results in two possible events for each input: Cin
, Cout
, Lin
, Lout
, Rin
, Rout
. In this case Cin
is an event triggered by activating detector C, and Cout
is generated when the detector is deactivated. An additional event (Tup
) is always created. This event is triggered when the timer corresponding to the current state ends.
Outputs are defined by a similar Python dictionary such as {'centerValve':0, 'centerLED':1}
.
When creating an instance of StateMatrix
, we can also specify the name of the “readystate”. When the system reaches this state, it gives the control back from the state machine to the user interface until dispatcher.ready_to_start_trial()
is called.
Here is an example of how this is done in code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | from taskontrol import statematrix from taskontrol.plugins import templates class Paradigm(templates.ParadigmMinimal): def __init__(self, parent=None): super().__init__(parent) self.sm = statematrix.StateMatrix(inputs={'C':0, 'L':1, 'R':2}, outputs={'centerValve':0, 'centerLED':1}, readystate='ready_next_trial') # The parent class defines self.dispatcher used below. def prepare_next_trial(self, nextTrial): # -- Set state matrix -- self.sm.add_state(name='wait_for_event', statetimer=100, transitions={'Cin':'light_on'}) self.sm.add_state(name='light_on', statetimer=2.0, transitions={'Cin':'light_off', 'Tup':'light_off'}, outputsOn=['centerLED']) self.sm.add_state(name='light_off', statetimer=0, transitions={'Tup':'ready_next_trial'}, outputsOff=['centerLED']) self.dispatcher.set_state_matrix(self.sm) # -- Tell the state machine that we are ready to start -- self.dispatcher.ready_to_start_trial() if __name__ == "__main__": (app, paradigm) = templates.paramgui.create_app(Paradigm) |
Alternatively, we can import rigsettings.py and use the inputs and outputs defined there:
1 2 3 4 5 6 7 8 9 10 11 | from taskontrol import statematrix from taskontrol import rigsettings from taskontrol.plugins import templates class Paradigm(templates.ParadigmMinimal): def __init__(self, parent=None): super().__init__(parent) self.sm = statematrix.StateMatrix(inputs=rigsettings.INPUTS, outputs=rigsettings.OUTPUTS, readystate='ready_next_trial') # ...lines 10-27 from code above. |
You can check rigsettings_template.py, to see what inputs and outputs are defined by default.
Note
In this example, we import a couple of additional modules (statematrix
and rigsettings
). In previous examples, these were imported by the templates
module, but here we are using them directly.