pyForceDAQ 2.0.2__tar.gz → 2.0.3.dev1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/PKG-INFO +1 -1
  2. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/pyproject.toml +1 -1
  3. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/__init__.py +8 -6
  4. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/__main__.py +7 -4
  5. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/_lib/clock.py +9 -9
  6. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/_lib/data_recorder.py +81 -54
  7. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/_lib/lsl.py +11 -8
  8. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/_lib/misc.py +38 -14
  9. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/_lib/polling_time_profile.py +12 -9
  10. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/_lib/process_priority_manager.py +28 -21
  11. pyforcedaq-2.0.3.dev1/src/pyforcedaq/_lib/sensor.py +110 -0
  12. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/_lib/sensor_process.py +85 -81
  13. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/_lib/settings.py +59 -45
  14. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/_lib/types.py +71 -72
  15. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/_lib/udp_connection.py +33 -26
  16. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/daq/__init__.py +1 -2
  17. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/daq/_calibration_dll.py +5 -6
  18. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/daq/_calibration_iaftt.py +1 -1
  19. pyforcedaq-2.0.2/src/pyforcedaq/daq/pyATIDAQ.py → pyforcedaq-2.0.3.dev1/src/pyforcedaq/daq/_pyATIDAQ.py +2 -9
  20. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/daq/_use_nidaqmx.py +22 -20
  21. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/daq/_use_pydaqmx.py +38 -36
  22. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/gui/__init__.py +1 -2
  23. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/gui/_gui_status.py +54 -38
  24. pyforcedaq-2.0.3.dev1/src/pyforcedaq/gui/_layout.py +120 -0
  25. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/gui/_level_indicator.py +28 -18
  26. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/gui/_pg_surface.py +1 -2
  27. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/gui/_plotter.py +90 -67
  28. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/gui/_run.py +214 -144
  29. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/gui/_scaling.py +13 -12
  30. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/launcher.py +72 -40
  31. pyforcedaq-2.0.2/src/pyforcedaq/_lib/_log.py +0 -19
  32. pyforcedaq-2.0.2/src/pyforcedaq/_lib/sensor.py +0 -97
  33. pyforcedaq-2.0.2/src/pyforcedaq/gui/_layout.py +0 -101
  34. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/_lib/__init__.py +0 -0
  35. {pyforcedaq-2.0.2/src/pyforcedaq/_lib → pyforcedaq-2.0.3.dev1/src/pyforcedaq}/constants.py +0 -0
  36. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/daq/_mock_sensor.py +0 -0
  37. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/extras/__init__.py +0 -0
  38. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/extras/convert.py +0 -0
  39. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/extras/read_force_data.py +0 -0
  40. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/force.py +0 -0
  41. {pyforcedaq-2.0.2 → pyforcedaq-2.0.3.dev1}/src/pyforcedaq/gui/forceDAQ_logo.png +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: pyForceDAQ
3
- Version: 2.0.2
3
+ Version: 2.0.3.dev1
4
4
  Summary: A Python package for data acquisition and analysis in force-based experiments.
5
5
  Author: Oliver Lindemann
6
6
  Author-email: Oliver Lindemann <lindemann@essb.eur.nl>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "pyForceDAQ"
3
- version = "2.0.2"
3
+ version = "2.0.3-dev1"
4
4
  description = "A Python package for data acquisition and analysis in force-based experiments."
5
5
  authors = [
6
6
  { name = "Oliver Lindemann", email = "lindemann@essb.eur.nl" },
@@ -30,9 +30,11 @@ __author__ = "Oliver Lindemann"
30
30
 
31
31
  import sys as _sys
32
32
 
33
- if _sys.version_info[0] != 3 or _sys.version_info[1]<12:
34
- raise RuntimeError("pyForceDAQ {0} ".format(__version__) +
35
- "is not compatible with Python {0}.{1}. ".format(
36
- _sys.version_info[0],
37
- _sys.version_info[1]) +
38
- "Please use Python 3.12+.")
33
+ if _sys.version_info[0] != 3 or _sys.version_info[1] < 12:
34
+ raise RuntimeError(
35
+ "pyForceDAQ {0} ".format(__version__)
36
+ + "is not compatible with Python {0}.{1}. ".format(
37
+ _sys.version_info[0], _sys.version_info[1]
38
+ )
39
+ + "Please use Python 3.12+."
40
+ )
@@ -17,14 +17,16 @@ def cli():
17
17
  parser.add_argument("SETTINGS_FILE", nargs="?", default="", help="settings file")
18
18
 
19
19
  parser.add_argument(
20
- "-l", "--launcher",
20
+ "-l",
21
+ "--launcher",
21
22
  action="store_true",
22
23
  default=False,
23
24
  help="Run with launcher GUI to edit settings and start recording",
24
25
  )
25
26
 
26
27
  parser.add_argument(
27
- "-o", "--omit-launcher",
28
+ "-o",
29
+ "--omit-launcher",
28
30
  action="store_true",
29
31
  default=False,
30
32
  help="Omit launcher GUI and start recording directly",
@@ -41,12 +43,13 @@ def cli():
41
43
  exit()
42
44
 
43
45
  from .launcher import run_launcher
46
+
44
47
  return run_launcher()
45
48
  else:
46
49
  from .gui import run_settings_file
47
- run_settings_file(args.SETTINGS_FILE)
48
50
 
51
+ run_settings_file(args.SETTINGS_FILE)
49
52
 
50
53
 
51
- if __name__ == "__main__": # required because of threading
54
+ if __name__ == "__main__": # required because of threading
52
55
  cli()
@@ -1,5 +1,5 @@
1
- """A high-resolution monotonic timer based on LSL's local_clock() function.
2
- """
1
+ """A high-resolution monotonic timer based on LSL's local_clock() function."""
2
+
3
3
  from time import sleep
4
4
 
5
5
  from pylsl import local_clock
@@ -9,24 +9,24 @@ def local_clock_ms():
9
9
  """Returns the current time in milliseconds, based on LSL's local_clock()"""
10
10
  return local_clock() * 1000
11
11
 
12
- def wait_ms(waiting_time: int | float, looptime : int = 200) -> None:
13
- """Wait for a certain amount of milliseconds.
14
- """
12
+
13
+ def wait_ms(waiting_time: int | float, looptime: int = 200) -> None:
14
+ """Wait for a certain amount of milliseconds."""
15
15
  start = local_clock_ms()
16
16
  if waiting_time > looptime:
17
17
  sleep((waiting_time - looptime) / 1000)
18
18
  while local_clock_ms() < start + waiting_time:
19
19
  pass
20
20
 
21
- class StopWatch(object):#
21
+
22
+ class StopWatch(object): #
22
23
  """A simple timer"""
23
24
 
24
25
  def __init__(self):
25
26
  self._init_time = local_clock()
26
27
 
27
28
  def reset_stopwatch(self):
28
- """Reset the stopwatch time to zero.
29
- """
29
+ """Reset the stopwatch time to zero."""
30
30
  self._init_time = local_clock()
31
31
 
32
32
  @property
@@ -35,4 +35,4 @@ class StopWatch(object):#
35
35
 
36
36
  @property
37
37
  def time_ms(self) -> float:
38
- return self.time * 1000
38
+ return self.time * 1000
@@ -2,6 +2,7 @@
2
2
 
3
3
  See COPYING file distributed along with the pyForceDAQ copyright and license terms.
4
4
  """
5
+
5
6
  __author__ = "Oliver Lindemann"
6
7
 
7
8
  import atexit
@@ -13,8 +14,8 @@ from time import asctime, localtime, strftime
13
14
  from typing import List
14
15
 
15
16
  from .. import __version__ as forceDAQVersion
16
- from . import _log
17
17
  from .clock import wait_ms
18
+ from .misc import set_logging
18
19
  from .process_priority_manager import ProcessPriorityManager
19
20
  from .sensor_process import SensorProcess
20
21
  from .settings import RecordingSettings, SensorSettings
@@ -29,19 +30,20 @@ from .types import (
29
30
  )
30
31
  from .udp_connection import UDPConnectionProcess
31
32
 
32
- _log.set_logging(data_directory="data", log_file="recording.log")
33
+ set_logging(data_directory="data", log_file="recording.log")
33
34
 
34
35
  NEWLINE = "\n"
35
36
 
37
+
36
38
  class DataRecorder(object):
37
39
  """handles multiple sensors and udp connection"""
38
40
 
39
- def __init__(self,
40
- recording_settings: RecordingSettings,
41
- force_sensor_settings:SensorSettings | List[SensorSettings],
42
- poll_udp_connection: bool = False):
43
-
44
-
41
+ def __init__(
42
+ self,
43
+ recording_settings: RecordingSettings,
44
+ force_sensor_settings: SensorSettings | List[SensorSettings],
45
+ poll_udp_connection: bool = False,
46
+ ):
45
47
  """queue_data will be saved
46
48
  see sensorprocess.__init__
47
49
 
@@ -55,15 +57,17 @@ class DataRecorder(object):
55
57
  self.recording_settings = recording_settings
56
58
 
57
59
  # create sensor processes
58
- self._force_sensor_processes =[]
60
+ self._force_sensor_processes = []
59
61
  event_trigger = []
60
62
  for fs in force_sensor_settings:
61
63
  if not isinstance(fs, SensorSettings):
62
64
  raise RuntimeError("Recorder needs a list of Force Sensor Settings!")
63
65
  else:
64
- fst = SensorProcess(sensor_settings = fs,
65
- recording_settings=recording_settings,
66
- pipe_buffered_data_after_pause=True)
66
+ fst = SensorProcess(
67
+ sensor_settings=fs,
68
+ recording_settings=recording_settings,
69
+ pipe_buffered_data_after_pause=True,
70
+ )
67
71
  fst.start()
68
72
  event_trigger.append(fst.event_trigger)
69
73
  self._force_sensor_processes.append(fst)
@@ -80,13 +84,15 @@ class DataRecorder(object):
80
84
  self._proc_manager.add_subprocess(self.udp)
81
85
  self._proc_manager.add_subprocess(self._force_sensor_processes)
82
86
  if self.recording_settings.priority is not None:
83
- level = PollingPriority.NORMAL
87
+ level = PollingPriority.NORMAL
84
88
  else:
85
89
  level = PollingPriority.get_priority(self.recording_settings.priority)
86
90
  self._proc_manager.set_subprocess_priorities(level=level, disable_gc=False)
87
91
 
88
- logging.info("Main process priority: %s", self._proc_manager.get_main_priority())
89
- #logging.info("Subprocess priorities: {}".format(self._proc_manager.get_subprocess_priorities()))
92
+ logging.info(
93
+ "Main process priority: %s", self._proc_manager.get_main_priority()
94
+ )
95
+ # logging.info("Subprocess priorities: {}".format(self._proc_manager.get_subprocess_priorities()))
90
96
 
91
97
  self._is_recording = False
92
98
  self._file = None
@@ -118,8 +124,7 @@ class DataRecorder(object):
118
124
 
119
125
  @property
120
126
  def sensor_settings_list(self):
121
- return list(map(lambda x:x.sensor_settings,
122
- self._force_sensor_processes))
127
+ return list(map(lambda x: x.sensor_settings, self._force_sensor_processes))
123
128
 
124
129
  def quit(self) -> list | None:
125
130
  """Stop all recording processes, close data file and quit recording
@@ -152,28 +157,28 @@ class DataRecorder(object):
152
157
  buffer = []
153
158
  while True:
154
159
  try:
155
- data = self.udp.receive_queue.get_nowait() # type: ignore
160
+ data = self.udp.receive_queue.get_nowait() # type: ignore
156
161
  except AttributeError:
157
162
  # until queue empty or no udp connection
158
163
  break
159
164
  buffer.append(data)
160
- if len(buffer)>0:
165
+ if len(buffer) > 0:
161
166
  self._write_data(buffer)
162
167
  return buffer
163
168
 
164
- def _write_data(self, data_buffer: list,
165
- recording_screen=None,
166
- float_decimal_places: int = 4) -> None:
167
- """ writes data to disk and set counters
169
+ def _write_data(
170
+ self, data_buffer: list, recording_screen=None, float_decimal_places: int = 4
171
+ ) -> None:
172
+ """writes data to disk and set counters
168
173
 
169
174
  ignores UDP remote control commands
170
175
  """
171
- #DOC output format
176
+ # DOC output format
172
177
 
173
- BLOCKSIZE = 10000 # for recording screen feedback only
178
+ BLOCKSIZE = 10000 # for recording screen feedback only
174
179
  write_forces = self.recording_settings.array_write_forces()
175
180
  write_trigger = self.recording_settings.array_write_trigger()
176
- write_deviceid = len(self.recording_settings.device_labels)>1
181
+ write_deviceid = len(self.recording_settings.device_labels) > 1
177
182
  float_format = "{0:." + str(float_decimal_places) + "f},"
178
183
  buffer_len = len(data_buffer)
179
184
  for c, d in enumerate(data_buffer):
@@ -182,9 +187,9 @@ class DataRecorder(object):
182
187
  line = f"{d.time}, {d.acquisition_delay},"
183
188
  if write_deviceid:
184
189
  line += f"{d.sensor_id},"
185
- for x in d.selected_forces(select=write_forces):
190
+ for x in d.forces[write_forces]:
186
191
  line += float_format.format(x)
187
- for x in d.selected_trigger(select=write_trigger):
192
+ for x in d.trigger[write_trigger]:
188
193
  if isinstance(x, int):
189
194
  line += f"{x},"
190
195
  else:
@@ -199,8 +204,10 @@ class DataRecorder(object):
199
204
 
200
205
  if recording_screen is not None and c % BLOCKSIZE == 0:
201
206
  recording_screen.stimulus(
202
- "Saving {0} of {1} blocks".format(c//BLOCKSIZE,
203
- buffer_len//BLOCKSIZE)).present()
207
+ "Saving {0} of {1} blocks".format(
208
+ c // BLOCKSIZE, buffer_len // BLOCKSIZE
209
+ )
210
+ ).present()
204
211
 
205
212
  def _file_write(self, s: str) -> None:
206
213
 
@@ -209,15 +216,15 @@ class DataRecorder(object):
209
216
  elif isinstance(self._file, TextIOWrapper):
210
217
  self._file.write(s)
211
218
 
212
-
213
- def store_daq_event(self, code: str | int | float, time: float | None = None) -> None:
219
+ def store_daq_event(
220
+ self, code: str | int | float, time: float | None = None
221
+ ) -> None:
214
222
  """Set marker code in file
215
223
 
216
224
  DAQEvent will be timestamps and occur in the data output
217
225
 
218
226
  """
219
- self._daq_event.append(DAQEvents(time = time, code = code))
220
-
227
+ self._daq_event.append(DAQEvents(time=time, code=code))
221
228
 
222
229
  def start_recording(self, determine_bias: bool = False) -> None:
223
230
  """Start polling process and record
@@ -231,12 +238,20 @@ class DataRecorder(object):
231
238
  if determine_bias:
232
239
  self.determine_biases(n_samples=1000)
233
240
 
234
- if len(list(filter(lambda x:x.event_bias_is_available.is_set(),
235
- self._force_sensor_processes))) != len(self._force_sensor_processes):
236
- raise RuntimeError("Sensors can't be started before bias has been determined.")
241
+ if len(
242
+ list(
243
+ filter(
244
+ lambda x: x.event_bias_is_available.is_set(),
245
+ self._force_sensor_processes,
246
+ )
247
+ )
248
+ ) != len(self._force_sensor_processes):
249
+ raise RuntimeError(
250
+ "Sensors can't be started before bias has been determined."
251
+ )
237
252
 
238
253
  # start polling
239
- list(map(lambda x:x.start_polling(), self._force_sensor_processes))
254
+ list(map(lambda x: x.start_polling(), self._force_sensor_processes))
240
255
  self._is_recording = True
241
256
 
242
257
  def pause_recording(self, recording_screen=None) -> list:
@@ -253,7 +268,7 @@ class DataRecorder(object):
253
268
  if recording_screen is not None:
254
269
  recording_screen.stimulus("").present()
255
270
 
256
- #pause polling
271
+ # pause polling
257
272
  for fsp in self._force_sensor_processes:
258
273
  fsp.pause_polling()
259
274
 
@@ -301,11 +316,13 @@ class DataRecorder(object):
301
316
  for x in self._force_sensor_processes:
302
317
  x.event_bias_is_available.wait()
303
318
 
304
- def open_data_file(self,
305
- filename: str | Path,
306
- subdirectory: str = "data",
307
- varnames: bool = True,
308
- comment_line: str = "") -> Path:
319
+ def open_data_file(
320
+ self,
321
+ filename: str | Path,
322
+ subdirectory: str = "data",
323
+ varnames: bool = True,
324
+ comment_line: str = "",
325
+ ) -> Path:
309
326
  """Create a data file
310
327
 
311
328
  Only if data file has been opened, data will be saved!
@@ -344,40 +361,50 @@ class DataRecorder(object):
344
361
  self.path_open_file = data_dir / filename
345
362
  if self.path_open_file.is_file():
346
363
  # print "data file already exists, adding counter"
347
- filename = Path(filename.stem + "_" + strftime("%m%d%H%M", localtime()) + \
348
- filename.suffix)
364
+ filename = Path(
365
+ filename.stem
366
+ + "_"
367
+ + strftime("%m%d%H%M", localtime())
368
+ + filename.suffix
369
+ )
349
370
  else:
350
371
  break
351
372
 
352
373
  if self.recording_settings.zip_data:
353
- self._file = gzip.open(self.path_open_file, 'w')
374
+ self._file = gzip.open(self.path_open_file, "w")
354
375
  else:
355
- self._file = open(self.path_open_file, 'w')
376
+ self._file = open(self.path_open_file, "w")
356
377
  print("Data file: {}".format(self.path_open_file))
357
378
 
358
- self._file_write(TAG_COMMENTS + "Recorded at {0} with pyForceDAQ {1}\n".format(
359
- asctime(localtime()), forceDAQVersion))
379
+ self._file_write(
380
+ TAG_COMMENTS
381
+ + "Recorded at {0} with pyForceDAQ {1}\n".format(
382
+ asctime(localtime()), forceDAQVersion
383
+ )
384
+ )
360
385
  logging.info("new file: {}".format(self.path_open_file))
361
386
 
362
387
  for s in self.sensor_settings_list:
363
388
  txt = f" Sensor: label={s.device_label}, cal-file={s.calibration_file}\n"
364
389
  self._file_write(TAG_COMMENTS + txt)
365
390
 
366
- if len(comment_line)>0:
391
+ if len(comment_line) > 0:
367
392
  self._file_write(TAG_COMMENTS + comment_line + "\n")
368
393
 
369
394
  if varnames:
370
395
  write_forces = self.recording_settings.array_write_forces()
371
396
  write_trigger = self.recording_settings.array_write_trigger()
372
- write_deviceid = len(self.recording_settings.device_labels)>1
397
+ write_deviceid = len(self.recording_settings.device_labels) > 1
373
398
  line = "time,delay,"
374
399
  if write_deviceid:
375
400
  line += "device_tag,"
376
401
  for x in range(6):
377
402
  if write_forces[x]:
378
403
  line += ForceSensorData.forces_names[x] + ","
379
- if write_trigger[0]: line += "trigger1,"
380
- if write_trigger[1]: line += "trigger2,"
404
+ if write_trigger[0]:
405
+ line += "trigger1,"
406
+ if write_trigger[1]:
407
+ line += "trigger2,"
381
408
  self._file_write(line[:-1] + NEWLINE)
382
409
 
383
410
  return self.path_open_file
@@ -12,8 +12,7 @@ from pylsl import (
12
12
  )
13
13
 
14
14
 
15
- class LSLSream():
16
-
15
+ class LSLSream:
17
16
  def __init__(self):
18
17
  self.outlet = None
19
18
  self._is_init = False
@@ -22,7 +21,8 @@ class LSLSream():
22
21
  def is_init(self):
23
22
  return self._is_init
24
23
 
25
- def init(self,
24
+ def init(
25
+ self,
26
26
  name: str,
27
27
  n_channels: int,
28
28
  stream_id: str,
@@ -50,11 +50,14 @@ class LSLSream():
50
50
  if self._is_init:
51
51
  return
52
52
 
53
- info = StreamInfo(name, "force",
54
- channel_count=n_channels,
55
- nominal_srate=freq,
56
- channel_format=channel_format,
57
- source_id=stream_id)
53
+ info = StreamInfo(
54
+ name,
55
+ "force",
56
+ channel_count=n_channels,
57
+ nominal_srate=freq,
58
+ channel_format=channel_format,
59
+ source_id=stream_id,
60
+ )
58
61
 
59
62
  # Check if there is metadata to add to the lsl stream
60
63
  if metadata:
@@ -1,7 +1,28 @@
1
+ import logging
2
+ import os
3
+ import sys
1
4
  from pathlib import Path
2
5
 
6
+ from ..constants import SETTINGS_FILE_EXTENSION
3
7
  from .clock import local_clock_ms
4
- from .constants import SETTINGS_FILE_EXTENSION
8
+
9
+
10
+ def set_logging(data_directory, log_file):
11
+ base_dir = os.path.split(sys.argv[0])[0]
12
+ log_dir = os.path.join(base_dir, data_directory)
13
+ try:
14
+ os.mkdir(log_dir)
15
+ except:
16
+ pass
17
+ log_file = os.path.abspath(os.path.join(log_dir, log_file))
18
+ logging.basicConfig(
19
+ level=logging.INFO,
20
+ format="[%(asctime)s] %(message)s",
21
+ datefmt="%m-%d %H:%M:%S",
22
+ filename=log_file,
23
+ filemode="a",
24
+ )
25
+ return log_file
5
26
 
6
27
 
7
28
  def list_settings_files():
@@ -10,11 +31,11 @@ def list_settings_files():
10
31
 
11
32
 
12
33
  def N2g(N):
13
- kg = N/9.81
14
- return kg*1000
34
+ kg = N / 9.81
35
+ return kg * 1000
15
36
 
16
- class MinMaxDetector(object):
17
37
 
38
+ class MinMaxDetector(object):
18
39
  def __init__(self, start_value, duration_ms):
19
40
  self._minmax = [start_value, start_value]
20
41
  self._duration_ms = duration_ms
@@ -33,7 +54,7 @@ class MinMaxDetector(object):
33
54
  elif value < self._minmax[0]:
34
55
  self._minmax[0] = value
35
56
 
36
- elif self._minmax[0] != value: # level change just occurred
57
+ elif self._minmax[0] != value: # level change just occurred
37
58
  self._level_change_time = local_clock_ms()
38
59
  return self.process(value)
39
60
 
@@ -42,8 +63,10 @@ class MinMaxDetector(object):
42
63
  @property
43
64
  def is_sampling_for_minmax(self):
44
65
  """true true if currently sampling for minmax"""
45
- return (self._level_change_time is not None) and \
46
- (local_clock_ms() - self._level_change_time) < self._duration_ms
66
+ return (self._level_change_time is not None) and (
67
+ local_clock_ms() - self._level_change_time
68
+ ) < self._duration_ms
69
+
47
70
 
48
71
  # def find_calibration_file(calibration_folder: str, device_label: str,
49
72
  # calibration_suffix=".cal") -> str:
@@ -71,7 +94,8 @@ class MinMaxDetector(object):
71
94
  # print("No calibration file found for sensor '{0}'.".format(device_label))
72
95
  # exit()
73
96
 
74
- #Sensor History with moving average filtering and distance, velocity
97
+
98
+ # Sensor History with moving average filtering and distance, velocity
75
99
  class SensorHistory(object):
76
100
  """The Sensory History keeps track of the last n recorded sample and
77
101
  calculates online the moving average (running mean).
@@ -109,10 +133,12 @@ class SensorHistory(object):
109
133
  self.moving_average = self.calc_history_average()
110
134
  else:
111
135
  self._correction_cnt += 1
112
- self.moving_average = list(map(
113
- lambda x: x[0] + (float(x[1] - x[2]) / len(self.history)),
114
- zip(self.moving_average, values, pop)))
115
-
136
+ self.moving_average = list(
137
+ map(
138
+ lambda x: x[0] + (float(x[1] - x[2]) / len(self.history)),
139
+ zip(self.moving_average, values, pop),
140
+ )
141
+ )
116
142
 
117
143
  def calc_history_average(self):
118
144
  """Calculate history averages for all sensor parameter.
@@ -128,7 +154,6 @@ class SensorHistory(object):
128
154
  s = list(map(lambda x: x[0] + x[1], zip(s, t)))
129
155
  return list(map(lambda x: x / len(self.history), s))
130
156
 
131
-
132
157
  @property
133
158
  def history_size(self):
134
159
  return len(self.history)
@@ -140,4 +165,3 @@ class SensorHistory(object):
140
165
  @property
141
166
  def previous_moving_average(self):
142
167
  return self._previous_moving_average
143
-
@@ -4,13 +4,12 @@ from .clock import local_clock
4
4
 
5
5
 
6
6
  class PollingTimeProfile(object):
7
-
8
7
  def __init__(self, timing_range_ms=10):
9
8
  self._last = None
10
9
  self._timing_range_ms = 10
11
10
  self._zero_cnt = 0
12
11
 
13
- #self._zero_time_polling_frequency = {}
12
+ # self._zero_time_polling_frequency = {}
14
13
  self.profile_frequency = np.array([0] * (timing_range_ms + 1))
15
14
 
16
15
  def stop(self):
@@ -25,9 +24,9 @@ class PollingTimeProfile(object):
25
24
  d = self._timing_range_ms
26
25
  self.profile_frequency[d] += 1
27
26
 
28
- #if d == 0:
27
+ # if d == 0:
29
28
  # self._zero_cnt += 1
30
- #elif self._zero_cnt > 0:
29
+ # elif self._zero_cnt > 0:
31
30
  # try:
32
31
  # self._zero_time_polling_frequency[self._zero_cnt] += 1
33
32
  # except:
@@ -45,10 +44,14 @@ class PollingTimeProfile(object):
45
44
  return self.profile_frequency / n
46
45
 
47
46
  def get_profile_str(self):
48
- rtn = str(list(self.profile_frequency)
49
- ).replace("[", "").replace("]", "").replace(" ", "")
47
+ rtn = (
48
+ str(list(self.profile_frequency))
49
+ .replace("[", "")
50
+ .replace("]", "")
51
+ .replace(" ", "")
52
+ )
50
53
  return "polling profile [{}]".format(rtn)
51
54
 
52
- #@property
53
- #def zero_time_polling_frequency(self):
54
- # return np.array(list(self._zero_time_polling_frequency.items()))
55
+ # @property
56
+ # def zero_time_polling_frequency(self):
57
+ # return np.array(list(self._zero_time_polling_frequency.items()))