hasyutils 2.0.0__py2.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.
- HasyUtils/MgUtils.py +722 -0
- HasyUtils/MsUtils.py +1283 -0
- HasyUtils/OtherUtils.py +1097 -0
- HasyUtils/TgUtils.py +6712 -0
- HasyUtils/__init__.py +11 -0
- HasyUtils/fastscananalysis.py +476 -0
- HasyUtils/fioReader.py +714 -0
- HasyUtils/nxIO.py +309 -0
- HasyUtils/nxsReader.py +697 -0
- HasyUtils/nxsconftools.py +144 -0
- HasyUtils/pooltools.py +2648 -0
- HasyUtils/pyqtSelector.py +49 -0
- HasyUtils/spectraDoor.py +1549 -0
- HasyUtils/ssa.py +223 -0
- HasyUtils/tngMonitorAttrs.py +567 -0
- hasyutils-2.0.0.data/scripts/ECMonitor.py +85 -0
- hasyutils-2.0.0.data/scripts/HasyUtilsMain.py +44 -0
- hasyutils-2.0.0.data/scripts/MotorLogger.py +439 -0
- hasyutils-2.0.0.data/scripts/SardanaAIO.py +140 -0
- hasyutils-2.0.0.data/scripts/SardanaAdjustLimits.py +63 -0
- hasyutils-2.0.0.data/scripts/SardanaAlarmMonitor.py +129 -0
- hasyutils-2.0.0.data/scripts/SardanaChMg.py +289 -0
- hasyutils-2.0.0.data/scripts/SardanaChat.py +58 -0
- hasyutils-2.0.0.data/scripts/SardanaCheckOnlineXml.py +108 -0
- hasyutils-2.0.0.data/scripts/SardanaClearSCAs.py +22 -0
- hasyutils-2.0.0.data/scripts/SardanaConvert.py +1847 -0
- hasyutils-2.0.0.data/scripts/SardanaDeleteMotorGroups.py +32 -0
- hasyutils-2.0.0.data/scripts/SardanaDiag.py +149 -0
- hasyutils-2.0.0.data/scripts/SardanaIVP.py +767 -0
- hasyutils-2.0.0.data/scripts/SardanaInfoViewer.py +165 -0
- hasyutils-2.0.0.data/scripts/SardanaLimitsFromTS2Pool.py +31 -0
- hasyutils-2.0.0.data/scripts/SardanaMacroExecutor.py +51 -0
- hasyutils-2.0.0.data/scripts/SardanaMacroTester.py +256 -0
- hasyutils-2.0.0.data/scripts/SardanaMotorMonitor.py +318 -0
- hasyutils-2.0.0.data/scripts/SardanaRestartBoth.py +36 -0
- hasyutils-2.0.0.data/scripts/SardanaRestartMacroServer.py +51 -0
- hasyutils-2.0.0.data/scripts/SardanaRestartPool.py +40 -0
- hasyutils-2.0.0.data/scripts/SardanaShutdown.py +80 -0
- hasyutils-2.0.0.data/scripts/SardanaStartMacroServer.py +39 -0
- hasyutils-2.0.0.data/scripts/SardanaStartPool.py +40 -0
- hasyutils-2.0.0.data/scripts/SardanaStartup.py +245 -0
- hasyutils-2.0.0.data/scripts/SardanaStatus.py +63 -0
- hasyutils-2.0.0.data/scripts/SardanaStopBoth.py +28 -0
- hasyutils-2.0.0.data/scripts/SardanaStopMacro.py +57 -0
- hasyutils-2.0.0.data/scripts/SardanaStopMacroServer.py +36 -0
- hasyutils-2.0.0.data/scripts/SardanaStopPool.py +38 -0
- hasyutils-2.0.0.data/scripts/TngEigerCLI.py +277 -0
- hasyutils-2.0.0.data/scripts/TngMonitorAttrs.py +83 -0
- hasyutils-2.0.0.data/scripts/TngUtility.py +1445 -0
- hasyutils-2.0.0.data/scripts/alarm.ui +54 -0
- hasyutils-2.0.0.data/scripts/nxs_ifc.py +50 -0
- hasyutils-2.0.0.data/scripts/nxsclient.py +51 -0
- hasyutils-2.0.0.data/scripts/nxsreader.py +62 -0
- hasyutils-2.0.0.dist-info/AUTHORS +7 -0
- hasyutils-2.0.0.dist-info/LICENSE +34 -0
- hasyutils-2.0.0.dist-info/METADATA +9 -0
- hasyutils-2.0.0.dist-info/RECORD +59 -0
- hasyutils-2.0.0.dist-info/WHEEL +6 -0
- hasyutils-2.0.0.dist-info/top_level.txt +1 -0
HasyUtils/MsUtils.py
ADDED
|
@@ -0,0 +1,1283 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
'''
|
|
3
|
+
this file contains the helper functions for the MacroServer
|
|
4
|
+
'''
|
|
5
|
+
#
|
|
6
|
+
# not fatal because pyspViewer.py might be called on a non-exp host
|
|
7
|
+
#
|
|
8
|
+
try:
|
|
9
|
+
import PyTango as _PyTango
|
|
10
|
+
except:
|
|
11
|
+
pass
|
|
12
|
+
from . import TgUtils
|
|
13
|
+
import os as _os
|
|
14
|
+
import imp as _imp
|
|
15
|
+
import sys as _sys
|
|
16
|
+
import math as _math
|
|
17
|
+
|
|
18
|
+
def _findTangoDevice( macro, poolDevice):
|
|
19
|
+
'''
|
|
20
|
+
return the TangoDevice belonging to a poolDevice
|
|
21
|
+
'''
|
|
22
|
+
try:
|
|
23
|
+
poolProxy = _PyTango.DeviceProxy( poolDevice)
|
|
24
|
+
temp = poolProxy.read_attribute( "TangoDevice").value
|
|
25
|
+
except Exception as e:
|
|
26
|
+
macro.output( "MsUtils._findTangoDevice: failed for %s, %s" %
|
|
27
|
+
( poolDevice, str( e)))
|
|
28
|
+
macro.abort()
|
|
29
|
+
return None
|
|
30
|
+
#macro.output( "MsUtils._findTangoDevice: %s" % temp)
|
|
31
|
+
return temp
|
|
32
|
+
|
|
33
|
+
def _findFilewriter( macro, name):
|
|
34
|
+
'''
|
|
35
|
+
name is the Tango device name of an EigerDectris. This
|
|
36
|
+
function returns the name of the corresponding filewriter.
|
|
37
|
+
'''
|
|
38
|
+
#
|
|
39
|
+
# find an EigerFilewriter for the EigerDectris
|
|
40
|
+
#
|
|
41
|
+
deviceNameFw = None
|
|
42
|
+
TangoHost = None
|
|
43
|
+
if name.find( ":10000"):
|
|
44
|
+
lst = name.split( ':')
|
|
45
|
+
TangoHost = "%s:10000" % lst[0]
|
|
46
|
+
|
|
47
|
+
devsFw = TgUtils.getDeviceNamesByClass( "EigerFilewriter", tangoHost = TangoHost)
|
|
48
|
+
for devFw in devsFw:
|
|
49
|
+
prop = TgUtils.getDeviceProperty( devFw, 'EigerDevice', tangoHost = TangoHost)
|
|
50
|
+
#
|
|
51
|
+
# prop[0]: p62/eiger/e4m vs. hasnp62eh:10000/p62/eiger/e4m
|
|
52
|
+
#
|
|
53
|
+
if name.find( prop[0]) != -1:
|
|
54
|
+
deviceNameFw = devFw
|
|
55
|
+
break
|
|
56
|
+
if deviceNameFw is None:
|
|
57
|
+
macro.output( "MsUtils._findFilewriter: failed to find filewriter for %s" %
|
|
58
|
+
(name))
|
|
59
|
+
macro.abort()
|
|
60
|
+
return None
|
|
61
|
+
if TangoHost is not None:
|
|
62
|
+
deviceNameFw = "%s/%s" % (TangoHost, deviceNameFw)
|
|
63
|
+
return deviceNameFw
|
|
64
|
+
|
|
65
|
+
def prepareEigerDectrisAttrs( macro, name = None, NbImages = 1,
|
|
66
|
+
CountTime = None, TriggerMode = None, NbTriggers = 1,
|
|
67
|
+
ArmFlag = True, ImagesPerFile = 1000):
|
|
68
|
+
'''
|
|
69
|
+
|
|
70
|
+
called from MsUtils.prepareDetectorAttrs()
|
|
71
|
+
|
|
72
|
+
sets these detector attributes
|
|
73
|
+
CountTime
|
|
74
|
+
NbImages
|
|
75
|
+
NbTriggers
|
|
76
|
+
TriggerMode
|
|
77
|
+
|
|
78
|
+
the Filewriter FileNamePattern ist derived from ScanFile, ScanDir, ScanID
|
|
79
|
+
#
|
|
80
|
+
# ScanDir == "/gpfs/commissioning/raw"
|
|
81
|
+
#
|
|
82
|
+
if scan_dir.find( "commissioning/raw") != -1:
|
|
83
|
+
temp = "commissioning/raw/%s_%05d/%s/%s_%05d" % ( prefix, int( scan_id), detectorName, prefix, int( scan_id))
|
|
84
|
+
#
|
|
85
|
+
# ScanDir == "/gpfs/local"
|
|
86
|
+
#
|
|
87
|
+
elif scan_dir.find( "/gpfs/local") != -1:
|
|
88
|
+
temp = "local/%s_%05d/%s/%s_%05d" % ( prefix, int( scan_id), detectorName, prefix, int( scan_id))
|
|
89
|
+
#
|
|
90
|
+
# ScanDir == /gpfs/current/raw
|
|
91
|
+
#
|
|
92
|
+
else:
|
|
93
|
+
temp = "current/raw/%s_%05d/%s/%s_%05d" % ( prefix, int( scan_id), detectorName, prefix, int( scan_id))
|
|
94
|
+
eigerFw_proxy.FilenamePattern = temp
|
|
95
|
+
|
|
96
|
+
scanNameDir = "%s/%s_%05d" % ( scan_dir, prefix, int( scan_id))
|
|
97
|
+
fileDir = "%s/%s_%05d/%s" % ( scan_dir, prefix, int( scan_id), detectorName)
|
|
98
|
+
*** scanNameDir and fileDir are created with 0777
|
|
99
|
+
this feature has been added to avoid permission issues for beamlines
|
|
100
|
+
with two different users, e.g. p99user and p99femto
|
|
101
|
+
|
|
102
|
+
ImagesPerFile = 1000 by default
|
|
103
|
+
|
|
104
|
+
Eventually execute arm()
|
|
105
|
+
ArmFlag can be False, if users want to do some extra initialisations
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
Here is an example (PreScan Hook)
|
|
109
|
+
|
|
110
|
+
scanInfo = HasyUtils.createScanInfo( self.getParentMacro().getCommand())
|
|
111
|
+
if HasyUtils.isInMg( self, detectorName):
|
|
112
|
+
if not HasyUtils.prepareDetectorAttrs( self,
|
|
113
|
+
name = detectorName,
|
|
114
|
+
trig_mode = 'ints',
|
|
115
|
+
nbFrames = 1, # per trigger
|
|
116
|
+
acq_time = scanInfo[ 'sampleTime'],
|
|
117
|
+
NbTriggers = scanInfo[ 'intervals'] + 1,
|
|
118
|
+
ImagesPerFile = 1000):
|
|
119
|
+
self.output( "general_features.gh_pre_scan: prepareDetectors: returned error")
|
|
120
|
+
return False
|
|
121
|
+
|
|
122
|
+
'''
|
|
123
|
+
|
|
124
|
+
detectorName = name
|
|
125
|
+
if detectorName is None:
|
|
126
|
+
macro.output( "MsUtils.prepareEigerDectrisAttrs: no detectorName")
|
|
127
|
+
macro.abort()
|
|
128
|
+
return False
|
|
129
|
+
#
|
|
130
|
+
# detectorName is a pool device name, find the Tango device
|
|
131
|
+
#
|
|
132
|
+
tangoDevice = _findTangoDevice( macro, detectorName)
|
|
133
|
+
if tangoDevice is None:
|
|
134
|
+
return
|
|
135
|
+
try:
|
|
136
|
+
eiger_proxy = _PyTango.DeviceProxy( tangoDevice)
|
|
137
|
+
macro.output( "MsUtils.prepareEigerDectrisAttrs: Eiger %s" % tangoDevice)
|
|
138
|
+
macro.debug("MsUtils.prepareEigerDectrisAttrs: %s found in active MG" % detectorName)
|
|
139
|
+
except Exception as e:
|
|
140
|
+
macro.output( "MsUtils.prepareEigerDectrisAttrs: failed to create proxy to %s, %s, %s" %
|
|
141
|
+
(detectorName, controllerProxy.TangoDevice, str( e)))
|
|
142
|
+
macro.abort()
|
|
143
|
+
return False
|
|
144
|
+
|
|
145
|
+
#
|
|
146
|
+
# disarm the detector before setting the attributes
|
|
147
|
+
#
|
|
148
|
+
eiger_proxy.disarm()
|
|
149
|
+
|
|
150
|
+
#
|
|
151
|
+
# CountTime (exposure time)
|
|
152
|
+
#
|
|
153
|
+
if CountTime is not None:
|
|
154
|
+
eiger_proxy.CountTime = float( CountTime)
|
|
155
|
+
macro.output( "MsUtils.prepareEigerDectrisAttrs: CountTime to %g" % eiger_proxy.CountTime)
|
|
156
|
+
#eiger_proxy.FrameTime = float( CountTime)*1.001
|
|
157
|
+
#macro.output( "MsUtils.prepareEigerDectrisAttrs: FrameTime to %g" % eiger_proxy.CountTime)
|
|
158
|
+
#
|
|
159
|
+
# NbImages per Trigger
|
|
160
|
+
#
|
|
161
|
+
eiger_proxy.NbImages = int( NbImages)
|
|
162
|
+
macro.output( "MsUtils.prepareEigerDectrisAttrs: NbImages to %d" % eiger_proxy.NbImages)
|
|
163
|
+
|
|
164
|
+
#
|
|
165
|
+
# TriggerMode, usually 'ints' for internal triggers
|
|
166
|
+
#
|
|
167
|
+
if TriggerMode is not None:
|
|
168
|
+
eiger_proxy.TriggerMode = TriggerMode
|
|
169
|
+
macro.output( "MsUtils.prepareEigerDectrisAttrs: TriggerMode to %s" % eiger_proxy.TriggerMode)
|
|
170
|
+
#
|
|
171
|
+
# NbTriggers
|
|
172
|
+
#
|
|
173
|
+
eiger_proxy.NbTriggers = int( NbTriggers)
|
|
174
|
+
macro.output( "MsUtils.prepareEigerDectrisAttrs: NbTrigger to %d" % eiger_proxy.NbTriggers)
|
|
175
|
+
|
|
176
|
+
#
|
|
177
|
+
# handle Filewriter
|
|
178
|
+
#
|
|
179
|
+
deviceNameFw = _findFilewriter( macro, tangoDevice)
|
|
180
|
+
if deviceNameFw is None:
|
|
181
|
+
return
|
|
182
|
+
|
|
183
|
+
try:
|
|
184
|
+
eigerFw_proxy = _PyTango.DeviceProxy( deviceNameFw)
|
|
185
|
+
macro.output( "MsUtils.prepareEigerDectrisAttrs: FileWriter %s" % deviceNameFw)
|
|
186
|
+
except Exception as e:
|
|
187
|
+
macro.output( "MsUtils.prepareEigerDectrisAttrs: failed to create proxy to %s, %s" %
|
|
188
|
+
( deviceNameFw, str( e)))
|
|
189
|
+
macro.abort()
|
|
190
|
+
return False
|
|
191
|
+
|
|
192
|
+
#
|
|
193
|
+
# tst.fio -> tst
|
|
194
|
+
#
|
|
195
|
+
scan_file = macro.getEnv("ScanFile")
|
|
196
|
+
if type(scan_file).__name__ == 'list':
|
|
197
|
+
scan_file = scan_file[0]
|
|
198
|
+
|
|
199
|
+
prefix = scan_file.split( '.')[0]
|
|
200
|
+
scan_id = macro.getEnv("ScanID")
|
|
201
|
+
#
|
|
202
|
+
# use ScanDir to select
|
|
203
|
+
# current/raw/<prefix>_<ScanID>/<detectorName>/<prefix>_$id
|
|
204
|
+
# or
|
|
205
|
+
# commissioning/raw/<prefix>_<ScanID>/<detectorName>/<prefix>_$id
|
|
206
|
+
#
|
|
207
|
+
# $id is handled by Dectris
|
|
208
|
+
#
|
|
209
|
+
# on the DCU we will always have /data/current/raw
|
|
210
|
+
# the download job looks at ScanDir
|
|
211
|
+
#
|
|
212
|
+
scan_dir = macro.getEnv( "ScanDir")
|
|
213
|
+
scanNameDir = "%s/%s_%05d" % ( scan_dir, prefix, int( scan_id))
|
|
214
|
+
fileDir = "%s/%s_%05d/%s" % ( scan_dir, prefix, int( scan_id), detectorName)
|
|
215
|
+
try:
|
|
216
|
+
_os.makedirs( fileDir, exist_ok=True)
|
|
217
|
+
_os.chmod( fileDir, 0o777)
|
|
218
|
+
_os.chmod( scanNameDir, 0o777)
|
|
219
|
+
except Exception as e:
|
|
220
|
+
macro.output( "MsUtils.prepareDetectorAttrs: failed to create %s, %s" % (fileDir, e))
|
|
221
|
+
return False
|
|
222
|
+
macro.output( "MsUtils.prepareEigerDetectorAttrs: creating %s" % (fileDir))
|
|
223
|
+
#+++
|
|
224
|
+
#
|
|
225
|
+
# 9.3.2021: taken out $id for Florian Bertram
|
|
226
|
+
#
|
|
227
|
+
if scan_dir.find( "commissioning/raw") != -1:
|
|
228
|
+
#temp = "commissioning/raw/%s_%05d/%s/%s_$id" % ( prefix, int( scan_id), detectorName, prefix)
|
|
229
|
+
temp = "commissioning/raw/%s_%05d/%s/%s_%05d" % ( prefix, int( scan_id), detectorName, prefix, int( scan_id))
|
|
230
|
+
#
|
|
231
|
+
# ScanDir == "/gpfs/local"
|
|
232
|
+
#
|
|
233
|
+
elif scan_dir.find( "/gpfs/local") != -1:
|
|
234
|
+
#temp = "local/%s_%05d/%s/%s_$id" % ( prefix, int( scan_id), detectorName, prefix)
|
|
235
|
+
temp = "local/%s_%05d/%s/%s_%05d" % ( prefix, int( scan_id), detectorName, prefix, int( scan_id))
|
|
236
|
+
else:
|
|
237
|
+
#temp = "current/raw/%s_%05d/%s/%s_$id" % ( prefix, int( scan_id), detectorName, prefix)
|
|
238
|
+
temp = "current/raw/%s_%05d/%s/%s_%05d" % ( prefix, int( scan_id), detectorName, prefix, int( scan_id))
|
|
239
|
+
eigerFw_proxy.FilenamePattern = temp
|
|
240
|
+
macro.output( "MsUtils.prepareEigerDectrisAttrs: FilenamePattern to %s" % eigerFw_proxy.FilenamePattern)
|
|
241
|
+
#
|
|
242
|
+
# ImagesPerFile
|
|
243
|
+
#
|
|
244
|
+
# eigerFw_proxy.ImagesPerFile = NbImages*NbTriggers
|
|
245
|
+
# Florian like the 'fixed' 1000 better, to avoid large files
|
|
246
|
+
#
|
|
247
|
+
eigerFw_proxy.ImagesPerFile = ImagesPerFile
|
|
248
|
+
macro.output( "MsUtils.prepareEigerDectrisAttrs: ImagesPerFile to %d" % eigerFw_proxy.ImagesPerFile)
|
|
249
|
+
|
|
250
|
+
#
|
|
251
|
+
# eventually arm() the detector
|
|
252
|
+
#
|
|
253
|
+
if ArmFlag:
|
|
254
|
+
macro.output( "MsUtils.prepareEigerDectrisAttrs: calling arm()")
|
|
255
|
+
eiger_proxy.arm()
|
|
256
|
+
else:
|
|
257
|
+
macro.output( "MsUtils.prepareEigerDectrisAttrs: NOT calling arm()")
|
|
258
|
+
|
|
259
|
+
return True
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def resetEigerDectrisAttrs( macro, name = None):
|
|
263
|
+
'''
|
|
264
|
+
make sure that:
|
|
265
|
+
- the detector is disarmed to close the file
|
|
266
|
+
- NbTriggers is set to 1 in order to allow for 'ct'
|
|
267
|
+
- ImagesPerFile is set to 1 in order to allow for 'ct'
|
|
268
|
+
'''
|
|
269
|
+
|
|
270
|
+
import time
|
|
271
|
+
detectorName = name
|
|
272
|
+
if detectorName is None:
|
|
273
|
+
macro.output( "MsUtils.resetEigerDectrisAttrs: no detectorName")
|
|
274
|
+
macro.abort()
|
|
275
|
+
return False
|
|
276
|
+
|
|
277
|
+
tangoDevice = _findTangoDevice( macro, detectorName)
|
|
278
|
+
if tangoDevice is None:
|
|
279
|
+
return
|
|
280
|
+
try:
|
|
281
|
+
eiger_proxy = _PyTango.DeviceProxy( tangoDevice)
|
|
282
|
+
except Exception as e:
|
|
283
|
+
macro.output( "MsUtils.resetEigerDectrisAttrs: failed to create proxy to %s, %s" %
|
|
284
|
+
( tangoDevice, str( e)))
|
|
285
|
+
macro.abort()
|
|
286
|
+
return False
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
deviceNameFw = _findFilewriter( macro, tangoDevice)
|
|
290
|
+
if deviceNameFw is None:
|
|
291
|
+
return
|
|
292
|
+
try:
|
|
293
|
+
eigerFw_proxy = _PyTango.DeviceProxy( deviceNameFw)
|
|
294
|
+
except Exception as e:
|
|
295
|
+
macro.output( "MsUtils.resetEigerDectrisAttrs: failed to create proxy to %s, %s" %
|
|
296
|
+
( deviceNameFw, str( e)))
|
|
297
|
+
macro.abort()
|
|
298
|
+
return False
|
|
299
|
+
|
|
300
|
+
if eigerFw_proxy.state() == _PyTango.DevState.MOVING:
|
|
301
|
+
macro.output( "MsUtils.resetEigerDectrisAttrs: FW (%s) is MOVING -> disarm detector" % deviceNameFw)
|
|
302
|
+
eiger_proxy.disarm()
|
|
303
|
+
startTime = time.time()
|
|
304
|
+
while eigerFw_proxy.state() != _PyTango.DevState.ON:
|
|
305
|
+
time.sleep( 0.1)
|
|
306
|
+
if (time.time() - startTime) > 2:
|
|
307
|
+
macro.output( "MsUtils.resetEigerDectrisAttrs: FW %s does not become ON" % deviceNameFw)
|
|
308
|
+
return False
|
|
309
|
+
while eigerFw_proxy.status() != 'ready':
|
|
310
|
+
time.sleep( 0.1)
|
|
311
|
+
if (time.time() - startTime) > 2:
|
|
312
|
+
macro.output( "MsUtils.resetEigerDectrisAttrs: FW %s does not become 'ready'" % deviceNameFw)
|
|
313
|
+
return False
|
|
314
|
+
|
|
315
|
+
scan_file = macro.getEnv("ScanFile")
|
|
316
|
+
if type(scan_file).__name__ == 'list':
|
|
317
|
+
scan_file = scan_file[0]
|
|
318
|
+
lst = scan_file.split( '.')
|
|
319
|
+
#
|
|
320
|
+
# this creates current/raw/SingleShots
|
|
321
|
+
#
|
|
322
|
+
eigerFw_proxy.FilenamePattern = "current/raw/SingleShots/%s_$id" % lst[0]
|
|
323
|
+
macro.output( "MsUtils.resetEigerDectrisAttrs: FilenamePattern to %s" % eigerFw_proxy.Filenamepattern)
|
|
324
|
+
|
|
325
|
+
eigerFw_proxy.ImagesPerFile = 1
|
|
326
|
+
macro.output( "MsUtils.resetEigerDectrisAttrs: ImagesPerFile to %d" % int( eigerFw_proxy.ImagesPerFile))
|
|
327
|
+
eiger_proxy.NbImages = 1
|
|
328
|
+
macro.output( "MsUtils.resetEigerDectrisAttrs: NbImages to %d" % int( eiger_proxy.NbImages))
|
|
329
|
+
eiger_proxy.NbTriggers = 1
|
|
330
|
+
macro.output( "MsUtils.resetEigerDectrisAttrs: NbTriggers to %d" % int( eiger_proxy.NbTriggers))
|
|
331
|
+
eiger_proxy.TriggerMode = 'ints'
|
|
332
|
+
macro.output( "MsUtils.resetEigerDectrisAttrs: TriggerMode to %s" % eiger_proxy.TriggerMode)
|
|
333
|
+
|
|
334
|
+
return True
|
|
335
|
+
|
|
336
|
+
def prepareDetectorAttrs( macro, name = "pilatus", rootDir = "/ramdisk",
|
|
337
|
+
nbFrames = 1, acq_time = None, trig_mode = None, NbTriggers = 1,
|
|
338
|
+
ArmFlag = True, ImagesPerFile = 1000, do_check_if_detector_in_mg=True):
|
|
339
|
+
'''
|
|
340
|
+
prepareDetectorAttrs() uses the input arguments and the MacroServer
|
|
341
|
+
environment variables ScanFile and ScanID to set these detector attributes:
|
|
342
|
+
FileDir|SaveFilePath|saving_directory: /<rootDir>/<scanName>/<detectorName>
|
|
343
|
+
/ramdisk/au_01390/pilatus
|
|
344
|
+
FilePrefix|saving_prefix: <scanName>
|
|
345
|
+
au_01390
|
|
346
|
+
NbFrames|FrameNumbers|acq_nb_frames: nbFrames
|
|
347
|
+
|
|
348
|
+
FileStartNum|saving_next_number: 0
|
|
349
|
+
|
|
350
|
+
This directory is created:
|
|
351
|
+
rootDir + "/" + scanName + "/" + detectorName
|
|
352
|
+
/gpfs/current/raw/au_00001/pilatus
|
|
353
|
+
|
|
354
|
+
As a safety measure, rootDir is compared with FileDir|SaveFilePath|saving_directory.
|
|
355
|
+
An error is thrown, if the values are incompatible. Both
|
|
356
|
+
strings are compatible, if FileDir starts with rootDir
|
|
357
|
+
|
|
358
|
+
So far Dalsa, Eiger, Pilatus, Lambda, Kromo and Lima (Andor) servers are supported
|
|
359
|
+
|
|
360
|
+
trig_mode: FreeRunning, ExtTrigger, Snapshot, TimedSnap, TrigSequence
|
|
361
|
+
|
|
362
|
+
for doku about the Eiger interface, see HasyUtils.prepareEigerDectrisAttrs? and
|
|
363
|
+
HasyUtils.resetEigerDectrisAttrs?
|
|
364
|
+
|
|
365
|
+
ArmFlag == True
|
|
366
|
+
Eiger: ArmFlag can be False, if users want to do some extra initialisations
|
|
367
|
+
ImagesPerFile, for the EigerFilewriter
|
|
368
|
+
'''
|
|
369
|
+
detectorName = name
|
|
370
|
+
|
|
371
|
+
if do_check_if_detector_in_mg and not isInMg( macro, detectorName):
|
|
372
|
+
macro.output( "MsUtils.prepareDetectorAttrs: MG does not contain %s " % detectorName)
|
|
373
|
+
return True
|
|
374
|
+
|
|
375
|
+
try:
|
|
376
|
+
clss = TgUtils.getClassNameByDevice( _findTangoDevice( macro, detectorName))
|
|
377
|
+
except Exception as e:
|
|
378
|
+
macro.output( "MsUtils.prepareDetectorAttrs: error finding class for %s" % detectorName)
|
|
379
|
+
macro.output( "MsUtils.prepareDetectorAttrs: %s" % repr( e))
|
|
380
|
+
return
|
|
381
|
+
if clss == "EigerDectris":
|
|
382
|
+
return prepareEigerDectrisAttrs( macro,
|
|
383
|
+
name = detectorName,
|
|
384
|
+
NbImages = nbFrames,
|
|
385
|
+
CountTime = acq_time,
|
|
386
|
+
TriggerMode = trig_mode,
|
|
387
|
+
NbTriggers = NbTriggers,
|
|
388
|
+
ArmFlag = ArmFlag,
|
|
389
|
+
ImagesPerFile = ImagesPerFile)
|
|
390
|
+
|
|
391
|
+
scan_file = macro.getEnv("ScanFile")
|
|
392
|
+
if type(scan_file).__name__ == 'list':
|
|
393
|
+
scan_file = scan_file[0]
|
|
394
|
+
scan_id = macro.getEnv("ScanID")
|
|
395
|
+
|
|
396
|
+
tangoDevice_proxy = None
|
|
397
|
+
count = 0
|
|
398
|
+
while True:
|
|
399
|
+
try:
|
|
400
|
+
controllerProxy = _PyTango.DeviceProxy(detectorName)
|
|
401
|
+
temp = controllerProxy.read_attribute( "TangoDevice").value
|
|
402
|
+
tangoDevice_proxy = _PyTango.DeviceProxy( temp)
|
|
403
|
+
macro.debug("MsUtils.prepareDetectorAttrs: %s found in active MG" % detectorName)
|
|
404
|
+
break
|
|
405
|
+
except Exception as e:
|
|
406
|
+
count += 1
|
|
407
|
+
if count > 5:
|
|
408
|
+
macro.output( "MsUtils.prepareDetectorAttrs: failed to create proxy to %s, %s, %s" %
|
|
409
|
+
(detectorName, controllerProxy.TangoDevice, str( e)))
|
|
410
|
+
macro.abort()
|
|
411
|
+
return False
|
|
412
|
+
macro.output( "MsUtils.prepareDetectorAttrs: failed to create proxy to %s, %s, retry" %
|
|
413
|
+
(detectorName, controllerProxy.TangoDevice))
|
|
414
|
+
|
|
415
|
+
#
|
|
416
|
+
# ScanName, e.g.: au_012345
|
|
417
|
+
#
|
|
418
|
+
scanName = "%s_%05d" % (scan_file.split('.')[0], int( scan_id))
|
|
419
|
+
fileDirName = None
|
|
420
|
+
lst = ["FileDir", "SaveFilePath", "saving_directory"]
|
|
421
|
+
for elm in lst:
|
|
422
|
+
if TgUtils.proxyHasAttribute( tangoDevice_proxy, elm):
|
|
423
|
+
fileDirName = elm
|
|
424
|
+
break
|
|
425
|
+
else:
|
|
426
|
+
macro.output( "MsUtils.prepareDetectorAttrs: attribute %s is missing on %s" %
|
|
427
|
+
(str(lst), tangoDevice_proxy.name()))
|
|
428
|
+
return False
|
|
429
|
+
|
|
430
|
+
try:
|
|
431
|
+
rootDirSrv = tangoDevice_proxy.read_attribute( fileDirName).value
|
|
432
|
+
except Exception as e:
|
|
433
|
+
macro.output( "MsUtils.prepareDetectorAttrs: caught exception during reading %s of %s, %s" %
|
|
434
|
+
(fileDirName, tangoDevice_proxy.name(), str(e)))
|
|
435
|
+
return
|
|
436
|
+
|
|
437
|
+
if rootDirSrv is None:
|
|
438
|
+
macro.output( "MsUtils.prepareDetectorAttrs: rootDirSrv is None, fileDirName %s" % (fileDirName))
|
|
439
|
+
return
|
|
440
|
+
#
|
|
441
|
+
# see, if rootDir is compatible with the FileDir on the server
|
|
442
|
+
#
|
|
443
|
+
if rootDirSrv.find( rootDir) != 0:
|
|
444
|
+
macro.output( "MsUtils.prepareDetectorAttrs:")
|
|
445
|
+
macro.output( " %s: %s which is an attr of %s " % (fileDirName, rootDirSrv, tangoDevice_proxy.name()))
|
|
446
|
+
macro.output( " and")
|
|
447
|
+
macro.output( " rootDir: %s found in general_features" % (rootDir))
|
|
448
|
+
macro.output( " are incompatible")
|
|
449
|
+
macro.output( " Please fix it, maybe by changing the %s attribute in the detector server" % fileDirName)
|
|
450
|
+
macro.abort()
|
|
451
|
+
return False
|
|
452
|
+
|
|
453
|
+
macro.output( "MsUtils.prepareDetectorAttrs: device %s" % ( tangoDevice_proxy.name()))
|
|
454
|
+
#
|
|
455
|
+
# it is important to create the directory before it is written to the server
|
|
456
|
+
#
|
|
457
|
+
if rootDir[-1] == '/':
|
|
458
|
+
fileDir = rootDir + scanName + "/" + detectorName
|
|
459
|
+
else:
|
|
460
|
+
fileDir = rootDir + "/" + scanName + "/" + detectorName
|
|
461
|
+
macro.output( "MsUtils.prepareDetectorAttrs: creating %s %s (0o777)" % (fileDirName, fileDir))
|
|
462
|
+
try:
|
|
463
|
+
_os.makedirs( fileDir)
|
|
464
|
+
_os.chmod( fileDir, 0o777)
|
|
465
|
+
except Exception as e:
|
|
466
|
+
macro.output( "MsUtils.prepareDetectorAttrs: failed to create %s, %s" % (fileDir, e))
|
|
467
|
+
return False
|
|
468
|
+
macro.output( "MsUtils.prepareDetectorAttrs: setting %s to %s" % (fileDirName, fileDir))
|
|
469
|
+
try:
|
|
470
|
+
tangoDevice_proxy.write_attribute( fileDirName, fileDir)
|
|
471
|
+
except Exception as e:
|
|
472
|
+
macro.output( "MsUtils.prepareDetectorAttrs: caught exception writing %s to %s, %s " % \
|
|
473
|
+
(fileDir, fileDirName, tangoDevice_proxy.name()))
|
|
474
|
+
macro.output( "%s" % ( repr(e)))
|
|
475
|
+
return False
|
|
476
|
+
#
|
|
477
|
+
# FrameNumbers
|
|
478
|
+
#
|
|
479
|
+
set_nbframes = 1
|
|
480
|
+
nbFramesName = None
|
|
481
|
+
lst = ["NbFrames", "FrameNumbers", "acq_nb_frames"]
|
|
482
|
+
for elm in lst:
|
|
483
|
+
if TgUtils.proxyHasAttribute( tangoDevice_proxy, elm):
|
|
484
|
+
nbFramesName = elm
|
|
485
|
+
break
|
|
486
|
+
else:
|
|
487
|
+
set_nbframes = 0
|
|
488
|
+
|
|
489
|
+
if set_nbframes:
|
|
490
|
+
try:
|
|
491
|
+
tangoDevice_proxy.write_attribute( nbFramesName, nbFrames)
|
|
492
|
+
macro.output( "MsUtils.prepareDetectorAttrs: Number of frames set to 1")
|
|
493
|
+
except Exception as e:
|
|
494
|
+
macro.output( "MsUtils.prepareDetectorAttrs: caught exception writing to %s, %s, %s" % \
|
|
495
|
+
(nbFramesName, tangoDevice_proxy.name(), str(e)))
|
|
496
|
+
return False
|
|
497
|
+
#
|
|
498
|
+
# fileStartNum
|
|
499
|
+
#
|
|
500
|
+
fileStartNum = None
|
|
501
|
+
lst = ["FileStartNum", "saving_next_number", "FileIndex", "FileRefNumber"]
|
|
502
|
+
for elm in lst:
|
|
503
|
+
if TgUtils.proxyHasAttribute( tangoDevice_proxy, elm):
|
|
504
|
+
fileStartNum = elm
|
|
505
|
+
break
|
|
506
|
+
else:
|
|
507
|
+
macro.output( "MsUtils.prepareDetectorAttrs: attribute %s is missing on %s" %
|
|
508
|
+
(str(lst), tangoDevice_proxy.name()))
|
|
509
|
+
return False
|
|
510
|
+
|
|
511
|
+
try:
|
|
512
|
+
#
|
|
513
|
+
# P03, Jannik Woehnert: pscamera: FileRefNumber ist ein string
|
|
514
|
+
#
|
|
515
|
+
cfg = tangoDevice_proxy.get_attribute_config( fileStartNum)
|
|
516
|
+
if cfg.data_type == _PyTango.CmdArgType.DevString:
|
|
517
|
+
tangoDevice_proxy.write_attribute( fileStartNum, "0")
|
|
518
|
+
else:
|
|
519
|
+
tangoDevice_proxy.write_attribute( fileStartNum, 0)
|
|
520
|
+
except Exception as e:
|
|
521
|
+
macro.output( "MsUtils.prepareDetectorAttrs: caught exception writing to %s, %s, %s" %
|
|
522
|
+
(fileStartNum, tangoDevice_proxy.name(), str(e)))
|
|
523
|
+
return False
|
|
524
|
+
#
|
|
525
|
+
# FilePrefix
|
|
526
|
+
#
|
|
527
|
+
filePrefix = None
|
|
528
|
+
lst = ["FilePrefix", "saving_prefix"]
|
|
529
|
+
for elm in lst:
|
|
530
|
+
if TgUtils.proxyHasAttribute( tangoDevice_proxy, elm):
|
|
531
|
+
filePrefix = elm
|
|
532
|
+
#
|
|
533
|
+
# Lima does not provide the '_' between prefix and image number itself
|
|
534
|
+
#
|
|
535
|
+
if elm == "saving_prefix":
|
|
536
|
+
scanName += "_"
|
|
537
|
+
break
|
|
538
|
+
else:
|
|
539
|
+
macro.output( "MsUtils.prepareDetectorAttrs: attribute %s is missing on %s" %
|
|
540
|
+
( str(lst), tangoDevice_proxy.name()))
|
|
541
|
+
return False
|
|
542
|
+
|
|
543
|
+
try:
|
|
544
|
+
tangoDevice_proxy.write_attribute( filePrefix, scanName)
|
|
545
|
+
except Exception as e:
|
|
546
|
+
macro.output( "MsUtils.prepareDetectorAttrs: failed to set %s %s, %s, %s" %
|
|
547
|
+
(filePrefix, detectorName, scanName, str(e)))
|
|
548
|
+
return False
|
|
549
|
+
#
|
|
550
|
+
# ShutterTime
|
|
551
|
+
#
|
|
552
|
+
if acq_time is not None:
|
|
553
|
+
actTimeName = None
|
|
554
|
+
lst = ["ExtendedExposure", "ShutterTime"]
|
|
555
|
+
for elm in lst:
|
|
556
|
+
if TgUtils.proxyHasAttribute( tangoDevice_proxy, elm):
|
|
557
|
+
actTimeName = elm
|
|
558
|
+
break
|
|
559
|
+
if actTimeName is None:
|
|
560
|
+
macro.output( "MsUtils.prepareDetectorAttrs: device has no %s attributes" %
|
|
561
|
+
( detectorName, str(lst)))
|
|
562
|
+
return False
|
|
563
|
+
return False
|
|
564
|
+
|
|
565
|
+
try:
|
|
566
|
+
tangoDevice_proxy.write_attribute( actTimeName, acq_time)
|
|
567
|
+
except Exception as e:
|
|
568
|
+
macro.output( "MsUtils.prepareDetectorAttrs: failed to set %s %s to %s, %s" %
|
|
569
|
+
(detectorName, actTimeName, acq_time, repr( e)))
|
|
570
|
+
#
|
|
571
|
+
# TriggerMode: FreeRunning, ExtTrigger, Snapshot, TimedSnap, TrigSequence (Dalsa)
|
|
572
|
+
#
|
|
573
|
+
if trig_mode is not None:
|
|
574
|
+
lst = ["TriggerMode"]
|
|
575
|
+
trigModeName = None
|
|
576
|
+
for elm in lst:
|
|
577
|
+
if TgUtils.proxyHasAttribute( tangoDevice_proxy, elm):
|
|
578
|
+
trigModeName = elm
|
|
579
|
+
break
|
|
580
|
+
if trigModeName is None:
|
|
581
|
+
macro.output( "MsUtils.prepareDetectorAttrs: device has no %s attributes" %
|
|
582
|
+
( detectorName, str(lst)))
|
|
583
|
+
return False
|
|
584
|
+
try:
|
|
585
|
+
tangoDevice_proxy.write_attribute( trigModeName, trig_mode)
|
|
586
|
+
except Exception as e:
|
|
587
|
+
macro.output( "MsUtils.prepareDetectorAttrs: failed to set %s %s to %s, %s" %
|
|
588
|
+
(detectorName, trigModeName, trig_mode, repr( e)))
|
|
589
|
+
|
|
590
|
+
return True
|
|
591
|
+
|
|
592
|
+
def resetDetectorAttrs( macro, name = "pilatus", rootDir = "/ramdisk", do_check_if_detector_in_mg=True):
|
|
593
|
+
'''
|
|
594
|
+
resetDetectorAttrs() is intended to be use in post-scan hooks to
|
|
595
|
+
store imgages created by the 'ct' command in rootDir
|
|
596
|
+
|
|
597
|
+
FileDir|SaveFilePath|saving_directory: to <rootDir>
|
|
598
|
+
|
|
599
|
+
So far Pilatus, Lambda and Eiger servers are supported
|
|
600
|
+
'''
|
|
601
|
+
detectorName = name
|
|
602
|
+
|
|
603
|
+
if do_check_if_detector_in_mg and not isInMg( macro, detectorName):
|
|
604
|
+
macro.output( "MsUtils.resetDetectorAttrs: MG does not contain %s" % detectorName)
|
|
605
|
+
return True
|
|
606
|
+
|
|
607
|
+
clss = TgUtils.getClassNameByDevice( _findTangoDevice( macro, detectorName))
|
|
608
|
+
if clss == "EigerDectris":
|
|
609
|
+
return resetEigerDectrisAttrs( macro, name = detectorName)
|
|
610
|
+
|
|
611
|
+
tangoDevice_proxy = None
|
|
612
|
+
|
|
613
|
+
count = 0
|
|
614
|
+
while True:
|
|
615
|
+
try:
|
|
616
|
+
controllerProxy = _PyTango.DeviceProxy(detectorName)
|
|
617
|
+
temp = controllerProxy.read_attribute( "TangoDevice").value
|
|
618
|
+
tangoDevice_proxy = _PyTango.DeviceProxy( temp)
|
|
619
|
+
macro.debug("MsUtils.resetDetectorAttrs: %s found in active MG" % detectorName)
|
|
620
|
+
break
|
|
621
|
+
except:
|
|
622
|
+
count += 1
|
|
623
|
+
if count > 5:
|
|
624
|
+
macro.output( "MsUtils.resetDetectorAttrs: failed to create proxy to %s, %s" %
|
|
625
|
+
(detectorName, controllerProxy.TangoDevice))
|
|
626
|
+
macro.abort()
|
|
627
|
+
return False
|
|
628
|
+
macro.output( "MsUtils.resetDetectorAttrs: failed to create proxy to %s, %s, retry" %
|
|
629
|
+
(detectorName, controllerProxy.TangoDevice))
|
|
630
|
+
|
|
631
|
+
fileDirName = None
|
|
632
|
+
lst = ["FileDir", "SaveFilePath", "saving_directory"]
|
|
633
|
+
for elm in lst:
|
|
634
|
+
if TgUtils.proxyHasAttribute( tangoDevice_proxy, elm):
|
|
635
|
+
fileDirName = elm
|
|
636
|
+
break
|
|
637
|
+
else:
|
|
638
|
+
macro.output( "MsUtils.resetDetectorAttrs: attribute %s is missing on %s" %
|
|
639
|
+
(str(lst), tangoDevice_proxy.name()))
|
|
640
|
+
return False
|
|
641
|
+
|
|
642
|
+
try:
|
|
643
|
+
rootDirSrv = tangoDevice_proxy.read_attribute( fileDirName).value
|
|
644
|
+
except Exception:
|
|
645
|
+
macro.output( "MsUtils.resetDetectorAttrs: caught exception during reading FileDir of %s" %
|
|
646
|
+
tangoDevice_proxy.name())
|
|
647
|
+
|
|
648
|
+
try:
|
|
649
|
+
tangoDevice_proxy.write_attribute( fileDirName, rootDir)
|
|
650
|
+
except Exception as e:
|
|
651
|
+
macro.output( "MsUtils.resetDetectorAttrs: caught exception writing %s to %s, %s " % \
|
|
652
|
+
(fileDir, fileDirName, tangoDevice_proxy.name()))
|
|
653
|
+
macro.output( "%s" % ( repr(e)))
|
|
654
|
+
return False
|
|
655
|
+
|
|
656
|
+
return True
|
|
657
|
+
|
|
658
|
+
def isInMg( macro, detectorName):
|
|
659
|
+
'''
|
|
660
|
+
getObj() disables Ctrl-Cs
|
|
661
|
+
'''
|
|
662
|
+
import sardana.macroserver.macro as _ms
|
|
663
|
+
_ms.Type = TgUtils.TypeNames()
|
|
664
|
+
|
|
665
|
+
active_mg = macro.getEnv("ActiveMntGrp")
|
|
666
|
+
try:
|
|
667
|
+
mg = macro.getObj(active_mg, type_class=_ms.Type.MeasurementGroup)
|
|
668
|
+
except Exception as e:
|
|
669
|
+
macro.output( "MsUtils.isInMg: getObj active_mg exception %s, aborting" % e)
|
|
670
|
+
macro.abort()
|
|
671
|
+
return False
|
|
672
|
+
|
|
673
|
+
channels = mg.getChannelLabels()
|
|
674
|
+
if detectorName in channels:
|
|
675
|
+
return True
|
|
676
|
+
return False
|
|
677
|
+
|
|
678
|
+
def isInMgWOgetObj( macro, detectorName):
|
|
679
|
+
'''
|
|
680
|
+
returns True, if detectorName in in the ActiveMntGrp
|
|
681
|
+
'''
|
|
682
|
+
active_mg = macro.getEnv("ActiveMntGrp")
|
|
683
|
+
try:
|
|
684
|
+
mg = _PyTango.DeviceProxy( active_mg)
|
|
685
|
+
except Exception as e:
|
|
686
|
+
macro.output( "MsUtils.isInMg: failed to create a proxy to %s, %s, aborting" % (active_mg, e))
|
|
687
|
+
macro.abort()
|
|
688
|
+
return False
|
|
689
|
+
channels = mg.read_attribute( "ElementList").value
|
|
690
|
+
if detectorName in channels:
|
|
691
|
+
return True
|
|
692
|
+
return False
|
|
693
|
+
|
|
694
|
+
def testImportOld( filename):
|
|
695
|
+
"""
|
|
696
|
+
uses 'import importlib.util'
|
|
697
|
+
returns (True, ""), if filename can be imported
|
|
698
|
+
returns (False, "exception-string") otherwise
|
|
699
|
+
"""
|
|
700
|
+
import importlib.util
|
|
701
|
+
|
|
702
|
+
status = True
|
|
703
|
+
msg = ""
|
|
704
|
+
try:
|
|
705
|
+
spec = importlib.util.spec_from_file_location( '', filename)
|
|
706
|
+
a = importlib.util.module_from_spec(spec)
|
|
707
|
+
spec.loader.exec_module(a)
|
|
708
|
+
except Exception as e:
|
|
709
|
+
status = False
|
|
710
|
+
msg = repr( e)
|
|
711
|
+
finally:
|
|
712
|
+
pass
|
|
713
|
+
|
|
714
|
+
return( status, msg)
|
|
715
|
+
|
|
716
|
+
def testImport( filename):
|
|
717
|
+
"""
|
|
718
|
+
uses importlib.import_module to see whether a python
|
|
719
|
+
file can be importet
|
|
720
|
+
|
|
721
|
+
returns (True, ""), if filename can be imported
|
|
722
|
+
returns (False, "exception-string") otherwise
|
|
723
|
+
|
|
724
|
+
Works at least on Debian-11 and Debian-12
|
|
725
|
+
"""
|
|
726
|
+
import importlib
|
|
727
|
+
|
|
728
|
+
dirName = _os.path.dirname( filename)
|
|
729
|
+
baseName = _os.path.basename( filename)
|
|
730
|
+
|
|
731
|
+
prefixName = baseName
|
|
732
|
+
if baseName.find( '.py') > 0:
|
|
733
|
+
prefixName = baseName.rpartition('.')[0]
|
|
734
|
+
|
|
735
|
+
if dirName not in _sys.path:
|
|
736
|
+
_sys.path.insert( 0, dirName)
|
|
737
|
+
|
|
738
|
+
status = True
|
|
739
|
+
msg = ""
|
|
740
|
+
try:
|
|
741
|
+
mod = importlib.import_module( prefixName)
|
|
742
|
+
except Exception as e:
|
|
743
|
+
msg = repr( e)
|
|
744
|
+
status = False
|
|
745
|
+
|
|
746
|
+
return (status, msg)
|
|
747
|
+
|
|
748
|
+
def getModule( filename):
|
|
749
|
+
"""
|
|
750
|
+
returns the module or None
|
|
751
|
+
"""
|
|
752
|
+
import importlib.util
|
|
753
|
+
|
|
754
|
+
status = True
|
|
755
|
+
msg = ""
|
|
756
|
+
try:
|
|
757
|
+
spec = importlib.util.spec_from_file_location( '', filename)
|
|
758
|
+
a = importlib.util.module_from_spec(spec)
|
|
759
|
+
spec.loader.exec_module(a)
|
|
760
|
+
except Exception as e:
|
|
761
|
+
a = None
|
|
762
|
+
|
|
763
|
+
return( a)
|
|
764
|
+
#
|
|
765
|
+
# ===
|
|
766
|
+
#
|
|
767
|
+
def _appendAbs( scanInfo, mot, start, stop, intervals = None):
|
|
768
|
+
'''
|
|
769
|
+
function to append absolute scans to the scanInfo
|
|
770
|
+
ascan exp_dmy01 0 10 10 0.1
|
|
771
|
+
|
|
772
|
+
extend the motor array of scanInfo by an entry of the kind
|
|
773
|
+
{ name: someName,
|
|
774
|
+
start: the start of the scan
|
|
775
|
+
stop: the stop of the scan
|
|
776
|
+
}
|
|
777
|
+
'''
|
|
778
|
+
mDct = {}
|
|
779
|
+
mDct['name'] = mot
|
|
780
|
+
mDct['start'] = float( start)
|
|
781
|
+
mDct['stop'] = float( stop)
|
|
782
|
+
if intervals is not None:
|
|
783
|
+
mDct['intervals'] = int( intervals)
|
|
784
|
+
scanInfo[ 'motors'].append( mDct)
|
|
785
|
+
return
|
|
786
|
+
#
|
|
787
|
+
# ===
|
|
788
|
+
#
|
|
789
|
+
def _appendRel( scanInfo, mot, left, right, intervals = None):
|
|
790
|
+
'''
|
|
791
|
+
function to append relative scans to the scanInfo
|
|
792
|
+
dscan exp_dmy01 -1 1 10 0.1
|
|
793
|
+
|
|
794
|
+
extend the motor array of scanInfo by an entry of the kind
|
|
795
|
+
{ name: someName,
|
|
796
|
+
start: the start of the scan
|
|
797
|
+
stop: the stop of the scan
|
|
798
|
+
}
|
|
799
|
+
'''
|
|
800
|
+
mDct = {}
|
|
801
|
+
mDct['name'] = mot
|
|
802
|
+
try:
|
|
803
|
+
p = _PyTango.DeviceProxy( mDct[ 'name'])
|
|
804
|
+
except Exception as e:
|
|
805
|
+
print( "MsUtils._appendRel: failed to create proxy to %s" % mDct['name'])
|
|
806
|
+
mDct['start'] = p.position + float( left)
|
|
807
|
+
mDct['stop'] = p.position + float( right)
|
|
808
|
+
if intervals is not None:
|
|
809
|
+
mDct['intervals'] = int( intervals)
|
|
810
|
+
scanInfo[ 'motors'].append( mDct)
|
|
811
|
+
return
|
|
812
|
+
|
|
813
|
+
def getScanFileName():
|
|
814
|
+
'''
|
|
815
|
+
returns the file name used by the last scan
|
|
816
|
+
returns None, if the file does not exist
|
|
817
|
+
|
|
818
|
+
uses the MacroServer environment variables: ScanDir, ScanFilem ScanID
|
|
819
|
+
'''
|
|
820
|
+
scanDir = TgUtils.getEnv( "ScanDir")
|
|
821
|
+
scanFile = TgUtils.getEnv( "ScanFile")
|
|
822
|
+
scanID = TgUtils.getEnv( "ScanID")
|
|
823
|
+
|
|
824
|
+
if type( scanFile) is list:
|
|
825
|
+
scanFileTemp = scanFile[0]
|
|
826
|
+
else:
|
|
827
|
+
scanFileTemp = scanFile
|
|
828
|
+
#
|
|
829
|
+
# ['tst.fio'] -> ['tst', 'fio']
|
|
830
|
+
#
|
|
831
|
+
lst = scanFileTemp.split( ".")
|
|
832
|
+
|
|
833
|
+
fileName = "%s/%s_%05d.%s" % ( scanDir, lst[0], int( scanID), lst[1])
|
|
834
|
+
|
|
835
|
+
if not _os.path.exists( fileName):
|
|
836
|
+
argout = None
|
|
837
|
+
else:
|
|
838
|
+
argout = fileName
|
|
839
|
+
|
|
840
|
+
return fileName
|
|
841
|
+
|
|
842
|
+
#
|
|
843
|
+
# ===
|
|
844
|
+
#
|
|
845
|
+
def createScanInfo( title = None):
|
|
846
|
+
'''
|
|
847
|
+
Depending on whether createScanInfo() is called in an after-scan-scenario or
|
|
848
|
+
a pre-scan-scenario the title has to be supplied or not.
|
|
849
|
+
|
|
850
|
+
title == None (after-scan-scenario): the function takes the title from ScanHistory
|
|
851
|
+
returns None, if ScanID != serialno (history), probably because
|
|
852
|
+
the last scan has been aborted (ctrl-c)
|
|
853
|
+
|
|
854
|
+
title != None (pre-scan-scenario): if ScanHistory is not valid because createScanInfo()
|
|
855
|
+
is called from a hook, the title has to be supplied.
|
|
856
|
+
|
|
857
|
+
pre_scan_hook example:
|
|
858
|
+
scanInfo = HasyUtils.createScanInfo( self.getParentMacro().getCommand())
|
|
859
|
+
|
|
860
|
+
returns a data structure describing the scan, see below, used e.g. mvsa and CursorApp
|
|
861
|
+
|
|
862
|
+
{'motors': [{'name': 'exp_dmy01', 'start': 0.0, 'stop': 10.0}],
|
|
863
|
+
'title': 'ascan exp_dmy01 0.0 10.0 10 1.0',
|
|
864
|
+
'serialno': 1502,
|
|
865
|
+
'intervals': 10,
|
|
866
|
+
'nPts': 11,
|
|
867
|
+
'sampleTime': 1.0}
|
|
868
|
+
|
|
869
|
+
{'motors': [{'name': 'exp_dmy01', 'start': 0.0, 'stop': 10.0},
|
|
870
|
+
{'name': 'exp_dmy02', 'start': 2.0, 'stop': 3.0}],
|
|
871
|
+
'title': 'a2scan exp_dmy01 0.0 10.0 exp_dmy02 2.0 3.0 3 1.0',
|
|
872
|
+
'serialno': 1503,
|
|
873
|
+
'intervals': 3,
|
|
874
|
+
'nPts': 4,
|
|
875
|
+
'sampleTime': 1.0}
|
|
876
|
+
|
|
877
|
+
{'motors': [{'name': 'exp_dmy01', 'start': 0.0, 'stop': 1.0, 'intervals': 2},
|
|
878
|
+
{'name': 'exp_dmy02', 'start': 2.0, 'stop': 3.0, 'intervals': 3}],
|
|
879
|
+
'title': 'mesh exp_dmy01 0.0 1.0 2 exp_dmy02 2.0 3.0 3 0.1 False None',
|
|
880
|
+
'serialno': 1504,
|
|
881
|
+
'nPts': 12,
|
|
882
|
+
'sampleTime': 0.1}
|
|
883
|
+
|
|
884
|
+
serialno is taken from the environment.
|
|
885
|
+
nPts is normally (intervals + 1). For mesh scans it is the
|
|
886
|
+
total no. of points in the mesh
|
|
887
|
+
'''
|
|
888
|
+
#print( "MsUtils.createScanInfo: title %s" % repr(title))
|
|
889
|
+
env = TgUtils.getEnvDct()
|
|
890
|
+
scanInfo = {}
|
|
891
|
+
scanInfo[ 'motors'] = []
|
|
892
|
+
#
|
|
893
|
+
# 1. case: after a scan, ScanHistory can be used
|
|
894
|
+
#
|
|
895
|
+
if title is None:
|
|
896
|
+
if 'ScanHistory' not in list( env.keys()):
|
|
897
|
+
return None
|
|
898
|
+
lastScan = env['ScanHistory'][-1]
|
|
899
|
+
|
|
900
|
+
scanInfo[ 'serialno'] = lastScan['serialno']
|
|
901
|
+
#
|
|
902
|
+
# serialno is from ScanHistory which is created after the scan completed successfully
|
|
903
|
+
# ScanID is updated when a scan starts. ScanID != sericalno may be an indication
|
|
904
|
+
# that the last scan has been ctrl-c'ed
|
|
905
|
+
#
|
|
906
|
+
if TgUtils.getEnv( "ScanID") != scanInfo['serialno']:
|
|
907
|
+
return None
|
|
908
|
+
scanInfo[ 'title'] = lastScan['title']
|
|
909
|
+
#
|
|
910
|
+
# 2. case: from e.g. a hook
|
|
911
|
+
#
|
|
912
|
+
else:
|
|
913
|
+
if type( title) is str:
|
|
914
|
+
scanInfo[ 'title'] = title
|
|
915
|
+
scanInfo[ 'serialno'] = env['ScanID']
|
|
916
|
+
else:
|
|
917
|
+
return None
|
|
918
|
+
|
|
919
|
+
scanTitleToScanInfo( scanInfo[ 'title'], scanInfo)
|
|
920
|
+
|
|
921
|
+
#print( "MsUtils.createScanInfo %s " % repr( scanInfo))
|
|
922
|
+
return scanInfo
|
|
923
|
+
#
|
|
924
|
+
#
|
|
925
|
+
#
|
|
926
|
+
def scanTitleToScanInfo( title, scanInfo):
|
|
927
|
+
|
|
928
|
+
#print( "MsUtils.py: this is scanTitleToScanInfo, title %s" % title)
|
|
929
|
+
|
|
930
|
+
#
|
|
931
|
+
# if bad syntrax for fscan commands, indepvar contain spaces
|
|
932
|
+
#
|
|
933
|
+
if title is None:
|
|
934
|
+
return
|
|
935
|
+
|
|
936
|
+
lst = title.split()
|
|
937
|
+
#
|
|
938
|
+
# ascan exp_dmy01 0 1 10 0.1
|
|
939
|
+
#
|
|
940
|
+
if lst[0] == 'ascan':
|
|
941
|
+
_appendAbs( scanInfo, lst[1], lst[2], lst[3])
|
|
942
|
+
scanInfo[ 'intervals'] = int( lst[4])
|
|
943
|
+
scanInfo[ 'nPts'] = int( lst[4]) + 1
|
|
944
|
+
scanInfo[ 'sampleTime'] = float( lst[5])
|
|
945
|
+
#
|
|
946
|
+
# a2scan exp_dmy01 0 1 exp_dmy02 0 2 10 0.1
|
|
947
|
+
#
|
|
948
|
+
elif lst[0] == 'a2scan':
|
|
949
|
+
_appendAbs( scanInfo, lst[1], lst[2], lst[3])
|
|
950
|
+
_appendAbs( scanInfo, lst[4], lst[5], lst[6])
|
|
951
|
+
scanInfo[ 'intervals'] = int( lst[7])
|
|
952
|
+
scanInfo[ 'nPts'] = int( lst[7]) + 1
|
|
953
|
+
scanInfo[ 'sampleTime'] = float( lst[8])
|
|
954
|
+
#
|
|
955
|
+
# a3scan exp_dmy01 0 1 exp_dmy02 0 2 ... 10 0.1
|
|
956
|
+
#
|
|
957
|
+
elif lst[0] == 'a3scan':
|
|
958
|
+
_appendAbs( scanInfo, lst[1], lst[2], lst[3])
|
|
959
|
+
_appendAbs( scanInfo, lst[4], lst[5], lst[6])
|
|
960
|
+
_appendAbs( scanInfo, lst[7], lst[8], lst[9])
|
|
961
|
+
scanInfo[ 'intervals'] = int( lst[10])
|
|
962
|
+
scanInfo[ 'nPts'] = int( lst[10]) + 1
|
|
963
|
+
scanInfo[ 'sampleTime'] = float( lst[11])
|
|
964
|
+
|
|
965
|
+
#
|
|
966
|
+
# ascan_repeat exp_dmy01 0 1 10 0.1 2
|
|
967
|
+
#
|
|
968
|
+
elif lst[0] == 'ascan_repeat':
|
|
969
|
+
_appendAbs( scanInfo, lst[1], lst[2], lst[3])
|
|
970
|
+
scanInfo[ 'intervals'] = int( lst[4])
|
|
971
|
+
scanInfo[ 'nPts'] = int( lst[4]) + 1
|
|
972
|
+
scanInfo[ 'sampleTime'] = float( lst[5])
|
|
973
|
+
scanInfo[ 'repeats'] = int( lst[6])
|
|
974
|
+
#
|
|
975
|
+
# hscan 1.0 1.1 20 0.1
|
|
976
|
+
#
|
|
977
|
+
elif lst[0] == 'hscan':
|
|
978
|
+
if TgUtils.isDevice( 'e6cctrl_h'):
|
|
979
|
+
_appendAbs( scanInfo, 'e6cctrl_h', lst[1], lst[2])
|
|
980
|
+
elif TgUtils.isDevice( 'kozhue6cctrl_h'):
|
|
981
|
+
_appendAbs( scanInfo, 'kozhue6cctrl_h', lst[1], lst[2])
|
|
982
|
+
scanInfo[ 'intervals'] = int( lst[3])
|
|
983
|
+
scanInfo[ 'nPts'] = int( lst[3]) + 1
|
|
984
|
+
scanInfo[ 'sampleTime'] = float( lst[4])
|
|
985
|
+
elif lst[0] == 'kscan':
|
|
986
|
+
if TgUtils.isDevice( 'e6cctrl_k'):
|
|
987
|
+
_appendAbs( scanInfo, 'e6cctrl_k', lst[1], lst[2])
|
|
988
|
+
elif TgUtils.isDevice( 'kozhue6cctrl_k'):
|
|
989
|
+
_appendAbs( scanInfo, 'kozhue6cctrl_k', lst[1], lst[2])
|
|
990
|
+
scanInfo[ 'intervals'] = int( lst[3])
|
|
991
|
+
scanInfo[ 'nPts'] = int( lst[3]) + 1
|
|
992
|
+
scanInfo[ 'sampleTime'] = float( lst[4])
|
|
993
|
+
elif lst[0] == 'lscan':
|
|
994
|
+
if TgUtils.isDevice( 'e6cctrl_l'):
|
|
995
|
+
_appendAbs( scanInfo, 'e6cctrl_l', lst[1], lst[2])
|
|
996
|
+
elif TgUtils.isDevice( 'kozhue6cctrl_l'):
|
|
997
|
+
_appendAbs( scanInfo, 'kozhue6cctrl_l', lst[1], lst[2])
|
|
998
|
+
scanInfo[ 'intervals'] = int( lst[3])
|
|
999
|
+
scanInfo[ 'nPts'] = int( lst[3]) + 1
|
|
1000
|
+
scanInfo[ 'sampleTime'] = float( lst[4])
|
|
1001
|
+
|
|
1002
|
+
#
|
|
1003
|
+
# hklscan 1.0 1.1 2 2.2 3 3.3 20 0.1
|
|
1004
|
+
#
|
|
1005
|
+
elif lst[0] == 'hklscan':
|
|
1006
|
+
diffH = _math.fabs( float( lst[2]) - float( lst[1]))
|
|
1007
|
+
diffK = _math.fabs( float( lst[4]) - float( lst[3]))
|
|
1008
|
+
diffL = _math.fabs( float( lst[6]) - float( lst[5]))
|
|
1009
|
+
if diffH > diffK and diffH > diffL:
|
|
1010
|
+
if TgUtils.isDevice( 'e6cctrl_h'):
|
|
1011
|
+
_appendAbs( scanInfo, 'e6cctrl_h', lst[1], lst[2])
|
|
1012
|
+
elif TgUtils.isDevice( 'kozhue6cctrl_h'):
|
|
1013
|
+
_appendAbs( scanInfo, 'kozhue6cctrl_h', lst[1], lst[2])
|
|
1014
|
+
if TgUtils.isDevice( 'e6cctrl_k'):
|
|
1015
|
+
_appendAbs( scanInfo, 'e6cctrl_k', lst[3], lst[4])
|
|
1016
|
+
elif TgUtils.isDevice( 'kozhue6cctrl_k'):
|
|
1017
|
+
_appendAbs( scanInfo, 'kozhue6cctrl_k', lst[3], lst[4])
|
|
1018
|
+
if TgUtils.isDevice( 'e6cctrl_l'):
|
|
1019
|
+
_appendAbs( scanInfo, 'e6cctrl_l', lst[5], lst[6])
|
|
1020
|
+
elif TgUtils.isDevice( 'kozhue6cctrl_l'):
|
|
1021
|
+
_appendAbs( scanInfo, 'kozhue6cctrl_l', lst[5], lst[6])
|
|
1022
|
+
elif diffK > diffH and diffK > diffL:
|
|
1023
|
+
if TgUtils.isDevice( 'e6cctrl_k'):
|
|
1024
|
+
_appendAbs( scanInfo, 'e6cctrl_k', lst[3], lst[4])
|
|
1025
|
+
elif TgUtils.isDevice( 'kozhue6cctrl_k'):
|
|
1026
|
+
_appendAbs( scanInfo, 'kozhue6cctrl_k', lst[3], lst[4])
|
|
1027
|
+
if TgUtils.isDevice( 'e6cctrl_h'):
|
|
1028
|
+
_appendAbs( scanInfo, 'e6cctrl_h', lst[1], lst[2])
|
|
1029
|
+
elif TgUtils.isDevice( 'kozhue6cctrl_h'):
|
|
1030
|
+
_appendAbs( scanInfo, 'kozhue6cctrl_h', lst[1], lst[2])
|
|
1031
|
+
if TgUtils.isDevice( 'e6cctrl_l'):
|
|
1032
|
+
_appendAbs( scanInfo, 'e6cctrl_l', lst[5], lst[6])
|
|
1033
|
+
elif TgUtils.isDevice( 'kozhue6cctrl_l'):
|
|
1034
|
+
_appendAbs( scanInfo, 'kozhue6cctrl_l', lst[5], lst[6])
|
|
1035
|
+
elif diffL > diffH and diffL > diffK:
|
|
1036
|
+
if TgUtils.isDevice( 'e6cctrl_l'):
|
|
1037
|
+
_appendAbs( scanInfo, 'e6cctrl_l', lst[5], lst[6])
|
|
1038
|
+
elif TgUtils.isDevice( 'kozhue6cctrl_l'):
|
|
1039
|
+
_appendAbs( scanInfo, 'kozhue6cctrl_l', lst[5], lst[6])
|
|
1040
|
+
if TgUtils.isDevice( 'e6cctrl_h'):
|
|
1041
|
+
_appendAbs( scanInfo, 'e6cctrl_h', lst[1], lst[2])
|
|
1042
|
+
elif TgUtils.isDevice( 'kozhue6cctrl_h'):
|
|
1043
|
+
_appendAbs( scanInfo, 'kozhue6cctrl_h', lst[1], lst[2])
|
|
1044
|
+
if TgUtils.isDevice( 'e6cctrl_k'):
|
|
1045
|
+
_appendAbs( scanInfo, 'e6cctrl_k', lst[3], lst[4])
|
|
1046
|
+
elif TgUtils.isDevice( 'kozhue6cctrl_k'):
|
|
1047
|
+
_appendAbs( scanInfo, 'kozhue6cctrl_k', lst[3], lst[4])
|
|
1048
|
+
elif diffH > 0.:
|
|
1049
|
+
if TgUtils.isDevice( 'e6cctrl_h'):
|
|
1050
|
+
_appendAbs( scanInfo, 'e6cctrl_h', lst[1], lst[2])
|
|
1051
|
+
elif TgUtils.isDevice( 'kozhue6cctrl_h'):
|
|
1052
|
+
_appendAbs( scanInfo, 'kozhue6cctrl_h', lst[1], lst[2])
|
|
1053
|
+
if TgUtils.isDevice( 'e6cctrl_k'):
|
|
1054
|
+
_appendAbs( scanInfo, 'e6cctrl_k', lst[3], lst[4])
|
|
1055
|
+
elif TgUtils.isDevice( 'kozhue6cctrl_k'):
|
|
1056
|
+
_appendAbs( scanInfo, 'kozhue6cctrl_k', lst[3], lst[4])
|
|
1057
|
+
if TgUtils.isDevice( 'e6cctrl_l'):
|
|
1058
|
+
_appendAbs( scanInfo, 'e6cctrl_l', lst[5], lst[6])
|
|
1059
|
+
elif TgUtils.isDevice( 'kozhue6cctrl_l'):
|
|
1060
|
+
_appendAbs( scanInfo, 'kozhue6cctrl_l', lst[5], lst[6])
|
|
1061
|
+
elif diffK > 0.:
|
|
1062
|
+
if TgUtils.isDevice( 'e6cctrl_k'):
|
|
1063
|
+
_appendAbs( scanInfo, 'e6cctrl_k', lst[3], lst[4])
|
|
1064
|
+
elif TgUtils.isDevice( 'kozhue6cctrl_k'):
|
|
1065
|
+
_appendAbs( scanInfo, 'kozhue6cctrl_k', lst[3], lst[4])
|
|
1066
|
+
if TgUtils.isDevice( 'e6cctrl_h'):
|
|
1067
|
+
_appendAbs( scanInfo, 'e6cctrl_h', lst[1], lst[2])
|
|
1068
|
+
elif TgUtils.isDevice( 'kozhue6cctrl_h'):
|
|
1069
|
+
_appendAbs( scanInfo, 'kozhue6cctrl_h', lst[1], lst[2])
|
|
1070
|
+
if TgUtils.isDevice( 'e6cctrl_l'):
|
|
1071
|
+
_appendAbs( scanInfo, 'e6cctrl_l', lst[5], lst[6])
|
|
1072
|
+
elif TgUtils.isDevice( 'kozhue6cctrl_l'):
|
|
1073
|
+
_appendAbs( scanInfo, 'kozhue6cctrl_l', lst[5], lst[6])
|
|
1074
|
+
else:
|
|
1075
|
+
if TgUtils.isDevice( 'e6cctrl_l'):
|
|
1076
|
+
_appendAbs( scanInfo, 'e6cctrl_l', lst[5], lst[6])
|
|
1077
|
+
elif TgUtils.isDevice( 'kozhue6cctrl_l'):
|
|
1078
|
+
_appendAbs( scanInfo, 'kozhue6cctrl_l', lst[5], lst[6])
|
|
1079
|
+
if TgUtils.isDevice( 'e6cctrl_h'):
|
|
1080
|
+
_appendAbs( scanInfo, 'e6cctrl_h', lst[1], lst[2])
|
|
1081
|
+
elif TgUtils.isDevice( 'kozhue6cctrl_h'):
|
|
1082
|
+
_appendAbs( scanInfo, 'kozhue6cctrl_h', lst[1], lst[2])
|
|
1083
|
+
if TgUtils.isDevice( 'e6cctrl_k'):
|
|
1084
|
+
_appendAbs( scanInfo, 'e6cctrl_k', lst[3], lst[4])
|
|
1085
|
+
elif TgUtils.isDevice( 'kozhue6cctrl_k'):
|
|
1086
|
+
_appendAbs( scanInfo, 'kozhue6cctrl_k', lst[3], lst[4])
|
|
1087
|
+
scanInfo[ 'intervals'] = int( lst[7])
|
|
1088
|
+
scanInfo[ 'nPts'] = int( lst[7]) + 1
|
|
1089
|
+
scanInfo[ 'sampleTime'] = float( lst[8])
|
|
1090
|
+
#
|
|
1091
|
+
# dscan exp_dmy01 -1 1 10 0.1
|
|
1092
|
+
#
|
|
1093
|
+
elif lst[0] == 'dscan':
|
|
1094
|
+
_appendRel( scanInfo, lst[1], lst[2], lst[3])
|
|
1095
|
+
scanInfo[ 'intervals'] = int( lst[4])
|
|
1096
|
+
scanInfo[ 'nPts'] = int( lst[4]) + 1
|
|
1097
|
+
scanInfo[ 'sampleTime'] = float( lst[5])
|
|
1098
|
+
#
|
|
1099
|
+
# d2scan exp_dmy01 0 1 exp_dmy02 0 2 10 0.1
|
|
1100
|
+
#
|
|
1101
|
+
elif lst[0] == 'd2scan':
|
|
1102
|
+
_appendRel( scanInfo, lst[1], lst[2], lst[3])
|
|
1103
|
+
_appendRel( scanInfo, lst[4], lst[5], lst[6])
|
|
1104
|
+
scanInfo[ 'intervals'] = int( lst[7])
|
|
1105
|
+
scanInfo[ 'nPts'] = int( lst[7]) + 1
|
|
1106
|
+
scanInfo[ 'sampleTime'] = float( lst[8])
|
|
1107
|
+
#
|
|
1108
|
+
# d3scan exp_dmy01 0 1 exp_dmy02 0 2 ... 10 0.1
|
|
1109
|
+
#
|
|
1110
|
+
elif lst[0] == 'd3scan':
|
|
1111
|
+
_appendRel( scanInfo, lst[1], lst[2], lst[3])
|
|
1112
|
+
_appendRel( scanInfo, lst[4], lst[5], lst[6])
|
|
1113
|
+
_appendRel( scanInfo, lst[7], lst[8], lst[9])
|
|
1114
|
+
scanInfo[ 'intervals'] = int( lst[10])
|
|
1115
|
+
scanInfo[ 'nPts'] = int( lst[10]) + 1
|
|
1116
|
+
scanInfo[ 'sampleTime'] = float( lst[11])
|
|
1117
|
+
|
|
1118
|
+
#
|
|
1119
|
+
# dscan_repeat exp_dmy01 -1 1 10 0.1 2
|
|
1120
|
+
#
|
|
1121
|
+
elif lst[0] == 'dscan_repeat':
|
|
1122
|
+
_appendRel( scanInfo, lst[1], lst[2], lst[3])
|
|
1123
|
+
scanInfo[ 'intervals'] = int( lst[4])
|
|
1124
|
+
scanInfo[ 'nPts'] = int( lst[4]) + 1
|
|
1125
|
+
scanInfo[ 'sampleTime'] = float( lst[5])
|
|
1126
|
+
scanInfo[ 'repeats'] = int( lst[6])
|
|
1127
|
+
#
|
|
1128
|
+
# mesh exp_dmy01 0 1 10 exp_dmy02 1 2 12 0.1
|
|
1129
|
+
#
|
|
1130
|
+
elif lst[0] == 'mesh':
|
|
1131
|
+
_appendAbs( scanInfo, lst[1], lst[2], lst[3], lst[4])
|
|
1132
|
+
_appendAbs( scanInfo, lst[5], lst[6], lst[7], lst[8])
|
|
1133
|
+
scanInfo[ 'nPts'] = (int( lst[4]) + 1)*(int( lst[8]) + 1)
|
|
1134
|
+
scanInfo[ 'sampleTime'] = float( lst[9])
|
|
1135
|
+
#
|
|
1136
|
+
# dmesh exp_dmy01 1 1 10 exp_dmy02 -1 2 12 0.1
|
|
1137
|
+
#
|
|
1138
|
+
elif lst[0] == 'dmesh':
|
|
1139
|
+
_appendRel( scanInfo, lst[1], lst[2], lst[3], lst[4])
|
|
1140
|
+
_appendRel( scanInfo, lst[5], lst[6], lst[7], lst[8])
|
|
1141
|
+
scanInfo[ 'nPts'] = (int( lst[4]) + 1)*(int( lst[8]) + 1)
|
|
1142
|
+
scanInfo[ 'sampleTime'] = float( lst[9])
|
|
1143
|
+
#
|
|
1144
|
+
# timescan 10 0.1
|
|
1145
|
+
#
|
|
1146
|
+
elif lst[0] == 'timescan':
|
|
1147
|
+
scanInfo[ 'intervals'] = int( lst[1])
|
|
1148
|
+
scanInfo[ 'nPts'] = int( lst[1]) + 1
|
|
1149
|
+
scanInfo[ 'sampleTime'] = float( lst[2])
|
|
1150
|
+
#
|
|
1151
|
+
# fscan np=1500 0.1 exp_dmy01 exp_dmy02, this is a fake because I do not calculate start/stop for fscans
|
|
1152
|
+
# the real syntax: fscan "x=[1,3,5,7,9],y=arange(5)" 0.1 exp_dmy01 x**2 exp_dmy02 sqrt(y*x+3)
|
|
1153
|
+
#
|
|
1154
|
+
elif lst[0] == 'fscan':
|
|
1155
|
+
#np = int( lst[1].split( '=')[1])
|
|
1156
|
+
np = 1500
|
|
1157
|
+
nPts = 1
|
|
1158
|
+
for mot in lst[ 3:]:
|
|
1159
|
+
_appendAbs( scanInfo, mot, 0, 100, intervals = np)
|
|
1160
|
+
nPts = nPts*(np + 1)
|
|
1161
|
+
try:
|
|
1162
|
+
scanInfo[ 'sampleTime'] = float( lst[2])
|
|
1163
|
+
scanInfo[ 'nPts'] = nPts
|
|
1164
|
+
except:
|
|
1165
|
+
scanInfo[ 'sampleTime'] = -1
|
|
1166
|
+
scanInfo[ 'nPts'] = -1
|
|
1167
|
+
else:
|
|
1168
|
+
pass
|
|
1169
|
+
#raise ValueError( "MsUtils.scanTitleToScanInfo: failed to identify scan type %s" % lst[0])
|
|
1170
|
+
|
|
1171
|
+
return
|
|
1172
|
+
#
|
|
1173
|
+
# ===
|
|
1174
|
+
#
|
|
1175
|
+
def repairFscanTitle( title):
|
|
1176
|
+
#
|
|
1177
|
+
# u"fscan x=[0,1,2],y=[10,11,12] 0.1 \
|
|
1178
|
+
# [[Motor(tango://haso107tk.desy.de:10000/motor/dummy_mot_ctrl/1), 'x'], \
|
|
1179
|
+
# [Motor(tango://haso107tk.desy.de:10000/motor/dummy_mot_ctrl/2), 'y']]"
|
|
1180
|
+
# -> 'fscan' np=3 0.1 exp_dmy0 exp_dmy02'
|
|
1181
|
+
|
|
1182
|
+
# about fscan syntax, see remark in diary 17.3.2023
|
|
1183
|
+
|
|
1184
|
+
lines = title.split( ' ')
|
|
1185
|
+
|
|
1186
|
+
try:
|
|
1187
|
+
nameSpace = {}
|
|
1188
|
+
exec( "a = dict( %s)" % lines[1], nameSpace)
|
|
1189
|
+
lengths = []
|
|
1190
|
+
lenMin = 10000000000
|
|
1191
|
+
for elm in nameSpace[ 'a']:
|
|
1192
|
+
if len( nameSpace[ 'a'][ elm]) < lenMin:
|
|
1193
|
+
lenMin = len( nameSpace[ 'a'][ elm])
|
|
1194
|
+
except:
|
|
1195
|
+
lenMin = 1500
|
|
1196
|
+
|
|
1197
|
+
cmdLine = lines[0] + " "
|
|
1198
|
+
cmdLine += "np=%d " % lenMin
|
|
1199
|
+
cmdLine += lines[2] + " "
|
|
1200
|
+
|
|
1201
|
+
temp = ""
|
|
1202
|
+
for line in lines[3:]:
|
|
1203
|
+
temp += line
|
|
1204
|
+
temp = temp.replace( 'Motor(tango://', '\'')
|
|
1205
|
+
temp = temp.replace( ')', '\'')
|
|
1206
|
+
|
|
1207
|
+
try:
|
|
1208
|
+
nameSpace = {}
|
|
1209
|
+
exec( "a = %s" % temp, nameSpace)
|
|
1210
|
+
for elm in nameSpace[ 'a']:
|
|
1211
|
+
p = _PyTango.DeviceProxy( elm[0])
|
|
1212
|
+
cmdLine += " %s" % (p.alias())
|
|
1213
|
+
except Exception as e:
|
|
1214
|
+
cmdLine = None
|
|
1215
|
+
#raise Exception( "MsUtils.RepairFscanTitle", "failed to parse %s" % title)
|
|
1216
|
+
|
|
1217
|
+
return cmdLine
|
|
1218
|
+
|
|
1219
|
+
|
|
1220
|
+
def dataRecordToScanInfo( dataRecord):
|
|
1221
|
+
'''
|
|
1222
|
+
creates the scanInfo dictionary from the first dataRecord
|
|
1223
|
+
|
|
1224
|
+
scanInfo:
|
|
1225
|
+
{'title': u'ascan exp_dmy01 0.0 0.1 10 0.1',
|
|
1226
|
+
'serialno': 1775,
|
|
1227
|
+
'motors': [{'start': 0.0, 'stop': 0.1, 'name': u'exp_dmy01', 'proxy': Motor(motor/dummy_mot_ctrl/1)}],
|
|
1228
|
+
'scanfile': [u'tst.fio', u'tst.nxs'],
|
|
1229
|
+
'filename': [u'tst_01780.fio', u'tst_01780.nxs'],
|
|
1230
|
+
'starttime': u'Thu Oct 13 15:35:48 2016',
|
|
1231
|
+
'scandir': u'/home/kracht/Misc/IVP/temp'}
|
|
1232
|
+
'''
|
|
1233
|
+
scanInfo = {}
|
|
1234
|
+
scanInfo['scanfile'] = dataRecord[1]['data'][ 'scanfile']
|
|
1235
|
+
if scanInfo['scanfile'] is None:
|
|
1236
|
+
raise Exception( "MsUtils.dataRecordToScanInfo", "scanfile not defined")
|
|
1237
|
+
scanInfo['scandir'] = dataRecord[1]['data'][ 'scandir']
|
|
1238
|
+
if scanInfo['scandir'] is None:
|
|
1239
|
+
raise Exception( "MsUtils.dataRecordToScanInfo", "scandir not defined")
|
|
1240
|
+
scanInfo['serialno'] = dataRecord[1]['data'][ 'serialno']
|
|
1241
|
+
|
|
1242
|
+
scanInfo['filename'] = []
|
|
1243
|
+
if type(scanInfo['scanfile']) is list:
|
|
1244
|
+
for sf in scanInfo['scanfile']:
|
|
1245
|
+
tpl = sf.rpartition('.')
|
|
1246
|
+
scanInfo['filename'].append( "%s_%05d.%s" % (tpl[0], scanInfo['serialno'], tpl[2]))
|
|
1247
|
+
else:
|
|
1248
|
+
tpl = scanInfo['scanfile'].rpartition('.')
|
|
1249
|
+
scanInfo['filename'].append( "%s_%05d.%s" % (tpl[0], scanInfo['serialno'], tpl[2]))
|
|
1250
|
+
|
|
1251
|
+
scanInfo['starttime'] = dataRecord[1]['data']['starttime']
|
|
1252
|
+
if dataRecord[1]['data']['title'].find( 'fscan') == 0:
|
|
1253
|
+
scanInfo['title'] = repairFscanTitle( dataRecord[1]['data']['title'])
|
|
1254
|
+
else:
|
|
1255
|
+
scanInfo['title'] = dataRecord[1]['data']['title']
|
|
1256
|
+
#
|
|
1257
|
+
# scanInfo is None for an fscan command spaces in the indepvar definition
|
|
1258
|
+
#
|
|
1259
|
+
if scanInfo is not None:
|
|
1260
|
+
scanInfo[ 'motors'] = []
|
|
1261
|
+
scanTitleToScanInfo( scanInfo[ 'title'], scanInfo)
|
|
1262
|
+
|
|
1263
|
+
return scanInfo
|
|
1264
|
+
|
|
1265
|
+
def doorAbortMacro( doorName = None):
|
|
1266
|
+
'''
|
|
1267
|
+
executes abortMacro() on the specified Door
|
|
1268
|
+
or choses the first Door. This is more than
|
|
1269
|
+
executing abort()
|
|
1270
|
+
'''
|
|
1271
|
+
if doorName is None:
|
|
1272
|
+
try:
|
|
1273
|
+
doorName = TgUtils.getDoorNames()[0]
|
|
1274
|
+
except Exception as e:
|
|
1275
|
+
print( "MsUtils.abortMacro: failed to get doorName")
|
|
1276
|
+
print( repr( e))
|
|
1277
|
+
return False
|
|
1278
|
+
|
|
1279
|
+
p = _PyTango.DeviceProxy( doorName)
|
|
1280
|
+
p.abortMacro()
|
|
1281
|
+
|
|
1282
|
+
return True
|
|
1283
|
+
|