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_TOPIC
event comes in
BaseState
– The state machines API¶
-
class
ocd.states.
BaseState
[source]¶ Bases:
object
This class defines the mandatory API for state machines used by OCD. The properties and methods defined here must be reimplemented in derived classes
Attributes: topics
list of topics handled by the state machine. Defaults to
trigger_topics
list of topics that can trigger a machine state change
machine
transitions.Machine
instance 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
True
if the event has been handled,False
otherwise
-
machine
¶ transitions.Machine
instance representing the states
-
topics
¶ list of topics handled by the state machine. Defaults to
trigger_topics
plusTCS_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.StateMixin
State 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.Machine
and 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
topics
list of topics handled by the state machine. Defaults to
trigger_topics
Topics that trigger a machine state transition.
-
_do_transition
(self, trigger_name, force_name, *args, **kwargs)[source]¶ Try to execute the
triggered
transition: 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_TOPIC
with 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 theexposure
key of the inputtcs_event
Parameters: - 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_TOPIC
with 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_TOPIC
with 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_topic
isocd.run_shot.ALL_TOPICS
; seeocd.run_shot
for a description of topics and events; - emit the current the state with
StateMixin.emit_state_name()
(iftcs_topic
isTCS_HEARTBEAT_TOPIC
).
Parameters: - tcs_topic : string
topic of the event
- tcs_event : dict
event to handle
Returns: - bool
True
iftcs_topic
intopics
,False
otherwise
- update the state, if
-
on_enter_idle
(self, state_event)[source]¶ Callback that is triggered when entering the
idle
state.The function looks for the following entry in
event.kwargs
:tcs_event
: if present and dictionary like, try to extract theshotid
key; if successful it updates the database callingocd.shots_db.update_shot()
. Failures are logged as warning. Iftcs_event
is not present nothing happens.
Parameters: - state_event :
transition.EventData
happened event
-
trigger_topics
¶ Topics that trigger a machine state transition. See
ocd.run_shot
for a description of topics.
MetrologyState
– Monitor the metrology¶
-
class
ocd.states.
MetrologyState
(conf, vault)[source]¶ Bases:
ocd.states.BaseState
,ocd.states.CallbackMixin
,ocd.states.StateMixin
State 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
topics
list of topics handled by the state machine. Defaults to
trigger_topics
Same 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_masked
of the values stored in theMetrologyVault
the 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_good
of 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_topic
is the same of the topics handled byocd.storage.MetrologyVault
. - emit the current the state with
StateMixin.emit_state_name()
(iftcs_topic
isTCS_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
HetdexAllowedState
state 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.StateMixin
This 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.ENABLE
triggersallow()
, if it isHETDEX_TOGGLE.DISABLE
triggersforbid()
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_TOPIC
is emitted. The associated event is:Topic State Event ocd.states.hetdex_allowed allowed new_state (int): HETDEX_CHANGED.ENABLED
ocd.states.hetdex_allowed not_allowed new_state (int): HETDEX_CHANGED.DISABLED
Note
Since the state is update in the main OCD loop, it make sense to use the
ocd_main_loop
ZeroMQ 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
topics
list of topics handled by the state machine. Defaults to
trigger_topics
Topics 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
HetdexAllowedState
for 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_topic
isHETDEX_ALLOWED_TOPIC
. - emit the current the state with
StateMixin.emit_state_name()
(iftcs_topic
isTCS_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.StateMixin
Collect 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,
MetaState
switches to theallowed
state, 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
topics
list of topics handled by the state machine. Defaults to
trigger_topics
topics 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_topic
is in the list oftrigger_topics
that 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_topic
is not intrigger_topics
but 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:
object
Mixin 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_TOPIC
to document state transitions. This should be used after a transition takes place, for example as afinalize_event
callback.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; theabort
transition 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_event
callback.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; theabort
transition 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:
object
Mixin 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_TOPIC
to document state the current state.This method assumes that the class has a
state
attribute
-