pyForceDAQ 2.0.2.dev0__py3-none-any.whl → 2.0.3.dev1__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.
Files changed (37) hide show
  1. pyforcedaq/__init__.py +8 -8
  2. pyforcedaq/__main__.py +14 -8
  3. pyforcedaq/_lib/clock.py +8 -10
  4. pyforcedaq/_lib/data_recorder.py +88 -58
  5. pyforcedaq/_lib/lsl.py +11 -8
  6. pyforcedaq/_lib/misc.py +45 -13
  7. pyforcedaq/_lib/polling_time_profile.py +12 -9
  8. pyforcedaq/_lib/process_priority_manager.py +28 -21
  9. pyforcedaq/_lib/sensor.py +55 -52
  10. pyforcedaq/_lib/sensor_process.py +86 -80
  11. pyforcedaq/_lib/settings.py +60 -48
  12. pyforcedaq/_lib/types.py +77 -67
  13. pyforcedaq/_lib/udp_connection.py +33 -26
  14. pyforcedaq/constants.py +9 -0
  15. pyforcedaq/daq/__init__.py +15 -7
  16. pyforcedaq/daq/_calibration_dll.py +20 -0
  17. pyforcedaq/daq/_calibration_iaftt.py +17 -0
  18. pyforcedaq/daq/_pyATIDAQ.py +2 -9
  19. pyforcedaq/daq/_use_nidaqmx.py +25 -23
  20. pyforcedaq/daq/_use_pydaqmx.py +38 -36
  21. pyforcedaq/force.py +1 -1
  22. pyforcedaq/gui/__init__.py +1 -2
  23. pyforcedaq/gui/_gui_status.py +54 -39
  24. pyforcedaq/gui/_layout.py +65 -47
  25. pyforcedaq/gui/_level_indicator.py +28 -18
  26. pyforcedaq/gui/_pg_surface.py +1 -2
  27. pyforcedaq/gui/_plotter.py +90 -67
  28. pyforcedaq/gui/_run.py +217 -151
  29. pyforcedaq/gui/_scaling.py +13 -12
  30. pyforcedaq/launcher.py +168 -0
  31. {pyforcedaq-2.0.2.dev0.dist-info → pyforcedaq-2.0.3.dev1.dist-info}/METADATA +1 -1
  32. pyforcedaq-2.0.3.dev1.dist-info/RECORD +40 -0
  33. {pyforcedaq-2.0.2.dev0.dist-info → pyforcedaq-2.0.3.dev1.dist-info}/WHEEL +1 -1
  34. pyforcedaq/_lib/_log.py +0 -19
  35. pyforcedaq/gui/launcher.py +0 -117
  36. pyforcedaq-2.0.2.dev0.dist-info/RECORD +0 -38
  37. {pyforcedaq-2.0.2.dev0.dist-info → pyforcedaq-2.0.3.dev1.dist-info}/entry_points.txt +0 -0
pyforcedaq/__init__.py CHANGED
@@ -30,11 +30,11 @@ __author__ = "Oliver Lindemann"
30
30
 
31
31
  import sys as _sys
32
32
 
33
- USE_MOCK_SENSOR = False # <-- change for usage in lab to False
34
-
35
- if _sys.version_info[0] != 3 or _sys.version_info[1]<12:
36
- raise RuntimeError("pyForceDAQ {0} ".format(__version__) +
37
- "is not compatible with Python {0}.{1}. ".format(
38
- _sys.version_info[0],
39
- _sys.version_info[1]) +
40
- "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
+ )
pyforcedaq/__main__.py CHANGED
@@ -1,7 +1,6 @@
1
-
2
1
  import argparse
3
2
 
4
- from . import __author__, __version__, gui
3
+ from . import __author__, __version__
5
4
 
6
5
 
7
6
  def cli():
@@ -18,18 +17,23 @@ def cli():
18
17
  parser.add_argument("SETTINGS_FILE", nargs="?", default="", help="settings file")
19
18
 
20
19
  parser.add_argument(
21
- "-l", "--launcher",
20
+ "-l",
21
+ "--launcher",
22
22
  action="store_true",
23
23
  default=False,
24
24
  help="Run with launcher GUI to edit settings and start recording",
25
25
  )
26
26
 
27
27
  parser.add_argument(
28
- "-o", "--omit-launcher",
28
+ "-o",
29
+ "--omit-launcher",
29
30
  action="store_true",
30
31
  default=False,
31
32
  help="Omit launcher GUI and start recording directly",
32
33
  )
34
+ print("+" + "-" * 23 + "+")
35
+ print(f"| pyforceDAQ {__version__}".ljust(24) + "|")
36
+ print("+" + "-" * 23 + "+")
33
37
 
34
38
  args = parser.parse_args()
35
39
 
@@ -38,12 +42,14 @@ def cli():
38
42
  print("Can't use launcher and settings file")
39
43
  exit()
40
44
 
41
- from .gui import launcher
42
- return launcher.run_launcher()
45
+ from .launcher import run_launcher
46
+
47
+ return run_launcher()
43
48
  else:
44
- gui.run_settings_file(args.SETTINGS_FILE)
49
+ from .gui import run_settings_file
45
50
 
51
+ run_settings_file(args.SETTINGS_FILE)
46
52
 
47
53
 
48
- if __name__ == "__main__": # required because of threading
54
+ if __name__ == "__main__": # required because of threading
49
55
  cli()
pyforcedaq/_lib/clock.py CHANGED
@@ -1,6 +1,4 @@
1
- """A high-resolution monotonic timer based on LSL's local_clock() function.
2
- """
3
-
1
+ """A high-resolution monotonic timer based on LSL's local_clock() function."""
4
2
 
5
3
  from time import sleep
6
4
 
@@ -11,24 +9,24 @@ def local_clock_ms():
11
9
  """Returns the current time in milliseconds, based on LSL's local_clock()"""
12
10
  return local_clock() * 1000
13
11
 
14
- def wait_ms(waiting_time: int | float, looptime : int = 200) -> None:
15
- """Wait for a certain amount of milliseconds.
16
- """
12
+
13
+ def wait_ms(waiting_time: int | float, looptime: int = 200) -> None:
14
+ """Wait for a certain amount of milliseconds."""
17
15
  start = local_clock_ms()
18
16
  if waiting_time > looptime:
19
17
  sleep((waiting_time - looptime) / 1000)
20
18
  while local_clock_ms() < start + waiting_time:
21
19
  pass
22
20
 
23
- class StopWatch(object):#
21
+
22
+ class StopWatch(object): #
24
23
  """A simple timer"""
25
24
 
26
25
  def __init__(self):
27
26
  self._init_time = local_clock()
28
27
 
29
28
  def reset_stopwatch(self):
30
- """Reset the stopwatch time to zero.
31
- """
29
+ """Reset the stopwatch time to zero."""
32
30
  self._init_time = local_clock()
33
31
 
34
32
  @property
@@ -37,4 +35,4 @@ class StopWatch(object):#
37
35
 
38
36
  @property
39
37
  def time_ms(self) -> float:
40
- return self.time * 1000
38
+ return self.time * 1000
@@ -2,22 +2,20 @@
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
8
9
  import gzip
9
10
  import logging
10
- from fileinput import filename
11
11
  from io import TextIOWrapper
12
12
  from pathlib import Path
13
13
  from time import asctime, localtime, strftime
14
14
  from typing import List
15
15
 
16
- from icecream import ic
17
-
18
16
  from .. import __version__ as forceDAQVersion
19
- from . import _log
20
17
  from .clock import wait_ms
18
+ from .misc import set_logging
21
19
  from .process_priority_manager import ProcessPriorityManager
22
20
  from .sensor_process import SensorProcess
23
21
  from .settings import RecordingSettings, SensorSettings
@@ -32,19 +30,20 @@ from .types import (
32
30
  )
33
31
  from .udp_connection import UDPConnectionProcess
34
32
 
35
- _log.set_logging(data_directory="data", log_file="recording.log")
33
+ set_logging(data_directory="data", log_file="recording.log")
36
34
 
37
35
  NEWLINE = "\n"
38
36
 
37
+
39
38
  class DataRecorder(object):
40
39
  """handles multiple sensors and udp connection"""
41
40
 
42
- def __init__(self,
43
- recording_settings: RecordingSettings,
44
- force_sensor_settings:SensorSettings | List[SensorSettings],
45
- poll_udp_connection: bool = False):
46
-
47
-
41
+ def __init__(
42
+ self,
43
+ recording_settings: RecordingSettings,
44
+ force_sensor_settings: SensorSettings | List[SensorSettings],
45
+ poll_udp_connection: bool = False,
46
+ ):
48
47
  """queue_data will be saved
49
48
  see sensorprocess.__init__
50
49
 
@@ -58,15 +57,17 @@ class DataRecorder(object):
58
57
  self.recording_settings = recording_settings
59
58
 
60
59
  # create sensor processes
61
- self._force_sensor_processes =[]
60
+ self._force_sensor_processes = []
62
61
  event_trigger = []
63
62
  for fs in force_sensor_settings:
64
63
  if not isinstance(fs, SensorSettings):
65
64
  raise RuntimeError("Recorder needs a list of Force Sensor Settings!")
66
65
  else:
67
- fst = SensorProcess(sensor_settings = fs,
68
- recording_settings=recording_settings,
69
- 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
+ )
70
71
  fst.start()
71
72
  event_trigger.append(fst.event_trigger)
72
73
  self._force_sensor_processes.append(fst)
@@ -83,13 +84,15 @@ class DataRecorder(object):
83
84
  self._proc_manager.add_subprocess(self.udp)
84
85
  self._proc_manager.add_subprocess(self._force_sensor_processes)
85
86
  if self.recording_settings.priority is not None:
86
- level = PollingPriority.NORMAL
87
+ level = PollingPriority.NORMAL
87
88
  else:
88
89
  level = PollingPriority.get_priority(self.recording_settings.priority)
89
90
  self._proc_manager.set_subprocess_priorities(level=level, disable_gc=False)
90
91
 
91
- logging.info("Main process priority: %s", self._proc_manager.get_main_priority())
92
- #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()))
93
96
 
94
97
  self._is_recording = False
95
98
  self._file = None
@@ -121,8 +124,7 @@ class DataRecorder(object):
121
124
 
122
125
  @property
123
126
  def sensor_settings_list(self):
124
- return list(map(lambda x:x.sensor_settings,
125
- self._force_sensor_processes))
127
+ return list(map(lambda x: x.sensor_settings, self._force_sensor_processes))
126
128
 
127
129
  def quit(self) -> list | None:
128
130
  """Stop all recording processes, close data file and quit recording
@@ -155,28 +157,28 @@ class DataRecorder(object):
155
157
  buffer = []
156
158
  while True:
157
159
  try:
158
- data = self.udp.receive_queue.get_nowait() # type: ignore
160
+ data = self.udp.receive_queue.get_nowait() # type: ignore
159
161
  except AttributeError:
160
162
  # until queue empty or no udp connection
161
163
  break
162
164
  buffer.append(data)
163
- if len(buffer)>0:
165
+ if len(buffer) > 0:
164
166
  self._write_data(buffer)
165
167
  return buffer
166
168
 
167
- def _write_data(self, data_buffer: list,
168
- recording_screen=None,
169
- float_decimal_places: int = 4) -> None:
170
- """ 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
171
173
 
172
174
  ignores UDP remote control commands
173
175
  """
174
- #DOC output format
176
+ # DOC output format
175
177
 
176
- BLOCKSIZE = 10000 # for recording screen feedback only
178
+ BLOCKSIZE = 10000 # for recording screen feedback only
177
179
  write_forces = self.recording_settings.array_write_forces()
178
180
  write_trigger = self.recording_settings.array_write_trigger()
179
- write_deviceid = len(self.recording_settings.device_labels)>1
181
+ write_deviceid = len(self.recording_settings.device_labels) > 1
180
182
  float_format = "{0:." + str(float_decimal_places) + "f},"
181
183
  buffer_len = len(data_buffer)
182
184
  for c, d in enumerate(data_buffer):
@@ -185,9 +187,9 @@ class DataRecorder(object):
185
187
  line = f"{d.time}, {d.acquisition_delay},"
186
188
  if write_deviceid:
187
189
  line += f"{d.sensor_id},"
188
- for x in d.selected_forces(select=write_forces):
190
+ for x in d.forces[write_forces]:
189
191
  line += float_format.format(x)
190
- for x in d.selected_trigger(select=write_trigger):
192
+ for x in d.trigger[write_trigger]:
191
193
  if isinstance(x, int):
192
194
  line += f"{x},"
193
195
  else:
@@ -202,8 +204,10 @@ class DataRecorder(object):
202
204
 
203
205
  if recording_screen is not None and c % BLOCKSIZE == 0:
204
206
  recording_screen.stimulus(
205
- "Writing {0} of {1} blocks".format(c//BLOCKSIZE,
206
- buffer_len//BLOCKSIZE)).present()
207
+ "Saving {0} of {1} blocks".format(
208
+ c // BLOCKSIZE, buffer_len // BLOCKSIZE
209
+ )
210
+ ).present()
207
211
 
208
212
  def _file_write(self, s: str) -> None:
209
213
 
@@ -212,15 +216,15 @@ class DataRecorder(object):
212
216
  elif isinstance(self._file, TextIOWrapper):
213
217
  self._file.write(s)
214
218
 
215
-
216
- 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:
217
222
  """Set marker code in file
218
223
 
219
224
  DAQEvent will be timestamps and occur in the data output
220
225
 
221
226
  """
222
- self._daq_event.append(DAQEvents(time = time, code = code))
223
-
227
+ self._daq_event.append(DAQEvents(time=time, code=code))
224
228
 
225
229
  def start_recording(self, determine_bias: bool = False) -> None:
226
230
  """Start polling process and record
@@ -234,12 +238,20 @@ class DataRecorder(object):
234
238
  if determine_bias:
235
239
  self.determine_biases(n_samples=1000)
236
240
 
237
- if len(list(filter(lambda x:x.event_bias_is_available.is_set(),
238
- self._force_sensor_processes))) != len(self._force_sensor_processes):
239
- 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
+ )
240
252
 
241
253
  # start polling
242
- list(map(lambda x:x.start_polling(), self._force_sensor_processes))
254
+ list(map(lambda x: x.start_polling(), self._force_sensor_processes))
243
255
  self._is_recording = True
244
256
 
245
257
  def pause_recording(self, recording_screen=None) -> list:
@@ -254,14 +266,20 @@ class DataRecorder(object):
254
266
 
255
267
  data = []
256
268
  if recording_screen is not None:
257
- recording_screen.stimulus("writing data ...").present()
269
+ recording_screen.stimulus("").present()
258
270
 
259
- #pause polling
271
+ # pause polling
260
272
  for fsp in self._force_sensor_processes:
261
273
  fsp.pause_polling()
262
274
 
263
275
  wait_ms(500)
264
276
 
277
+ if recording_screen is not None:
278
+ if self.is_saving_data:
279
+ recording_screen.stimulus("saving data ...").present()
280
+ else:
281
+ recording_screen.stimulus("pause recording").present()
282
+
265
283
  # get data
266
284
  for fsp in self._force_sensor_processes:
267
285
  buffer = fsp.get_buffer()
@@ -298,11 +316,13 @@ class DataRecorder(object):
298
316
  for x in self._force_sensor_processes:
299
317
  x.event_bias_is_available.wait()
300
318
 
301
- def open_data_file(self,
302
- filename: str | Path,
303
- subdirectory: str = "data",
304
- varnames: bool = True,
305
- 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:
306
326
  """Create a data file
307
327
 
308
328
  Only if data file has been opened, data will be saved!
@@ -341,40 +361,50 @@ class DataRecorder(object):
341
361
  self.path_open_file = data_dir / filename
342
362
  if self.path_open_file.is_file():
343
363
  # print "data file already exists, adding counter"
344
- filename = Path(filename.stem + "_" + strftime("%m%d%H%M", localtime()) + \
345
- filename.suffix)
364
+ filename = Path(
365
+ filename.stem
366
+ + "_"
367
+ + strftime("%m%d%H%M", localtime())
368
+ + filename.suffix
369
+ )
346
370
  else:
347
371
  break
348
372
 
349
373
  if self.recording_settings.zip_data:
350
- self._file = gzip.open(self.path_open_file, 'w')
374
+ self._file = gzip.open(self.path_open_file, "w")
351
375
  else:
352
- self._file = open(self.path_open_file, 'w')
376
+ self._file = open(self.path_open_file, "w")
353
377
  print("Data file: {}".format(self.path_open_file))
354
378
 
355
- self._file_write(TAG_COMMENTS + "Recorded at {0} with pyForceDAQ {1}\n".format(
356
- 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
+ )
357
385
  logging.info("new file: {}".format(self.path_open_file))
358
386
 
359
387
  for s in self.sensor_settings_list:
360
388
  txt = f" Sensor: label={s.device_label}, cal-file={s.calibration_file}\n"
361
389
  self._file_write(TAG_COMMENTS + txt)
362
390
 
363
- if len(comment_line)>0:
391
+ if len(comment_line) > 0:
364
392
  self._file_write(TAG_COMMENTS + comment_line + "\n")
365
393
 
366
394
  if varnames:
367
395
  write_forces = self.recording_settings.array_write_forces()
368
396
  write_trigger = self.recording_settings.array_write_trigger()
369
- write_deviceid = len(self.recording_settings.device_labels)>1
397
+ write_deviceid = len(self.recording_settings.device_labels) > 1
370
398
  line = "time,delay,"
371
399
  if write_deviceid:
372
400
  line += "device_tag,"
373
401
  for x in range(6):
374
402
  if write_forces[x]:
375
403
  line += ForceSensorData.forces_names[x] + ","
376
- if write_trigger[0]: line += "trigger1,"
377
- if write_trigger[1]: line += "trigger2,"
404
+ if write_trigger[0]:
405
+ line += "trigger1,"
406
+ if write_trigger[1]:
407
+ line += "trigger2,"
378
408
  self._file_write(line[:-1] + NEWLINE)
379
409
 
380
410
  return self.path_open_file
pyforcedaq/_lib/lsl.py CHANGED
@@ -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:
pyforcedaq/_lib/misc.py CHANGED
@@ -1,12 +1,41 @@
1
+ import logging
2
+ import os
3
+ import sys
4
+ from pathlib import Path
5
+
6
+ from ..constants import SETTINGS_FILE_EXTENSION
1
7
  from .clock import local_clock_ms
2
8
 
3
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
26
+
27
+
28
+ def list_settings_files():
29
+ """Returns a list of all settings files in the current directory."""
30
+ return [f.name for f in Path(".").glob(f"*{SETTINGS_FILE_EXTENSION}")]
31
+
32
+
4
33
  def N2g(N):
5
- kg = N/9.81
6
- return kg*1000
34
+ kg = N / 9.81
35
+ return kg * 1000
7
36
 
8
- class MinMaxDetector(object):
9
37
 
38
+ class MinMaxDetector(object):
10
39
  def __init__(self, start_value, duration_ms):
11
40
  self._minmax = [start_value, start_value]
12
41
  self._duration_ms = duration_ms
@@ -25,7 +54,7 @@ class MinMaxDetector(object):
25
54
  elif value < self._minmax[0]:
26
55
  self._minmax[0] = value
27
56
 
28
- elif self._minmax[0] != value: # level change just occurred
57
+ elif self._minmax[0] != value: # level change just occurred
29
58
  self._level_change_time = local_clock_ms()
30
59
  return self.process(value)
31
60
 
@@ -34,8 +63,10 @@ class MinMaxDetector(object):
34
63
  @property
35
64
  def is_sampling_for_minmax(self):
36
65
  """true true if currently sampling for minmax"""
37
- return (self._level_change_time is not None) and \
38
- (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
+
39
70
 
40
71
  # def find_calibration_file(calibration_folder: str, device_label: str,
41
72
  # calibration_suffix=".cal") -> str:
@@ -63,7 +94,8 @@ class MinMaxDetector(object):
63
94
  # print("No calibration file found for sensor '{0}'.".format(device_label))
64
95
  # exit()
65
96
 
66
- #Sensor History with moving average filtering and distance, velocity
97
+
98
+ # Sensor History with moving average filtering and distance, velocity
67
99
  class SensorHistory(object):
68
100
  """The Sensory History keeps track of the last n recorded sample and
69
101
  calculates online the moving average (running mean).
@@ -101,10 +133,12 @@ class SensorHistory(object):
101
133
  self.moving_average = self.calc_history_average()
102
134
  else:
103
135
  self._correction_cnt += 1
104
- self.moving_average = list(map(
105
- lambda x: x[0] + (float(x[1] - x[2]) / len(self.history)),
106
- zip(self.moving_average, values, pop)))
107
-
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
+ )
108
142
 
109
143
  def calc_history_average(self):
110
144
  """Calculate history averages for all sensor parameter.
@@ -120,7 +154,6 @@ class SensorHistory(object):
120
154
  s = list(map(lambda x: x[0] + x[1], zip(s, t)))
121
155
  return list(map(lambda x: x / len(self.history), s))
122
156
 
123
-
124
157
  @property
125
158
  def history_size(self):
126
159
  return len(self.history)
@@ -132,4 +165,3 @@ class SensorHistory(object):
132
165
  @property
133
166
  def previous_moving_average(self):
134
167
  return self._previous_moving_average
135
-
@@ -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()))