Acquisition chain¶
Used by a Scan
object, the AcquisitionChain
object is a tree
describing triggering relations between acquisition objects.
Note
- An AcquisitionChain can only be run once by a scan.
- It’s sometimes needed to control the state of devices like shutter, multiplexer, or detector cover. Those devices should be controlled with Preset objects.
Building the chain¶
The AcquisitionChain
tree is built by inserting acquisition objects into the chain.
Inserted acquisition objects must inherit from
AcquisitionMaster or
AcquisitionSlave.
Acquisition objects are inserted using the add(parent_obj, child_obj)
method of
the AcquisitionChain
object, where parent_obj
is the object under which
child_obj
object should be inserted.
If parent_obj
is not already in the chain, it will be added as a top master.
If child_obj
is not provided, parent_obj
is added as a top master.
Build a chain for a simple loop scan
from bliss.scanning import chain
from bliss.scanning.acquisition.timer import SoftwareTimerMaster
from bliss.scanning.acquisition.counter import SamplingCounterAcquisitionSlave
acq_chain = chain.AcquisitionChain()
timer = SoftwareTimerMaster(1, npoints=2)
counter_device = SamplingCounterAcquisitionSlave(diode, count_time=1, npoints=2)
acq_chain.add(timer, counter_device)
print(acq_chain._tree)
Out [4]:
acquisition chain
└── timer
└── simulation_diode_sampling_controller
Run the scan using the chain
from bliss.scanning.scan import Scan
s = Scan(acq_chain, name='simple loop', scan_info={}, save=False)
s.run()
s.get_data()
Out [12]: {'elapsed_time': array([0. , 1.0063]),
'diode': array([11.59349, -6.2747])}
Build a chain for a one-axis step-by-step scan
from bliss.scanning import chain
from bliss.scanning.acquisition.timer import SoftwareTimerMaster
from bliss.scanning.acquisition.counter import SamplingCounterAcquisitionSlave
from bliss.scanning.acquisition.motor import LinearStepTriggerMaster
acq_chain = chain.AcquisitionChain()
motor_master = LinearStepTriggerMaster(2,robz,0,1)
timer = SoftwareTimerMaster(1, npoints=2)
counter_device = SamplingCounterAcquisitionSlave(diode, count_time=1, npoints=2)
acq_chain.add(motor_master, timer)
acq_chain.add(timer, counter_device)
print(acq_chain._tree)
Out [12]:
acquisition chain
└── axis
└── timer
└── simulation_diode_sampling_controller
See custom scans section for more advanced acquisition chain examples
Display chain tree¶
A print()
on the tree
property of the acquisition chain object,
displays the acquisition tree.
Print the acquisition chain tree
DEMO [1]: s = ascan(robz, 0, 1, 10, 0.1, diode2, diode3, run=False)
DEMO [2]: print(s.acq_chain.tree)
acquisition chain
└── axis
└── timer
└── simulation_diode_sampling_controller
Scan iterations¶
During the scanning procedure iterations, specific methods are called
on each acquisition object composing the acquisition chain (see AcquisitionChainIter
).
The calls can be made down-stream (from top-master to slaves) or up-stream (from slaves to top-master).
One method calls can be sequential or parallelized over chain objects.
At each scan iteration, these acquisition object methods are called:
acq_prepare
: device preparation (up-stream)acq_start
: starts acquisition on device (up-stream)acq_wait_ready
: block until device is ready for next scan iteration (down-stream)
At the beginning of a scan, apply_parameters
(up-stream) and acq_wait_ready
(down-stream) are also called on chain objects.
At the end of the scan acq_stop
is called once per acquisition object (down-stream).
A master acquisition object may call trigger_slaves
in its trigger
method.
If so, this will call the acq_trigger
method of its children nodes if children
objects are using a trigger_type == TRIGGER_MODE_ENUM.SOFTWARE
.
Monitor iterations calls¶
Acquisition object methods called during scan iterations can be
displayed using the bliss.scans
logger.
Monitor acquisition objects methods called during a scan
DEMO [1]: s = loopscan(2,1,diode,diode2,run=False)
DEMO [2]: debugon('bliss.scans')
DEMO [3]: s.run()
DEBUG 29,288 Scan: Start timer.wait_ready
DEBUG 29,289 Scan: End timer.wait_ready Took 0.000449s
DEBUG 29,289 Scan: Start diode.wait_ready
DEBUG 29,289 Scan: Start simulation_diode_controller.wait_ready
DEBUG 29,290 Scan: End diode.wait_ready Took 0.000545s
DEBUG 29,290 Scan: End simulation_diode_controller.wait_ready Took 0.000495s
Scan 11 Wed Mar 06 24 2019 /tmp/scans/test_session/data.h5
test_session user = seb
loopscan 2 1
# dt[s] diode diode2
DEBUG 29,314 Scan: Start simulation_diode_controller.prepare
DEBUG 29,314 Scan: End simulation_diode_controller.prepare Took 0.000120s
DEBUG 29,314 Scan: Start diode.prepare
DEBUG 29,314 Scan: End diode.prepare Took 0.000040s
DEBUG 29,314 Scan: Start timer.prepare
DEBUG 29,315 Scan: End timer.prepare Took 0.000033s
DEBUG 29,315 Scan: Start simulation_diode_controller.start
DEBUG 29,315 Scan: End simulation_diode_controller.start Took 0.000536s
DEBUG 29,315 Scan: Start diode.start
DEBUG 29,316 Scan: End diode.start Took 0.000395s
DEBUG 29,316 Scan: Start timer.start
DEBUG 29,316 Scan: Start timer.trigger_slaves
DEBUG 29,316 Scan: End timer.trigger_slaves Took 0.000090s
DEBUG 29,317 Scan: Start diode.trigger
DEBUG 29,317 Scan: End diode.trigger Took 0.000062s
DEBUG 29,317 Scan: Start simulation_diode_controller.trigger
DEBUG 29,317 Scan: End simulation_diode_controller.trigger Took 0.000037s
DEBUG 29,318 Scan: Start timer.wait_slaves
DEBUG 29,318 Scan: End timer.wait_slaves Took 0.000249s
DEBUG 30,319 Scan: End timer.start Took 1.002655s
DEBUG 30,320 Scan: Start timer.wait_ready
DEBUG 30,321 Scan: End timer.wait_ready Took 0.000566s
DEBUG 30,322 Scan: Start diode.wait_ready
DEBUG 30,322 Scan: Start simulation_diode_controller.wait_ready
DEBUG 30,323 Scan: End diode.wait_ready Took 0.001143s
DEBUG 30,323 Scan: End simulation_diode_controller.wait_ready Took 0.001143s
DEBUG 30,324 Scan: Start timer.prepare
DEBUG 30,325 Scan: End timer.prepare Took 0.000302s
DEBUG 30,326 Scan: Start timer.start
DEBUG 30,327 Scan: Start timer.trigger_slaves
DEBUG 30,327 Scan: End timer.trigger_slaves Took 0.000420s
DEBUG 30,328 Scan: Start diode.trigger
DEBUG 30,329 Scan: End diode.trigger Took 0.000344s
DEBUG 30,329 Scan: Start simulation_diode_controller.trigger
DEBUG 30,329 Scan: End simulation_diode_controller.trigger Took 0.000291s
DEBUG 30,332 Scan: Start timer.wait_slaves
DEBUG 30,334 Scan: End timer.wait_slaves Took 0.001394s
0 0 3.52747 -2.57778
DEBUG 31,329 Scan: End timer.start Took 1.002674s
DEBUG 31,331 Scan: Start timer.wait_ready
DEBUG 31,331 Scan: End timer.wait_ready Took 0.000565s
DEBUG 31,332 Scan: Start diode.wait_ready
DEBUG 31,332 Scan: Start simulation_diode_controller.wait_ready
DEBUG 31,339 Scan: End simulation_diode_controller.wait_ready Took 0.006308s
DEBUG 31,339 Scan: End diode.wait_ready Took 0.007317s
DEBUG 31,340 Scan: Start timer.wait_slaves
DEBUG 31,340 Scan: End timer.wait_slaves Took 0.000504s
1 1.01025 -1.74157 10.4382
DEBUG 31,349 Scan: Start timer.stop
DEBUG 31,350 Scan: End timer.stop Took 0.000574s
DEBUG 31,351 Scan: Start diode.stop
DEBUG 31,352 Scan: End diode.stop Took 0.000701s
DEBUG 31,352 Scan: Start simulation_diode_controller.stop
DEBUG 31,352 Scan: End simulation_diode_controller.stop Took 0.000295s
DEBUG 31,353 Scan: Start timer.wait_slaves
DEBUG 31,354 Scan: End timer.wait_slaves Took 0.000611s
Took 0:00:06.935785