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/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 io import StringIO
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
- out = ["# XPS host: %s (%s)" % (self.host, socket.getfqdn(self.host)),
79
- "# Firmware: %s" % self.firmware_version,
80
- "# Current Time: %s" % time.ctime(),
81
- "# Last Reboot: %s" % time.ctime(boottime),
82
- "# Trajectory Group: %s" % self.traj_group,
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("%s (%s), Status: %s" %
92
- (groupname, this['category'], status))
91
+ out.append(f"{groupname} ({this['category']}), Status: {status}")
93
92
  for pos in this['positioners']:
94
- stagename = '%s.%s' % (groupname, pos)
93
+ stagename = f"{groupname}.{pos}"
95
94
  stage = self.stages[stagename]
96
- out.append(" %s (%s)" % (stagename, stage['stagetype']))
97
- out.append(" Hardware Status: %s" % (hstat[stagename]))
98
- out.append(" Positioner Errors: %s" % (perrs[stagename]))
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 %s' % self.host)
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
- try:
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 = "%d" % err
126
+ err = f"{err}"
131
127
  desc = self._xps.errorcodes.get(err, 'unknown error')
132
- print("XPSError: message= %s, error=%s, description=%s" % (msg, err, desc))
128
+ print(f"XPSError: message={msg}, error={err}, description={desc}")
133
129
  if with_raise:
134
- raise XPSException("%s %s [Error %s]" % (msg, desc, err))
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.readfp(StringIO(initext))
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 %s" % sname)
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 %s" % sname)
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 '%s' not found: " % 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 %s" % stage)
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: params[1] = kp
355
- if ki is not None: params[2] = ki
356
- if kd is not None: params[3] = kd
357
- if ks is not None: params[4] = ks
358
- if inttime is not None: params[5] = inttime
359
- if dfilter is not None: params[6] = dfilter
360
- if gkp is not None: params[7] = gkp
361
- if gki is not None: params[8] = gki
362
- if gkd is not None: params[9] = gkd
363
- if kform is not None: params[10] = kform
364
- if ffgain is not None: params[11] = ffgain
365
- ret = self._xps.PositionerCorrectorPIDFFVelocitySet(self._sid, stage, *params)
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 '%s' not found: " % 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 %s" % stage)
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 = "'%s' cannot be a trajectory group, must be one of %s"
404
- raise XPSException(msg % (group, pvtgroups))
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 '%s'"% self.traj_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="%s group '%s'" % (action, group),
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="%s group '%s'" % (action, group),
462
+ self.check_error(err, msg=f"%{action} group '{group}'",
456
463
  with_raise=with_raise)
457
464
  else:
458
- raise ValueError("Group '%s' not found" % 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 '%s'" % (group))
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 '%s'" % (stat))
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): continue
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 '%s'" % (stage))
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 '%s'" % (stat))
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): continue
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 '%s'" % (stage))
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 '%s'" % (stat))
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
- print("Stage '%s' not found" % stage)
603
- return
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
- print("Stage '%s' not found" % stage)
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 '%s'" % (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
- print("Stage '%s' not found: " % stage)
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 '%s'" % (stage))
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, scantime=10.0,
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 in PVT Mode
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
- print("Must define a trajectory group first!")
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 = "%s.%s" % (self.traj_group, axname)
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 = float(abs(scantime))
771
- pixeltime= scantime / (npulses-1)
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], 'pixeltime': pixeltime,
782
- 'npulses': npulses, 'nsegments': 3}
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["%s_%s" % (ax, attr)] = val
809
+ fore[f"{ax}_{attr}"] = val
801
810
 
802
811
  back = fore.copy()
803
- back["%s_start" % axis] = fore["%s_stop" % axis]
804
- back["%s_stop" % axis] = fore["%s_start" % axis]
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["%s_%s" % (axis, attr)] *= -1.0
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 arm_trajectory(self, name, verbose=False):
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
- set up the trajectory from previously defined, uploaded trajectory
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 named '%s'" % name)
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 = '%s.trj' % name
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('%s.%s.%s' % (self.traj_group, ax, out))
1035
+ outputs.append(f'{self.traj_group}.{ax}.{out}')
847
1036
 
848
- end_segment = traj['nsegments'] # - 1 + self.extra_triggers
1037
+ end_segment = traj['nsegments']
849
1038
  self.nsegments = end_segment
850
1039
 
851
- self.gather_titles = "%s\n#%s\n" % (self.gather_header, " ".join(outputs))
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
- buffer = ('Always', '%s.PVT.TrajectoryPulse' % self.traj_group,)
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 %i lines, %i bytes to %s' % (nlines, len(buff), fname))
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["%s.%s"%(self.traj_group, posname)]['max_accel']
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
- print('Cannot find trajectory named %s' % name)
1135
- return
1322
+ raise XPSException(f'Cannot find trajectory named {name}')
1136
1323
 
1137
- traj_file = '%s.trj' % name
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('%s.%s.%s' % (self.traj_group, ax, out))
1341
+ outputs.append(f'{self.traj_group}.{ax}.{out}')
1165
1342
  # move_kws[ax] = float(traj['start'][i])
1166
1343
 
1167
- end_segment = traj['nsegments'] - 1 + self.extra_triggers
1168
- # self.move_group(self.traj_group, **move_kws)
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
- # print("step_number", step_number)
1175
- ret = self._xps.MultipleAxesPVTPulseOutputSet(self._sid, self.traj_group,
1176
- 2, step_number + 1, dtime)
1177
- ret = self._xps.MultipleAxesPVTVerification(self._sid, self.traj_group, traj_file)
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
- o = self._xps.EventExtendedConfigurationTriggerSet(self._sid, buffer,
1181
- ('0', '0'), ('0', '0'),
1182
- ('0', '0'), ('0', '0'))
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
- o = self._xps.EventExtendedConfigurationActionSet(self._sid, ('GatheringOneData',),
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
- ret = self._xps.MultipleAxesPVTExecution(self._sid, self.traj_group, traj_file, 1)
1190
- o = self._xps.EventExtendedRemove(self._sid, eventID)
1191
- o = self._xps.GatheringStop(self._sid)
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: