genie-python 15.1.0__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/_version.py +16 -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 +551 -0
- genie_python/genie_change_cache.py +151 -0
- genie_python/genie_dae.py +2219 -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/scanning_instrument_pylint_plugin.py +31 -0
- genie_python/testing_utils/__init__.py +4 -0
- genie_python/testing_utils/script_checker.py +63 -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 +6 -0
- genie_python-15.1.0.dist-info/LICENSE +28 -0
- genie_python-15.1.0.dist-info/METADATA +84 -0
- genie_python-15.1.0.dist-info/RECORD +45 -0
- genie_python-15.1.0.dist-info/WHEEL +5 -0
- genie_python-15.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from __future__ import absolute_import
|
|
2
|
+
|
|
3
|
+
import ctypes
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
6
|
+
from importlib import reload # noqa F401
|
|
7
|
+
|
|
8
|
+
from genie_python import BLOCK_NAMES as b # noqa F401
|
|
9
|
+
from genie_python import genie as g # noqa F401
|
|
10
|
+
|
|
11
|
+
# Required so that scientists can just call reload(inst) in the python console.
|
|
12
|
+
# Importing genie and block names is required for user scripts.
|
|
13
|
+
from genie_python.genie import * # noqa F403
|
|
14
|
+
|
|
15
|
+
if os.name == "nt":
|
|
16
|
+
# Disable Windows console quick edit mode
|
|
17
|
+
win32 = ctypes.windll.kernel32
|
|
18
|
+
hin = win32.GetStdHandle(-10)
|
|
19
|
+
mode = ctypes.c_ulong(0)
|
|
20
|
+
win32.GetConsoleMode(hin, ctypes.byref(mode))
|
|
21
|
+
# To disable quick edit need to disable the 7th bit and enable the 8th
|
|
22
|
+
new_mode = mode.value & ~(0x0040) | (0x0080)
|
|
23
|
+
win32.SetConsoleMode(hin, new_mode)
|
|
24
|
+
|
|
25
|
+
# Call set_instrument with None to force it to try to guess the instrument
|
|
26
|
+
set_instrument(None) # noqa F405 (defined from star import)
|
|
27
|
+
|
|
28
|
+
# Add shared instrument scripts to the PYTHONPATH
|
|
29
|
+
sys.path.append("C:\\Instrument\\scripts")
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Genie Toggle Settings module.
|
|
3
|
+
|
|
4
|
+
This module is used for storing and updating user preferences and settings.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import absolute_import, print_function
|
|
8
|
+
|
|
9
|
+
import genie_python.genie_api_setup # for _exceptions_raised
|
|
10
|
+
from genie_python.genie_api_setup import helparglist, log_command_and_handle_exception, usercommand
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ToggleSettings:
|
|
14
|
+
cset_verbose = False
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@usercommand
|
|
18
|
+
@helparglist("")
|
|
19
|
+
@log_command_and_handle_exception
|
|
20
|
+
def exceptions_raised(toggle_on):
|
|
21
|
+
"""
|
|
22
|
+
Set whether to allow exceptions to propagate (True) or let genie handle any exceptions (False).
|
|
23
|
+
By default (False), genie_python will handle any exceptions by printing the error message and carrying on.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
toggle_on (bool): Allow exceptions if True, let genie handle exceptions if False.
|
|
27
|
+
|
|
28
|
+
Examples:
|
|
29
|
+
Set genie_python not to handle exceptions:
|
|
30
|
+
|
|
31
|
+
>>> exceptions_raised(True)
|
|
32
|
+
"""
|
|
33
|
+
if not isinstance(toggle_on, bool):
|
|
34
|
+
raise ValueError("Exceptions raised setting needs to be True or False.")
|
|
35
|
+
genie_python.genie_api_setup._exceptions_raised = toggle_on
|
|
36
|
+
# noinspection PyProtectedMember
|
|
37
|
+
print("Raise exceptions set to {}.".format(genie_python.genie_api_setup._exceptions_raised))
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@usercommand
|
|
41
|
+
@helparglist("")
|
|
42
|
+
@log_command_and_handle_exception
|
|
43
|
+
def cset_verbose(verbose):
|
|
44
|
+
"""
|
|
45
|
+
Set the default verbosity of cset.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
verbose (bool): The cset verbose flag.
|
|
49
|
+
|
|
50
|
+
Examples:
|
|
51
|
+
Setting up all cset calls to be verbose:
|
|
52
|
+
|
|
53
|
+
>>> cset_verbose(True)
|
|
54
|
+
"""
|
|
55
|
+
if not isinstance(verbose, bool):
|
|
56
|
+
raise ValueError("Default verbosity needs to be True or False.")
|
|
57
|
+
ToggleSettings.cset_verbose = verbose
|
|
58
|
+
print("Default cset verbosity set to {}.".format(ToggleSettings.cset_verbose))
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
"""Waits until the supplied process variable returns 'done'.
|
|
4
|
+
Allows motors to complete their motion fully before proceeding."""
|
|
5
|
+
|
|
6
|
+
# If you include db/motorUtil.db and call motorUtilInit(“pv prefix”) from your IOC you get 3 PVs defined:
|
|
7
|
+
# $(P)alldone, $(P)allstop, $(P)moving which cover all motors in that IOC.
|
|
8
|
+
# The “allstop” PV is automatically reset after the stop command has been issued to all motors,
|
|
9
|
+
# “alldone” indicates when any motion has completed and “moving” gives a count of moving motors.
|
|
10
|
+
|
|
11
|
+
from __future__ import absolute_import, print_function
|
|
12
|
+
|
|
13
|
+
import time
|
|
14
|
+
from builtins import object
|
|
15
|
+
|
|
16
|
+
from genie_python.utilities import check_break
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class WaitForMoveController(object):
|
|
20
|
+
def __init__(self, api, motion_pv):
|
|
21
|
+
self._api = api
|
|
22
|
+
self._motion_pv = motion_pv
|
|
23
|
+
self._polling_delay = 0.02
|
|
24
|
+
self._wait_succeeded = False
|
|
25
|
+
self._missing_blocks = list()
|
|
26
|
+
|
|
27
|
+
def wait(self, start_timeout=None, move_timeout=None):
|
|
28
|
+
"""Wait for motor motion to complete.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
start_timeout (int, optional) : the number of seconds to wait for the movement to begin
|
|
32
|
+
move_timeout (int, optional) : the maximum number of seconds to wait for motion to stop
|
|
33
|
+
|
|
34
|
+
If the motion does not start within the specified start_timeout then it will continue as if it did.
|
|
35
|
+
"""
|
|
36
|
+
self._do_wait(start_timeout, move_timeout, self._any_motion)
|
|
37
|
+
|
|
38
|
+
def wait_specific(self, blocks, start_timeout=None, move_timeout=None):
|
|
39
|
+
"""Wait for motor motion to complete on the specified blocks only.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
blocks (list) : the names of the blocks to wait for
|
|
43
|
+
start_timeout (int, optional) : the number of seconds to wait for the movement to begin
|
|
44
|
+
move_timeout (int, optional) : the maximum number of seconds to wait for motion to stop
|
|
45
|
+
|
|
46
|
+
If the motion does not start within the specified start_timeout then it will continue as if it did
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
def check_blocks():
|
|
50
|
+
return self._check_specific_motion(blocks)
|
|
51
|
+
|
|
52
|
+
self._do_wait(start_timeout, move_timeout, check_blocks)
|
|
53
|
+
self._flag_error_conditions(blocks)
|
|
54
|
+
|
|
55
|
+
def _do_wait(self, start_timeout, move_timeout, check_for_move):
|
|
56
|
+
# Pause very briefly to avoid any "double move" that may occur when multiple motors are moved
|
|
57
|
+
# and one of the motors is sent to its current position
|
|
58
|
+
time.sleep(0.01)
|
|
59
|
+
|
|
60
|
+
self._missing_blocks = []
|
|
61
|
+
|
|
62
|
+
start_timeout, move_timeout = self._check_timeouts_valid(start_timeout, move_timeout)
|
|
63
|
+
|
|
64
|
+
# If not already moving then wait for up to "timeout" seconds for a move to start
|
|
65
|
+
self.wait_for_start(start_timeout, check_for_move)
|
|
66
|
+
|
|
67
|
+
start = time.time()
|
|
68
|
+
while check_for_move():
|
|
69
|
+
check_break(2)
|
|
70
|
+
time.sleep(self._polling_delay)
|
|
71
|
+
if move_timeout is not None and time.time() - start >= move_timeout:
|
|
72
|
+
self._api.logger.log_info_msg("WAITFOR_MOVE TIMED OUT")
|
|
73
|
+
return
|
|
74
|
+
self._api.logger.log_info_msg("WAITFOR_MOVE MOVE FINISHED")
|
|
75
|
+
|
|
76
|
+
def _check_timeouts_valid(self, start_timeout, move_timeout):
|
|
77
|
+
if start_timeout is not None and start_timeout <= 0:
|
|
78
|
+
self._api.logger.log_info_msg(
|
|
79
|
+
"Start time out cannot be less than zero - using default value"
|
|
80
|
+
)
|
|
81
|
+
start_timeout = 0
|
|
82
|
+
if move_timeout is not None and move_timeout <= 0:
|
|
83
|
+
self._api.logger.log_info_msg(
|
|
84
|
+
"Move time out cannot be less than zero - using default value"
|
|
85
|
+
)
|
|
86
|
+
move_timeout = None
|
|
87
|
+
return start_timeout, move_timeout
|
|
88
|
+
|
|
89
|
+
def wait_for_start(self, timeout, check_for_move):
|
|
90
|
+
if timeout is not None:
|
|
91
|
+
start = time.time()
|
|
92
|
+
|
|
93
|
+
while not check_for_move():
|
|
94
|
+
check_break(2)
|
|
95
|
+
time.sleep(self._polling_delay)
|
|
96
|
+
if time.time() - start >= timeout:
|
|
97
|
+
self._api.logger.log_info_msg("WAITFOR_MOVE START TIMED OUT")
|
|
98
|
+
return
|
|
99
|
+
self._api.logger.log_info_msg("WAITFOR_MOVE START FINISHED")
|
|
100
|
+
|
|
101
|
+
def _any_motion(self):
|
|
102
|
+
return self._api.get_pv_value(self._motion_pv) != 0
|
|
103
|
+
|
|
104
|
+
def _check_specific_motion(self, blocks):
|
|
105
|
+
for block in blocks:
|
|
106
|
+
if block in self._missing_blocks:
|
|
107
|
+
# Skip any missing blocks
|
|
108
|
+
continue
|
|
109
|
+
block_pv = self._api.get_pv_from_block(block)
|
|
110
|
+
# DMOV = 0 when moving
|
|
111
|
+
try:
|
|
112
|
+
moving = self._api.get_pv_value(block_pv + ":DMOV", attempts=1) == 0
|
|
113
|
+
except IOError:
|
|
114
|
+
# Could not find block so don't try it again
|
|
115
|
+
self._api.logger.log_info_msg("WAITFOR_MOVE DISCONNECTED BLOCK: {}".format(block))
|
|
116
|
+
print("Could not connect to block {} so ignoring it".format(block))
|
|
117
|
+
self._missing_blocks.append(block)
|
|
118
|
+
moving = False
|
|
119
|
+
if moving:
|
|
120
|
+
return True
|
|
121
|
+
|
|
122
|
+
return False
|
|
123
|
+
|
|
124
|
+
def _flag_error_conditions(self, blocks):
|
|
125
|
+
time.sleep(0.5)
|
|
126
|
+
filtered_blocks = self._filter_out_missing_blocks(blocks)
|
|
127
|
+
|
|
128
|
+
# Check alarms
|
|
129
|
+
minor, major, invalid = self._api.check_alarms(filtered_blocks)
|
|
130
|
+
for i in major:
|
|
131
|
+
self._api.logger.log_info_msg("WAITFOR_MOVE BLOCK %s IN MAJOR ALARM" % i)
|
|
132
|
+
print("Block %s is in alarm: MAJOR" % i)
|
|
133
|
+
for i in minor:
|
|
134
|
+
self._api.logger.log_info_msg("WAITFOR_MOVE BLOCK %s IN MINOR ALARM" % i)
|
|
135
|
+
print("Block %s is in alarm state: MINOR" % i)
|
|
136
|
+
|
|
137
|
+
# Check soft limit violations
|
|
138
|
+
violations = self._api.check_limit_violations(filtered_blocks)
|
|
139
|
+
for i in violations:
|
|
140
|
+
self._api.logger.log_info_msg("WAITFOR_MOVE BLOCK %s HAS SOFT LIMIT VIOLATIONS" % i)
|
|
141
|
+
print("Block %s has soft limit violations" % i)
|
|
142
|
+
|
|
143
|
+
# Print missing blocks
|
|
144
|
+
for i in self._missing_blocks:
|
|
145
|
+
self._api.logger.log_info_msg("WAITFOR_MOVE BLOCK %s COULD NOT BE FOUND" % i)
|
|
146
|
+
print("Block %s could not be found" % i)
|
|
147
|
+
|
|
148
|
+
def _filter_out_missing_blocks(self, blocks):
|
|
149
|
+
filtered_blocks = []
|
|
150
|
+
for b in blocks:
|
|
151
|
+
if b in self._missing_blocks:
|
|
152
|
+
continue
|
|
153
|
+
filtered_blocks.append(b)
|
|
154
|
+
return filtered_blocks
|