PBSwissMX

This repository is used by the SwissMX application.
A complete list of SwissMX repositories dependencies is shown in grp-sf_cristallina/SwissMX.git.

PBSwissMX contains python application and executables to:

  • generate trajectories and motion programs for SwissMX (shapepath.py and helicalscan.py[obsolete])
  • motion synchronization executables (triggerSync) for Deltatau
  • analyse recorded trajectories on SwissMX (ShapePathAnalyser)
  • motor tuning tools (MXTuning)
  • documentation about the tuning results (MXfastStageDoc)

motion start/framesynchronization (update31.10.24)

For more details about triggerSync read: src/triggerSync/Readme.md

Important used vaiables:

Coord[1].Q[0] : sync points indicator: (at whick point is the motion program)
               val: desc                                    set in code
                -3: waiting at start position               motion code generated in MXMotion.py:setup_sync(mode=?)
                -2: got start trigger                       triggerSync.c:trigsync_func(mode&1) else motion code generated in MXMotion.py:setup_sync(mode=?)
                 0: after MXMotion.py:setup_sync call       triggerSync.c:trigsync_func(mode&1)
               idx: index of position during run            triggerSync.c:trigsync_func(mode&1)
                -1: motion is finished                      MXMotion.py:setup_sync(mode=?)

Gather.Enable : mode of gathering data 
                1: prepared (calculate Gather.MaxLines)     MotionBase.py:setup_gather()
                2: finite                                   motion code: during data gathering
                0: disabled                                 motion code: when gather finished

Gather.Samples : number af gathered data samples

MXMotion.py:setup_sync():
 sync_mode : default=2
         0 : no sync at all
         1 : synchronize start
         2 : synchronize start and adapt motion speed
 
 sync_flag : default=0
   bit 0=1 : simulated start trigger
   bit 1=2 : simulated frame trigger

triggerSync.c mode:
 bit0:1: sync mode
 bit1:2: simulate start trigger
 bit2:4: simulate frame trigger
 bit3:8: verbose

start/frame event system

Start event:
  sim: Coord[1].Q[10]
  EVR: Gate3[1].Chan[0].UserFlag == (gate3_1->Chan[0].Status&0x800) == FrontUnivOut4,  EPICS MACRO: $(USR_FLAG_ID)=5
       -> Pulser0 -> (active Low, 5000us delay   0us) Map: 214
         -> event 214 is 'ESC multipurpose event. In this case used as: start motion'

Frame event:
  sim: Coord[1].Q[11]
  EVR: Gate3[1].Chan[1].UserFlag == (gate3_1->Chan[1].Status&0x800) == FrontUnivOut5,  EPICS MACRO: $(USR_FLAG_ID)=5 
       -> Pulser1 -> (active Low, 5000us delay 750us) Map: 40
         -> event 40 = 'ESA_detector 100 Hz' >>> should be 77='ESC detector'

unused EVR input?: 
  EVR: Gate3[1].Chan[2].UserFlag == (gate3_1->Chan[2].Status&0x800) == FrontUnivOut6,  EPICS MACRO: $(USR_FLAG_ID)=7 

!!! Deltatau flags are inverted: FrontUnivOut6(Force Low) -> Gate3[1].Chan[2].UserFlag==1
event simulated real
start Coord[.].Q[10] Gate3[1].Chan[0].UserFlag
frame Coord[.].Q[11] Gate3[1].Chan[1].UserFlag

frequence jitter 50Hz Swissgrid: https://www.swissgrid.ch/de/home/operation/grid-data/current-data.html

partial python class diagram of PBSwissMX

classDiagram
MotionBase <|-- ShapePath
MotionBase <|-- HelicalScan

  class MotionBase {
    @MXMotion.py
    + setup_sync(self, crdId, prgId, verbose, timeOfs, timeCor)
    + homing(self)
    + run(self, crdId)
    + wait_armed(self, crdId)
    + progress(self)
    + trigger(self, wait)
  }

  class ShapePath {
    @shapepath.py
    %%- __init__(self, args) None
    + setup_gather(self,acq_per=None,numPts=None)
    + setup_coord_trf(self,fx='X',fy='Y',cz='0')
    + setup_motion(self,prgId=2,fnPrg=None,mode=0,**kwargs)
    + gather_upload(self,fnRec=None)
  }

  class HelicalScan {
    @helicalscan.py [obsolete]
    + setup_gather(self,acq_per=1)
    + setup_coord_trf(self,fnCrdTrf='/tmp/coordTrf.cfg')
    + setup_motion(self,prgId=2,fnPrg=None,mode=0,**kwargs)
    + gather_upload(self,fnRec=None)
  }

  class GenPath {
    @shapepath.py
    + swissmx(self, flipx, flipy, ofs, width)
    + swissfel(self, flipx, flipy, ofs, width)
    %%+ rand(self, n, scale, ofs)
    + grid(self, w, h, pitch, rnd, ofs)
    %%+ spiral(self, rStart, rInc, numSeg, numCir, phase, ofs)
    %%+ closed_shifted(self, pitch, shift, mult)
    %%+ sort(self, mode, grp_sz)
  }

Simplified Python sequence

Source for the instance "start/frame event system" can be:

  • python code
  • timing system (EVR)
  • motion code
  • triggerSync executable running on Deltatau
sequenceDiagram
  participant es as start/frame<br/>event system
  participant py as Python
  participant pb as PowerBrick

  Note over py: .setup_sync()<br/>prepare code snipplets
  activate py
  opt needs triggerSync
    Note over es,pb: triggerSync is needed in  case of:<br/>simulated start/frame triggers<br/>and/or adjust DesTimeBase
    py -) pb: sftp / ssh
  Note over pb: sftp triggerSync<br/>run triggerSync
    pb ->> es: run triggerSync
  end

  Note over py: .setup_coord_trf()
  py -) pb: download code
  Note over pb: setup coordinate transformation
  Note over py: .setup_motion()
  py -) pb: generate code<br/>download code
  Note over pb: setup motion program
  Note over py: .setup_gather()
  py -) pb: download code<br/>set gather vars
  Note over pb: set addresses to gather<br/>Gather.Enable=1
  Note over py: .homing()
  py -)+ pb: download code<br/>run homing PLC
  Note over py: wait(Motor[1].HomeComplete)
  deactivate py
  Note over pb: runs homing PLC [if needed]<br/>enable plc 1
  pb ->>- py: Motor[1].HomeComplete
  activate py
  Note over py: .run()
  py -)+ pb: run motion program
  Note over pb: runs motion program 2 in coordSystem 1<br/>&1br2
  Note over pb: move to first point<br/>DesTimeBase=0 (wait motion)<br/>Q[0]=-3 (motion program waiting at start position)
  pb ->>- es: Q[0]=-3
  Note over es: Q[0]=-2 (event system armed)<br/>[in motion code or<br/>triggerSync exe]
  Note over py: .wait_armed()<br/>wait(Q[0]==-2)  # wait until motors are at first position
  deactivate py
  es ->>+ py: Q[0]=-2
  Note over es: wait for start trigger
    Note over py: .trigger()
  alt sim start trig
    Note over py: Q[10]=1 [send a simulated start trigger<br/>after given time]
    py ->> es: Q[10]=1
  else real start trig
    es->> es: Gate3[1].Chan[0].UserFlag==1
  end
  Note over es: DesTimeBase=Sys.ServoPeriod<br/>[in motion code or<br/>triggerSync exe]
  es->>+pb: continue motion
  opt adjust time base
    Note over es: in thread trigger_sync_func()<br/>of triggerSync exe 
    es->>es: adjust DesTimeBase
  end
  Note over pb: pvt10abs<br/>move to all points
  loop 10 ms
    Note over pb: move to next point
  end
  opt triggerSync running
    pb ->> es: Gather.Enable=0
    Note over es: exit triggerSync exe
  end
  Note over py: while .progress()<br/>wait(Gather.Enable==0)
  deactivate py
  Note over pb: end motion program
  pb ->>- py: Gather.Enable=0
  activate py
  Note over py: .gather_upload()
  deactivate py

12.2.25: debugging motion code

&1b2r
go to <&>coordsystem <1> <b>eginning of program <2> and <r>un

s step one line
q quit program
a abort motion program
bpset set breakpoints

list  plc2,10,3
   list 3 lines strating from line 10 

list  pc
   show program counter
   &1b2r

open prog 3
  linearabs
  X2Y1
  dwell10
  X0Y3
  dwell10
  X3Y3
  dwell10
  X3Y0
  dwell10
  X0Y0
close

&1b3

cpx linearabs X1Y1

//return coordinate transcormation of all axes (in coordinate system 1)
&1 #1..8->

&1p  // returns coordinate positions in 'wells' (in coordinate system 1)
X1.000208333333334 Y1.000104166666666

#1..2p

//show were the program is:
list pc
list pc, // with line numbers

Coord[1].ProgRunning
Coord[1].ProgActive
Coord[1].ProgProceeding
Coord[1].Program.Lsize
Coord[1].Program.Number
Coord[1].Program.Size
Coord[1].Program.Store   

Work log

??10.24: testing shapepath.py in different modes (tunneling)

zamofing_t@ganymede:~$
>>> kill previous tunnels 127.0.0.1:100??
ps -f `lsof -i -n | grep '127.0.0.1:100.. (LISTEN)' | awk '{print $2}'`
kill `lsof -i -n | grep '127.0.0.1:100.. (LISTEN)' | awk '{print $2}'`
#lsof -i -n | grep '127.0.0.1:100.. (LISTEN)' | tee /tmp/0.log | awk '{print $2}' | tee /tmp/1.log && grep -n '' /tmp/*.log

>>> open cameras in chrome
ssh -L 10010:cristallina-cam-top:80 saresc-vcons-01 'uname -a'
google-chrome --app-url 127.0.0.1:10010
google-chrome --app-url http://cristallina-cam-north.psi.ch/camera/index.html#/video


>>> prepare debug environment
cmdt.py -p EXPMX -tpb   # select SAR-CPPM-EXPMX1

>>> prepare shapepath and ssh tunneling
cd ~/Documents/prj/SwissFEL/apps/PBSwissMX/python/
subl shapepath.py
./shapepath.py -h

PPMAC=SAR-CPPM-EXPMX1
ssh -L 10001:localhost:22 root@$PPMAC 'uname -a'
ssh -L 10002:localhost:2332 root@$PPMAC 'uname -a'

gather_server triggerSync are copied with sftp. This does not work with tunneling:
gather_server: ~/Documents/prj/SwissFEL/PBTools/build/lib/pbtools/misc/pp_comm.py:889
triggerSync:   ~/Documents/prj/SwissFEL/apps/PBSwissMX/python/MXMotion.py:122

rsync -vai ~/Documents/prj/SwissFEL/PBTools/pbtools/gather/gather_server root@$PPMAC:/tmp/
rsync -vai ~/Documents/prj/SwissFEL/apps/PBSwissMX/src/triggerSync/triggerSync root@$PPMAC:/tmp/

gather_server needs to be started explicitly in tunneling:
ssh root@$PPMAC
LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/gather_server

triggerSync is started if required at each acquisition and exits when done.

mode:
0  unused
1  pvt motion
2  unused
3  pvt motion using inverse fft velocity
4  pvt motion short code using grid parameters
5  pvt motion short code using grid parameters. Instead of continous motion it moves and waits as give in the parameter time

sync:
 0 real start and frame trigger with sync
 1 direct start
 2 simulated start and frame trigger no sync
 3 simulated start and frame trigger with sync
 4 simulated start real frame trigger no sync
 5 simulated start real frame trigger with sync


# set start EVT to value 0 (=Force Hi)
caput SAR-EXPMX-EVR0:FrontUnivOut4-Src-Scale-SP 9
./shapepath.py --host=localhost:10001:10002 -v 0x59 -m4 -s0 # works
# set start EVT to value 1 (=Force Lo)
caput SAR-EXPMX-EVR0:FrontUnivOut4-Src-Scale-SP 8
# reset EVT default value (Pulser 0)
caput SAR-EXPMX-EVR0:FrontUnivOut4-Src-Pulse-SP 0
./shapepath.py --host=localhost:10001:10002 -v 0x59 -m4 -s1  # works
./shapepath.py --host=localhost:10001:10002 -v 0x59 -m4 -s2  # works
./shapepath.py --host=localhost:10001:10002 -v 0x59 -m4 -s3  # works
./shapepath.py --host=localhost:10001:10002 -v 0x59 -m4 -s4  # works
./shapepath.py --host=localhost:10001:10002 -v 0x59 -m4 -s5  # works

Debugging were the coordinate program counter is:
&1 list pc,10
pip install pymermaider --user
pymermaider ~/Documents/prj/SwissFEL/apps/PBSwissMX/python -o /tmp
subl /tmp/python.md
Description
No description provided
Readme 10 MiB
Languages
Python 57.2%
C 15.7%
MATLAB 12.5%
TeX 11.3%
Makefile 3.3%