ocd.states – OCD state machines¶
Module containing the states necessary to run OCD
The classes here use the transitions package for the states definitions and transitions.
TCS events¶
Transition event¶
When any of the states change a TCS-like event with topic
STATE_CHANGE_TOPIC and the following payload, based on
tcs_lib.tcs_event.TCSDict.
| Topic | Event |
|---|---|
| ocd.states.change | machine_name (string): name of the state machine that just had the transition |
| transition (string): name of the transition | |
| old_state (string): name of the old state | |
| new_state (string): name of the new state | |
| msg (string): extra message attached to the transition | |
| traceback (string): full error traceback if some problem happened | |
| __data_time (string): time at which the event payload is created | |
| __wire_time (string): time at which the event is sent | |
| __data (bool): whether an other event with data is coming (always false) | |
| __system, __source, __key (string): components of the topic |
State event¶
When a TCS_HEARTBEAT_TOPIC is received, emit a TCS-like event with
topic STATE_NAME_TOPIC and the following payload, based on
tcs_lib.tcs_event.TCSDict.
| Topic | Event |
|---|---|
| ocd.states.state | machine_name (string): name of the state machine that just had the transition |
| state (string): name of the current state | |
| __data_time (string): time at which the event payload is created | |
| __wire_time (string): time at which the event is sent | |
| __data (bool): whether an other event with data is coming (always false) | |
| __system, __source, __key (string): components of the topic |
Variables¶
-
ocd.states.TCS_HEARTBEAT_TOPIC= 'tcs.receiver.heartbeat'¶ Topic of the TCS heartbeat events. The machines in this module emit their state when such an event arrive
-
ocd.states.STATE_CHANGE_TOPIC= 'ocd.states.change'¶ Topic used when emitting TCS-like events on state change
-
ocd.states.STATE_NAME_TOPIC= 'ocd.states.state'¶ Topic used when emitting TCS-like events when a
TCS_HEARTBEAT_TOPICevent comes in
BaseState – The state machines API¶
-
class
ocd.states.BaseState[source]¶ Bases:
objectThis class defines the mandatory API for state machines used by OCD. The properties and methods defined here must be reimplemented in derived classes
Attributes: topicslist of topics handled by the state machine. Defaults to
trigger_topicslist of topics that can trigger a machine state change
machinetransitions.Machineinstance representing the states
-
handle_event(self, tcs_topic, tcs_event)[source]¶ Handle a TCS event and decide whether the status need to be changed or not.
Parameters: - tcs_topic : string
topic of the event
- tcs_event : dict
event to handle
Returns: - bool
Trueif the event has been handled,Falseotherwise
-
machine¶ transitions.Machineinstance representing the states
-
topics¶ list of topics handled by the state machine. Defaults to
trigger_topicsplusTCS_HEARTBEAT_TOPIC
-
trigger_topics¶ list of topics that can trigger a machine state change
RunShotState – Keep track of the shots run by OCD¶
-
class
ocd.states.RunShotState[source]¶ Bases:
ocd.states.BaseState,ocd.states.CallbackMixin,ocd.states.StateMixinState machine that keeps track of shots run by OCD.
The method
handle_event()accepts events from the TCS stream and, if relevant, use the event payloads to modify the internal state.See the documentation for a graph of the states and explicit transitions.
Warning
all the transitions called
to_{state}, with{state}one of the state names, are created by thetransitions.Machineand allow to force the transition to the corresponding state.Attributes: - exp_f : string
format string to build the exposure name
- machine :
transitions.Machine underlying class representing the states
- topic_handler_map : dict
mapping between the topics and the functions that handle the corresponding events
topicslist of topics handled by the state machine. Defaults to
trigger_topicsTopics that trigger a machine state transition.
-
_do_transition(self, trigger_name, force_name, *args, **kwargs)[source]¶ Try to execute the
triggeredtransition: if it fail, run the forced one.Parameters: - triggered, forced : string
name of the transitions to force
- args, kwargs : arguments
positional and keyword arguments to pass to the triggered transitions
-
_handle_exp_event(self, tcs_event)[source]¶ Handle events associated with
EXP_TOPICwith the following logic:- if the event is marked as starting, try to execute the
do_exp{0:02d}()transition; if it fails forceto_exp{0:02d}(); - if the event is marked as finished, try to execute the
finish_exp{0:02d}()transition; if it fails forceto_exp{0:02d}_done().
The format field
{0:02d}is a zero padded two digit integer, whose value is taken from theexposurekey of the inputtcs_eventParameters: - tcs_event : dict
event to handle
- if the event is marked as starting, try to execute the
-
_handle_run_event(self, tcs_event)[source]¶ Handle events associated with
RUN_TOPICwith the following logic:- if the event is marked as starting, try to execute the
start()transition; if it fails forceto_started(); - if the event is marked as finished, try to execute the
finish()transition; if it fails forceto_idle(); - if the event is marked as finished and an error happened, execute the
abort()with the traceback contained in the event
Parameters: - tcs_event : dict
event to handle
- if the event is marked as starting, try to execute the
-
_handle_setup_event(self, tcs_event)[source]¶ Handle events associated with
SETUP_TOPICwith the following logic:- if the event is marked as starting, try to execute the
do_setup()transition; if it fails forceto_setup(); - if the event is marked as finished, try to execute the
finish_setup()transition; if it fails forceto_setup_done();
Parameters: - tcs_event : dict
event to handle
- if the event is marked as starting, try to execute the
-
_make_machine(self)[source]¶ create the machine with all the relevant states and transitions
Returns: - machine :
transitions.Machine state machine
- machine :
-
handle_event(self, tcs_topic, tcs_event)[source]¶ Handle a TCS event and:
- update the state, if
tcs_topicisocd.run_shot.ALL_TOPICS; seeocd.run_shotfor a description of topics and events; - emit the current the state with
StateMixin.emit_state_name()(iftcs_topicisTCS_HEARTBEAT_TOPIC).
Parameters: - tcs_topic : string
topic of the event
- tcs_event : dict
event to handle
Returns: - bool
Trueiftcs_topicintopics,Falseotherwise
- update the state, if
-
on_enter_idle(self, state_event)[source]¶ Callback that is triggered when entering the
idlestate.The function looks for the following entry in
event.kwargs:tcs_event: if present and dictionary like, try to extract theshotidkey; if successful it updates the database callingocd.shots_db.update_shot(). Failures are logged as warning. Iftcs_eventis not present nothing happens.
Parameters: - state_event :
transition.EventData happened event
-
trigger_topics¶ Topics that trigger a machine state transition. See
ocd.run_shotfor a description of topics.
MetrologyState – Monitor the metrology¶
-
class
ocd.states.MetrologyState(conf, vault)[source]¶ Bases:
ocd.states.BaseState,ocd.states.CallbackMixin,ocd.states.StateMixinState machine that keep track of the metrology.
Any time one of the events that can update containers in the
ocd.storage.MetrologyVault, a state change is evaluated.Parameters: - conf :
pyhetdex.tools.configuration.ConfigParser configuration
- vault :
ocd.storage.MetrologyVault vault containing the values of interest
Attributes: - machine :
transitions.Machine underlying class representing the states
topicslist of topics handled by the state machine. Defaults to
trigger_topicsSame as the topics used by the input
vault- quantities : list
names of the quantities to check
- ref_values : dict
for each quantities, save the minimum and maximum value allowed
-
_make_machine(self)[source]¶ create the machine with all the relevant states and transitions
Returns: - machine :
transitions.Machine state machine
- machine :
-
compare_probes(self)[source]¶ For each probe, check that the conditions are good enough to run HETDEX.
Compare the
median_maskedof the values stored in theMetrologyVaultthe corresponding expected values from the[containers]section of the configuration file.Returns: - is_good : list of bool
True is the conditions are in spec for each guide probe
- probe_msg : string
string with the guide probe values and their reference values
-
good_conditions(self, probes_conditions)[source]¶ From the list of boolean representing the probes conditions, extract a single value representing good/bad conditions.
If the option
both_gp_goodof the[containers]section isyes/true, then all the probes must be in spec, otherwise can be just one of them.Parameters: - probes_conditions : list of bool
True is the conditions are in spec for each guide probe
Returns: - bool
good conditions
-
handle_event(self, tcs_topic, tcs_event)[source]¶ Handle a TCS event and:
- update the state, if
tcs_topicis the same of the topics handled byocd.storage.MetrologyVault. - emit the current the state with
StateMixin.emit_state_name()(iftcs_topicisTCS_HEARTBEAT_TOPIC).
Parameters: - tcs_topic : string
topic of the event
- tcs_event : dict
event to handle
Returns: - bool
whether the topic triggers a state change
- update the state, if
-
trigger_topics¶ Same as the topics used by the input
vault
-
update_config(self, conf)[source]¶ Update the local copy of the configuration file and
ref_values.Parameters: - conf :
pyhetdex.tools.configuration.ConfigParser new configuration object
Returns: - string
message to report back
- conf :
- conf :
HetdexAllowedState – It is time to run HETDEX?¶
-
ocd.states.HETDEX_ALLOWED_TOPIC= 'ocd.states.hetdex_allowed'¶ Topic associated with the events necessary to update the
HetdexAllowedStatestate machine
-
ocd.states.HETDEX_CHANGED_TOPIC= 'ocd.states.hetdex_allowed_changed'¶ Topic of the events emitted after a state is changed
-
ocd.states.HETDEX_TOGGLE= ENUM(ENABLE=0, DISABLE=1)¶ Enumerator to use to signal that HETDEX is to be enabled or disabled
-
ocd.states.HETDEX_CHANGED= ENUM(ENABLED=10, DISABLED=11)¶ Enumerator to use to signal that HETDEX has been enabled or disabled
-
class
ocd.states.HetdexAllowedState[source]¶ Bases:
ocd.states.BaseState,ocd.states.CallbackMixin,ocd.states.StateMixinThis state tracks whether OCD is allowed to execute HETDEX shots even if all the other states would allow it.
A state change is triggered by tcs events with topic
HETDEX_ALLOWED_TOPIC. The associated event needs to contain one entry:Topic Event ocd.states.hetdex_allowed action (int): if it is HETDEX_TOGGLE.ENABLEtriggersallow(), if it isHETDEX_TOGGLE.DISABLEtriggersforbid()This state is triggered externally via the
ocd allow_hetdex {start,stop}command.When a state change happens, a TCS-like event with topic
HETDEX_CHANGED_TOPICis emitted. The associated event is:Topic State Event ocd.states.hetdex_allowed allowed new_state (int): HETDEX_CHANGED.ENABLEDocd.states.hetdex_allowed not_allowed new_state (int): HETDEX_CHANGED.DISABLEDNote
Since the state is update in the main OCD loop, it make sense to use the
ocd_main_loopZeroMQ server here. In the case we need more flexibility it is possible to add a new server.Attributes: - machine :
transitions.Machine underlying class representing the states
topicslist of topics handled by the state machine. Defaults to
trigger_topicsTopics that triggers a machine state change.
-
_make_machine(self)[source]¶ create the machine with all the relevant states and transitions
Returns: - machine :
transitions.Machine state machine
- machine :
-
emit_tcs_event(self, state_event)[source]¶ Emit a TCS-like event using a ZeroMQ server. See
HetdexAllowedStatefor more info.Parameters: - state_event :
transition.EventData happened event
- state_event :
-
handle_event(self, tcs_topic, tcs_event)[source]¶ Handle a TCS event and:
- update the state, if
tcs_topicisHETDEX_ALLOWED_TOPIC. - emit the current the state with
StateMixin.emit_state_name()(iftcs_topicisTCS_HEARTBEAT_TOPIC).
Parameters: - tcs_topic : string
topic of the event
- tcs_event : dict
event to handle
Returns: - bool
whether the event has been handled
- update the state, if
-
trigger_topics¶ Topics that triggers a machine state change. I.e.
HETDEX_ALLOWED_TOPIC
- machine :
MetaState – Meta state machine¶
This machine aggregates the state of other machines and according to their
states switch between the satisfied and not_satisfied states.
Consider the following case:
>>> run_shot = RunShotState()
>>> hetdex_allowed = HetdexAllowedState()
>>> meta = MetaState([(run_shot, 'idle'), (hetdex_allowed. 'allowed')])
If run_shot.state == idle and hetdex_allowed == allowed, then
meta.state == satisfied. Any other combination of states of run_shot
and hetdex_allowed results in meta.state == not_satisfied.
-
class
ocd.states.MetaState(machines_states)[source]¶ Bases:
ocd.states.BaseState,ocd.states.CallbackMixin,ocd.states.StateMixinCollect other states and decide whether they all have the expected state.
Parameters: - machines_states : list of 2-tuples (machine, string)
each element is a state machine and the name of the reference state; if all the machines are in the corresponding state,
MetaStateswitches to theallowedstate, otherwise it switches tonot_allowed
Raises: - ValueError
if machines_states doesn’t contain at least one element and if any element is not a 2-tuple
Attributes: - machine :
transitions.Machine underlying class representing the states
topicslist of topics handled by the state machine. Defaults to
trigger_topicstopics that trigger a machine state change; they are the union of
-
_make_machine(self)[source]¶ create the machine with all the relevant states and transitions
Returns: - machine :
transitions.Machine state machine
- machine :
-
handle_event(self, tcs_topic, tcs_event)[source]¶ If
tcs_topicis in the list oftrigger_topicsthat were handled by the input state machines, re-evaluate their states and if they all are in their reference state,allow()the execution of a new shot, otherwiseforbid()it.If
tcs_topicis not intrigger_topicsbut intopics, emit the current the state withStateMixin.emit_state_name().Parameters: - tcs_topic : string
topic of the event
- tcs_event : dict
event to handle, ignored
Returns: - bool
whether the event has been handled
-
trigger_topics¶ topics that trigger a machine state change; they are the union of the trigger_topics from the input machines.
Mixin classes and helpers¶
-
class
ocd.states.CallbackMixin[source]¶ Bases:
objectMixin class that provides implementation for common callbacks that can be used by state machine
-
_msg_fmt(self, state_event)[source]¶ Create a message from the state_event containing the transition name, the source and destination state name and whether the transition is forced.
The function looks for the following entries in
event.kwargs:forced: if the transition is forced; typically theto_{state}transitions will use it.
Parameters: - state_event :
transition.EventData happened event
Returns: - msg : string
string to containing the message to send
- fmt_args : dict
formatting keys for
msg(only positional arguments)
-
emit_state_change(self, state_event)[source]¶ Emit a TCS event with topic
STATE_CHANGE_TOPICto document state transitions. This should be used after a transition takes place, for example as afinalize_eventcallback.The function looks for the following entries in
event.kwargs:extra_msg: an extra message to appen to the state change message; if present comes after thetraceback;traceback: traceback to add to the log message; theaborttransition will typically use this;forced: if the transition is forced; typically theto_{state}transitions will use it.
Parameters: - state_event :
transition.EventData happened event
-
log_state_change(self, state_event)[source]¶ Log state transitions. This should be used after a transition takes place, for example as a
finalize_eventcallback.The function looks for the following entries in
event.kwargs:extra_msg: an extra message to appen to the state change message; if present comes after thetraceback;traceback: traceback to add to the log message; theaborttransition will typically use this;forced: if the transition is forced; typically theto_{state}transitions will use it.
Parameters: - state_event :
transition.EventData happened event
-
-
class
ocd.states.StateMixin[source]¶ Bases:
objectMixin class that provides implementation for common functionalities that can be used by state machines
-
emit_state_name(self)[source]¶ Emit a TCS event with topic
STATE_NAME_TOPICto document state the current state.This method assumes that the class has a
stateattribute
-
Inheritance scheme¶
