23.3. Sample Handling

23.3.1. Overview

The Sample Handling process is a continually running process that controls the movement of plates through the beamline via two robots and the load-lock. The process is encapsulated into states and actions.

A plate’s state is read from ISPyB and other sources *. The action to be executed on a plate is decided based upon its current state. Once an action has completed the plate’s new state is written to ISPyB. Plates are individually identified using barcodes.

The concept of an action is plate movement from one location to another. The valid locations are:

  • IN_STORAGE - plate is in a Formulatrix (Hotel)

  • IN_LOCALSTORAGE - plate is in beamline Local Storage (a series of storage slots inside the Endstation Enclosure)

  • ON_GONIO - plate is on the Goniometer

In addition a plate being moved is considered In Transit (every action has an associated In Transit status) - IN_TRANSIT_...

Thus the four sample handling actions are:

  • Retrieve a plate from a Formulatrix to Local Storage

  • Load a plate from Local Storage onto the Goniometer

  • Unload a plate from the Goniometer to Local Storage

  • Return a plate from Local Storage to a Formulatrix

Only one of these actions can be executed at any one time. The goal is to minimise the time no plate is on the Goniometer ready to be shot.

Plate states and actions allowed to move between them are shown below. Sample Handling processing

Each plate is either shot or not shot, this state is stored in ISPyB as its own field. A plate’s shot state is set by the Data Collection Process, allowing unloads.


* Data sources for a plate's state are:
  • ISPyB for plate locations and status.

  • Orange Triangle (a remote Python app) for the next-plate to retrieve from storage.

  • Configuration files for allowed Local Storage slots.


23.3.2. Action Determination

The Sample Handling process has a set of sensors that retrieve information regarding the location of plates and available Local Storage slots. Plate locations are stored in ISPyB, retrieved and updated via the VMXi LIMS Agent (Laboratory Information Management System Agent). The allowed storage slots are set by beamline staff and stored as JSON in i02-2-config/etc/sample_handling/local_storage.json. The information from the sensors is passed to an action selector (sample_handling.actions.selection) which returns a list of potential sample-handling actions, in priority order. The first of these actions is selected for execution by the handling process.

The sensor objects (defined in sample_handling.sense) are:

  • SenseLoadNext - asks the Orange Triangle what the next plate to retrieve from a Formulatrix is

  • SenseSlots - reads the allowed Local Storage storage slots from the specified JSON file

  • SenseLocalStorage - request which plates (if any) are in Local Storage from ISPyB

  • SenseGonio - requests which plate (if any) is on the Goniometer

  • SenseTransit - requests which plates (if any) are currently in transit between fixed locations.

Additional sensor objects may be implemented in the future should the sample handling process need to become more sophisticated.

The prioritisations for sample handling actions, and their required conditions are (highest to lowest):

  • Unload a shot plate from the Goniometer (requires a completed plate on the Goniometer, i.e. all selected crystals in all plate wells have been imaged)

  • Load an unshot plate from Local Storage onto the Goniometer (requires no plate on Goniometer and an uncompleted plate in Local Storage) - plates are prioritised based on when they were placed into local storage (FIFO order)

  • Retrieve the next-plate from a Formulatrix (requires a next-plate from Orange Triangle service and an empty Local Storage slot of the correct type (20 versus 4 degrees Celsius))

  • Return a shot plate to a Formulatrix (requires a completed plate in Local Storage).

No action is considered if a plate is left In Transit - this is expected to be a superfluous check during normal operation, but is left as a precaution (to encourage proper manual recovery after failures, etc).

23.3.3. Action Objects

Actions encapsulate the work required to move a plate from one location to another, including requests to the internal and external robot, preparation of the endstation, final verification of hardware state, and updates to ISPyB.

The high-level interface is given by the Action Java interface but a Jython base class (gda-mx.git/configurations/i02-2-config/scripts/sample_handling/actions/actions.py) is used to provide the base behaviour as described below.

class VmxiAction(Action):
    def update_pre_action_state(self):
        """
        Set the Plate's status to relevant "IN_TRANSIT" state in ISPyB.
        Called by the Sample Handling Processor.
        """
 
    def update_post_action_state(self):
        """
        Set the Plate's status to its final location in ISPyB.
        Called by the Sample Handling Processor.
        """
 
    def execute(self):
        """
        Wraps run_action, handling exceptions and manages the action status appropriately.
        Called by the Sample Handling Processor.
        """
 
    def run_action(self):
        """
        Run the action, triggering hardware moves.
        Successful return indicates the action ran to completion, otherwise
        an exception should be raised.
        """
 
    def stop(self):
        """
        Ask the action to stop (may not be honoured, best effort only,
        particularly where the robot is concerned).
        May be called by the Sample Handling Processor.
        """
 
    def getStatus(self):
        """
        Return an ActionStatus for the current state.
        """
 
    def getName(self):
        """
        Return the name given to the action.
        """
 
    def getRunTime(self):
        """
        Return the execution time for the action.
        """

The parameters for the action (e.g. plate barcode, Hotel to use, storage slot to use, etc), are passed to the action’s constructor.

23.3.4. Action Status

getStatus (see above) returns an ActionStatus enum , which has the following values:

  • PENDING - action has not yet started

  • RUNNING - action has started running

  • COMPLETE - action ran successfully

  • ERROR - action entered an error state and could not safely recover

  • FAILED - action failed safely

  • STOPPED - action stopped after receiving a stop request (assumed to be unsafe)

Actions are responsible for handling their own status, including the transition from PENDING to RUNNING.

Action states COMPLETE, STOPPED, ERROR and FAILED are termination states and no transitions can occur from these states. An action must only set its status to COMPLETE if the movement of the plate was successful and further actions can be safely taken.

NOTE: The semantics of the FAILED condition are not currently well defined and therefore its use is not properly supported.

The VmxiAction base class handles all status updates appropriately, assuming a correct implementation of run_action.

23.3.5. Interrupts

It is possible to request the Sample Handling process to stop. This will result in the stop method being called on any currently running action. It is not required that this request is honoured, and in the case of robot motions, may not be possible (e.g. without leaving the robot in a difficult to recover state). If a stop can be facilitated, some cleanup may still be required, so action execution may resume for a short while after the stop request has been made.

It can be noted that Sample Handling Actions are very similar to Data Collection Tasks; there are differences, but the trend is the same.

23.3.6. The Sample Handling control loop

An outline of the sample handling process control loop is given below:

while True:
    if running_action:
        if running_action.completed:
            update_ispyb()
            continue
        elif running_action.errored:
            raise
        else:
            continue
    else:
        state = sense_state()
        action = decide_action(state)
        if action:
            start_action_async(action)
            running_action = action

The screenshots below show the Sample Handling Montior displying plate processing progressing.

VMXi Overview

VMXi Overview