You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 22 Next »

Finite Burst Sequence With 1 Slow Andor

Summary: A 33kHz beam train simulation (28 buckets between shots) with a starting gap of 14000 buckets to allow a periodic 1Hz Andor to readout while not receiving beam.  A 100Hz trigger is added for other non-integrating detectors (e.g. opals).  Each sequence is repeated twice, although there appears to be an "off by one" difference in the definition of the repeat count of traingenerator (repeat=2) and periodicgenerator (repeat=1).  The "--notify" flag on periodic generator tells the DAQ to end the scan step after that finite sequence is complete after 2 andor images.  The andor "shutter" is always open, so the trigger event-code starts the readout.  The first andor trigger in the first step clears out old charge at the beginning so the very first image data is "corrupted".  Note that 14000+32000*28=910000 (14000 is starting gap for andor readout, and 32000 shots 28 buckets apart adds up to the 910000 buckets that the accelerator always repeats on every 0.98 seconds).  The number of beam shots is set to 32001 instead of 32000 because without this there would be no high-rate beam shot at the same time as the andor trigger (this can be seen with seqbrowser.py): there is a requirement in the DAQ that the highest rate trigger must show up in every event, except for rare cases of deadtime.

export EPICS_PVA_ADDR_LIST=172.21.152.78 (allows rix-daq to talk to the XPM, e.g. to program sequences)

source /cds/group/pcds/dist/pds/rix/scripts/setup_env.sh
traingenerator -s 14000 -b 28 -n 32001 -r 2 -d "burst" -t 910000 >& /tmp/beam.py
periodicgenerator -p 910000 9100 -s 0 0 -d '1Hz' '100Hz' --repeat 1 --notify >& /tmp/codes.py 
seqprogram --seq 0:/tmp/codes.py 3:/tmp/beam.py --pv DAQ:NEH:XPM:3

beam.py is a simulation of a 33kHz beam, while codes.py is used to generate triggers for two cameras, one of which is an integrating-over-shots andor.

The output of "python tools/seqbrowser.py --seq 0:codes.py 3:beam.py --time 2.0" looks like:

Command to view the status of the sequence (note that for this run the simulated-beam event code 284 was running at 10kHz, not the 33kHz in the example above):

rix-daq:~> pvget DAQ:NEH:XPM:3:SEQCODES
DAQ:NEH:XPM:3:SEQCODES 2023-05-22 17:26:52.369    
EventCode Description  Rate Enabled
      272                 1       1
      273               102       1
      274                 0       1
      275                 0       1
      276                 0       0
      277                 0       0
      278                 0       0
      279                 0       0
      280                 0       0
      281                 0       0
      282                 0       0
      283                 0       0
      284             10206       1
      285                 0       1
      286                 0       1
      287                 0       1
rix-daq:~> 

Command to start a sequence that has ended (note that 9=(8<<3) | (1<<0) so sequence engines 3 and 0 are restarted):

pvput DAQ:NEH:XPM:3:SeqReset 9

Or one can add "--start" to the seqprogram command.

A hutch-python scan (using the finite sequences generated by traingenerator.py/burstgenerator.py):

In [4]: daq.configure(motors=[sim.fast_motor1],group_mask=0x24, events=0, detname='andor_norm_0', seq_ctl=['DAQ:NEH:XPM:3:SeqReset',9,'DAQ:NEH:XPM:3:SeqDone'])
INFO     configure - configure: 1 motors
INFO     configure - Found readout group 5 for andor_norm_0.
Out[4]: ({}, {})
In [5]: RE(bp.scan([daq], sim.fast_motor1, -10, 10, 5))

An example run for this mode is rixx1003821 run 68 which has been made public in the directory /cds/data/psdm/prj/public01/xtc/.  A simple analysis script counting events along with output is:

(ps-4.5.26) drp-srcf-eb009:lcls2$ python junk5.py
nstep/nevent/nnorm 0 64001 2
nstep/nevent/nnorm 1 64001 2
nstep/nevent/nnorm 2 64001 2
nstep/nevent/nnorm 3 64001 2
nstep/nevent/nnorm 4 64001 2

(ps-4.5.26) drp-srcf-eb009:lcls2$ cat junk5.py
from psana import DataSource
import datetime as dt
import numpy as np
import sys

ds = DataSource(exp='rixx1003821',run=68,dir='/cds/data/psdm/prj/public01/xtc')
myrun = next(ds.runs())
andor_norm = myrun.Detector('andor_norm')

for nstep,step in enumerate(myrun.steps()):
    nnorm = 0
    for nevent,evt in enumerate(step.events()):
        norm_value = andor_norm.raw.value(evt)
        if norm_value is not None: nnorm+=1
    print('nstep/nevent/nnorm',nstep,nevent,nnorm)
(ps-4.5.26) drp-srcf-eb009:lcls2$ 

Infinite Sequence With 2 Different Slow Andor Rates

The only way to stop a running infinite sequence is to program another sequence.

  • python psdaq/psdaq/seq/rixgeneratory.py --periods 1.0 0.01  (units in seconds).  Generates three files beam.py, codes.py and codes2.py in the current directory which should be programmed with "seqprogram".
    • beam.py simulates the beam pattern with gaps left for reading out both the fast and slow andor (eventually programmed on the accelerator side)
    • codes.py generates periodic triggers for a low rate andor and a high rate andor, but the high rate andor continues (needlessly) reading out when the beam is stopped for the low rate andor (see next point for solution)
    • codes2.py generates periodic triggers for the high rate andor, but avoids triggering it when the beam is inhibited for the slow andor readout.  because of this it is called "fast gated andor" in codes2.py 
  • seqprogram --seq 0:codes.py 1:codes2.py 3:beam.py --pv DAQ:NEH:XPM:3 --start
(ps-4.5.26) rix-daq:scripts> pvget DAQ:NEH:XPM:3:SEQCODES
DAQ:NEH:XPM:3:SEQCODES 2023-06-09 19:20:09.502    
EventCode        Description  Rate Enabled
      272       "Slow Andor"     1       1
      276 "Fast Andor Gated"    63       1
      284      "Bunch Train" 10206       1

The output of "python tools/seqbrowser.py --seq 0:codes.py 1:codes2.py 3:beam.py --time 4.0" looks like this:

Running a standalone daq step-scan (no hutch-python).  The number "9" corresponds to two bits: 9=8+1, or 9=(1<<3) | (1<<0), where 3 and 0 are the two sequence engines that have been programmed with seqprogram above.  The "-g" argument is for the readout groups in the partition (2,5): 36=(1<<5) | (1<<2).

python psdaq/psdaq/control/rix_bluesky_scan.py -p 2 -C drp-srcf-cmp004 -g 36 --detname andor_norm_0 --seqctl DAQ:NEH:XPM:3:SeqReset 9 DAQ:NEH:XPM:3:SeqDone

A hutch-python scan where the sequence runs continuously, recording 1 slow-andor event per step.  In this case the start of the DAQ acquisition in each step is asynchronous to the running sequence.

In [8]: daq.configure(motors=[sim.fast_motor1],group_mask=0x24, events=200, detname='andor_norm_0', record=True)
INFO     configure - configure: 1 motors
INFO     configure - Found readout group 5 for andor_norm_0.
Out[8]: ({}, {})

In [9]: RE(bp.scan([daq], sim.fast_motor1, -10, 10, 5))

An example run for this mode is rixx1003821 run 55 which has been made public in the directory /cds/data/psdm/prj/public01/xtc/.  A simple analysis script and associated output is here.  Since the sequence is running continuously the "phase" of the scan startup is random on each step with respect to the sequence, and so the number of beam shots and slow-andor triggers have some randomness, while the faster andor has a well defined number of events (200).

(ps-4.5.26) drp-srcf-eb009:lcls2$ python junk4.py
nstep/nevent/nnorm/ndir 0 32399 200 3
nstep/nevent/nnorm/ndir 1 32283 200 3
nstep/nevent/nnorm/ndir 2 32399 200 3
nstep/nevent/nnorm/ndir 3 32284 200 3
nstep/nevent/nnorm/ndir 4 32298 200 4

(ps-4.5.26) drp-srcf-eb009:lcls2$ more junk4.py
from psana import DataSource
import datetime as dt
import numpy as np
import sys

ds = DataSource(exp='rixx1003821',run=55,dir='/cds/data/psdm/prj/public01/xtc')
myrun = next(ds.runs())
andor_norm = myrun.Detector('andor_norm')
andor_dir = myrun.Detector('andor_dir')

for nstep,step in enumerate(myrun.steps()):
    nnorm = 0
    ndir = 0
    for nevent,evt in enumerate(step.events()):
        norm_value = andor_norm.raw.value(evt)
        dir_value = andor_dir.raw.value(evt)
        if norm_value is not None: nnorm+=1
        if dir_value is not None: ndir+=1
    print('nstep/nevent/nnorm/ndir',nstep,nevent,nnorm,ndir)
(ps-4.5.26) drp-srcf-eb009:lcls2$  
  • No labels