cgse-common 2023.1.4__py3-none-any.whl → 2024.1.4__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.
egse/calibration.py ADDED
@@ -0,0 +1,250 @@
1
+ import numpy as np
2
+
3
+ from egse.setup import NavigableDict, Setup, SetupError
4
+
5
+
6
+ def apply_gain_offset(counts: float, gain: float, offset: float) -> float:
7
+ """ Applies the given gain and offset to the given counts.
8
+
9
+ Args:
10
+ counts: Uncalibrated, raw data [ADU]
11
+ gain: Gain to apply
12
+ offset: Offset to apply
13
+
14
+ Returns: Counts after applying the given gain and offset.
15
+ """
16
+
17
+ return counts * gain + offset
18
+
19
+ #########################
20
+ # Temperature calibration
21
+ #########################
22
+
23
+
24
+ def counts_to_temperature(sensor_name: str, counts: float, sensor_info: NavigableDict, setup: Setup):
25
+ """ Converts the given counts for the given sensor to temperature.
26
+
27
+ This conversion can be done as follows:
28
+
29
+ - (1) Directly from counts to temperature, by applying the gain and offset;
30
+ - (2) Directly from counts to temperature, by applying a function;
31
+ - (3) From counts, via resistance, to temperature.
32
+
33
+ Args:
34
+ sensor_name: Sensor name
35
+ counts: Uncalibrated, raw data [ADU]
36
+ sensor_info: Calibration information for the given sensor (type)
37
+ setup: Setup
38
+
39
+ Returns: Calibrated temperature [°C] for the given sensor
40
+ """
41
+
42
+ # (1) Conversion: temperature = counts * gain + offset
43
+
44
+ if "counts_to_temperature_gain" in sensor_info and "counts_to_temperature_offset" in sensor_info:
45
+
46
+ return apply_gain_offset(counts,
47
+ gain=eval(str(sensor_info.counts_to_temperature_gain)),
48
+ offset=sensor_info.counts_to_temperature_offset)
49
+
50
+ # (2) Conversion: temperature = func(counts)
51
+
52
+ if "counts_to_temperature" in sensor_info:
53
+
54
+ # (2a) Polynomial
55
+
56
+ if sensor_info.counts_to_temperature.method == "polynomial":
57
+ return np.polyval(sensor_info.counts_to_temperature.counts_to_temperature_coefficients, counts)
58
+
59
+ # (3) Conversion: counts -> resistance -> temperature
60
+
61
+ else:
62
+ resistance = counts_to_resistance(sensor_name, counts, sensor_info)
63
+ return resistance_to_temperature(sensor_name, resistance, sensor_info, setup)
64
+
65
+
66
+ def counts_to_resistance(sensor_name: str, counts: float, sensor_info: NavigableDict):
67
+ """ Converts the given counts for the given sensor to resistance.
68
+
69
+ Args:
70
+ sensor_name: Sensor name
71
+ counts: Uncalibrated, raw data [ADU]
72
+ sensor_info: Calibration information for the given sensor (type)
73
+
74
+ Returns: Resistance [Ohm] for the given sensor.
75
+ """
76
+
77
+ # Offset (if any)
78
+
79
+ counts_to_resistance_offset = sensor_info.counts_to_resistance_offset \
80
+ if "counts_to_resistance_offset" in sensor_info \
81
+ else 0
82
+
83
+ # Conversion: counts -> voltage -> resistance
84
+
85
+ if "counts_to_voltage_gain" in sensor_info and "voltage_to_resistance_gain" in sensor_info:
86
+
87
+ return apply_gain_offset(counts,
88
+ gain=sensor_info.counts_to_voltage_gain * sensor_info.voltage_to_resistance_gain,
89
+ offset=counts_to_resistance_offset)
90
+
91
+ # Conversion: counts -> resistance
92
+
93
+ elif "counts_to_resistance_gain" in sensor_info:
94
+
95
+ return apply_gain_offset(counts,
96
+ gain=sensor_info.counts_to_resistance_gain,
97
+ offset=counts_to_resistance_offset)
98
+
99
+ raise SetupError(f"Setup does not contain info for conversion from counts to resistance for {sensor_name}")
100
+
101
+
102
+ def resistance_to_temperature(sensor_name: str, resistance: float, sensor_info: NavigableDict, setup: Setup):
103
+ """ Converts the given resistance for the given sensor to temperature.
104
+
105
+ Args:
106
+ sensor_name: Sensor name
107
+ resistance: Resistance [Ohm]
108
+ sensor_info: Calibration information for the given sensor (type)
109
+ setup: Setup
110
+
111
+ Returns: Temperature [°C] for the given sensor.
112
+ """
113
+
114
+ resistance_to_temperature_info = sensor_info.resistance_to_temperature
115
+
116
+ # Series resistance (if any)
117
+
118
+ if "series_resistance" in resistance_to_temperature_info:
119
+
120
+ series_resistance = resistance_to_temperature_info.series_resistance
121
+ if sensor_name in resistance_to_temperature_info:
122
+ series_resistance = series_resistance[sensor_name]
123
+ resistance -= series_resistance
124
+
125
+ method: str = resistance_to_temperature_info.method
126
+
127
+ if "divide_resistance_by" in resistance_to_temperature_info:
128
+ resistance /= resistance_to_temperature_info.divide_resistance_by
129
+
130
+ # Polynomial
131
+
132
+ if method == "polynomial":
133
+
134
+ # Coefficients given for conversion temperature -> resistance
135
+
136
+ if "temperature_to_resistance_coefficients" in resistance_to_temperature_info:
137
+ return solve_temperature(resistance_to_temperature_info.temperature_to_resistance_coefficients, resistance)
138
+
139
+ # Coefficients given for conversion resistance -> temperature
140
+
141
+ if "resistance_to_temperature_coefficients" in resistance_to_temperature_info:
142
+ return np.polyval(resistance_to_temperature_info.resistance_to_temperature_coefficients, resistance)
143
+
144
+ elif method == "callendar_van_dusen":
145
+
146
+ standard = resistance_to_temperature_info.standard
147
+ ref_resistance = resistance_to_temperature_info.ref_resistance
148
+
149
+ return callendar_van_dusen(resistance, ref_resistance, standard, setup)
150
+
151
+ else:
152
+ raise SetupError(f"Setup does not contain info for conversion from resistance to temperature for {sensor_name}")
153
+
154
+
155
+ def solve_temperature(temperature_to_resistance_coefficients, resistance: float):
156
+ """ Solves the temperature from the temperature -> resistance polynomial.
157
+
158
+ For the given temperature -> resistance polynomial and the given resistance, we determine what the corresponding
159
+ temperature is by:
160
+
161
+ - Finding the roots of polynomial(temperature) = resistance;
162
+ - Discarding the roots with an imaginary component;
163
+ - Selecting the remaining root in the relevant temperature regime (here: [-200°C, 200°C]).
164
+ """
165
+
166
+ temperature_to_resistance_poly = np.poly1d(temperature_to_resistance_coefficients)
167
+ temperatures = (temperature_to_resistance_poly - resistance).roots
168
+
169
+ for temperature in temperatures:
170
+ if temperature.imag == 0 and -200 <= temperature <= 200:
171
+ return temperature.real
172
+
173
+
174
+ def callendar_van_dusen(resistance: float, ref_resistance: float, standard: str, setup: Setup):
175
+ """ Solves the Callendar - van Dusen equation for temperature.
176
+
177
+ Args:
178
+ resistance: Resistance [Ohm] for which to calculate the temperature
179
+ ref_resistance: Resistance [Ohm] for a temperature of 0°C
180
+ standard: Sensor standard
181
+ setup: Setup
182
+
183
+ Returns: Temperature [°C] corresponding to the given resistance.
184
+ """
185
+
186
+ # Resistances higher than the reference resistance correspond to
187
+
188
+ coefficients = setup.sensor_calibration.callendar_van_dusen[standard]
189
+
190
+ # Positive temperatures
191
+
192
+ if resistance >= ref_resistance:
193
+ resistance_to_temperature_coefficients = [ref_resistance * coefficients.C,
194
+ -ref_resistance * 100 * coefficients.C,
195
+ ref_resistance * coefficients.B,
196
+ ref_resistance * coefficients.A, ref_resistance * 1]
197
+
198
+ # Negative temperatures
199
+
200
+ else:
201
+ resistance_to_temperature_coefficients = [ref_resistance * coefficients.B,
202
+ ref_resistance * coefficients.A,
203
+ ref_resistance * 1]
204
+
205
+ return solve_temperature(resistance_to_temperature_coefficients, resistance)
206
+
207
+
208
+ def chebychev(resistance: float, sensor_info: NavigableDict):
209
+ """ Solves the Chebychev equation for temperature.
210
+
211
+ Implemented as specified in the calibration certificate of the LakeShore Cernox sensors.
212
+
213
+ Args:
214
+ resistance:Resistance [Ohm] for which to calculate the temperature
215
+ sensor_info: Calibration information
216
+
217
+ Returns: Temperature [°C] corresponding to the given resistance.
218
+ """
219
+
220
+ num_fit_ranges = sensor_info.num_fit_ranges
221
+
222
+ for fit_range_index in range(1, num_fit_ranges + 1):
223
+
224
+ range_info = sensor_info[f"range{fit_range_index}"]
225
+
226
+ resistance_lower_limit, resistance_upper_limit = range_info.resistance_range
227
+
228
+ if resistance_lower_limit <= resistance <= resistance_upper_limit:
229
+
230
+ if range_info.fit_type == "LOG":
231
+ z = np.log10(resistance)
232
+
233
+ zl, zu = range_info.z_range
234
+ order = range_info.order
235
+ coefficients = range_info.coefficients
236
+
237
+ temperature = 0
238
+
239
+ for index in range(0, order + 1):
240
+
241
+ k = ((z-zl)-(zu-z))/(zu-zl)
242
+ temperature += coefficients[index] * np.cos(index * np.arccos(k))
243
+
244
+ return temperature
245
+
246
+ ############################
247
+ # Supply voltage calibration
248
+ ############################
249
+
250
+ # TODO
egse/command.py CHANGED
@@ -87,6 +87,7 @@ Do we need additional hooks into this commanding?
87
87
  * provide an execute method for the CommandExecution that executes the command
88
88
  with the saved parameters
89
89
  """
90
+
90
91
  import functools
91
92
  import inspect
92
93
  import logging
@@ -149,7 +150,6 @@ def dry_run(func: Callable) -> Callable:
149
150
 
150
151
  @functools.wraps(func)
151
152
  def func_wrapper(self, *args, **kwargs):
152
-
153
153
  from egse.state import GlobalState # prevent circular import
154
154
 
155
155
  if GlobalState.dry_run:
@@ -167,9 +167,7 @@ def dry_run(func: Callable) -> Callable:
167
167
  else:
168
168
  FunctionExecution = namedtuple("FunctionExecution", ["name", "args", "kwargs"])
169
169
  GlobalState.add_command(FunctionExecution(func.__name__, args, kwargs))
170
- return Success(
171
- "Command execution appended to command sequence, function not executed in dry_run."
172
- )
170
+ return Success("Command execution appended to command sequence, function not executed in dry_run.")
173
171
  else:
174
172
  return func(self, *args, **kwargs)
175
173
 
@@ -206,8 +204,7 @@ def parse_format_string(fstring):
206
204
 
207
205
  # If this assertion fails, there is a flaw in the algorithm above
208
206
  assert tot_n_args == n_args + n_kwargs, (
209
- f"Total number of arguments ({tot_n_args}) doesn't match # args ({n_args}) + "
210
- f"# kwargs ({n_kwargs})."
207
+ f"Total number of arguments ({tot_n_args}) doesn't match # args ({n_args}) + # kwargs ({n_kwargs})."
211
208
  )
212
209
 
213
210
  if n_args > 0 and n_kwargs > 0:
@@ -291,9 +288,7 @@ class InvalidCommandExecution(CommandExecution):
291
288
  self._exc = exc
292
289
 
293
290
  def run(self):
294
- raise InvalidArgumentsError(
295
- f"The command {self.get_name()} can not be executed. Reason: {self._exc}"
296
- )
291
+ raise InvalidArgumentsError(f"The command {self.get_name()} can not be executed. Reason: {self._exc}")
297
292
 
298
293
  def __str__(self):
299
294
  msg = super().__str__()
@@ -307,7 +302,6 @@ class WaitCommand:
307
302
  self._condition = condition
308
303
 
309
304
  def __call__(self):
310
-
311
305
  # .. todo:: do we need a timeout possibility here?
312
306
 
313
307
  while True:
@@ -330,10 +324,7 @@ class Command:
330
324
  Arguments can be positional or keyword arguments, not both.
331
325
  """
332
326
 
333
- def __init__(
334
- self, name, cmd, response=None, wait=None, check=None, description=None,
335
- device_method=None
336
- ):
327
+ def __init__(self, name, cmd, response=None, wait=None, check=None, description=None, device_method=None):
337
328
  self._name = name
338
329
  self._cmd = cmd
339
330
  self._response = response
@@ -362,7 +353,6 @@ class Command:
362
353
  return msg
363
354
 
364
355
  def validate_arguments(self, *args, **kwargs):
365
-
366
356
  # Special case for commands with *args or **kwargs, we don't validate
367
357
 
368
358
  if self._cmd in ("*", "**"):
@@ -373,8 +363,7 @@ class Command:
373
363
 
374
364
  if self._tot_n_args != nargs + nkwargs:
375
365
  raise InvalidArgumentsError(
376
- f"Expected {self._tot_n_args} arguments for command {self._name}, "
377
- f"got {nargs + nkwargs} arguments."
366
+ f"Expected {self._tot_n_args} arguments for command {self._name}, got {nargs + nkwargs} arguments."
378
367
  )
379
368
 
380
369
  if self._tot_n_args == 0:
@@ -414,7 +403,6 @@ class Command:
414
403
  return self._device_method.__name__
415
404
 
416
405
  def get_command_execution(self, *args, **kwargs):
417
-
418
406
  return CommandExecution(self, *args, **kwargs)
419
407
 
420
408
  def __call__(self, *args, **kwargs):
@@ -444,8 +432,7 @@ class Command:
444
432
 
445
433
  if self._tot_n_args != nargs + nkwargs:
446
434
  raise CommandError(
447
- f"Expected {self._tot_n_args} arguments for command {self._name}, "
448
- f"got {nargs + nkwargs} arguments."
435
+ f"Expected {self._tot_n_args} arguments for command {self._name}, got {nargs + nkwargs} arguments."
449
436
  )
450
437
 
451
438
  if self._tot_n_args == 0:
@@ -539,17 +526,13 @@ class ClientServerCommand(Command):
539
526
  # the class instances are not known at the other side.
540
527
 
541
528
  if self._response.__name__ == "handle_device_method":
542
-
543
529
  # call the handle_device_method of the Protocol sub-class
544
530
 
545
- logger.log(0,
546
- f"Executing Command {self._response.__name__}({other!r}, "
547
- f"{self!r}, {args}, {kwargs})")
531
+ logger.log(0, f"Executing Command {self._response.__name__}({other!r}, {self!r}, {args}, {kwargs})")
548
532
 
549
533
  rc = self._response(other, self, *args, **kwargs)
550
534
  else:
551
- logger.log(0,
552
- f"Executing Command {self._response.__name__}({other!r}, {args}, {kwargs})")
535
+ logger.log(0, f"Executing Command {self._response.__name__}({other!r}, {args}, {kwargs})")
553
536
 
554
537
  rc = self._response(other, *args, **kwargs)
555
538
 
@@ -615,9 +598,7 @@ def get_function(parent_class, method_name: str):
615
598
  return func
616
599
  logger.warning(f"{method_name} is not a function, type={type(func)}")
617
600
  else:
618
- logger.warning(
619
- f"{parent_class.__module__}.{parent_class.__name__} has no method called {method_name}"
620
- )
601
+ logger.warning(f"{parent_class.__module__}.{parent_class.__name__} has no method called {method_name}")
621
602
 
622
603
  return None
623
604
 
egse/config.py CHANGED
@@ -20,8 +20,10 @@ from typing import Union
20
20
 
21
21
  import git
22
22
 
23
- HERE = Path(__file__).parent.resolve()
24
- MODULE_LOGGER = logging.getLogger(__name__)
23
+ from egse.decorators import deprecate
24
+
25
+ _HERE = Path(__file__).parent.resolve()
26
+ _LOGGER = logging.getLogger(__name__)
25
27
 
26
28
 
27
29
  def find_first_occurrence_of_dir(pattern: str, root: Path | str = None) -> Optional[Path]:
@@ -43,7 +45,7 @@ def find_first_occurrence_of_dir(pattern: str, root: Path | str = None) -> Optio
43
45
  """
44
46
  import fnmatch
45
47
 
46
- root = Path(root).resolve() if root else HERE
48
+ root = Path(root).resolve() if root else _HERE
47
49
  if not root.is_dir():
48
50
  root = root.parent
49
51
 
@@ -130,7 +132,7 @@ def find_dirs(pattern: str, root: str = None):
130
132
  yield Path(path) / name
131
133
 
132
134
 
133
- def find_files(pattern: str, root: str = None, in_dir: str = None):
135
+ def find_files(pattern: str, root: PurePath | str = None, in_dir: str = None):
134
136
  """
135
137
  Generator for returning file paths from a top folder, matching the pattern.
136
138
 
@@ -171,7 +173,7 @@ def find_files(pattern: str, root: str = None, in_dir: str = None):
171
173
 
172
174
  def find_file(name: str, root: str = None, in_dir: str = None) -> Optional[Path]:
173
175
  """
174
- Find the path to the given file starting from the root directory of the Common-EGSE
176
+ Find the path to the given file starting from the root directory of the
175
177
  distribution.
176
178
 
177
179
  Note that if there are more files with the given name found in the distribution,
@@ -202,7 +204,7 @@ def find_file(name: str, root: str = None, in_dir: str = None) -> Optional[Path]
202
204
 
203
205
 
204
206
  def find_root(
205
- path: Union[str, PurePath], tests: Tuple[str, ...] = (), default: str = None
207
+ path: Union[str, PurePath] | None, tests: Tuple[str, ...] = (), default: str = None
206
208
  ) -> Union[PurePath, None]:
207
209
  """
208
210
  Find the root folder based on the files in ``tests``.
@@ -240,6 +242,8 @@ def find_root(
240
242
 
241
243
 
242
244
  @lru_cache(maxsize=16)
245
+ @deprecate(reason="the concept of CGSE root doesn't exist in a monorepo.",
246
+ alternative="a case-by-case alternative.")
243
247
  def get_common_egse_root(path: Union[str, PurePath] = None) -> Optional[PurePath]:
244
248
  """
245
249
  Returns the absolute path to the installation directory for the Common-EGSE.
@@ -266,7 +270,7 @@ def get_common_egse_root(path: Union[str, PurePath] = None) -> Optional[PurePath
266
270
  if path is not None:
267
271
  return find_root(path, tests=_TEST_NAMES)
268
272
 
269
- egse_path: Union[str, PurePath, None] = os.getenv("PLATO_COMMON_EGSE_PATH")
273
+ egse_path: Union[str, PurePath, None] = os.getenv("COMMON_EGSE_PATH")
270
274
 
271
275
  if egse_path is None:
272
276
 
@@ -285,13 +289,13 @@ def get_common_egse_root(path: Union[str, PurePath] = None) -> Optional[PurePath
285
289
  git_root = git_repo.git.rev_parse("--show-toplevel")
286
290
  egse_path = git_root
287
291
  except (git.exc.InvalidGitRepositoryError, git.exc.NoSuchPathError):
288
- MODULE_LOGGER.info("no git repository found, assuming installation from distribution.")
292
+ _LOGGER.info("no git repository found, assuming installation from distribution.")
289
293
  egse_path = find_root(_THIS_FILE_LOCATION, tests=_TEST_NAMES)
290
294
 
291
- MODULE_LOGGER.debug(f"Common-EGSE location is automatically determined: {egse_path}.")
295
+ _LOGGER.debug(f"Common-EGSE location is automatically determined: {egse_path}.")
292
296
 
293
297
  else:
294
- MODULE_LOGGER.debug(
298
+ _LOGGER.debug(
295
299
  f"Common-EGSE location determined from environment variable "
296
300
  f"PLATO_COMMON_EGSE_PATH: {egse_path}"
297
301
  )
@@ -368,7 +372,8 @@ def set_logger_levels(logger_levels: List[Tuple] = None):
368
372
 
369
373
 
370
374
  class WorkingDirectory:
371
- """WorkingDirectory is a context manager to temporarily change the working directory while
375
+ """
376
+ WorkingDirectory is a context manager to temporarily change the working directory while
372
377
  executing some code.
373
378
 
374
379
  This context manager has a property `path` which returns the absolute path of the
@@ -402,7 +407,7 @@ class WorkingDirectory:
402
407
  try:
403
408
  os.chdir(self._current_dir)
404
409
  except OSError as exc:
405
- MODULE_LOGGER.warning(f"Change back to previous directory failed: {exc}")
410
+ _LOGGER.warning(f"Change back to previous directory failed: {exc}")
406
411
 
407
412
  @property
408
413
  def path(self):
egse/control.py CHANGED
@@ -5,7 +5,6 @@ import abc
5
5
  import logging
6
6
  import pickle
7
7
  import threading
8
- import time
9
8
  from typing import Any
10
9
 
11
10
  import zmq
@@ -63,86 +62,6 @@ def is_control_server_active(endpoint: str = None, timeout: float = 0.5) -> bool
63
62
  return return_code
64
63
 
65
64
 
66
- class Response:
67
- """Base class for any reply or response between client-server communication.
68
-
69
- The idea is that the response is encapsulated in one of the subclasses depending
70
- on the type of response.
71
- """
72
-
73
- def __init__(self, message: str):
74
- self.message = message
75
-
76
- def __str__(self):
77
- return self.message
78
-
79
- @property
80
- def successful(self):
81
- """Returns True if the Response is not an Exception."""
82
- return not isinstance(self, Exception)
83
-
84
-
85
- class Failure(Response, Exception):
86
- """A failure response indicating something went wrong at the other side.
87
-
88
- This class is used to encapsulate an Exception that was caught and needs to be
89
- passed to the client. So, the intended use is like this:
90
- ```
91
- try:
92
- # perform some useful action that might raise an Exception
93
- except SomeException as exc:
94
- return Failure("Our action failed", exc)
95
- ```
96
- The client can inspect the Exception that was originally raised, in this case `SomeException`
97
- with the `cause` variable.
98
-
99
- Since a Failure is also an Exception, the property `successful` will return False.
100
- So, the calling method can test for this easily.
101
-
102
- ```
103
- rc: Response = function_that_returns_a_response()
104
-
105
- if not rc.successful:
106
- # handle the failure
107
- else:
108
- # handle success
109
- ```
110
-
111
- """
112
-
113
- def __init__(self, message: str, cause: Exception = None):
114
- msg = f"{message}: {cause}" if cause is not None else message
115
- super().__init__(msg)
116
- self.cause = cause
117
-
118
-
119
- class Success(Response):
120
- """A success response for the client.
121
-
122
- The return code from any action or function that needs to be returned to the
123
- client shall be added.
124
-
125
- Since `Success` doesn't inherit from `Exception`, the property `successful` will return True.
126
- """
127
-
128
- def __init__(self, message: str, return_code: Any = None):
129
- msg = f"{message}: {return_code}" if return_code is not None else message
130
- super().__init__(msg)
131
- self.return_code = return_code
132
-
133
-
134
- class Message(Response):
135
- """A message response from the client.
136
-
137
- Send a Message when there is no Failure, but also no return code. This is the alternative of
138
- returning a None.
139
-
140
- Message returns True for the property successful since it doesn't inherit from Exception.
141
- """
142
-
143
- pass
144
-
145
-
146
65
  class ControlServer(metaclass=abc.ABCMeta):
147
66
  """
148
67
  The base class for all device control servers and for the Storage Manager and Configuration
egse/decorators.py CHANGED
@@ -13,7 +13,7 @@ from typing import Optional
13
13
  from egse.settings import Settings
14
14
  from egse.system import get_caller_info
15
15
 
16
- MODULE_LOGGER = logging.getLogger(__name__)
16
+ _LOGGER = logging.getLogger(__name__)
17
17
 
18
18
 
19
19
  def static_vars(**kwargs):
@@ -95,7 +95,7 @@ def timer(*, level: int = logging.INFO, precision: int = 4):
95
95
  value = func(*args, **kwargs)
96
96
  end_time = time.perf_counter()
97
97
  run_time = end_time - start_time
98
- MODULE_LOGGER.log(level, f"Finished {func.__name__!r} in {run_time:.{precision}f} secs")
98
+ _LOGGER.log(level, f"Finished {func.__name__!r} in {run_time:.{precision}f} secs")
99
99
  return value
100
100
 
101
101
  return wrapper_timer
@@ -160,9 +160,9 @@ def debug(func):
160
160
  args_repr = [repr(a) for a in args]
161
161
  kwargs_repr = [f"{k}={v!r}" for k, v in kwargs.items()]
162
162
  signature = ", ".join(args_repr + kwargs_repr)
163
- MODULE_LOGGER.debug(f"Calling {func.__name__}({signature})")
163
+ _LOGGER.debug(f"Calling {func.__name__}({signature})")
164
164
  value = func(*args, **kwargs)
165
- MODULE_LOGGER.debug(f"{func.__name__!r} returned {value!r}")
165
+ _LOGGER.debug(f"{func.__name__!r} returned {value!r}")
166
166
  else:
167
167
  value = func(*args, **kwargs)
168
168
  return value
@@ -240,10 +240,10 @@ def profile(func):
240
240
  signature = ", ".join(args_repr + kwargs_repr)
241
241
  caller = get_caller_info(level=2)
242
242
  prefix = f"PROFILE[{profile.counter}]: "
243
- MODULE_LOGGER.info(f"{prefix}Calling {func.__name__}({signature})")
244
- MODULE_LOGGER.info(f"{prefix} from {caller.filename} at {caller.lineno}.")
243
+ _LOGGER.info(f"{prefix}Calling {func.__name__}({signature})")
244
+ _LOGGER.info(f"{prefix} from {caller.filename} at {caller.lineno}.")
245
245
  value = func(*args, **kwargs)
246
- MODULE_LOGGER.info(f"{prefix}{func.__name__!r} returned {value!r}")
246
+ _LOGGER.info(f"{prefix}{func.__name__!r} returned {value!r}")
247
247
  profile.counter -= 1
248
248
  else:
249
249
  value = func(*args, **kwargs)
@@ -257,7 +257,7 @@ def to_be_implemented(func):
257
257
 
258
258
  @functools.wraps(func)
259
259
  def wrapper_tbi(*args, **kwargs):
260
- MODULE_LOGGER.warning(f"The function/method {func.__name__} is not yet implemented.")
260
+ _LOGGER.warning(f"The function/method {func.__name__} is not yet implemented.")
261
261
  return func(*args, **kwargs)
262
262
 
263
263
  return wrapper_tbi
egse/device.py CHANGED
@@ -12,8 +12,10 @@ class DeviceConnectionState(IntEnum):
12
12
  """Defines connection states for device connections."""
13
13
 
14
14
  # We do not use zero '0' as the connected state to prevent a state to be set
15
- # to connected by default without it explicitly being set.
15
+ # to connected by default without it explicitly being set. Therefore, 0 will
16
+ # be the state where the connection is not explicitly set.
16
17
 
18
+ DEVICE_CONNECTION_NOT_SET = 0
17
19
  DEVICE_CONNECTED = 1
18
20
  DEVICE_NOT_CONNECTED = 2
19
21