newportxps 0.9__tar.gz → 2025.1.0__tar.gz
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-2025.1.0/LICENSE +21 -0
- {newportxps-0.9/newportxps.egg-info → newportxps-2025.1.0}/PKG-INFO +8 -9
- {newportxps-0.9 → newportxps-2025.1.0}/newportxps/XPS_C8_drivers.py +3 -2
- {newportxps-0.9 → newportxps-2025.1.0}/newportxps/ftp_wrapper.py +37 -13
- {newportxps-0.9 → newportxps-2025.1.0}/newportxps/newportxps.py +76 -54
- newportxps-2025.1.0/newportxps/version.py +34 -0
- {newportxps-0.9 → newportxps-2025.1.0/newportxps.egg-info}/PKG-INFO +8 -9
- newportxps-2025.1.0/newportxps.egg-info/requires.txt +2 -0
- {newportxps-0.9 → newportxps-2025.1.0}/pyproject.toml +6 -7
- newportxps-0.9/LICENSE +0 -25
- newportxps-0.9/newportxps/version.py +0 -16
- newportxps-0.9/newportxps.egg-info/requires.txt +0 -2
- {newportxps-0.9 → newportxps-2025.1.0}/.gitignore +0 -0
- {newportxps-0.9 → newportxps-2025.1.0}/README.md +0 -0
- {newportxps-0.9 → newportxps-2025.1.0}/examples/stages_XPSC.ini +0 -0
- {newportxps-0.9 → newportxps-2025.1.0}/examples/stages_XPSD.ini +0 -0
- {newportxps-0.9 → newportxps-2025.1.0}/examples/system_exA.ini +0 -0
- {newportxps-0.9 → newportxps-2025.1.0}/examples/system_exB.ini +0 -0
- {newportxps-0.9 → newportxps-2025.1.0}/examples/system_exC.ini +0 -0
- {newportxps-0.9 → newportxps-2025.1.0}/examples/system_exD.ini +0 -0
- {newportxps-0.9 → newportxps-2025.1.0}/newportxps/__init__.py +0 -0
- {newportxps-0.9 → newportxps-2025.1.0}/newportxps/debugtime.py +0 -0
- {newportxps-0.9 → newportxps-2025.1.0}/newportxps/debugtimer.py +0 -0
- {newportxps-0.9 → newportxps-2025.1.0}/newportxps/utils.py +0 -0
- {newportxps-0.9 → newportxps-2025.1.0}/newportxps.egg-info/SOURCES.txt +0 -0
- {newportxps-0.9 → newportxps-2025.1.0}/newportxps.egg-info/dependency_links.txt +0 -0
- {newportxps-0.9 → newportxps-2025.1.0}/newportxps.egg-info/top_level.txt +0 -0
- {newportxps-0.9 → newportxps-2025.1.0}/setup.cfg +0 -0
- {newportxps-0.9 → newportxps-2025.1.0}/setup.py +0 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Matthew Newville, The University of Chicago
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
7
|
+
the Software without restriction, including without limitation the rights to
|
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
9
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
|
10
|
+
so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXP80RESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE qUSE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: newportxps
|
|
3
|
-
Version: 0
|
|
3
|
+
Version: 2025.1.0
|
|
4
4
|
Summary: Python interface to Newport XPS motion controllers
|
|
5
5
|
Author-email: Matthew Newville <newville@cars.uchicago.edu>
|
|
6
|
-
License:
|
|
6
|
+
License-Expression: MIT
|
|
7
7
|
Project-URL: Homepage, https://github.com/pyepics/newportxps/
|
|
8
8
|
Keywords: motion control,data collection
|
|
9
9
|
Classifier: Development Status :: 5 - Production/Stable
|
|
@@ -11,16 +11,14 @@ Classifier: Intended Audience :: Developers
|
|
|
11
11
|
Classifier: Intended Audience :: Education
|
|
12
12
|
Classifier: Intended Audience :: Other Audience
|
|
13
13
|
Classifier: Intended Audience :: Science/Research
|
|
14
|
-
Classifier: License :: OSI Approved :: BSD License
|
|
15
14
|
Classifier: Operating System :: OS Independent
|
|
16
15
|
Classifier: Programming Language :: Python
|
|
17
16
|
Classifier: Programming Language :: Python :: 3
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
20
17
|
Classifier: Programming Language :: Python :: 3.10
|
|
21
18
|
Classifier: Programming Language :: Python :: 3.11
|
|
22
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
-
Classifier: Programming Language :: Python ::
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
24
22
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
25
23
|
Classifier: Topic :: Education
|
|
26
24
|
Classifier: Topic :: Scientific/Engineering
|
|
@@ -29,11 +27,12 @@ Classifier: Topic :: Software Development
|
|
|
29
27
|
Classifier: Topic :: Software Development :: Libraries
|
|
30
28
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
31
29
|
Classifier: Topic :: Utilities
|
|
32
|
-
Requires-Python: >=3.
|
|
30
|
+
Requires-Python: >=3.10
|
|
33
31
|
Description-Content-Type: text/markdown
|
|
34
32
|
License-File: LICENSE
|
|
35
|
-
Requires-Dist:
|
|
33
|
+
Requires-Dist: paramiko
|
|
36
34
|
Requires-Dist: numpy
|
|
35
|
+
Dynamic: license-file
|
|
37
36
|
|
|
38
37
|
# newportxps
|
|
39
38
|
|
|
@@ -91,6 +91,7 @@ class XPS:
|
|
|
91
91
|
# print("SEND REC ", command, type(command))
|
|
92
92
|
suffix = ',EndOfAPI'
|
|
93
93
|
try:
|
|
94
|
+
XPS.__sockets[socketId].settimeout(3600.0)
|
|
94
95
|
XPS.__sockets[socketId].send(str2bytes(command))
|
|
95
96
|
ret = bytes2str(XPS.__sockets[socketId].recv(1024))
|
|
96
97
|
while (ret.find(suffix) == -1):
|
|
@@ -1139,7 +1140,7 @@ class XPS:
|
|
|
1139
1140
|
def MultipleAxesPVTVerification (self, socketId, GroupName, TrajectoryFileName):
|
|
1140
1141
|
command = 'MultipleAxesPVTVerification(' + GroupName + ',' + TrajectoryFileName + ')'
|
|
1141
1142
|
return self.Send(socketId, command)
|
|
1142
|
-
|
|
1143
|
+
|
|
1143
1144
|
# MultipleAxesPTVerification : Multiple axes PT trajectory verification
|
|
1144
1145
|
def MultipleAxesPTVerification (self, socketId, GroupName, TrajectoryFileName):
|
|
1145
1146
|
command = 'MultipleAxesPTVerification(' + GroupName + ',' + TrajectoryFileName + ')'
|
|
@@ -1156,7 +1157,7 @@ class XPS:
|
|
|
1156
1157
|
def MultipleAxesPVTExecution (self, socketId, GroupName, TrajectoryFileName, ExecutionNumber):
|
|
1157
1158
|
command = 'MultipleAxesPVTExecution(' + GroupName + ',' + TrajectoryFileName + ',' + str(ExecutionNumber) + ')'
|
|
1158
1159
|
return self.Send(socketId, command)
|
|
1159
|
-
|
|
1160
|
+
|
|
1160
1161
|
# MultipleAxesPTExecution : Multiple axes PT trajectory execution
|
|
1161
1162
|
def MultipleAxesPTExecution (self, socketId, GroupName, TrajectoryFileName, ExecutionNumber):
|
|
1162
1163
|
command = 'MultipleAxesPTExecution(' + GroupName + ',' + TrajectoryFileName + ',' + str(ExecutionNumber) + ')'
|
|
@@ -9,6 +9,15 @@ logger = logging.getLogger('paramiko')
|
|
|
9
9
|
logger.setLevel(logging.ERROR)
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
SFTP_ERROR_MESSAGE = """Could not connect to XPS with sftp: no host key.
|
|
13
|
+
|
|
14
|
+
You may need to add a host key to your `ssh known_hosts` file, using
|
|
15
|
+
ssh-keyscan {host} >> ~/.ssh/known_hosts
|
|
16
|
+
|
|
17
|
+
or first connecting with `sftp Administrator@{host}` """
|
|
18
|
+
|
|
19
|
+
import paramiko
|
|
20
|
+
|
|
12
21
|
HAS_PYSFTP = False
|
|
13
22
|
try:
|
|
14
23
|
import pysftp
|
|
@@ -53,7 +62,9 @@ class FTPBaseWrapper(object):
|
|
|
53
62
|
class SFTPWrapper(FTPBaseWrapper):
|
|
54
63
|
"""wrap ftp interactions for Newport XPS models D"""
|
|
55
64
|
def __init__(self, host=None, username='Administrator',
|
|
56
|
-
password='Administrator'):
|
|
65
|
+
password='Administrator', use_paramiko=True):
|
|
66
|
+
self.use_paramiko = use_paramiko
|
|
67
|
+
self.ssh_client = None
|
|
57
68
|
FTPBaseWrapper.__init__(self, host=host,
|
|
58
69
|
username=username, password=password)
|
|
59
70
|
|
|
@@ -64,19 +75,32 @@ class SFTPWrapper(FTPBaseWrapper):
|
|
|
64
75
|
self.username = username
|
|
65
76
|
if password is not None:
|
|
66
77
|
self.password = password
|
|
78
|
+
if not self.use_paramiko and HAS_PYSFTP:
|
|
79
|
+
self._conn = pysftp.Connection(host,
|
|
80
|
+
username=username,
|
|
81
|
+
password=password)
|
|
82
|
+
else:
|
|
83
|
+
if self.ssh_client is None:
|
|
84
|
+
self.ssh_client = paramiko.SSHClient()
|
|
85
|
+
self.ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
86
|
+
|
|
87
|
+
try:
|
|
88
|
+
self.ssh_client.connect(host, 22, username, password)
|
|
89
|
+
|
|
90
|
+
except paramiko.AuthenticationException:
|
|
91
|
+
print("Authentication failed. Check your username and password/key.")
|
|
92
|
+
raise ValueError(SFTP_ERROR_MESSAGE.format(host=self.host))
|
|
93
|
+
except paramiko.SSHException as e:
|
|
94
|
+
print(f"SSH connection error: {e}")
|
|
95
|
+
raise ValueError(SFTP_ERROR_MESSAGE.format(host=self.host))
|
|
96
|
+
finally:
|
|
97
|
+
self._conn = self.ssh_client.open_sftp()
|
|
67
98
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
password=self.password)
|
|
74
|
-
except:
|
|
75
|
-
print("ERROR: sftp connection to %s failed" % self.host)
|
|
76
|
-
print("You may need to add the host keys for your XPS to your")
|
|
77
|
-
print("ssh known_hosts file, using a command like this:")
|
|
78
|
-
print(" ssh-keyscan %s >> ~/.ssh/known_hosts" % self.host)
|
|
79
|
-
|
|
99
|
+
def cwd(self, remotedir):
|
|
100
|
+
if self.use_paramiko:
|
|
101
|
+
self._conn.chdir(remotedir)
|
|
102
|
+
elif hasattr(self._conn, 'cwd'):
|
|
103
|
+
self._conn.cwd(remotedir)
|
|
80
104
|
|
|
81
105
|
def save(self, remotefile, localfile):
|
|
82
106
|
"save remote file to local file"
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env python
|
|
2
2
|
|
|
3
3
|
import posixpath
|
|
4
|
+
import atexit
|
|
4
5
|
import sys
|
|
5
6
|
import time
|
|
6
7
|
import socket
|
|
@@ -97,10 +98,17 @@ class NewportXPS:
|
|
|
97
98
|
f" Positioner Errors: {perrs[stagename]}"])
|
|
98
99
|
return "\n".join(out)
|
|
99
100
|
|
|
101
|
+
def disconnect(self):
|
|
102
|
+
self.ftpconn.close()
|
|
103
|
+
if self._sid is not None:
|
|
104
|
+
self._xps.TCP_CloseSocket(self._sid)
|
|
105
|
+
self._sid = None
|
|
100
106
|
|
|
101
107
|
def connect(self):
|
|
102
108
|
self._sid = self._xps.TCP_ConnectToServer(self.host,
|
|
103
109
|
self.port, self.timeout)
|
|
110
|
+
|
|
111
|
+
atexit.register(self.disconnect)
|
|
104
112
|
try:
|
|
105
113
|
self._xps.Login(self._sid, self.username, self.password)
|
|
106
114
|
except:
|
|
@@ -109,8 +117,7 @@ class NewportXPS:
|
|
|
109
117
|
err, val = self._xps.FirmwareVersionGet(self._sid)
|
|
110
118
|
self.firmware_version = val
|
|
111
119
|
self.ftphome = ''
|
|
112
|
-
|
|
113
|
-
if any([m in self.firmware_version for m in ['XPS-D', 'HXP-D']]):
|
|
120
|
+
if any([m in self.firmware_version for m in ['XPS-D', 'HXP-D', 'XPS-RL']]):
|
|
114
121
|
err, val = self._xps.Send(self._sid, 'InstallerVersionGet(char *)')
|
|
115
122
|
self.firmware_version = val
|
|
116
123
|
self.ftpconn = SFTPWrapper(**self.ftpargs)
|
|
@@ -120,6 +127,11 @@ class NewportXPS:
|
|
|
120
127
|
self.ftphome = '/Admin'
|
|
121
128
|
self.read_systemini()
|
|
122
129
|
|
|
130
|
+
def clean_folders(self):
|
|
131
|
+
if 'xps-d' in self.firmware_version.lower():
|
|
132
|
+
self._xps.CleanTmpFolder(self._sid)
|
|
133
|
+
self._xps.CleanCoreDumpFolder(self._sid)
|
|
134
|
+
|
|
123
135
|
|
|
124
136
|
def check_error(self, err, msg='', with_raise=True):
|
|
125
137
|
if err != 0:
|
|
@@ -168,7 +180,7 @@ class NewportXPS:
|
|
|
168
180
|
sconf.read_string(initext)
|
|
169
181
|
|
|
170
182
|
# read and populate lists of groups first
|
|
171
|
-
for gtype, glist in sconf.items('GROUPS'):
|
|
183
|
+
for gtype, glist in sconf.items('GROUPS'):
|
|
172
184
|
if len(glist) > 0:
|
|
173
185
|
for gname in glist.split(','):
|
|
174
186
|
gname = gname.strip()
|
|
@@ -191,21 +203,19 @@ class NewportXPS:
|
|
|
191
203
|
|
|
192
204
|
if len(pvtgroups) == 1:
|
|
193
205
|
self.set_trajectory_group(pvtgroups[0])
|
|
194
|
-
|
|
195
206
|
for sname in self.stages:
|
|
196
207
|
ret = self._xps.PositionerMaximumVelocityAndAccelerationGet(self._sid, sname)
|
|
197
208
|
try:
|
|
198
209
|
self.stages[sname]['max_velo'] = ret[1]
|
|
199
|
-
self.stages[sname]['max_accel'] = ret[2]
|
|
210
|
+
self.stages[sname]['max_accel'] = 0.75*ret[2]
|
|
200
211
|
except:
|
|
201
|
-
print(f"could not
|
|
212
|
+
print(f"could not read max velo/accel for {sname}")
|
|
202
213
|
ret = self._xps.PositionerUserTravelLimitsGet(self._sid, sname)
|
|
203
214
|
try:
|
|
204
215
|
self.stages[sname]['low_limit'] = ret[1]
|
|
205
216
|
self.stages[sname]['high_limit'] = ret[2]
|
|
206
217
|
except:
|
|
207
|
-
print(f"could not
|
|
208
|
-
|
|
218
|
+
print(f"could not read limits for {sname}")
|
|
209
219
|
return self.groups
|
|
210
220
|
|
|
211
221
|
def download_trajectory(self, filename):
|
|
@@ -426,8 +436,8 @@ class NewportXPS:
|
|
|
426
436
|
print(f"Warning: could not enable trajectory group '{self.traj_group}'")
|
|
427
437
|
return
|
|
428
438
|
|
|
429
|
-
for i in range(64):
|
|
430
|
-
|
|
439
|
+
#for i in range(64):
|
|
440
|
+
# self._xps.EventExtendedRemove(self._sid, i)
|
|
431
441
|
|
|
432
442
|
# build template for linear trajectory file:
|
|
433
443
|
trajline1 = ['%(ramptime)f']
|
|
@@ -630,8 +640,6 @@ class NewportXPS:
|
|
|
630
640
|
print("Do have a group to move")
|
|
631
641
|
return
|
|
632
642
|
ret = self._xps.GroupMoveAbort(self._sid, group)
|
|
633
|
-
print('abort group ', group, ret)
|
|
634
|
-
|
|
635
643
|
|
|
636
644
|
@withConnectedXPS
|
|
637
645
|
def move_group(self, group=None, **kws):
|
|
@@ -640,7 +648,7 @@ class NewportXPS:
|
|
|
640
648
|
if group is None or group not in self.groups:
|
|
641
649
|
group = self.traj_group
|
|
642
650
|
if group is None:
|
|
643
|
-
print("
|
|
651
|
+
print("no group to move")
|
|
644
652
|
return
|
|
645
653
|
posnames = [p.lower() for p in self.groups[group]['positioners']]
|
|
646
654
|
ret = self._xps.GroupPositionCurrentGet(self._sid, group, len(posnames))
|
|
@@ -742,8 +750,8 @@ class NewportXPS:
|
|
|
742
750
|
|
|
743
751
|
|
|
744
752
|
@withConnectedXPS
|
|
745
|
-
def define_line_trajectories(self, axis, group=None, pixeltime=
|
|
746
|
-
scantime=None, start=0, stop=1, step=0.
|
|
753
|
+
def define_line_trajectories(self, axis, group=None, pixeltime=None,
|
|
754
|
+
scantime=None, start=0, stop=1, step=0.01,
|
|
747
755
|
accel=None, upload=True, verbose=False):
|
|
748
756
|
"""defines 'forward' and 'backward' trajectories for a simple
|
|
749
757
|
single element line scan using PVT Mode
|
|
@@ -759,9 +767,8 @@ class NewportXPS:
|
|
|
759
767
|
if stage in self.stages:
|
|
760
768
|
break
|
|
761
769
|
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
max_accel = 0.5*self.stages[stage]['max_accel']
|
|
770
|
+
max_velo = self.stages[stage]['max_velo']
|
|
771
|
+
max_accel = self.stages[stage]['max_accel']
|
|
765
772
|
|
|
766
773
|
if accel is None:
|
|
767
774
|
accel = max_accel
|
|
@@ -773,17 +780,20 @@ class NewportXPS:
|
|
|
773
780
|
step = scandir*abs(step)
|
|
774
781
|
|
|
775
782
|
npulses = int((abs(stop - start) + abs(step)*1.1) / abs(step))
|
|
776
|
-
if pixeltime is None
|
|
777
|
-
scantime
|
|
778
|
-
|
|
779
|
-
|
|
783
|
+
if pixeltime is None:
|
|
784
|
+
if scantime is None:
|
|
785
|
+
raise ValueError("line trajectory must set pixeltime or scantime")
|
|
786
|
+
else:
|
|
787
|
+
pixeltime = float(abs(scantime))/(npulses-1)
|
|
788
|
+
scantime = float(abs(pixeltime))*npulses
|
|
780
789
|
|
|
781
790
|
distance = (abs(stop - start) + abs(step))*1.0
|
|
782
791
|
velocity = min(distance/scantime, max_velo)
|
|
783
|
-
|
|
792
|
+
if verbose:
|
|
793
|
+
print(f"trajecory: {scantime=:.4f}, {pixeltime=:.4f}, {npulses=}, {start=:.4f}, {stop=:.4f}, {step=:.4f}")
|
|
784
794
|
ramptime = max(2.e-5, abs(velocity/accel))
|
|
785
|
-
rampdist = velocity*ramptime
|
|
786
|
-
offset = step
|
|
795
|
+
rampdist = 0.5*velocity*ramptime
|
|
796
|
+
offset = 0.5*step + scandir*rampdist
|
|
787
797
|
|
|
788
798
|
trajbase = {'axes': [axis],
|
|
789
799
|
'type': 'line',
|
|
@@ -828,6 +838,8 @@ class NewportXPS:
|
|
|
828
838
|
self.linear_template % back)
|
|
829
839
|
self.trajectories['foreward']['uploaded'] = True
|
|
830
840
|
self.trajectories['backward']['uploaded'] = True
|
|
841
|
+
self.trajectories['foreward']['text'] = self.linear_template % fore
|
|
842
|
+
self.trajectories['backward']['text'] = self.linear_template % back
|
|
831
843
|
ret = True
|
|
832
844
|
except:
|
|
833
845
|
raise ValueError("error uploading trajectory")
|
|
@@ -966,7 +978,7 @@ class NewportXPS:
|
|
|
966
978
|
p, v = pos[axes][n], velo[axes][n]
|
|
967
979
|
line.extend([f"{p:.8f}", f"{v:.8f}"])
|
|
968
980
|
buff.append(', '.join(line))
|
|
969
|
-
|
|
981
|
+
buff.append('')
|
|
970
982
|
buff = '\n'.join(buff)
|
|
971
983
|
traj['pvt_buffer'] = buff
|
|
972
984
|
|
|
@@ -1005,7 +1017,6 @@ class NewportXPS:
|
|
|
1005
1017
|
self.move_stage(f'{tgroup}.{axes}', pos)
|
|
1006
1018
|
|
|
1007
1019
|
|
|
1008
|
-
|
|
1009
1020
|
@withConnectedXPS
|
|
1010
1021
|
def arm_trajectory(self, name, verbose=False, move_to_start=True):
|
|
1011
1022
|
"""
|
|
@@ -1027,7 +1038,6 @@ class NewportXPS:
|
|
|
1027
1038
|
|
|
1028
1039
|
if move_to_start:
|
|
1029
1040
|
self.move_to_trajectory_start(name)
|
|
1030
|
-
|
|
1031
1041
|
# move_kws = {}
|
|
1032
1042
|
outputs = []
|
|
1033
1043
|
for out in self.gather_outputs:
|
|
@@ -1049,33 +1059,33 @@ class NewportXPS:
|
|
|
1049
1059
|
|
|
1050
1060
|
if verbose:
|
|
1051
1061
|
print(" GatheringConfigurationSet outputs ", outputs)
|
|
1052
|
-
print(" GatheringConfigurationSet returned ", ret)
|
|
1062
|
+
print(" GatheringConfigurationSet returned ", ret, time.ctime())
|
|
1053
1063
|
print(" segments, pixeltime" , end_segment, traj['pixeltime'])
|
|
1054
1064
|
|
|
1055
1065
|
err, ret = self._xps.MultipleAxesPVTPulseOutputSet(self._sid, self.traj_group,
|
|
1056
1066
|
2, end_segment,
|
|
1057
1067
|
traj['pixeltime'])
|
|
1058
|
-
self.check_error(err, msg="PVTPulseOutputSet", with_raise=
|
|
1068
|
+
self.check_error(err, msg="PVTPulseOutputSet", with_raise=True)
|
|
1059
1069
|
if verbose:
|
|
1060
|
-
print(" PVTPulse ", ret)
|
|
1070
|
+
print(" PVTPulse ", ret, time.ctime())
|
|
1061
1071
|
err, ret = self._xps.MultipleAxesPVTVerification(self._sid,
|
|
1062
1072
|
self.traj_group,
|
|
1063
1073
|
self.traj_file)
|
|
1064
1074
|
|
|
1065
|
-
self.check_error(err, msg="PVTVerification", with_raise=
|
|
1075
|
+
self.check_error(err, msg="PVTVerification", with_raise=True)
|
|
1066
1076
|
if verbose:
|
|
1067
|
-
print(" PVTVerify ", ret)
|
|
1077
|
+
print(" PVTVerify ", ret, time.ctime())
|
|
1068
1078
|
self.traj_state = ARMED
|
|
1069
1079
|
|
|
1070
1080
|
@withConnectedXPS
|
|
1071
1081
|
def run_trajectory(self, name=None, save=True, clean=False,
|
|
1072
|
-
output_file='Gather.dat', verbose=False):
|
|
1082
|
+
output_file='Gather.dat', verbose=False, move_to_start=True):
|
|
1073
1083
|
|
|
1074
1084
|
"""run a trajectory in PVT mode
|
|
1075
1085
|
|
|
1076
1086
|
The trajectory *must be in the ARMED state
|
|
1077
1087
|
"""
|
|
1078
|
-
|
|
1088
|
+
dt = debugtime()
|
|
1079
1089
|
if 'xps-d' in self.firmware_version.lower():
|
|
1080
1090
|
self._xps.CleanTmpFolder(self._sid)
|
|
1081
1091
|
|
|
@@ -1083,11 +1093,12 @@ class NewportXPS:
|
|
|
1083
1093
|
self._xps.CleanCoreDumpFolder(self._sid)
|
|
1084
1094
|
|
|
1085
1095
|
if name in self.trajectories and self.traj_state != ARMED:
|
|
1086
|
-
self.arm_trajectory(name, verbose=verbose)
|
|
1096
|
+
self.arm_trajectory(name, verbose=verbose, move_to_start=move_to_start)
|
|
1087
1097
|
|
|
1088
1098
|
if self.traj_state != ARMED:
|
|
1089
1099
|
raise XPSException("Must arm trajectory before running!")
|
|
1090
1100
|
|
|
1101
|
+
dt.add('armed')
|
|
1091
1102
|
tgroup = self.traj_group
|
|
1092
1103
|
buffer = ('Always', f'{tgroup}.PVT.TrajectoryPulse',)
|
|
1093
1104
|
err, ret = self._xps.EventExtendedConfigurationTriggerSet(self._sid, buffer,
|
|
@@ -1096,35 +1107,46 @@ class NewportXPS:
|
|
|
1096
1107
|
self.check_error(err, msg="EventConfigTrigger")
|
|
1097
1108
|
if verbose:
|
|
1098
1109
|
print( " EventExtended Trigger Set ", ret)
|
|
1099
|
-
|
|
1110
|
+
dt.add('event trigger set')
|
|
1100
1111
|
err, ret = self._xps.EventExtendedConfigurationActionSet(self._sid,
|
|
1101
1112
|
('GatheringOneData',),
|
|
1102
1113
|
('',), ('',),('',),('',))
|
|
1103
1114
|
self.check_error(err, msg="EventConfigAction")
|
|
1104
1115
|
if verbose:
|
|
1105
1116
|
print( " EventExtended Action Set ", ret)
|
|
1106
|
-
|
|
1117
|
+
dt.add('event action set')
|
|
1107
1118
|
eventID, m = self._xps.EventExtendedStart(self._sid)
|
|
1108
1119
|
self.traj_state = RUNNING
|
|
1109
1120
|
|
|
1110
1121
|
if verbose:
|
|
1111
1122
|
print( " EventExtended ExtendedStart ", eventID, m)
|
|
1112
|
-
|
|
1123
|
+
dt.add('event start')
|
|
1113
1124
|
err, ret = self._xps.MultipleAxesPVTExecution(self._sid,
|
|
1114
1125
|
self.traj_group,
|
|
1115
1126
|
self.traj_file, 1)
|
|
1116
1127
|
self.check_error(err, msg="PVT Execute", with_raise=False)
|
|
1117
1128
|
if verbose:
|
|
1118
|
-
print( " PVT Execute
|
|
1119
|
-
|
|
1129
|
+
print( " PVT Execute done ", ret)
|
|
1130
|
+
dt.add('pvt execute')
|
|
1120
1131
|
ret = self._xps.EventExtendedRemove(self._sid, eventID)
|
|
1121
1132
|
ret = self._xps.GatheringStop(self._sid)
|
|
1122
|
-
|
|
1133
|
+
dt.add('gathering stop')
|
|
1123
1134
|
self.traj_state = COMPLETE
|
|
1124
1135
|
npulses = 0
|
|
1125
1136
|
if save:
|
|
1126
|
-
self.
|
|
1137
|
+
npulses, buff = self.read_gathering(set_idle_when_done=False,
|
|
1138
|
+
verbose=verbose)
|
|
1139
|
+
dt.add('read gathering')
|
|
1140
|
+
if npulses > 0:
|
|
1141
|
+
self.save_gathering_file(output_file, buff,
|
|
1142
|
+
verbose=verbose,
|
|
1143
|
+
set_idle_when_done=False)
|
|
1144
|
+
dt.add('saved gathering')
|
|
1145
|
+
self.ngathered = npulses
|
|
1146
|
+
# self.read_and_save(output_file, verbose=verbose)
|
|
1127
1147
|
self.traj_state = IDLE
|
|
1148
|
+
if verbose:
|
|
1149
|
+
dt.show()
|
|
1128
1150
|
return npulses
|
|
1129
1151
|
|
|
1130
1152
|
@withConnectedXPS
|
|
@@ -1156,16 +1178,18 @@ class NewportXPS:
|
|
|
1156
1178
|
t0 = time.time()
|
|
1157
1179
|
while npulses < 1:
|
|
1158
1180
|
try:
|
|
1159
|
-
|
|
1181
|
+
gdat = self._xps.GatheringCurrentNumberGet(self._sid)
|
|
1160
1182
|
except SyntaxError:
|
|
1161
1183
|
print("#XPS Gathering Read failed, will try again")
|
|
1162
|
-
|
|
1184
|
+
if len(gdat) == 3:
|
|
1185
|
+
ret, npulses, nx = gdat
|
|
1186
|
+
if npulses < 1 or ret != 0:
|
|
1187
|
+
time.sleep(0.1)
|
|
1188
|
+
|
|
1163
1189
|
if time.time()-t0 > 5:
|
|
1164
1190
|
print("Failed to get gathering size after 5 seconds: return 0 points")
|
|
1165
1191
|
print("Gather Returned: ", ret, npulses, nx, self._xps, time.ctime())
|
|
1166
1192
|
return (0, ' \n')
|
|
1167
|
-
if npulses < 1 or ret != 0:
|
|
1168
|
-
time.sleep(0.05)
|
|
1169
1193
|
dt.add("gather num %d npulses=%d (%d)" % (ret, npulses, self.nsegments))
|
|
1170
1194
|
counter = 0
|
|
1171
1195
|
while npulses < 1 and counter < 5:
|
|
@@ -1177,7 +1201,7 @@ class NewportXPS:
|
|
|
1177
1201
|
try:
|
|
1178
1202
|
ret, buff = self._xps.GatheringDataMultipleLinesGet(self._sid, 0, npulses)
|
|
1179
1203
|
except ValueError:
|
|
1180
|
-
print("Failed to read gathering: ", ret
|
|
1204
|
+
print("Failed to read gathering: ", ret)
|
|
1181
1205
|
return (0, ' \n')
|
|
1182
1206
|
dt.add("gather after multilinesget %d" % ret)
|
|
1183
1207
|
nchunks = -1
|
|
@@ -1337,9 +1361,8 @@ class NewportXPS:
|
|
|
1337
1361
|
|
|
1338
1362
|
outputs = []
|
|
1339
1363
|
for out in self.gather_outputs:
|
|
1340
|
-
for
|
|
1364
|
+
for ax in traj['axes']:
|
|
1341
1365
|
outputs.append(f'{self.traj_group}.{ax}.{out}')
|
|
1342
|
-
# move_kws[ax] = float(traj['start'][i])
|
|
1343
1366
|
|
|
1344
1367
|
o = " ".join(outputs)
|
|
1345
1368
|
self.gather_titles = f"{self.gather_header}\n#{o}\n"
|
|
@@ -1350,7 +1373,7 @@ class NewportXPS:
|
|
|
1350
1373
|
2, step_number + 1, dtime)
|
|
1351
1374
|
self.check_error(err, msg="MultipleAxesPVTPulseOutputSet", with_raise=False)
|
|
1352
1375
|
|
|
1353
|
-
err,
|
|
1376
|
+
err, _ = self._xps.MultipleAxesPVTVerification(self._sid, self.traj_group, traj_file)
|
|
1354
1377
|
self.check_error(err, msg="MultipleAxesPVTVerification", with_raise=False)
|
|
1355
1378
|
|
|
1356
1379
|
buffer = ('Always', self.traj_group + '.PVT.TrajectoryPulse')
|
|
@@ -1363,7 +1386,7 @@ class NewportXPS:
|
|
|
1363
1386
|
('',), ('',), ('',), ('',))
|
|
1364
1387
|
self.check_error(err, msg="EventExtendedConfigurationActionSet", with_raise=False)
|
|
1365
1388
|
|
|
1366
|
-
eventID,
|
|
1389
|
+
eventID, _ = self._xps.EventExtendedStart(self._sid)
|
|
1367
1390
|
|
|
1368
1391
|
self._xps.MultipleAxesPVTExecution(self._sid, self.traj_group, traj_file, 1)
|
|
1369
1392
|
self._xps.EventExtendedRemove(self._sid, eventID)
|
|
@@ -1371,7 +1394,7 @@ class NewportXPS:
|
|
|
1371
1394
|
|
|
1372
1395
|
npulses = 0
|
|
1373
1396
|
if save:
|
|
1374
|
-
npulses,
|
|
1397
|
+
npulses, _ = self.read_and_save(outfile)
|
|
1375
1398
|
|
|
1376
1399
|
self._xps.GroupMoveRelative(self._sid, self.traj_group, ramps)
|
|
1377
1400
|
return npulses
|
|
@@ -1379,7 +1402,6 @@ class NewportXPS:
|
|
|
1379
1402
|
|
|
1380
1403
|
|
|
1381
1404
|
if __name__ == '__main__':
|
|
1382
|
-
import sys
|
|
1383
1405
|
ipaddr = sys.argv[1]
|
|
1384
1406
|
x = NewportXPS(ipaddr)
|
|
1385
1407
|
x.read_systemini()
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# file generated by setuptools-scm
|
|
2
|
+
# don't change, don't track in version control
|
|
3
|
+
|
|
4
|
+
__all__ = [
|
|
5
|
+
"__version__",
|
|
6
|
+
"__version_tuple__",
|
|
7
|
+
"version",
|
|
8
|
+
"version_tuple",
|
|
9
|
+
"__commit_id__",
|
|
10
|
+
"commit_id",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
TYPE_CHECKING = False
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from typing import Tuple
|
|
16
|
+
from typing import Union
|
|
17
|
+
|
|
18
|
+
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
19
|
+
COMMIT_ID = Union[str, None]
|
|
20
|
+
else:
|
|
21
|
+
VERSION_TUPLE = object
|
|
22
|
+
COMMIT_ID = object
|
|
23
|
+
|
|
24
|
+
version: str
|
|
25
|
+
__version__: str
|
|
26
|
+
__version_tuple__: VERSION_TUPLE
|
|
27
|
+
version_tuple: VERSION_TUPLE
|
|
28
|
+
commit_id: COMMIT_ID
|
|
29
|
+
__commit_id__: COMMIT_ID
|
|
30
|
+
|
|
31
|
+
__version__ = version = '2025.1.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (2025, 1, 0)
|
|
33
|
+
|
|
34
|
+
__commit_id__ = commit_id = 'gd77177eec'
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: newportxps
|
|
3
|
-
Version: 0
|
|
3
|
+
Version: 2025.1.0
|
|
4
4
|
Summary: Python interface to Newport XPS motion controllers
|
|
5
5
|
Author-email: Matthew Newville <newville@cars.uchicago.edu>
|
|
6
|
-
License:
|
|
6
|
+
License-Expression: MIT
|
|
7
7
|
Project-URL: Homepage, https://github.com/pyepics/newportxps/
|
|
8
8
|
Keywords: motion control,data collection
|
|
9
9
|
Classifier: Development Status :: 5 - Production/Stable
|
|
@@ -11,16 +11,14 @@ Classifier: Intended Audience :: Developers
|
|
|
11
11
|
Classifier: Intended Audience :: Education
|
|
12
12
|
Classifier: Intended Audience :: Other Audience
|
|
13
13
|
Classifier: Intended Audience :: Science/Research
|
|
14
|
-
Classifier: License :: OSI Approved :: BSD License
|
|
15
14
|
Classifier: Operating System :: OS Independent
|
|
16
15
|
Classifier: Programming Language :: Python
|
|
17
16
|
Classifier: Programming Language :: Python :: 3
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
20
17
|
Classifier: Programming Language :: Python :: 3.10
|
|
21
18
|
Classifier: Programming Language :: Python :: 3.11
|
|
22
19
|
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
-
Classifier: Programming Language :: Python ::
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
24
22
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
25
23
|
Classifier: Topic :: Education
|
|
26
24
|
Classifier: Topic :: Scientific/Engineering
|
|
@@ -29,11 +27,12 @@ Classifier: Topic :: Software Development
|
|
|
29
27
|
Classifier: Topic :: Software Development :: Libraries
|
|
30
28
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
31
29
|
Classifier: Topic :: Utilities
|
|
32
|
-
Requires-Python: >=3.
|
|
30
|
+
Requires-Python: >=3.10
|
|
33
31
|
Description-Content-Type: text/markdown
|
|
34
32
|
License-File: LICENSE
|
|
35
|
-
Requires-Dist:
|
|
33
|
+
Requires-Dist: paramiko
|
|
36
34
|
Requires-Dist: numpy
|
|
35
|
+
Dynamic: license-file
|
|
37
36
|
|
|
38
37
|
# newportxps
|
|
39
38
|
|
|
@@ -16,13 +16,14 @@ authors = [
|
|
|
16
16
|
{name="Matthew Newville", email="newville@cars.uchicago.edu"},
|
|
17
17
|
]
|
|
18
18
|
|
|
19
|
-
dependencies = ['
|
|
19
|
+
dependencies = ['paramiko', 'numpy']
|
|
20
20
|
description = "Python interface to Newport XPS motion controllers"
|
|
21
21
|
readme = "README.md"
|
|
22
|
-
requires-python = ">=3.
|
|
22
|
+
requires-python = ">=3.10"
|
|
23
23
|
keywords = ["motion control", "data collection"]
|
|
24
24
|
|
|
25
|
-
license =
|
|
25
|
+
license = "MIT"
|
|
26
|
+
license-files = ["LICENSE"]
|
|
26
27
|
|
|
27
28
|
classifiers = [
|
|
28
29
|
"Development Status :: 5 - Production/Stable",
|
|
@@ -30,16 +31,14 @@ classifiers = [
|
|
|
30
31
|
"Intended Audience :: Education",
|
|
31
32
|
"Intended Audience :: Other Audience",
|
|
32
33
|
"Intended Audience :: Science/Research",
|
|
33
|
-
"License :: OSI Approved :: BSD License",
|
|
34
34
|
"Operating System :: OS Independent",
|
|
35
35
|
"Programming Language :: Python",
|
|
36
36
|
"Programming Language :: Python :: 3",
|
|
37
|
-
"Programming Language :: Python :: 3.8",
|
|
38
|
-
"Programming Language :: Python :: 3.9",
|
|
39
37
|
"Programming Language :: Python :: 3.10",
|
|
40
38
|
"Programming Language :: Python :: 3.11",
|
|
41
39
|
"Programming Language :: Python :: 3.12",
|
|
42
|
-
"Programming Language :: Python ::
|
|
40
|
+
"Programming Language :: Python :: 3.13",
|
|
41
|
+
"Programming Language :: Python :: 3.14",
|
|
43
42
|
"Programming Language :: Python :: Implementation :: PyPy",
|
|
44
43
|
"Topic :: Education",
|
|
45
44
|
"Topic :: Scientific/Engineering",
|
newportxps-0.9/LICENSE
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
BSD 2-Clause License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2018, Matthew Newville, The University of Chicago
|
|
4
|
-
All rights reserved.
|
|
5
|
-
|
|
6
|
-
Redistribution and use in source and binary forms, with or without
|
|
7
|
-
modification, are permitted provided that the following conditions are met:
|
|
8
|
-
|
|
9
|
-
* Redistributions of source code must retain the above copyright notice, this
|
|
10
|
-
list of conditions and the following disclaimer.
|
|
11
|
-
|
|
12
|
-
* Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
-
this list of conditions and the following disclaimer in the documentation
|
|
14
|
-
and/or other materials provided with the distribution.
|
|
15
|
-
|
|
16
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
17
|
-
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
18
|
-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
19
|
-
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
20
|
-
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
21
|
-
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
22
|
-
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
23
|
-
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
24
|
-
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
25
|
-
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# file generated by setuptools_scm
|
|
2
|
-
# don't change, don't track in version control
|
|
3
|
-
TYPE_CHECKING = False
|
|
4
|
-
if TYPE_CHECKING:
|
|
5
|
-
from typing import Tuple, Union
|
|
6
|
-
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
7
|
-
else:
|
|
8
|
-
VERSION_TUPLE = object
|
|
9
|
-
|
|
10
|
-
version: str
|
|
11
|
-
__version__: str
|
|
12
|
-
__version_tuple__: VERSION_TUPLE
|
|
13
|
-
version_tuple: VERSION_TUPLE
|
|
14
|
-
|
|
15
|
-
__version__ = version = '0.9'
|
|
16
|
-
__version_tuple__ = version_tuple = (0, 9)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|