bapsf-motion 0.2.2__tar.gz → 0.2.3__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 (153) hide show
  1. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/PKG-INFO +1 -1
  2. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/gui/configure/configure_.py +1 -1
  3. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/gui/configure/motion_builder_overlay.py +8 -41
  4. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/gui/configure/motion_group_widget.py +142 -4
  5. bapsf_motion-0.2.3/bapsf_motion/gui/configure/motion_space_display.py +350 -0
  6. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/motion_builder/core.py +18 -0
  7. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion.egg-info/PKG-INFO +1 -1
  8. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion.egg-info/SOURCES.txt +1 -0
  9. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/.gitattributes +0 -0
  10. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/.github/dependabot.yml +0 -0
  11. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/.github/workflows/python-publish.yml +0 -0
  12. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/.github/workflows/test.yml +0 -0
  13. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/.gitignore +0 -0
  14. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/.readthedocs.yml +0 -0
  15. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/README.md +0 -0
  16. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/__init__.py +0 -0
  17. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/actors/__init__.py +0 -0
  18. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/actors/axis_.py +0 -0
  19. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/actors/base.py +0 -0
  20. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/actors/demos/__init__.py +0 -0
  21. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/actors/demos/drive_timed_run_1D.py +0 -0
  22. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/actors/demos/drive_timed_run_2D.py +0 -0
  23. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/actors/demos/mgroup_timed_run_2D.py +0 -0
  24. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/actors/drive_.py +0 -0
  25. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/actors/manager_.py +0 -0
  26. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/actors/motion_group_.py +0 -0
  27. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/actors/motor_.py +0 -0
  28. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/actors/tests/__init__.py +0 -0
  29. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/examples/20240627_2D_test_setup.toml +0 -0
  30. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/examples/20241004_2D_test_setup.toml +0 -0
  31. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/examples/bapsf_motion.toml +0 -0
  32. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/examples/benchtop_motion_group.toml +0 -0
  33. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/examples/benchtop_run.toml +0 -0
  34. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/examples/mg_1d.toml +0 -0
  35. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/examples/mg_2d_strb_test_setup.toml +0 -0
  36. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/examples/motion_group.toml +0 -0
  37. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/gui/__init__.py +0 -0
  38. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/gui/configure/__init__.py +0 -0
  39. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/gui/configure/bases.py +0 -0
  40. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/gui/configure/configure.qss +0 -0
  41. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/gui/configure/drive_overlay.py +0 -0
  42. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/gui/configure/helpers.py +0 -0
  43. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/gui/configure/transform_overlay.py +0 -0
  44. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/gui/helpers.py +0 -0
  45. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/gui/motor.py +0 -0
  46. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/gui/widgets/__init__.py +0 -0
  47. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/gui/widgets/buttons.py +0 -0
  48. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/gui/widgets/logging.py +0 -0
  49. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/gui/widgets/misc.py +0 -0
  50. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/motion_builder/__init__.py +0 -0
  51. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/motion_builder/exclusions/__init__.py +0 -0
  52. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/motion_builder/exclusions/base.py +0 -0
  53. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/motion_builder/exclusions/circular.py +0 -0
  54. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/motion_builder/exclusions/divider.py +0 -0
  55. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/motion_builder/exclusions/helpers.py +0 -0
  56. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/motion_builder/exclusions/lapd.py +0 -0
  57. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/motion_builder/exclusions/shadow.py +0 -0
  58. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/motion_builder/item.py +0 -0
  59. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/motion_builder/layers/__init__.py +0 -0
  60. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/motion_builder/layers/base.py +0 -0
  61. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/motion_builder/layers/helpers.py +0 -0
  62. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/motion_builder/layers/regular_grid.py +0 -0
  63. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/transform/__init__.py +0 -0
  64. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/transform/base.py +0 -0
  65. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/transform/helpers.py +0 -0
  66. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/transform/identity.py +0 -0
  67. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/transform/lapd.py +0 -0
  68. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/transform/lapd_droop.py +0 -0
  69. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/utils/__init__.py +0 -0
  70. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/utils/exceptions.py +0 -0
  71. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/utils/toml.py +0 -0
  72. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion/utils/units_.py +0 -0
  73. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion.egg-info/dependency_links.txt +0 -0
  74. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion.egg-info/requires.txt +0 -0
  75. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/bapsf_motion.egg-info/top_level.txt +0 -0
  76. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/Makefile +0 -0
  77. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/_static/BaPSF_Logo_Color_RGB.png +0 -0
  78. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/_static/BaPSF_Logo_Color_yellow_background_RGB_32px.ico +0 -0
  79. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/_static/BaPSF_Logo_White_RGB.png +0 -0
  80. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/_static/BaPSF_Logo_White_RGB_150px.png +0 -0
  81. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/_static/css/overrides.css +0 -0
  82. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.actors.axis_.rst +0 -0
  83. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.actors.base.rst +0 -0
  84. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.actors.drive_.rst +0 -0
  85. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.actors.manager_.rst +0 -0
  86. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.actors.motion_group_.rst +0 -0
  87. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.actors.motor_.rst +0 -0
  88. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.actors.rst +0 -0
  89. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.gui.configure.rst +0 -0
  90. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.gui.motor.rst +0 -0
  91. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.gui.rst +0 -0
  92. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.gui.widgets.buttons.rst +0 -0
  93. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.gui.widgets.logging.rst +0 -0
  94. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.gui.widgets.misc.rst +0 -0
  95. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.gui.widgets.rst +0 -0
  96. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.motion_builder.core.rst +0 -0
  97. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.motion_builder.exclusions.base.rst +0 -0
  98. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.motion_builder.exclusions.circular.rst +0 -0
  99. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.motion_builder.exclusions.divider.rst +0 -0
  100. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.motion_builder.exclusions.helpers.rst +0 -0
  101. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.motion_builder.exclusions.lapd.rst +0 -0
  102. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.motion_builder.exclusions.rst +0 -0
  103. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.motion_builder.exclusions.shadow.rst +0 -0
  104. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.motion_builder.item.rst +0 -0
  105. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.motion_builder.layers.base.rst +0 -0
  106. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.motion_builder.layers.helpers.rst +0 -0
  107. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.motion_builder.layers.regular_grid.rst +0 -0
  108. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.motion_builder.layers.rst +0 -0
  109. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.motion_builder.rst +0 -0
  110. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.rst +0 -0
  111. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.transform.base.rst +0 -0
  112. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.transform.helpers.rst +0 -0
  113. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.transform.identity.rst +0 -0
  114. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.transform.lapd.rst +0 -0
  115. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.transform.lapd_droop.rst +0 -0
  116. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.transform.rst +0 -0
  117. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.utils.exceptions.rst +0 -0
  118. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.utils.rst +0 -0
  119. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.utils.toml.rst +0 -0
  120. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/api_static/bapsf_motion.utils.units_.rst +0 -0
  121. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/available_transformers.rst +0 -0
  122. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/bibliography.bib +0 -0
  123. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/bibliography.rst +0 -0
  124. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/common_links.rst +0 -0
  125. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/conf.py +0 -0
  126. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/glossary.rst +0 -0
  127. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/index.rst +0 -0
  128. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/make.bat +0 -0
  129. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/motion_builder/index.rst +0 -0
  130. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/notebooks/motion_list/CircularExclusion.ipynb +0 -0
  131. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/notebooks/motion_list/LaPDXYExclusion.ipynb +0 -0
  132. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/notebooks/motion_list/Shadow2DExclusion.ipynb +0 -0
  133. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/notebooks/motion_list/motionlist.ipynb +0 -0
  134. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/notebooks/prototypes/README.md +0 -0
  135. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/notebooks/transform/identity_transform.ipynb +0 -0
  136. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/notebooks/transform/lapd_xy_droop_correction.ipynb +0 -0
  137. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/notebooks/transform/lapd_xy_transform.ipynb +0 -0
  138. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/notebooks_.rst +0 -0
  139. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/robots.txt +0 -0
  140. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/docs/toml/index.rst +0 -0
  141. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/pyproject.toml +0 -0
  142. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/requirements/build.txt +0 -0
  143. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/requirements/docs.txt +0 -0
  144. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/requirements/extras.txt +0 -0
  145. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/requirements/gui.txt +0 -0
  146. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/requirements/install.txt +0 -0
  147. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/requirements/readthedocs.txt +0 -0
  148. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/requirements/tests.txt +0 -0
  149. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/requirements.txt +0 -0
  150. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/resources/README.md +0 -0
  151. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/resources/Remote module installation guide.pdf +0 -0
  152. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/setup.cfg +0 -0
  153. {bapsf_motion-0.2.2 → bapsf_motion-0.2.3}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: bapsf_motion
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: Package for controlling motion devices in a BaPSF DAQ system
5
5
  Author: Basic Plasma Science Facility
6
6
  Keywords: plasma physics,plasma,science,bapsf,motion
@@ -358,7 +358,7 @@ class ConfigureGUI(QMainWindow):
358
358
  return self._logging_config_dict
359
359
 
360
360
  def replace_rm(self, config):
361
- if isinstance(self.rm, RunManager) and not self.rm.terminated:
361
+ if isinstance(self.rm, RunManager):
362
362
  self.rm.terminate()
363
363
 
364
364
  self.logger.info(f"Replacing the run manager with new config: {config}.")
@@ -8,9 +8,8 @@ import matplotlib as mpl
8
8
  import re
9
9
 
10
10
  from PySide6.QtCore import Qt, Slot, QSize
11
- from PySide6.QtGui import QIcon, QDoubleValidator
11
+ from PySide6.QtGui import QDoubleValidator
12
12
  from PySide6.QtWidgets import (
13
- QFrame,
14
13
  QHBoxLayout,
15
14
  QLabel,
16
15
  QGridLayout,
@@ -29,6 +28,7 @@ import qtawesome as qta
29
28
  from bapsf_motion.actors import MotionGroup
30
29
  from bapsf_motion.gui.configure import motion_group_widget as mgw
31
30
  from bapsf_motion.gui.configure.bases import _ConfigOverlay
31
+ from bapsf_motion.gui.configure.motion_space_display import MotionSpaceDisplay
32
32
  from bapsf_motion.gui.widgets import (
33
33
  DiscardButton,
34
34
  DoneButton,
@@ -107,24 +107,9 @@ class MotionBuilderConfigOverlay(_ConfigOverlay):
107
107
  self.edit_ex_btn.setEnabled(False)
108
108
 
109
109
  # SET UP PLOT WIDGET
110
- self.mpl_canvas = FigureCanvas()
111
- self.mpl_canvas.setParent(self)
112
- self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)
113
-
114
- self.mpl_canvas_frame = QFrame(parent=self)
115
- self.mpl_canvas_frame.setObjectName("mpl_canvas_frame")
116
- self.mpl_canvas_frame.setStyleSheet(
117
- """
118
- QFrame#mpl_canvas_frame {
119
- border: 2px solid rgb(125, 125, 125);
120
- border-radius: 5px;
121
- padding: 0px;
122
- margin: 0px;
123
- }
124
- """
125
- )
126
- self.mpl_canvas_frame.setLayout(QVBoxLayout())
127
- self.mpl_canvas_frame.layout().addWidget(self.mpl_canvas)
110
+ self.mpl_canvas = MotionSpaceDisplay(parent=self)
111
+ if isinstance(self.mg, MotionGroup) and isinstance(self.mg.mb, MotionBuilder):
112
+ self.mpl_canvas.link_motion_builder(self.mg.mb)
128
113
 
129
114
  # SET UP INPUT WIDGETS (those in self._params_widget)
130
115
 
@@ -304,7 +289,7 @@ class MotionBuilderConfigOverlay(_ConfigOverlay):
304
289
 
305
290
  layout = QVBoxLayout(_widget)
306
291
  layout.setContentsMargins(0, 0, 0, 0)
307
- layout.addWidget(self.mpl_canvas_frame)
292
+ layout.addWidget(self.mpl_canvas)
308
293
  layout.addWidget(self._define_params_widget())
309
294
  layout.addStretch(1)
310
295
 
@@ -1142,26 +1127,7 @@ class MotionBuilderConfigOverlay(_ConfigOverlay):
1142
1127
  self.remove_ly_btn.setEnabled(enable)
1143
1128
 
1144
1129
  def update_canvas(self):
1145
- self.logger.info("Redrawing plot...")
1146
- self.logger.info(f"MB config = {self.mb.config}")
1147
-
1148
- self.mpl_canvas.figure.clear()
1149
- ax = self.mpl_canvas.figure.gca()
1150
- xdim, ydim = self.mb.mspace_dims
1151
- self.mb.mask.plot(x=xdim, y=ydim, ax=ax)
1152
-
1153
- pts = self.mb.motion_list
1154
- if pts is not None:
1155
- ax.scatter(
1156
- x=pts[..., 0],
1157
- y=pts[..., 1],
1158
- linewidth=1,
1159
- s=2 ** 2,
1160
- facecolors="deepskyblue",
1161
- edgecolors="black",
1162
- )
1163
-
1164
- self.mpl_canvas.draw()
1130
+ self.mpl_canvas.update_canvas()
1165
1131
 
1166
1132
  def update_exclusion_list_box(self):
1167
1133
  self.logger.info("Updating Exclusion List Box")
@@ -1301,6 +1267,7 @@ class MotionBuilderConfigOverlay(_ConfigOverlay):
1301
1267
  self.logger.info(f"layer looks like : {layers}")
1302
1268
 
1303
1269
  self._mb = MotionBuilder(space=space, exclusions=exclusions, layers=layers)
1270
+ self.mpl_canvas.link_motion_builder(self._mb)
1304
1271
  self.configChanged.emit()
1305
1272
  return self._mb
1306
1273
 
@@ -14,7 +14,7 @@ import pygame # noqa
14
14
 
15
15
  from abc import abstractmethod
16
16
  from PySide6.QtCore import Qt, Signal, Slot, QRunnable, QSize, QThreadPool, QObject
17
- from PySide6.QtGui import QDoubleValidator, QFont, QIcon
17
+ from PySide6.QtGui import QDoubleValidator, QFont
18
18
  from PySide6.QtWidgets import (
19
19
  QCheckBox,
20
20
  QComboBox,
@@ -41,6 +41,7 @@ from bapsf_motion.gui.configure.bases import _ConfigOverlay, _OverlayWidget
41
41
  from bapsf_motion.gui.configure.drive_overlay import DriveConfigOverlay
42
42
  from bapsf_motion.gui.configure.helpers import gui_logger
43
43
  from bapsf_motion.gui.configure.motion_builder_overlay import MotionBuilderConfigOverlay
44
+ from bapsf_motion.gui.configure.motion_space_display import MotionSpaceDisplay
44
45
  from bapsf_motion.gui.configure.transform_overlay import TransformConfigOverlay
45
46
  from bapsf_motion.gui.widgets import (
46
47
  DiscardButton,
@@ -288,6 +289,7 @@ class AxisControlWidget(QWidget):
288
289
  movementStarted = Signal(int)
289
290
  movementStopped = Signal(int)
290
291
  axisStatusChanged = Signal()
292
+ targetPositionChanged = Signal(float)
291
293
 
292
294
  def __init__(
293
295
  self,
@@ -392,6 +394,9 @@ class AxisControlWidget(QWidget):
392
394
  self.jog_backward_btn.clicked.connect(self.jog_backward)
393
395
  self.zero_btn.clicked.connect(self._zero_axis)
394
396
  self.jog_delta_label.editingFinished.connect(self._validate_jog_value)
397
+ self.target_position_label.editingFinished.connect(
398
+ self._validate_target_position_value
399
+ )
395
400
 
396
401
  def _define_layout(self):
397
402
  layout = QVBoxLayout()
@@ -571,6 +576,14 @@ class AxisControlWidget(QWidget):
571
576
  val = abs(val)
572
577
  self.jog_delta_label.setText(f"{val:.2f}")
573
578
 
579
+ def _validate_target_position_value(self):
580
+ try:
581
+ val = self.target_position
582
+ except ValueError:
583
+ val = None
584
+
585
+ self.targetPositionChanged.emit(val)
586
+
574
587
  def _zero_axis(self):
575
588
  self.logger.info(f"Setting zero of axis {self.axis_index}")
576
589
  self.mg.set_zero(axis=self.axis_index)
@@ -655,6 +668,7 @@ class DriveBaseController(QWidget):
655
668
  movementStopped = Signal()
656
669
  moveTo = Signal(list)
657
670
  zeroDrive = Signal()
671
+ targetPositionChanged = Signal(list)
658
672
 
659
673
  def __init__(self, axis_display_mode="interactive", parent=None):
660
674
  # axis_display_mode == "interactive" or "readonly"
@@ -696,6 +710,9 @@ class DriveBaseController(QWidget):
696
710
  self.movementStarted.connect(self.disable_motion_buttons)
697
711
  self.movementStopped.connect(self.enable_motion_buttons)
698
712
 
713
+ for acw in self._axis_control_widgets:
714
+ acw.targetPositionChanged.connect(self._target_position_changed)
715
+
699
716
  @abstractmethod
700
717
  def _define_layout(self) -> QLayout:
701
718
  ...
@@ -712,6 +729,43 @@ class DriveBaseController(QWidget):
712
729
  def mspace_drive_polarity(self):
713
730
  return self._mspace_drive_polarity
714
731
 
732
+ @property
733
+ def position(self) -> List[float]:
734
+ position = []
735
+ for acw in self._axis_control_widgets:
736
+ if acw.isHidden():
737
+ continue
738
+
739
+ position.append(acw.position.value)
740
+
741
+ return position
742
+
743
+ @property
744
+ def target_position(self) -> Union[List[float], None]:
745
+ target_position = []
746
+ for acw in self._axis_control_widgets:
747
+ if acw.isHidden():
748
+ continue
749
+
750
+ target_position.append(acw.target_position)
751
+
752
+ if not bool(target_position):
753
+ # no values in target position
754
+ return None
755
+
756
+ if any(pos is None for pos in target_position):
757
+ # some target positions are not valid
758
+ return None
759
+
760
+ return target_position
761
+
762
+ def _target_position_changed(self, position):
763
+ self.logger.info(f"DBC target position changed {self.target_position}")
764
+ tpos = self.target_position
765
+ if tpos is None:
766
+ tpos = []
767
+ self.targetPositionChanged.emit(tpos)
768
+
715
769
  def link_motion_group(self, mg: MotionGroup):
716
770
  if not isinstance(mg, MotionGroup):
717
771
  self.logger.warning(
@@ -935,6 +989,22 @@ class DriveDesktopController(DriveBaseController):
935
989
 
936
990
  self.moveTo.emit(target_pos)
937
991
 
992
+ def set_target_position(self, target_position: List[float]):
993
+ npos = len(target_position)
994
+ naxes = self.mg.drive.naxes
995
+
996
+ if npos != naxes:
997
+ self.logger.warning(
998
+ f"Received target position {target_position} does NOT "
999
+ f"have the same dimensionality as the drive "
1000
+ f"({naxes})."
1001
+ )
1002
+ return
1003
+
1004
+ for ii, pos in enumerate(target_position):
1005
+ acw = self._axis_control_widgets[ii]
1006
+ acw.target_position_label.setText(f"{pos}")
1007
+
938
1008
  def disable_motion_buttons(self):
939
1009
  self.move_to_btn.setEnabled(False)
940
1010
  self.zero_all_btn.setEnabled(False)
@@ -1248,6 +1318,8 @@ class DriveGameController(DriveBaseController):
1248
1318
  class DriveControlWidget(QWidget):
1249
1319
  movementStarted = Signal()
1250
1320
  movementStopped = Signal()
1321
+ driveStatusChanged = Signal()
1322
+ targetPositionChanged = Signal(list)
1251
1323
 
1252
1324
  def __init__(self, parent=None):
1253
1325
  super().__init__(parent)
@@ -1312,6 +1384,12 @@ class DriveControlWidget(QWidget):
1312
1384
 
1313
1385
  self.desktop_controller_widget.zeroDrive.connect(self._zero_drive)
1314
1386
  self.desktop_controller_widget.moveTo.connect(self._move_to)
1387
+ self.desktop_controller_widget.targetPositionChanged.connect(
1388
+ self.targetPositionChanged.emit
1389
+ )
1390
+ self.desktop_controller_widget.driveStatusChanged.connect(
1391
+ self.driveStatusChanged.emit
1392
+ )
1315
1393
 
1316
1394
  self.controller_combo_box.currentTextChanged.connect(self._switch_stack)
1317
1395
 
@@ -1362,6 +1440,14 @@ class DriveControlWidget(QWidget):
1362
1440
  def mg(self) -> Union[MotionGroup, None]:
1363
1441
  return self._mg
1364
1442
 
1443
+ @property
1444
+ def position(self) -> List[float]:
1445
+ return self.desktop_controller_widget.position
1446
+
1447
+ @property
1448
+ def target_position(self):
1449
+ return self.desktop_controller_widget.target_position
1450
+
1365
1451
  def _stop_move(self):
1366
1452
  self.mg.stop()
1367
1453
 
@@ -1472,6 +1558,20 @@ class DriveControlWidget(QWidget):
1472
1558
  if proceed:
1473
1559
  self.mg.move_to(target_pos)
1474
1560
 
1561
+ def set_target_position(self, target_position: List[float]):
1562
+ npos = len(target_position)
1563
+ naxes = self.mg.drive.naxes
1564
+
1565
+ if npos != naxes:
1566
+ self.logger.warning(
1567
+ f"Received target position {target_position} does NOT "
1568
+ f"have the same dimensionality as the drive "
1569
+ f"({naxes})."
1570
+ )
1571
+ return
1572
+
1573
+ self.desktop_controller_widget.set_target_position(target_position)
1574
+
1475
1575
  def closeEvent(self, event):
1476
1576
  self.logger.info(f"Closing {self.__class__.__name__}")
1477
1577
 
@@ -1657,6 +1757,8 @@ class MGWidget(QWidget):
1657
1757
  self.drive_control_widget = DriveControlWidget(parent=self)
1658
1758
  self.drive_control_widget.setEnabled(False)
1659
1759
 
1760
+ self.mpl_canvas = MotionSpaceDisplay(parent=self)
1761
+
1660
1762
  self.setLayout(self._define_layout())
1661
1763
  self._connect_signals()
1662
1764
 
@@ -1734,12 +1836,24 @@ class MGWidget(QWidget):
1734
1836
  self._transform_dropdown_new_selection
1735
1837
  )
1736
1838
 
1839
+ self.mpl_canvas.targetPositionSelected.connect(self._update_target_position)
1840
+
1737
1841
  self.drive_control_widget.movementStarted.connect(self.disable_config_controls)
1738
1842
  self.drive_control_widget.movementStopped.connect(self.enable_config_controls)
1843
+ self.drive_control_widget.targetPositionChanged.connect(
1844
+ self.mpl_canvas.update_target_position_plot
1845
+ )
1846
+ self.drive_control_widget.driveStatusChanged.connect(
1847
+ self._update_position_in_plot
1848
+ )
1739
1849
 
1740
1850
  self.done_btn.clicked.connect(self.return_and_close)
1741
1851
  self.discard_btn.clicked.connect(self.close)
1742
1852
 
1853
+ def _update_position_in_plot(self):
1854
+ position = self.drive_control_widget.position
1855
+ self.mpl_canvas.update_position_plot(position)
1856
+
1743
1857
  def _define_layout(self):
1744
1858
 
1745
1859
  layout = QVBoxLayout()
@@ -1767,9 +1881,7 @@ class MGWidget(QWidget):
1767
1881
  layout.addSpacing(12)
1768
1882
  layout.addLayout(self._define_central_builder_layout())
1769
1883
  layout.addSpacing(12)
1770
- # probe position graph widgets should go HERE
1771
- # - i.e. self._define_mspace_display_layout()
1772
- layout.addStretch(1)
1884
+ layout.addWidget(self.mpl_canvas)
1773
1885
 
1774
1886
  return layout
1775
1887
 
@@ -2007,6 +2119,7 @@ class MGWidget(QWidget):
2007
2119
  self._update_drive_dropdown()
2008
2120
  self._update_mb_dropdown()
2009
2121
  self._update_transform_dropdown()
2122
+ self._update_mpl_canvas_mb()
2010
2123
 
2011
2124
  # updating the drive control widget should always be the last
2012
2125
  # step
@@ -2377,6 +2490,9 @@ class MGWidget(QWidget):
2377
2490
 
2378
2491
  self.drive_control_widget.link_motion_group(self.mg)
2379
2492
 
2493
+ target_position = self.drive_control_widget.target_position
2494
+ self.drive_control_widget.targetPositionChanged.emit(target_position)
2495
+
2380
2496
  def _update_drive_dropdown(self):
2381
2497
  if self._custom_drive_index == -1:
2382
2498
  # this should never happen if self._custom_drive_index was
@@ -2449,6 +2565,28 @@ class MGWidget(QWidget):
2449
2565
 
2450
2566
  self._refresh_drive_control()
2451
2567
 
2568
+ def _update_mpl_canvas_mb(self):
2569
+ if (
2570
+ not isinstance(self.mg, MotionGroup)
2571
+ or not isinstance(self.mg.mb, MotionBuilder)
2572
+ ):
2573
+ self.mpl_canvas.unlink_motion_builder()
2574
+ return
2575
+
2576
+ if not isinstance(self.mpl_canvas.mb, MotionBuilder):
2577
+ self.mpl_canvas.link_motion_builder(self.mg.mb)
2578
+ return
2579
+
2580
+ if dict_equal(self.mg.mb.config, self.mpl_canvas.mb.config):
2581
+ # canvas already had current motion builder
2582
+ return
2583
+
2584
+ self.mpl_canvas.link_motion_builder(self.mg.mb)
2585
+
2586
+ @Slot(list)
2587
+ def _update_target_position(self, target_position: List[float]):
2588
+ self.drive_control_widget.set_target_position(target_position)
2589
+
2452
2590
  def _rename_motion_group(self):
2453
2591
  self.logger.info("Renaming motion group")
2454
2592
  self.mg.config["name"] = self.mg_name_widget.text()