Core Acquaman Classes - acquaman/acquaman GitHub Wiki

This page details some of the core classes within Acquaman, in an attempt to introduce new team members to the structure of the system, as well as a reference for more experienced team members.

AMDbObject

All Acquaman classes which can be stored to the database for later retrieval are subclasses (directly or indirectly) of AMDbObject. By inheriting from AMDbObject it is possible to store member variables in a consistent way, and not worry about the specifics of saving or reloading them.

In order to define a member variable that should be stored to the database, the Q_PROPERTY macro is used, e.g.

    class SGMPersistantObject : public AMDbObject {
        Q_OBJECT                 // Usual Q_OBJECT macro, as AMDbObject is of QObject type
        Q_PROPERTY(QString description READ description WRITE setDescription)
    protected:
        QString description_;    // The variable we wish to store
    public:
        QString description();   // The usual getter
        void setDescription(const QString& newValue);    // The usual setter
    };

The above example will ensure that a text field is written to the database called Description

AMAction

Acquaman uses a state machine class to create and run workflow actions. Classes which define Actions must inherit from AMAction3, and implement the pure virtual functions defined therein:

public:
	virtual bool hasChildren() const = 0;
	virtual int numberOfChildren() const = 0;
protected:
	virtual void startImplementation() = 0;
	virtual void pauseImplementation() = 0;
	virtual void resumeImplementation() = 0;
	virtual void cancelImplementation() = 0;	
	virtual void skipImplementation(const QString &command) = 0;

Note Full documentation for these functions can be found in AMAction3

All Actions operate on classes derived from AMActionInfo3, which each hold the persistent information on a scan and, being themselves AMDbObject derived, can store this information to the database.

Actions are started by calling their run() function, or created and then placed in the workflow in order to be run at a later time. Some classes contain helper functions that create and return pre-created Actions, for example AMAction3* CLSSIS3820Scaler::createStartAction(), which returns an action, and can be passed to a class which never needs to know anything about the CLSSIS3920Scaler class.

AMControl

AMControl is an interface class for any piece of equipment on the beamlines that can be read from, or possibly moved in some fashion (motors, pressure readers etc.). This class is subclassed by a number of AMPVControl classes, which provide the standard AMControl interface, but for EPICS PVs. AMControls interface features such things as:

  • value()
  • units()
  • isConnected() etc.

For a full definition of the AMControl interface, see the AMControl.h file.

AMDetector

AMDetector is an abstract class which is used to work with detectors on the beamline from which you wish to acquire data. Most detectors have their own derived class which implements the methods specified in AMDetector (see AMXRFDetector,VESPERSFourElementVortexDetector, CLSBasicScalerChannelDetector). This interface is generally used as a model to be visualized in some form (eg. a widget to readout the data in a human comprehensible form) or within the scan engine itself, to collect data.

AMAppController

AMAppController (and its derived classes, SGMAppController, VESPERSAppController, REIXSAppController etc.) represents the central controlling window in which Acquaman's GUI is run. All startup functions for a given instance of Acquaman are invoked in AMAppController. AMAppController itself inherits from AMDatamanAppController, which invokes all the startup methods which are required for all Acuqman instances (eg. database initializaton).

AMErrorMon

As Acquaman framework programmers and users we try to do a good job of reporting errors to users and making them easy for us to diagnose after the fact. If there are places that things can go wrong, you should make a call to AMErrorMon to display this to the screen. By using a unique error code, the time to diagnose problems can be reduced from hours to seconds. AMErrorMon reports are split into different levels of severity:

  • Information ~ Simply provides an extra means of communicating information to the user
  • Alert ~ Warns the user that something may not be as they, or Acquaman expects. A detector is not connected, for instance
  • Serious ~ Something is definitely wrong. Should be displayed in a prominent way when you call it.
  • Debug ~ Used by a programmer who is trying to diagnose an issue, and wants a readout of a value at runtime.

Usually AMErrorMon codes are defined in an appropriate place (for example a header file for the class that is using them, or a namespace header that pertains to a group of classes, if multiple are to call it) and given some unique number:

SomeWidget.h

#define AMBEAMLINE_IS_ON_FIRE 666666

this code can then be referred to in the class that includes SomeWidget.h

AMErrorMon::alert(this, AMBEAMLINE_IS_ON_FIRE, "I'd get my coat if I was you.");