Class ScannableGroup

All Implemented Interfaces:
Device, Scannable, IScannableGroup, Configurable, Findable, gda.observable.IObservable, gda.observable.IObserver
Direct Known Subclasses:
CoordinatedScannableGroup, Diffractometer, MiniKappaGoniometerScannableGroup, MotomanRobotScannableGroup, ScannableGroupNamed, ScannableGroupSinglePosition, SmarGonXyzScannableGroup, TpScannableGroup, XesSpectrometerCrystal

@ServiceInterface(IScannableGroup.class) public class ScannableGroup extends ScannableBase implements IScannableGroup, gda.observable.IObserver
A logical group of Scannables that allows multiple Scannables to be moved at the same time, or allows further validation for movement, e.g. MotomanRobotScannableGroup's validation on simultaneous KTheta, KPhi movement. inputNames, extraNames and outputFormat are taken from the constituent Scannables, not maintained as a field of the Group. A ScannableGroup is a logical group of Scannables that can be created through Spring instantiation or by adding Scannables from the Jython console. Configuring a ScannableGroup configures all of its component Scannables and adds itself as an IObserver, and the default behaviour of adding a Scannable to an already configured ScannableGroup is to configure the Scannable (although it can instead un-configure the group, allowing it to be configured again). ScannableGroups can add, remove or set Scannables by using the Scannables, and additionally can remove Scannables by their index. See also ScannableGroupNamed, which additionally uses the Finder to manage Scannables by name, a former function of this class
  • Constructor Details

  • Method Details

    • configure

      public void configure() throws FactoryException
      Description copied from class: ConfigurableBase
      Default implementation for classes that do not have to do any specific configuration.
      Classes that do their own configuration should *not* call this superclass function, as it may cause the object to appear configured before it really is.
      Specified by:
      configure in interface Configurable
      Overrides:
      configure in class ConfigurableBase
      Throws:
      FactoryException - if there is an error in configuration e.g. required variable not set or cannot connect to device
    • getGroupMemberNames

      public String[] getGroupMemberNames()
      Specified by:
      getGroupMemberNames in interface IScannableGroup
      Returns:
      the names of the members of this group
    • addGroupMember

      public void addGroupMember(Scannable groupMember) throws FactoryException
      Adds a scannable to this group. This will not add a Scannable if it is already included Will configure the Scannable if the ScannableGroup is already configured
      Specified by:
      addGroupMember in interface IScannableGroup
      Parameters:
      groupMember -
      Throws:
      FactoryException
    • addGroupMember

      public void addGroupMember(Scannable groupMember, boolean toConfigure) throws FactoryException
      Adds a scannable to this group. This will not add a Scannable if it is already included
      Specified by:
      addGroupMember in interface IScannableGroup
      Parameters:
      groupMember -
      toConfigure - - controls behaviour if the ScannableGroup is already configured: whether to configure the scannable (true) or set the ScannableGroue to be unconfigured (false)
      Throws:
      FactoryException
    • removeGroupMemberByScannable

      public void removeGroupMemberByScannable(Scannable groupMember)
      Specified by:
      removeGroupMemberByScannable in interface IScannableGroup
    • getGroupMembersAsArray

      public Scannable[] getGroupMembersAsArray()
      Specified by:
      getGroupMembersAsArray in interface IScannableGroup
      Returns:
      array of scannable objects in this group
    • getGroupMember

      public Scannable getGroupMember(String name)
      Parameters:
      name -
      Returns:
      the Scannable of the given name
    • setGroupMembers

      public void setGroupMembers(List<Scannable> groupMembers) throws FactoryException
      Sets the group members that make up this scannable group. If this ScannableGroup is configured, sets it to unconfigured, to allow all the scannables to be configured by call this.configure()
      Specified by:
      setGroupMembers in interface IScannableGroup
      Parameters:
      groupMembers - the group members
      Throws:
      FactoryException
    • setGroupMembersWithList

      public void setGroupMembersWithList(List<Scannable> groupMembers, boolean toConfigure) throws FactoryException
      Sets the group members that make up this scannable group.
      Specified by:
      setGroupMembersWithList in interface IScannableGroup
      Parameters:
      groupMembers - the group members
      Throws:
      FactoryException
    • setGroupMembersWithArray

      public final void setGroupMembersWithArray(Scannable[] groupMembers) throws FactoryException
      Sets the members of this group.

      This is final, as for historical reasons there are two setters on here, and it is natural to extend just one.

      See setGroupMembersWithList for configuration behaviour

      Specified by:
      setGroupMembersWithArray in interface IScannableGroup
      Parameters:
      groupMembers -
      Throws:
      FactoryException
    • __getattr__

      public Object __getattr__(org.python.core.PyString name)
      See __getattr__(String name).
    • asynchronousMoveTo

      public void asynchronousMoveTo(Object position) throws DeviceException
      Description copied from class: ScannableBase
      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
      Overrides:
      asynchronousMoveTo in class ScannableBase
      Parameters:
      position - Position to move to should have an element for each input field.
      Throws:
      DeviceException
    • extractPositionsFromObject

      protected Vector<Object[]> extractPositionsFromObject(Object position) throws DeviceException
      Throws:
      DeviceException
    • getPosition

      public Object getPosition() throws DeviceException
      Description copied from class: ScannableBase
      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
      Overrides:
      getPosition in class ScannableBase
      Returns:
      Current position with an element for each input and extra field. null if their are no fields.
      Throws:
      DeviceException
    • isBusy

      public boolean isBusy() throws DeviceException
      Description copied from interface: Scannable
      Check if the Scannable is moving/operating.
      Specified by:
      isBusy in interface Scannable
      Returns:
      true - if operation carried out by moveTo has not completed yet
      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
      Overrides:
      setExtraNames in class ScannableBase
      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
      Overrides:
      setInputNames in class ScannableBase
      Parameters:
      names -
    • 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
      Overrides:
      toFormattedString in class ScannableBase
      Returns:
      string as defined above
    • stop

      public void stop() throws DeviceException
      Description copied from class: ScannableBase
      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
      Overrides:
      stop in class ScannableBase
      Throws:
      DeviceException
      See Also:
    • update

      public void update(Object theObserved, Object changeCode)
      Acts as a fan-out for messages from the Scannables inside this group
      Specified by:
      update in interface gda.observable.IObserver
      See Also:
      • IObserver.update(java.lang.Object, java.lang.Object)
    • getExtraNames

      public String[] getExtraNames()
      Description copied from interface: Scannable
      Additional names for extra values that returned by getPosition().
      Specified by:
      getExtraNames in interface Scannable
      Overrides:
      getExtraNames in class ScannableBase
      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
      Overrides:
      getInputNames in class ScannableBase
      Returns:
      array of the names of the elements of the object returned by getPosition
    • 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
      Overrides:
      getOutputFormat in class ScannableBase
      Returns:
      string array
    • atPointEnd

      public void atPointEnd() throws DeviceException
      Description copied from class: ScannableBase
      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
      Overrides:
      atPointEnd in class ScannableBase
      Throws:
      DeviceException
      See Also:
    • atPointStart

      public void atPointStart() throws DeviceException
      Description copied from class: ScannableBase
      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
      Overrides:
      atPointStart in class ScannableBase
      Throws:
      DeviceException
      See Also:
    • atScanLineEnd

      public void atScanLineEnd() throws DeviceException
      Description copied from class: ScannableBase
      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
      Overrides:
      atScanLineEnd in class ScannableBase
      Throws:
      DeviceException
      See Also:
    • atScanEnd

      public void atScanEnd() throws DeviceException
      Description copied from class: ScannableBase
      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
      Overrides:
      atScanEnd in class ScannableBase
      Throws:
      DeviceException
      See Also:
    • atLevelMoveStart

      public void atLevelMoveStart() throws DeviceException
      Description copied from class: ScannableBase
      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
      Overrides:
      atLevelMoveStart in class ScannableBase
      Throws:
      DeviceException
      See Also:
    • atLevelStart

      public void atLevelStart() throws DeviceException
      Description copied from class: ScannableBase
      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
      Overrides:
      atLevelStart in class ScannableBase
      Throws:
      DeviceException
      See Also:
    • atLevelEnd

      public void atLevelEnd() throws DeviceException
      Description copied from class: ScannableBase
      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
      Overrides:
      atLevelEnd in class ScannableBase
      Throws:
      DeviceException
      See Also:
    • atCommandFailure

      public void atCommandFailure() throws DeviceException
      Description copied from class: ScannableBase
      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
      Overrides:
      atCommandFailure in class ScannableBase
      Throws:
      DeviceException
      See Also:
    • atScanStart

      public void atScanStart() throws DeviceException
      Description copied from class: ScannableBase
      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
      Overrides:
      atScanStart in class ScannableBase
      Throws:
      DeviceException
      See Also:
    • atScanLineStart

      public void atScanLineStart() throws DeviceException
      Description copied from class: ScannableBase
      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
      Overrides:
      atScanLineStart in class ScannableBase
      Throws:
      DeviceException
      See Also:
    • checkPositionValid

      public String checkPositionValid(Object illDefinedPosObject) throws DeviceException
      Description copied from class: ScannableBase
      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
      Overrides:
      checkPositionValid in class ScannableBase
      Parameters:
      illDefinedPosObject -
      Returns:
      null if position is valid, or returns a description if not.
      Throws:
      DeviceException
      See Also:
    • waitWhileBusy

      public void waitWhileBusy() throws DeviceException, InterruptedException
      Description copied from class: ScannableBase
      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
      Overrides:
      waitWhileBusy in class ScannableBase
      Throws:
      DeviceException
      InterruptedException
    • removeGroupMemberByIndex

      public void removeGroupMemberByIndex(int index)
      Specified by:
      removeGroupMemberByIndex in interface IScannableGroup
    • toString

      public String toString()
      Overrides:
      toString in class ScannableBase
    • getGroupMembers

      public List<Scannable> getGroupMembers()
      Specified by:
      getGroupMembers in interface IScannableGroup
    • isDemandAllScannablePositions

      public boolean isDemandAllScannablePositions()
    • setDemandAllScannablePositions

      public void setDemandAllScannablePositions(boolean demandAllScannablePositions)
    • getUnits

      public String[] getUnits()
      Specified by:
      getUnits in interface IScannableGroup
      Returns:
      units corresponding to each field name.