}
--- pycdb module ---
class pycdb.Db(path)
Initializes access to the configuration database residing at 'path'.
Members:
get(key=<Integer> or alias=<string>,
src=<Integer> or level=<Integer>, typeid=<Integer>) or
get(key=<Integer> or alias=<string>,
typeid=<Integer>)
Returns a tuple of configuration datum which satisfies the
search criteria. The search criteria is composed of either
a particular database key number (integer) or alias name
(for example, "BEAM"), an integer detector id 'src' or level
(for example, 0=control), and an integer typeid
(for example, 0x00050008 = Evr configuration version 5).
The Python type of each returned object is specific to the
datum returned { pycdb.DiodeFexConfig, pycdb.CspadConfig, ... }.
set(alias, datum)
Inserts the configuration 'datum' into the database for the
global entry 'alias' (for example, "BEAM").
commit()
Updates all current run keys with the data inserted via calls to 'set'.
clone(key)
Returns a new database key created as a copy of the existing key 'key'.
The returned key is suitable for modifying via calls to 'substitute'.
substitute(key, datum)
Insert the configuration 'datum' only for the given database 'key'.
{code}
h3. Controlling the DAQ - the 'pydaq' module
An example script for controlling the DAQ through a scan follows:
{code}
import pydaq
if __name__ == "__main__":
host = 'xpp-daq' # host name running the DAQ control process
platform = 0 # DAQ identifier
cycles = 100 # number of iterations in the scan
nevents = 105 # number of events at each iteration
do_record = False # option to record the data
daq = pydaq.Control(host,platform) # Connect to the DAQ control process
daq.configure(record=do_record, # Configure the DAQ with the scan information,
events=nevents, # number of events per scan cycle,
controls=[('EXAMPLEPV1',0),('EXAMPLEPV2',0)]) # list of scan variables and current values
print "Configured."
#
# Wait for the user to declare 'ready'
# Setting up monitoring displays for example
#
ready = raw_input('--Hit Enter when Ready-->')
for cycle in range(options.cycles): # Loop over the scan cycles
print "Cycle ", cycle
pv1 = cycle # Change the scan variable
pv2 = 100-cycle # For example, move a motor with EPICS.
daq.begin(controls=[('EXAMPLEPV1',pv1), # Acquire the events with the
('EXAMPLEPV2',pv2)]) # list of scan variables and their values.
# enable the EVR sequence, if necessary
daq.end() # Wait for the events to complete
# disable the EVR sequence, if necessary
if (do_record==True):
print 'Recorded expt %d run %d' % (daq.experiment(),daq.runnumber())
#
# Wait for the user to declare 'done'
# Saving monitoring displays for example
#
ready = raw_input('--Hit Enter when Done-->')
{code}
The previous script simply reports the change in the scan variables to the DAQ and acquires the indicated number of events for each scan point. A more complete implementation would include code that controls the motors/devices that the scan variables represent (through 'pyca', for example). Alternatively, the scan may be designed to vary the DAQ configuration (a trigger delay scan, for example); this can be accomplished in conjunction with the 'pycdb' module. In addition, the implementation may wish to retrieve the accumulated data at each step for scripted processing or plotting; this is described in the next section ('pyami' module).
The complete pydaq module programmer's description:
{code}
--- pydaq module ---
class pydaq.Control(host, platform=0)
Arguments:
'host' : host name or IP address (dotted-string notation or integer)
'platform' : DAQ platform number (subdivision of readout hardware)
Function:
Initializes the interface for controlling the data acquisition system remotely.
Creates a connection with the local control and queries the configuration
database and current key in use.
Members:
Control.dbpath()
Returns path to configuration database
Control.dbkey()
Returns current key in use
Control.configure(record=<Bool>,
key=<Integer>,
events=<Integer> or duration=[seconds,nanoseconds],
controls=[(name,value)],
monitors=[(name,lo_range,hi_range)])
Configures control to use database key (default to current key) either:
(1) collecting a fixed number of events on each cycle (when events=<Integer>
is specified) or
(2) collection events for a fixed duration (when duration=[seconds,nanoseconds]
is specified).
The list of variables controlled (optional) in the scan and
the list of variables to be monitored (optional) during acquisition
are specified.
The option to record can also be set. If it is omitted, then the value from
the local control is used.
Control.begin(events=<Integer> or duration=[seconds,nanoseconds],
controls=[(name,value)],)
monitors=[(name,lo_range,hi_range)])
Begins acquisition for the specified settings of control variables (if specified).
Actual control of these variables is the responsibility of the remote application.
Monitor variables (optional) are enforced during acquisition. Omitted values
default to those specified most recently (or in the 'configure' method).
Control.end()
Waits for the end of acquisition signalled from the local host control.
Control.experiment()
Returns experiment number of run, if recorded.
Only valid after acquisition is complete.
Control.runnumber()
Returns run number, if recorded.
Only valid after acquisition is complete.
{code}
h3. Monitoring the Data - the 'pyami' module
An example script (not very useful) for retrieving data accumulated by the monitoring follows:
{code}
import pyami
class AmiScalar(pyami.Entry): # subclass for readability
def __init__(self,name):
pyami.Entry.__init__(self,name)
class AmiAcqiris(pyami.Entry): # subclass for readability
def __init__(self,detid,channel):
pyami.Entry.__init__(self,detid,channel)
eth_lo = 0x7f000001
eth_mc = 0xefff2604
CxiAcq = 0x18000200 # detector identifier for CxiEndstation Acqiris readout
if __name__ == "__main__":
pyami.connect(eth_lo,eth_lo,eth_mc) # example parameters for a monitoring playback job
x = AmiScalar("ProcTime") # accumulate (events,mean,rms) for 'ProcTime' scalar variable
x.get() # return accumulated data
x = AmiAcqiris(CxiAcq,1) # accumulate averaged waveform for Cxi Acqiris readout module
x.get() # return accumulated waveform
{code}
The pyami module programmer's description:
{code}
-- pyami module --
connect(CDS_interface, FEZ_interface, Server_Group)
Connects the module to the group of monitoring servers.
The input parameters are specific to the hutch.
This must be called before any of the following class methods.
class pyami.Entry(name,'Scalar')
Monitors data from the scalar variable 'name'. A tuple of
('Scalar', n_events, mean, rms) is accumulated.
class pyami.Entry(name,'TH1F',nbins,xlo,xhi)
Monitors data from the scalar variable 'name'. A tuple of
('TH1F', underflows, overflows, ( n_bin0, n_bin1, ...)) is accumulated.
class pyami.Entry(det_identifier) or
class pyami.Entry(det_identifier,channel)
Monitors the data from the detector associated with 'det_identifier' and
'channel'. A tuple of data averaged over events is accumulated. The
dimensions and binning of the data are determined from the detector.
The tuple format is
('Waveform', events, xlow, xhigh, (y0, y1, ...)) or
('Image', events, dark_level, ppxbin, ppybin,
((row0col0,row0col1,...),(row1col0,row1col1,...))) or
('ImageArray', events, dark_level, ppxbin, ppybin,
( ((row0col0,row0col1,...),(row1col0,row1col1,...))_0,
((row0col0,row0col1,...),(row1col0,row1col1,...))_1,
... ))
Each of the above methods also takes an optional final string argument that
defines an event filter. The string must take the form:
_lo_value_<_scalar_name_<_hi_value_ or
(_expr1_)&(_expr2_) or
(_expr1_)|(_expr2_)
where _expr1_ and _expr2_ also take one of the forms.
Members:
Entry.get()
Returns the data accumulated since the object was created.
{code} |