Class ScannableBase

All Implemented Interfaces:
Device, Scannable, Configurable, Findable, gda.observable.IObservable
Direct Known Subclasses:
AbstractKeithley2600Series, AbstractKeithley6400Series, AgilentWaveform, AlignmentStageScannable, Apple2IDScannableBase, AsciiFileProcessor, BaseChipRegScannable, BeamDimensions, BeamlineConditionMonitorBase, BimorphMirrorScannable, BSSCScannable, CameraXYScannable, CombinedManipulator, CurrentAmplifierBase, DAServerStatusChecker, DetectorBase, DetectorDistance, DetectorMonitorDataProvider, DummyEpicsLakeshore336, DummyLakeshoreScannable, DummyPersistentEnumScannable, DummySampleWheel, DummySpinner, DummyTopupScannable, EH2ShutterControl, EigerThresholdScannable, EnergyScannable, EnergyScannable, EnumPositionerBase, EpicsBpmController, EpicsCurrAmpGain, EpicsDouble, EpicsEurotherm903, EpicsLakeshore336, EpicsRecord, EpicsSimpleArray, Eurotherm, ExafsScannable, ExperimentShutterController, ExternalSourceWrapper, FastAttenuatorFilters, FastAttenuatorScannable, FrameIndexer, GainWithScalingAndOffset, GasInjectionScannable, GasInjectionScannable, GasInjectionScannablePumpOn, HidenRGAScannable, I05Apple, I11Robot, JEPScannable, Keyence, Lakeshore340Scannable, LakeshoreScannable, LakeshoreScannable, Ln2Scannable, MecaRobotMover, MetashopDataScannable, MirrorCoating, MirrorInOut, MonitorBase, MonitorZebraAndMoveScannable, MonoCoolScannable, PolarisationScannable, PositionerDeterminedScannable, PowerSupplyScannable, PressureCell, PulseTubeMeta, PVScannable, RotatedXyScannable, RotationAxisXScannable, SamplePlateMoverBase, SampleWheel, ScaledScannable, ScanEventHandlerScannable, ScannableGaussian, ScannableGroup, ScannableMotionBase, ScriptAdapter, ShutterChecker, ShutterOpenClose, SimplePVScannable, SimpleScannable, SimpleScannable, SimpleUDPServerScannable, Spin, Spinner, StringValueScannable, TestingEurotherm, TimeDelayScannable, TimeScannable, TimeTravelScannable, TogglerScannable, TwoDScanPlotter, WheelAttenuators, XasProgressUpdater, XasScannable, XpsConstantVelocityMoveController, XspressFillMonitor, XspressHdfWriter, ZebraConstantVelocityMoveController, ZebraMonitorController, ZebraScannableMonitor

@ServiceInterface(Scannable.class) public abstract class ScannableBase extends DeviceBase implements Scannable
A base implementation for a Scannable Device.

Routes calls to asynchronousMoveTo through an externalToInternal method to rawAsynchronousMoveTo; and, vice-versa, calls to getPosition through an internalToExternal method from rawGetPosition. The protected methods externalArrayToInternal and internalArraytoExternal should be overridden to provide automated support for things such as offsets and unit conversion. By default they do nothing.

  • Field Details

    • DEFAULT_INPUT_NAME

      public static final String DEFAULT_INPUT_NAME
      See Also:
    • DEFAULT_OUTPUT_FORMAT

      public static final String DEFAULT_OUTPUT_FORMAT
      See Also:
    • __doc__

      public static String __doc__
      This is the Jython documentation. Use it in the GDA Jython via the help command.
    • level

      protected int level
      The move priority for this Scannable
    • inputNames

      protected String[] inputNames
      Array names for the positioner elements in this Scannable.
    • extraNames

      protected String[] extraNames
      Array names for additional readout elements of this Scannable.
    • outputFormat

      protected String[] outputFormat
      Array of strings which specify the format to output when getting the position of this Scannable.
  • Constructor Details

    • ScannableBase

      public ScannableBase()
  • Method Details

    • validateScannable

      public static void validateScannable(Scannable scannable) throws DeviceException
      This performs a series of tests to check that the internal setup of the Scannable is consistent. It does not and should not operate the scannable by calling getPosition().

      It will set the internal arrays of strings to defaults to prevent NPE where appropriate.

      Parameters:
      scannable -
      Throws:
      DeviceException
    • asynchronousMoveTo

      public void asynchronousMoveTo(Object externalPosition) throws DeviceException
      Trigger a move/operation and return immediately. Implementations of this method should be non-blocking to allow concurrent motion; the isBusy method will be used to determine when the move has completed. Converts the external (user) position to an internal position and passes this to rawAsynchronousMoveTo.
      Specified by:
      asynchronousMoveTo in interface Scannable
      Parameters:
      externalPosition - Position to move to should have an element for each input field.
      Throws:
      DeviceException
    • getPosition

      public Object getPosition() throws DeviceException
      Returns the current position of the Scannable. Called by ConcurentScan at the end of the point. Reads an internal (hardware) position from rawGetPosition, converts this to an external (user) position and returns it.
      Specified by:
      getPosition in interface Scannable
      Returns:
      Current position with an element for each input and extra field. null if their are no fields.
      Throws:
      DeviceException
    • rawAsynchronousMoveTo

      public void rawAsynchronousMoveTo(Object position) throws DeviceException
      [Consider abstract] Trigger a move/operation to an internal/hardware position and return immediately.
      Parameters:
      position - Position in its internal/hardware representation. e.g. with units and offsets removed
      Throws:
      DeviceException
      See Also:
    • rawGetPosition

      public Object rawGetPosition() throws DeviceException
      [Consider abstract] Read the position in its internal (user) representation.
      Returns:
      the value represented by this Scannable
      Throws:
      DeviceException
      See Also:
    • externalToInternal

      public Object externalToInternal(Object externalPosition)
      Converts a position in its external representation to its internal representation.

      Verifies that the object (represented as an array) has the same number of fields as the scannable has input fields, or the total number of fields of the scannable. The later allows scripts to provide the output of getPosition to moveTo methods, e.g. "pos scannable_with_extra_fields scannable_with_extra_fields()".

      Parameters:
      externalPosition - an object array if the Scannable has multiple input fields, otherwise an object. The length must match the number of the Scannables input fields.
      Returns:
      an object array if the Scannable has multiple input fields, otherwise an object. The length will match the number of the Scannables input fields.
    • internalToExternal

      public Object internalToExternal(Object internalPosition)
      Converts a position in its internal representation to its external representation.

      Verifies that the object (represented as an array) has the same number of fields as the scannable.

      Parameters:
      internalPosition -
      Returns:
      an object array if the scannable has multiple fields, otherwise an object.
    • atPointEnd

      public void atPointEnd() throws DeviceException
      Called on every Scannable at the end of every data point, for scans which are broken down into individual points (i.e. non-continous scans) Default behaviour is to do nothing. Inheriting classes have the option to implement this if their specific behaviour requires it.
      Specified by:
      atPointEnd in interface Scannable
      Throws:
      DeviceException
      See Also:
    • atPointStart

      public void atPointStart() throws DeviceException
      Called on every Scannable at every data point, for scans which are broken down into individual points (i.e. non-continuous scans) Default behaviour is to do nothing. Inheriting classes have the option to implement this if their specific behaviour requires it.
      Specified by:
      atPointStart in interface Scannable
      Throws:
      DeviceException
      See Also:
    • atScanLineEnd

      public void atScanLineEnd() throws DeviceException
      Called for every Scannable at the end of every scan Default behaviour is to do nothing. Inheriting classes have the option to implement this if their specific behaviour requires it.
      Specified by:
      atScanLineEnd in interface Scannable
      Throws:
      DeviceException
      See Also:
    • atScanEnd

      public void atScanEnd() throws DeviceException
      Called for every Scannable at the end of a group of nested scans (or a single scan if that is the case).

      Note that this is only called if the Scan finishes normally, or has been requested to finish early. This will not be called if the scan finishes due to an exception of any kind. See Scannable.atCommandFailure() Default behaviour is to do nothing. Inheriting classes have the option to implement this if their specific behaviour requires it.

      Specified by:
      atScanEnd in interface Scannable
      Throws:
      DeviceException
      See Also:
    • atLevelStart

      public void atLevelStart() throws DeviceException
      Called by both the pos and scan commands at the start of each subsequent level move on all Scannables that are part that level's movement.

      This provides a useful mechanism for e.g. creating a Scannable that opens a shutter after motors have moved but before a detector is exposed. Default behaviour is to do nothing. Inheriting classes have the option to implement this if their specific behaviour requires it.

      Specified by:
      atLevelStart in interface Scannable
      Throws:
      DeviceException
      See Also:
    • atLevelMoveStart

      public void atLevelMoveStart() throws DeviceException
      Called by both the pos and scan commands at the start of each subsequent level move only on Scannables that will be moved as part that level's movement.

      For example "pos a 1 b 2 c 3", will, if a and b have the same level and c a higher level will result in:

       a.atLevelMoveStart()   invalid input: '<'----
       b.atLevelMoveStart()   invalid input: '<'----
       a.asynchronousMoveTo()
       b.asynchronousMoveTo()
       a.waitWhileBusy()
       b.waitWhileBusy()
       c.atLevelMoveStart()   invalid input: '<'----
       c.asynchronousMoveTo()
       c.waitWhileBusy()
       
      This hook is used by CoordinatedMotionScannables. Default behaviour is to do nothing. Inheriting classes have the option to implement this if their specific behaviour requires it.
      Specified by:
      atLevelMoveStart in interface Scannable
      Throws:
      DeviceException
      See Also:
    • atLevelEnd

      public void atLevelEnd() throws DeviceException
      Default behaviour is to do nothing. Inheriting classes have the option to implement this if their specific behaviour requires it.
      Specified by:
      atLevelEnd in interface Scannable
      Throws:
      DeviceException
      See Also:
    • atCommandFailure

      public void atCommandFailure() throws DeviceException
      Hook to be used by Scan and pos commands to inform the Scannable that an exception, such as a DeviceExcpetion, has occurred. However not called when the command is aborted using an InterruptionException. If a Scan is aborted then only Scannable.stop() will be called by the Scan or pos command.

      Useful for telling Scannables which hold state during a scan for example, to reset themselves. Used for example by CoordinatedMotionScannables. This hook should be used not in the same way as the stop hook. Default behaviour is to do nothing. Inheriting classes have the option to implement this if their specific behaviour requires it.

      Specified by:
      atCommandFailure in interface Scannable
      Throws:
      DeviceException
      See Also:
    • atScanStart

      public void atScanStart() throws DeviceException
      Called for every Scannable at the start of a group of nested scans (or a single scan if that is the case) Default behaviour is to do nothing. Inheriting classes have the option to implement this if their specific behaviour requires it.
      Specified by:
      atScanStart in interface Scannable
      Throws:
      DeviceException
      See Also:
    • atScanLineStart

      public void atScanLineStart() throws DeviceException
      Called for every Scannable at the start of every scan Default behaviour is to do nothing. Inheriting classes have the option to implement this if their specific behaviour requires it.
      Specified by:
      atScanLineStart in interface Scannable
      Throws:
      DeviceException
      See Also:
    • getExtraNames

      public String[] getExtraNames()
      Description copied from interface: Scannable
      Additional names for extra values that returned by getPosition().
      Specified by:
      getExtraNames in interface Scannable
      Returns:
      array of names of the extra elements if the array returned by getPosition is larger than the array required by moveTo
    • getInputNames

      public String[] getInputNames()
      Description copied from interface: Scannable
      gets a array of InputNames used by moveTo of this scannable.
      Specified by:
      getInputNames in interface Scannable
      Returns:
      array of the names of the elements of the object returned by getPosition
    • getLevel

      public int getLevel()
      Description copied from interface: Scannable
      get the operation level of this scannable.
      Specified by:
      getLevel in interface Scannable
      Returns:
      int - the level
    • getOutputFormat

      public String[] getOutputFormat()
      Description copied from interface: Scannable
      Returns an array of strings which are the format strings to use when pretty printing parts of the output
      Specified by:
      getOutputFormat in interface Scannable
      Returns:
      string array
    • moveTo

      public void moveTo(Object position) throws DeviceException
      Trigger a move/operation and block until completion. If this is overridden, asynchronousMoveTo must also be valid, and the externalToInternal conversion must be applied.
      Specified by:
      moveTo in interface Scannable
      Parameters:
      position -
      Throws:
      DeviceException
    • setExtraNames

      public void setExtraNames(String[] names)
      Description copied from interface: Scannable
      Sets the array of names returned by getExtraNames of this scannable.
      Specified by:
      setExtraNames in interface Scannable
      Parameters:
      names -
    • setInputNames

      public void setInputNames(String[] names)
      Description copied from interface: Scannable
      sets the array of names returned by getInputNames method of this scannable.
      Specified by:
      setInputNames in interface Scannable
      Parameters:
      names -
    • setLevel

      public void setLevel(int level)
      Description copied from interface: Scannable
      Used for ordering the operations of Scannables during scans
      Specified by:
      setLevel in interface Scannable
      Parameters:
      level -
    • setOutputFormat

      public void setOutputFormat(String[] names)
      Description copied from interface: Scannable
      Sets the array of strings describing how best to format the positions from this scannable
      Specified by:
      setOutputFormat in interface Scannable
      Parameters:
      names -
    • stop

      public void stop() throws DeviceException
      Stop the current move/operation. Default behaviour is to do nothing. Inheriting classes have the option to implement this if their specific behaviour requires it.
      Specified by:
      stop in interface Scannable
      Throws:
      DeviceException
      See Also:
    • toString

      public String toString()
      Overrides:
      toString in class Object
    • toFormattedString

      public String toFormattedString()
      Description copied from interface: Scannable
      Returns a string representation of the Scannable and its current position/value/status

      Typically should return:

      name : position

      or for detectors, name : status

      If the position/status cannot be determined, the function should return Scannable.VALUE_UNAVAILABLE in its place.

      Specified by:
      toFormattedString in interface Scannable
      Returns:
      string as defined above
    • waitWhileBusy

      public void waitWhileBusy() throws DeviceException, InterruptedException
      Returns when operation carried out by moveTo has completed If this is to be overriden, isBusy must also be valid. Although the pos and scan command currently use this method to determine if the Scannable is busy, this must not be relied upon.
      Specified by:
      waitWhileBusy in interface Scannable
      Throws:
      DeviceException
      InterruptedException
    • waitWhileBusy

      public void waitWhileBusy(double timeoutInSeconds) throws DeviceException, InterruptedException
      Its like waitWhileBusy, has a timeout and will throws a DeviceException if the time limit is reached.
      Parameters:
      timeoutInSeconds -
      Throws:
      DeviceException
      InterruptedException
    • checkPositionValid

      public String checkPositionValid(Object illDefinedPosObject) throws DeviceException
      This default behaviour should be extended by most subclasses! Tests if the given object is meaningful to this Scannable and so could be used by one of the move commands. May check limits and other things too. This is the method called by scans on all points before the scan is run.
      Specified by:
      checkPositionValid in interface Scannable
      Parameters:
      illDefinedPosObject -
      Returns:
      null if position is valid, or returns a description if not.
      Throws:
      DeviceException
      See Also:
    • throwExceptionIfInvalidTarget

      protected void throwExceptionIfInvalidTarget(Object position) throws DeviceException
      Throws:
      DeviceException
    • isAt

      public boolean isAt(Object positionToTest) throws DeviceException
      Tests if the scannable is at (or if appropriate, close to) the value positionToTest. If positionToTest is a string (as will be the case for valves or pneumatics for example), this is compared to the value obtained from getPosition(). An exception is thrown if this is not also a string.

      Otherwise if positionToTest is not a string the object is compared to the value from getPosition(), after having first pushed both values through objectToArray() from ScannableUtils.

      This behaviour should be extended where possible, and has been in ScannableMotionBase

      Specified by:
      isAt in interface Scannable
      Parameters:
      positionToTest - The position to compare the scannable's position to.
      Returns:
      true if scannable is at positionToTest
      Throws:
      DeviceException
      See Also:
    • setScanMetadataAttribute

      public void setScanMetadataAttribute(String attributeName, Object value) throws DeviceException
      Sets the scan attribute with the given name to the given value. A scan attribute is an attribute that should be written into the scan output (e.g. a NeXus file). The type of the value can be:
      • a dataset;
      • a primitive type supported by datasets;
      • an array whose component type that is supported by datasets;
      • a list whose element type is supported by datasets.

      There are two special attributes, 'NXclass' and 'nexusCategory'. If set these attributes are not written into the nexus file as fields. Instead the control how the nexus object is created and added to the nexus tree. Specifically:

      • 'NXclass' specifies what Nexus base class the nexus object has;
      • 'nexusCategory' specifies the class of the parent group the nexus object is added to, e.g. if this attribute has the value 'NXsample' then the nexus object will be added to the NXsample group.
      Note: this is a temporary mechanism to allow GDA8 devices to work with the new scanning framework. It should be removed once GDA9 scans use templates to write Nexus files.

      Sets the entry for this attribute name in the map. Subclasses may override.

      Specified by:
      setScanMetadataAttribute in interface Scannable
      Parameters:
      attributeName - attribute name
      value - value of attribute
      Throws:
      DeviceException - if the attribute could not be set for any reason
    • getScanMetadataAttribute

      public Object getScanMetadataAttribute(String attributeName) throws DeviceException
      Returns the value of the scan attribute, or null if no such attribute exists (or if the value of the attribute is null) The type of the value returned can be:
      • a dataset;
      • a primitive type supported by datasets;
      • an array whose component type that is supported by datasets;
      • a list whose element type is supported by datasets.

      Note: this is a temporary mechanism to allow GDA8 devices to work with the new scanning framework. It should be removed once GDA9 scans use templates to write Nexus files.

      Sets the entry for this attribute name in the map. Subclasses may override.

      Specified by:
      getScanMetadataAttribute in interface Scannable
      Parameters:
      attributeName - the name of the attribute
      Throws:
      DeviceException - if the value of the attribute could not be retrieved for any reason
    • getScanMetadataAttributeNames

      public Set<String> getScanMetadataAttributeNames() throws DeviceException
      Returns the name of the scan attributes. These are the attributes that should be written into the scan output (e.g. a NeXus file).

      Note: this is a temporary mechanism to allow GDA8 devices to work with the new scanning framework. It should be removed once GDA9 scans use templates to write Nexus files.

      Sets the entry for this attribute name in the map. Subclasses may override.

      Specified by:
      getScanMetadataAttributeNames in interface Scannable
      Returns:
      names of scan attributes
      Throws:
      DeviceException - if the names of the scan attributes could not be retrieved for any reason
    • setScanMetadataAttributes

      public void setScanMetadataAttributes(Map<String,Object> attributes) throws DeviceException
      Specified by:
      setScanMetadataAttributes in interface Scannable
      Throws:
      DeviceException
    • getScanMetadataAttributes

      public Map<String,Object> getScanMetadataAttributes() throws DeviceException
      Specified by:
      getScanMetadataAttributes in interface Scannable
      Throws:
      DeviceException
    • valueUnavailableString

      protected String valueUnavailableString()
      Name/value string that can be used by toFormattedString() when getting current value/position fails
    • __call__

      public org.python.core.PyObject __call__() throws DeviceException
      Returns:
      the position of this object as a native or array of natives
      Throws:
      DeviceException
      See Also:
      • PyObject.__call__()
    • __call__

      public org.python.core.PyObject __call__(org.python.core.PyObject new_position) throws DeviceException
      Moves the scannable to new_position when a scannable(new_position) call is made from Python
      Parameters:
      new_position -
      Returns:
      a message explaining what happened
      Throws:
      DeviceException
      See Also:
      • PyObject.__call__(org.python.core.PyObject)
    • __len__

      public int __len__()
      Returns:
      the size of input names. This is intentional as slicing should only work over input parameters. (A design request)
    • __getitem__

      public org.python.core.PyObject __getitem__(org.python.core.PyObject index) throws org.python.core.PyException
      Parameters:
      index - a number or a PySlice object
      Returns:
      the part of the objects array of position as defined by index
      Throws:
      org.python.core.PyException
    • __str__

      public String __str__()
      Jython method to return string description of the object
      Returns:
      the result of the toString method
    • __repr__

      public String __repr__()
      Jython method to return a string representation of the object
      Returns:
      the result of the toString method
    • __doc__

      public String __doc__()
      Returns:
      the name of the scannable