genie-python 15.1.0rc1__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.
- genie_python/.pylintrc +539 -0
- genie_python/__init__.py +1 -0
- genie_python/block_names.py +123 -0
- genie_python/channel_access_exceptions.py +45 -0
- genie_python/genie.py +2462 -0
- genie_python/genie_advanced.py +418 -0
- genie_python/genie_alerts.py +195 -0
- genie_python/genie_api_setup.py +451 -0
- genie_python/genie_blockserver.py +64 -0
- genie_python/genie_cachannel_wrapper.py +545 -0
- genie_python/genie_change_cache.py +151 -0
- genie_python/genie_dae.py +2218 -0
- genie_python/genie_epics_api.py +906 -0
- genie_python/genie_experimental_data.py +186 -0
- genie_python/genie_logging.py +200 -0
- genie_python/genie_p4p_wrapper.py +203 -0
- genie_python/genie_plot.py +77 -0
- genie_python/genie_pre_post_cmd_manager.py +21 -0
- genie_python/genie_pv_connection_protocol.py +36 -0
- genie_python/genie_script_checker.py +507 -0
- genie_python/genie_script_generator.py +212 -0
- genie_python/genie_simulate.py +69 -0
- genie_python/genie_simulate_impl.py +1265 -0
- genie_python/genie_startup.py +29 -0
- genie_python/genie_toggle_settings.py +58 -0
- genie_python/genie_wait_for_move.py +154 -0
- genie_python/genie_waitfor.py +576 -0
- genie_python/matplotlib_backend/__init__.py +0 -0
- genie_python/matplotlib_backend/ibex_websocket_backend.py +366 -0
- genie_python/mysql_abstraction_layer.py +272 -0
- genie_python/run_tests.py +56 -0
- genie_python/scanning_instrument_pylint_plugin.py +31 -0
- genie_python/typings/CaChannel/CaChannel.pyi +893 -0
- genie_python/typings/CaChannel/__init__.pyi +9 -0
- genie_python/typings/CaChannel/_version.pyi +6 -0
- genie_python/typings/CaChannel/ca.pyi +31 -0
- genie_python/utilities.py +406 -0
- genie_python/version.py +1 -0
- genie_python-15.1.0rc1.dist-info/LICENSE +28 -0
- genie_python-15.1.0rc1.dist-info/METADATA +95 -0
- genie_python-15.1.0rc1.dist-info/RECORD +43 -0
- genie_python-15.1.0rc1.dist-info/WHEEL +5 -0
- genie_python-15.1.0rc1.dist-info/top_level.txt +1 -0
genie_python/genie.py
ADDED
|
@@ -0,0 +1,2462 @@
|
|
|
1
|
+
from __future__ import absolute_import, print_function
|
|
2
|
+
|
|
3
|
+
import datetime
|
|
4
|
+
import imp
|
|
5
|
+
import os
|
|
6
|
+
import re
|
|
7
|
+
import sys
|
|
8
|
+
import types
|
|
9
|
+
from builtins import FileNotFoundError, str
|
|
10
|
+
from io import open
|
|
11
|
+
from typing import Any, Callable, TypedDict
|
|
12
|
+
|
|
13
|
+
import numpy.typing as npt
|
|
14
|
+
|
|
15
|
+
from genie_python.genie_api_setup import __api as _genie_api
|
|
16
|
+
|
|
17
|
+
os.environ["EPICS_CA_MAX_ARRAY_BYTES"] = "20000000"
|
|
18
|
+
os.environ["FROM_IBEX"] = str(False)
|
|
19
|
+
|
|
20
|
+
# for user import this functionality so they can do g.adv and g.sim
|
|
21
|
+
import genie_python.genie_advanced as adv # noqa F401
|
|
22
|
+
import genie_python.genie_alerts as alerts # noqa F401
|
|
23
|
+
import genie_python.genie_simulate as sim # noqa F401
|
|
24
|
+
import genie_python.genie_toggle_settings as toggle # noqa F401
|
|
25
|
+
|
|
26
|
+
# Import required for g.my_pv_prefix
|
|
27
|
+
from genie_python.genie_api_setup import (
|
|
28
|
+
get_user_script_dir,
|
|
29
|
+
helparglist,
|
|
30
|
+
log_command_and_handle_exception,
|
|
31
|
+
my_pv_prefix, # noqa F401
|
|
32
|
+
set_user_script_dir,
|
|
33
|
+
usercommand,
|
|
34
|
+
)
|
|
35
|
+
from genie_python.genie_script_checker import ScriptChecker
|
|
36
|
+
from genie_python.genie_toggle_settings import ToggleSettings
|
|
37
|
+
from genie_python.utilities import (
|
|
38
|
+
EnvironmentDetails,
|
|
39
|
+
check_lowlimit_against_highlimit,
|
|
40
|
+
get_correct_filepath_existing,
|
|
41
|
+
get_correct_path,
|
|
42
|
+
)
|
|
43
|
+
from genie_python.version import VERSION
|
|
44
|
+
|
|
45
|
+
PVBaseValue = bool | int | float | str
|
|
46
|
+
PVValue = PVBaseValue | list[PVBaseValue] | npt.NDArray | None
|
|
47
|
+
|
|
48
|
+
print("\ngenie_python version " + VERSION)
|
|
49
|
+
|
|
50
|
+
SUPPORTED_PYTHON_VERSION = (3, 11, 6)
|
|
51
|
+
if sys.version_info[0:3] != SUPPORTED_PYTHON_VERSION[0:3]:
|
|
52
|
+
message = (
|
|
53
|
+
"WARNING: genie_python only guarantees support for "
|
|
54
|
+
"Python version {0[0]}.{0[1]}.{0[2]}, you are running {1}".format(
|
|
55
|
+
SUPPORTED_PYTHON_VERSION, sys.version
|
|
56
|
+
)
|
|
57
|
+
)
|
|
58
|
+
print(message, file=sys.stderr)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@log_command_and_handle_exception
|
|
62
|
+
def set_instrument(pv_prefix: str, import_instrument_init: bool = True) -> None:
|
|
63
|
+
"""
|
|
64
|
+
Sets the instrument this session is communicating with.
|
|
65
|
+
Used for remote access - do not delete.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
pv_prefix (string): the PV prefix
|
|
69
|
+
import_instrument_init (bool): if True import the instrument init
|
|
70
|
+
from the config area; otherwise don't
|
|
71
|
+
"""
|
|
72
|
+
globs = _get_correct_globals()
|
|
73
|
+
_genie_api.set_instrument(pv_prefix, globs, import_instrument_init)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@log_command_and_handle_exception
|
|
77
|
+
def reload_current_config() -> None:
|
|
78
|
+
"""
|
|
79
|
+
Reload the current configuration.
|
|
80
|
+
"""
|
|
81
|
+
_genie_api.reload_current_config()
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@usercommand
|
|
85
|
+
@helparglist("")
|
|
86
|
+
@log_command_and_handle_exception
|
|
87
|
+
def get_blocks() -> list[str]:
|
|
88
|
+
"""
|
|
89
|
+
Get the names of the blocks.
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
list: the blocknames
|
|
93
|
+
"""
|
|
94
|
+
return _genie_api.get_block_names()
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@usercommand
|
|
98
|
+
@helparglist("block")
|
|
99
|
+
@log_command_and_handle_exception
|
|
100
|
+
def get_block_units(block_name: str) -> str | dict | None:
|
|
101
|
+
"""
|
|
102
|
+
Get the physical measurement units associated with a block name.
|
|
103
|
+
|
|
104
|
+
Args:
|
|
105
|
+
block_name: name of the block
|
|
106
|
+
|
|
107
|
+
Returns
|
|
108
|
+
string: units of the block
|
|
109
|
+
"""
|
|
110
|
+
return _genie_api.get_block_units(block_name)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
@usercommand
|
|
114
|
+
@helparglist("...")
|
|
115
|
+
@log_command_and_handle_exception
|
|
116
|
+
def cset(
|
|
117
|
+
*args: str,
|
|
118
|
+
runcontrol: bool | None = None,
|
|
119
|
+
lowlimit: float | None = None,
|
|
120
|
+
highlimit: float | None = None,
|
|
121
|
+
wait: bool | None = None,
|
|
122
|
+
verbose: bool | None = None,
|
|
123
|
+
**kwargs: bool | int | float | str | None,
|
|
124
|
+
) -> None:
|
|
125
|
+
"""
|
|
126
|
+
Sets the setpoint and runcontrol settings for blocks.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
runcontrol (bool, optional): whether to set runcontrol for this block
|
|
130
|
+
wait (bool, optional): pause execution until setpoint is reached (one block only)
|
|
131
|
+
lowlimit (float, optional): the lower limit for runcontrol or waiting
|
|
132
|
+
highlimit (float, optional): the upper limit for runcontrol or waiting
|
|
133
|
+
verbose (bool, optional): report what the new block state is as a result of the command
|
|
134
|
+
|
|
135
|
+
Note: cannot use wait and runcontrol in the same command
|
|
136
|
+
|
|
137
|
+
Examples:
|
|
138
|
+
Setting a value for a block:
|
|
139
|
+
|
|
140
|
+
>>> cset(block1=100)
|
|
141
|
+
|
|
142
|
+
Or:
|
|
143
|
+
|
|
144
|
+
>>> cset("block1", 100)
|
|
145
|
+
|
|
146
|
+
Setting values for more than one block:
|
|
147
|
+
|
|
148
|
+
>>> cset(block1=100, block2=200, block3=300)
|
|
149
|
+
|
|
150
|
+
NOTE: the order in which the values are set is random,
|
|
151
|
+
e.g. block1 may or may not be set before block2 and block3
|
|
152
|
+
|
|
153
|
+
Setting runcontrol values for a block:
|
|
154
|
+
|
|
155
|
+
>>> cset(block1=100, runcontrol=True, lowlimit=99, highlimit=101)
|
|
156
|
+
|
|
157
|
+
Changing runcontrol settings for a block without changing the setpoint:
|
|
158
|
+
|
|
159
|
+
>>> cset("block1", runcontrol=False)
|
|
160
|
+
>>> cset(block1=None, runcontrol=False)
|
|
161
|
+
|
|
162
|
+
Wait for setpoint to be reached (one block only):
|
|
163
|
+
|
|
164
|
+
>>> cset(block1=100, wait=True)
|
|
165
|
+
|
|
166
|
+
Wait for limits to be reached - this does NOT change the runcontrol limits:
|
|
167
|
+
|
|
168
|
+
>>> cset(block1=100, wait=True, lowlimit=99, highlimit=101)
|
|
169
|
+
"""
|
|
170
|
+
# Block names contain alpha-numeric and underscores only
|
|
171
|
+
|
|
172
|
+
# See if single block name was entered, i.e. cset("block1", runcontrol=True)
|
|
173
|
+
if len(args) > 0:
|
|
174
|
+
if len(args) > 2:
|
|
175
|
+
raise Exception(
|
|
176
|
+
"Too many arguments, please type: help(g.cset) for more information on the syntax"
|
|
177
|
+
)
|
|
178
|
+
blocks = [args[0]]
|
|
179
|
+
values = [args[1]] if len(args) == 2 else [None]
|
|
180
|
+
elif len(kwargs) > 0:
|
|
181
|
+
# Check for specifying blocks via the cset(block=value) syntax
|
|
182
|
+
blocks, values = zip(*kwargs.items())
|
|
183
|
+
else:
|
|
184
|
+
raise Exception(
|
|
185
|
+
"Incorrect syntax, please type: help(g.cset) for more information on the syntax"
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
for block in blocks:
|
|
189
|
+
if not _genie_api.block_exists(block):
|
|
190
|
+
raise Exception('No block with the name "{}" exists'.format(block))
|
|
191
|
+
|
|
192
|
+
if wait and runcontrol is not None:
|
|
193
|
+
raise Exception("Cannot enable or disable runcontrol at the same time as setting a wait")
|
|
194
|
+
if wait and values[0] is None:
|
|
195
|
+
raise Exception("Cannot wait as no setpoint specified. Please type: help(g.cset) for help")
|
|
196
|
+
|
|
197
|
+
# Warn if highlimit and lowlimit are round the incorrect way
|
|
198
|
+
check_lowlimit_against_highlimit(lowlimit, highlimit)
|
|
199
|
+
|
|
200
|
+
if len(blocks) > 1:
|
|
201
|
+
# Setting multiple blocks, so other settings not allowed
|
|
202
|
+
if not all(argument is None for argument in [runcontrol, lowlimit, highlimit, wait]):
|
|
203
|
+
raise Exception("Runcontrol and wait can only be changed for one block at a time")
|
|
204
|
+
|
|
205
|
+
for block, value in list(zip(blocks, values)):
|
|
206
|
+
# If there are multiple blocks then runcontrol etc.
|
|
207
|
+
# should be None anyway so pass them through
|
|
208
|
+
|
|
209
|
+
_genie_api.set_block_value(block, value, runcontrol, lowlimit, highlimit, wait)
|
|
210
|
+
_warn_if_block_alarm(block)
|
|
211
|
+
|
|
212
|
+
# Display what the new block state is as a result of the command if
|
|
213
|
+
# cset verbosity is toggled on, or the command
|
|
214
|
+
# was specifically called with 'verbose=True'.
|
|
215
|
+
# If default verbosity is True, but the command was specifically
|
|
216
|
+
# called with no verbose, do not display new state.
|
|
217
|
+
if verbose is not False and (verbose or ToggleSettings.cset_verbose):
|
|
218
|
+
for block, value in list(zip(blocks, values)):
|
|
219
|
+
waitfor_block(block=block, value=value, maxwait=5)
|
|
220
|
+
print("Result: ", end="")
|
|
221
|
+
cshow(block)
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
class _CgetReturn(TypedDict):
|
|
225
|
+
name: str
|
|
226
|
+
value: Any
|
|
227
|
+
unit: str
|
|
228
|
+
connected: bool
|
|
229
|
+
runcontrol: bool
|
|
230
|
+
lowlimit: Any
|
|
231
|
+
highlimit: Any
|
|
232
|
+
alarm: str
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
@usercommand
|
|
236
|
+
@helparglist("block")
|
|
237
|
+
@log_command_and_handle_exception
|
|
238
|
+
def cget(block: str) -> _CgetReturn:
|
|
239
|
+
"""
|
|
240
|
+
Gets the useful values associated with a block.
|
|
241
|
+
|
|
242
|
+
The value will be None if the block is not "connected".
|
|
243
|
+
|
|
244
|
+
Args:
|
|
245
|
+
block (string): the name of the block
|
|
246
|
+
|
|
247
|
+
Returns
|
|
248
|
+
dict: details about about the block. Contains:
|
|
249
|
+
name - name of the block
|
|
250
|
+
value - value of the block
|
|
251
|
+
unit - physical units of the block
|
|
252
|
+
connected - True if connected; False otherwise
|
|
253
|
+
runcontrol - NO not in runcontrol, YES otherwise
|
|
254
|
+
lowlimit - run control low limit set
|
|
255
|
+
highlimit - run control high limit set
|
|
256
|
+
alarm - the alarm status of the block
|
|
257
|
+
"""
|
|
258
|
+
ans = _genie_api.get_block_data(block)
|
|
259
|
+
if ans["alarm"] != "NO_ALARM":
|
|
260
|
+
_log_alarmed_block(block, ans["alarm"])
|
|
261
|
+
return ans
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
def _log_alarmed_block(block_name: str, alarm_state: str) -> None:
|
|
265
|
+
_genie_api.logger.log_info_msg("BLOCK {} IN {} ALARM".format(block_name, alarm_state))
|
|
266
|
+
print("Block {} is in alarm: {}".format(block_name, alarm_state), file=sys.stdout)
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
def _warn_if_block_alarm(block: object) -> None:
|
|
270
|
+
"""
|
|
271
|
+
Checks whether a block is in an alarmed state and warn user (inc log)
|
|
272
|
+
|
|
273
|
+
Args:
|
|
274
|
+
block (object): The block to be checked
|
|
275
|
+
"""
|
|
276
|
+
minor, major, invalid = check_alarms(block)
|
|
277
|
+
alarms = {"MINOR": minor, "MAJOR": major, "INVALID": invalid}
|
|
278
|
+
for alarm_type, alarm in alarms.items():
|
|
279
|
+
if alarm:
|
|
280
|
+
_log_alarmed_block(alarm[0], alarm_type)
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
def _print_from_cget(block_details: dict[str, str]) -> None:
|
|
284
|
+
"""
|
|
285
|
+
Prints the values obtained through cget into a
|
|
286
|
+
human readable format, used for cshow.
|
|
287
|
+
|
|
288
|
+
Args:
|
|
289
|
+
block_details (dict): dict containing information on the block
|
|
290
|
+
(see return of cget)
|
|
291
|
+
"""
|
|
292
|
+
format_string = (
|
|
293
|
+
"{name} = {value} (runcontrol = {runcontrol}, "
|
|
294
|
+
"lowlimit = {lowlimit}, highlimit = {highlimit}, "
|
|
295
|
+
"alarm = {alarm})"
|
|
296
|
+
)
|
|
297
|
+
if not block_details["connected"]:
|
|
298
|
+
block_details["value"] = "*** disconnected ***"
|
|
299
|
+
print(format_string.format(**block_details))
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
@log_command_and_handle_exception
|
|
303
|
+
def cshow(block: str | None = None) -> None:
|
|
304
|
+
"""
|
|
305
|
+
Show the current settings for one block or for all blocks.
|
|
306
|
+
|
|
307
|
+
Args:
|
|
308
|
+
block (string, optional): the name of the block
|
|
309
|
+
|
|
310
|
+
Examples:
|
|
311
|
+
Showing all block values:
|
|
312
|
+
|
|
313
|
+
>>> cshow()
|
|
314
|
+
|
|
315
|
+
Showing values for one block only (name must be quoted):
|
|
316
|
+
|
|
317
|
+
>>> cshow("block1")
|
|
318
|
+
"""
|
|
319
|
+
blocks_to_get = [block] if block is not None else _genie_api.get_block_names()
|
|
320
|
+
for block in blocks_to_get:
|
|
321
|
+
_print_from_cget(_genie_api.get_block_data(block, True))
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
@log_command_and_handle_exception
|
|
325
|
+
def waitfor(
|
|
326
|
+
block: str | None = None,
|
|
327
|
+
value: float | None = None,
|
|
328
|
+
lowlimit: float | None = None,
|
|
329
|
+
highlimit: float | None = None,
|
|
330
|
+
maxwait: float | None = None,
|
|
331
|
+
wait_all: bool = False,
|
|
332
|
+
seconds: float | None = None,
|
|
333
|
+
minutes: float | None = None,
|
|
334
|
+
hours: float | None = None,
|
|
335
|
+
time: str | None = None,
|
|
336
|
+
frames: int | None = None,
|
|
337
|
+
raw_frames: int | None = None,
|
|
338
|
+
uamps: float | None = None,
|
|
339
|
+
mevents: float | None = None,
|
|
340
|
+
early_exit: Callable[[], bool] = lambda: False,
|
|
341
|
+
quiet: bool = False,
|
|
342
|
+
**pars: bool | int | float | str | Callable[[None], bool] | None,
|
|
343
|
+
) -> None:
|
|
344
|
+
"""
|
|
345
|
+
Interrupts execution until certain conditions are met.
|
|
346
|
+
|
|
347
|
+
Args:
|
|
348
|
+
block (string, optional): the name of the block to wait for
|
|
349
|
+
value (float, optional): the block value to wait for
|
|
350
|
+
lowlimit (float, optional): wait for the block to be >= this value (numeric only)
|
|
351
|
+
highlimit (float, optional): wait for the block to be <= this value (numeric only)
|
|
352
|
+
maxwait (float, optional): wait no longer that the specified number of seconds
|
|
353
|
+
wait_all (bool, optional): wait for all conditions to be met
|
|
354
|
+
(e.g. a number of frames and an amount of uamps)
|
|
355
|
+
seconds (float, optional): wait for a specified number of seconds
|
|
356
|
+
minutes (float, optional): wait for a specified number of minutes
|
|
357
|
+
hours (float, optional): wait for a specified number of hours
|
|
358
|
+
time (string, optional): a quicker way of setting hours, minutes and seconds
|
|
359
|
+
(must be of format "HH:MM:SS")
|
|
360
|
+
frames (int, optional): wait for a total number of good frames to be collected
|
|
361
|
+
raw_frames (int, optional): wait for a total number of raw frames to be collected
|
|
362
|
+
uamps (float, optional): wait for a total number of uamps to be received
|
|
363
|
+
mevents (float, optional): wait for a total number of millions of events to be collected
|
|
364
|
+
early_exit (lambda, optional): stop waiting if the function evaluates to True
|
|
365
|
+
quiet (bool, optional): suppress normal output messages to the console
|
|
366
|
+
|
|
367
|
+
Examples:
|
|
368
|
+
Wait for a block to reach a specific value:
|
|
369
|
+
|
|
370
|
+
>>> waitfor(myblock=123)
|
|
371
|
+
>>> waitfor("myblock", 123)
|
|
372
|
+
>>> waitfor("myblock", True)
|
|
373
|
+
>>> waitfor("myblock", "OPEN")
|
|
374
|
+
|
|
375
|
+
Wait for a block to be between limits:
|
|
376
|
+
|
|
377
|
+
>>> waitfor("myblock", lowlimit=100, highlimit=110)
|
|
378
|
+
|
|
379
|
+
Wait for a block to reach a specific value, but no longer than 60 seconds:
|
|
380
|
+
|
|
381
|
+
>>> waitfor(myblock=123, maxwait=60)
|
|
382
|
+
|
|
383
|
+
Wait for a specified time interval:
|
|
384
|
+
|
|
385
|
+
>>> waitfor(seconds=10)
|
|
386
|
+
>>> waitfor(hours=1, minutes=30, seconds=15)
|
|
387
|
+
>>> waitfor(time="1:30:15")
|
|
388
|
+
|
|
389
|
+
Wait for a data collection condition:
|
|
390
|
+
|
|
391
|
+
>>> waitfor(frames=5000)
|
|
392
|
+
>>> waitfor(uamps=200)
|
|
393
|
+
|
|
394
|
+
Wait for either a number of frames OR a time interval to occur:
|
|
395
|
+
|
|
396
|
+
>>> waitfor(frames=5000, hours=2)
|
|
397
|
+
|
|
398
|
+
Wait for a number of frames AND a time interval to occur:
|
|
399
|
+
|
|
400
|
+
>>> waitfor(frames=5000, hours=2, wait_all=True)
|
|
401
|
+
|
|
402
|
+
Wait for either the block to reach a value or a condition to be met:
|
|
403
|
+
|
|
404
|
+
>>> waitfor(myblock=123, early_exit=lambda:
|
|
405
|
+
some_function(cget("another_block")["value"]) > 123)
|
|
406
|
+
"""
|
|
407
|
+
if block is None:
|
|
408
|
+
# Search through the params to see if there is a block there
|
|
409
|
+
blks = _genie_api.get_block_names()
|
|
410
|
+
for k in pars:
|
|
411
|
+
if k in blks:
|
|
412
|
+
if block is not None:
|
|
413
|
+
raise Exception("Can set waitfor for only one block at a time")
|
|
414
|
+
block = k
|
|
415
|
+
value = pars[k]
|
|
416
|
+
else:
|
|
417
|
+
raise ValueError("Block named '{}' did not exist.".format(k))
|
|
418
|
+
# Check that wait_for object exists
|
|
419
|
+
if _genie_api.waitfor is None:
|
|
420
|
+
raise Exception("Cannot execute waitfor - try calling set_instrument first")
|
|
421
|
+
# Warn if highlimit and lowlimit are round correct way
|
|
422
|
+
check_lowlimit_against_highlimit(lowlimit, highlimit)
|
|
423
|
+
# Start_waiting checks the block exists
|
|
424
|
+
_genie_api.waitfor.start_waiting(
|
|
425
|
+
block,
|
|
426
|
+
value,
|
|
427
|
+
lowlimit,
|
|
428
|
+
highlimit,
|
|
429
|
+
maxwait,
|
|
430
|
+
wait_all,
|
|
431
|
+
seconds,
|
|
432
|
+
minutes,
|
|
433
|
+
hours,
|
|
434
|
+
time,
|
|
435
|
+
frames,
|
|
436
|
+
raw_frames,
|
|
437
|
+
uamps,
|
|
438
|
+
mevents,
|
|
439
|
+
early_exit,
|
|
440
|
+
quiet,
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
|
|
444
|
+
@usercommand
|
|
445
|
+
@helparglist("block[, value][, lowlimit][, highlimit][, maxwait]")
|
|
446
|
+
@log_command_and_handle_exception
|
|
447
|
+
def waitfor_block(
|
|
448
|
+
block: str,
|
|
449
|
+
value: bool | int | float | str | None = None,
|
|
450
|
+
lowlimit: float | None = None,
|
|
451
|
+
highlimit: float | None = None,
|
|
452
|
+
maxwait: float | None = None,
|
|
453
|
+
early_exit: Callable[[], bool] = lambda: False,
|
|
454
|
+
quiet: bool = False,
|
|
455
|
+
) -> None:
|
|
456
|
+
"""
|
|
457
|
+
Interrupts execution until block reaches specific value
|
|
458
|
+
|
|
459
|
+
Args:
|
|
460
|
+
block: the name of the block to wait for
|
|
461
|
+
value: the target block value
|
|
462
|
+
lowlimit: waits for the block to be >= this value (numeric only)
|
|
463
|
+
highlimit: waits for the block to be <= this value (numeric only)
|
|
464
|
+
maxwait: wait no longer that the specified number of seconds
|
|
465
|
+
early_exit: stop waiting if the exception evaluates to True
|
|
466
|
+
quiet (bool, optional): suppress normal output messages to the console
|
|
467
|
+
|
|
468
|
+
Examples:
|
|
469
|
+
|
|
470
|
+
>>> waitfor_block("myblock", value=123)
|
|
471
|
+
>>> waitfor_block("myblock", value=True, maxwait=15)
|
|
472
|
+
>>> waitfor_block("myblock", lowlimit=100, highlimit=110)
|
|
473
|
+
>>> waitfor_block("myblock", highlimit=1.0, maxwait=60)
|
|
474
|
+
>>> waitfor_block(
|
|
475
|
+
... "myblock", value=123, early_exit=lambda: cget("myblock_limit_reached")["value"] != 0
|
|
476
|
+
... )
|
|
477
|
+
"""
|
|
478
|
+
if _genie_api.waitfor is None:
|
|
479
|
+
raise Exception("Cannot execute waitfor_block - try calling set_instrument first")
|
|
480
|
+
# Warn if highlimit and lowlimit are round correct way
|
|
481
|
+
check_lowlimit_against_highlimit(lowlimit, highlimit)
|
|
482
|
+
_genie_api.waitfor.start_waiting(
|
|
483
|
+
block=block,
|
|
484
|
+
value=value,
|
|
485
|
+
lowlimit=lowlimit,
|
|
486
|
+
highlimit=highlimit,
|
|
487
|
+
maxwait=maxwait,
|
|
488
|
+
early_exit=early_exit,
|
|
489
|
+
quiet=quiet,
|
|
490
|
+
)
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
@usercommand
|
|
494
|
+
@helparglist("[seconds][, minutes][, hours][, time]")
|
|
495
|
+
@log_command_and_handle_exception
|
|
496
|
+
def waitfor_time(
|
|
497
|
+
seconds: float | None = None,
|
|
498
|
+
minutes: float | None = None,
|
|
499
|
+
hours: float | None = None,
|
|
500
|
+
time: str | None = None,
|
|
501
|
+
quiet: bool = False,
|
|
502
|
+
) -> None:
|
|
503
|
+
"""
|
|
504
|
+
Interrupts execution for a specified amount of time
|
|
505
|
+
|
|
506
|
+
Args:
|
|
507
|
+
seconds (float, optional): wait for a specified number of seconds
|
|
508
|
+
minutes (float, optional): wait for a specified number of minutes
|
|
509
|
+
hours (float, optional): wait for a specified number of hours
|
|
510
|
+
time (string, optional): a quicker way of setting hours,
|
|
511
|
+
minutes and seconds (must be of format "HH:MM:SS")
|
|
512
|
+
quiet (bool, optional): suppress normal output messages to the console
|
|
513
|
+
|
|
514
|
+
Examples:
|
|
515
|
+
|
|
516
|
+
>>> waitfor_time(seconds=10)
|
|
517
|
+
>>> waitfor_time(hours=1, minutes=30, seconds=15)
|
|
518
|
+
>>> waitfor_time(time="1:30:15")
|
|
519
|
+
"""
|
|
520
|
+
if all(t is None for t in (seconds, minutes, hours, time)):
|
|
521
|
+
raise TypeError(
|
|
522
|
+
"Cannot execute waitfor_time - need to set at least one parameter. "
|
|
523
|
+
"Type help(waitfor_time) "
|
|
524
|
+
"to see guidelines"
|
|
525
|
+
)
|
|
526
|
+
if any(t is not None and t < 0 for t in (seconds, minutes, hours)):
|
|
527
|
+
raise ValueError("Cannot execute waitfor_time - Time parameters cannot be negative")
|
|
528
|
+
if _genie_api.waitfor is None:
|
|
529
|
+
raise TypeError("Cannot execute waitfor_time - try calling set_instrument first")
|
|
530
|
+
_genie_api.waitfor.start_waiting(
|
|
531
|
+
seconds=seconds, minutes=minutes, hours=hours, time=time, quiet=quiet
|
|
532
|
+
)
|
|
533
|
+
|
|
534
|
+
|
|
535
|
+
@usercommand
|
|
536
|
+
@helparglist("frames")
|
|
537
|
+
@log_command_and_handle_exception
|
|
538
|
+
def waitfor_frames(frames: int, quiet: bool = False) -> None:
|
|
539
|
+
"""
|
|
540
|
+
Interrupts execution to wait for number of total good frames to reach parameter value
|
|
541
|
+
|
|
542
|
+
Args:
|
|
543
|
+
frames (int): the number of frames to wait for
|
|
544
|
+
quiet (bool, optional): suppress normal output messages to the console
|
|
545
|
+
|
|
546
|
+
Example:
|
|
547
|
+
|
|
548
|
+
>>> waitfor_frames(4000)
|
|
549
|
+
"""
|
|
550
|
+
if frames is None:
|
|
551
|
+
raise TypeError(
|
|
552
|
+
"Cannot execute waitfor_frames - need to set frames parameter. Type help(waitfor_frames"
|
|
553
|
+
)
|
|
554
|
+
if frames < 0:
|
|
555
|
+
raise ValueError("Cannot execute waitfor_frames - frames parameter cannot be negative")
|
|
556
|
+
if _genie_api.waitfor is None:
|
|
557
|
+
raise Exception("Cannot execute waitfor_frames - try calling set_instrument first")
|
|
558
|
+
_genie_api.waitfor.start_waiting(frames=frames, quiet=quiet)
|
|
559
|
+
|
|
560
|
+
|
|
561
|
+
@usercommand
|
|
562
|
+
@helparglist("raw_frames")
|
|
563
|
+
@log_command_and_handle_exception
|
|
564
|
+
def waitfor_raw_frames(raw_frames: int, quiet: bool = False) -> None:
|
|
565
|
+
"""
|
|
566
|
+
Interrupts execution to wait for number of total raw frames to reach parameter value
|
|
567
|
+
|
|
568
|
+
Args:
|
|
569
|
+
raw frames (int): the number of raw frames to wait for
|
|
570
|
+
quiet (bool, optional): suppress normal output messages to the console
|
|
571
|
+
|
|
572
|
+
Example:
|
|
573
|
+
|
|
574
|
+
>>> waitfor_raw_frames(4000)
|
|
575
|
+
"""
|
|
576
|
+
if raw_frames is None:
|
|
577
|
+
raise TypeError(
|
|
578
|
+
"Cannot execute waitfor_raw_frames - need to set raw_frames parameter. "
|
|
579
|
+
"Type help(waitfor_raw_frames"
|
|
580
|
+
)
|
|
581
|
+
if raw_frames < 0:
|
|
582
|
+
raise ValueError(
|
|
583
|
+
"Cannot execute waitfor_raw_frames - raw_frames parameter cannot be negative"
|
|
584
|
+
)
|
|
585
|
+
if _genie_api.waitfor is None:
|
|
586
|
+
raise Exception("Cannot execute waitfor_raw_frames - try calling set_instrument first")
|
|
587
|
+
_genie_api.waitfor.start_waiting(raw_frames=raw_frames, quiet=quiet)
|
|
588
|
+
|
|
589
|
+
|
|
590
|
+
@usercommand
|
|
591
|
+
@helparglist("uamps")
|
|
592
|
+
@log_command_and_handle_exception
|
|
593
|
+
def waitfor_uamps(uamps: float, quiet: bool = False) -> None:
|
|
594
|
+
"""
|
|
595
|
+
Interrupts execution to wait for a specific total charge
|
|
596
|
+
|
|
597
|
+
Args:
|
|
598
|
+
uamps: the charge to wait for
|
|
599
|
+
quiet (bool, optional): suppress normal output messages to the console
|
|
600
|
+
|
|
601
|
+
Example:
|
|
602
|
+
|
|
603
|
+
>>> waitfor_uamps(115.5)
|
|
604
|
+
"""
|
|
605
|
+
if _genie_api.waitfor is None:
|
|
606
|
+
raise Exception("Cannot execute waitfor_uamps - try calling set_instrument first")
|
|
607
|
+
_genie_api.waitfor.start_waiting(uamps=uamps, quiet=quiet)
|
|
608
|
+
|
|
609
|
+
|
|
610
|
+
@usercommand
|
|
611
|
+
@helparglist("mevents")
|
|
612
|
+
@log_command_and_handle_exception
|
|
613
|
+
def waitfor_mevents(mevents: float, quiet: bool = False) -> None:
|
|
614
|
+
"""
|
|
615
|
+
Interrupts execution to wait for number of millions of events to reach parameter value
|
|
616
|
+
|
|
617
|
+
Args:
|
|
618
|
+
mevents (float): the number of millions of events to wait for
|
|
619
|
+
quiet (bool, optional): suppress normal output messages to the console
|
|
620
|
+
|
|
621
|
+
Example:
|
|
622
|
+
|
|
623
|
+
>>> waitfor_mevents(0.0004)
|
|
624
|
+
"""
|
|
625
|
+
if mevents is None:
|
|
626
|
+
raise TypeError(
|
|
627
|
+
"Cannot execute waitfor_mevents - need to set mevents parameter. "
|
|
628
|
+
"Type help(waitfor_mevents)"
|
|
629
|
+
)
|
|
630
|
+
if mevents < 0:
|
|
631
|
+
raise ValueError("Cannot execute waitfor_mevents - mevents parameter cannot be negative")
|
|
632
|
+
if _genie_api.waitfor is None:
|
|
633
|
+
raise Exception("Cannot execute waitfor_mevents - try calling set_instrument first")
|
|
634
|
+
_genie_api.waitfor.start_waiting(mevents=mevents, quiet=quiet)
|
|
635
|
+
|
|
636
|
+
|
|
637
|
+
@usercommand
|
|
638
|
+
@helparglist("state[, maxwaitsecs][, onexit]")
|
|
639
|
+
@log_command_and_handle_exception
|
|
640
|
+
def waitfor_runstate(
|
|
641
|
+
state: str, maxwaitsecs: int = 3600, onexit: bool = False, quiet: bool = False
|
|
642
|
+
) -> None:
|
|
643
|
+
"""
|
|
644
|
+
Wait for a particular instrument run state.
|
|
645
|
+
|
|
646
|
+
Args:
|
|
647
|
+
state (string): the state to wait for (e.g. "paused")
|
|
648
|
+
maxwaitsecs (int, optional): the maximum time to wait for the state before carrying on
|
|
649
|
+
onexit (bool, optional): wait for runstate to change from the specified state
|
|
650
|
+
quiet (bool, optional): suppress normal output messages to the console
|
|
651
|
+
|
|
652
|
+
Examples:
|
|
653
|
+
Wait for a run to enter the paused state:
|
|
654
|
+
|
|
655
|
+
>>> waitfor_runstate("paused")
|
|
656
|
+
|
|
657
|
+
Wait for a run to exit the paused state:
|
|
658
|
+
|
|
659
|
+
>>> waitfor_runstate("paused", onexit=True)
|
|
660
|
+
"""
|
|
661
|
+
# Check that wait_for object exists
|
|
662
|
+
if _genie_api.waitfor is None:
|
|
663
|
+
raise Exception("Cannot execute waitfor_runstate - try calling set_instrument first")
|
|
664
|
+
_genie_api.waitfor.wait_for_runstate(state, maxwaitsecs, onexit, quiet)
|
|
665
|
+
|
|
666
|
+
|
|
667
|
+
@usercommand
|
|
668
|
+
@helparglist("[block, ...][, start_timeout][, move_timeout]")
|
|
669
|
+
@log_command_and_handle_exception
|
|
670
|
+
def waitfor_move(*blocks: str | None, **kwargs: int | None) -> None:
|
|
671
|
+
"""
|
|
672
|
+
Wait for all motion or specific motion to complete.
|
|
673
|
+
|
|
674
|
+
If block names are supplied then it will only wait for those to stop moving.
|
|
675
|
+
Otherwise, it will wait for all motion
|
|
676
|
+
to stop.
|
|
677
|
+
|
|
678
|
+
Args:
|
|
679
|
+
blocks (string, multiple, optional): the names of specific blocks to wait for
|
|
680
|
+
start_timeout (int, optional): the number of seconds to wait for the
|
|
681
|
+
movement to begin (default = 2 seconds)
|
|
682
|
+
move_timeout (int, optional): the maximum number of seconds to wait for motion to stop
|
|
683
|
+
|
|
684
|
+
Examples:
|
|
685
|
+
Wait for all motors to stop moving:
|
|
686
|
+
|
|
687
|
+
>>> waitfor_move()
|
|
688
|
+
|
|
689
|
+
Wait for all motors to stop moving with a timeout of 30 seconds:
|
|
690
|
+
|
|
691
|
+
>>> waitfor_move(move_timeout=30)
|
|
692
|
+
|
|
693
|
+
Wait for only slit1 and slit2 motors to stop moving:
|
|
694
|
+
|
|
695
|
+
>>> waitfor_move("slit1", "slit2")
|
|
696
|
+
"""
|
|
697
|
+
# Sort out the parameters
|
|
698
|
+
# Standard parameters
|
|
699
|
+
if "start_timeout" in kwargs:
|
|
700
|
+
start_timeout = kwargs["start_timeout"]
|
|
701
|
+
else:
|
|
702
|
+
start_timeout = 2
|
|
703
|
+
if "move_timeout" in kwargs:
|
|
704
|
+
move_timeout = kwargs["move_timeout"]
|
|
705
|
+
else:
|
|
706
|
+
move_timeout = None
|
|
707
|
+
|
|
708
|
+
# Check that wait_for_move object exists
|
|
709
|
+
if _genie_api.wait_for_move is None:
|
|
710
|
+
raise Exception("Cannot execute waitfor_move - try calling set_instrument first")
|
|
711
|
+
|
|
712
|
+
if len(blocks) > 0:
|
|
713
|
+
# Specified blocks waitfor_move
|
|
714
|
+
move_blocks = list()
|
|
715
|
+
# Check blocks exist
|
|
716
|
+
for b in blocks:
|
|
717
|
+
if _genie_api.block_exists(b):
|
|
718
|
+
move_blocks.append(b)
|
|
719
|
+
else:
|
|
720
|
+
print("Block %s does not exist, so ignoring it" % b)
|
|
721
|
+
_genie_api.wait_for_move.wait_specific(move_blocks, start_timeout, move_timeout)
|
|
722
|
+
else:
|
|
723
|
+
# Standard waitfor_move
|
|
724
|
+
_genie_api.wait_for_move.wait(start_timeout, move_timeout)
|
|
725
|
+
|
|
726
|
+
|
|
727
|
+
@usercommand
|
|
728
|
+
@helparglist("name[, to_string][, is_local][, use_numpy]")
|
|
729
|
+
@log_command_and_handle_exception
|
|
730
|
+
def get_pv(
|
|
731
|
+
name: str, to_string: bool = False, is_local: bool = False, use_numpy: bool = False
|
|
732
|
+
) -> PVValue:
|
|
733
|
+
"""
|
|
734
|
+
Get the value for the specified PV.
|
|
735
|
+
|
|
736
|
+
Args:
|
|
737
|
+
name (string): the name of the PV to get the value for
|
|
738
|
+
to_string (bool, optional): whether to get the value as a string
|
|
739
|
+
is_local (bool, optional): whether to automatically prepend the
|
|
740
|
+
local inst prefix to the PV name
|
|
741
|
+
use_numpy (bool, optional): True use numpy to return arrays,
|
|
742
|
+
False return a list; None for use the default
|
|
743
|
+
|
|
744
|
+
Returns:
|
|
745
|
+
the current PV value
|
|
746
|
+
"""
|
|
747
|
+
return _genie_api.get_pv_value(name, to_string, is_local=is_local, use_numpy=use_numpy)
|
|
748
|
+
|
|
749
|
+
|
|
750
|
+
@usercommand
|
|
751
|
+
@helparglist("name, value[, wait][, is_local]")
|
|
752
|
+
@log_command_and_handle_exception
|
|
753
|
+
def set_pv(name: str, value: PVValue, wait: bool = False, is_local: bool = False) -> None:
|
|
754
|
+
"""
|
|
755
|
+
Set the value for the specified PV.
|
|
756
|
+
|
|
757
|
+
Args:
|
|
758
|
+
name (string): the PV name
|
|
759
|
+
value: the new value to set
|
|
760
|
+
wait (bool, optional): whether to wait until the value
|
|
761
|
+
has been received by the hardware
|
|
762
|
+
is_local (bool, optional): whether to automatically
|
|
763
|
+
prepend the local inst prefix to the PV name
|
|
764
|
+
"""
|
|
765
|
+
_genie_api.set_pv_value(name, value, wait, is_local=is_local)
|
|
766
|
+
|
|
767
|
+
|
|
768
|
+
@usercommand
|
|
769
|
+
@helparglist("pv_list, [, is_local]")
|
|
770
|
+
@log_command_and_handle_exception
|
|
771
|
+
def connected_pvs_in_list(pv_list: list[str], is_local: bool = False) -> list[str]:
|
|
772
|
+
"""
|
|
773
|
+
Check if the specified PVs are connected.
|
|
774
|
+
|
|
775
|
+
Args:
|
|
776
|
+
pv_list (list): the PV names
|
|
777
|
+
is_local (bool, optional): whether to automatically prepend the
|
|
778
|
+
local inst prefix to the PV names
|
|
779
|
+
|
|
780
|
+
Returns:
|
|
781
|
+
list: the PV names that are connected
|
|
782
|
+
"""
|
|
783
|
+
return _genie_api.connected_pvs_in_list(pv_list, is_local=is_local)
|
|
784
|
+
|
|
785
|
+
|
|
786
|
+
@usercommand
|
|
787
|
+
@helparglist("...")
|
|
788
|
+
@log_command_and_handle_exception
|
|
789
|
+
def begin(
|
|
790
|
+
period: int = 1,
|
|
791
|
+
meas_id: str | None = None,
|
|
792
|
+
meas_type: str = "",
|
|
793
|
+
meas_subid: str = "",
|
|
794
|
+
sample_id: str = "",
|
|
795
|
+
delayed: bool = False,
|
|
796
|
+
quiet: bool = False,
|
|
797
|
+
paused: bool = False,
|
|
798
|
+
verbose: bool = False,
|
|
799
|
+
prepost: bool = True,
|
|
800
|
+
) -> None:
|
|
801
|
+
"""
|
|
802
|
+
Starts a data collection run.
|
|
803
|
+
|
|
804
|
+
Args:
|
|
805
|
+
period (int, optional): the period to begin data collection in
|
|
806
|
+
meas_id (string, optional): the measurement id
|
|
807
|
+
meas_type (string, optional): the type of measurement
|
|
808
|
+
meas_subid (string, optional): the measurement sub-id
|
|
809
|
+
sample_id (string, optional): the sample id
|
|
810
|
+
delayed (bool, optional): puts the period card to into delayed start mode
|
|
811
|
+
quiet (bool, optional): suppress the output to the screen
|
|
812
|
+
paused (bool, optional): begin in the paused state
|
|
813
|
+
verbose (bool, optional): show the messages from the DAE
|
|
814
|
+
prepost (bool, optional): run pre and post commands (default: True)
|
|
815
|
+
Returns:
|
|
816
|
+
Any: return what the begin_postcmd method returns
|
|
817
|
+
"""
|
|
818
|
+
# Returns None if we should start the run or the reason why if not
|
|
819
|
+
pre_post_cmd_return = _genie_api.pre_post_cmd_manager.begin_precmd(quiet=quiet, prepost=prepost)
|
|
820
|
+
if pre_post_cmd_return is None:
|
|
821
|
+
_genie_api.dae.begin_run(
|
|
822
|
+
period, meas_id, meas_type, meas_subid, sample_id, delayed, quiet, paused, prepost
|
|
823
|
+
)
|
|
824
|
+
|
|
825
|
+
waitfor_runstate("SETUP", onexit=True)
|
|
826
|
+
|
|
827
|
+
_genie_api.dae.post_begin_check(verbose)
|
|
828
|
+
_genie_api.pre_post_cmd_manager.begin_postcmd(
|
|
829
|
+
run_num=_genie_api.dae.get_run_number(), quiet=quiet, prepost=prepost
|
|
830
|
+
)
|
|
831
|
+
else:
|
|
832
|
+
print(str(pre_post_cmd_return))
|
|
833
|
+
|
|
834
|
+
|
|
835
|
+
@usercommand
|
|
836
|
+
@helparglist("[verbose], [prepost]")
|
|
837
|
+
@log_command_and_handle_exception
|
|
838
|
+
def abort(verbose: bool = False, prepost: bool = True) -> None:
|
|
839
|
+
"""
|
|
840
|
+
Abort the current run.
|
|
841
|
+
|
|
842
|
+
Args:
|
|
843
|
+
verbose (bool, optional): show the messages from the DAE
|
|
844
|
+
prepost (bool, optional): run pre and post commands (default: True)
|
|
845
|
+
"""
|
|
846
|
+
_genie_api.pre_post_cmd_manager.abort_precmd(prepost=prepost)
|
|
847
|
+
_genie_api.dae.abort_run(prepost)
|
|
848
|
+
_genie_api.dae.post_abort_check(verbose)
|
|
849
|
+
_genie_api.pre_post_cmd_manager.abort_postcmd(prepost=prepost)
|
|
850
|
+
|
|
851
|
+
|
|
852
|
+
@usercommand
|
|
853
|
+
@helparglist("[verbose], [quiet], [immediate], [prepost]")
|
|
854
|
+
@log_command_and_handle_exception
|
|
855
|
+
def end(
|
|
856
|
+
verbose: bool = False, quiet: bool = False, immediate: bool = False, prepost: bool = False
|
|
857
|
+
) -> None:
|
|
858
|
+
"""
|
|
859
|
+
End the current run.
|
|
860
|
+
|
|
861
|
+
Args:
|
|
862
|
+
verbose (bool, optional): show the messages from the DAE
|
|
863
|
+
quiet (bool, optional): suppress the end_precmd output to the screen
|
|
864
|
+
immediate (bool, optional): end immediately, without waiting for
|
|
865
|
+
a period sequence to complete
|
|
866
|
+
prepost (bool, optional): run pre and post commands (default: True)
|
|
867
|
+
"""
|
|
868
|
+
_genie_api.pre_post_cmd_manager.end_precmd(quiet=quiet, prepost=prepost)
|
|
869
|
+
_genie_api.dae.end_run(verbose=verbose, quiet=quiet, immediate=immediate, prepost=prepost)
|
|
870
|
+
waitfor_runstate("SETUP")
|
|
871
|
+
_genie_api.dae.post_end_check(verbose)
|
|
872
|
+
_genie_api.pre_post_cmd_manager.end_postcmd(quiet=quiet, prepost=prepost)
|
|
873
|
+
|
|
874
|
+
|
|
875
|
+
@usercommand
|
|
876
|
+
@helparglist("[verbose], [immediate], [prepost]")
|
|
877
|
+
@log_command_and_handle_exception
|
|
878
|
+
def pause(verbose: bool = False, immediate: bool = False, prepost: bool = True) -> None:
|
|
879
|
+
"""
|
|
880
|
+
Pause the current run.
|
|
881
|
+
|
|
882
|
+
Args:
|
|
883
|
+
verbose (bool, optional): show the messages from the DAE
|
|
884
|
+
immediate (bool, optional): pause immediately,
|
|
885
|
+
without waiting for a period sequence to complete
|
|
886
|
+
prepost (bool, optional): run pre and post commands (default: True)
|
|
887
|
+
"""
|
|
888
|
+
_genie_api.pre_post_cmd_manager.pause_precmd(prepost=prepost)
|
|
889
|
+
_genie_api.dae.pause_run(immediate=immediate, prepost=prepost)
|
|
890
|
+
_genie_api.dae.post_pause_check(verbose)
|
|
891
|
+
_genie_api.pre_post_cmd_manager.pause_postcmd(prepost=prepost)
|
|
892
|
+
|
|
893
|
+
|
|
894
|
+
@usercommand
|
|
895
|
+
@helparglist("[verbose], [prepost]")
|
|
896
|
+
@log_command_and_handle_exception
|
|
897
|
+
def resume(verbose: bool = False, prepost: bool = False) -> None:
|
|
898
|
+
"""
|
|
899
|
+
Resume the current run after it has been paused.
|
|
900
|
+
|
|
901
|
+
Args:
|
|
902
|
+
verbose (bool, optional): show the messages from the DAE
|
|
903
|
+
prepost (bool, optional): run pre and post commands (default: True)
|
|
904
|
+
"""
|
|
905
|
+
_genie_api.pre_post_cmd_manager.resume_precmd(prepost=prepost)
|
|
906
|
+
_genie_api.dae.resume_run(prepost)
|
|
907
|
+
_genie_api.dae.post_resume_check(verbose)
|
|
908
|
+
_genie_api.pre_post_cmd_manager.resume_postcmd(prepost=prepost)
|
|
909
|
+
|
|
910
|
+
|
|
911
|
+
@usercommand
|
|
912
|
+
@helparglist("[verbose]")
|
|
913
|
+
@log_command_and_handle_exception
|
|
914
|
+
def recover(verbose: bool = False) -> None:
|
|
915
|
+
"""
|
|
916
|
+
Recovers the run if it has been aborted.
|
|
917
|
+
The command should be run before the next run is started.
|
|
918
|
+
|
|
919
|
+
Note: the run will be recovered in the paused state.
|
|
920
|
+
|
|
921
|
+
Args:
|
|
922
|
+
verbose (bool, optional): show the messages from the DAE
|
|
923
|
+
"""
|
|
924
|
+
_genie_api.dae.recover_run()
|
|
925
|
+
waitfor_runstate("SETUP", onexit=True)
|
|
926
|
+
_genie_api.dae.post_recover_check(verbose)
|
|
927
|
+
|
|
928
|
+
|
|
929
|
+
@usercommand
|
|
930
|
+
@helparglist("[verbose]")
|
|
931
|
+
@log_command_and_handle_exception
|
|
932
|
+
def updatestore(verbose: bool = False) -> None:
|
|
933
|
+
"""
|
|
934
|
+
Performs an update and a store operation in a combined operation.
|
|
935
|
+
This is more efficient than doing the commands separately.
|
|
936
|
+
|
|
937
|
+
Args:
|
|
938
|
+
verbose (bool, optional): show the messages from the DAE
|
|
939
|
+
"""
|
|
940
|
+
_genie_api.dae.update_store_run()
|
|
941
|
+
waitfor_runstate("SAVING", onexit=True)
|
|
942
|
+
_genie_api.dae.post_update_store_check(verbose)
|
|
943
|
+
|
|
944
|
+
|
|
945
|
+
@usercommand
|
|
946
|
+
@helparglist("[pause_run], [verbose]")
|
|
947
|
+
@log_command_and_handle_exception
|
|
948
|
+
def update(pause_run: bool = True, verbose: bool = False) -> None:
|
|
949
|
+
"""
|
|
950
|
+
Data is loaded from the DAE into the computer memory, but is not written to disk.
|
|
951
|
+
|
|
952
|
+
Args:
|
|
953
|
+
pause_run (bool, optional): whether to pause data collection first [optional]
|
|
954
|
+
verbose (bool, optional): show the messages from the DAE
|
|
955
|
+
"""
|
|
956
|
+
if pause_run:
|
|
957
|
+
# Pause
|
|
958
|
+
pause(verbose=verbose)
|
|
959
|
+
|
|
960
|
+
# Update
|
|
961
|
+
_genie_api.dae.update_run()
|
|
962
|
+
waitfor_runstate("UPDATING", onexit=True)
|
|
963
|
+
_genie_api.dae.post_update_check(verbose)
|
|
964
|
+
|
|
965
|
+
if pause_run:
|
|
966
|
+
# Resume
|
|
967
|
+
resume(verbose=verbose)
|
|
968
|
+
|
|
969
|
+
|
|
970
|
+
@usercommand
|
|
971
|
+
@helparglist("[verbose]")
|
|
972
|
+
@log_command_and_handle_exception
|
|
973
|
+
def store(verbose: bool = False) -> None:
|
|
974
|
+
"""
|
|
975
|
+
Data loaded into memory by a previous update command is now written to disk.
|
|
976
|
+
|
|
977
|
+
Args:
|
|
978
|
+
verbose (bool, optional): show the messages from the DAE
|
|
979
|
+
"""
|
|
980
|
+
_genie_api.dae.store_run()
|
|
981
|
+
waitfor_runstate("STORING", onexit=True)
|
|
982
|
+
_genie_api.dae.post_store_check(verbose)
|
|
983
|
+
|
|
984
|
+
|
|
985
|
+
@usercommand
|
|
986
|
+
@helparglist("[filename], [verbose]")
|
|
987
|
+
@log_command_and_handle_exception
|
|
988
|
+
def snapshot_crpt(filename: str = "c:\\Data\\snapshot_crpt.tmp", verbose: bool = False) -> None:
|
|
989
|
+
"""
|
|
990
|
+
Create a snapshot of the current data.
|
|
991
|
+
|
|
992
|
+
Args:
|
|
993
|
+
filename (string, optional): where to write the data file(s)
|
|
994
|
+
verbose (bool, optional): show the messages from the DAE
|
|
995
|
+
|
|
996
|
+
Examples:
|
|
997
|
+
Snapshot to a file called my_snapshot:
|
|
998
|
+
|
|
999
|
+
>>> snapshot_crpt("c:\\Data\\my_snapshot")
|
|
1000
|
+
"""
|
|
1001
|
+
name = get_correct_path(filename)
|
|
1002
|
+
_genie_api.dae.snapshot_crpt(name)
|
|
1003
|
+
waitfor_runstate("STORING", onexit=True)
|
|
1004
|
+
_genie_api.dae.post_snapshot_check(verbose)
|
|
1005
|
+
|
|
1006
|
+
|
|
1007
|
+
@usercommand
|
|
1008
|
+
@helparglist("[period]")
|
|
1009
|
+
@log_command_and_handle_exception
|
|
1010
|
+
def get_uamps(period: bool = False) -> float:
|
|
1011
|
+
"""
|
|
1012
|
+
Get the current number of micro-amp hours.
|
|
1013
|
+
|
|
1014
|
+
Args:
|
|
1015
|
+
period (bool, optional): whether to return the value for the current period only
|
|
1016
|
+
|
|
1017
|
+
Returns:
|
|
1018
|
+
float: the number of uamps
|
|
1019
|
+
"""
|
|
1020
|
+
return _genie_api.dae.get_uamps(period)
|
|
1021
|
+
|
|
1022
|
+
|
|
1023
|
+
@usercommand
|
|
1024
|
+
@helparglist("[period]")
|
|
1025
|
+
@log_command_and_handle_exception
|
|
1026
|
+
def get_frames(period: bool = False) -> int:
|
|
1027
|
+
"""
|
|
1028
|
+
Gets the current number of good frames.
|
|
1029
|
+
|
|
1030
|
+
Args:
|
|
1031
|
+
period (bool, optional): whether to return the value for the current period only
|
|
1032
|
+
|
|
1033
|
+
Returns:
|
|
1034
|
+
int: the number of frames
|
|
1035
|
+
"""
|
|
1036
|
+
return _genie_api.dae.get_good_frames(period)
|
|
1037
|
+
|
|
1038
|
+
|
|
1039
|
+
@usercommand
|
|
1040
|
+
@helparglist("[period]")
|
|
1041
|
+
@log_command_and_handle_exception
|
|
1042
|
+
def get_raw_frames(period: bool = False) -> int:
|
|
1043
|
+
"""
|
|
1044
|
+
Gets the current number of raw frames.
|
|
1045
|
+
|
|
1046
|
+
Args:
|
|
1047
|
+
period (bool, optional): whether to return the value for the current period only
|
|
1048
|
+
|
|
1049
|
+
Returns:
|
|
1050
|
+
int: the number of raw frames
|
|
1051
|
+
"""
|
|
1052
|
+
return _genie_api.dae.get_raw_frames(period)
|
|
1053
|
+
|
|
1054
|
+
|
|
1055
|
+
@usercommand
|
|
1056
|
+
@helparglist("")
|
|
1057
|
+
@log_command_and_handle_exception
|
|
1058
|
+
def get_runstate() -> str:
|
|
1059
|
+
"""
|
|
1060
|
+
Get the current status of the instrument as a string.
|
|
1061
|
+
|
|
1062
|
+
Note: this value can take a few seconds to update after a change of state.
|
|
1063
|
+
|
|
1064
|
+
Returns:
|
|
1065
|
+
string: the current run state
|
|
1066
|
+
"""
|
|
1067
|
+
return _genie_api.dae.get_run_state()
|
|
1068
|
+
|
|
1069
|
+
|
|
1070
|
+
@usercommand
|
|
1071
|
+
@helparglist("")
|
|
1072
|
+
@log_command_and_handle_exception
|
|
1073
|
+
def get_time_since_begin(get_timedelta: bool = False) -> float | datetime.timedelta:
|
|
1074
|
+
"""
|
|
1075
|
+
Gets the time since start of the current run in seconds or in datetime
|
|
1076
|
+
|
|
1077
|
+
Args:
|
|
1078
|
+
get_timedelta (bool): If true return the value as a datetime object,
|
|
1079
|
+
otherwise return seconds (defaults to false)
|
|
1080
|
+
|
|
1081
|
+
Returns
|
|
1082
|
+
integer: the time since start in seconds if get_datetime is False,
|
|
1083
|
+
or timedelta, the time since begin as a datetime.timedelta object
|
|
1084
|
+
(Year-Month-Day Hour:Minute:Second) if get_datetime is True
|
|
1085
|
+
"""
|
|
1086
|
+
|
|
1087
|
+
return _genie_api.dae.get_time_since_begin(get_timedelta)
|
|
1088
|
+
|
|
1089
|
+
|
|
1090
|
+
@usercommand
|
|
1091
|
+
@helparglist("")
|
|
1092
|
+
@log_command_and_handle_exception
|
|
1093
|
+
def get_events() -> int:
|
|
1094
|
+
"""
|
|
1095
|
+
Gets the total events for all the detectors.
|
|
1096
|
+
|
|
1097
|
+
Returns:
|
|
1098
|
+
int: the number of events
|
|
1099
|
+
"""
|
|
1100
|
+
return _genie_api.dae.get_events()
|
|
1101
|
+
|
|
1102
|
+
|
|
1103
|
+
@usercommand
|
|
1104
|
+
@helparglist("")
|
|
1105
|
+
@log_command_and_handle_exception
|
|
1106
|
+
def get_mevents() -> float:
|
|
1107
|
+
"""
|
|
1108
|
+
Gets the total millions of events for all the detectors.
|
|
1109
|
+
|
|
1110
|
+
Returns:
|
|
1111
|
+
float: the number of millions of events
|
|
1112
|
+
"""
|
|
1113
|
+
return _genie_api.dae.get_mevents()
|
|
1114
|
+
|
|
1115
|
+
|
|
1116
|
+
@usercommand
|
|
1117
|
+
@helparglist("")
|
|
1118
|
+
@log_command_and_handle_exception
|
|
1119
|
+
def get_period() -> int:
|
|
1120
|
+
"""
|
|
1121
|
+
Gets the current period number.
|
|
1122
|
+
|
|
1123
|
+
Returns:
|
|
1124
|
+
int: the current period
|
|
1125
|
+
"""
|
|
1126
|
+
return _genie_api.dae.get_period()
|
|
1127
|
+
|
|
1128
|
+
|
|
1129
|
+
@usercommand
|
|
1130
|
+
@helparglist("")
|
|
1131
|
+
@log_command_and_handle_exception
|
|
1132
|
+
def get_number_periods() -> int:
|
|
1133
|
+
"""
|
|
1134
|
+
Get the number of software periods.
|
|
1135
|
+
|
|
1136
|
+
Returns:
|
|
1137
|
+
int: the number of periods
|
|
1138
|
+
"""
|
|
1139
|
+
return _genie_api.dae.get_num_periods()
|
|
1140
|
+
|
|
1141
|
+
|
|
1142
|
+
@usercommand
|
|
1143
|
+
@helparglist("")
|
|
1144
|
+
@log_command_and_handle_exception
|
|
1145
|
+
def get_number_timechannels() -> int:
|
|
1146
|
+
"""
|
|
1147
|
+
Get the number of time channels. This is the number of bins used
|
|
1148
|
+
to map the time region of interest, it does not include the
|
|
1149
|
+
special diagnostic "bin zero" in this count but this fact is not
|
|
1150
|
+
normally of interest to most users.
|
|
1151
|
+
|
|
1152
|
+
Returns:
|
|
1153
|
+
int: the number of time channels
|
|
1154
|
+
"""
|
|
1155
|
+
return _genie_api.dae.get_num_timechannels()
|
|
1156
|
+
|
|
1157
|
+
|
|
1158
|
+
@usercommand
|
|
1159
|
+
@helparglist("")
|
|
1160
|
+
@log_command_and_handle_exception
|
|
1161
|
+
def get_number_spectra() -> int:
|
|
1162
|
+
"""
|
|
1163
|
+
Get the number of spectra. The diagnostic spectrum zero
|
|
1164
|
+
is not included in the count, so valid spectrum numbers
|
|
1165
|
+
are 0 to get_number_spectra()
|
|
1166
|
+
|
|
1167
|
+
Returns:
|
|
1168
|
+
int: the number of spectra
|
|
1169
|
+
"""
|
|
1170
|
+
return _genie_api.dae.get_num_spectra()
|
|
1171
|
+
|
|
1172
|
+
|
|
1173
|
+
@usercommand
|
|
1174
|
+
@helparglist("")
|
|
1175
|
+
@log_command_and_handle_exception
|
|
1176
|
+
def get_spectrum_integrals(with_spec_zero: bool = True) -> npt.NDArray:
|
|
1177
|
+
"""
|
|
1178
|
+
Get the event mode spectrum integrals as numpy ND array.
|
|
1179
|
+
|
|
1180
|
+
Args:
|
|
1181
|
+
with_spec_zero (bool, optional): Include or exclude diagnostic spectrum 0
|
|
1182
|
+
if you have 10 spectra and include spectrum zero, your array will be
|
|
1183
|
+
of size 11 and spectrum 5 will be at array[5]. If you exclude spectrum zero
|
|
1184
|
+
then spectrum 5 would be at array[4]
|
|
1185
|
+
|
|
1186
|
+
Returns:
|
|
1187
|
+
numpy int array: spectrum integrals numpy ND array
|
|
1188
|
+
this is of dimensions [periods, spectra]
|
|
1189
|
+
"""
|
|
1190
|
+
data = _genie_api.dae.get_spec_integrals()
|
|
1191
|
+
nper = get_number_periods()
|
|
1192
|
+
nsp = get_number_spectra()
|
|
1193
|
+
# original array is nsp + 1 as has spectrum 0
|
|
1194
|
+
data_reshaped = data.reshape((nper, nsp + 1))
|
|
1195
|
+
return data_reshaped if with_spec_zero else data_reshaped[:, 1:]
|
|
1196
|
+
|
|
1197
|
+
|
|
1198
|
+
@usercommand
|
|
1199
|
+
@helparglist("")
|
|
1200
|
+
@log_command_and_handle_exception
|
|
1201
|
+
def get_spectrum_data(with_spec_zero: bool = True) -> npt.NDArray:
|
|
1202
|
+
"""
|
|
1203
|
+
Get the event mode spectrum data as numpy ND array.
|
|
1204
|
+
|
|
1205
|
+
Args:
|
|
1206
|
+
with_spec_zero (bool, optional): Include or exclude diagnostic spectrum 0
|
|
1207
|
+
if you have 10 spectra and include spectrum zero, you array will be
|
|
1208
|
+
of size 11 and spectrum 5 will be at array[5]. If you exclude spectrum zero
|
|
1209
|
+
then spectrum 5 would be at array[4]
|
|
1210
|
+
|
|
1211
|
+
Returns:
|
|
1212
|
+
numpy int array: spectrum data ND array
|
|
1213
|
+
this is of dimensions [periods, spectra, time_bins]
|
|
1214
|
+
"""
|
|
1215
|
+
|
|
1216
|
+
return adv.get_spectrum_data(with_spec_zero=with_spec_zero)
|
|
1217
|
+
|
|
1218
|
+
|
|
1219
|
+
@usercommand
|
|
1220
|
+
@helparglist("")
|
|
1221
|
+
@log_command_and_handle_exception
|
|
1222
|
+
def get_runnumber() -> str:
|
|
1223
|
+
"""
|
|
1224
|
+
Get the current run-number.
|
|
1225
|
+
|
|
1226
|
+
Returns:
|
|
1227
|
+
string: the run-number
|
|
1228
|
+
"""
|
|
1229
|
+
return _genie_api.dae.get_run_number()
|
|
1230
|
+
|
|
1231
|
+
|
|
1232
|
+
@usercommand
|
|
1233
|
+
@helparglist("")
|
|
1234
|
+
@log_command_and_handle_exception
|
|
1235
|
+
def get_totalcounts() -> int:
|
|
1236
|
+
"""
|
|
1237
|
+
Get the total counts for the current run.
|
|
1238
|
+
|
|
1239
|
+
Returns:
|
|
1240
|
+
int: the total counts
|
|
1241
|
+
"""
|
|
1242
|
+
return _genie_api.dae.get_total_counts()
|
|
1243
|
+
|
|
1244
|
+
|
|
1245
|
+
@usercommand
|
|
1246
|
+
@helparglist("")
|
|
1247
|
+
@log_command_and_handle_exception
|
|
1248
|
+
def get_title() -> str:
|
|
1249
|
+
"""
|
|
1250
|
+
Returns the current title.
|
|
1251
|
+
|
|
1252
|
+
Returns:
|
|
1253
|
+
string: the title
|
|
1254
|
+
"""
|
|
1255
|
+
return _genie_api.dae.get_title()
|
|
1256
|
+
|
|
1257
|
+
|
|
1258
|
+
@usercommand
|
|
1259
|
+
@helparglist("")
|
|
1260
|
+
@log_command_and_handle_exception
|
|
1261
|
+
def get_display_title() -> bool:
|
|
1262
|
+
"""
|
|
1263
|
+
Returns the current display title status.
|
|
1264
|
+
|
|
1265
|
+
Returns:
|
|
1266
|
+
boolean: the display title status
|
|
1267
|
+
"""
|
|
1268
|
+
return _genie_api.dae.get_display_title()
|
|
1269
|
+
|
|
1270
|
+
|
|
1271
|
+
@usercommand
|
|
1272
|
+
@helparglist("")
|
|
1273
|
+
@log_command_and_handle_exception
|
|
1274
|
+
def get_rb() -> str:
|
|
1275
|
+
"""
|
|
1276
|
+
Returns the current RB number.
|
|
1277
|
+
|
|
1278
|
+
Returns:
|
|
1279
|
+
string: the RB number
|
|
1280
|
+
"""
|
|
1281
|
+
return _genie_api.dae.get_rb_number()
|
|
1282
|
+
|
|
1283
|
+
|
|
1284
|
+
class _GetdashboardReturn(TypedDict):
|
|
1285
|
+
status: str
|
|
1286
|
+
run_number: str
|
|
1287
|
+
rb_number: str
|
|
1288
|
+
user: str
|
|
1289
|
+
title: str
|
|
1290
|
+
display_title: str
|
|
1291
|
+
run_time: int
|
|
1292
|
+
good_frames_total: int
|
|
1293
|
+
good_frames_period: int
|
|
1294
|
+
raw_frames_total: int
|
|
1295
|
+
raw_frames_period: int
|
|
1296
|
+
beam_current: float
|
|
1297
|
+
total_current: float
|
|
1298
|
+
spectra: int
|
|
1299
|
+
periods: int
|
|
1300
|
+
time_channels: int
|
|
1301
|
+
monitor_spectrum: int
|
|
1302
|
+
monitor_from: float
|
|
1303
|
+
monitor_to: float
|
|
1304
|
+
monitor_counts: int
|
|
1305
|
+
|
|
1306
|
+
|
|
1307
|
+
@usercommand
|
|
1308
|
+
@helparglist("")
|
|
1309
|
+
@log_command_and_handle_exception
|
|
1310
|
+
def get_dashboard() -> _GetdashboardReturn:
|
|
1311
|
+
"""
|
|
1312
|
+
Get the current experiment values.
|
|
1313
|
+
|
|
1314
|
+
Returns:
|
|
1315
|
+
dict: the experiment values
|
|
1316
|
+
"""
|
|
1317
|
+
data = dict()
|
|
1318
|
+
data["status"] = _genie_api.dae.get_run_state()
|
|
1319
|
+
data["run_number"] = _genie_api.dae.get_run_number()
|
|
1320
|
+
data["rb_number"] = _genie_api.dae.get_rb_number()
|
|
1321
|
+
data["user"] = _genie_api.dae.get_users()
|
|
1322
|
+
data["title"] = _genie_api.dae.get_title()
|
|
1323
|
+
data["display_title"] = _genie_api.dae.get_display_title()
|
|
1324
|
+
data["run_time"] = _genie_api.dae.get_run_duration()
|
|
1325
|
+
data["good_frames_total"] = _genie_api.dae.get_good_frames()
|
|
1326
|
+
data["good_frames_period"] = _genie_api.dae.get_good_frames(True)
|
|
1327
|
+
data["raw_frames_total"] = _genie_api.dae.get_raw_frames()
|
|
1328
|
+
data["raw_frames_period"] = _genie_api.dae.get_raw_frames(True)
|
|
1329
|
+
data["beam_current"] = _genie_api.dae.get_beam_current()
|
|
1330
|
+
data["total_current"] = _genie_api.dae.get_total_uamps()
|
|
1331
|
+
data["spectra"] = _genie_api.dae.get_num_spectra()
|
|
1332
|
+
# data["dae_memory_used"] = genie_api.dae.get_memory_used()
|
|
1333
|
+
# Not implemented in EPICS system
|
|
1334
|
+
data["periods"] = _genie_api.dae.get_num_periods()
|
|
1335
|
+
data["time_channels"] = _genie_api.dae.get_num_timechannels()
|
|
1336
|
+
data["monitor_spectrum"] = _genie_api.dae.get_monitor_spectrum()
|
|
1337
|
+
data["monitor_from"] = _genie_api.dae.get_monitor_from()
|
|
1338
|
+
data["monitor_to"] = _genie_api.dae.get_monitor_to()
|
|
1339
|
+
data["monitor_counts"] = _genie_api.dae.get_monitor_counts()
|
|
1340
|
+
return data
|
|
1341
|
+
|
|
1342
|
+
|
|
1343
|
+
def _get_correct_globals() -> dict[types.FrameType, int]:
|
|
1344
|
+
"""
|
|
1345
|
+
This is a hack to find the frame in which to add the script function(s).
|
|
1346
|
+
|
|
1347
|
+
The frame we want is the outermost one that contains a reference to cshow().
|
|
1348
|
+
"""
|
|
1349
|
+
import inspect
|
|
1350
|
+
|
|
1351
|
+
globs = dict()
|
|
1352
|
+
|
|
1353
|
+
for i in inspect.stack():
|
|
1354
|
+
if "cshow" in i[0].f_globals:
|
|
1355
|
+
globs = i[0].f_globals
|
|
1356
|
+
return globs
|
|
1357
|
+
|
|
1358
|
+
|
|
1359
|
+
def load_script(name: str, check_script: bool = True, warnings_as_error: bool = False) -> None:
|
|
1360
|
+
"""
|
|
1361
|
+
Loads a user script.
|
|
1362
|
+
|
|
1363
|
+
Args:
|
|
1364
|
+
name (string): the name of the file to load. If this is not a
|
|
1365
|
+
full path the file is assumed to be in C:\\scripts
|
|
1366
|
+
check_script: When True run the script checker on the script;
|
|
1367
|
+
False otherwise (default True)
|
|
1368
|
+
warnings_as_error: When true throw an exception on a warning;
|
|
1369
|
+
False otherwise (default False)
|
|
1370
|
+
"""
|
|
1371
|
+
|
|
1372
|
+
globs = _get_correct_globals()
|
|
1373
|
+
|
|
1374
|
+
_genie_api.logger.log_info_msg("Trying to resolve full filename for %s" % name)
|
|
1375
|
+
|
|
1376
|
+
try:
|
|
1377
|
+
try:
|
|
1378
|
+
full_name = get_correct_filepath_existing(name)
|
|
1379
|
+
except Exception:
|
|
1380
|
+
# Try with default script directory prepended
|
|
1381
|
+
|
|
1382
|
+
full_name = get_correct_filepath_existing(os.path.join(get_user_script_dir(), name))
|
|
1383
|
+
except Exception:
|
|
1384
|
+
raise Exception("Script file was not found (%s)" % get_correct_path(name))
|
|
1385
|
+
|
|
1386
|
+
_genie_api.logger.log_info_msg("Trying to load script from: %s" % full_name)
|
|
1387
|
+
|
|
1388
|
+
directory, filename = os.path.split(os.path.abspath(full_name))
|
|
1389
|
+
|
|
1390
|
+
# Add the directory to the path in case there are relative imports
|
|
1391
|
+
if directory not in sys.path:
|
|
1392
|
+
sys.path.append(directory)
|
|
1393
|
+
|
|
1394
|
+
try:
|
|
1395
|
+
# Now check the script details with a linter
|
|
1396
|
+
if check_script:
|
|
1397
|
+
instrument_full_name = _genie_api.get_instrument_full_name()
|
|
1398
|
+
sc = ScriptChecker()
|
|
1399
|
+
errs = sc.check_script(
|
|
1400
|
+
full_name, instrument_full_name, warnings_as_error=warnings_as_error
|
|
1401
|
+
)
|
|
1402
|
+
if len(errs) > 0:
|
|
1403
|
+
combined = "script not loaded as errors found in script: "
|
|
1404
|
+
for e in errs:
|
|
1405
|
+
combined += "\n\t" + e
|
|
1406
|
+
raise Exception(combined)
|
|
1407
|
+
|
|
1408
|
+
mod = __load_module(filename[0:-3], directory)
|
|
1409
|
+
# Safe to load
|
|
1410
|
+
# Read the file to get the name of the functions
|
|
1411
|
+
funcs = []
|
|
1412
|
+
file_path = os.path.join(directory, filename)
|
|
1413
|
+
with open(file_path) as f:
|
|
1414
|
+
for line in f.readlines():
|
|
1415
|
+
m = re.match(r"^def\s+(.+)\(", line)
|
|
1416
|
+
if m is not None:
|
|
1417
|
+
funcs.append(m.group(1))
|
|
1418
|
+
|
|
1419
|
+
scripts = []
|
|
1420
|
+
for att in dir(mod):
|
|
1421
|
+
if isinstance(mod.__dict__.get(att), types.FunctionType):
|
|
1422
|
+
# Check function comes from script file not an import
|
|
1423
|
+
if att in funcs:
|
|
1424
|
+
scripts.append(att)
|
|
1425
|
+
|
|
1426
|
+
if len(scripts) > 0:
|
|
1427
|
+
# This is where the script file is actually loaded
|
|
1428
|
+
with open(file_path) as f:
|
|
1429
|
+
file_contents = f.read()
|
|
1430
|
+
|
|
1431
|
+
# dont_inherit=True so that __future__
|
|
1432
|
+
# statements in this file are not propagated to user scripts
|
|
1433
|
+
code = compile(file_contents, file_path, "exec", dont_inherit=True)
|
|
1434
|
+
exec(code, globs)
|
|
1435
|
+
|
|
1436
|
+
msg = "Loaded the following script(s): "
|
|
1437
|
+
for script in scripts:
|
|
1438
|
+
msg += script + ", "
|
|
1439
|
+
print(msg[0:-2])
|
|
1440
|
+
print("From: %s" % file_path)
|
|
1441
|
+
|
|
1442
|
+
print(
|
|
1443
|
+
"File last modified: %s"
|
|
1444
|
+
% datetime.datetime.fromtimestamp(os.path.getmtime(file_path)).strftime(
|
|
1445
|
+
"%Y-%m-%d %H:%M:%S"
|
|
1446
|
+
)
|
|
1447
|
+
)
|
|
1448
|
+
else:
|
|
1449
|
+
raise Exception(
|
|
1450
|
+
"No scripts found in {} - please ensure all your code is"
|
|
1451
|
+
" contained within functions.".format(file_path)
|
|
1452
|
+
)
|
|
1453
|
+
except Exception as e:
|
|
1454
|
+
if directory in sys.path:
|
|
1455
|
+
sys.path.remove(directory)
|
|
1456
|
+
raise
|
|
1457
|
+
|
|
1458
|
+
|
|
1459
|
+
def __load_module(name: str, directory: str) -> types.ModuleType:
|
|
1460
|
+
"""
|
|
1461
|
+
This will reload the module if it has already been loaded.
|
|
1462
|
+
"""
|
|
1463
|
+
fpath = None
|
|
1464
|
+
try:
|
|
1465
|
+
fpath, pathname, description = imp.find_module(name, [directory])
|
|
1466
|
+
return imp.load_module(name, fpath, pathname, description)
|
|
1467
|
+
finally:
|
|
1468
|
+
# Since we may exit via an exception, close fpath explicitly.
|
|
1469
|
+
if fpath is not None:
|
|
1470
|
+
fpath.close()
|
|
1471
|
+
|
|
1472
|
+
|
|
1473
|
+
@log_command_and_handle_exception
|
|
1474
|
+
def get_script_dir() -> str:
|
|
1475
|
+
"""
|
|
1476
|
+
Get the current script directory.
|
|
1477
|
+
|
|
1478
|
+
Returns:
|
|
1479
|
+
string: the directory
|
|
1480
|
+
"""
|
|
1481
|
+
return get_user_script_dir()
|
|
1482
|
+
|
|
1483
|
+
|
|
1484
|
+
@log_command_and_handle_exception
|
|
1485
|
+
def change_script_dir(*directory: str) -> None:
|
|
1486
|
+
"""
|
|
1487
|
+
Set the directory for loading user scripts from.
|
|
1488
|
+
|
|
1489
|
+
Args:
|
|
1490
|
+
directory (string|List(string)): the directory to load user scripts from,
|
|
1491
|
+
either as a single entry or as multiple arguments
|
|
1492
|
+
Example:
|
|
1493
|
+
g.change_script_dir(r"c/scrips/mydir")
|
|
1494
|
+
g.change_script_dir(r"c/scrips", "mydir")
|
|
1495
|
+
|
|
1496
|
+
|
|
1497
|
+
"""
|
|
1498
|
+
set_user_script_dir(*directory)
|
|
1499
|
+
|
|
1500
|
+
|
|
1501
|
+
@usercommand
|
|
1502
|
+
@helparglist("")
|
|
1503
|
+
@log_command_and_handle_exception
|
|
1504
|
+
def change_start() -> None:
|
|
1505
|
+
"""
|
|
1506
|
+
Start a change operation.
|
|
1507
|
+
|
|
1508
|
+
The operation is finished when change_finish is called.
|
|
1509
|
+
|
|
1510
|
+
Between these two calls a sequence of other change commands can be called.
|
|
1511
|
+
For example: change_tables, change_tcb etc.
|
|
1512
|
+
"""
|
|
1513
|
+
_genie_api.dae.change_start()
|
|
1514
|
+
|
|
1515
|
+
|
|
1516
|
+
@usercommand
|
|
1517
|
+
@helparglist("")
|
|
1518
|
+
@log_command_and_handle_exception
|
|
1519
|
+
def change_finish() -> None:
|
|
1520
|
+
"""
|
|
1521
|
+
End a change operation.
|
|
1522
|
+
|
|
1523
|
+
The operation is begun when change_start is called.
|
|
1524
|
+
|
|
1525
|
+
Between these two calls a sequence of other change commands can be called.
|
|
1526
|
+
For example: change_tables, change_tcb etc.
|
|
1527
|
+
"""
|
|
1528
|
+
_genie_api.dae.change_finish()
|
|
1529
|
+
|
|
1530
|
+
|
|
1531
|
+
@usercommand
|
|
1532
|
+
@helparglist("spec, low, high")
|
|
1533
|
+
@log_command_and_handle_exception
|
|
1534
|
+
def change_monitor(spec: int, low: float, high: float) -> None:
|
|
1535
|
+
"""
|
|
1536
|
+
Change the monitor to a specified spectrum and range.
|
|
1537
|
+
|
|
1538
|
+
Args:
|
|
1539
|
+
spec (int): the spectrum number
|
|
1540
|
+
low (float): the low end of the integral
|
|
1541
|
+
high (float): the high end of the integral
|
|
1542
|
+
"""
|
|
1543
|
+
_genie_api.dae.change_monitor(spec, low, high)
|
|
1544
|
+
|
|
1545
|
+
|
|
1546
|
+
@usercommand
|
|
1547
|
+
@helparglist("[wiring], [detector], [spectra]")
|
|
1548
|
+
@log_command_and_handle_exception
|
|
1549
|
+
def change_tables(
|
|
1550
|
+
wiring: str | None = None, detector: str | None = None, spectra: str | None = None
|
|
1551
|
+
) -> None:
|
|
1552
|
+
"""
|
|
1553
|
+
Load the wiring, detector and/or spectra tables.
|
|
1554
|
+
Checks that the file paths are valid, throws exception if not.
|
|
1555
|
+
Args:
|
|
1556
|
+
wiring (string, optional): the filename of the wiring table file
|
|
1557
|
+
detector (string, optional): the filename of the detector table file
|
|
1558
|
+
spectra (string, optional): the filename of the spectra table file
|
|
1559
|
+
"""
|
|
1560
|
+
|
|
1561
|
+
def get_table_file(path: str) -> str:
|
|
1562
|
+
"""Assume the path is a correct path, if not try it relative to tables directory"""
|
|
1563
|
+
try:
|
|
1564
|
+
return get_correct_filepath_existing(path)
|
|
1565
|
+
except Exception:
|
|
1566
|
+
env_details = EnvironmentDetails()
|
|
1567
|
+
tables_dir = os.path.join(env_details.get_settings_directory(), "tables")
|
|
1568
|
+
return get_correct_filepath_existing(os.path.join(tables_dir, path))
|
|
1569
|
+
|
|
1570
|
+
errors = []
|
|
1571
|
+
if wiring is not None:
|
|
1572
|
+
try:
|
|
1573
|
+
wiring = get_table_file(wiring)
|
|
1574
|
+
except Exception:
|
|
1575
|
+
errors.append(
|
|
1576
|
+
"Could not find wiring table. Did you type the file name correctly? %s" % wiring
|
|
1577
|
+
)
|
|
1578
|
+
if spectra is not None:
|
|
1579
|
+
try:
|
|
1580
|
+
spectra = get_table_file(spectra)
|
|
1581
|
+
except Exception:
|
|
1582
|
+
errors.append(
|
|
1583
|
+
"Could not find spectra table. Did you type the file name correctly? %s" % spectra
|
|
1584
|
+
)
|
|
1585
|
+
if detector is not None:
|
|
1586
|
+
try:
|
|
1587
|
+
detector = get_table_file(detector)
|
|
1588
|
+
except Exception:
|
|
1589
|
+
errors.append(
|
|
1590
|
+
"Could not find detector table. Did you type the file name correctly? %s" % detector
|
|
1591
|
+
)
|
|
1592
|
+
|
|
1593
|
+
if errors:
|
|
1594
|
+
raise FileNotFoundError(" ".join(errors))
|
|
1595
|
+
elif not all(path is None for path in (wiring, detector, spectra)):
|
|
1596
|
+
_genie_api.dae.change_tables(wiring, detector, spectra)
|
|
1597
|
+
else:
|
|
1598
|
+
raise ValueError("No file paths were provided.")
|
|
1599
|
+
|
|
1600
|
+
|
|
1601
|
+
@usercommand
|
|
1602
|
+
@helparglist("source")
|
|
1603
|
+
@log_command_and_handle_exception
|
|
1604
|
+
def change_sync(source: str) -> None:
|
|
1605
|
+
"""
|
|
1606
|
+
Change the source the DAE using for synchronisation.
|
|
1607
|
+
|
|
1608
|
+
Args:
|
|
1609
|
+
source (string): the source to use (
|
|
1610
|
+
'isis',
|
|
1611
|
+
'internal',
|
|
1612
|
+
'smp',
|
|
1613
|
+
'muon cerenkov',
|
|
1614
|
+
'muon ms',
|
|
1615
|
+
'isis (first ts1)'
|
|
1616
|
+
)
|
|
1617
|
+
"""
|
|
1618
|
+
_genie_api.dae.change_sync(source)
|
|
1619
|
+
|
|
1620
|
+
|
|
1621
|
+
@usercommand
|
|
1622
|
+
@helparglist("[tcbfile], [default]")
|
|
1623
|
+
@log_command_and_handle_exception
|
|
1624
|
+
def change_tcb_file(tcbfile: str | None = None, default: bool = False) -> None:
|
|
1625
|
+
"""
|
|
1626
|
+
Change the time channel boundaries.
|
|
1627
|
+
|
|
1628
|
+
Args:
|
|
1629
|
+
tcbfile (string, optional): the file to load
|
|
1630
|
+
default (bool, optional): load the default file
|
|
1631
|
+
"""
|
|
1632
|
+
_genie_api.dae.change_tcb_file(tcbfile, default)
|
|
1633
|
+
|
|
1634
|
+
|
|
1635
|
+
@usercommand
|
|
1636
|
+
@helparglist("[low], [high], [step], [trange], [log], [regime]")
|
|
1637
|
+
@log_command_and_handle_exception
|
|
1638
|
+
def change_tcb(
|
|
1639
|
+
low: float | None = None,
|
|
1640
|
+
high: float | None = None,
|
|
1641
|
+
step: float | None = None,
|
|
1642
|
+
trange: int = 1,
|
|
1643
|
+
log: bool = False,
|
|
1644
|
+
regime: int = 1,
|
|
1645
|
+
) -> None:
|
|
1646
|
+
"""
|
|
1647
|
+
Change the time channel boundaries.
|
|
1648
|
+
If None is specified for low, high or step then the values are left unchanged.
|
|
1649
|
+
|
|
1650
|
+
Args
|
|
1651
|
+
low (float, optional): the lower limit. Default is no change from the current value.
|
|
1652
|
+
high (float, optional): the upper limit. Default is no change from the current value.
|
|
1653
|
+
step (float,optional): the step size. Default is no change from the current value.
|
|
1654
|
+
trange (int, optional): the time range (1 to 5). Default is 1.
|
|
1655
|
+
log (bool, optional): whether to use LOG binning. Default is no.
|
|
1656
|
+
regime (int, optional): the time regime to set (1 to 6). Default is 1.
|
|
1657
|
+
|
|
1658
|
+
Examples:
|
|
1659
|
+
Changes the from, to and step of the 1st range to 0, 10 and 5 respectively.
|
|
1660
|
+
|
|
1661
|
+
>>> change_tcb(0, 10, 5)
|
|
1662
|
+
|
|
1663
|
+
Changes the step size of the 2nd range to 2, leaving other parameters unchanged.
|
|
1664
|
+
|
|
1665
|
+
>>> change_tcb(step=2, trange=2)
|
|
1666
|
+
"""
|
|
1667
|
+
_genie_api.dae.change_tcb(low, high, step, trange, log, regime)
|
|
1668
|
+
|
|
1669
|
+
|
|
1670
|
+
@usercommand
|
|
1671
|
+
@helparglist("trange, [regime]")
|
|
1672
|
+
@log_command_and_handle_exception
|
|
1673
|
+
def get_tcb_settings(trange: int, regime: int = 1) -> dict[str, int]:
|
|
1674
|
+
"""
|
|
1675
|
+
Gets a dictionary of the time channel settings.
|
|
1676
|
+
|
|
1677
|
+
Args:
|
|
1678
|
+
trange (int): the time range to read (1 to 5)
|
|
1679
|
+
regime (int, optional): the regime to read (1 to 6). Default is 1.
|
|
1680
|
+
|
|
1681
|
+
Returns:
|
|
1682
|
+
dict: the low, high and step for the supplied range and regime
|
|
1683
|
+
|
|
1684
|
+
Examples:
|
|
1685
|
+
Get the step size for the 2nd range in the 3rd regime:
|
|
1686
|
+
|
|
1687
|
+
>>> get_tcb_settings(2, 3)["Steps"]
|
|
1688
|
+
|
|
1689
|
+
Get the step size for the 2nd range in the 3rd regime:
|
|
1690
|
+
|
|
1691
|
+
>>> get_tcb_settings(2, 3)["Steps"]
|
|
1692
|
+
"""
|
|
1693
|
+
return _genie_api.dae.get_tcb_settings(trange, regime)
|
|
1694
|
+
|
|
1695
|
+
|
|
1696
|
+
@usercommand
|
|
1697
|
+
@helparglist("[...]")
|
|
1698
|
+
@log_command_and_handle_exception
|
|
1699
|
+
def change_vetos(**params: bool | None) -> None:
|
|
1700
|
+
"""
|
|
1701
|
+
Change the DAE veto settings.
|
|
1702
|
+
|
|
1703
|
+
Args:
|
|
1704
|
+
clearall (bool, optional): remove all vetos
|
|
1705
|
+
smp (bool, optional): set SMP veto
|
|
1706
|
+
ts2 (bool, optional): set TS2 veto
|
|
1707
|
+
hz50 (bool, optional): set 50 hz veto
|
|
1708
|
+
ext0 (bool, optional): set external veto 0
|
|
1709
|
+
ext1 (bool, optional): set external veto 1
|
|
1710
|
+
ext2 (bool, optional): set external veto 2
|
|
1711
|
+
ext3 (bool, optional): set external veto 3
|
|
1712
|
+
fifo (bool, optional): set FIFO veto
|
|
1713
|
+
|
|
1714
|
+
Note: If clearall is specified then all vetos (excluding the FIFO veto) are turned off,
|
|
1715
|
+
but it is possible to turn other vetoes back on at the same time.
|
|
1716
|
+
|
|
1717
|
+
Note: FIFO veto is automatically enabled on run begin, but can be changed whilst running.
|
|
1718
|
+
|
|
1719
|
+
Examples:
|
|
1720
|
+
Turns all vetoes off then turns the SMP veto back on:
|
|
1721
|
+
|
|
1722
|
+
>>> change_vetos(clearall=True, smp=True)
|
|
1723
|
+
|
|
1724
|
+
Turn off FIFO:
|
|
1725
|
+
|
|
1726
|
+
>>> change_vetos(fifo=False)
|
|
1727
|
+
"""
|
|
1728
|
+
_genie_api.dae.change_vetos(**params)
|
|
1729
|
+
|
|
1730
|
+
|
|
1731
|
+
@usercommand
|
|
1732
|
+
@helparglist("[enable], [delay], [width]")
|
|
1733
|
+
@log_command_and_handle_exception
|
|
1734
|
+
def change_fermi_veto(enable: bool | None = None, delay: float = 1.0, width: float = 1.0) -> None:
|
|
1735
|
+
"""
|
|
1736
|
+
Configure the fermi chopper veto.
|
|
1737
|
+
|
|
1738
|
+
Args:
|
|
1739
|
+
enable (bool, optional): enable the fermi veto
|
|
1740
|
+
delay (float, optional): the veto delay
|
|
1741
|
+
width (float, optional): the veto width
|
|
1742
|
+
"""
|
|
1743
|
+
_genie_api.dae.set_fermi_veto(enable, delay, width)
|
|
1744
|
+
|
|
1745
|
+
|
|
1746
|
+
@usercommand
|
|
1747
|
+
@helparglist("[nperiods]")
|
|
1748
|
+
@log_command_and_handle_exception
|
|
1749
|
+
def enable_soft_periods(nperiods: int | None = None) -> None:
|
|
1750
|
+
"""
|
|
1751
|
+
Switch the DAE to software periods mode.
|
|
1752
|
+
|
|
1753
|
+
Args:
|
|
1754
|
+
nperiods (int, optional): the number of software periods
|
|
1755
|
+
"""
|
|
1756
|
+
_genie_api.dae.set_period_mode("soft")
|
|
1757
|
+
if nperiods is not None:
|
|
1758
|
+
_genie_api.dae.set_num_soft_periods(nperiods)
|
|
1759
|
+
|
|
1760
|
+
|
|
1761
|
+
@usercommand
|
|
1762
|
+
@helparglist("mode[, ...]")
|
|
1763
|
+
@log_command_and_handle_exception
|
|
1764
|
+
def enable_hard_periods(
|
|
1765
|
+
mode: str,
|
|
1766
|
+
period_file: str | None = None,
|
|
1767
|
+
sequences: int | None = None,
|
|
1768
|
+
output_delay: int | None = None,
|
|
1769
|
+
period: int | None = None,
|
|
1770
|
+
daq: bool = False,
|
|
1771
|
+
dwell: bool = False,
|
|
1772
|
+
unused: bool = False,
|
|
1773
|
+
frames: int | None = None,
|
|
1774
|
+
output: int | None = None,
|
|
1775
|
+
label: str | None = None,
|
|
1776
|
+
) -> None:
|
|
1777
|
+
"""
|
|
1778
|
+
Sets the DAE to use hardware periods.
|
|
1779
|
+
|
|
1780
|
+
Args:
|
|
1781
|
+
mode (string): set the mode to internal ('int') or external ('ext')
|
|
1782
|
+
period_file (string, optional): the file containing the internal period settings
|
|
1783
|
+
(ignores any other settings)
|
|
1784
|
+
sequences (int, optional): the number of times to repeat the period loop (0 = infinite loop)
|
|
1785
|
+
output_delay (int, optional): the output delay in microseconds
|
|
1786
|
+
period (int, optional): the number of the period to set the following parameters for
|
|
1787
|
+
daq (bool, optional): the specified period is a acquisition period
|
|
1788
|
+
dwell (bool, optional): the specified period is a dwell period
|
|
1789
|
+
unused (bool, optional): the specified period is a unused period
|
|
1790
|
+
frames (int, optional): the number of frames to count for the specified period
|
|
1791
|
+
output (int, optional): the binary output the specified period
|
|
1792
|
+
label (string, optional): the label for the period the specified period
|
|
1793
|
+
|
|
1794
|
+
Note: if the period number is unspecified then the settings will be applied to all periods
|
|
1795
|
+
|
|
1796
|
+
Examples:
|
|
1797
|
+
Setting external periods:
|
|
1798
|
+
|
|
1799
|
+
>>> enable_hard_periods("ext")
|
|
1800
|
+
|
|
1801
|
+
Setting internal periods from a file:
|
|
1802
|
+
|
|
1803
|
+
>>> enable_hard_periods("int", "c:\\myperiods.txt")
|
|
1804
|
+
"""
|
|
1805
|
+
_genie_api.dae.configure_hard_periods(
|
|
1806
|
+
mode,
|
|
1807
|
+
period_file,
|
|
1808
|
+
sequences,
|
|
1809
|
+
output_delay,
|
|
1810
|
+
period,
|
|
1811
|
+
daq,
|
|
1812
|
+
dwell,
|
|
1813
|
+
unused,
|
|
1814
|
+
frames,
|
|
1815
|
+
output,
|
|
1816
|
+
label,
|
|
1817
|
+
)
|
|
1818
|
+
|
|
1819
|
+
|
|
1820
|
+
@usercommand
|
|
1821
|
+
@helparglist("[...]")
|
|
1822
|
+
@log_command_and_handle_exception
|
|
1823
|
+
def configure_internal_periods(
|
|
1824
|
+
sequences: int | None = None,
|
|
1825
|
+
output_delay: int | None = None,
|
|
1826
|
+
period: int | None = None,
|
|
1827
|
+
daq: bool = False,
|
|
1828
|
+
dwell: bool = False,
|
|
1829
|
+
unused: bool = False,
|
|
1830
|
+
frames: int | None = None,
|
|
1831
|
+
output: int | None = None,
|
|
1832
|
+
label: str | None = None,
|
|
1833
|
+
) -> None:
|
|
1834
|
+
"""
|
|
1835
|
+
Configure the internal periods without switching to internal period mode.
|
|
1836
|
+
|
|
1837
|
+
Args:
|
|
1838
|
+
sequences (int, optional): the number of times to repeat the period loop (0 = infinite loop)
|
|
1839
|
+
output_delay (int, optional): the output delay in microseconds
|
|
1840
|
+
period (int, optional): the number of the period to set the following parameters for
|
|
1841
|
+
daq (bool, optional): the specified period is a acquisition period
|
|
1842
|
+
dwell (bool, optional): the specified period is a dwell period
|
|
1843
|
+
unused (bool, optional): the specified period is a unused period
|
|
1844
|
+
frames (int, optional): the number of frames to count for the specified period
|
|
1845
|
+
output (int, optional): the binary output the specified period
|
|
1846
|
+
label (string, optional): the label for the period the specified period
|
|
1847
|
+
|
|
1848
|
+
Note: if the period number is unspecified then the settings will be applied to all periods
|
|
1849
|
+
"""
|
|
1850
|
+
_genie_api.dae.configure_internal_periods(
|
|
1851
|
+
sequences, output_delay, period, daq, dwell, unused, frames, output, label
|
|
1852
|
+
)
|
|
1853
|
+
|
|
1854
|
+
|
|
1855
|
+
@usercommand
|
|
1856
|
+
@helparglist("[...]")
|
|
1857
|
+
@log_command_and_handle_exception
|
|
1858
|
+
def define_hard_period(
|
|
1859
|
+
period: int | None = None,
|
|
1860
|
+
daq: bool = False,
|
|
1861
|
+
dwell: bool = False,
|
|
1862
|
+
unused: bool = False,
|
|
1863
|
+
frames: int | None = None,
|
|
1864
|
+
output: int | None = None,
|
|
1865
|
+
label: str | None = None,
|
|
1866
|
+
) -> None:
|
|
1867
|
+
"""
|
|
1868
|
+
Define the internal hardware periods.
|
|
1869
|
+
|
|
1870
|
+
Args:
|
|
1871
|
+
period (int, optional): the number of the period to set the following parameters for
|
|
1872
|
+
daq (bool, optional): the specified period is a acquisition period
|
|
1873
|
+
dwell (bool, optional): the specified period is a dwell period
|
|
1874
|
+
unused (bool, optional): the specified period is a unused period
|
|
1875
|
+
frames (int, optional): the number of frames to count for the specified period
|
|
1876
|
+
output (int, optional): the binary output the specified period
|
|
1877
|
+
label (string, optional): the label for the period the specified period
|
|
1878
|
+
|
|
1879
|
+
Note: if the period number is unspecified then the settings will be applied to all periods
|
|
1880
|
+
"""
|
|
1881
|
+
configure_internal_periods(None, None, period, daq, dwell, unused, frames, output, label)
|
|
1882
|
+
|
|
1883
|
+
|
|
1884
|
+
@log_command_and_handle_exception
|
|
1885
|
+
def change(**params: str | int) -> None:
|
|
1886
|
+
"""
|
|
1887
|
+
Change experiment parameters.
|
|
1888
|
+
|
|
1889
|
+
Note: it is possible to change more than one item at a time.
|
|
1890
|
+
|
|
1891
|
+
Args:
|
|
1892
|
+
title (string, optional): the new title
|
|
1893
|
+
period (int, optional): the new period (must be in a non-running state)
|
|
1894
|
+
nperiods (int, optional): the new number of software periods
|
|
1895
|
+
(must be in a non-running state)
|
|
1896
|
+
user (string, optional): the new user(s) as a comma-separated list
|
|
1897
|
+
rb (int, optional): the new RB number
|
|
1898
|
+
|
|
1899
|
+
Examples:
|
|
1900
|
+
Change the title:
|
|
1901
|
+
|
|
1902
|
+
>>> change(title="The new title")
|
|
1903
|
+
|
|
1904
|
+
Change the user:
|
|
1905
|
+
|
|
1906
|
+
>>> change(user="Instrument Team")
|
|
1907
|
+
|
|
1908
|
+
Set multiple users:
|
|
1909
|
+
|
|
1910
|
+
>>> change(user="Thouless, Haldane, Kosterlitz")
|
|
1911
|
+
|
|
1912
|
+
Change the RB number and the users:
|
|
1913
|
+
|
|
1914
|
+
>>> change(rb=123456, user="Smith, Jones")
|
|
1915
|
+
"""
|
|
1916
|
+
for k in params:
|
|
1917
|
+
key = k.lower().strip()
|
|
1918
|
+
if key == "title":
|
|
1919
|
+
change_title(params[k])
|
|
1920
|
+
elif key == "period":
|
|
1921
|
+
change_period(params[k])
|
|
1922
|
+
elif key == "nperiods":
|
|
1923
|
+
change_number_soft_periods(params[k])
|
|
1924
|
+
elif key == "user" or key == "users":
|
|
1925
|
+
change_users(params[k])
|
|
1926
|
+
elif key == "rb":
|
|
1927
|
+
change_rb(params[k])
|
|
1928
|
+
else:
|
|
1929
|
+
raise KeyError("Unknown parameter supplied. Type help(change) for more information")
|
|
1930
|
+
|
|
1931
|
+
|
|
1932
|
+
@usercommand
|
|
1933
|
+
@helparglist("title")
|
|
1934
|
+
@log_command_and_handle_exception
|
|
1935
|
+
def change_title(title: str) -> None:
|
|
1936
|
+
"""
|
|
1937
|
+
Sets the current title.
|
|
1938
|
+
|
|
1939
|
+
Args:
|
|
1940
|
+
title: the new title
|
|
1941
|
+
"""
|
|
1942
|
+
_genie_api.dae.set_title(title)
|
|
1943
|
+
|
|
1944
|
+
|
|
1945
|
+
@usercommand
|
|
1946
|
+
@helparglist("display_title")
|
|
1947
|
+
@log_command_and_handle_exception
|
|
1948
|
+
def set_display_title(display_title: bool) -> None:
|
|
1949
|
+
"""
|
|
1950
|
+
Sets the current display title status.
|
|
1951
|
+
|
|
1952
|
+
Args:
|
|
1953
|
+
display_title: the new display title status
|
|
1954
|
+
"""
|
|
1955
|
+
_genie_api.dae.set_display_title(display_title)
|
|
1956
|
+
|
|
1957
|
+
|
|
1958
|
+
@usercommand
|
|
1959
|
+
@helparglist("period")
|
|
1960
|
+
@log_command_and_handle_exception
|
|
1961
|
+
def change_period(period: int) -> None:
|
|
1962
|
+
"""
|
|
1963
|
+
Changes the current period number.
|
|
1964
|
+
|
|
1965
|
+
Args:
|
|
1966
|
+
period (int): the period to switch to
|
|
1967
|
+
"""
|
|
1968
|
+
_genie_api.dae.set_period(period)
|
|
1969
|
+
|
|
1970
|
+
|
|
1971
|
+
@usercommand
|
|
1972
|
+
@helparglist("number[, enable]")
|
|
1973
|
+
@log_command_and_handle_exception
|
|
1974
|
+
def change_number_soft_periods(number: int, enable: bool = False) -> None:
|
|
1975
|
+
"""
|
|
1976
|
+
Sets the number of software periods for the DAE.
|
|
1977
|
+
|
|
1978
|
+
Args:
|
|
1979
|
+
number (int): the number of periods to create
|
|
1980
|
+
enable (bool, optional): switch to soft period mode
|
|
1981
|
+
"""
|
|
1982
|
+
if enable:
|
|
1983
|
+
_genie_api.dae.set_period_mode("soft")
|
|
1984
|
+
_genie_api.dae.set_num_soft_periods(number)
|
|
1985
|
+
|
|
1986
|
+
|
|
1987
|
+
@usercommand
|
|
1988
|
+
@helparglist("")
|
|
1989
|
+
@log_command_and_handle_exception
|
|
1990
|
+
def get_users() -> str:
|
|
1991
|
+
"""
|
|
1992
|
+
Get the users.
|
|
1993
|
+
|
|
1994
|
+
Returns:
|
|
1995
|
+
str: the users.
|
|
1996
|
+
"""
|
|
1997
|
+
return _genie_api.dae.get_users()
|
|
1998
|
+
|
|
1999
|
+
|
|
2000
|
+
@usercommand
|
|
2001
|
+
@helparglist("users")
|
|
2002
|
+
@log_command_and_handle_exception
|
|
2003
|
+
def change_users(users: str) -> None:
|
|
2004
|
+
"""
|
|
2005
|
+
Changes the users.
|
|
2006
|
+
|
|
2007
|
+
Args:
|
|
2008
|
+
users: a string containing the user name(s)
|
|
2009
|
+
|
|
2010
|
+
Example:
|
|
2011
|
+
|
|
2012
|
+
>>> change_users("Emerson, Lake, Palmer")
|
|
2013
|
+
"""
|
|
2014
|
+
_genie_api.dae.set_users(users)
|
|
2015
|
+
|
|
2016
|
+
|
|
2017
|
+
@usercommand
|
|
2018
|
+
@helparglist("rb")
|
|
2019
|
+
@log_command_and_handle_exception
|
|
2020
|
+
def change_rb(rb: int | str) -> None:
|
|
2021
|
+
"""
|
|
2022
|
+
Changes the RB number.
|
|
2023
|
+
|
|
2024
|
+
Args:
|
|
2025
|
+
rb (int or string): the new RB number
|
|
2026
|
+
"""
|
|
2027
|
+
if isinstance(rb, int):
|
|
2028
|
+
# If it is an int then that is fine, just cast to str as the PV is a string
|
|
2029
|
+
rb = str(rb)
|
|
2030
|
+
elif isinstance(rb, str):
|
|
2031
|
+
# Let's be kind in case they enter a string.
|
|
2032
|
+
# Check string contains only digits though
|
|
2033
|
+
if not rb.isdigit():
|
|
2034
|
+
raise TypeError("RB number must be a number.")
|
|
2035
|
+
else:
|
|
2036
|
+
raise TypeError("RB number must be a number.")
|
|
2037
|
+
_genie_api.dae.set_rb_number(rb)
|
|
2038
|
+
|
|
2039
|
+
|
|
2040
|
+
class _GetspectrumReturn(TypedDict):
|
|
2041
|
+
time: list[float]
|
|
2042
|
+
signal: list[float]
|
|
2043
|
+
sum: None
|
|
2044
|
+
mode: str
|
|
2045
|
+
|
|
2046
|
+
|
|
2047
|
+
@usercommand
|
|
2048
|
+
@helparglist("spectrum[, period][, dist]")
|
|
2049
|
+
@log_command_and_handle_exception
|
|
2050
|
+
def get_spectrum(spectrum: int, period: int = 1, dist: bool = True) -> _GetspectrumReturn:
|
|
2051
|
+
"""
|
|
2052
|
+
Get the specified spectrum from the DAE.
|
|
2053
|
+
|
|
2054
|
+
Args:
|
|
2055
|
+
spectrum (int): the spectrum number
|
|
2056
|
+
period (int, optional): the period
|
|
2057
|
+
dist (bool, optional): whether to get the spectrum as a distribution. Default is True.
|
|
2058
|
+
|
|
2059
|
+
Returns:
|
|
2060
|
+
dict: dictionary of values
|
|
2061
|
+
"""
|
|
2062
|
+
return _genie_api.dae.get_spectrum(spectrum, period, dist)
|
|
2063
|
+
|
|
2064
|
+
|
|
2065
|
+
@usercommand
|
|
2066
|
+
@helparglist("spectrum[, period][, dist]")
|
|
2067
|
+
@log_command_and_handle_exception
|
|
2068
|
+
def plot_spectrum(spectrum: int, period: int = 1, dist: bool = True) -> object:
|
|
2069
|
+
"""
|
|
2070
|
+
Get the specified spectrum from the DAE and plot it. Returns the plot that was created.
|
|
2071
|
+
|
|
2072
|
+
Note: this will replace any other plots which are open.
|
|
2073
|
+
|
|
2074
|
+
Args:
|
|
2075
|
+
spectrum (int): the spectrum number
|
|
2076
|
+
period (int, optional): the period. Default is 1
|
|
2077
|
+
dist (bool, optional): whether to get the spectrum as a distribution. Default is True
|
|
2078
|
+
|
|
2079
|
+
Returns:
|
|
2080
|
+
The created plot
|
|
2081
|
+
|
|
2082
|
+
"""
|
|
2083
|
+
# Import SpectraPlot locally as it uses matplotlib, and the user may want to change
|
|
2084
|
+
# some matplotlib config parameters before it is used for the first time.
|
|
2085
|
+
from genie_python.genie_plot import SpectraPlot
|
|
2086
|
+
|
|
2087
|
+
return SpectraPlot(_genie_api, spectrum, period, dist)
|
|
2088
|
+
|
|
2089
|
+
|
|
2090
|
+
@usercommand
|
|
2091
|
+
@helparglist("spectrum[, period][, t_min][, t_max]")
|
|
2092
|
+
@log_command_and_handle_exception
|
|
2093
|
+
def integrate_spectrum(
|
|
2094
|
+
spectrum: int, period: int = 1, t_min: float | None = None, t_max: float | None = None
|
|
2095
|
+
) -> float | None:
|
|
2096
|
+
"""
|
|
2097
|
+
Integrates the spectrum within the time period and returns neutron counts.
|
|
2098
|
+
|
|
2099
|
+
The underlying algorithm sums the counts from each bin, if a bin is split by
|
|
2100
|
+
the time region then a proportional fraction of the count for that bin is used.
|
|
2101
|
+
|
|
2102
|
+
Args:
|
|
2103
|
+
spectrum (int): the spectrum number
|
|
2104
|
+
period (int, optional): the period
|
|
2105
|
+
t_min (float, optional): time of flight to start from
|
|
2106
|
+
t_max (float, optional): time of flight to finish at
|
|
2107
|
+
|
|
2108
|
+
Returns:
|
|
2109
|
+
float: integral of the spectrum (neutron counts); None spectrum can not be read
|
|
2110
|
+
"""
|
|
2111
|
+
return _genie_api.dae.integrate_spectrum(spectrum, period, t_min, t_max)
|
|
2112
|
+
|
|
2113
|
+
|
|
2114
|
+
class GetSampleParsReturnMEAS(TypedDict):
|
|
2115
|
+
ID: int
|
|
2116
|
+
LABEL: str
|
|
2117
|
+
SUBID: int
|
|
2118
|
+
TYPE: int
|
|
2119
|
+
|
|
2120
|
+
|
|
2121
|
+
class GetSampleParsReturnSCRIPT(TypedDict):
|
|
2122
|
+
NAME: str
|
|
2123
|
+
|
|
2124
|
+
|
|
2125
|
+
class _GetSampleParsReturn(TypedDict):
|
|
2126
|
+
AOI: float
|
|
2127
|
+
COMMENTS: str
|
|
2128
|
+
FIELD_LABEL: str
|
|
2129
|
+
GEOMETRY: str
|
|
2130
|
+
HEIGHT: float
|
|
2131
|
+
ID: int
|
|
2132
|
+
MEAS: GetSampleParsReturnMEAS
|
|
2133
|
+
NAME: str
|
|
2134
|
+
PHI: float
|
|
2135
|
+
SCRIPT: GetSampleParsReturnSCRIPT
|
|
2136
|
+
TEMP_LABEL: str
|
|
2137
|
+
THICK: float
|
|
2138
|
+
TYPE: str
|
|
2139
|
+
WIDTH: float
|
|
2140
|
+
|
|
2141
|
+
|
|
2142
|
+
@usercommand
|
|
2143
|
+
@helparglist("")
|
|
2144
|
+
@log_command_and_handle_exception
|
|
2145
|
+
def get_sample_pars() -> _GetSampleParsReturn:
|
|
2146
|
+
"""
|
|
2147
|
+
Get the current sample parameter values.
|
|
2148
|
+
|
|
2149
|
+
Returns:
|
|
2150
|
+
dict: the sample parameters
|
|
2151
|
+
"""
|
|
2152
|
+
names = _genie_api.get_sample_pars()
|
|
2153
|
+
return names
|
|
2154
|
+
|
|
2155
|
+
|
|
2156
|
+
@usercommand
|
|
2157
|
+
@helparglist("name, value")
|
|
2158
|
+
@log_command_and_handle_exception
|
|
2159
|
+
def change_sample_par(name: str, value: bool | int | float | str | None) -> None:
|
|
2160
|
+
"""
|
|
2161
|
+
Set a new value for a sample parameter.
|
|
2162
|
+
|
|
2163
|
+
Args:
|
|
2164
|
+
name (string): the name of the parameter to change
|
|
2165
|
+
value: the new value
|
|
2166
|
+
"""
|
|
2167
|
+
_genie_api.set_sample_par(name, value)
|
|
2168
|
+
|
|
2169
|
+
|
|
2170
|
+
class _GetbeamlineparsReturnBEAMSTOP(TypedDict):
|
|
2171
|
+
POS: str
|
|
2172
|
+
|
|
2173
|
+
|
|
2174
|
+
class _GetbeamlineparsReturnCHOPEN(TypedDict):
|
|
2175
|
+
ANG: float
|
|
2176
|
+
|
|
2177
|
+
|
|
2178
|
+
class _GetbeamlineparsReturnJOURNAL(TypedDict):
|
|
2179
|
+
BLOCKS: str
|
|
2180
|
+
|
|
2181
|
+
|
|
2182
|
+
class _GetbeamlineparsReturn(TypedDict):
|
|
2183
|
+
A1: float
|
|
2184
|
+
A2: float
|
|
2185
|
+
A3: float
|
|
2186
|
+
BCX: float
|
|
2187
|
+
BCY: float
|
|
2188
|
+
BEAMSTOP: _GetbeamlineparsReturnBEAMSTOP
|
|
2189
|
+
CHOPEN: _GetbeamlineparsReturnCHOPEN
|
|
2190
|
+
CURR_CONFIG: str
|
|
2191
|
+
FOEMIRROR: float
|
|
2192
|
+
GEOMETRY: str
|
|
2193
|
+
JOURNAL: _GetbeamlineparsReturnJOURNAL
|
|
2194
|
+
L1: float
|
|
2195
|
+
SDD: float
|
|
2196
|
+
|
|
2197
|
+
|
|
2198
|
+
@usercommand
|
|
2199
|
+
@helparglist("")
|
|
2200
|
+
@log_command_and_handle_exception
|
|
2201
|
+
def get_beamline_pars() -> _GetbeamlineparsReturn:
|
|
2202
|
+
"""
|
|
2203
|
+
Get the current beamline parameter values.
|
|
2204
|
+
|
|
2205
|
+
Returns:
|
|
2206
|
+
dict: the beamline parameters
|
|
2207
|
+
"""
|
|
2208
|
+
names = _genie_api.get_beamline_pars()
|
|
2209
|
+
return names
|
|
2210
|
+
|
|
2211
|
+
|
|
2212
|
+
@usercommand
|
|
2213
|
+
@helparglist("name, value")
|
|
2214
|
+
@log_command_and_handle_exception
|
|
2215
|
+
def change_beamline_par(name: str, value: bool | int | float | str | None) -> None:
|
|
2216
|
+
"""
|
|
2217
|
+
Set a new value for a beamline parameter
|
|
2218
|
+
|
|
2219
|
+
Args:
|
|
2220
|
+
name (string): the name of the parameter to change
|
|
2221
|
+
value: the new value
|
|
2222
|
+
"""
|
|
2223
|
+
_genie_api.set_beamline_par(name, value)
|
|
2224
|
+
|
|
2225
|
+
|
|
2226
|
+
@usercommand
|
|
2227
|
+
@helparglist("phone_num, message")
|
|
2228
|
+
@log_command_and_handle_exception
|
|
2229
|
+
def send_sms(phone_num: str, message: str) -> None:
|
|
2230
|
+
"""
|
|
2231
|
+
Sends an SMS message to a phone number.
|
|
2232
|
+
If you are sending to messages to the same number often consider using g.alerts.send()
|
|
2233
|
+
|
|
2234
|
+
Args:
|
|
2235
|
+
phone_num (string): the phone number to send the SMS to
|
|
2236
|
+
message (string): the message to send
|
|
2237
|
+
"""
|
|
2238
|
+
_genie_api.send_sms(phone_num, message)
|
|
2239
|
+
|
|
2240
|
+
|
|
2241
|
+
@usercommand
|
|
2242
|
+
@helparglist("message, inst")
|
|
2243
|
+
@log_command_and_handle_exception
|
|
2244
|
+
def send_alert(message: str, inst: str | None = None) -> None:
|
|
2245
|
+
"""
|
|
2246
|
+
Sends an alert message for the specified instrument.
|
|
2247
|
+
|
|
2248
|
+
Args:
|
|
2249
|
+
message (string): the message to send
|
|
2250
|
+
inst (string, optional): the instrument to generate the alert for.
|
|
2251
|
+
Defaults to current instrument.
|
|
2252
|
+
"""
|
|
2253
|
+
_genie_api.send_alert(message, inst)
|
|
2254
|
+
|
|
2255
|
+
|
|
2256
|
+
@usercommand
|
|
2257
|
+
@helparglist("address, message")
|
|
2258
|
+
@log_command_and_handle_exception
|
|
2259
|
+
def send_email(address: str, message: str) -> None:
|
|
2260
|
+
"""
|
|
2261
|
+
Sends a message to an email address.
|
|
2262
|
+
|
|
2263
|
+
Args:
|
|
2264
|
+
address (string): the email address to use
|
|
2265
|
+
message (string): the message to send
|
|
2266
|
+
"""
|
|
2267
|
+
_genie_api.send_email(address, message)
|
|
2268
|
+
|
|
2269
|
+
|
|
2270
|
+
@usercommand
|
|
2271
|
+
@helparglist("")
|
|
2272
|
+
@log_command_and_handle_exception
|
|
2273
|
+
def get_wiring_tables() -> list[str]:
|
|
2274
|
+
"""
|
|
2275
|
+
Gets a list of possible wiring table choices.
|
|
2276
|
+
|
|
2277
|
+
Returns:
|
|
2278
|
+
list: the files
|
|
2279
|
+
"""
|
|
2280
|
+
return _genie_api.dae.get_wiring_tables()
|
|
2281
|
+
|
|
2282
|
+
|
|
2283
|
+
@usercommand
|
|
2284
|
+
@helparglist("")
|
|
2285
|
+
@log_command_and_handle_exception
|
|
2286
|
+
def get_spectra_tables() -> list[str]:
|
|
2287
|
+
"""
|
|
2288
|
+
Gets a list of possible spectra table choices.
|
|
2289
|
+
|
|
2290
|
+
Returns:
|
|
2291
|
+
list: the files
|
|
2292
|
+
"""
|
|
2293
|
+
return _genie_api.dae.get_spectra_tables()
|
|
2294
|
+
|
|
2295
|
+
|
|
2296
|
+
@usercommand
|
|
2297
|
+
@helparglist("")
|
|
2298
|
+
@log_command_and_handle_exception
|
|
2299
|
+
def get_detector_tables() -> list[str]:
|
|
2300
|
+
"""
|
|
2301
|
+
Gets a list of possible detector table choices.
|
|
2302
|
+
|
|
2303
|
+
Returns:
|
|
2304
|
+
list: the files
|
|
2305
|
+
"""
|
|
2306
|
+
return _genie_api.dae.get_detector_tables()
|
|
2307
|
+
|
|
2308
|
+
|
|
2309
|
+
@usercommand
|
|
2310
|
+
@helparglist("")
|
|
2311
|
+
@log_command_and_handle_exception
|
|
2312
|
+
def get_period_files() -> list[str]:
|
|
2313
|
+
"""
|
|
2314
|
+
Gets a list of possible period file choices.
|
|
2315
|
+
|
|
2316
|
+
Returns:
|
|
2317
|
+
list: the files
|
|
2318
|
+
"""
|
|
2319
|
+
return _genie_api.dae.get_period_files()
|
|
2320
|
+
|
|
2321
|
+
|
|
2322
|
+
@log_command_and_handle_exception
|
|
2323
|
+
def check_alarms(*blocks: str) -> tuple[list[str], list[str], list[str]]:
|
|
2324
|
+
"""
|
|
2325
|
+
Checks whether the specified blocks are in alarm.
|
|
2326
|
+
|
|
2327
|
+
Args:
|
|
2328
|
+
blocks (string, multiple): the block(s) to check
|
|
2329
|
+
|
|
2330
|
+
Returns:
|
|
2331
|
+
list, list: the blocks in minor alarm and major alarm respectively
|
|
2332
|
+
|
|
2333
|
+
Example:
|
|
2334
|
+
Check alarm state for block1 and block2:
|
|
2335
|
+
|
|
2336
|
+
>>> check_alarms("block1", "block2")
|
|
2337
|
+
"""
|
|
2338
|
+
return _genie_api.check_alarms(blocks)
|
|
2339
|
+
|
|
2340
|
+
|
|
2341
|
+
@log_command_and_handle_exception
|
|
2342
|
+
def check_limit_violations(*blocks: str) -> list[str]:
|
|
2343
|
+
"""
|
|
2344
|
+
Checks whether the specified blocks have soft limit violations.
|
|
2345
|
+
|
|
2346
|
+
Args:
|
|
2347
|
+
blocks (string, multiple): the block(s) to check
|
|
2348
|
+
|
|
2349
|
+
Returns:
|
|
2350
|
+
list: the blocks that have soft limit violations
|
|
2351
|
+
|
|
2352
|
+
Example:
|
|
2353
|
+
Check soft limit violations for block1 and block2:
|
|
2354
|
+
|
|
2355
|
+
>>> check_limit_violations("block1", "block2")
|
|
2356
|
+
"""
|
|
2357
|
+
return _genie_api.check_limit_violations(blocks)
|
|
2358
|
+
|
|
2359
|
+
|
|
2360
|
+
@usercommand
|
|
2361
|
+
@helparglist("name")
|
|
2362
|
+
@log_command_and_handle_exception
|
|
2363
|
+
def prefix_pv_name(name: str) -> str:
|
|
2364
|
+
"""
|
|
2365
|
+
Prepends the instrument PV prefix on to the supplied PV name
|
|
2366
|
+
|
|
2367
|
+
Args:
|
|
2368
|
+
name (string): The PV without the prefix.
|
|
2369
|
+
|
|
2370
|
+
Returns:
|
|
2371
|
+
string: The PV with the instrument prefix prepended
|
|
2372
|
+
"""
|
|
2373
|
+
return _genie_api.prefix_pv_name(name)
|
|
2374
|
+
|
|
2375
|
+
|
|
2376
|
+
@usercommand
|
|
2377
|
+
@helparglist("")
|
|
2378
|
+
def get_version() -> str:
|
|
2379
|
+
"""
|
|
2380
|
+
Tells you the version of genie_python that is used.
|
|
2381
|
+
|
|
2382
|
+
Returns:
|
|
2383
|
+
string: The current version number of genie python
|
|
2384
|
+
"""
|
|
2385
|
+
return VERSION
|
|
2386
|
+
|
|
2387
|
+
|
|
2388
|
+
@usercommand
|
|
2389
|
+
@helparglist("mode")
|
|
2390
|
+
@log_command_and_handle_exception
|
|
2391
|
+
def set_dae_simulation_mode(mode: bool, skip_required_runstates: bool = False) -> None:
|
|
2392
|
+
"""
|
|
2393
|
+
Sets the DAE into simulation mode.
|
|
2394
|
+
|
|
2395
|
+
Args:
|
|
2396
|
+
mode: True to set the DAE into simulated mode, False to set the DAE into
|
|
2397
|
+
non-simulated (hardware) mode
|
|
2398
|
+
skip_required_runstates: Ignore all checks, use with caution
|
|
2399
|
+
"""
|
|
2400
|
+
# skip_required_runstates must be passed as a keyword argument for wrapper to catch it.
|
|
2401
|
+
_genie_api.dae.set_simulation_mode(mode, skip_required_runstates=skip_required_runstates)
|
|
2402
|
+
|
|
2403
|
+
|
|
2404
|
+
@usercommand
|
|
2405
|
+
@helparglist("")
|
|
2406
|
+
@log_command_and_handle_exception
|
|
2407
|
+
def get_dae_simulation_mode() -> bool:
|
|
2408
|
+
"""
|
|
2409
|
+
Gets the DAE simulation mode.
|
|
2410
|
+
Returns:
|
|
2411
|
+
True if the DAE is in simulation mode, False otherwise.
|
|
2412
|
+
"""
|
|
2413
|
+
return _genie_api.dae.get_simulation_mode()
|
|
2414
|
+
|
|
2415
|
+
|
|
2416
|
+
def load(name: str) -> None:
|
|
2417
|
+
"""
|
|
2418
|
+
Informs the user that load may not be the function they want.
|
|
2419
|
+
Prints a message telling the user about g.loadscript and numpy.load.
|
|
2420
|
+
|
|
2421
|
+
Args:
|
|
2422
|
+
name (string): The script the user is trying to load.
|
|
2423
|
+
"""
|
|
2424
|
+
print(
|
|
2425
|
+
'This function does not load a script; you probably wanted g.load_script("{0}").'
|
|
2426
|
+
"If you wanted numpy load please call it directly with import numpy as numpy; "
|
|
2427
|
+
'numpy.load("{0}")'.format(get_correct_path(name))
|
|
2428
|
+
)
|
|
2429
|
+
return
|
|
2430
|
+
|
|
2431
|
+
|
|
2432
|
+
@usercommand
|
|
2433
|
+
@log_command_and_handle_exception
|
|
2434
|
+
def get_wiring_table() -> str | None:
|
|
2435
|
+
"""Gets the current wiring table path"
|
|
2436
|
+
|
|
2437
|
+
Returns:
|
|
2438
|
+
The file path of the current wiring table.
|
|
2439
|
+
"""
|
|
2440
|
+
return _genie_api.dae.get_table_path("Wiring")
|
|
2441
|
+
|
|
2442
|
+
|
|
2443
|
+
@usercommand
|
|
2444
|
+
@log_command_and_handle_exception
|
|
2445
|
+
def get_spectra_table() -> str | None:
|
|
2446
|
+
"""Gets the current spectra table path"
|
|
2447
|
+
|
|
2448
|
+
Returns:
|
|
2449
|
+
The file path of the current spectra table.
|
|
2450
|
+
"""
|
|
2451
|
+
return _genie_api.dae.get_table_path("Spectra")
|
|
2452
|
+
|
|
2453
|
+
|
|
2454
|
+
@usercommand
|
|
2455
|
+
@log_command_and_handle_exception
|
|
2456
|
+
def get_detector_table() -> str | None:
|
|
2457
|
+
"""Gets the current detector table path"
|
|
2458
|
+
|
|
2459
|
+
Returns:
|
|
2460
|
+
The file path of the current detector table.
|
|
2461
|
+
"""
|
|
2462
|
+
return _genie_api.dae.get_table_path("Detector")
|