Merge branch 'master' of git.psi.ch:grp-sf_cristallina/SwissMX

This commit is contained in:
2024-12-11 15:28:02 +01:00
6 changed files with 828 additions and 646 deletions

449
Log.md Normal file
View File

@@ -0,0 +1,449 @@
16.9.22 remote Deltatau test:
-----------------------------
```
(s.a. /home/zamofing_t/Documents/prj/SwissFEL/PBTools/pbtools/gather/PBGatherPlot.py
PPMAC=SAR-CPPM-EXPMX1
rsync -va ~/Documents/prj/SwissFEL/PBTools/pbtools/gather/gather_server root@$PPMAC:/tmp/
ssh root@$PPMAC
LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/gather_server
ssh -L 10001:localhost:22 root@$PPMAC 'uname -a'
ssh -L 10002:localhost:2332 root@$PPMAC 'uname -a'
Deltatau host in config:
localhost:10001:10002 (instead SAR-CPPM-EXPMX1)
ssh gac-cristall@saresc-cons-03
pw: ValToira_2021
```
4.10.22 final test:
-------------------
```
zamofing_t@ganymede:~$ ssh gac-cristall@saresc-cons-03
cd /sf/cristallina/applications/mx/zamofing_t/ESB_MX/python/SwissMX/
# conda env list
conda activate crmx38
python swissmx.py
ssh gac-cristall@saresc-cons-03 ls /sf/cristallina/applications/mx/zamofing_t/ESB_MX/python/SwissMX
git@git.psi.ch:epics_ioc_modules/ESB_MX.git
git remote add sf-cristallina gac-cristall@saresc-cons-03:/sf/cristallina/applications/mx/zamofing_t/ESB_MX/python/SwissMX
git fetch sf-cristallina
# do local changes and commit stuff
git push sf-cristallina
```
22.6.23 debug segmentation fault
--------------------------------
```
THE CHRISTALLINA CONTROL ROOM RUNS NORMALLY ON saresc-cons-05
[saresc-cons-05 ~]$
ulimit -a
ulimit -c unlimited
python -X faulthandler -X tracemalloc -X dev swissmx.py 2>&1 | tee /tmp/swissmx000.log
reset;tail -c+0 -F /tmp/swissmx000.log
python -X faulthandler -X tracemalloc -X importtime -X dev swissmx.py --sim 0xff
python -X faulthandler -X tracemalloc -X dev swissmx.py --sim 0xff
zamofing_t@ganymede:~/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/SwissMX$
rsync -vai swissmx.py saresc-cons-03:/sf/cristallina/applications/mx/zamofing_t/ESB_MX/python/SwissMX/swissmx_segFault.py
read: https://docs.python.org/3/library/faulthandler.html
coredump erzeugen
cat /proc/sys/kernel/core_pattern
sudo echo "/tmp/core" > /proc/sys/kernel/core_pattern
ulimit -c unlimited
python -c "import ctypes; ctypes.string_at(0)"
python -X faulthandler -c "import ctypes; ctypes.string_at(0)"
Rene did:
[root@saresc-cons-05 ~]# sysctl -w kernel.core_pattern="/tmp/%e_core_dump.%p"
cat /proc/sys/kernel/core_pattern
/tmp/%e_core_dump.%p
ll /tmp/python_core_dump.*
gdb python /tmp/core
bt (for facktrace)
trying python c code extention:
/home/zamofing_t/Documents/prj/scratch/python/sample_c_extension
Thread 0x00007fd2e16e8700 (most recent call first):
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 620 in get_with_metadata
...
File "/gfa/.mounts/sf_cristallina/applications/mx/zamofing_t/ESB_MX/python/SwissMX/epics_widgets/MotorTweak.py", line 216 in update_label
...
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 48 in wrapped
```
29.6.23 Coredump 18h40
----------------------
```
grep -c '5000/5000' *
swissmx000.log:57
swissmx001.log:36
swissmx002.log:35
swissmx002.log 35*5000 frames
35*5000/100/60 -> every 29.16min of acquisition a crash
rsync -vai gac-cristall@saresc-cons-05:/tmp/swissmx* ~/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/SwissMX/log
ll /tmp/swissmx*
ll /tmp/python_core_dump.*
Thread 0x00007fb9b13f7700 (most recent call first):
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 48 in wrapped
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 620 in get_with_metadata
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 48 in wrapped
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 620 in get_with_metadata
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 48 in wrapped
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/ca.py", line 1122 in element_count
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 489 in get
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 48 in wrapped
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 620 in get_with_metadata
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 48 in wrapped
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 981 in nelm
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/ca.py", line 579 in wrapper
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/ca.py", line 1122 in element_count
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 48 in wrapped
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 48 in wrapped
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/ca.py", line 549 in wrapper
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/ca.py", line 871 in current_context
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 48 in wrapped
conda activate crmx38
ll /tmp/python_core_dump.*
gdb python /tmp/python_core_dump.21072
Core was generated by `python -X faulthandler -X tracemalloc -X dev swissmx.py'.
Program terminated with signal 11, Segmentation fault.
bt
0 write_thread_id.isra.3 (is_current=0, fd=<optimized out>) at /opt/conda/conda-bld/python-split_1648465063888/work/Python/traceback.c:849
#1 _Py_DumpTracebackThreads () at /opt/conda/conda-bld/python-split_1648465063888/work/Python/traceback.c:914
#2 0x000055c2b7ef6635 in faulthandler_dump_traceback.isra.2 (fd=fd@entry=2, all_threads=1) at /opt/conda/conda-bld/python-split_1648465063888/work/Modules/faulthandler.c:242
#3 0x000055c2b7ef67a3 in faulthandler_fatal_error (signum=11) at /opt/conda/conda-bld/python-split_1648465063888/work/Modules/faulthandler.c:348
#4 <signal handler called>
#5 0x00007fb9c7ed4ef4 in QWidgetTextControl::document() const () from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/../../../libQt5Widgets.so.5
#6 0x00007fb9c7e676e1 in ?? () from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/../../../libQt5Widgets.so.5
#7 0x00007fb9c7e69230 in QLabel::paintEvent(QPaintEvent*) () from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/../../../libQt5Widgets.so.5
#8 0x00007fb9d7fa16d3 in sipQLabel::paintEvent(QPaintEvent*) () from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/QtWidgets.abi3.so
#9 0x00007fb9c7dcc580 in QWidget::event(QEvent*) () from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/../../../libQt5Widgets.so.5
#10 0x00007fb9c7e36203 in QFrame::event(QEvent*) () from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/../../../libQt5Widgets.so.5
#11 0x00007fb9d7fa2d03 in sipQLabel::event(QEvent*) () from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/QtWidgets.abi3.so
#12 0x00007fb9c7da20f1 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/../../../libQt5Widgets.so.5
#13 0x00007fb9d8097afe in sipQApplication::notify(QObject*, QEvent*) () from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/QtWidgets.abi3.so
#14 0x00007fb9e6cadd62 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/../../../libQt5Core.so.5
#15 0x00007fb9c7dc6de6 in QWidgetPrivate::sendPaintEvent(QRegion const&) () from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/../../../libQt5Widgets.so.5
#16 0x00007fb9c7dc774e in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) ()
from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/../../../libQt5Widgets.so.5
#17 0x00007fb9c7dc8147 in QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRe
```
Localize monitors and callbacks:
```
grep -Rn 'add_callback' *.py
swissmx.py:698: self.sigNewCamImg.connect(self.cb_update_img)
swissmx.py:745: def cb_update_img(self):
epics_widgets/MotorTweak.py:88: m.set_callback('RBV', self.emit_signals, {'source_field': 'RBV'})
epics_widgets/SmaractMotorTweak.py:100: self._pv_readback.add_callback(self.update_label)
swissmx.py:717: cam.run(self.cb_new_frame_pv)
swissmx.py:743: self.sigNewCamImg.emit()
swissmx.py:745: def cb_update_img(self):
swissmx.py:698: self.sigNewCamImg.connect(self.cb_update_img)
camera.py:159: self._pv['pic'] = epics.PV(self._prefix + "FPICTURE", auto_monitor=True, callback=cb)
-> try to turn of the monitors during ascuisition:
zamofing_t@ganymede:~/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX$
grep -r set_callback *
https://pyepics.github.io/pyepics/pv.html#automatic-monitoring-of-a-pv
Try with:
pv.clear_auto_monitor() -> pv.reconnect()
pv.remove_callback(index=None) -> pv.add_callback(callback=None[, index=None [, with_ctrlvars=True[, **kw]])
pv.set_callback
FixTargetFrame -> paint -> _log.debug()
Turn off jungfrau.
no motion -> wait 1h
constant up-dow motion code -> wait 1h
```
23.9.24 spitting/moving repositories
------------------------------------
```
https://jira.psi.ch/browse/SFELPHOTON-1337: SwissMX split/ cleanup/move repositories
```
----------------------------------------------------------------------
SCRATCH
=======
Deploy stuff (22.8.22) quick and dirty (21.9.22 rewworked)
----------------------------------------------------------
```
DST=/sf/cristallina/applications/mx/zamofing_t/
ssh saresc-cons-03 mkdir $DST
# add '--delete' if needed
rsync -vai ~/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX saresc-cons-03:$DST -n
rsync -vai ~/Documents/prj/SwissFEL/PBTools saresc-cons-03:$DST -n
ssh saresc-cons-03 saresc-cons-03 chmod -R go+w $DST/ESB_MX/python/SwissMX
cd /sf/cristallina/applications/mx/zamofing_t/ESB_MX/python/SwissMX/
/opt/gfa/python-3.8/latest/bin/pip install qtawesome --user
/opt/gfa/python-3.8/latest/bin/pip install opencv-python
/opt/gfa/python-3.8/latest/bin/python swissmx.py
rsync -vai gac-cristall@saresc-cons-03:~/.config/PSI/SwissMX.conf /home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/SwissMX/
cd $DST
/opt/gfa/python-3.8/latest/bin/python -m pdb swissmx.py
rsync -vai saresc-cons-03:/tmp/image*.png ~/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/SwissMX/scratch/
/home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/SwissMX/scratch/autofocus2
```
pyqtgraph examples
------------------
```
ipython3
import pyqtgraph.examples
pyqtgraph.examples.run()
```
EPICS simulator
---------------
```
This provides very dummy images and motor(to be done) records
cd /home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/EpicsSim/iocBoot/iocSwissMxSim
./st.cmd
```
simulate camera (with EPICS simulator)
--------------------------------------
```
cd /home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/SwissMX
EPICS_CA_ADDR_LIST=localhost
./simCam.py
```
test camera display
-------------------
```
cd /home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/SwissMX
EPICS_CA_ADDR_LIST=localhost
./camera.py -u -b SwissMxSim
```
test at ESC
-----------
```
https://git.psi.ch/SwissMX/swissmx_cristallina/-/wikis/Instructions%20on%20how%20to%20use%20software
P=ESB_MX/python/SwissMX/
ssh saresc-cons-02 mkdir -p /tmp/zamofing_t/$P
rsync -vai ~/Documents/prj/SwissFEL/epics_ioc_modules/$P saresc-cons-02:/tmp/zamofing_t/$P
cd /tmp/zamofing_t/ESB_MX/python/SwissMX
/opt/gfa/python-3.7/2018.12/bin/python camera.py -u 1 -p SARES30-CAMS156-SMX-OAV
/opt/gfa/python-3.7/2018.12/bin/python swissmx.py
caqtdm -macro 'NAME=SARES30-CAMS156-SMX-OAV,CAMNAME=SARES30-CAMS156-SMX-OAV' /sf/controls/config/qt/Camera/CameraExpert_RF.ui
```
try revive Zac code
-------------------
```
cd /tmp/; git clone https://github.com/malcolmreynolds/transformations.git
cd /tmp/transformations.git
-> modify __init__.py -> .transformation (add dot)
setup.py install --user
cd /tmp/; git clone https://github.com/spyder-ide/qtawesome.git
cd /tmp/qtawesome
#To have epics channels we must be connected to the ESC network
EPICS_CA_ADDR_LIST='129.129.244.255 sf-saresc-cagw.psi.ch:5062 sf-saresc-cagw.psi.ch:5066'
cd /home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/oldRepos/app/src
python swissmx.py
```
pyqtgraph examples
------------------
```
import pyqtgraph.examples
pyqtgraph.examples.run()
```
-0.952
pp_comm.py_:
@property
def fast_gather(self):
tries to connect to port and to query_types(), if fails starts the fast gather process.
triggerSync.c:
root@:/opt/ppmac# LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/triggerSync
usage:
/tmp/triggerSync pt2ptTime timeOfs mode
pt2ptTime: time in ms (float value) from point to point == frequency if FEL
timeOfs: time offset in ms (float value) for motion relative to the FEL timing
The program changes the speed of motion
pshm->Coord[1].DesTimeBase= (default serverPeriod= 0.2?)
SIMFLAG0 (pshm->Coord[1].Q[10]) -> start trigger
SIMFLAG1 (pshm->Coord[1].Q[11]) -> FEL pulse trigger
//Power PMAC Software Reference Manual.pdf Gate3[i].Chan[j].Status -> page 919 UserFlag
#define FLAG0 (gate3_1->Chan[0].Status&0x800) -> start trigger
#define FLAG1 (gate3_1->Chan[1].Status&0x800) -> FEL pulse trigger
mode:
bit0:1: sync mode
bit1:2: simulate start trigger
bit2:4: simulate frame trigger
bit3:8: verbose
simulate start trigger:
set pshm->Coord[1].Q[10]=1 to simulate a Jungfrau aquire start
simulate frame trigger
is output to pshm->Coord[1].Q[11]
1: synchronize real frame and start triggers
3: synchronize real frame and simulated start triggers
6: simulated frame and start triggers (no sync)
7: synchronize simulated frame and start triggers
in simulate mode:
set pshm->Coord[1].Q[10]=1 to simulate a Jungfrau aquire start
set pshm->Coord[1].Q[10]=2 to stop simulate trigger generation
Coord[1].Q[11] is the simulated frame trigger
in synchronize mode
Coord[1].Q[0]=-2 : trigsync_func start, Wait for 'arm' trigger
Coord[1].Q[0]=-1 : got 'arm' trigger, wait frame trigger
Coord[1].Q[0]= 0 : got frame trigger 0
Coord[1].Q[0] is incremented at each trigger
sync task ends when Gather.Enable==0
// /tmp/triggerSync 40 11 trigger all 40 ms, simulated start, use real frame triggers, verbose
// /tmp/triggerSync 40 14 trigger all 40 ms, simulated start and frame triggers, no sync, verbose
// /tmp/triggerSync 40 15 trigger all 40 ms, simulated start and frame triggers, with sync, verbose
// /tmp/triggerSync 40 7 trigger all 40 ms, simulated start and frame triggers, with sync, minimal verbose
78x78 points =6084pts a 10ms =60 sec. -> 70 sec.
-> we are at 100 Hz !!!
remote ssh tunnel + start gather_server
---------------------------------------
```
PPMAC=SAR-CPPM-EXPMX1
rsync -va ~/Documents/prj/SwissFEL/PBTools/pbtools/gather/gather_server root@$PPMAC:/tmp/
lsof -i -n | grep '127.0.0.1:1000'
ssh -L 10001:localhost:22 root@$PPMAC 'uname -a'
ssh -L 10002:localhost:2332 root@$PPMAC 'uname -a'
ssh root@$PPMAC
LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/gather_server
```
cleanup /tmp/
-------------
```
PPMAC=SAR-CPPM-EXPMX1
ssh root@$PPMAC rm /tmp/gather_server /tmp/triggerSync
ssh root@$PPMAC ls -l /tmp
```
start debug tools
-----------------
```
PPMAC=SAR-CPPM-EXPMX1
PBInspect --host=$PPMAC&
gpasciiCommander --host $PPMAC -i
ssh root@$PPMAC
ssh root@$PPMAC rm /tmp/gather_server /tmp/triggerSync
ssh root@$PPMAC ls -l /tmp
```
restart IOC
-----------
```
ssh saresc-cons-03
PPMAC=SAR-CPPM-EXPMX1
telnet $PPMAC 50001
Ctrl-X
dbgf SAR-CPPM-EXPMX1:MOD_VER
caget SAR-CPPM-EXPMX1:MOD_VER
```
checking versions
-----------------
```
git: 7a968aac967
asyn 427.0.2
motorBase alpha_220518
asynMotor alpha_220518
powerPmac alpha_220518
PB_COMMON 2.0.1
gpasciiCommander 0.9.0
ESB_MX 0.0.2
```
zamofing_t@ganymede:~/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX$
git loggraph -10
* 7a968aa 2022-09-20 (HEAD -> master, tag: latest, tag: 0.0.2, psigithub/master) change speeds and directions [Thierry Zamofing]
* 00588f8 2022-09-16 minor changes [Thierry Zamofing]
* d52a6ce 2022-08-30 minor changes [Thierry Zamofing]
* f47e111 2022-05-20 (tag: 0.0.1) add DET_Z motor [Thierry Zamofing]
* 8e5b15e 2022-05-20 wip [Thierry Zamofing]
* 399282c 2019-03-20 enhance triggering [Thierry Zamofing]
* eda8caf 2019-03-19 wip [Thierry Zamofing]
* 0c45705 2019-03-08 optimize [Thierry Zamofing]
* c962ebd 2019-03-06 documentation [Thierry Zamofing]
git reset --hard 399282c
rmake -e LIBVERSION=42.42.42 uninstall install
-> restart IOC
ssh root@$PPMAC rm /tmp/triggerSync
cd python
git dt latest -- shapepath.py
./shapepath.py --host=localhost:10001:10002
removing test verion
ssh sf-lc7 ls -l /ioc/modules/ESB_MX/
ssh sf-lc7 rm -rf /ioc/modules/ESB_MX/42.42.42
IOC locations
-------------
```
~/Documents/prj/SwissFEL/epics_ioc_boot_sf/ESC_all/ESB_MX_PowerBrick
They are just using the new alphy driver. That should have no impact on the motion config.
```
test shapepath
--------------
```
cd ~/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX
./shapepath.py --host=localhost:10001:10002
```

View File

@@ -16,7 +16,7 @@ This contains a Widget to handle FixTargetFrames and fiducials, calculate final
import logging import logging
_log=logging.getLogger(__name__) _log=logging.getLogger(__name__)
import json, base64 import os, json, base64, yaml
import numpy as np import numpy as np
import pyqtUsrObj as UsrGO import pyqtUsrObj as UsrGO
import pyqtgraph as pg import pyqtgraph as pg
@@ -47,6 +47,22 @@ class MyJsonEncoder(json.JSONEncoder):
return repr(obj) return repr(obj)
return json.JSONEncoder.default(self, obj) return json.JSONEncoder.default(self, obj)
def iterencode(self, o, _one_shot=False):
list_lvl = 0
l=super().iterencode(o, _one_shot=_one_shot)
#l=tuple(l);print(''.join(l)) # helpful to debug
for s in l:
if s.startswith('['):
list_lvl += 1
if list_lvl > 0:
s = s[0]+s[1:].replace('\n', '').strip()
s = s.replace('\n', '').rstrip()
#self.item_separator):
#self.key_separator
if s.endswith(']'):
list_lvl -= 1
yield s
def MyJsonDecoder(dct): def MyJsonDecoder(dct):
if isinstance(dct, dict): if isinstance(dct, dict):
if '__class__' in dct: if '__class__' in dct:
@@ -161,6 +177,30 @@ class WndFixTarget(QWidget):
act.triggered.connect(self.tree_ctx_delete) act.triggered.connect(self.tree_ctx_delete)
tree.addAction(act) tree.addAction(act)
act = QAction("update param", self)
act.triggered.connect(self.tree_ctx_update)
tree.addAction(act)
def get_param(self):
param=self._txtParam.text().replace('(','[').replace(')',']').strip()
if param=='' or param[0]!='{':
param='{'+param+'}'
#mft._cbType.addItems(["Fiducial", "FixTarget(12.5x12.5)", "FixTarget(23.0x23.0)", "FixTarget(<param>)", "Grid(<param>)", "SwissMX-path"])
#bm_pos_eu=self._goBeamMarker._pos_eu
#bm_size_eu=self._goBeamMarker._size_eu
try:
#parse the parameters: as yaml string.
# allows : without space, allows () as []
# no {} to define a dictionary
# e.g. 'a:ggf,b:5,c:[5,6.1],d(8,9,3)'
param=param.replace(':', ': ') # allow gen:4 without space
param=yaml.safe_load(param) # "ofs":[10, 5],"width":200,"fidScl":0.5,"fiducial":[[18,7],[25,16],[70, 20]]
except BaseException as e:
_log.error(f'{e}:{param}')
param=dict()
return param
def tree_get_path(self): def tree_get_path(self):
path=[] path=[]
it=self._tree.currentItem() it=self._tree.currentItem()
@@ -213,6 +253,21 @@ class WndFixTarget(QWidget):
r1.translate(r2.center()-r1.center()) r1.translate(r2.center()-r1.center())
vb.setRange(r1) vb.setRange(r1)
def tree_ctx_update(self):
app=QApplication.instance()
path=self.tree_get_path()
if len(path)==1:
try:
wnd=app._mainWnd
except AttributeError:
_log.info('_mainWnd not handeled')
else:
grp=wnd._goTracked
go=grp.childItems()[path[0]]
go._param=self.get_param()
data=grp.childItems()
self._tree.setData(data)
def load_file(self, filename=None): def load_file(self, filename=None):
app = QApplication.instance() app = QApplication.instance()
if filename is None: if filename is None:
@@ -319,7 +374,10 @@ class WndFixTarget(QWidget):
#df = pd.DataFrame(data) #df = pd.DataFrame(data)
#df.to_csv(filename, float_format="%.6f") #df.to_csv(filename, float_format="%.6f")
#import numpy as np #import numpy as np
ext=filename.rsplit('.',1)[1].lower() base,ext=os.path.splitext(filename)
if not ext.lower():
ext='json'
filename=base+'.'+ext
try: try:
wnd=app._mainWnd wnd=app._mainWnd
except AttributeError: except AttributeError:
@@ -329,7 +387,7 @@ class WndFixTarget(QWidget):
grp=wnd._goTracked grp=wnd._goTracked
data=grp.childItems() data=grp.childItems()
if ext=='json': if ext.lower()=='json':
with open(filename, 'w') as f: with open(filename, 'w') as f:
json.dump(data, f,cls=MyJsonEncoder, indent=2)#separators=(',', ':') json.dump(data, f,cls=MyJsonEncoder, indent=2)#separators=(',', ':')
else: else:

666
Readme.md
View File

@@ -1,39 +1,57 @@
Repository structure and dependency (update:23.09.24) SwissMX
----------------------------------------------------- =======
SwissMX is a python application to operate the SwissMX system at cristallina:<br/>
![alt text](SwissMX.jpg "Title")
Repositories and dependencies (update:23.09.24)
-----------------------------------------------
|repo |`https://git.psi.ch/`|`~/Documents/prj/SwissFEL/`|description|
|:- |:- |:- |:- |
|SwissMX |[grp-sf_cristallina/SwissMX.git](https://git.psi.ch/grp-sf_cristallina/SwissMX) |apps/SwissMX |Main python user interface fro SwissMX|
|PBSwissMX|[grp-sf_cristallina/PBSwissMX.git](https://git.psi.ch/grp-sf_cristallina/PBSwissMX) |apps/PBSwissMX |PowerBrick documents and tool to generate trajectories and motion programs for SwissMX|
|PBTools |[epics_support_apps/PBTools.git](https://git.psi.ch/epics_support_apps/PBTools) |PBTools |packages needed by PBSwissMX for low level communication to PowerBrick|
|ppmac |[epics_support_apps/ppmac.git](https://git.psi.ch/epics_support_apps/ppmac) |PBTools/ppmac |packages needed by PBTools for lowest level communication to PowerBrick|
|SW_MX |[epics_ioc_modules/SW_MX.git](https://git.psi.ch/epics_ioc_modules/SW_MX) |epics_ioc_modules/SW_MX |IOC modules and `generate.py` for all SwissMX motors|
```mermaid
flowchart BT
PBSwissMX --> SwissMX
PBTools --> PBSwissMX
ppmac --> PBTools
SW_MX-->PBSwissMX
``` ```
https://jira.psi.ch/browse/SFELPHOTON-1337 <!--
```mermaid
%% info
%%``` -->
psigithub git@git.psi.ch:grp-sf_cristallina/SwissMX.git --> ~/Documents/prj/SwissFEL/apps/SwissMX #### installation location
Main python user interface fro SwissMX |repo | installed at
|:- |:-
|SwissMX | /sf/cristallina/applications/SwissMX/
|PBSwissMX| /sf/cristallina/applications/SwissMX/PBSwissMX/
|PBTools | /sf/cristallina/applications/SwissMX/PBTools/
|ppmac | /sf/cristallina/applications/SwissMX/PBTools/ppmac/
|SW_MX | /ioc/modules/SW_MX/ and ioc directories
psigithub git@git.psi.ch:grp-sf_cristallina/PBSwissMX.git --> ~/Documents/prj/SwissFEL/apps/PBSwissMX #### related documentation
PowerBrick documents and tool to generate trajectories and motion programs for SwissMX - additional module `slic` is needed, which is provided by Sven and covers the JungFrau acquisition framefork
- For **motion/frame synchronization** read: [grp-sf_cristallina/PBSwissMX.git:Readme.md](https://git.psi.ch/grp-sf_cristallina/PBSwissMX/-/blob/master/Readme.md)
- For old but still usefull information read the [Log.md](Log.md) file
- [SFELPHOTON-1337](https://jira.psi.ch/browse/SFELPHOTON-1337): ticket about restructuing repositories
psigithub git@git.psi.ch:epics_support_apps/PBTools.git --> ~/Documents/prj/SwissFEL/PBTools ---
packages needed by PBSwissMX for low level communication to PowerBrick
psigithub git@git.psi.ch:epics_support_apps/ppmac.git --> ~/Documents/prj/SwissFEL/PBTools/ppmac deployment and tests (update: 31.10.24)
packages needed by PBTools for lowest level communication to PowerBrick
additional module 'slic' is needed, which is provided by Sven and covers the JungFrau acquisition framefork
For motion/frame synchronization read:
~/Documents/prj/SwissFEL/apps/PBSwissMX/Readme.md
```
deployment and tests (update: 18.01.24)
--------------------------------------- ---------------------------------------
#### push local stuff to git
#initial full deployment:
git commit-amend && git push psigithub -f && make uninstall init update
Document to start SwissMX in cristallina environment:
https://docs.google.com/document/d/1yEmV_DbRBKQKVCoovjXriNgSjNEBaz50WA0l3yA5jtg/edit#heading=h.z9io692b8tow
``` ```
***************************
* push local stuff to git *
***************************
zamofing_t@ganymede: zamofing_t@ganymede:
cd ~/Documents/prj/SwissFEL/apps/SwissMX &&\ cd ~/Documents/prj/SwissFEL/apps/SwissMX &&\
git commit-amend &&\ git commit-amend &&\
@@ -42,10 +60,9 @@ git push psigithub -f
cd ~/Documents/prj/SwissFEL/apps/PBSwissMX &&\ cd ~/Documents/prj/SwissFEL/apps/PBSwissMX &&\
git commit-amend &&\ git commit-amend &&\
git push psigithub -f git push psigithub -f
```
************************************* #### switch to latest test environment
* switch to latest test environment * ```
*************************************
ssh saresc-cons-03 ssh saresc-cons-03
cd /sf/cristallina/applications/SwissMX &&\ cd /sf/cristallina/applications/SwissMX &&\
@@ -65,511 +82,134 @@ git stash pop
#git pull psigithub --ff-only master #git pull psigithub --ff-only master
chmod -R g+w /sf/cristallina/applications/SwissMX chmod -R g+w /sf/cristallina/applications/SwissMX
```
******************* #### run application
* run application * ```
*******************
*** with official python *** *** with official python ***
additionally needed packages: additionally needed packages:
RH7: RH7:
[saresc-vcons-01 ~]$ /opt/gfa/python-3.8/latest/bin/pip install --user qtawesome [saresc-vcons-01 ~]$ /opt/gfa/python-3.8/latest/bin/pip install --user qtawesome
RH8: RH8:
[saresc-cons-03 ~]$ pip install --user qtawesome [saresc-cons-03 ~]$ pip install --user qtawesome
swissmx swissmx
#with conda environment: *** with conda environment ***
ssh gac-cristall@saresc-cons-03 (pw:ValToira_2021) ssh gac-cristall@saresc-cons-03 (pw:ValToira_2021)
cd /sf/cristallina/applications/SwissMX/ cd /sf/cristallina/applications/SwissMX/
# conda env list # conda env list
conda activate crmx38 conda activate crmx38
python swissmx.py --sim 0xc0 python swissmx.py --sim 0xc0
``` ```
Document to start SwissMX in cristallina environment (maintained by John):
https://docs.google.com/document/d/1yEmV_DbRBKQKVCoovjXriNgSjNEBaz50WA0l3yA5jtg/edit#heading=h.z9io692b8tow
pyqtgraph examples ## code generation parameters
------------------
``` ```
ipython3 copied from: PBSwissMX/python/shapepath.py: ShapePath.setup_motion
import pyqtgraph.examples
pyqtgraph.examples.run()
generates program <prgId> and saves to fnPrg
the type of generated program is defined by <mode>$
-> the list af all points that will be moved at, is in 'mot_pts'
(m)= mandatory
(o)= optional
common kwargs:
scale : (o) scaling velocity (default=1. value=0 would stop at each point
cnt : (o) move path multiple times (default=1)
dwell : (o) dwell time at end (default=100ms)
mode:0 unused
mode:1 pvt motion point list
common kwargs plus:
points : (m) point list
trf : (o) transformation that will be done on 'points', mot_pts=trf*points
mode:2 unused
mode:3 pvt motion point list using inverse fft velocity
common kwargs plus:
points : (m) point list
trf : (o) transformation that will be done on 'points', mot_pts=trf*points
numPad : (o) number of padding points to reduce aliasing (default=16)
mode:4 pvt motion short code using grid parameters
common kwargs plus:
trf : (o) transformation that will be done on 'grid points'
grid: (m) grid parameters: {orig:(0,0),pitch(10,10),cnt:(10,10),mode:0}
mode:5 pvt motion 'stop and go' short code using grid parameters.
Instead of continous motion it moves and waits as given in the parameters
common kwargs plus:
trf : (o) transformation that will be done on 'grid points'
grid: (m) grid parameters: {orig:(0,0),pitch(10,10),cnt:(10,10),mode:0}
tmove: (m) time to move in ms (move start on FEL-trigger
twait: (m) time to wait in ms
(tmove+twait will be rounded to a multiple of fel_per)
mode:6 pvt motion 'hit and return using grid parameters. continous motion on 2n ells to pump then same 2n wells to probe, then go 2 rows down
common kwargs plus:
trf : (o) transformation that will be done on 'grid points'
grid : (m) grid parameters: {orig:(0,0),pitch(10,10),cnt:(10,10),mode:0}
ssz : (m) section size (in wells)
smv : (o) time(in num of shots) to move to next section (horiz/vert)
default is (ssz[0]-1,ssz[1])
sdelay: (o) shots count of delay. Default is ssz[0]*ssz[1]
Examples:
mode:1
mode:3
mode:4
mode:5,tmove:20,twait:30
mode:6,ssz:(4,3)
```
## graphical object parameters
```
FixTarget:
90*40+480*2=4560
60*30+360*2=2520
2520-240=2280
4560-240=4320
size in mm, dscr.size in user units (um)
"size:(6,3.5),
dscr: {
size:(4560,2520),
fiducial:{type:0,pos:((240,240),(4320,240),(240,2280),(4320,2280))},
grid:{pos:(480,360),pitch:(90,60),count:(40,30)}
}"
grid:
size, fiducialSize in mm:
(60-1)*.120 -> 7.08mm
(45-1)*.120 -> 5.28mm
fiducialSize -> 0.1mm
"size:(7.08,5.28),cnt:(60,45),fiducialSize:.01"
SwissMX():
"ofs:[.2,.2],width:10,fidScl:.02,fiducial:[[.1,.1],[.1,2.7],[10.3,.1],[10.3, 2.7]]"
SwissFEL():
"ofs:[.2,.2],width:10,fidScl:.02,fiducial:[[.1,.1],[.1,2.2],[10.3,.1],[10.3,2.2]]"
``` ```
EPICS simulator ## fully parameter examples:
---------------
``` ```
This provides very dummy images and motor(to be done) records "mode:4,size:(7.08,5.28), cnt:(60,45), fiducialSize:.01" -> add a grid
cd /home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/EpicsSim/iocBoot/iocSwissMxSim "mode:6,ssz:(4,3), size:(7.08,5.28), cnt:(60,45), fiducialSize:.01" -> add a grid
./st.cmd "mode:6,ssz:(4,3), size:(3,1.5), cnt:(30,15), fiducialSize:.01" -> add a grid
```
simulate camera (with EPICS simulator) "mode:6,ssz:(6,8),
-------------------------------------- dscr: {
``` size:(4560,2520),
cd /home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/SwissMX fiducial:{type:0,pos:((240,240),(4320,240),(240,2280),(4320,2280))},
EPICS_CA_ADDR_LIST=localhost grid:{pos:(480,360),pitch:(90,60),count:(40,30)}
./simCam.py }" -> add a FixTarget
```
test camera display
-------------------
```
cd /home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/SwissMX
EPICS_CA_ADDR_LIST=localhost
./camera.py -u -b SwissMxSim
```
test at ESC
-----------
```
https://git.psi.ch/SwissMX/swissmx_cristallina/-/wikis/Instructions%20on%20how%20to%20use%20software
P=ESB_MX/python/SwissMX/
ssh saresc-cons-02 mkdir -p /tmp/zamofing_t/$P
rsync -vai ~/Documents/prj/SwissFEL/epics_ioc_modules/$P saresc-cons-02:/tmp/zamofing_t/$P
cd /tmp/zamofing_t/ESB_MX/python/SwissMX
/opt/gfa/python-3.7/2018.12/bin/python camera.py -u 1 -p SARES30-CAMS156-SMX-OAV
/opt/gfa/python-3.7/2018.12/bin/python swissmx.py
caqtdm -macro 'NAME=SARES30-CAMS156-SMX-OAV,CAMNAME=SARES30-CAMS156-SMX-OAV' /sf/controls/config/qt/Camera/CameraExpert_RF.ui
```
try revive Zac code
-------------------
```
cd /tmp/; git clone https://github.com/malcolmreynolds/transformations.git
cd /tmp/transformations.git
-> modify __init__.py -> .transformation (add dot)
setup.py install --user
cd /tmp/; git clone https://github.com/spyder-ide/qtawesome.git
cd /tmp/qtawesome
#To have epics channels we must be connected to the ESC network
EPICS_CA_ADDR_LIST='129.129.244.255 sf-saresc-cagw.psi.ch:5062 sf-saresc-cagw.psi.ch:5066'
cd /home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/oldRepos/app/src
python swissmx.py
```
pyqtgraph examples
------------------
```
import pyqtgraph.examples
pyqtgraph.examples.run()
```
Deploy stuff (22.8.22) quick and dirty (21.9.22 rewworked)
----------------------------------------------------------
```
DST=/sf/cristallina/applications/mx/zamofing_t/
ssh saresc-cons-03 mkdir $DST
# add '--delete' if needed
rsync -vai ~/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX saresc-cons-03:$DST -n
rsync -vai ~/Documents/prj/SwissFEL/PBTools saresc-cons-03:$DST -n
ssh saresc-cons-03 saresc-cons-03 chmod -R go+w $DST/ESB_MX/python/SwissMX
cd /sf/cristallina/applications/mx/zamofing_t/ESB_MX/python/SwissMX/
/opt/gfa/python-3.8/latest/bin/pip install qtawesome --user
/opt/gfa/python-3.8/latest/bin/pip install opencv-python
/opt/gfa/python-3.8/latest/bin/python swissmx.py
rsync -vai gac-cristall@saresc-cons-03:~/.config/PSI/SwissMX.conf /home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/SwissMX/
cd $DST
/opt/gfa/python-3.8/latest/bin/python -m pdb swissmx.py
rsync -vai saresc-cons-03:/tmp/image*.png ~/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/SwissMX/scratch/
/home/zamofing_t/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/SwissMX/scratch/autofocus2
```
16.9.22 remote Deltatau test:
-----------------------------
```
(s.a. /home/zamofing_t/Documents/prj/SwissFEL/PBTools/pbtools/gather/PBGatherPlot.py
PPMAC=SAR-CPPM-EXPMX1
rsync -va ~/Documents/prj/SwissFEL/PBTools/pbtools/gather/gather_server root@$PPMAC:/tmp/
ssh root@$PPMAC
LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/gather_server
ssh -L 10001:localhost:22 root@$PPMAC 'uname -a'
ssh -L 10002:localhost:2332 root@$PPMAC 'uname -a'
Deltatau host in config:
localhost:10001:10002 (instead SAR-CPPM-EXPMX1)
ssh gac-cristall@saresc-cons-03
pw: ValToira_2021
```
4.10.22 final test:
-------------------
```
zamofing_t@ganymede:~$ ssh gac-cristall@saresc-cons-03
cd /sf/cristallina/applications/mx/zamofing_t/ESB_MX/python/SwissMX/
# conda env list
conda activate crmx38
python swissmx.py
ssh gac-cristall@saresc-cons-03 ls /sf/cristallina/applications/mx/zamofing_t/ESB_MX/python/SwissMX
git@git.psi.ch:epics_ioc_modules/ESB_MX.git
git remote add sf-cristallina gac-cristall@saresc-cons-03:/sf/cristallina/applications/mx/zamofing_t/ESB_MX/python/SwissMX
git fetch sf-cristallina
# do local changes and commit stuff
git push sf-cristallina
```
22.6.23 debug segmentation fault
--------------------------------
```
THE CHRISTALLINA CONTROL ROOM RUNS NORMALLY ON saresc-cons-05
[saresc-cons-05 ~]$
ulimit -a
ulimit -c unlimited
python -X faulthandler -X tracemalloc -X dev swissmx.py 2>&1 | tee /tmp/swissmx000.log
reset;tail -c+0 -F /tmp/swissmx000.log
python -X faulthandler -X tracemalloc -X importtime -X dev swissmx.py --sim 0xff
python -X faulthandler -X tracemalloc -X dev swissmx.py --sim 0xff
zamofing_t@ganymede:~/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/SwissMX$
rsync -vai swissmx.py saresc-cons-03:/sf/cristallina/applications/mx/zamofing_t/ESB_MX/python/SwissMX/swissmx_segFault.py
read: https://docs.python.org/3/library/faulthandler.html
coredump erzeugen
cat /proc/sys/kernel/core_pattern
sudo echo "/tmp/core" > /proc/sys/kernel/core_pattern
ulimit -c unlimited
python -c "import ctypes; ctypes.string_at(0)"
python -X faulthandler -c "import ctypes; ctypes.string_at(0)"
Rene did:
[root@saresc-cons-05 ~]# sysctl -w kernel.core_pattern="/tmp/%e_core_dump.%p"
cat /proc/sys/kernel/core_pattern
/tmp/%e_core_dump.%p
ll /tmp/python_core_dump.*
gdb python /tmp/core
bt (for facktrace)
trying python c code extention:
/home/zamofing_t/Documents/prj/scratch/python/sample_c_extension
Thread 0x00007fd2e16e8700 (most recent call first):
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 620 in get_with_metadata
...
File "/gfa/.mounts/sf_cristallina/applications/mx/zamofing_t/ESB_MX/python/SwissMX/epics_widgets/MotorTweak.py", line 216 in update_label
...
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 48 in wrapped
```
Coredump 29.6.23 18h40
----------------------
```
grep -c '5000/5000' *
swissmx000.log:57
swissmx001.log:36
swissmx002.log:35
swissmx002.log 35*5000 frames
35*5000/100/60 -> every 29.16min of acquisition a crash
rsync -vai gac-cristall@saresc-cons-05:/tmp/swissmx* ~/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/python/SwissMX/log
ll /tmp/swissmx*
ll /tmp/python_core_dump.*
Thread 0x00007fb9b13f7700 (most recent call first):
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 48 in wrapped
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 620 in get_with_metadata
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 48 in wrapped
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 620 in get_with_metadata
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 48 in wrapped
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/ca.py", line 1122 in element_count
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 489 in get
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 48 in wrapped
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 620 in get_with_metadata
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 48 in wrapped
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 981 in nelm
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/ca.py", line 579 in wrapper
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/ca.py", line 1122 in element_count
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 48 in wrapped
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 48 in wrapped
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/ca.py", line 549 in wrapper
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/ca.py", line 871 in current_context
File "/sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/pyepics-3.4.3-py3.9.egg/epics/pv.py", line 48 in wrapped
conda activate crmx38
ll /tmp/python_core_dump.*
gdb python /tmp/python_core_dump.21072
Core was generated by `python -X faulthandler -X tracemalloc -X dev swissmx.py'.
Program terminated with signal 11, Segmentation fault.
bt
0 write_thread_id.isra.3 (is_current=0, fd=<optimized out>) at /opt/conda/conda-bld/python-split_1648465063888/work/Python/traceback.c:849
#1 _Py_DumpTracebackThreads () at /opt/conda/conda-bld/python-split_1648465063888/work/Python/traceback.c:914
#2 0x000055c2b7ef6635 in faulthandler_dump_traceback.isra.2 (fd=fd@entry=2, all_threads=1) at /opt/conda/conda-bld/python-split_1648465063888/work/Modules/faulthandler.c:242
#3 0x000055c2b7ef67a3 in faulthandler_fatal_error (signum=11) at /opt/conda/conda-bld/python-split_1648465063888/work/Modules/faulthandler.c:348
#4 <signal handler called>
#5 0x00007fb9c7ed4ef4 in QWidgetTextControl::document() const () from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/../../../libQt5Widgets.so.5
#6 0x00007fb9c7e676e1 in ?? () from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/../../../libQt5Widgets.so.5
#7 0x00007fb9c7e69230 in QLabel::paintEvent(QPaintEvent*) () from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/../../../libQt5Widgets.so.5
#8 0x00007fb9d7fa16d3 in sipQLabel::paintEvent(QPaintEvent*) () from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/QtWidgets.abi3.so
#9 0x00007fb9c7dcc580 in QWidget::event(QEvent*) () from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/../../../libQt5Widgets.so.5
#10 0x00007fb9c7e36203 in QFrame::event(QEvent*) () from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/../../../libQt5Widgets.so.5
#11 0x00007fb9d7fa2d03 in sipQLabel::event(QEvent*) () from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/QtWidgets.abi3.so
#12 0x00007fb9c7da20f1 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/../../../libQt5Widgets.so.5
#13 0x00007fb9d8097afe in sipQApplication::notify(QObject*, QEvent*) () from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/QtWidgets.abi3.so
#14 0x00007fb9e6cadd62 in QCoreApplication::notifyInternal2(QObject*, QEvent*) () from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/../../../libQt5Core.so.5
#15 0x00007fb9c7dc6de6 in QWidgetPrivate::sendPaintEvent(QRegion const&) () from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/../../../libQt5Widgets.so.5
#16 0x00007fb9c7dc774e in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRepaintManager*) ()
from /sf/cristallina/applications/conda/envs/crmx38/lib/python3.8/site-packages/PyQt5/../../../libQt5Widgets.so.5
#17 0x00007fb9c7dc8147 in QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, QFlags<QWidgetPrivate::DrawWidgetFlag>, QPainter*, QWidgetRe
``` ```
Localize mionitors and callbacks:
## testing hit and return:
``` ```
-> add a FixTarget
grep -Rn 'add_callback' *.py "mode:6,ssz:(6,8),
dscr: {
size:(4560,2520),
swissmx.py:698: self.sigNewCamImg.connect(self.cb_update_img) fiducial:{type:0,pos:((240,240),(4320,240),(240,2280),(4320,2280))},
swissmx.py:745: def cb_update_img(self): grid:{pos:(480,360),pitch:(90,60),count:(40,30)}
epics_widgets/MotorTweak.py:88: m.set_callback('RBV', self.emit_signals, {'source_field': 'RBV'}) }" -> add a FixTarget
epics_widgets/SmaractMotorTweak.py:100: self._pv_readback.add_callback(self.update_label)
swissmx.py:717: cam.run(self.cb_new_frame_pv)
swissmx.py:743: self.sigNewCamImg.emit()
swissmx.py:745: def cb_update_img(self):
swissmx.py:698: self.sigNewCamImg.connect(self.cb_update_img)
camera.py:159: self._pv['pic'] = epics.PV(self._prefix + "FPICTURE", auto_monitor=True, callback=cb)
-> try to turn of the monitors during ascuisition:
zamofing_t@ganymede:~/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX$
grep -r set_callback *
https://pyepics.github.io/pyepics/pv.html#automatic-monitoring-of-a-pv
Try with:
pv.clear_auto_monitor() -> pv.reconnect()
pv.remove_callback(index=None) -> pv.add_callback(callback=None[, index=None [, with_ctrlvars=True[, **kw]])
pv.set_callback
FixTargetFrame -> paint -> _log.debug()
Turn off jungfrau.
no motion -> wait 1h
constant up-dow motion code -> wait 1h
``` ```
sync and triggering
-------------------
```
EVR output powerBrick register $(USR_FLAG_ID)
FrontUnivOut4 Gate3[1].Chan[0].UserFlag 5 acquisition start
FrontUnivOut5 Gate3[1].Chan[1].UserFlag 6 frame trigger
FrontUnivOut6 Gate3[1].Chan[2].UserFlag 7 unused
-> Deltatau flags are inverted: FrontUnivOut6(Force Low) -> Gate3[1].Chan[2].UserFlag==1
FrontUnivOut4 <- Pulser 0 <- active low <- event 254 (not used any more)
FrontUnivOut5 <- Pulser 1 <- active low <- event 215 (cristallina frame trigger)
FrontUnivOut6 <- Force Low
MXMotion.py -> setup_sync()
elif sync_mode in(1,2):
#frequence jitter 50Hz Swissgrid:
#https://www.swissgrid.ch/de/home/operation/grid-data/current-data.html#
flag0='Coord[{crdId}].Q[10]'.format(crdId=crdId) if sync_flag&1 else 'Gate3[1].Chan[0].UserFlag'
flag1='Coord[{crdId}].Q[11]'.format(crdId=crdId) if sync_flag&2 else 'Gate3[1].Chan[1].UserFlag'
-> looks at Q10/Q11 for start and sync (in simulation)
-> looks at User-Flags from the EVR for start and sync (in real)
s.a. ~/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX/Readme.md -> EVR
```
23.9.24 spitting/moving repositories
------------------------------------
```
https://jira.psi.ch/browse/SFELPHOTON-1337: SwissMX split/ cleanup/move repositories
```
----------------------------------- SCRATCH -----------------------------------
-0.952
pp_comm.py_:
@property
def fast_gather(self):
tries to connect to port and to query_types(), if fails starts the fast gather process.
triggerSync.c:
root@:/opt/ppmac# LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/triggerSync
usage:
/tmp/triggerSync pt2ptTime timeOfs mode
pt2ptTime: time in ms (float value) from point to point == frequency if FEL
timeOfs: time offset in ms (float value) for motion relative to the FEL timing
The program changes the speed of motion
pshm->Coord[1].DesTimeBase= (default serverPeriod= 0.2?)
SIMFLAG0 (pshm->Coord[1].Q[10]) -> start trigger
SIMFLAG1 (pshm->Coord[1].Q[11]) -> FEL pulse trigger
//Power PMAC Software Reference Manual.pdf Gate3[i].Chan[j].Status -> page 919 UserFlag
#define FLAG0 (gate3_1->Chan[0].Status&0x800) -> start trigger
#define FLAG1 (gate3_1->Chan[1].Status&0x800) -> FEL pulse trigger
mode:
bit0:1: sync mode
bit1:2: simulate start trigger
bit2:4: simulate frame trigger
bit3:8: verbose
simulate start trigger:
set pshm->Coord[1].Q[10]=1 to simulate a Jungfrau aquire start
simulate frame trigger
is output to pshm->Coord[1].Q[11]
1: synchronize real frame and start triggers
3: synchronize real frame and simulated start triggers
6: simulated frame and start triggers (no sync)
7: synchronize simulated frame and start triggers
in simulate mode:
set pshm->Coord[1].Q[10]=1 to simulate a Jungfrau aquire start
set pshm->Coord[1].Q[10]=2 to stop simulate trigger generation
Coord[1].Q[11] is the simulated frame trigger
in synchronize mode
Coord[1].Q[0]=-2 : trigsync_func start, Wait for 'arm' trigger
Coord[1].Q[0]=-1 : got 'arm' trigger, wait frame trigger
Coord[1].Q[0]= 0 : got frame trigger 0
Coord[1].Q[0] is incremented at each trigger
sync task ends when Gather.Enable==0
// /tmp/triggerSync 40 11 trigger all 40 ms, simulated start, use real frame triggers, verbose
// /tmp/triggerSync 40 14 trigger all 40 ms, simulated start and frame triggers, no sync, verbose
// /tmp/triggerSync 40 15 trigger all 40 ms, simulated start and frame triggers, with sync, verbose
// /tmp/triggerSync 40 7 trigger all 40 ms, simulated start and frame triggers, with sync, minimal verbose
78x78 points =6084pts a 10ms =60 sec. -> 70 sec.
-> we are at 100 Hz !!!
remote ssh tunnel + start gather_server
---------------------------------------
```
PPMAC=SAR-CPPM-EXPMX1
rsync -va ~/Documents/prj/SwissFEL/PBTools/pbtools/gather/gather_server root@$PPMAC:/tmp/
lsof -i -n | grep '127.0.0.1:1000'
ssh -L 10001:localhost:22 root@$PPMAC 'uname -a'
ssh -L 10002:localhost:2332 root@$PPMAC 'uname -a'
ssh root@$PPMAC
LD_LIBRARY_PATH=/opt/ppmac/libppmac/ /tmp/gather_server
```
cleanup /tmp/
-------------
```
PPMAC=SAR-CPPM-EXPMX1
ssh root@$PPMAC rm /tmp/gather_server /tmp/triggerSync
ssh root@$PPMAC ls -l /tmp
```
start debug tools
-----------------
```
PPMAC=SAR-CPPM-EXPMX1
PBInspect --host=$PPMAC&
gpasciiCommander --host $PPMAC -i
ssh root@$PPMAC
ssh root@$PPMAC rm /tmp/gather_server /tmp/triggerSync
ssh root@$PPMAC ls -l /tmp
```
restart IOC
-----------
```
ssh saresc-cons-03
PPMAC=SAR-CPPM-EXPMX1
telnet $PPMAC 50001
Ctrl-X
dbgf SAR-CPPM-EXPMX1:MOD_VER
caget SAR-CPPM-EXPMX1:MOD_VER
```
checking versions
-----------------
```
git: 7a968aac967
asyn 427.0.2
motorBase alpha_220518
asynMotor alpha_220518
powerPmac alpha_220518
PB_COMMON 2.0.1
gpasciiCommander 0.9.0
ESB_MX 0.0.2
```
zamofing_t@ganymede:~/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX$
git loggraph -10
* 7a968aa 2022-09-20 (HEAD -> master, tag: latest, tag: 0.0.2, psigithub/master) change speeds and directions [Thierry Zamofing]
* 00588f8 2022-09-16 minor changes [Thierry Zamofing]
* d52a6ce 2022-08-30 minor changes [Thierry Zamofing]
* f47e111 2022-05-20 (tag: 0.0.1) add DET_Z motor [Thierry Zamofing]
* 8e5b15e 2022-05-20 wip [Thierry Zamofing]
* 399282c 2019-03-20 enhance triggering [Thierry Zamofing]
* eda8caf 2019-03-19 wip [Thierry Zamofing]
* 0c45705 2019-03-08 optimize [Thierry Zamofing]
* c962ebd 2019-03-06 documentation [Thierry Zamofing]
git reset --hard 399282c
rmake -e LIBVERSION=42.42.42 uninstall install
-> restart IOC
ssh root@$PPMAC rm /tmp/triggerSync
cd python
git dt latest -- shapepath.py
./shapepath.py --host=localhost:10001:10002
removing test verion
ssh sf-lc7 ls -l /ioc/modules/ESB_MX/
ssh sf-lc7 rm -rf /ioc/modules/ESB_MX/42.42.42
IOC locations
-------------
```
~/Documents/prj/SwissFEL/epics_ioc_boot_sf/ESC_all/ESB_MX_PowerBrick
They are just using the new alphy driver. That should have no impact on the motion config.
```
test shapepath
--------------
```
cd ~/Documents/prj/SwissFEL/epics_ioc_modules/ESB_MX
./shapepath.py --host=localhost:10001:10002
```

BIN
SwissMX.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

View File

@@ -251,13 +251,33 @@ class Grid(UsrROI):
def get_scan_param(self): def get_scan_param(self):
'returns scan parameters for scanning with deltatau. the format is as used for shapepath' 'returns scan parameters for scanning with deltatau. the format is as used for shapepath'
scan=1 # snake motion Y fast, X slow (default)
cnt=np.array(self._cnt, np.int32) cnt=np.array(self._cnt, np.int32)
sz=np.array(self.size()) grid={'pos':tuple(self.pos()), 'pitch':tuple(np.array(self.size())/cnt), 'count':self._cnt}
pitch=sz/cnt use_trf=self._param.get('use_trf', True) # do not use coordinate transformation
mode=self._param.get('mode',1)
num_pts=np.array(self._cnt, np.int32).prod()
param={'num_pts':num_pts}
param.update(self._param)
# TODO: simplify !!!
t=self.transform() #obj_info(t)
p=np.array(self.pos())
s=1#self.size()/self._dscr['size']
trf=np.array(((t.m11(),t.m12()),(t.m21(),t.m22()),(0,0)))
trf[2,:]=p # shift origin
trf[:2,:]=(trf[:2,:].T*s).T # same as np.asmatrix(np.diag(s))*trf[:2,:], trf[:2,:]*=s not working, scale before rot / shear
pos=np.array((0,0)) #np.array(grid['pos']) # in um
pitch=np.array(grid['pitch']) # in um
trf2=np.asmatrix(np.identity(3))
trf2[:, :2]=trf
trf2*=np.asmatrix(((1000, 0, 0), (0, 1000, 0), (0, 0, 1)))
trf3=np.asmatrix(((pitch[0], 0, 0), (0, pitch[1], 0), (pos[0], pos[1], 1)))
trf=(trf3*trf2)[:, :2]
if mode in (1,3): # needs all points, not grid
scan=1 # snake motion Y fast, X slow (default)
xx, yy=np.meshgrid(range(cnt[0]), range(cnt[1])) xx, yy=np.meshgrid(range(cnt[0]), range(cnt[1]))
if scan==0: # snake motion X fast, Y slow if scan==0: # snake motion X fast, Y slow
for i in range(1,cnt[1],2): for i in range(1,cnt[1],2):
xx[i]=xx[i][::-1] xx[i]=xx[i][::-1]
@@ -266,10 +286,20 @@ class Grid(UsrROI):
yy=yy.T yy=yy.T
for i in range(1, cnt[0], 2): for i in range(1, cnt[0], 2):
yy[i]=yy[i][::-1] yy[i]=yy[i][::-1]
pts=np.array([xx.reshape(-1), yy.reshape(-1)], dtype=np.float64).transpose()*pitch
param={'points':pts} pts=np.array([xx.reshape(-1), yy.reshape(-1)], dtype=np.float64).transpose() #*pitch
param.update(self._param)
assert(param.get('code_gen',0)==0) # this provides fully x,y motor coordinates if not use_trf:
pts=(np.hstack((pts, np.ones((pts.shape[0], 1))))*trf).A
param['trf']=trf
param['points']=pts
else:
if use_trf:
param.update({'grid':grid, 'trf':trf})
else:
g=grid.copy() #has not be tested !
g['pos']=tuple((np.array((0,0,1))*trf).A.reshape(-1).tolist())
param.update({'grid':p, 'trf':trf})
return param return param
@@ -371,11 +401,9 @@ class Path(UsrROI):
s=self.size()/self.szOrig s=self.size()/self.szOrig
trf=np.array(((t.m11(),t.m12()),(t.m21(),t.m22()),(0,0))) trf=np.array(((t.m11(),t.m12()),(t.m21(),t.m22()),(0,0)))
trf[2,:]=p # shift origin trf[2,:]=p # shift origin
#trf[:2, 0]*=s[0];trf[:2, 1]*=s[1] #scaling (before rotation shear) trf[:2,:]=(trf[:2,:].T*s).T
trf[:2,:]=(trf[:2,:].T*s).T # same as np.asmatrix(np.diag(s))*trf[:2,:], trf[:2,:]*=s not working, scale before rot / shear
# trf*'gridpos in um' -> motor pos in mm # trf*'gridpos in um' -> motor pos in mm
param={'points':self._path,'trf':trf} param={'num_pts':len(self._path),'trf':trf,'points':self._path}
param.update(self._param) param.update(self._param)
return param return param
@@ -518,21 +546,13 @@ class FixTargetFrame(UsrROI):
def get_scan_param(self): def get_scan_param(self):
'returns scan parameters for scanning with deltatau. the format is as used for shapepath' 'returns scan parameters for scanning with deltatau. the format is as used for shapepath'
scan=1 # snake motion Y fast, X slow (default)
grid=self._dscr['grid'] grid=self._dscr['grid']
self._dscr['size'] use_trf=self._param.get('use_trf', True) # do not use coordinate transformation
mode=self._param.get('mode',1)
cnt=np.array(grid['count'], np.int32) cnt=np.array(grid['count'], np.int32)
xx, yy=np.meshgrid(range(cnt[0]), range(cnt[1])) num_pts=cnt.prod()
if scan==0: # snake motion X fast, Y slow param={'num_pts':num_pts}
for i in range(1,cnt[1],2): param.update(self._param)
xx[i]=xx[i][::-1]
else: # scan==1 # snake motion Y fast, X slow (default)
xx=xx.T
yy=yy.T
for i in range(1, cnt[0], 2):
yy[i]=yy[i][::-1]
pts=np.array([xx.reshape(-1), yy.reshape(-1)], dtype=np.float64).transpose() #*pitch
# TODO: simplify !!! # TODO: simplify !!!
t=self.transform() #obj_info(t) t=self.transform() #obj_info(t)
@@ -549,9 +569,32 @@ class FixTargetFrame(UsrROI):
trf2*=np.asmatrix(((1000, 0, 0), (0, 1000, 0), (0, 0, 1))) trf2*=np.asmatrix(((1000, 0, 0), (0, 1000, 0), (0, 0, 1)))
trf3=np.asmatrix(((pitch[0], 0, 0), (0, pitch[1], 0), (pos[0], pos[1], 1))) trf3=np.asmatrix(((pitch[0], 0, 0), (0, pitch[1], 0), (pos[0], pos[1], 1)))
trf=(trf3*trf2)[:, :2] trf=(trf3*trf2)[:, :2]
param={'grid':grid, 'points':pts, 'trf':trf}
param.update(self._param)
if mode in (1,3): # needs all points, not grid
scan=1 # snake motion Y fast, X slow (default)
xx, yy=np.meshgrid(range(cnt[0]), range(cnt[1]))
if scan==0: # snake motion X fast, Y slow
for i in range(1,cnt[1],2):
xx[i]=xx[i][::-1]
else: # scan==1 # snake motion Y fast, X slow (default)
xx=xx.T
yy=yy.T
for i in range(1, cnt[0], 2):
yy[i]=yy[i][::-1]
pts=np.array([xx.reshape(-1), yy.reshape(-1)], dtype=np.float64).transpose() #*pitch
if not use_trf:
pts=(np.hstack((pts, np.ones((pts.shape[0], 1))))*trf).A
param['trf']=trf
param['points']=pts
else:
if use_trf:
param.update({'grid':grid, 'trf':trf})
else:
g=grid.copy() #has not be tested !
g['pos']=tuple((np.array((0,0,1))*trf).A.reshape(-1).tolist())
param.update({'grid':p, 'trf':trf})
return param return param

View File

@@ -100,7 +100,7 @@ class timestamp():
ts=timestamp() ts=timestamp()
ts.log('Import part 1/8:') ts.log('Import part 1/8:')
import sys, os import sys, os
import json, re import yaml
import signal, subprocess import signal, subprocess
import matplotlib as mpl import matplotlib as mpl
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
@@ -1516,7 +1516,7 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
#self._inspect = self._grid_inspect_area #self._inspect = self._grid_inspect_area
#self._inspect.setPlainText("") #self._inspect.setPlainText("")
fast_x=self.tweakers["fast_x"]; fast_x=self.tweakers["fast_x"]
fast_y=self.tweakers["fast_y"] fast_y=self.tweakers["fast_y"]
fx=fast_x.get_val() fx=fast_x.get_val()
fy=fast_y.get_val() fy=fast_y.get_val()
@@ -1527,7 +1527,7 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
if type(go)==UsrGO.Fiducial: if type(go)==UsrGO.Fiducial:
continue continue
t=type(go) t=type(go)
if t not in(UsrGO.FixTargetFrame,UsrGO.Path): if t not in(UsrGO.FixTargetFrame,UsrGO.Path,UsrGO.Grid):
_log.warning(f'{t} not supported for FixTargetFrame ->skipped:{go}') _log.warning(f'{t} not supported for FixTargetFrame ->skipped:{go}')
continue continue
try: try:
@@ -1535,11 +1535,6 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
except AttributeError as e: except AttributeError as e:
_log.warning(f'no scan parameters for object->skipped:{go}') _log.warning(f'no scan parameters for object->skipped:{go}')
continue continue
trf=np.asmatrix(param['trf'])
p=param['points']
p=(np.hstack((p,np.ones((p.shape[0],1))))*trf).A
param['pts_trf']=p # transformed points in um motor coordinates
param['num_pts']=p.shape[0]
vb=self.vb vb=self.vb
grp=self._goTracked grp=self._goTracked
mft=self._moduleFixTarget mft=self._moduleFixTarget
@@ -1986,6 +1981,53 @@ Author Thierry Zamofing (thierry.zamofing@psi.ch)
self._tabs_daq_methods.setCurrentWidget(mft) #set this as the active tabs self._tabs_daq_methods.setCurrentWidget(mft) #set this as the active tabs
mft._cbType.addItems(["Fiducial", "FixTarget(12.5x12.5)", "FixTarget(23.0x23.0)", "FixTarget(test)", "Grid()", "SwissMX()", "SwissFEL()"]) mft._cbType.addItems(["Fiducial", "FixTarget(12.5x12.5)", "FixTarget(23.0x23.0)", "FixTarget(test)", "Grid()", "SwissMX()", "SwissFEL()"])
#print(psi_device.shapepath.ShapePath.setup_motion.__doc__)
mft._txtParam.setToolTip('''\
additional parameter as yaml for object settings and motion generation:
full example for grid() object and motion settings:
size:[3.6,2.664],cnt:[30,22],fiducialSize:0.05,mode:6,scale:.5,ssz:[7,4],smv:[6,4],sdelay:9
further examples:
object settings:
for Grid(): size:[4,3],cnt:[30,22],fiducialSize:0.1
motion param:
for continous: cnt:2,scale:.3,dwell:100
for stop-and-go: tmove:10,twait:20
for hit-and-return: ssz:(4,6)
motion generation:
For details read: psi_device.shapepath.ShapePath.setup_motion.__doc__
mode: select one of following modes: 1,3,4,5,6
mode settings:
all: cnt:1
scale:1.
dwell:10
5: tmove:10
twait:20
6: ssz:(7,4)
smv:(6,4) (delault defined)
sdelay:9 (delault defined)
object settings:
Fiducial:
no param
FixTarget(12.5x12.5), FixTarget(23.0x23.0), FixTarget(test):
no param
Grid():
size:[30,20]
cnt:[30,22]
fiducialSize:0.1
SwissMX():
ofs:[.2,.2]
width:10
fidScl:.02
fiducial:[[.1,.1],[.1,2.7],[10.3,.1],[10.3, 2.7]]
SwissFEL():
ofs:[.2,.2]
width:10
fidScl:.02
fiducial:[[.1,.1],[.1,2.2],[10.3,.1],[10.3,2.2]]
''')
mft._btnAdd.clicked.connect(self.module_fix_target_add_obj) mft._btnAdd.clicked.connect(self.module_fix_target_add_obj)
mft._btnDelAll.clicked.connect(self.module_fix_target_del_all_obj) mft._btnDelAll.clicked.connect(self.module_fix_target_del_all_obj)
mft._btnFit.clicked.connect(self.module_fix_target_fit_fiducial) mft._btnFit.clicked.connect(self.module_fix_target_fit_fiducial)
@@ -2097,67 +2139,23 @@ Author Thierry Zamofing (thierry.zamofing@psi.ch)
bm_pos=self._goBeamMarker.pos() bm_pos=self._goBeamMarker.pos()
bm_sz=self._goBeamMarker.size() bm_sz=self._goBeamMarker.size()
idx=mft._cbType.currentIndex() idx=mft._cbType.currentIndex()
param=mft._txtParam.text() param=mft.get_param()
#mft._cbType.addItems(["Fiducial", "FixTarget(12.5x12.5)", "FixTarget(23.0x23.0)", "FixTarget(<param>)", "Grid(<param>)", "SwissMX-path"])
#bm_pos_eu=self._goBeamMarker._pos_eu
#bm_size_eu=self._goBeamMarker._size_eu
try:
#parse the parameters: 'key:value [,key:value]'
# as key value separator : and = are allowed
#examples:
#Fiducial:
# no param
#FixTarget(12.5x12.5), FixTarget(23.0x23.0), FixTarget(test):
# code_gen:2
# code_gen=3 | tmove=10 | twait=30
#Grid():
# size:(30, 20)
# cnt:(30, 22)
# fiducialSize:0.1
#SwissMX():
# ofs:(.2, .2)
# width:10
# fidScl:.02
# fiducial:((.1, .1), (.1, 2.7), (10.3, .1), (10.3, 2.7))
#SwissFEL():
# ofs:(.2, .2)
# width:10
# fidScl:.02
# fiducial:((.1, .1), (.1, 2.2), (10.3, .1), (10.3, 2.2))
pLst=param.split('|')
pStr=list()
for p in pLst:
if not p: continue
m=re.match('\s*(.*?)\s*[=:]\s*(.*)\s*', p)
k, v=m.groups()
v=v.replace('(', '[').replace(')', ']')
pStr.append(f'"{k}":{v}')
pStr='{'+','.join(pStr)+'}'
param=json.loads(pStr) # "ofs":[10, 5],"width":200,"fidScl":0.5,"fiducial":[[18,7],[25,16],[70, 20]]
except json.decoder.JSONDecodeError as e:
_log.error(f'{e}:{param}')
param=dict()
if idx==0: if idx==0:
#go=UsrGO.Fiducial(bm_pos+bm_sz/2-(20, 20), (40, 40),(fx,fy,bz)) #go=UsrGO.Fiducial(bm_pos+bm_sz/2-(20, 20), (40, 40),(fx,fy,bz))
l=.120 l=.120
go=UsrGO.Fiducial((fx-l/2,fy-l/2), (l, l),bz) go=UsrGO.Fiducial((fx-l/2,fy-l/2), (l, l),bz)
go.sigRegionChangeFinished.connect(self.cb_fiducial_update_z) go.sigRegionChangeFinished.connect(self.cb_fiducial_update_z)
elif idx==1: elif idx==1:
v=geo.pos2pix((12.5, 0)) #v=geo.pos2pix((12.5, 0));l=np.linalg.norm(v);l=12.5
l=np.linalg.norm(v) sz=param.pop('size',(12.5, 12.5))
l=12.5
#ctr=bm_pos+bm_sz/2
go=UsrGO.FixTargetFrame((fx-l/2,fy-l/2), (l, l), tpl='12.5x12.5',**param) go=UsrGO.FixTargetFrame((fx-l/2,fy-l/2), (l, l), tpl='12.5x12.5',**param)
elif idx==2: elif idx==2:
v=geo.pos2pix((23, 0)) #v=geo.pos2pix((23, 0));l=np.linalg.norm(v)#l=23
l=np.linalg.norm(v) sz=param.pop('size',(23, 23))
l=23
go=UsrGO.FixTargetFrame((fx-l/2,fy-l/2), (l, l), tpl='23.0x23.0',**param) go=UsrGO.FixTargetFrame((fx-l/2,fy-l/2), (l, l), tpl='23.0x23.0',**param)
elif idx==3: elif idx==3:
w,h=(.120*12, .120*8) sz=param.pop('size',(.120*12, .120*8))
go=UsrGO.FixTargetFrame((fx-w/2,fy-h/2), (w, h), tpl='test',**param) go=UsrGO.FixTargetFrame((fx-sz[0]/2,fy-sz[1]/2), sz, tpl='test',**param)
elif idx==4: elif idx==4:
w,h=size=param.pop('size',(30, 20)) w,h=size=param.pop('size',(30, 20))
cnt=param.pop('cnt',(30, 22)) cnt=param.pop('cnt',(30, 22))
@@ -2271,14 +2269,6 @@ Author Thierry Zamofing (thierry.zamofing@psi.ch)
def daq_collect(self, **kwargs):# points, visualizer_method, visualizer_params): def daq_collect(self, **kwargs):# points, visualizer_method, visualizer_params):
''' '''
kwargs: kwargs:
code_gen: 0 pvt motion using ptsTrf
1 pvt motion using trf and points
2 pvt motion, compact grid code
3 pvt motion, compact grid code move and wait
tmove: time to move
twait: time to wait
grid: grid dictionary with orig, pitch, count grid: grid dictionary with orig, pitch, count
trf: transformation matrix trf: transformation matrix
points: list of points without transformation points: list of points without transformation
@@ -2322,28 +2312,24 @@ Author Thierry Zamofing (thierry.zamofing@psi.ch)
#dlg.setAutoClose(True) #dlg.setAutoClose(True)
#dlg.show() #dlg.show()
dlg.setLabelText("Setup Gather/Sync");dlg+=5 dlg.setLabelText("Setup Gather/Sync");dlg+=5
code_gen=kwargs.get('code_gen',0) mode=kwargs.pop('mode',1)
sp.setup_sync(verbose=sp.verbose&0x40, timeOfs=dt_misc['time_ofs'], timeCor=dt_misc['time_cor']) sp.setup_sync(verbose=sp.verbose&0x40, timeOfs=dt_misc['time_ofs'], timeCor=dt_misc['time_cor'])
dlg.setLabelText("Download motion program");dlg+=5 dlg.setLabelText("Download motion program");dlg+=5
if code_gen==0:
sp.setup_motion(fnPrg=fn+'.prg', mode=3, scale=1., dwell=10, points=kwargs['pts_trf']) use_trf=kwargs.get('use_trf', True) # do not use coordinate transformation
elif code_gen==1: if not use_trf:
sp.setup_motion(fnPrg=fn+'.prg', mode=3, scale=1., dwell=10, points=kwargs['points'],trf=kwargs['trf']) trf=kwargs.pop('trf')
elif code_gen==2: try:
sp.setup_motion(fnPrg=fn+'.prg', mode=4, scale=1., dwell=10, grid=kwargs['grid'], trf=kwargs['trf']) sp.setup_motion(fnPrg=fn+'.prg', mode=mode, **kwargs)
elif code_gen==3: except BaseException as e:
sp.setup_motion(fnPrg=fn+'.prg', mode=5, dwell=10, tmove=kwargs['tmove'] ,twait=kwargs['twait'], grid=kwargs['grid'],trf=kwargs['trf']) _log.error(repr(e));return
sp.setup_gather() sp.setup_gather()
if not use_trf:
kwargs['trf']=trf
try: try:
p=geo._fitPlane p=geo._fitPlane
# TODO: Cleanup #TODO: cleanup
if code_gen==0: if use_trf:
# X has inverted sign !
# Z is in um -> therefore the offset must be multiplied with 1000 ! Z motor has opposite sign !
#cz=f'{+p[0]:+.18g}X{-p[1]:+.18g}Y{-p[2]*1000:+.18g}'
t=p*np.array((1,1,1000))
cz=f'{t[0]:+.18g}X{t[1]:+.18g}Y{t[2]:+.18g}'
else:
trf=kwargs['trf'] # grid-coord -> motor-um trf=kwargs['trf'] # grid-coord -> motor-um
#(0,0,1)*trf #(0,0,1)*trf
# trf*'gridpos in um' -> motor pos in mm # trf*'gridpos in um' -> motor pos in mm
@@ -2354,25 +2340,31 @@ Author Thierry Zamofing (thierry.zamofing@psi.ch)
#(0, 0, 1)*trf2*trf3 -> z in um of gridpos(0,0) #(0, 0, 1)*trf2*trf3 -> z in um of gridpos(0,0)
t=(trf2*trf3)[:,0].A.ravel() t=(trf2*trf3)[:,0].A.ravel()
cz=f'{t[0]:+.18g}X{t[1]:+.18g}Y{t[2]:+.18g}' cz=f'{t[0]:+.18g}X{t[1]:+.18g}Y{t[2]:+.18g}'
else:
# X has inverted sign !
# Z is in um -> therefore the offset must be multiplied with 1000 ! Z motor has opposite sign !
#cz=f'{+p[0]:+.18g}X{-p[1]:+.18g}Y{-p[2]*1000:+.18g}'
t=p*np.array((1,1,1000))
cz=f'{t[0]:+.18g}X{t[1]:+.18g}Y{t[2]:+.18g}'
except AttributeError: except AttributeError:
cz='0' cz='0'
_log.warning('no plane fitting done. z does not move') _log.warning('no plane fitting done. z does not move')
trf=kwargs['trf'] trf=kwargs['trf']
if code_gen==0: if use_trf:
fx='X';fy='Y'
else:
fx=f'{trf[0, 0]:+.18g}X{trf[1, 0]:+.18g}Y{trf[2, 0]:+.18g}' fx=f'{trf[0, 0]:+.18g}X{trf[1, 0]:+.18g}Y{trf[2, 0]:+.18g}'
fy=f'{trf[0, 1]:+.18g}X{trf[1, 1]:+.18g}Y{trf[2, 1]:+.18g}' fy=f'{trf[0, 1]:+.18g}X{trf[1, 1]:+.18g}Y{trf[2, 1]:+.18g}'
else:
fx='X';fy='Y'
if _log.level==logging.DEBUG: if _log.level==logging.DEBUG:
try: t try: t
except NameError: t=(np.nan,np.nan,np.nan) except NameError: t=(np.nan,np.nan,np.nan)
fn='/tmp/coord.log' fn='/tmp/coord.log'
_log.debug(f'write all coordinates to {fn}') _log.debug(f'write all coordinates to {fn}')
if code_gen==0: if use_trf:
xy1=np.hstack((kwargs["pts_trf"],np.ones((kwargs["pts_trf"].shape[0],1))))
else:
xy1=np.hstack((kwargs["points"],np.ones((kwargs["points"].shape[0],1)))) xy1=np.hstack((kwargs["points"],np.ones((kwargs["points"].shape[0],1))))
else:
xy1=np.hstack((kwargs["pts_trf"],np.ones((kwargs["pts_trf"].shape[0],1))))
pcz=np.matrix(((t[0],t[1],t[2])))*xy1.T pcz=np.matrix(((t[0],t[1],t[2])))*xy1.T
x_y_fx_fy_cz=np.vstack((kwargs["points"].T, kwargs["pts_trf"].T, pcz)).A x_y_fx_fy_cz=np.vstack((kwargs["points"].T, kwargs["pts_trf"].T, pcz)).A
with open('/tmp/coord.log','w') as fh: with open('/tmp/coord.log','w') as fh: