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

Compare with Current View Page History

« Previous Version 16 Next »

Finite Burst Sequence With 1 Slow Andor

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 91 91000 -s 0 0 -d '10kHz' '10Hz' --repeat 3 --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:

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 

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