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 import logging
_log=logging.getLogger(__name__) _log=logging.getLogger(__name__)
import json, base64, yaml 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:
@@ -173,28 +189,10 @@ class WndFixTarget(QWidget):
#bm_pos_eu=self._goBeamMarker._pos_eu #bm_pos_eu=self._goBeamMarker._pos_eu
#bm_size_eu=self._goBeamMarker._size_eu #bm_size_eu=self._goBeamMarker._size_eu
try: try:
#parse the parameters: 'key:value [,key:value]' #parse the parameters: as yaml string.
# as key value separator : and = are allowed # allows : without space, allows () as []
#examples: # no {} to define a dictionary
#Fiducial: # e.g. 'a:ggf,b:5,c:[5,6.1],d(8,9,3)'
# 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))
param=param.replace(':', ': ') # allow gen:4 without space 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]] 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 = 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:
@@ -386,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:

111
Readme.md
View File

@@ -102,3 +102,114 @@ python swissmx.py --sim 0xc0
``` ```
Document to start SwissMX in cristallina environment (maintained by John): Document to start SwissMX in cristallina environment (maintained by John):
https://docs.google.com/document/d/1yEmV_DbRBKQKVCoovjXriNgSjNEBaz50WA0l3yA5jtg/edit#heading=h.z9io692b8tow 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): 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) grid={'pos':tuple(self.pos()), 'pitch':tuple(np.array(self.size())/cnt), 'count':self._cnt}
sz=np.array(self.size()) use_trf=self._param.get('use_trf', True) # do not use coordinate transformation
pitch=sz/cnt mode=self._param.get('mode',1)
xx, yy=np.meshgrid(range(cnt[0]), range(cnt[1])) num_pts=np.array(self._cnt, np.int32).prod()
param={'num_pts':num_pts}
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}
param.update(self._param) 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 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

View File

@@ -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:
@@ -2025,7 +2025,7 @@ object settings:
ofs:[.2,.2] ofs:[.2,.2]
width:10 width:10
fidScl:.02 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) 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=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))