newportxps 0.3.0__py3-none-any.whl → 0.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- newportxps/XPS_C8_drivers.py +276 -877
- newportxps/__init__.py +2 -0
- newportxps/debugtimer.py +107 -0
- newportxps/newportxps.py +302 -123
- newportxps/version.py +16 -0
- {newportxps-0.3.0.dist-info → newportxps-0.9.dist-info}/METADATA +3 -1
- newportxps-0.9.dist-info/RECORD +13 -0
- {newportxps-0.3.0.dist-info → newportxps-0.9.dist-info}/WHEEL +1 -1
- newportxps-0.3.0.dist-info/RECORD +0 -11
- {newportxps-0.3.0.dist-info → newportxps-0.9.dist-info}/LICENSE +0 -0
- {newportxps-0.3.0.dist-info → newportxps-0.9.dist-info}/top_level.txt +0 -0
newportxps/newportxps.py
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env python
|
|
2
2
|
|
|
3
|
-
import os
|
|
4
3
|
import posixpath
|
|
5
4
|
import sys
|
|
6
5
|
import time
|
|
7
6
|
import socket
|
|
8
|
-
from
|
|
7
|
+
from copy import deepcopy
|
|
9
8
|
from configparser import ConfigParser
|
|
10
9
|
import numpy as np
|
|
11
10
|
|
|
@@ -75,11 +74,12 @@ class NewportXPS:
|
|
|
75
74
|
err, uptime = self._xps.ElapsedTimeGet(self._sid)
|
|
76
75
|
self.check_error(err, msg="Elapsed Time")
|
|
77
76
|
boottime = time.time() - uptime
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
"#
|
|
81
|
-
"#
|
|
82
|
-
"#
|
|
77
|
+
hostn = socket.getfqdn(self.host)
|
|
78
|
+
out = [f"# XPS host: {self.host} ({hostn})",
|
|
79
|
+
f"# Firmware: {self.firmware_version}",
|
|
80
|
+
f"# Current Time: {time.ctime()}",
|
|
81
|
+
f"# Last Reboot: {time.ctime(boottime)}",
|
|
82
|
+
f"# Trajectory Group: {self.traj_group}",
|
|
83
83
|
]
|
|
84
84
|
|
|
85
85
|
out.append("# Groups and Stages")
|
|
@@ -88,14 +88,13 @@ class NewportXPS:
|
|
|
88
88
|
|
|
89
89
|
for groupname, status in self.get_group_status().items():
|
|
90
90
|
this = self.groups[groupname]
|
|
91
|
-
out.append("
|
|
92
|
-
(groupname, this['category'], status))
|
|
91
|
+
out.append(f"{groupname} ({this['category']}), Status: {status}")
|
|
93
92
|
for pos in this['positioners']:
|
|
94
|
-
stagename =
|
|
93
|
+
stagename = f"{groupname}.{pos}"
|
|
95
94
|
stage = self.stages[stagename]
|
|
96
|
-
out.
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
out.extend([f"# {stagename} ({stage['stagetype']})",
|
|
96
|
+
f" Hardware Status: {hstat[stagename]}",
|
|
97
|
+
f" Positioner Errors: {perrs[stagename]}"])
|
|
99
98
|
return "\n".join(out)
|
|
100
99
|
|
|
101
100
|
|
|
@@ -105,7 +104,7 @@ class NewportXPS:
|
|
|
105
104
|
try:
|
|
106
105
|
self._xps.Login(self._sid, self.username, self.password)
|
|
107
106
|
except:
|
|
108
|
-
raise XPSException('Login failed for
|
|
107
|
+
raise XPSException(f'Login failed for {self.host}')
|
|
109
108
|
|
|
110
109
|
err, val = self._xps.FirmwareVersionGet(self._sid)
|
|
111
110
|
self.firmware_version = val
|
|
@@ -119,19 +118,16 @@ class NewportXPS:
|
|
|
119
118
|
self.ftpconn = FTPWrapper(**self.ftpargs)
|
|
120
119
|
if 'XPS-C' in self.firmware_version:
|
|
121
120
|
self.ftphome = '/Admin'
|
|
122
|
-
|
|
123
|
-
self.read_systemini()
|
|
124
|
-
except:
|
|
125
|
-
print("Could not read system.ini!!!")
|
|
121
|
+
self.read_systemini()
|
|
126
122
|
|
|
127
123
|
|
|
128
124
|
def check_error(self, err, msg='', with_raise=True):
|
|
129
125
|
if err != 0:
|
|
130
|
-
err = "
|
|
126
|
+
err = f"{err}"
|
|
131
127
|
desc = self._xps.errorcodes.get(err, 'unknown error')
|
|
132
|
-
print("XPSError: message=
|
|
128
|
+
print(f"XPSError: message={msg}, error={err}, description={desc}")
|
|
133
129
|
if with_raise:
|
|
134
|
-
raise XPSException("
|
|
130
|
+
raise XPSException(f"{msg} {desc} [Error {err}]")
|
|
135
131
|
|
|
136
132
|
def save_systemini(self, fname='system.ini'):
|
|
137
133
|
"""
|
|
@@ -169,7 +165,7 @@ class NewportXPS:
|
|
|
169
165
|
self.stages= {}
|
|
170
166
|
self.groups = {}
|
|
171
167
|
sconf = ConfigParser()
|
|
172
|
-
sconf.
|
|
168
|
+
sconf.read_string(initext)
|
|
173
169
|
|
|
174
170
|
# read and populate lists of groups first
|
|
175
171
|
for gtype, glist in sconf.items('GROUPS'): # ].items():
|
|
@@ -202,13 +198,13 @@ class NewportXPS:
|
|
|
202
198
|
self.stages[sname]['max_velo'] = ret[1]
|
|
203
199
|
self.stages[sname]['max_accel'] = ret[2]/3.0
|
|
204
200
|
except:
|
|
205
|
-
print("could not set max velo/accel for
|
|
201
|
+
print(f"could not set max velo/accel for {name}")
|
|
206
202
|
ret = self._xps.PositionerUserTravelLimitsGet(self._sid, sname)
|
|
207
203
|
try:
|
|
208
204
|
self.stages[sname]['low_limit'] = ret[1]
|
|
209
205
|
self.stages[sname]['high_limit'] = ret[2]
|
|
210
206
|
except:
|
|
211
|
-
print("could not set limits for
|
|
207
|
+
print(f"could not set limits for {sname}")
|
|
212
208
|
|
|
213
209
|
return self.groups
|
|
214
210
|
|
|
@@ -342,27 +338,38 @@ class NewportXPS:
|
|
|
342
338
|
gkp, gki, gkd, kform, ffgain
|
|
343
339
|
"""
|
|
344
340
|
if stage not in self.stages:
|
|
345
|
-
print("Stage '
|
|
341
|
+
print(f"Stage '{stage}' not found: ")
|
|
346
342
|
return
|
|
347
343
|
params = self._xps.PositionerCorrectorPIDFFVelocityGet(self._sid, stage)
|
|
348
344
|
if params[0] != 0 or len(params) != 13:
|
|
349
|
-
print("error getting tuning parameters for
|
|
345
|
+
print(f"error getting tuning parameters for {stage}")
|
|
350
346
|
return
|
|
351
347
|
|
|
352
348
|
params = params[1:]
|
|
353
349
|
params[0] = closedloopstatus
|
|
354
|
-
if kp is not None:
|
|
355
|
-
|
|
356
|
-
if
|
|
357
|
-
|
|
358
|
-
if
|
|
359
|
-
|
|
360
|
-
if
|
|
361
|
-
|
|
362
|
-
if
|
|
363
|
-
|
|
364
|
-
if
|
|
365
|
-
|
|
350
|
+
if kp is not None:
|
|
351
|
+
params[1] = kp
|
|
352
|
+
if ki is not None:
|
|
353
|
+
params[2] = ki
|
|
354
|
+
if kd is not None:
|
|
355
|
+
params[3] = kd
|
|
356
|
+
if ks is not None:
|
|
357
|
+
params[4] = ks
|
|
358
|
+
if inttime is not None:
|
|
359
|
+
params[5] = inttime
|
|
360
|
+
if dfilter is not None:
|
|
361
|
+
params[6] = dfilter
|
|
362
|
+
if gkp is not None:
|
|
363
|
+
params[7] = gkp
|
|
364
|
+
if gki is not None:
|
|
365
|
+
params[8] = gki
|
|
366
|
+
if gkd is not None:
|
|
367
|
+
params[9] = gkd
|
|
368
|
+
if kform is not None:
|
|
369
|
+
params[10] = kform
|
|
370
|
+
if ffgain is not None:
|
|
371
|
+
params[11] = ffgain
|
|
372
|
+
self._xps.PositionerCorrectorPIDFFVelocitySet(self._sid, stage, *params)
|
|
366
373
|
|
|
367
374
|
@withConnectedXPS
|
|
368
375
|
def get_tuning(self, stage):
|
|
@@ -371,11 +378,11 @@ class NewportXPS:
|
|
|
371
378
|
gkp, gki, gkd, kform, ffgain
|
|
372
379
|
"""
|
|
373
380
|
if stage not in self.stages:
|
|
374
|
-
print("Stage '
|
|
381
|
+
print(f"Stage '{stage}' not found: ")
|
|
375
382
|
return
|
|
376
383
|
params = self._xps.PositionerCorrectorPIDFFVelocityGet(self._sid, stage)
|
|
377
384
|
if params[0] != 0 or len(params) != 13:
|
|
378
|
-
print("error getting tuning parameters for
|
|
385
|
+
print(f"error getting tuning parameters for {stage}")
|
|
379
386
|
return
|
|
380
387
|
|
|
381
388
|
params = params[1:]
|
|
@@ -400,8 +407,8 @@ class NewportXPS:
|
|
|
400
407
|
if group['category'].lower().startswith('multiple'):
|
|
401
408
|
pvtgroups.append(gname)
|
|
402
409
|
pvtgroups = ', '.join(pvtgroups)
|
|
403
|
-
msg = "'
|
|
404
|
-
raise XPSException(msg
|
|
410
|
+
msg = f"'{group}' cannot be a trajectory group, must be one of {pvtgroups}"
|
|
411
|
+
raise XPSException(msg)
|
|
405
412
|
|
|
406
413
|
self.traj_group = group
|
|
407
414
|
self.traj_positioners = self.groups[group]['positioners']
|
|
@@ -416,7 +423,7 @@ class NewportXPS:
|
|
|
416
423
|
try:
|
|
417
424
|
self.enable_group(self.traj_group)
|
|
418
425
|
except XPSException:
|
|
419
|
-
print("Warning: could not enable trajectory group '
|
|
426
|
+
print(f"Warning: could not enable trajectory group '{self.traj_group}'")
|
|
420
427
|
return
|
|
421
428
|
|
|
422
429
|
for i in range(64):
|
|
@@ -448,14 +455,14 @@ class NewportXPS:
|
|
|
448
455
|
if group is None:
|
|
449
456
|
for group in self.groups:
|
|
450
457
|
err, ret = method(self._sid, group)
|
|
451
|
-
self.check_error(err, msg="
|
|
458
|
+
self.check_error(err, msg=f"{action} group '{group}'",
|
|
452
459
|
with_raise=with_raise)
|
|
453
460
|
elif group in self.groups:
|
|
454
461
|
err, ret = method(self._sid, group)
|
|
455
|
-
self.check_error(err, msg="%
|
|
462
|
+
self.check_error(err, msg=f"%{action} group '{group}'",
|
|
456
463
|
with_raise=with_raise)
|
|
457
464
|
else:
|
|
458
|
-
raise ValueError("Group '
|
|
465
|
+
raise ValueError("Group '{group}' not found")
|
|
459
466
|
|
|
460
467
|
def kill_group(self, group=None):
|
|
461
468
|
"""
|
|
@@ -478,8 +485,8 @@ class NewportXPS:
|
|
|
478
485
|
self.initialize_group(group=g)
|
|
479
486
|
except XPSException:
|
|
480
487
|
print(f"Warning: could not initialize '{g}' (already initialized?)")
|
|
481
|
-
|
|
482
|
-
|
|
488
|
+
|
|
489
|
+
|
|
483
490
|
def home_allgroups(self, with_encoder=True, home=False):
|
|
484
491
|
"""
|
|
485
492
|
home all groups
|
|
@@ -549,10 +556,10 @@ class NewportXPS:
|
|
|
549
556
|
out = {}
|
|
550
557
|
for group in self.groups:
|
|
551
558
|
err, stat = self._xps.GroupStatusGet(self._sid, group)
|
|
552
|
-
self.check_error(err, msg="GroupStatus '
|
|
559
|
+
self.check_error(err, msg=f"GroupStatus '{group}'")
|
|
553
560
|
|
|
554
561
|
err, val = self._xps.GroupStatusStringGet(self._sid, stat)
|
|
555
|
-
self.check_error(err, msg="GroupStatusString '
|
|
562
|
+
self.check_error(err, msg=f"GroupStatusString '{stat}'")
|
|
556
563
|
|
|
557
564
|
out[group] = val
|
|
558
565
|
return out
|
|
@@ -564,12 +571,13 @@ class NewportXPS:
|
|
|
564
571
|
"""
|
|
565
572
|
out = {}
|
|
566
573
|
for stage in self.stages:
|
|
567
|
-
if stage in ('', None):
|
|
574
|
+
if stage in ('', None):
|
|
575
|
+
continue
|
|
568
576
|
err, stat = self._xps.PositionerHardwareStatusGet(self._sid, stage)
|
|
569
|
-
self.check_error(err, msg="Pos HardwareStatus '
|
|
577
|
+
self.check_error(err, msg=f"Pos HardwareStatus '{stage}'")
|
|
570
578
|
|
|
571
579
|
err, val = self._xps.PositionerHardwareStatusStringGet(self._sid, stat)
|
|
572
|
-
self.check_error(err, msg="Pos HardwareStatusString '
|
|
580
|
+
self.check_error(err, msg=f"Pos HardwareStatusString '{stat}'")
|
|
573
581
|
out[stage] = val
|
|
574
582
|
return out
|
|
575
583
|
|
|
@@ -580,12 +588,13 @@ class NewportXPS:
|
|
|
580
588
|
"""
|
|
581
589
|
out = {}
|
|
582
590
|
for stage in self.stages:
|
|
583
|
-
if stage in ('', None):
|
|
591
|
+
if stage in ('', None):
|
|
592
|
+
continue
|
|
584
593
|
err, stat = self._xps.PositionerErrorGet(self._sid, stage)
|
|
585
|
-
self.check_error(err, msg="Pos Error '
|
|
594
|
+
self.check_error(err, msg=f"Pos Error '{stage}'")
|
|
586
595
|
|
|
587
596
|
err, val = self._xps.PositionerErrorStringGet(self._sid, stat)
|
|
588
|
-
self.check_error(err, msg="Pos ErrorString '
|
|
597
|
+
self.check_error(err, msg=f"Pos ErrorString '{stat}'")
|
|
589
598
|
|
|
590
599
|
if len(val) < 1:
|
|
591
600
|
val = 'OK'
|
|
@@ -599,8 +608,8 @@ class NewportXPS:
|
|
|
599
608
|
set velocity for stage
|
|
600
609
|
"""
|
|
601
610
|
if stage not in self.stages:
|
|
602
|
-
|
|
603
|
-
|
|
611
|
+
raise XPSException(f"Stage '{stage}' not found")
|
|
612
|
+
|
|
604
613
|
ret, v_cur, a_cur, jt0_cur, jt1_cur = \
|
|
605
614
|
self._xps.PositionerSGammaParametersGet(self._sid, stage)
|
|
606
615
|
if accl is None:
|
|
@@ -671,15 +680,14 @@ class NewportXPS:
|
|
|
671
680
|
relative (bool): whether move is relative [False]
|
|
672
681
|
"""
|
|
673
682
|
if stage not in self.stages:
|
|
674
|
-
|
|
675
|
-
return
|
|
683
|
+
raise XPSException(f"Stage '{stage}' not found")
|
|
676
684
|
|
|
677
685
|
move = self._xps.GroupMoveAbsolute
|
|
678
686
|
if relative:
|
|
679
687
|
move = self._xps.GroupMoveRelative
|
|
680
688
|
|
|
681
689
|
err, ret = move(self._sid, stage, [value])
|
|
682
|
-
self.check_error(err, msg="Moving stage '
|
|
690
|
+
self.check_error(err, msg=f"Moving stage '{stage}'")
|
|
683
691
|
return ret
|
|
684
692
|
|
|
685
693
|
@withConnectedXPS
|
|
@@ -691,11 +699,10 @@ class NewportXPS:
|
|
|
691
699
|
stage (string): name of stage -- must be in self.stages
|
|
692
700
|
"""
|
|
693
701
|
if stage not in self.stages:
|
|
694
|
-
|
|
695
|
-
return
|
|
702
|
+
raise XPSException(f"Stage '{stage}' not found")
|
|
696
703
|
|
|
697
704
|
err, val = self._xps.GroupPositionCurrentGet(self._sid, stage, 1)
|
|
698
|
-
self.check_error(err, msg="Get Stage Position '
|
|
705
|
+
self.check_error(err, msg=f"Get Stage Position '{stage}'")
|
|
699
706
|
return val
|
|
700
707
|
|
|
701
708
|
read_stage_position = get_stage_position
|
|
@@ -735,21 +742,20 @@ class NewportXPS:
|
|
|
735
742
|
|
|
736
743
|
|
|
737
744
|
@withConnectedXPS
|
|
738
|
-
def define_line_trajectories(self, axis, group=None,
|
|
739
|
-
start=0, stop=1, step=0.001,
|
|
745
|
+
def define_line_trajectories(self, axis, group=None, pixeltime=0.01,
|
|
746
|
+
scantime=None, start=0, stop=1, step=0.001,
|
|
740
747
|
accel=None, upload=True, verbose=False):
|
|
741
748
|
"""defines 'forward' and 'backward' trajectories for a simple
|
|
742
|
-
single element line scan
|
|
749
|
+
single element line scan using PVT Mode
|
|
743
750
|
"""
|
|
744
751
|
if group is not None:
|
|
745
752
|
self.set_trajectory_group(group)
|
|
746
753
|
|
|
747
754
|
if self.traj_group is None:
|
|
748
|
-
|
|
749
|
-
return
|
|
755
|
+
raise XPSException("No trajectory group defined")
|
|
750
756
|
|
|
751
757
|
for axname in (axis, axis.upper(), axis.lower(), axis.title()):
|
|
752
|
-
stage = "
|
|
758
|
+
stage = f"{self.traj_group}.{axname}"
|
|
753
759
|
if stage in self.stages:
|
|
754
760
|
break
|
|
755
761
|
|
|
@@ -767,8 +773,9 @@ class NewportXPS:
|
|
|
767
773
|
step = scandir*abs(step)
|
|
768
774
|
|
|
769
775
|
npulses = int((abs(stop - start) + abs(step)*1.1) / abs(step))
|
|
770
|
-
scantime
|
|
771
|
-
|
|
776
|
+
if pixeltime is None and scantime is not None:
|
|
777
|
+
scantime = float(abs(scantime))
|
|
778
|
+
pixeltime= scantime / (npulses-1)
|
|
772
779
|
scantime = pixeltime*npulses
|
|
773
780
|
|
|
774
781
|
distance = (abs(stop - start) + abs(step))*1.0
|
|
@@ -778,8 +785,10 @@ class NewportXPS:
|
|
|
778
785
|
rampdist = velocity*ramptime
|
|
779
786
|
offset = step/2.0 + scandir*rampdist
|
|
780
787
|
|
|
781
|
-
trajbase = {'axes': [axis],
|
|
782
|
-
'
|
|
788
|
+
trajbase = {'axes': [axis],
|
|
789
|
+
'type': 'line',
|
|
790
|
+
'pixeltime': pixeltime, 'uploaded': False,
|
|
791
|
+
'npulses': npulses+1, 'nsegments': 3}
|
|
783
792
|
|
|
784
793
|
self.trajectories['foreward'] = {'start': [start-offset],
|
|
785
794
|
'stop': [stop +offset]}
|
|
@@ -797,21 +806,19 @@ class NewportXPS:
|
|
|
797
806
|
val = 0.0
|
|
798
807
|
if ax == axis:
|
|
799
808
|
val = base[attr]
|
|
800
|
-
fore["
|
|
809
|
+
fore[f"{ax}_{attr}"] = val
|
|
801
810
|
|
|
802
811
|
back = fore.copy()
|
|
803
|
-
back["
|
|
804
|
-
back["
|
|
812
|
+
back[f"{axis}_start"] = fore[f"{axis}_stop"]
|
|
813
|
+
back[f"{axis}_stop"] = fore[f"{axis}_start"]
|
|
805
814
|
for attr in ('velo', 'ramp', 'dist'):
|
|
806
|
-
back["
|
|
815
|
+
back[f"{axis}_{attr}"] *= -1.0
|
|
807
816
|
|
|
808
817
|
if verbose:
|
|
809
|
-
print("TRAJ Text Fore, Back:")
|
|
810
818
|
print(self.linear_template % fore)
|
|
811
819
|
print(self.linear_template % back)
|
|
812
820
|
|
|
813
821
|
ret = True
|
|
814
|
-
|
|
815
822
|
if upload:
|
|
816
823
|
ret = False
|
|
817
824
|
try:
|
|
@@ -819,36 +826,219 @@ class NewportXPS:
|
|
|
819
826
|
self.linear_template % fore)
|
|
820
827
|
self.upload_trajectory('backward.trj',
|
|
821
828
|
self.linear_template % back)
|
|
829
|
+
self.trajectories['foreward']['uploaded'] = True
|
|
830
|
+
self.trajectories['backward']['uploaded'] = True
|
|
822
831
|
ret = True
|
|
823
832
|
except:
|
|
824
833
|
raise ValueError("error uploading trajectory")
|
|
825
834
|
return ret
|
|
826
835
|
|
|
827
836
|
@withConnectedXPS
|
|
828
|
-
def
|
|
837
|
+
def define_array_trajectory(self, positions, dtime=1.0, max_accels=None,
|
|
838
|
+
upload=True, name='array', verbose=True):
|
|
839
|
+
"""define a PVT trajectory for the trajectory group from a dictionary of
|
|
840
|
+
position arrays for each positioner in the trajectory group.
|
|
841
|
+
|
|
842
|
+
Positioners that are not included in the positions dict will not be moved.
|
|
843
|
+
|
|
844
|
+
Arguments
|
|
845
|
+
---------
|
|
846
|
+
positions: dict of {PosName: np.ndarray} for each positioner to move
|
|
847
|
+
dtime: float, time per segment
|
|
848
|
+
max_accels: dict of {PosName: max_acceleration} to use.
|
|
849
|
+
name: name of trajectory (file will be f"{name}.trj")
|
|
850
|
+
upload: bool, whether to upload trajectory
|
|
851
|
+
|
|
852
|
+
Returns:
|
|
853
|
+
-------
|
|
854
|
+
dict with information about trajcetory. This will include values for
|
|
855
|
+
pvt_buff: full text of trajectory buffer
|
|
856
|
+
type: 'array'
|
|
857
|
+
start: dict of starting values (backed up from first point so that
|
|
858
|
+
positioner can be accelerated to the desired velocity for the
|
|
859
|
+
second trajectory segment)
|
|
860
|
+
npulses: number of expected pulses.
|
|
861
|
+
|
|
862
|
+
Notes:
|
|
863
|
+
------
|
|
864
|
+
1. The np.ndarray for each positioner must be the same length, and will be
|
|
865
|
+
used as midpoints between trigger events.
|
|
866
|
+
2. For ndarrays of lenght N, the trajectory will have N+1 segments: one
|
|
867
|
+
to ramp up to velocity to approach the first point, and the last to
|
|
868
|
+
decelerate to zero velocity.
|
|
869
|
+
|
|
829
870
|
"""
|
|
830
|
-
|
|
871
|
+
tgroup = self.traj_group
|
|
872
|
+
if tgroup is None:
|
|
873
|
+
raise XPSException("No trajectory group defined")
|
|
874
|
+
|
|
875
|
+
all_axes = [a for a in self.groups[tgroup]['positioners']]
|
|
876
|
+
|
|
877
|
+
pdat = {}
|
|
878
|
+
input_ok = True
|
|
879
|
+
npts = None
|
|
880
|
+
for key, value in positions.items():
|
|
881
|
+
pname = key[:]
|
|
882
|
+
|
|
883
|
+
if key.startswith(tgroup):
|
|
884
|
+
pname = key[len(tgroup)+1:]
|
|
885
|
+
if pname not in all_axes:
|
|
886
|
+
print(f"Unknown positioner given: {pname}")
|
|
887
|
+
input_ok = False
|
|
888
|
+
if npts is None:
|
|
889
|
+
npts = len(value)
|
|
890
|
+
elif npts != len(value):
|
|
891
|
+
print(f"incorrect array length for {pname}")
|
|
892
|
+
input_ok = False
|
|
893
|
+
|
|
894
|
+
if isinstance(value, np.ndarray):
|
|
895
|
+
positions[key] = value.astype(np.float64).tolist()
|
|
896
|
+
else:
|
|
897
|
+
positions[key] = [float(x) for x in value]
|
|
898
|
+
|
|
899
|
+
if not input_ok:
|
|
900
|
+
return
|
|
901
|
+
|
|
902
|
+
npulses = npts+1
|
|
903
|
+
dtime = float(abs(dtime))
|
|
904
|
+
times = np.ones(npulses+1)*dtime
|
|
905
|
+
|
|
906
|
+
if max_accels is None:
|
|
907
|
+
max_accels = {}
|
|
908
|
+
pos, dpos = {}, {}
|
|
909
|
+
velo = {}
|
|
910
|
+
accel = {}
|
|
911
|
+
start = {}
|
|
912
|
+
for axes in all_axes:
|
|
913
|
+
stage = f'{tgroup}.{axes}'
|
|
914
|
+
maxv = self.stages[stage]['max_velo']
|
|
915
|
+
maxa = self.stages[stage]['max_accel']
|
|
916
|
+
if axes in max_accels:
|
|
917
|
+
maxa = min(max_accels[axes], maxa)
|
|
918
|
+
if axes in positions:
|
|
919
|
+
upos = positions[axes]
|
|
920
|
+
# mid are the trajectory trigger points, the
|
|
921
|
+
# mid points between the desired positions
|
|
922
|
+
mid = [3*upos[0]-2*upos[1], 2*upos[0] - upos[1]]
|
|
923
|
+
mid.extend(upos)
|
|
924
|
+
mid.extend([2*upos[-1]-upos[-2],
|
|
925
|
+
3*upos[-1]-2*upos[-2],
|
|
926
|
+
])
|
|
927
|
+
mid = np.array(mid)
|
|
928
|
+
pos[axes] = 0.5*(mid[1:] + mid[:-1])
|
|
929
|
+
|
|
930
|
+
# adjust first segment velocity to half max accel
|
|
931
|
+
p0, p1, p2 = pos[axes][0], pos[axes][1], pos[axes][2]
|
|
932
|
+
v0 = (p1-p0)/dtime
|
|
933
|
+
v1 = (p2-p1)/dtime
|
|
934
|
+
a0 = (v1-v0)/dtime
|
|
935
|
+
start[axes] = p1 - (p1-p0)*dtime*max(v0, 0.5*maxv)/max(a0, 0.5*maxa)
|
|
936
|
+
|
|
937
|
+
pos[axes] = np.diff(pos[axes] - start[axes])
|
|
938
|
+
velo[axes] = np.gradient(pos[axes])/times
|
|
939
|
+
velo[axes][-1] = 0.0
|
|
940
|
+
accel[axes] = np.gradient(velo[axes])/times
|
|
941
|
+
|
|
942
|
+
if (max(abs(velo[axes])) > maxv):
|
|
943
|
+
errmsg = f"max velocity {maxv} violated for {axes}"
|
|
944
|
+
raise ValueError(errmsg)
|
|
945
|
+
if (max(abs(accel[axes])) > maxa):
|
|
946
|
+
errmsg = f"max acceleration {maxa} violated for {axes}"
|
|
947
|
+
raise ValueError(errmsg)
|
|
948
|
+
else:
|
|
949
|
+
start[axes] = None
|
|
950
|
+
pos[axes] = np.zeros(npulses+1, dtype=np.float64)
|
|
951
|
+
velo[axes] = np.zeros(npulses+1, dtype=np.float64)
|
|
952
|
+
accel[axes] = np.zeros(npulses+1, dtype=np.float64)
|
|
953
|
+
|
|
954
|
+
|
|
955
|
+
traj = {'axes': all_axes,
|
|
956
|
+
'type': 'array',
|
|
957
|
+
'start': start, 'pixeltime': dtime,
|
|
958
|
+
'npulses': npulses+1, 'nsegments': npulses+1,
|
|
959
|
+
'uploaded': False}
|
|
960
|
+
|
|
961
|
+
buff = ['']
|
|
962
|
+
|
|
963
|
+
for n in range(npulses+1):
|
|
964
|
+
line = [f"{dtime:.8f}"]
|
|
965
|
+
for axes in all_axes:
|
|
966
|
+
p, v = pos[axes][n], velo[axes][n]
|
|
967
|
+
line.extend([f"{p:.8f}", f"{v:.8f}"])
|
|
968
|
+
buff.append(', '.join(line))
|
|
969
|
+
|
|
970
|
+
buff = '\n'.join(buff)
|
|
971
|
+
traj['pvt_buffer'] = buff
|
|
972
|
+
|
|
973
|
+
if upload:
|
|
974
|
+
tfile = f"{name}.trj"
|
|
975
|
+
traj['name'] = name
|
|
976
|
+
try:
|
|
977
|
+
self.upload_trajectory(tfile, buff)
|
|
978
|
+
traj['uploaded'] = True
|
|
979
|
+
except:
|
|
980
|
+
traj['uploaded'] = False
|
|
981
|
+
self.trajectories[name] = traj
|
|
982
|
+
return traj
|
|
983
|
+
|
|
984
|
+
|
|
985
|
+
@withConnectedXPS
|
|
986
|
+
def move_to_trajectory_start(self, name):
|
|
987
|
+
"""
|
|
988
|
+
move to the start position of a named trajectory
|
|
989
|
+
"""
|
|
990
|
+
tgroup = self.traj_group
|
|
991
|
+
if tgroup is None:
|
|
992
|
+
raise XPSException("No trajectory group defined")
|
|
993
|
+
|
|
994
|
+
traj = self.trajectories.get(name, None)
|
|
995
|
+
if traj is None:
|
|
996
|
+
raise XPSException(f"Cannot find trajectory named '{name}'")
|
|
997
|
+
|
|
998
|
+
if traj['type'] == 'line':
|
|
999
|
+
for pos, axes in zip(traj['start'], traj['axes']):
|
|
1000
|
+
self.move_stage(f'{tgroup}.{axes}', pos)
|
|
1001
|
+
|
|
1002
|
+
elif traj['type'] == 'array':
|
|
1003
|
+
for axes, pos in traj['start'].items():
|
|
1004
|
+
if pos is not None:
|
|
1005
|
+
self.move_stage(f'{tgroup}.{axes}', pos)
|
|
1006
|
+
|
|
1007
|
+
|
|
1008
|
+
|
|
1009
|
+
@withConnectedXPS
|
|
1010
|
+
def arm_trajectory(self, name, verbose=False, move_to_start=True):
|
|
1011
|
+
"""
|
|
1012
|
+
prepare to run a named (assumed uploaded) trajectory
|
|
831
1013
|
"""
|
|
832
1014
|
if self.traj_group is None:
|
|
833
1015
|
print("Must set group name!")
|
|
834
1016
|
|
|
835
1017
|
traj = self.trajectories.get(name, None)
|
|
836
1018
|
if traj is None:
|
|
837
|
-
raise XPSException("Cannot find trajectory
|
|
1019
|
+
raise XPSException(f"Cannot find trajectory '{name}'")
|
|
1020
|
+
|
|
1021
|
+
if not traj['uploaded']:
|
|
1022
|
+
raise XPSException(f"trajectory '{name}' has not been uploaded")
|
|
1023
|
+
|
|
838
1024
|
|
|
839
1025
|
self.traj_state = ARMING
|
|
840
|
-
self.traj_file = '
|
|
1026
|
+
self.traj_file = f'{name}.trj'
|
|
1027
|
+
|
|
1028
|
+
if move_to_start:
|
|
1029
|
+
self.move_to_trajectory_start(name)
|
|
841
1030
|
|
|
842
1031
|
# move_kws = {}
|
|
843
1032
|
outputs = []
|
|
844
1033
|
for out in self.gather_outputs:
|
|
845
1034
|
for i, ax in enumerate(traj['axes']):
|
|
846
|
-
outputs.append('
|
|
1035
|
+
outputs.append(f'{self.traj_group}.{ax}.{out}')
|
|
847
1036
|
|
|
848
|
-
end_segment = traj['nsegments']
|
|
1037
|
+
end_segment = traj['nsegments']
|
|
849
1038
|
self.nsegments = end_segment
|
|
850
1039
|
|
|
851
|
-
|
|
1040
|
+
o = " ".join(outputs)
|
|
1041
|
+
self.gather_titles = f"{self.gather_header}\n#{o}\n"
|
|
852
1042
|
err, ret = self._xps.GatheringReset(self._sid)
|
|
853
1043
|
self.check_error(err, msg="GatheringReset")
|
|
854
1044
|
if verbose:
|
|
@@ -898,7 +1088,8 @@ class NewportXPS:
|
|
|
898
1088
|
if self.traj_state != ARMED:
|
|
899
1089
|
raise XPSException("Must arm trajectory before running!")
|
|
900
1090
|
|
|
901
|
-
|
|
1091
|
+
tgroup = self.traj_group
|
|
1092
|
+
buffer = ('Always', f'{tgroup}.PVT.TrajectoryPulse',)
|
|
902
1093
|
err, ret = self._xps.EventExtendedConfigurationTriggerSet(self._sid, buffer,
|
|
903
1094
|
('0','0'), ('0','0'),
|
|
904
1095
|
('0','0'), ('0','0'))
|
|
@@ -1032,7 +1223,7 @@ class NewportXPS:
|
|
|
1032
1223
|
f.close()
|
|
1033
1224
|
nlines = len(buff.split('\n')) - 1
|
|
1034
1225
|
if verbose:
|
|
1035
|
-
print('Wrote
|
|
1226
|
+
print(f'Wrote {nlines} lines, {len(buff)} bytes to {fname}')
|
|
1036
1227
|
if set_idle_when_done:
|
|
1037
1228
|
self.traj_state = IDLE
|
|
1038
1229
|
|
|
@@ -1063,7 +1254,7 @@ class NewportXPS:
|
|
|
1063
1254
|
if accel_values is None:
|
|
1064
1255
|
accel_values = []
|
|
1065
1256
|
for posname in self.traj_positioners:
|
|
1066
|
-
accel = self.stages["
|
|
1257
|
+
accel = self.stages[f"{self.traj_group}.{posname}"]['max_accel']
|
|
1067
1258
|
accel_values.append(accel)
|
|
1068
1259
|
accel_values = np.array(accel_values)
|
|
1069
1260
|
|
|
@@ -1116,11 +1307,8 @@ class NewportXPS:
|
|
|
1116
1307
|
for ind, positioner in enumerate(self.traj_positioners):
|
|
1117
1308
|
self.trajectories[name][positioner + 'ramp'] = ramp[ind]
|
|
1118
1309
|
|
|
1119
|
-
ret = False
|
|
1120
1310
|
try:
|
|
1121
1311
|
self.upload_trajectory(name + '.trj', trajectory_str)
|
|
1122
|
-
ret = True
|
|
1123
|
-
# print('Trajectory File uploaded.')
|
|
1124
1312
|
except:
|
|
1125
1313
|
print('Failed to upload trajectory file')
|
|
1126
1314
|
|
|
@@ -1131,10 +1319,9 @@ class NewportXPS:
|
|
|
1131
1319
|
"""run trajectory in PVT mode"""
|
|
1132
1320
|
traj = self.trajectories.get(name, None)
|
|
1133
1321
|
if traj is None:
|
|
1134
|
-
|
|
1135
|
-
return
|
|
1322
|
+
raise XPSException(f'Cannot find trajectory named {name}')
|
|
1136
1323
|
|
|
1137
|
-
traj_file = '
|
|
1324
|
+
traj_file = f'{name}.trj'
|
|
1138
1325
|
dtime = traj['pulse_time']
|
|
1139
1326
|
ramps = []
|
|
1140
1327
|
for positioner in self.traj_positioners:
|
|
@@ -1148,47 +1335,39 @@ class NewportXPS:
|
|
|
1148
1335
|
|
|
1149
1336
|
self._xps.GroupMoveRelative(self._sid, self.traj_group, ramps)
|
|
1150
1337
|
|
|
1151
|
-
# self.gather_outputs = []
|
|
1152
|
-
## gather_titles = []
|
|
1153
|
-
|
|
1154
|
-
# for positioner in self.traj_positioners:
|
|
1155
|
-
# for out in self.gather_outputs:
|
|
1156
|
-
# self.gather_outputs.append('%s.%s.%s' % (self.traj_group, positioner, out))
|
|
1157
|
-
# gather_titles.append('%s.%s' % (positioner, out))
|
|
1158
|
-
## self.gather_titles = "%s\n#%s\n" % (xps_config['GATHER TITLES'],
|
|
1159
|
-
## " ".join(gather_titles))
|
|
1160
|
-
|
|
1161
1338
|
outputs = []
|
|
1162
1339
|
for out in self.gather_outputs:
|
|
1163
1340
|
for i, ax in enumerate(traj['axes']):
|
|
1164
|
-
outputs.append('
|
|
1341
|
+
outputs.append(f'{self.traj_group}.{ax}.{out}')
|
|
1165
1342
|
# move_kws[ax] = float(traj['start'][i])
|
|
1166
1343
|
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
self.gather_titles = "%s\n#%s\n" % (self.gather_header, " ".join(outputs))
|
|
1170
|
-
|
|
1344
|
+
o = " ".join(outputs)
|
|
1345
|
+
self.gather_titles = f"{self.gather_header}\n#{o}\n"
|
|
1171
1346
|
self._xps.GatheringReset(self._sid)
|
|
1172
1347
|
self._xps.GatheringConfigurationSet(self._sid, self.gather_outputs)
|
|
1173
1348
|
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1349
|
+
err, ret = self._xps.MultipleAxesPVTPulseOutputSet(self._sid, self.traj_group,
|
|
1350
|
+
2, step_number + 1, dtime)
|
|
1351
|
+
self.check_error(err, msg="MultipleAxesPVTPulseOutputSet", with_raise=False)
|
|
1352
|
+
|
|
1353
|
+
err, ret = self._xps.MultipleAxesPVTVerification(self._sid, self.traj_group, traj_file)
|
|
1354
|
+
self.check_error(err, msg="MultipleAxesPVTVerification", with_raise=False)
|
|
1178
1355
|
|
|
1179
1356
|
buffer = ('Always', self.traj_group + '.PVT.TrajectoryPulse')
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1357
|
+
err, ret = self._xps.EventExtendedConfigurationTriggerSet(self._sid, buffer,
|
|
1358
|
+
('0', '0'), ('0', '0'),
|
|
1359
|
+
('0', '0'), ('0', '0'))
|
|
1360
|
+
self.check_error(err, msg="EventExtendedConfigurationTriggerSet", with_raise=False)
|
|
1183
1361
|
|
|
1184
|
-
|
|
1185
|
-
|
|
1362
|
+
err, ret = self._xps.EventExtendedConfigurationActionSet(self._sid, ('GatheringOneData',),
|
|
1363
|
+
('',), ('',), ('',), ('',))
|
|
1364
|
+
self.check_error(err, msg="EventExtendedConfigurationActionSet", with_raise=False)
|
|
1186
1365
|
|
|
1187
1366
|
eventID, m = self._xps.EventExtendedStart(self._sid)
|
|
1188
1367
|
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1368
|
+
self._xps.MultipleAxesPVTExecution(self._sid, self.traj_group, traj_file, 1)
|
|
1369
|
+
self._xps.EventExtendedRemove(self._sid, eventID)
|
|
1370
|
+
self._xps.GatheringStop(self._sid)
|
|
1192
1371
|
|
|
1193
1372
|
npulses = 0
|
|
1194
1373
|
if save:
|