try to cleanup stuff(3)

This commit is contained in:
2024-12-11 15:26:01 +01:00
parent 71a473d25d
commit 0fe59e9ad6
4 changed files with 195 additions and 58 deletions

View File

@@ -16,7 +16,7 @@ This contains a Widget to handle FixTargetFrames and fiducials, calculate final
import logging
_log=logging.getLogger(__name__)
import json, base64, yaml
import os, json, base64, yaml
import numpy as np
import pyqtUsrObj as UsrGO
import pyqtgraph as pg
@@ -47,6 +47,22 @@ class MyJsonEncoder(json.JSONEncoder):
return repr(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):
if isinstance(dct, dict):
if '__class__' in dct:
@@ -173,28 +189,10 @@ class WndFixTarget(QWidget):
#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))
#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]]
@@ -376,7 +374,10 @@ class WndFixTarget(QWidget):
#df = pd.DataFrame(data)
#df.to_csv(filename, float_format="%.6f")
#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:
wnd=app._mainWnd
except AttributeError:
@@ -386,7 +387,7 @@ class WndFixTarget(QWidget):
grp=wnd._goTracked
data=grp.childItems()
if ext=='json':
if ext.lower()=='json':
with open(filename, 'w') as f:
json.dump(data, f,cls=MyJsonEncoder, indent=2)#separators=(',', ':')
else:

111
Readme.md
View File

@@ -102,3 +102,114 @@ 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
## code generation parameters
```
copied from: PBSwissMX/python/shapepath.py: ShapePath.setup_motion
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]]"
```
## fully parameter examples:
```
"mode:4,size:(7.08,5.28), cnt:(60,45), fiducialSize:.01" -> add a grid
"mode:6,ssz:(4,3), size:(7.08,5.28), cnt:(60,45), fiducialSize:.01" -> add a grid
"mode:6,ssz:(4,3), size:(3,1.5), cnt:(30,15), fiducialSize:.01" -> add a grid
"mode:6,ssz:(6,8),
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)}
}" -> add a FixTarget
```
## testing hit and return:
```
-> add a FixTarget
"mode:6,ssz:(6,8),
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)}
}" -> add a FixTarget
```

View File

@@ -251,25 +251,55 @@ class Grid(UsrROI):
def get_scan_param(self):
'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)
sz=np.array(self.size())
pitch=sz/cnt
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
param={'points':pts}
cnt=np.array(self._cnt, np.int32)
grid={'pos':tuple(self.pos()), 'pitch':tuple(np.array(self.size())/cnt), 'count':self._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)
assert(param.get('code_gen',0)==0) # this provides fully x,y motor coordinates
# 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]))
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
@@ -371,11 +401,9 @@ class Path(UsrROI):
s=self.size()/self.szOrig
trf=np.array(((t.m11(),t.m12()),(t.m21(),t.m22()),(0,0)))
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 # same as np.asmatrix(np.diag(s))*trf[:2,:], trf[:2,:]*=s not working, scale before rot / shear
trf[:2,:]=(trf[:2,:].T*s).T
# 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)
return param

View File

@@ -1527,7 +1527,7 @@ class WndSwissMx(QMainWindow, Ui_MainWindow):
if type(go)==UsrGO.Fiducial:
continue
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}')
continue
try:
@@ -2025,7 +2025,7 @@ object settings:
ofs:[.2,.2]
width:10
fidScl:.02
fiducial:[[.1,.1],[[.1,2.2],[10.3,.1],[10.3,2.2]]
fiducial:[[.1,.1],[.1,2.2],[10.3,.1],[10.3,2.2]]
''')
mft._btnAdd.clicked.connect(self.module_fix_target_add_obj)
@@ -2146,19 +2146,16 @@ object settings:
go=UsrGO.Fiducial((fx-l/2,fy-l/2), (l, l),bz)
go.sigRegionChangeFinished.connect(self.cb_fiducial_update_z)
elif idx==1:
v=geo.pos2pix((12.5, 0))
l=np.linalg.norm(v)
l=12.5
#ctr=bm_pos+bm_sz/2
#v=geo.pos2pix((12.5, 0));l=np.linalg.norm(v);l=12.5
sz=param.pop('size',(12.5, 12.5))
go=UsrGO.FixTargetFrame((fx-l/2,fy-l/2), (l, l), tpl='12.5x12.5',**param)
elif idx==2:
v=geo.pos2pix((23, 0))
l=np.linalg.norm(v)
l=23
#v=geo.pos2pix((23, 0));l=np.linalg.norm(v)#l=23
sz=param.pop('size',(23, 23))
go=UsrGO.FixTargetFrame((fx-l/2,fy-l/2), (l, l), tpl='23.0x23.0',**param)
elif idx==3:
w,h=(.120*12, .120*8)
go=UsrGO.FixTargetFrame((fx-w/2,fy-h/2), (w, h), tpl='test',**param)
sz=param.pop('size',(.120*12, .120*8))
go=UsrGO.FixTargetFrame((fx-sz[0]/2,fy-sz[1]/2), sz, tpl='test',**param)
elif idx==4:
w,h=size=param.pop('size',(30, 20))
cnt=param.pop('cnt',(30, 22))