quarchpy 2.2.1.dev6__py2.py3-none-any.whl → 2.2.3__py2.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 (214) hide show
  1. quarchpy/.idea/.gitignore +3 -0
  2. quarchpy/.idea/inspectionProfiles/Project_Default.xml +1 -39
  3. quarchpy/.idea/misc.xml +0 -3
  4. quarchpy/.idea/modules.xml +1 -0
  5. quarchpy/.idea/quarchpy.iml +1 -0
  6. quarchpy/.idea/workspace.xml +89 -88
  7. quarchpy/__init__.py +0 -1
  8. quarchpy/__pycache__/__init__.cpython-311.pyc +0 -0
  9. quarchpy/__pycache__/_version.cpython-311.pyc +0 -0
  10. quarchpy/__pycache__/connection.cpython-311.pyc +0 -0
  11. quarchpy/__pycache__/run.cpython-311.pyc +0 -0
  12. quarchpy/_version.py +1 -1
  13. quarchpy/_version.py.bak +1 -0
  14. quarchpy/config_files/__pycache__/__init__.cpython-311.pyc +0 -0
  15. quarchpy/config_files/__pycache__/quarch_config_parser.cpython-311.pyc +0 -0
  16. quarchpy/connection_specific/QPS/win-amd64/app.jar +0 -0
  17. quarchpy/connection_specific/QPS/win-amd64/qis/help.txt +3 -1
  18. quarchpy/connection_specific/QPS/win-amd64/qis/qis.jar +0 -0
  19. quarchpy/connection_specific/QPS/win-amd64/qis/qis_lib/{CInterface-2.0.jar → CInterface-2.2.jar} +0 -0
  20. quarchpy/connection_specific/QPS/win-amd64/qis/qis_lib/QuarchCommon-2.0.jar +0 -0
  21. quarchpy/connection_specific/QPS/win-amd64/qis/qis_lib/usb4java-1.3.1.jar +0 -0
  22. quarchpy/connection_specific/QPS/win-amd64/qps_lib/JFXUtilities-1.0.jar +0 -0
  23. quarchpy/connection_specific/QPS/win-amd64/qps_lib/QuarchCommon-2.0.jar +0 -0
  24. quarchpy/connection_specific/QPS/win-amd64/qps_lib/lin-x64/{javafx-base-21.0.1-linux.jar → javafx-base-21.0.4-linux.jar} +0 -0
  25. quarchpy/connection_specific/QPS/win-amd64/qps_lib/lin-x64/{javafx-controls-21.0.1-linux.jar → javafx-controls-21.0.4-linux.jar} +0 -0
  26. quarchpy/connection_specific/QPS/win-amd64/qps_lib/{lin-arm64/javafx-fxml-21.0.1-linux-aarch64.jar → lin-x64/javafx-fxml-21.0.4-linux.jar} +0 -0
  27. quarchpy/connection_specific/QPS/win-amd64/qps_lib/lin-x64/{javafx-graphics-21.0.1-linux.jar → javafx-graphics-21.0.4-linux.jar} +0 -0
  28. quarchpy/connection_specific/QPS/win-amd64/qps_lib/lin-x64/{javafx-swing-21.0.1-linux.jar → javafx-swing-21.0.4-linux.jar} +0 -0
  29. quarchpy/connection_specific/QPS/win-amd64/qps_lib/mac-arm64/{javafx-base-21.0.1-mac-aarch64.jar → javafx-base-21.0.4-mac-aarch64.jar} +0 -0
  30. quarchpy/connection_specific/QPS/win-amd64/qps_lib/mac-arm64/{javafx-controls-21.0.1-mac-aarch64.jar → javafx-controls-21.0.4-mac-aarch64.jar} +0 -0
  31. quarchpy/connection_specific/QPS/win-amd64/qps_lib/{lin-x64/javafx-fxml-21.0.1-linux.jar → mac-arm64/javafx-fxml-21.0.4-mac-aarch64.jar} +0 -0
  32. quarchpy/connection_specific/QPS/win-amd64/qps_lib/mac-arm64/{javafx-graphics-21.0.1-mac-aarch64.jar → javafx-graphics-21.0.4-mac-aarch64.jar} +0 -0
  33. quarchpy/connection_specific/QPS/win-amd64/qps_lib/mac-arm64/{javafx-swing-21.0.1-mac-aarch64.jar → javafx-swing-21.0.4-mac-aarch64.jar} +0 -0
  34. quarchpy/connection_specific/QPS/win-amd64/qps_lib/mac-x64/{javafx-base-21.0.1-mac.jar → javafx-base-21.0.4-mac.jar} +0 -0
  35. quarchpy/connection_specific/QPS/win-amd64/qps_lib/{lin-arm64/javafx-controls-21.0.1-linux-aarch64.jar → mac-x64/javafx-controls-21.0.4-mac.jar} +0 -0
  36. quarchpy/connection_specific/QPS/win-amd64/qps_lib/{win-x64/javafx-fxml-21.0.1-win.jar → mac-x64/javafx-fxml-21.0.4-mac.jar} +0 -0
  37. quarchpy/connection_specific/QPS/win-amd64/qps_lib/mac-x64/{javafx-graphics-21.0.1-mac.jar → javafx-graphics-21.0.4-mac.jar} +0 -0
  38. quarchpy/connection_specific/QPS/win-amd64/qps_lib/mac-x64/{javafx-swing-21.0.1-mac.jar → javafx-swing-21.0.4-mac.jar} +0 -0
  39. quarchpy/connection_specific/QPS/win-amd64/qps_lib/{qis-1.44.4.jar → qis-1.46.jar} +0 -0
  40. quarchpy/connection_specific/QPS/win-amd64/qps_lib/win-x64/{javafx-base-21.0.1-win.jar → javafx-base-21.0.4-win.jar} +0 -0
  41. quarchpy/connection_specific/QPS/win-amd64/qps_lib/win-x64/{javafx-controls-21.0.1-win.jar → javafx-controls-21.0.4-win.jar} +0 -0
  42. quarchpy/connection_specific/QPS/win-amd64/qps_lib/{mac-x64/javafx-fxml-21.0.1-mac.jar → win-x64/javafx-fxml-21.0.4-win.jar} +0 -0
  43. quarchpy/connection_specific/QPS/win-amd64/qps_lib/win-x64/{javafx-graphics-21.0.1-win.jar → javafx-graphics-21.0.4-win.jar} +0 -0
  44. quarchpy/connection_specific/QPS/win-amd64/qps_lib/win-x64/{javafx-swing-21.0.1-win.jar → javafx-swing-21.0.4-win.jar} +0 -0
  45. quarchpy/connection_specific/QPS/win-amd64/resources/profiles/3_PHASE_PAM_AC_DEFAULT.rcf +2 -2
  46. quarchpy/connection_specific/QPS/win-amd64/resources/profiles/3_PHASE_PAM_AC_FULL.rcf +5 -56
  47. quarchpy/connection_specific/QPS/win-amd64/resources/profiles/3_PHASE_PAM_AC_FULL.scf +3 -3
  48. quarchpy/connection_specific/QPS/win-amd64/resources/profiles/PAM_EXAMPLE_CONFIG.rcf +1 -1
  49. quarchpy/connection_specific/QPS/win-amd64/scriptCommands.txt +18 -7
  50. quarchpy/connection_specific/QPS/win-amd64/whats-new.txt +16 -18
  51. quarchpy/connection_specific/connection_QIS.py +55 -24
  52. quarchpy/debug/__pycache__/SystemTest.cpython-311.pyc +0 -0
  53. quarchpy/debug/__pycache__/__init__.cpython-311.pyc +0 -0
  54. quarchpy/debug/__pycache__/module_debug.cpython-311.pyc +0 -0
  55. quarchpy/debug/__pycache__/simple_terminal.cpython-311.pyc +0 -0
  56. quarchpy/debug/__pycache__/upgrade_quarchpy.cpython-311.pyc +0 -0
  57. quarchpy/debug/__pycache__/versionCompare.cpython-311.pyc +0 -0
  58. quarchpy/debug/simple_terminal.py +1 -1
  59. quarchpy/device/__pycache__/__init__.cpython-311.pyc +0 -0
  60. quarchpy/device/__pycache__/device.cpython-311.pyc +0 -0
  61. quarchpy/device/__pycache__/quarchArray.cpython-311.pyc +0 -0
  62. quarchpy/device/__pycache__/quarchPPM.cpython-311.pyc +0 -0
  63. quarchpy/device/__pycache__/quarchQPS.cpython-311.pyc +0 -0
  64. quarchpy/device/__pycache__/scanDevices.cpython-311.pyc +0 -0
  65. quarchpy/device/quarchPPM.py +105 -3
  66. quarchpy/device/quarchQPS.py +47 -52
  67. quarchpy/device/quarchQPS.py.bak +398 -0
  68. quarchpy/device/scanDevices.py +18 -10
  69. quarchpy/disk_test/__pycache__/AbsDiskFinder.cpython-311.pyc +0 -0
  70. quarchpy/disk_test/__pycache__/DiskTargetSelection.cpython-311.pyc +0 -0
  71. quarchpy/disk_test/__pycache__/__init__.cpython-311.pyc +0 -0
  72. quarchpy/disk_test/__pycache__/iometerDiskFinder.cpython-311.pyc +0 -0
  73. quarchpy/docs/CHANGES.rst +12 -0
  74. quarchpy/docs/CHANGES.rst.bak +430 -0
  75. quarchpy/docs/_build/doctrees/CHANGES.doctree +0 -0
  76. quarchpy/docs/_build/doctrees/environment.pickle +0 -0
  77. quarchpy/docs/_build/doctrees/index.doctree +0 -0
  78. quarchpy/docs/_build/doctrees/readme.doctree +0 -0
  79. quarchpy/docs/_build/doctrees/source/changelog.doctree +0 -0
  80. quarchpy/docs/_build/doctrees/source/licenses.doctree +0 -0
  81. quarchpy/docs/_build/doctrees/source/modules.doctree +0 -0
  82. quarchpy/docs/_build/doctrees/source/quarchpy.calibration.doctree +0 -0
  83. quarchpy/docs/_build/doctrees/source/quarchpy.config_files.doctree +0 -0
  84. quarchpy/docs/_build/doctrees/source/quarchpy.connection_specific.doctree +0 -0
  85. quarchpy/docs/_build/doctrees/source/quarchpy.debug.doctree +0 -0
  86. quarchpy/docs/_build/doctrees/source/quarchpy.device.doctree +0 -0
  87. quarchpy/docs/_build/doctrees/source/quarchpy.disk_test.doctree +0 -0
  88. quarchpy/docs/_build/doctrees/source/quarchpy.doctree +0 -0
  89. quarchpy/docs/_build/doctrees/source/quarchpy.fio.doctree +0 -0
  90. quarchpy/docs/_build/doctrees/source/quarchpy.iometer.doctree +0 -0
  91. quarchpy/docs/_build/doctrees/source/quarchpy.qis.doctree +0 -0
  92. quarchpy/docs/_build/doctrees/source/quarchpy.qps.doctree +0 -0
  93. quarchpy/docs/_build/doctrees/source/quarchpy.user_interface.doctree +0 -0
  94. quarchpy/docs/_build/doctrees/source/quarchpy.utilities.doctree +0 -0
  95. quarchpy/docs/_build/doctrees/source/readme.doctree +0 -0
  96. quarchpy/docs/_build/html/CHANGES.html +142 -127
  97. quarchpy/docs/_build/html/_sources/CHANGES.rst.txt +12 -0
  98. quarchpy/docs/_build/html/genindex.html +26 -18
  99. quarchpy/docs/_build/html/index.html +66 -64
  100. quarchpy/docs/_build/html/objects.inv +0 -0
  101. quarchpy/docs/_build/html/searchindex.js +1 -1
  102. quarchpy/docs/_build/html/source/changelog.html +208 -191
  103. quarchpy/docs/_build/html/source/quarchpy.device.html +51 -15
  104. quarchpy/docs/_build/html/source/quarchpy.fio.html +0 -10
  105. quarchpy/docs/_build/html/source/quarchpy.html +7 -5
  106. quarchpy/docs/_build/html/source/quarchpy.qps.html +0 -41
  107. quarchpy/fio/FIO_interface.py +0 -7
  108. quarchpy/fio/__pycache__/FIO_interface.cpython-311.pyc +0 -0
  109. quarchpy/fio/__pycache__/__init__.cpython-311.pyc +0 -0
  110. quarchpy/fio/__pycache__/fioDiskFinder.cpython-311.pyc +0 -0
  111. quarchpy/iometer/__pycache__/__init__.cpython-311.pyc +0 -0
  112. quarchpy/iometer/__pycache__/gen_iometer_template.cpython-311.pyc +0 -0
  113. quarchpy/iometer/__pycache__/iometerFuncs.cpython-311.pyc +0 -0
  114. quarchpy/qis/__pycache__/StreamHeaderInfo.cpython-311.pyc +0 -0
  115. quarchpy/qis/__pycache__/__init__.cpython-311.pyc +0 -0
  116. quarchpy/qis/__pycache__/qisFuncs.cpython-311.pyc +0 -0
  117. quarchpy/qps/__init__.py +2 -2
  118. quarchpy/qps/__pycache__/__init__.cpython-311.pyc +0 -0
  119. quarchpy/qps/__pycache__/qpsFuncs.cpython-311.pyc +0 -0
  120. quarchpy/qps/qpsFuncs.py +1 -51
  121. quarchpy/user_interface/__pycache__/__init__.cpython-311.pyc +0 -0
  122. quarchpy/user_interface/__pycache__/user_interface.cpython-311.pyc +0 -0
  123. quarchpy/user_interface/user_interface.py +4 -1
  124. quarchpy/utilities/__pycache__/TestCenter.cpython-311.pyc +0 -0
  125. quarchpy/utilities/__pycache__/TimeValue.cpython-311.pyc +0 -0
  126. quarchpy/utilities/__pycache__/Version.cpython-311.pyc +0 -0
  127. quarchpy/utilities/__pycache__/__init__.cpython-311.pyc +0 -0
  128. {quarchpy-2.2.1.dev6.dist-info → quarchpy-2.2.3.dist-info}/METADATA +13 -1
  129. {quarchpy-2.2.1.dev6.dist-info → quarchpy-2.2.3.dist-info}/RECORD +131 -208
  130. {quarchpy-2.2.1.dev6.dist-info → quarchpy-2.2.3.dist-info}/WHEEL +1 -1
  131. quarchpy/.idea/.name +0 -1
  132. quarchpy/.idea/vcs.xml +0 -6
  133. quarchpy/__pycache__/__init__.cpython-312.pyc +0 -0
  134. quarchpy/__pycache__/_version.cpython-312.pyc +0 -0
  135. quarchpy/__pycache__/connection.cpython-312.pyc +0 -0
  136. quarchpy/__pycache__/run.cpython-312.pyc +0 -0
  137. quarchpy/config_files/__pycache__/__init__.cpython-312.pyc +0 -0
  138. quarchpy/config_files/__pycache__/quarch_config_parser.cpython-312.pyc +0 -0
  139. quarchpy/connection_specific/QPS/win-amd64/InstallType.dat +0 -1
  140. quarchpy/connection_specific/QPS/win-amd64/qps_lib/lin-arm64/javafx-base-21.0.1-linux-aarch64.jar +0 -0
  141. quarchpy/connection_specific/QPS/win-amd64/qps_lib/lin-arm64/javafx-graphics-21.0.1-linux-aarch64.jar +0 -0
  142. quarchpy/connection_specific/QPS/win-amd64/qps_lib/lin-arm64/javafx-swing-21.0.1-linux-aarch64.jar +0 -0
  143. quarchpy/connection_specific/QPS/win-amd64/qps_lib/mac-arm64/javafx-fxml-21.0.1-mac-aarch64.jar +0 -0
  144. quarchpy/connection_specific/QPS/win-amd64/qps_lib/mac-x64/javafx-controls-21.0.1-mac.jar +0 -0
  145. quarchpy/connection_specific/QPS/win-amd64/qps_lib/qis-1.44.2.jar +0 -0
  146. quarchpy/connection_specific/__pycache__/StreamChannels.cpython-311.pyc +0 -0
  147. quarchpy/connection_specific/__pycache__/StreamChannels.cpython-312.pyc +0 -0
  148. quarchpy/connection_specific/__pycache__/__init__.cpython-311.pyc +0 -0
  149. quarchpy/connection_specific/__pycache__/__init__.cpython-312.pyc +0 -0
  150. quarchpy/connection_specific/__pycache__/connection_QIS.cpython-311.pyc +0 -0
  151. quarchpy/connection_specific/__pycache__/connection_QIS.cpython-312.pyc +0 -0
  152. quarchpy/connection_specific/__pycache__/connection_QPS.cpython-311.pyc +0 -0
  153. quarchpy/connection_specific/__pycache__/connection_QPS.cpython-312.pyc +0 -0
  154. quarchpy/connection_specific/__pycache__/connection_ReST.cpython-311.pyc +0 -0
  155. quarchpy/connection_specific/__pycache__/connection_ReST.cpython-312.pyc +0 -0
  156. quarchpy/connection_specific/__pycache__/connection_Serial.cpython-311.pyc +0 -0
  157. quarchpy/connection_specific/__pycache__/connection_Serial.cpython-312.pyc +0 -0
  158. quarchpy/connection_specific/__pycache__/connection_TCP.cpython-311.pyc +0 -0
  159. quarchpy/connection_specific/__pycache__/connection_TCP.cpython-312.pyc +0 -0
  160. quarchpy/connection_specific/__pycache__/connection_USB.cpython-311.pyc +0 -0
  161. quarchpy/connection_specific/__pycache__/connection_USB.cpython-312.pyc +0 -0
  162. quarchpy/connection_specific/__pycache__/mDNS.cpython-311.pyc +0 -0
  163. quarchpy/connection_specific/__pycache__/mDNS.cpython-312.pyc +0 -0
  164. quarchpy/connection_specific/jdk_j21_jres/__pycache__/__init__.cpython-312.pyc +0 -0
  165. quarchpy/connection_specific/jdk_j21_jres/__pycache__/fix_permissions.cpython-312.pyc +0 -0
  166. quarchpy/connection_specific/serial/__pycache__/__init__.cpython-311.pyc +0 -0
  167. quarchpy/connection_specific/serial/__pycache__/__init__.cpython-312.pyc +0 -0
  168. quarchpy/connection_specific/serial/__pycache__/serialutil.cpython-311.pyc +0 -0
  169. quarchpy/connection_specific/serial/__pycache__/serialutil.cpython-312.pyc +0 -0
  170. quarchpy/connection_specific/serial/__pycache__/serialwin32.cpython-311.pyc +0 -0
  171. quarchpy/connection_specific/serial/__pycache__/serialwin32.cpython-312.pyc +0 -0
  172. quarchpy/connection_specific/serial/__pycache__/win32.cpython-311.pyc +0 -0
  173. quarchpy/connection_specific/serial/__pycache__/win32.cpython-312.pyc +0 -0
  174. quarchpy/connection_specific/serial/tools/__pycache__/__init__.cpython-311.pyc +0 -0
  175. quarchpy/connection_specific/serial/tools/__pycache__/__init__.cpython-312.pyc +0 -0
  176. quarchpy/connection_specific/serial/tools/__pycache__/list_ports.cpython-311.pyc +0 -0
  177. quarchpy/connection_specific/serial/tools/__pycache__/list_ports.cpython-312.pyc +0 -0
  178. quarchpy/connection_specific/serial/tools/__pycache__/list_ports_common.cpython-311.pyc +0 -0
  179. quarchpy/connection_specific/serial/tools/__pycache__/list_ports_common.cpython-312.pyc +0 -0
  180. quarchpy/connection_specific/serial/tools/__pycache__/list_ports_windows.cpython-311.pyc +0 -0
  181. quarchpy/connection_specific/serial/tools/__pycache__/list_ports_windows.cpython-312.pyc +0 -0
  182. quarchpy/debug/__pycache__/SystemTest.cpython-312.pyc +0 -0
  183. quarchpy/debug/__pycache__/__init__.cpython-312.pyc +0 -0
  184. quarchpy/debug/__pycache__/module_debug.cpython-312.pyc +0 -0
  185. quarchpy/debug/__pycache__/simple_terminal.cpython-312.pyc +0 -0
  186. quarchpy/debug/__pycache__/upgrade_quarchpy.cpython-312.pyc +0 -0
  187. quarchpy/debug/__pycache__/versionCompare.cpython-312.pyc +0 -0
  188. quarchpy/device/__pycache__/__init__.cpython-312.pyc +0 -0
  189. quarchpy/device/__pycache__/device.cpython-312.pyc +0 -0
  190. quarchpy/device/__pycache__/quarchArray.cpython-312.pyc +0 -0
  191. quarchpy/device/__pycache__/quarchPPM.cpython-312.pyc +0 -0
  192. quarchpy/device/__pycache__/quarchQPS.cpython-312.pyc +0 -0
  193. quarchpy/device/__pycache__/scanDevices.cpython-312.pyc +0 -0
  194. quarchpy/disk_test/__pycache__/AbsDiskFinder.cpython-312.pyc +0 -0
  195. quarchpy/disk_test/__pycache__/DiskTargetSelection.cpython-312.pyc +0 -0
  196. quarchpy/disk_test/__pycache__/__init__.cpython-312.pyc +0 -0
  197. quarchpy/disk_test/__pycache__/iometerDiskFinder.cpython-312.pyc +0 -0
  198. quarchpy/fio/__pycache__/FIO_interface.cpython-312.pyc +0 -0
  199. quarchpy/fio/__pycache__/__init__.cpython-312.pyc +0 -0
  200. quarchpy/iometer/__pycache__/__init__.cpython-312.pyc +0 -0
  201. quarchpy/iometer/__pycache__/gen_iometer_template.cpython-312.pyc +0 -0
  202. quarchpy/iometer/__pycache__/iometerFuncs.cpython-312.pyc +0 -0
  203. quarchpy/qis/__pycache__/StreamHeaderInfo.cpython-312.pyc +0 -0
  204. quarchpy/qis/__pycache__/__init__.cpython-312.pyc +0 -0
  205. quarchpy/qis/__pycache__/qisFuncs.cpython-312.pyc +0 -0
  206. quarchpy/qps/__pycache__/__init__.cpython-312.pyc +0 -0
  207. quarchpy/qps/__pycache__/qpsFuncs.cpython-312.pyc +0 -0
  208. quarchpy/user_interface/__pycache__/__init__.cpython-312.pyc +0 -0
  209. quarchpy/user_interface/__pycache__/user_interface.cpython-312.pyc +0 -0
  210. quarchpy/utilities/__pycache__/TestCenter.cpython-312.pyc +0 -0
  211. quarchpy/utilities/__pycache__/TimeValue.cpython-312.pyc +0 -0
  212. quarchpy/utilities/__pycache__/Version.cpython-312.pyc +0 -0
  213. quarchpy/utilities/__pycache__/__init__.cpython-312.pyc +0 -0
  214. {quarchpy-2.2.1.dev6.dist-info → quarchpy-2.2.3.dist-info}/top_level.txt +0 -0
@@ -1,41 +1,39 @@
1
1
  *** What's New In Quarch Power Studio ***
2
2
 
3
- 19th July 2024
3
+ 11th November 2024
4
4
 
5
- QPS version 1.42
6
- QIS version 1.44
5
+ QPS version 1.44
6
+ QIS version 1.46
7
7
 
8
8
 
9
9
 
10
10
  *** New Features ***
11
11
 
12
- QPS is now build against Java21. The runtime is packaged in the installer so seperate Java install is not required in most cases
12
+ Synthetic channels can now be disabled without deleting them (as with instrument channels)
13
13
 
14
- This 'What's new' dialog added, to call out the latest features!
14
+ Added channel options to the CSV export dialog
15
15
 
16
- Annotations improvements: Hover-over displays their text. Hover over the Annotations tab text to highlight the annotation. Vertical movement is enabled by default, to arrange them more easily
16
+ Improved cursor controls and display
17
17
 
18
- Speed improvements when navigating through large datasets
18
+ Instrument profiles now display their name and description information when loaded
19
19
 
20
- Modules with updated firmware available are now indicated to the user
20
+ Synthetic channel for subtraction added
21
21
 
22
- Missing USB drivers are now highlighted to the user
22
+ Channels can now have visibility disabled by default for a less cluttered view
23
23
 
24
- Statistics tab now has auto-ranging for units, to be more readable
24
+ Added a simple user debug command to capture all logs
25
25
 
26
- The color of cursors can be changed, to make them more visible
27
-
28
- Summary data can now be collapsed to make it more readable
26
+ Improved debug logging when loading traces
29
27
 
30
28
 
31
29
  *** Major Fixes ***
32
30
 
33
- Fixed issue where old trace data did not delete correctly
31
+ Fixed loading of synthetic channel files for AC PAM
34
32
 
35
- Fixed issue where LAN devices could lose connection after a couple of hours of streaming
33
+ Fixed failure to calculate statistics for very short regions
36
34
 
37
- Fixed issue where progress bar and notifications were both modal, locking access
35
+ Fixed issue where stream start could take a second or so to begin showing data
38
36
 
39
- Touchpad horizontal two finger scrolling now works correctly
37
+ Fixed bug where QIS debug logging did not work to console
40
38
 
41
- Multiple other exceptions trapped and handled
39
+ Fixed bug where sparse user channels did not always export correctly to CSV
@@ -1100,24 +1100,25 @@ class QisInterface:
1100
1100
  try:
1101
1101
  if sock == None:
1102
1102
  sock = self.sock
1103
-
1104
- # Get the raw data
1105
- headerData = self.sendAndReceiveText(sock, sentText='stream text header', device=device)
1103
+ count = 0
1104
+ while(True):
1105
+ if count > 5:
1106
+ break
1107
+ count += 1
1108
+ # Get the raw data
1109
+ headerData = self.sendAndReceiveText(sock, sentText='stream text header', device=device)
1106
1110
 
1107
- # The XML can contain the cursor on the end! Trap and remove it here TODO: Needs fixed in the command layer above
1108
- if ('\r\n>' in headerData):
1109
- headerData = headerData[:-1]
1110
-
1111
- # Check for no header (no stream started)
1112
- if('Header Not Available' in headerData):
1113
- logging.error(device + ' Stream header not available.' + self.host + ':' + str(self.port))
1114
- return None;
1115
-
1116
- # Check for XML format
1117
- if('?xml version=' not in headerData):
1118
- logging.error(device + ' Header not in XML form.' + self.host + ':' + str(self.port))
1119
- return None;
1120
-
1111
+ # Check for no header (no stream started)
1112
+ if('Header Not Available' in headerData):
1113
+ logging.error(device + ' Stream header not available.' + self.host + ':' + str(self.port))
1114
+ continue
1115
+
1116
+ # Check for XML format
1117
+ if('?xml version=' not in headerData):
1118
+ logging.error(device + ' Header not in XML form.' + self.host + ':' + str(self.port))
1119
+ continue
1120
+
1121
+ break
1121
1122
  # Parse XML into structured format
1122
1123
  xml_root = ET.fromstring(headerData)
1123
1124
 
@@ -1567,9 +1568,12 @@ class QisInterface:
1567
1568
  res = self.sendAndReceiveText(sock, cmd, device, readUntilCursor)
1568
1569
  if (betweenCommandDelay > 0):
1569
1570
  time.sleep(betweenCommandDelay)
1571
+
1570
1572
  # If ends with cursor get rid of it
1571
- if res[-1:] == '>':
1572
- res = res[:-3] # remove last three chars - hopefully '\r\n>'
1573
+ if res[-3:] == '\r\n>':
1574
+ res = res[:-3] # remove last three chars - '\r\n>'
1575
+ elif res[-2:] == '\n>':
1576
+ res = res[:-2] # remove last 2 chars - '\n>'
1573
1577
  return res
1574
1578
 
1575
1579
  else :
@@ -1638,15 +1642,42 @@ class QisInterface:
1638
1642
  logging.warning(res[0])
1639
1643
  # If reading until a cursor comes back then keep reading until a cursor appears or max tries exceeded
1640
1644
  if readUntilCursor:
1645
+ import xml.etree.ElementTree as ET
1646
+
1641
1647
  maxReads = 1000
1642
1648
  count = 1
1643
- # check for cursor at end of read and if not there read again
1644
- while res[-1:] != self.cursor:
1645
- res+= self.receiveText(sock) #TODO Confirm this works with multi response CMD Like a $get stats on a large stream with many annos. test with py2 and py3
1646
- #res.extend(self.rxBytes(sock))
1649
+ is_xml = False
1650
+
1651
+ while True:
1652
+
1653
+ # Determine if the response is XML based on its start
1654
+ if count == 1: # Only check this on the first read
1655
+ if res.startswith("<?xml"): # Likely XML if it starts with '<'
1656
+ is_xml = True
1657
+ elif res.startswith("<XmlResponse"):
1658
+ is_xml = True
1659
+
1660
+
1661
+ if is_xml:
1662
+ # Try to parse the XML to check if it's complete
1663
+ try:
1664
+ ET.fromstring(res[:-1]) # If it parses, the response is complete
1665
+ return res[:-1] # Exit the loop, valid XML received
1666
+ except ET.ParseError:
1667
+ pass # Keep reading until XML is complete
1668
+ else:
1669
+ # Handle normal strings
1670
+ if res[-1:] == self.cursor: # If the last character is '>', stop reading
1671
+ break
1672
+
1673
+ # Receive more data
1674
+ res += self.receiveText(sock)
1675
+
1676
+ # Increment count and check for max reads
1647
1677
  count += 1
1648
1678
  if count >= maxReads:
1649
- raise Exception(' Count = Error: max reads exceeded before cursor returned')
1679
+ raise Exception('Count = Error: max reads exceeded before response was complete')
1680
+
1650
1681
  return res
1651
1682
 
1652
1683
  except Exception as e:
@@ -4,7 +4,7 @@ Feel free to expand and add your own features to this.
4
4
 
5
5
  ########### VERSION HISTORY ###########
6
6
 
7
- 26/11/2020 - Stuart Boon - First Version
7
+ 26/11/2020 - Stuart Boon - First Version
8
8
 
9
9
  ########### INSTRUCTIONS ###########
10
10
  Select the module you would like to talk to.
@@ -1,16 +1,22 @@
1
1
  from .device import quarchDevice
2
2
  import logging
3
+ import xml.etree.ElementTree as ET
3
4
  from quarchpy.user_interface.user_interface import printText
4
5
 
6
+
5
7
  class quarchPPM(quarchDevice):
6
- def __init__(self, originObj):
8
+ def __init__(self, originObj, skipDefaultSyntheticChannels=False):
7
9
 
8
10
  self.connectionObj = originObj.connectionObj
9
11
  self.ConString = originObj.ConString
10
12
  self.ConType = originObj.ConType
13
+ self.fixture_definition = self.sendCommand("fix:chan:xml?")
14
+ self.default_channels = None
11
15
  numb_colons = self.ConString.count(":")
12
16
  if numb_colons == 1:
13
17
  self.ConString = self.ConString.replace(':', '::')
18
+ if not skipDefaultSyntheticChannels and self.ConType[:3].upper() == "QIS":
19
+ self.create_default_synthetic_channels()
14
20
 
15
21
  def startStream(self, fileName='streamData.txt', fileMaxMB=200000, streamName ='Stream With No Name', streamDuration = None, streamAverage = None, releaseOnData = False, separator=",", inMemoryData = None):
16
22
  return self.connectionObj.qis.startStream(self.ConString, fileName, fileMaxMB, streamName, streamAverage, releaseOnData, separator, streamDuration, inMemoryData)
@@ -27,9 +33,12 @@ class quarchPPM(quarchDevice):
27
33
  def waitStop(self):
28
34
  return self.connectionObj.qis.waitStop()
29
35
 
30
- def streamResampleMode(self, streamCom):
36
+ def streamResampleMode(self, streamCom, group=None):
31
37
  if streamCom.lower() == "off" or streamCom[0:-2].isdigit():
32
- retVal = self.connectionObj.qis.sendAndReceiveCmd(cmd="stream mode resample " + streamCom.lower(),
38
+ cmd = "stream mode resample " + streamCom.lower()
39
+ if group is not None:
40
+ cmd = "stream mode resample group " + str(group) + " " + streamCom.lower()
41
+ retVal = self.connectionObj.qis.sendAndReceiveCmd(cmd=cmd,
33
42
  device=self.ConString)
34
43
  if "fail" in retVal.lower():
35
44
  logging.error(retVal)
@@ -65,3 +74,96 @@ class quarchPPM(quarchDevice):
65
74
  if "OFF" in powerState or "PULLED" in powerState: # PULLED comes from PAM
66
75
  # Power Up
67
76
  printText("\n Turning the outputs on:"), myModule.sendCommand("run:power up"), "!"
77
+
78
+ '''
79
+ Parses the fixture XML and extracts the synthetic channels specified by the instrument defaults.
80
+ This function reads the fixture XML structure and looks for channels under the SyntheticChannels node,
81
+ extracting the relevant information (number, function, enable status, etc.).
82
+ '''
83
+
84
+ def parse_synthetic_channels_from_instrument(self):
85
+ # Parse the XML data from the fixture_definition (which is an XML string) to get the root element
86
+ root = ET.fromstring(self.fixture_definition)
87
+
88
+ # Initialize an empty list to hold all parsed synthetic channels
89
+ synthetic_channels = []
90
+
91
+ # Loop over each 'Channel' element found within 'SyntheticChannels' in the XML tree
92
+ for channel in root.findall(".//SyntheticChannels/Channel"):
93
+ # Extract values of interest from each channel, using XPath queries to find the relevant parameters
94
+ number = channel.find(".//Param[Name='Number']/Value")
95
+ function = channel.find(".//Param[Name='Function']/Value")
96
+ enable = channel.find(".//Param[Name='Enable']/Value")
97
+ enabled_by_default = channel.find(".//Param[Name='EnabledByDefault']/Value")
98
+ visible_by_default = channel.find(".//Param[Name='VisibleByDefault']/Value")
99
+
100
+ # Convert values from XML to appropriate data types (number is an integer, others are strings or booleans)
101
+ number = int(number.text) if number is not None else 0
102
+ function = function.text if function is not None else ""
103
+ enable = enable.text.lower() == 'true' if enable is not None else False
104
+ enabled_by_default = enabled_by_default.text.lower() == 'true' if enabled_by_default is not None else False
105
+ visible_by_default = visible_by_default.text.lower() == 'true' if visible_by_default is not None else False
106
+
107
+ # Create an instance of the SyntheticChannel class with the extracted information
108
+ synthetic_channel = SyntheticChannel(number, function, enable, enabled_by_default, visible_by_default)
109
+
110
+ # Append the newly created SyntheticChannel object to the list of channels
111
+ synthetic_channels.append(synthetic_channel)
112
+
113
+ # Return the list of synthetic channels extracted from the XML
114
+ return synthetic_channels
115
+
116
+ '''
117
+ Sends the set of synthetic channels to the device.
118
+ This method iterates through the list of synthetic channels and sends the appropriate
119
+ commands to a QIS/QPS-based device to create the channels.
120
+ '''
121
+
122
+ def send_synthetic_channels(self, channels):
123
+ # Loop through each channel in the provided list of channels
124
+ for channel in channels:
125
+ # Send a command to the device to create a stream with the channel's function
126
+ result = self.sendCommand("stream create channel " + channel.function)
127
+
128
+ # If the command result is not "OK", raise an exception with an error message
129
+ if result != "OK":
130
+ raise Exception(f"Command failed for channel {channel.number}: {channel.function} = {result}")
131
+
132
+ '''
133
+ Creates the default synthetic channels based on the fixture XML.
134
+ This method first parses the synthetic channels from the instrument and sends them to the device.
135
+ '''
136
+
137
+ def create_default_synthetic_channels(self):
138
+ # The fixture XML and synthetic channels are only parsed once per connection.
139
+ # If the fixture is replaced or changed, this info should be refreshed via an API call.
140
+ # This stores the default channels in the class for later use to avoid re-parsing multiple times.
141
+ self.default_channels = self.parse_synthetic_channels_from_instrument()
142
+
143
+ # Sends the parsed default synthetic channels to the device.
144
+ # This could be part of the device initialization process, with an option to skip it using a flag.
145
+ self.send_synthetic_channels(self.default_channels)
146
+
147
+ # The following commented-out example shows how to manually send a command for a specific synthetic channel.
148
+ # Example: This command calculates the RMS current for the neutral line.
149
+ # self.sendCommand("stream create channel chan(Neutral_RMS,A) rms(100ms,chan(Neutral,A))")
150
+
151
+ '''
152
+ Class representing a SyntheticChannel.
153
+ Each synthetic channel is characterized by a number, function, enable status,
154
+ whether it's enabled by default, and whether it's visible by default.
155
+ '''
156
+
157
+ class SyntheticChannel:
158
+ def __init__(self, number, function, enable, enabled_by_default, visible_by_default):
159
+ self.number = number # The unique number identifier for the synthetic channel
160
+ self.function = function # The function or behavior of the channel (e.g., RMS calculation)
161
+ self.enable = enable # Whether the channel is currently enabled
162
+ self.enabled_by_default = enabled_by_default # Whether the channel is enabled by default
163
+ self.visible_by_default = visible_by_default # Whether the channel is visible by default
164
+
165
+ def __repr__(self):
166
+ # Provide a readable string representation of the synthetic channel, useful for debugging or logging
167
+ return (f"SyntheticChannel(Number={self.number}, Function='{self.function}', "
168
+ f"Enable={self.enable}, EnabledByDefault={self.enabled_by_default}, "
169
+ f"VisibleByDefault={self.visible_by_default})")
@@ -1,5 +1,4 @@
1
1
  from quarchpy.device import quarchDevice
2
- from quarchpy.qps import toQpsTimeStamp
3
2
  from quarchpy.utilities.Version import Version
4
3
  from quarchpy.user_interface.user_interface import requestDialog
5
4
  import os, time, datetime, sys, logging
@@ -35,7 +34,7 @@ class quarchQPS(quarchDevice):
35
34
  directory - str - desired stream dir
36
35
  unserInput=True - if a failure occurs userInput=True allows user to rectify problem with user input. set to False if user interaction is not available (automating).
37
36
  """
38
- time.sleep(1) # TODO remove this sleep once script->QPS timeing issue resolved. This works fine in the meantime
37
+ #time.sleep(1) # TODO remove this sleep once script->QPS timeing issue resolved. This works fine in the meantime
39
38
  return quarchStream(self.quarchDevice, directory, unserInput)
40
39
 
41
40
 
@@ -198,8 +197,9 @@ class quarchStream:
198
197
  raise Exception(command_response)
199
198
  return (command_response)
200
199
 
200
+
201
201
  def addAnnotation(self, title, annotationTime=0, extraText="", yPos="", titleColor="", annotationColor="",
202
- annotationType="", annotationGroup=""):
202
+ annotationType="", timeFormat="unix"):
203
203
  """
204
204
  Adds a custom annotation to stream with given parameters.
205
205
 
@@ -215,9 +215,9 @@ class quarchStream:
215
215
  The color of the text next to the annotation in hex format 000000 to FFFFFF
216
216
  annotationColor : str, optional
217
217
  The color of the annotation marker in hex format 000000 to FFFFFF
218
- annotationGroup : str, optional
219
- The group the annotation belongs to
220
- annotationTime : int, optional
218
+ annotationType : str, optional
219
+ The group the annotation belongs to, annotation comment or any custom group the user has made.
220
+ timeFormat : str, optional
221
221
  The time in milliseconds after the start of the stream at which the annotation should be placed. 0 will plot the annotation live at the most recent sample
222
222
 
223
223
  Returns
@@ -226,62 +226,56 @@ class quarchStream:
226
226
 
227
227
  The response text from QPS. "ok" if annotation successfully added
228
228
  """
229
- annotationTime = str(annotationTime)
229
+
230
230
  annotationType = annotationType.lower()
231
+ annotationTime = str(annotationTime)
232
+
233
+ if (annotationTime[0].isalpha() or annotationTime[-1].isalpha()):
234
+ timeFormat="elapsed"
235
+ if annotationTime.startswith("e"): #Old format allowed e to be used to pass elapsed time in seconds "e2" -> 2s + elapsed
236
+ annotationTime=annotationTime[1:]+"s"
237
+
238
+ elif annotationTime=="0":
239
+ annotationTime=current_milli_time()
240
+ timeFormat="unix"
241
+
231
242
  if annotationType == "" or annotationType == "annotation":
232
243
  annotationType = "annotate"
233
244
  elif annotationType == "comment":
234
245
  pass # already in the correct format for command
235
- else:
236
- retString = "Fail annotationType must be 'annotation' or 'comment'"
237
- logging.warning(retString)
238
- return retString
246
+ # else: # QPS now supports custom types passed as annotationType rather than annotation group.
247
+ # retString = "Fail annotationType must be 'annotation' or 'comment'"
248
+ # logging.warning(retString)
249
+ # return retString
250
+
251
+ title = title.replace("\n", "\\n")
252
+ cmd="$stream annotation add "+" time="+str(annotationTime)+ " text=\""+title+"\""
253
+ if extraText!="":
254
+ extraText = extraText.replace("\n", "\\n")
255
+ cmd+=" extraText=\"" +str(extraText)+"\""
256
+ if yPos!= "":
257
+ cmd+=" yPos="+str(yPos)
258
+ if type!="":
259
+ cmd+=" type="+ str(annotationType)
260
+ if annotationColor!="":
261
+ cmd+=" colour="+str(annotationColor)
262
+ if titleColor!="":
263
+ cmd+=" textColour="+str(titleColor)
264
+ if timeFormat!="":
265
+ cmd+=" timeFormat="+str(timeFormat)
266
+
267
+ return self.connectionObj.qps.sendCmdVerbose(cmd)
239
268
 
240
- # If the function has already been passed the XML string to give to QPS
241
- if ("<<" in title.replace(" ", "")):
242
- annotationString = str(title)
243
- else:
244
- annotationString = "<"
245
-
246
- if annotationTime == "0":
247
- # Use current time
248
- annotationTime = qpsNowStr()
249
- elif (annotationTime.startswith("e")):
250
- pass
251
- else:
252
- # Convert timestamp to QPS format
253
- # annotationTime = toQpsTimeStamp(annotationTime)
254
- annotationTime = str(annotationTime)
255
-
256
- if title != "":
257
- annotationString += "<text>" + str(title) + "</text>"
258
- if extraText != "":
259
- annotationString += "<extraText>" + str(extraText) + "</extraText>"
260
- if yPos != "":
261
- annotationString += "<yPos>" + str(yPos) + "</yPos>"
262
- if titleColor != "":
263
- annotationString += "<textColor>" + str(titleColor) + "</textColor>"
264
- if annotationColor != "":
265
- annotationString += "<color>" + str(annotationColor) + "</color>"
266
- if annotationGroup != "":
267
- annotationString += "<userType>" + str(annotationGroup) + "</userType>"
268
- annotationString += ">"
269
-
270
- # command is sent on newline so \n needs to be chnaged to \\n which is changed back just before printing in qps.
271
- annotationString = annotationString.replace("\n", "\\n")
272
- logging.debug("Time sending to QPS:" + str(annotationTime))
273
- return self.connectionObj.qps.sendCmdVerbose(
274
- "$" + annotationType + " " + str(annotationTime) + " " + annotationString)
275
269
 
276
270
  def addComment(self, title, commentTime=0, extraText="", yPos="", titleColor="", commentColor="", annotationType="",
277
- annotationGroup=""):
271
+ annotationGroup="", timeFormat="unix"):
278
272
  # Comments are just annotations that do not affect the statistics grid.
279
273
  # This function was kept to be backwards compatible and is a simple pass through to add annotation.
280
274
  if annotationType == "":
281
275
  annotationType = "comment"
282
276
  return self.addAnnotation(title=title, annotationTime=commentTime, extraText=extraText, yPos=yPos,
283
277
  titleColor=titleColor, annotationColor=commentColor, annotationType=annotationType,
284
- annotationGroup=annotationGroup)
278
+ annotationGroup=annotationGroup, timeFormat=timeFormat)
285
279
 
286
280
  def saveCSV(self, filePath, linesPerFile=None, cr=None, delimiter=None, timeout=60):
287
281
  """
@@ -378,7 +372,7 @@ class quarchStream:
378
372
  self.hideChannel("smclk:digital")
379
373
  self.hideChannel("smdat:digital")
380
374
 
381
- # function to add a data point the the stream
375
+ # function to add a data point to the stream
382
376
  # time value will default to current time if none passed
383
377
  def addDataPoint(self, channelName, groupName, dataValue, dataPointTime=0, timeFormat="unix"):
384
378
  '''
@@ -386,13 +380,14 @@ class quarchStream:
386
380
  groupName - str
387
381
  dataValue - int/float value of the data point
388
382
  dataPointTime=0 - time of the data point
389
- timeFormat="unix" - the format of the given time
383
+ timeFormat="unix" - the format of the given time ["elapsed"|"unix"]
390
384
  '''
391
385
  if dataPointTime == None or dataPointTime == 0:
392
386
  dataPointTime = qpsNowStr()
393
387
  else:
394
- dataPointTime = toQpsTimeStamp(dataPointTime)
395
-
388
+ dataPointTime = int(dataPointTime)
389
+ logging.warning("$stream data add " + channelName + " " + groupName + " " + str(dataPointTime) + " " + str(
390
+ dataValue) + " " + timeFormat)
396
391
  self.connectionObj.qps.sendCmdVerbose(
397
392
  "$stream data add " + channelName + " " + groupName + " " + str(dataPointTime) + " " + str(
398
393
  dataValue) + " " + timeFormat)