pyForceDAQ 2.0.5.dev3__tar.gz → 2.0.5.dev4__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 (35) hide show
  1. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/PKG-INFO +1 -1
  2. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/pyproject.toml +1 -1
  3. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/_lib/settings.py +3 -2
  4. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/constants.py +3 -3
  5. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/gui/_gui_status.py +7 -3
  6. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/gui/_layout.py +18 -9
  7. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/gui/_run.py +14 -13
  8. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/launcher.py +8 -1
  9. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/__init__.py +0 -0
  10. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/__main__.py +0 -0
  11. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/_lib/__init__.py +0 -0
  12. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/_lib/clock.py +0 -0
  13. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/_lib/data_recorder.py +0 -0
  14. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/_lib/file_writer.py +0 -0
  15. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/_lib/lsl.py +0 -0
  16. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/_lib/misc.py +0 -0
  17. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/_lib/process_priority_manager.py +0 -0
  18. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/_lib/sensor.py +0 -0
  19. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/_lib/sensor_process.py +0 -0
  20. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/_lib/types.py +0 -0
  21. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/_lib/udp_connection.py +0 -0
  22. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/daq/__init__.py +0 -0
  23. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/daq/_pyATIDAQ.py +0 -0
  24. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/daq/calibration_dll.py +0 -0
  25. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/daq/calibration_iaftt.py +0 -0
  26. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/daq/read_daq_mock_sensor.py +0 -0
  27. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/daq/read_daq_nidaqmx.py +0 -0
  28. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/daq/read_daq_pydaqmx.py +0 -0
  29. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/force.py +0 -0
  30. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/gui/__init__.py +0 -0
  31. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/gui/_level_indicator.py +0 -0
  32. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/gui/_pg_surface.py +0 -0
  33. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/gui/_plotter.py +0 -0
  34. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/src/pyforcedaq/gui/_scaling.py +0 -0
  35. {pyforcedaq-2.0.5.dev3 → pyforcedaq-2.0.5.dev4}/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.5.dev3
3
+ Version: 2.0.5.dev4
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.5-dev3"
3
+ version = "2.0.5-dev4"
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" },
@@ -7,7 +7,7 @@ from typing import Any, Dict, List, Tuple
7
7
 
8
8
  import tomlkit
9
9
 
10
- from ..constants import CALIBRATION_FOLDER, DATA_FOLDER
10
+ from ..constants import CALIBRATION_FOLDER, DATA_FOLDER, SETTINGS_FILE_EXTENSION
11
11
 
12
12
 
13
13
  class DAQConfiguration(object):
@@ -185,11 +185,12 @@ class AppSettings(object):
185
185
  self.recording_section = "Recording"
186
186
 
187
187
  self.filepath = Path(filename)
188
+ self.filepath = self.filepath.with_suffix(SETTINGS_FILE_EXTENSION)
188
189
  if os.path.isfile(self.filepath):
189
190
  self.load()
190
191
  else:
191
192
  self.save() # defaults
192
-
193
+ print(f"WARNING: {self.filepath} not found, creating new settings file with defaults")
193
194
  self.output_filename = ""
194
195
 
195
196
  def _asdict(self):
@@ -5,8 +5,8 @@ MOCK_SENSOR = 9
5
5
  DAQ_TYPE = NIDAQMX # default to nidaqmx, use constants.MOCK_SENSOR for mock sensor, constants.PYDAQMX for PyDAQmx
6
6
  USE_AIFTT = True # <-- change to False to use ATI DLL for calibration conversion, otherwise use atiiaftt
7
7
 
8
- SETTINGS_FILE_EXTENSION = ".settings.toml"
9
- DEFAULT_SETTINGS_FILE = "pyForceDAQ" + SETTINGS_FILE_EXTENSION
8
+ SETTINGS_FILE_EXTENSION = ".toml"
9
+ DEFAULT_SETTINGS_FILE = "pyForceDAQ.settings" + SETTINGS_FILE_EXTENSION
10
10
  DEFAULT_OUTPUT_FILENAME = None
11
- CALIBRATION_FOLDER = "calibration"
11
+ CALIBRATION_FOLDER = "."
12
12
  DATA_FOLDER = "data"
@@ -2,7 +2,7 @@ __author__ = "Oliver Lindemann"
2
2
 
3
3
 
4
4
  from time import sleep
5
- from typing import Tuple
5
+ from typing import List, Tuple
6
6
 
7
7
  from expyriment import io, misc
8
8
 
@@ -27,16 +27,19 @@ def _text2number_array(txt):
27
27
 
28
28
 
29
29
  class GUIStatus(object):
30
+
30
31
  def __init__(
31
32
  self,
32
33
  gui_settings: GUISettings,
33
34
  recorder: DataRecorder,
34
35
  screen_size: Tuple[int, int],
36
+ top_left_info:List[str] = [""]
35
37
  ):
36
38
 
37
39
  self.gs = gui_settings
38
40
  self.recorder = recorder
39
41
  self.screen_size = screen_size
42
+ self.top_left_info = top_left_info
40
43
 
41
44
  self.scaling_plotter = Scaling(
42
45
  min=gui_settings.data_min_max[0],
@@ -133,8 +136,9 @@ class GUIStatus(object):
133
136
 
134
137
  return RecordingScreen(
135
138
  window_size=self.screen_size,
136
- txt_top_center=info_file,
137
- txt_top_left=info_recording,
139
+ txt_top_left=self.top_left_info,
140
+ txt_top_right=info_file,
141
+ txt_top_center=info_recording,
138
142
  text_colour=txt_col,
139
143
  no_pause_option = not self.recorder.has_file_writer
140
144
  )
@@ -2,6 +2,8 @@ __author__ = "Oliver Lindemann"
2
2
 
3
3
  # helper functions
4
4
  import os
5
+ from copy import copy
6
+ from typing import List
5
7
 
6
8
  import pygame
7
9
  from expyriment import stimuli
@@ -31,6 +33,7 @@ def get_pygame_rect(stimulus, screen_size):
31
33
  return pygame.Rect(rect_pos, stim_size)
32
34
 
33
35
 
36
+
34
37
  def logo_text_line(text):
35
38
  blank = stimuli.Canvas(size=(600, 400))
36
39
  logo = stimuli.Picture(
@@ -56,7 +59,11 @@ def make_text_line(text, position, text_size, text_colour):
56
59
 
57
60
  class RecordingScreen(object):
58
61
 
59
- def __init__(self, window_size, txt_top_center, txt_top_left, text_colour,
62
+ def __init__(self, window_size,
63
+ txt_top_left: List[str],
64
+ txt_top_center:str,
65
+ txt_top_right:str,
66
+ text_colour,
60
67
  no_pause_option:bool = False):
61
68
  # NOTE: Expyriment has to be intialized
62
69
  margin = 30
@@ -67,12 +74,14 @@ class RecordingScreen(object):
67
74
 
68
75
  self.text_colour = text_colour
69
76
  self.elements = []
70
- self.add_text_line_left(
71
- f"{forceDAQVersion}",
72
- [self.left, self.top],
73
- text_size=15,
74
- text_colour=None
75
- )
77
+
78
+ txt_list = copy(txt_top_left)
79
+ txt_list.insert(0, f"Version {forceDAQVersion}")
80
+ for cnt, txt in enumerate(txt_list):
81
+ self.add_text_line_left(
82
+ txt,
83
+ [self.left, self.top - cnt * 20],
84
+ text_size=15,text_colour=None)
76
85
  col = expy_constants.C_GREY
77
86
  if not no_pause_option:
78
87
  self.add_text_line_left("P: pause/unpause saving", [self.left, self.bottom + 20], text_colour=col)
@@ -88,8 +97,8 @@ class RecordingScreen(object):
88
97
  )
89
98
  self.add_text_line_right("Q: quit recording", [self.right, self.bottom], text_colour=col)
90
99
 
91
- self.add_text_line_right(txt_top_center, [self.right, self.top], text_size=15)
92
- self.add_text_line_centered(txt_top_left, [0, self.top], text_size=15)
100
+ self.add_text_line_right(txt_top_right, [self.right, self.top], text_size=15)
101
+ self.add_text_line_centered(txt_top_center, [0, self.top], text_size=15)
93
102
 
94
103
  def add_text_line_centered(
95
104
  self, text, position, text_size=12, text_colour=None
@@ -19,7 +19,7 @@ from .._lib.clock import wait_ms
19
19
  from .._lib.data_recorder import DataRecorder
20
20
  from .._lib.sensor_process import SensorProcess
21
21
  from .._lib.settings import AppSettings, GUISettings, SensorSettings
22
- from ..constants import DEFAULT_OUTPUT_FILENAME, DEFAULT_SETTINGS_FILE
22
+ from ..constants import DEFAULT_OUTPUT_FILENAME
23
23
  from ._gui_status import GUIStatus
24
24
  from ._layout import colours, get_pygame_rect, logo_text_line, make_text_line
25
25
  from ._level_indicator import level_indicator
@@ -33,7 +33,7 @@ CHANGED_LEVEL = COMMAND_STR + b"xCL1"
33
33
  CHANGED_LEVEL2 = COMMAND_STR + b"xCL2"
34
34
 
35
35
 
36
- def _main_loop(exp, recorder: DataRecorder, gs: GUISettings):
36
+ def _main_loop(exp, recorder: DataRecorder, gs: GUISettings, info_strings: List[str]):
37
37
  """udp command:
38
38
  "start", "pause", "stop"
39
39
  "thresholds = [x,...]" : start level detection for Fz parameter and set threshold
@@ -44,7 +44,8 @@ def _main_loop(exp, recorder: DataRecorder, gs: GUISettings):
44
44
  plotter_width = 900
45
45
  plotter_position = (0, -30)
46
46
 
47
- s = GUIStatus(gui_settings=gs, recorder=recorder, screen_size=exp.screen.size)
47
+ s = GUIStatus(gui_settings=gs, recorder=recorder, screen_size=exp.screen.size,
48
+ top_left_info=info_strings)
48
49
 
49
50
  # plotter
50
51
  plotter_thread = None
@@ -295,14 +296,15 @@ def _main_loop(exp, recorder: DataRecorder, gs: GUISettings):
295
296
  update_rects.append(get_pygame_rect(txt, exp.screen.size))
296
297
 
297
298
  # counter
298
- pos = (-230, 250)
299
+ pos = (-270, 240)
300
+
299
301
  stimuli.Canvas(
300
- position=pos, size=(400, 50), colour=misc.constants.C_BLACK
302
+ position=pos, size=(400, 20), colour=misc.constants.C_BLACK
301
303
  ).present(update=False, clear=False)
302
304
 
303
305
  txt = stimuli.TextBox(
304
306
  position=pos,
305
- size=(400, 50),
307
+ size=(400, 20),
306
308
  # background_colour=(30,30,30),
307
309
  text_size=15,
308
310
  text="n samples (total): {0}".format(
@@ -314,7 +316,9 @@ def _main_loop(exp, recorder: DataRecorder, gs: GUISettings):
314
316
  txt.present(update=False, clear=False)
315
317
  update_rects.append(get_pygame_rect(txt, exp.screen.size))
316
318
 
317
- # Infos
319
+ #FIXME Threshold levels down work
320
+
321
+ # Sensor info
318
322
  pos = (200, 250)
319
323
  tmp = stimuli.Canvas(
320
324
  position=pos, size=(400, 50), colour=misc.constants.C_BLACK
@@ -329,6 +333,7 @@ def _main_loop(exp, recorder: DataRecorder, gs: GUISettings):
329
333
  ]
330
334
  else:
331
335
  tmp = s.thresholds.get_level(s.level_detection_parameter_average(0))
336
+
332
337
  txt = stimuli.TextBox(
333
338
  position=pos,
334
339
  size=(400, 50),
@@ -387,11 +392,6 @@ def _main_loop(exp, recorder: DataRecorder, gs: GUISettings):
387
392
 
388
393
 
389
394
  def run_settings_file(settings_file: str | Path = ""):
390
-
391
- if isinstance(settings_file, str) and len(settings_file) < 2:
392
- # load default settings file if not specified
393
- settings_file = DEFAULT_SETTINGS_FILE
394
-
395
395
  return run(AppSettings(settings_file))
396
396
 
397
397
 
@@ -456,7 +456,8 @@ def run(settings: AppSettings):
456
456
 
457
457
  sleep(show_logo_time)
458
458
 
459
- _main_loop(exp, recorder=recorder, gs=settings.gui)
459
+ _main_loop(exp, recorder=recorder, gs=settings.gui,
460
+ info_strings=[f"{settings.filepath.name}"])
460
461
 
461
462
  recorder.quit()
462
463
  control.end()
@@ -1,3 +1,4 @@
1
+ import glob
1
2
  from os import path
2
3
  from pathlib import Path
3
4
  from typing import List
@@ -139,7 +140,13 @@ def load_settings_file(settings_file: str | Path) -> AppSettings:
139
140
 
140
141
  def run_launcher():
141
142
  _sg.theme("DarkBlue14") # please make your windows colorful
142
- settings = load_settings_file(constants.DEFAULT_SETTINGS_FILE)
143
+
144
+ toml_files = glob.glob("*.toml")
145
+ if len(toml_files) == 0:
146
+ settings_file = constants.DEFAULT_SETTINGS_FILE
147
+ else:
148
+ settings_file = toml_files[0]
149
+ settings = load_settings_file(settings_file)
143
150
 
144
151
  while True:
145
152
  event, values, settings = _windows_run(settings)