cgse 2024.7.0__py3-none-any.whl → 2025.0.1__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 (664) hide show
  1. README.md +27 -0
  2. bump.py +85 -0
  3. cgse-2025.0.1.dist-info/METADATA +38 -0
  4. cgse-2025.0.1.dist-info/RECORD +5 -0
  5. {cgse-2024.7.0.dist-info → cgse-2025.0.1.dist-info}/WHEEL +1 -2
  6. cgse-2024.7.0.dist-info/COPYING +0 -674
  7. cgse-2024.7.0.dist-info/COPYING.LESSER +0 -165
  8. cgse-2024.7.0.dist-info/METADATA +0 -144
  9. cgse-2024.7.0.dist-info/RECORD +0 -660
  10. cgse-2024.7.0.dist-info/entry_points.txt +0 -75
  11. cgse-2024.7.0.dist-info/top_level.txt +0 -2
  12. egse/__init__.py +0 -12
  13. egse/__main__.py +0 -32
  14. egse/aeu/aeu.py +0 -5238
  15. egse/aeu/aeu_awg.yaml +0 -265
  16. egse/aeu/aeu_crio.yaml +0 -273
  17. egse/aeu/aeu_cs.py +0 -627
  18. egse/aeu/aeu_devif.py +0 -321
  19. egse/aeu/aeu_main_ui.py +0 -903
  20. egse/aeu/aeu_metrics.py +0 -131
  21. egse/aeu/aeu_protocol.py +0 -463
  22. egse/aeu/aeu_psu.yaml +0 -204
  23. egse/aeu/aeu_ui.py +0 -873
  24. egse/aeu/arbdata/FccdRead.arb +0 -2
  25. egse/aeu/arbdata/FccdRead_min_points.arb +0 -2
  26. egse/aeu/arbdata/HeaterSync_FccdRead.arb +0 -2
  27. egse/aeu/arbdata/HeaterSync_ccdRead25.arb +0 -2
  28. egse/aeu/arbdata/HeaterSync_ccdRead31_25.arb +0 -2
  29. egse/aeu/arbdata/HeaterSync_ccdRead37_50.arb +0 -2
  30. egse/aeu/arbdata/HeaterSync_ccdRead43_75.arb +0 -2
  31. egse/aeu/arbdata/HeaterSync_ccdRead50.arb +0 -2
  32. egse/aeu/arbdata/Heater_FccdRead_min_points.arb +0 -2
  33. egse/aeu/arbdata/ccdRead25.arb +0 -2
  34. egse/aeu/arbdata/ccdRead25_150ms.arb +0 -2
  35. egse/aeu/arbdata/ccdRead31_25.arb +0 -2
  36. egse/aeu/arbdata/ccdRead31_25_150ms.arb +0 -2
  37. egse/aeu/arbdata/ccdRead37_50.arb +0 -2
  38. egse/aeu/arbdata/ccdRead37_50_150ms.arb +0 -2
  39. egse/aeu/arbdata/ccdRead43_75.arb +0 -2
  40. egse/aeu/arbdata/ccdRead43_75_150ms.arb +0 -2
  41. egse/aeu/arbdata/ccdRead50.arb +0 -2
  42. egse/aeu/arbdata/ccdRead50_150ms.arb +0 -2
  43. egse/alert/__init__.py +0 -1049
  44. egse/alert/alertman.yaml +0 -37
  45. egse/alert/alertman_cs.py +0 -233
  46. egse/alert/alertman_ui.py +0 -600
  47. egse/alert/gsm/beaglebone.py +0 -138
  48. egse/alert/gsm/beaglebone.yaml +0 -51
  49. egse/alert/gsm/beaglebone_cs.py +0 -108
  50. egse/alert/gsm/beaglebone_devif.py +0 -122
  51. egse/alert/gsm/beaglebone_protocol.py +0 -46
  52. egse/bits.py +0 -318
  53. egse/camera.py +0 -44
  54. egse/collimator/__init__.py +0 -0
  55. egse/collimator/fcul/__init__.py +0 -0
  56. egse/collimator/fcul/ogse.py +0 -1077
  57. egse/collimator/fcul/ogse.yaml +0 -14
  58. egse/collimator/fcul/ogse_cs.py +0 -154
  59. egse/collimator/fcul/ogse_devif.py +0 -358
  60. egse/collimator/fcul/ogse_protocol.py +0 -132
  61. egse/collimator/fcul/ogse_sim.py +0 -431
  62. egse/collimator/fcul/ogse_ui.py +0 -1108
  63. egse/command.py +0 -699
  64. egse/config.py +0 -410
  65. egse/confman/__init__.py +0 -1058
  66. egse/confman/confman.yaml +0 -70
  67. egse/confman/confman_cs.py +0 -240
  68. egse/confman/confman_ui.py +0 -381
  69. egse/confman/setup_ui.py +0 -565
  70. egse/control.py +0 -632
  71. egse/coordinates/__init__.py +0 -534
  72. egse/coordinates/avoidance.py +0 -100
  73. egse/coordinates/cslmodel.py +0 -127
  74. egse/coordinates/laser_tracker_to_dict.py +0 -122
  75. egse/coordinates/point.py +0 -707
  76. egse/coordinates/pyplot.py +0 -194
  77. egse/coordinates/referenceFrame.py +0 -1279
  78. egse/coordinates/refmodel.py +0 -737
  79. egse/coordinates/rotationMatrix.py +0 -85
  80. egse/coordinates/transform3d_addon.py +0 -419
  81. egse/csl/__init__.py +0 -50
  82. egse/csl/commanding.py +0 -78
  83. egse/csl/icons/hexapod-connected-selected.svg +0 -30
  84. egse/csl/icons/hexapod-connected.svg +0 -30
  85. egse/csl/icons/hexapod-homing-selected.svg +0 -68
  86. egse/csl/icons/hexapod-homing.svg +0 -68
  87. egse/csl/icons/hexapod-retract-selected.svg +0 -56
  88. egse/csl/icons/hexapod-retract.svg +0 -51
  89. egse/csl/icons/hexapod-zero-selected.svg +0 -56
  90. egse/csl/icons/hexapod-zero.svg +0 -56
  91. egse/csl/icons/logo-puna.svg +0 -92
  92. egse/csl/icons/stop.svg +0 -1
  93. egse/csl/initialisation.py +0 -102
  94. egse/csl/mech_pos_settings.yaml +0 -18
  95. egse/das.py +0 -1240
  96. egse/das.yaml +0 -7
  97. egse/data/conf/SETUP_CSL_00000_170620_150000.yaml +0 -5
  98. egse/data/conf/SETUP_CSL_00001_170620_151010.yaml +0 -69
  99. egse/data/conf/SETUP_CSL_00002_170620_151020.yaml +0 -69
  100. egse/data/conf/SETUP_CSL_00003_170620_151030.yaml +0 -69
  101. egse/data/conf/SETUP_CSL_00004_170620_151040.yaml +0 -69
  102. egse/data/conf/SETUP_CSL_00005_170620_151050.yaml +0 -69
  103. egse/data/conf/SETUP_CSL_00006_170620_151060.yaml +0 -69
  104. egse/data/conf/SETUP_CSL_00007_170620_151070.yaml +0 -69
  105. egse/data/conf/SETUP_CSL_00008_170620_151080.yaml +0 -75
  106. egse/data/conf/SETUP_CSL_00010_210308_083016.yaml +0 -138
  107. egse/data/conf/SETUP_INTA_00000_170620_150000.yaml +0 -4
  108. egse/data/conf/SETUP_SRON_00000_170620_150000.yaml +0 -4
  109. egse/decorators.py +0 -514
  110. egse/device.py +0 -269
  111. egse/dpu/__init__.py +0 -2698
  112. egse/dpu/ccd_ui.py +0 -514
  113. egse/dpu/dpu.py +0 -783
  114. egse/dpu/dpu.yaml +0 -153
  115. egse/dpu/dpu_cs.py +0 -272
  116. egse/dpu/dpu_ui.py +0 -671
  117. egse/dpu/fitsgen.py +0 -2096
  118. egse/dpu/fitsgen_ui.py +0 -399
  119. egse/dpu/hdf5_model.py +0 -332
  120. egse/dpu/hdf5_ui.py +0 -277
  121. egse/dpu/hdf5_viewer.py +0 -506
  122. egse/dpu/hk_ui.py +0 -468
  123. egse/dpu_commands.py +0 -81
  124. egse/dsi/__init__.py +0 -33
  125. egse/dsi/_libesl.py +0 -232
  126. egse/dsi/constants.py +0 -296
  127. egse/dsi/esl.py +0 -630
  128. egse/dsi/rmap.py +0 -444
  129. egse/dsi/rmapci.py +0 -39
  130. egse/dsi/spw.py +0 -335
  131. egse/dsi/spw_state.py +0 -29
  132. egse/dummy.py +0 -318
  133. egse/dyndummy.py +0 -179
  134. egse/env.py +0 -278
  135. egse/exceptions.py +0 -88
  136. egse/fdir/__init__.py +0 -26
  137. egse/fdir/fdir_manager.py +0 -85
  138. egse/fdir/fdir_manager.yaml +0 -37
  139. egse/fdir/fdir_manager_controller.py +0 -136
  140. egse/fdir/fdir_manager_cs.py +0 -164
  141. egse/fdir/fdir_manager_interface.py +0 -15
  142. egse/fdir/fdir_remote.py +0 -73
  143. egse/fdir/fdir_remote.yaml +0 -30
  144. egse/fdir/fdir_remote_controller.py +0 -30
  145. egse/fdir/fdir_remote_cs.py +0 -94
  146. egse/fdir/fdir_remote_interface.py +0 -9
  147. egse/fdir/fdir_remote_popup.py +0 -26
  148. egse/fee/__init__.py +0 -106
  149. egse/fee/f_fee_register.yaml +0 -43
  150. egse/fee/feesim.py +0 -914
  151. egse/fee/n_fee_hk.py +0 -768
  152. egse/fee/nfee.py +0 -188
  153. egse/filterwheel/__init__.py +0 -4
  154. egse/filterwheel/eksma/__init__.py +0 -49
  155. egse/filterwheel/eksma/fw8smc4.py +0 -657
  156. egse/filterwheel/eksma/fw8smc4.yaml +0 -121
  157. egse/filterwheel/eksma/fw8smc4_cs.py +0 -144
  158. egse/filterwheel/eksma/fw8smc4_devif.py +0 -473
  159. egse/filterwheel/eksma/fw8smc4_protocol.py +0 -82
  160. egse/filterwheel/eksma/fw8smc4_ui.py +0 -940
  161. egse/filterwheel/eksma/fw8smc5.py +0 -115
  162. egse/filterwheel/eksma/fw8smc5.yaml +0 -105
  163. egse/filterwheel/eksma/fw8smc5_controller.py +0 -307
  164. egse/filterwheel/eksma/fw8smc5_cs.py +0 -141
  165. egse/filterwheel/eksma/fw8smc5_interface.py +0 -65
  166. egse/filterwheel/eksma/fw8smc5_simulator.py +0 -29
  167. egse/filterwheel/eksma/fw8smc5_ui.py +0 -1065
  168. egse/filterwheel/eksma/testpythonfw.py +0 -215
  169. egse/fov/__init__.py +0 -65
  170. egse/fov/fov_hk.py +0 -710
  171. egse/fov/fov_ui.py +0 -859
  172. egse/fov/fov_ui_controller.py +0 -140
  173. egse/fov/fov_ui_model.py +0 -200
  174. egse/fov/fov_ui_view.py +0 -345
  175. egse/gimbal/__init__.py +0 -32
  176. egse/gimbal/symetrie/__init__.py +0 -26
  177. egse/gimbal/symetrie/alpha.py +0 -586
  178. egse/gimbal/symetrie/generic_gimbal_ui.py +0 -1521
  179. egse/gimbal/symetrie/gimbal.py +0 -877
  180. egse/gimbal/symetrie/gimbal.yaml +0 -168
  181. egse/gimbal/symetrie/gimbal_cs.py +0 -183
  182. egse/gimbal/symetrie/gimbal_protocol.py +0 -138
  183. egse/gimbal/symetrie/gimbal_ui.py +0 -361
  184. egse/gimbal/symetrie/pmac.py +0 -1006
  185. egse/gimbal/symetrie/pmac_regex.py +0 -83
  186. egse/graph.py +0 -132
  187. egse/gui/__init__.py +0 -47
  188. egse/gui/buttons.py +0 -378
  189. egse/gui/focalplane.py +0 -1285
  190. egse/gui/formatter.py +0 -10
  191. egse/gui/led.py +0 -162
  192. egse/gui/limitswitch.py +0 -143
  193. egse/gui/mechanisms.py +0 -587
  194. egse/gui/states.py +0 -148
  195. egse/gui/stripchart.py +0 -729
  196. egse/gui/styles.qss +0 -48
  197. egse/gui/switch.py +0 -112
  198. egse/h5.py +0 -274
  199. egse/help/__init__.py +0 -0
  200. egse/help/help_ui.py +0 -126
  201. egse/hexapod/__init__.py +0 -32
  202. egse/hexapod/symetrie/__init__.py +0 -137
  203. egse/hexapod/symetrie/alpha.py +0 -874
  204. egse/hexapod/symetrie/dynalpha.py +0 -1387
  205. egse/hexapod/symetrie/hexapod_ui.py +0 -1516
  206. egse/hexapod/symetrie/pmac.py +0 -1010
  207. egse/hexapod/symetrie/pmac_regex.py +0 -83
  208. egse/hexapod/symetrie/puna.py +0 -1167
  209. egse/hexapod/symetrie/puna.yaml +0 -193
  210. egse/hexapod/symetrie/puna_cs.py +0 -195
  211. egse/hexapod/symetrie/puna_protocol.py +0 -134
  212. egse/hexapod/symetrie/puna_ui.py +0 -433
  213. egse/hexapod/symetrie/punaplus.py +0 -107
  214. egse/hexapod/symetrie/zonda.py +0 -872
  215. egse/hexapod/symetrie/zonda.yaml +0 -337
  216. egse/hexapod/symetrie/zonda_cs.py +0 -172
  217. egse/hexapod/symetrie/zonda_devif.py +0 -414
  218. egse/hexapod/symetrie/zonda_protocol.py +0 -123
  219. egse/hexapod/symetrie/zonda_ui.py +0 -449
  220. egse/hk.py +0 -791
  221. egse/icons/aeu-cs-start.svg +0 -117
  222. egse/icons/aeu-cs-stop.svg +0 -118
  223. egse/icons/aeu-cs.svg +0 -107
  224. egse/icons/aeu_cs-started.svg +0 -112
  225. egse/icons/aeu_cs-stopped.svg +0 -112
  226. egse/icons/aeu_cs.svg +0 -55
  227. egse/icons/alert.svg +0 -1
  228. egse/icons/arrow-double-left.png +0 -0
  229. egse/icons/arrow-double-right.png +0 -0
  230. egse/icons/arrow-up.svg +0 -11
  231. egse/icons/backward.svg +0 -1
  232. egse/icons/busy.svg +0 -1
  233. egse/icons/cleaning.svg +0 -115
  234. egse/icons/color-scheme.svg +0 -1
  235. egse/icons/cs-connected-alert.svg +0 -91
  236. egse/icons/cs-connected-disabled.svg +0 -43
  237. egse/icons/cs-connected.svg +0 -89
  238. egse/icons/cs-not-connected.svg +0 -44
  239. egse/icons/double-left-arrow.svg +0 -1
  240. egse/icons/double-right-arrow.svg +0 -1
  241. egse/icons/erase-disabled.svg +0 -19
  242. egse/icons/erase.svg +0 -59
  243. egse/icons/fitsgen-start.svg +0 -47
  244. egse/icons/fitsgen-stop.svg +0 -48
  245. egse/icons/fitsgen.svg +0 -1
  246. egse/icons/forward.svg +0 -1
  247. egse/icons/fov-hk-start.svg +0 -33
  248. egse/icons/fov-hk-stop.svg +0 -37
  249. egse/icons/fov-hk.svg +0 -1
  250. egse/icons/front-desk.svg +0 -1
  251. egse/icons/home-actioned.svg +0 -15
  252. egse/icons/home-disabled.svg +0 -15
  253. egse/icons/home.svg +0 -13
  254. egse/icons/info.svg +0 -1
  255. egse/icons/invalid.png +0 -0
  256. egse/icons/led-green.svg +0 -20
  257. egse/icons/led-grey.svg +0 -20
  258. egse/icons/led-orange.svg +0 -20
  259. egse/icons/led-red.svg +0 -20
  260. egse/icons/led-square-green.svg +0 -134
  261. egse/icons/led-square-grey.svg +0 -134
  262. egse/icons/led-square-orange.svg +0 -134
  263. egse/icons/led-square-red.svg +0 -134
  264. egse/icons/limit-switch-all-green.svg +0 -115
  265. egse/icons/limit-switch-all-red.svg +0 -117
  266. egse/icons/limit-switch-el+.svg +0 -116
  267. egse/icons/limit-switch-el-.svg +0 -117
  268. egse/icons/location-marker.svg +0 -1
  269. egse/icons/logo-dpu.svg +0 -48
  270. egse/icons/logo-gimbal.svg +0 -112
  271. egse/icons/logo-huber.svg +0 -23
  272. egse/icons/logo-ogse.svg +0 -31
  273. egse/icons/logo-puna.svg +0 -92
  274. egse/icons/logo-tcs.svg +0 -29
  275. egse/icons/logo-zonda.svg +0 -66
  276. egse/icons/maximize.svg +0 -1
  277. egse/icons/meter.svg +0 -1
  278. egse/icons/more.svg +0 -45
  279. egse/icons/n-fee-hk-start.svg +0 -24
  280. egse/icons/n-fee-hk-stop.svg +0 -25
  281. egse/icons/n-fee-hk.svg +0 -83
  282. egse/icons/observing-off.svg +0 -46
  283. egse/icons/observing-on.svg +0 -46
  284. egse/icons/open-document-hdf5.png +0 -0
  285. egse/icons/open-document-hdf5.svg +0 -21
  286. egse/icons/ops-mode.svg +0 -1
  287. egse/icons/play-green.svg +0 -17
  288. egse/icons/plugged-disabled.svg +0 -27
  289. egse/icons/plugged.svg +0 -21
  290. egse/icons/pm_ui.svg +0 -1
  291. egse/icons/power-button-green.svg +0 -27
  292. egse/icons/power-button-red.svg +0 -27
  293. egse/icons/power-button.svg +0 -27
  294. egse/icons/radar.svg +0 -1
  295. egse/icons/radioactive.svg +0 -2
  296. egse/icons/reload.svg +0 -1
  297. egse/icons/remote-control-off.svg +0 -28
  298. egse/icons/remote-control-on.svg +0 -28
  299. egse/icons/repeat-blue.svg +0 -15
  300. egse/icons/repeat.svg +0 -1
  301. egse/icons/settings.svg +0 -1
  302. egse/icons/shrink.svg +0 -1
  303. egse/icons/shutter.svg +0 -1
  304. egse/icons/sign-off.svg +0 -1
  305. egse/icons/sign-on.svg +0 -1
  306. egse/icons/sim-mode.svg +0 -1
  307. egse/icons/small-buttons-go.svg +0 -20
  308. egse/icons/small-buttons-minus.svg +0 -51
  309. egse/icons/small-buttons-plus.svg +0 -51
  310. egse/icons/sponge.svg +0 -220
  311. egse/icons/start-button-disabled.svg +0 -84
  312. egse/icons/start-button.svg +0 -50
  313. egse/icons/stop-button-disabled.svg +0 -84
  314. egse/icons/stop-button.svg +0 -50
  315. egse/icons/stop-red.svg +0 -17
  316. egse/icons/stop.svg +0 -1
  317. egse/icons/switch-disabled-square.svg +0 -87
  318. egse/icons/switch-disabled.svg +0 -15
  319. egse/icons/switch-off-square.svg +0 -87
  320. egse/icons/switch-off.svg +0 -72
  321. egse/icons/switch-on-square.svg +0 -87
  322. egse/icons/switch-on.svg +0 -61
  323. egse/icons/temperature-control.svg +0 -44
  324. egse/icons/th_ui_logo.svg +0 -1
  325. egse/icons/unplugged.svg +0 -23
  326. egse/icons/unvalid.png +0 -0
  327. egse/icons/user-interface.svg +0 -1
  328. egse/icons/vacuum.svg +0 -1
  329. egse/icons/valid.png +0 -0
  330. egse/icons/zoom-to-pixel-dark.svg +0 -64
  331. egse/icons/zoom-to-pixel-white.svg +0 -36
  332. egse/images/big-rotation-stage.png +0 -0
  333. egse/images/connected-100.png +0 -0
  334. egse/images/cross.svg +0 -6
  335. egse/images/disconnected-100.png +0 -0
  336. egse/images/gui-icon.png +0 -0
  337. egse/images/home.svg +0 -6
  338. egse/images/info-icon.png +0 -0
  339. egse/images/led-black.svg +0 -89
  340. egse/images/led-green.svg +0 -85
  341. egse/images/led-orange.svg +0 -85
  342. egse/images/led-red.svg +0 -85
  343. egse/images/load-icon.png +0 -0
  344. egse/images/load-setup.png +0 -0
  345. egse/images/load.png +0 -0
  346. egse/images/pause.png +0 -0
  347. egse/images/play-button.svg +0 -8
  348. egse/images/play.png +0 -0
  349. egse/images/process-status.png +0 -0
  350. egse/images/restart.png +0 -0
  351. egse/images/search.png +0 -0
  352. egse/images/sma.png +0 -0
  353. egse/images/start.png +0 -0
  354. egse/images/stop-button.svg +0 -8
  355. egse/images/stop.png +0 -0
  356. egse/images/switch-off.svg +0 -48
  357. egse/images/switch-on.svg +0 -48
  358. egse/images/undo.png +0 -0
  359. egse/images/update-button.svg +0 -11
  360. egse/imageviewer/exposureselection.py +0 -475
  361. egse/imageviewer/imageviewer.py +0 -198
  362. egse/imageviewer/matchfocalplane.py +0 -179
  363. egse/imageviewer/subfieldposition.py +0 -133
  364. egse/lampcontrol/__init__.py +0 -4
  365. egse/lampcontrol/beaglebone/beaglebone.py +0 -178
  366. egse/lampcontrol/beaglebone/beaglebone.yaml +0 -62
  367. egse/lampcontrol/beaglebone/beaglebone_cs.py +0 -106
  368. egse/lampcontrol/beaglebone/beaglebone_devif.py +0 -150
  369. egse/lampcontrol/beaglebone/beaglebone_protocol.py +0 -73
  370. egse/lampcontrol/energetiq/__init__.py +0 -22
  371. egse/lampcontrol/energetiq/eq99.yaml +0 -98
  372. egse/lampcontrol/energetiq/lampEQ99.py +0 -283
  373. egse/lampcontrol/energetiq/lampEQ99_cs.py +0 -128
  374. egse/lampcontrol/energetiq/lampEQ99_devif.py +0 -158
  375. egse/lampcontrol/energetiq/lampEQ99_encode_decode_errors.py +0 -73
  376. egse/lampcontrol/energetiq/lampEQ99_protocol.py +0 -71
  377. egse/lampcontrol/energetiq/lampEQ99_ui.py +0 -465
  378. egse/lib/CentOS-7/EtherSpaceLink_v34_86.dylib +0 -0
  379. egse/lib/CentOS-8/ESL-RMAP_v34_86.dylib +0 -0
  380. egse/lib/CentOS-8/EtherSpaceLink_v34_86.dylib +0 -0
  381. egse/lib/Debian/ESL-RMAP_v34_86.dylib +0 -0
  382. egse/lib/Debian/EtherSpaceLink_v34_86.dylib +0 -0
  383. egse/lib/Debian/libetherspacelink_v35_21.dylib +0 -0
  384. egse/lib/Linux/ESL-RMAP_v34_86.dylib +0 -0
  385. egse/lib/Linux/EtherSpaceLink_v34_86.dylib +0 -0
  386. egse/lib/Ubuntu-20/ESL-RMAP_v34_86.dylib +0 -0
  387. egse/lib/Ubuntu-20/EtherSpaceLink_v34_86.dylib +0 -0
  388. egse/lib/gssw/python3-gssw_2.2.3+31f63c9f-1_all.deb +0 -0
  389. egse/lib/ximc/__pycache__/pyximc.cpython-38 2.pyc +0 -0
  390. egse/lib/ximc/__pycache__/pyximc.cpython-38.pyc +0 -0
  391. egse/lib/ximc/libximc.framework/Frameworks/libbindy.dylib +0 -0
  392. egse/lib/ximc/libximc.framework/Frameworks/libxiwrapper.dylib +0 -0
  393. egse/lib/ximc/libximc.framework/Headers/ximc.h +0 -5510
  394. egse/lib/ximc/libximc.framework/Resources/Info.plist +0 -42
  395. egse/lib/ximc/libximc.framework/Resources/keyfile.sqlite +0 -0
  396. egse/lib/ximc/libximc.framework/libbindy.so +0 -0
  397. egse/lib/ximc/libximc.framework/libximc +0 -0
  398. egse/lib/ximc/libximc.framework/libximc.so +0 -0
  399. egse/lib/ximc/libximc.framework/libximc.so.7.0.0 +0 -0
  400. egse/lib/ximc/libximc.framework/libxiwrapper.so +0 -0
  401. egse/lib/ximc/pyximc.py +0 -922
  402. egse/listener.py +0 -179
  403. egse/logger/__init__.py +0 -243
  404. egse/logger/log_cs.py +0 -321
  405. egse/metrics.py +0 -102
  406. egse/mixin.py +0 -464
  407. egse/monitoring.py +0 -95
  408. egse/ni/alarms/__init__.py +0 -26
  409. egse/ni/alarms/cdaq9375.py +0 -300
  410. egse/ni/alarms/cdaq9375.yaml +0 -89
  411. egse/ni/alarms/cdaq9375_cs.py +0 -130
  412. egse/ni/alarms/cdaq9375_devif.py +0 -183
  413. egse/ni/alarms/cdaq9375_protocol.py +0 -48
  414. egse/obs_inspection.py +0 -165
  415. egse/observer.py +0 -41
  416. egse/obsid.py +0 -163
  417. egse/powermeter/__init__.py +0 -0
  418. egse/powermeter/ni/__init__.py +0 -38
  419. egse/powermeter/ni/cdaq9184.py +0 -224
  420. egse/powermeter/ni/cdaq9184.yaml +0 -73
  421. egse/powermeter/ni/cdaq9184_cs.py +0 -130
  422. egse/powermeter/ni/cdaq9184_devif.py +0 -201
  423. egse/powermeter/ni/cdaq9184_protocol.py +0 -48
  424. egse/powermeter/ni/cdaq9184_ui.py +0 -544
  425. egse/powermeter/thorlabs/__init__.py +0 -25
  426. egse/powermeter/thorlabs/pm100a.py +0 -380
  427. egse/powermeter/thorlabs/pm100a.yaml +0 -132
  428. egse/powermeter/thorlabs/pm100a_cs.py +0 -136
  429. egse/powermeter/thorlabs/pm100a_devif.py +0 -127
  430. egse/powermeter/thorlabs/pm100a_protocol.py +0 -80
  431. egse/powermeter/thorlabs/pm100a_ui.py +0 -725
  432. egse/process.py +0 -451
  433. egse/procman/__init__.py +0 -834
  434. egse/procman/cannot_start_process_popup.py +0 -43
  435. egse/procman/procman.yaml +0 -49
  436. egse/procman/procman_cs.py +0 -201
  437. egse/procman/procman_ui.py +0 -2081
  438. egse/protocol.py +0 -605
  439. egse/proxy.py +0 -531
  440. egse/randomwalk.py +0 -140
  441. egse/reg.py +0 -585
  442. egse/reload.py +0 -122
  443. egse/reprocess.py +0 -693
  444. egse/resource.py +0 -333
  445. egse/rmap.py +0 -406
  446. egse/rst.py +0 -135
  447. egse/search.py +0 -182
  448. egse/serialdevice.py +0 -190
  449. egse/services.py +0 -247
  450. egse/services.yaml +0 -68
  451. egse/settings.py +0 -379
  452. egse/settings.yaml +0 -980
  453. egse/setup.py +0 -1181
  454. egse/shutter/__init__.py +0 -0
  455. egse/shutter/thorlabs/__init__.py +0 -19
  456. egse/shutter/thorlabs/ksc101.py +0 -205
  457. egse/shutter/thorlabs/ksc101.yaml +0 -105
  458. egse/shutter/thorlabs/ksc101_cs.py +0 -136
  459. egse/shutter/thorlabs/ksc101_devif.py +0 -201
  460. egse/shutter/thorlabs/ksc101_protocol.py +0 -71
  461. egse/shutter/thorlabs/ksc101_ui.py +0 -548
  462. egse/shutter/thorlabs/sc10.py +0 -82
  463. egse/shutter/thorlabs/sc10.yaml +0 -52
  464. egse/shutter/thorlabs/sc10_controller.py +0 -81
  465. egse/shutter/thorlabs/sc10_cs.py +0 -108
  466. egse/shutter/thorlabs/sc10_interface.py +0 -25
  467. egse/shutter/thorlabs/sc10_simulator.py +0 -30
  468. egse/simulator.py +0 -41
  469. egse/slack.py +0 -61
  470. egse/socketdevice.py +0 -218
  471. egse/sockets.py +0 -218
  472. egse/spw.py +0 -1401
  473. egse/stages/__init__.py +0 -12
  474. egse/stages/aerotech/ensemble.py +0 -245
  475. egse/stages/aerotech/ensemble.yaml +0 -205
  476. egse/stages/aerotech/ensemble_controller.py +0 -275
  477. egse/stages/aerotech/ensemble_cs.py +0 -110
  478. egse/stages/aerotech/ensemble_interface.py +0 -132
  479. egse/stages/aerotech/ensemble_parameters.py +0 -433
  480. egse/stages/aerotech/ensemble_simulator.py +0 -27
  481. egse/stages/aerotech/mgse_sim.py +0 -188
  482. egse/stages/arun/smd3.py +0 -110
  483. egse/stages/arun/smd3.yaml +0 -68
  484. egse/stages/arun/smd3_controller.py +0 -470
  485. egse/stages/arun/smd3_cs.py +0 -112
  486. egse/stages/arun/smd3_interface.py +0 -53
  487. egse/stages/arun/smd3_simulator.py +0 -27
  488. egse/stages/arun/smd3_stop.py +0 -16
  489. egse/stages/huber/__init__.py +0 -49
  490. egse/stages/huber/smc9300.py +0 -920
  491. egse/stages/huber/smc9300.yaml +0 -63
  492. egse/stages/huber/smc9300_cs.py +0 -178
  493. egse/stages/huber/smc9300_devif.py +0 -345
  494. egse/stages/huber/smc9300_protocol.py +0 -113
  495. egse/stages/huber/smc9300_sim.py +0 -547
  496. egse/stages/huber/smc9300_ui.py +0 -973
  497. egse/state.py +0 -173
  498. egse/statemachine.py +0 -274
  499. egse/storage/__init__.py +0 -1067
  500. egse/storage/persistence.py +0 -2295
  501. egse/storage/storage.yaml +0 -79
  502. egse/storage/storage_cs.py +0 -231
  503. egse/styles/dark.qss +0 -343
  504. egse/styles/default.qss +0 -48
  505. egse/synoptics/__init__.py +0 -417
  506. egse/synoptics/syn.yaml +0 -9
  507. egse/synoptics/syn_cs.py +0 -195
  508. egse/system.py +0 -1611
  509. egse/tcs/__init__.py +0 -14
  510. egse/tcs/tcs.py +0 -879
  511. egse/tcs/tcs.yaml +0 -14
  512. egse/tcs/tcs_cs.py +0 -202
  513. egse/tcs/tcs_devif.py +0 -292
  514. egse/tcs/tcs_protocol.py +0 -180
  515. egse/tcs/tcs_sim.py +0 -177
  516. egse/tcs/tcs_ui.py +0 -543
  517. egse/tdms.py +0 -171
  518. egse/tempcontrol/__init__.py +0 -23
  519. egse/tempcontrol/agilent/agilent34970.py +0 -109
  520. egse/tempcontrol/agilent/agilent34970.yaml +0 -44
  521. egse/tempcontrol/agilent/agilent34970_cs.py +0 -114
  522. egse/tempcontrol/agilent/agilent34970_devif.py +0 -182
  523. egse/tempcontrol/agilent/agilent34970_protocol.py +0 -96
  524. egse/tempcontrol/agilent/agilent34972.py +0 -111
  525. egse/tempcontrol/agilent/agilent34972.yaml +0 -44
  526. egse/tempcontrol/agilent/agilent34972_cs.py +0 -115
  527. egse/tempcontrol/agilent/agilent34972_devif.py +0 -189
  528. egse/tempcontrol/agilent/agilent34972_protocol.py +0 -98
  529. egse/tempcontrol/beaglebone/beaglebone.py +0 -341
  530. egse/tempcontrol/beaglebone/beaglebone.yaml +0 -110
  531. egse/tempcontrol/beaglebone/beaglebone_cs.py +0 -117
  532. egse/tempcontrol/beaglebone/beaglebone_protocol.py +0 -134
  533. egse/tempcontrol/beaglebone/beaglebone_ui.py +0 -674
  534. egse/tempcontrol/digalox/digalox.py +0 -115
  535. egse/tempcontrol/digalox/digalox.yaml +0 -36
  536. egse/tempcontrol/digalox/digalox_cs.py +0 -108
  537. egse/tempcontrol/digalox/digalox_protocol.py +0 -56
  538. egse/tempcontrol/keithley/__init__.py +0 -33
  539. egse/tempcontrol/keithley/daq6510.py +0 -662
  540. egse/tempcontrol/keithley/daq6510.yaml +0 -105
  541. egse/tempcontrol/keithley/daq6510_cs.py +0 -163
  542. egse/tempcontrol/keithley/daq6510_devif.py +0 -343
  543. egse/tempcontrol/keithley/daq6510_protocol.py +0 -79
  544. egse/tempcontrol/keithley/daq6510_sim.py +0 -186
  545. egse/tempcontrol/lakeshore/__init__.py +0 -33
  546. egse/tempcontrol/lakeshore/lsci.py +0 -361
  547. egse/tempcontrol/lakeshore/lsci.yaml +0 -162
  548. egse/tempcontrol/lakeshore/lsci_cs.py +0 -174
  549. egse/tempcontrol/lakeshore/lsci_devif.py +0 -292
  550. egse/tempcontrol/lakeshore/lsci_protocol.py +0 -76
  551. egse/tempcontrol/lakeshore/lsci_ui.py +0 -387
  552. egse/tempcontrol/ni/__init__.py +0 -0
  553. egse/tempcontrol/spid/spid.py +0 -109
  554. egse/tempcontrol/spid/spid.yaml +0 -81
  555. egse/tempcontrol/spid/spid_controller.py +0 -279
  556. egse/tempcontrol/spid/spid_cs.py +0 -136
  557. egse/tempcontrol/spid/spid_protocol.py +0 -107
  558. egse/tempcontrol/spid/spid_ui.py +0 -723
  559. egse/tempcontrol/srs/__init__.py +0 -22
  560. egse/tempcontrol/srs/ptc10.py +0 -867
  561. egse/tempcontrol/srs/ptc10.yaml +0 -227
  562. egse/tempcontrol/srs/ptc10_cs.py +0 -128
  563. egse/tempcontrol/srs/ptc10_devif.py +0 -116
  564. egse/tempcontrol/srs/ptc10_protocol.py +0 -39
  565. egse/tempcontrol/srs/ptc10_ui.py +0 -906
  566. egse/ups/apc/apc.py +0 -236
  567. egse/ups/apc/apc.yaml +0 -45
  568. egse/ups/apc/apc_cs.py +0 -101
  569. egse/ups/apc/apc_protocol.py +0 -125
  570. egse/user.yaml +0 -7
  571. egse/vacuum/beaglebone/beaglebone.py +0 -149
  572. egse/vacuum/beaglebone/beaglebone.yaml +0 -44
  573. egse/vacuum/beaglebone/beaglebone_cs.py +0 -108
  574. egse/vacuum/beaglebone/beaglebone_devif.py +0 -159
  575. egse/vacuum/beaglebone/beaglebone_protocol.py +0 -192
  576. egse/vacuum/beaglebone/beaglebone_ui.py +0 -638
  577. egse/vacuum/instrutech/igm402.py +0 -91
  578. egse/vacuum/instrutech/igm402.yaml +0 -90
  579. egse/vacuum/instrutech/igm402_controller.py +0 -124
  580. egse/vacuum/instrutech/igm402_cs.py +0 -108
  581. egse/vacuum/instrutech/igm402_interface.py +0 -49
  582. egse/vacuum/instrutech/igm402_simulator.py +0 -36
  583. egse/vacuum/keller/kellerBus.py +0 -256
  584. egse/vacuum/keller/leo3.py +0 -100
  585. egse/vacuum/keller/leo3.yaml +0 -38
  586. egse/vacuum/keller/leo3_controller.py +0 -81
  587. egse/vacuum/keller/leo3_cs.py +0 -101
  588. egse/vacuum/keller/leo3_interface.py +0 -33
  589. egse/vacuum/mks/evision.py +0 -86
  590. egse/vacuum/mks/evision.yaml +0 -75
  591. egse/vacuum/mks/evision_cs.py +0 -101
  592. egse/vacuum/mks/evision_devif.py +0 -313
  593. egse/vacuum/mks/evision_interface.py +0 -60
  594. egse/vacuum/mks/evision_simulator.py +0 -24
  595. egse/vacuum/mks/evision_ui.py +0 -701
  596. egse/vacuum/pfeiffer/acp40.py +0 -87
  597. egse/vacuum/pfeiffer/acp40.yaml +0 -60
  598. egse/vacuum/pfeiffer/acp40_controller.py +0 -117
  599. egse/vacuum/pfeiffer/acp40_cs.py +0 -109
  600. egse/vacuum/pfeiffer/acp40_interface.py +0 -40
  601. egse/vacuum/pfeiffer/acp40_simulator.py +0 -37
  602. egse/vacuum/pfeiffer/tc400.py +0 -87
  603. egse/vacuum/pfeiffer/tc400.yaml +0 -83
  604. egse/vacuum/pfeiffer/tc400_controller.py +0 -136
  605. egse/vacuum/pfeiffer/tc400_cs.py +0 -109
  606. egse/vacuum/pfeiffer/tc400_interface.py +0 -70
  607. egse/vacuum/pfeiffer/tc400_simulator.py +0 -35
  608. egse/vacuum/pfeiffer/tpg261.py +0 -80
  609. egse/vacuum/pfeiffer/tpg261.yaml +0 -66
  610. egse/vacuum/pfeiffer/tpg261_controller.py +0 -150
  611. egse/vacuum/pfeiffer/tpg261_cs.py +0 -109
  612. egse/vacuum/pfeiffer/tpg261_interface.py +0 -59
  613. egse/vacuum/pfeiffer/tpg261_simulator.py +0 -23
  614. egse/version.py +0 -174
  615. egse/visitedpositions.py +0 -398
  616. egse/windowing.py +0 -213
  617. egse/zmq/__init__.py +0 -28
  618. egse/zmq/spw.py +0 -160
  619. egse/zmq_ser.py +0 -41
  620. scripts/alerts/cold.yaml +0 -278
  621. scripts/alerts/example_alerts.yaml +0 -54
  622. scripts/alerts/transition.yaml +0 -14
  623. scripts/alerts/warm.yaml +0 -49
  624. scripts/analyse_n_fee_hk_data.py +0 -52
  625. scripts/check_hdf5_files.py +0 -192
  626. scripts/check_register_sync.py +0 -47
  627. scripts/check_tcs_calib_coef.py +0 -90
  628. scripts/correct_ccd_cold_temperature_cal.py +0 -157
  629. scripts/create_hdf5_report.py +0 -293
  630. scripts/csl_model.py +0 -420
  631. scripts/csl_restore_setup.py +0 -229
  632. scripts/export-grafana-dashboards.py +0 -49
  633. scripts/fdir/cs_recovery/fdir_cs_recovery.py +0 -54
  634. scripts/fdir/fdir_table.yaml +0 -70
  635. scripts/fdir/fdir_test_recovery.py +0 -10
  636. scripts/fdir/hw_recovery/fdir_agilent_hw_recovery.py +0 -73
  637. scripts/fdir/limit_recovery/fdir_agilent_limit.py +0 -61
  638. scripts/fdir/limit_recovery/fdir_bb_heater_limit.py +0 -59
  639. scripts/fdir/limit_recovery/fdir_ensemble_limit.py +0 -33
  640. scripts/fdir/limit_recovery/fdir_pressure_limit_recovery.py +0 -71
  641. scripts/fix_csv.py +0 -80
  642. scripts/ias/correct_ccd_temp_cal_elfique.py +0 -43
  643. scripts/ias/correct_ccd_temp_cal_floreffe.py +0 -43
  644. scripts/ias/correct_trp_swap_achel.py +0 -199
  645. scripts/inta/correct_ccd_temp_cal_duvel.py +0 -43
  646. scripts/inta/correct_ccd_temp_cal_gueuze.py +0 -43
  647. scripts/n_fee_supply_voltage_calculation.py +0 -92
  648. scripts/playground.py +0 -30
  649. scripts/print_hdf5_hk_data.py +0 -68
  650. scripts/print_register_map.py +0 -43
  651. scripts/remove_lines_between_matches.py +0 -188
  652. scripts/sron/commanding/control_heaters.py +0 -44
  653. scripts/sron/commanding/pumpdown.py +0 -46
  654. scripts/sron/commanding/set_pid_setpoint.py +0 -19
  655. scripts/sron/commanding/shutdown_bbb_heaters.py +0 -10
  656. scripts/sron/commanding/shutdown_pumps.py +0 -33
  657. scripts/sron/correct_mgse_coordinates_brigand_chimay.py +0 -272
  658. scripts/sron/correct_trp_swap_brigand.py +0 -204
  659. scripts/sron/gimbal_conversions.py +0 -75
  660. scripts/sron/tm_gen/tm_gen_agilent.py +0 -37
  661. scripts/sron/tm_gen/tm_gen_heaters.py +0 -4
  662. scripts/sron/tm_gen/tm_gen_spid.py +0 -13
  663. scripts/update_operational_cgse.py +0 -268
  664. scripts/update_operational_cgse_old.py +0 -273
egse/das.py DELETED
@@ -1,1240 +0,0 @@
1
- """
2
- The Data Acquisition System (DAS) is a small application that performs measurements on
3
- different devices.
4
-
5
- For the Keithley DAQ6510, the DAS reads the configuration for the Keithley DAQ6510 from the
6
- Configuration Manager and then configures the device. When no Configuration Manager is
7
- available, the DAS can also be started with a filename to read the configuration from. The file
8
- should have the YAML format.
9
-
10
- ```
11
- Setup:
12
- DAQ6510:
13
- Sensors:
14
- Temperature:
15
- TRANSDUCER: FRTD
16
- "RTD:FOUR": PT100
17
- UNIT: KELVIN
18
- ```
19
-
20
- The Data Acquisition System can be started as follows:
21
-
22
- ```
23
- $ das
24
- Usage: das.py [OPTIONS] COMMAND [ARGS]...
25
-
26
- Options:
27
- --verbose print out more info to the terminal.
28
- --debug set the logging output to DEBUG mode.
29
- --help Show this message and exit.
30
-
31
- Commands:
32
- daq6510 Run the Data Acquisition System for the DAQ6510.
33
- tcs Run the Data Acquisition System for the TCS EGSE.
34
- cdaq Run the Data Acquisition System for the CDAQ EGSE
35
- ```
36
-
37
- """
38
- import logging
39
- import multiprocessing
40
- import re
41
- from datetime import datetime
42
- from datetime import timezone
43
- from pathlib import Path
44
- from typing import List
45
-
46
- import click
47
- import invoke
48
- import itertools
49
- import rich
50
- import sys
51
- import time
52
- from prometheus_client import Gauge
53
- from prometheus_client import start_http_server
54
-
55
- from egse.aeu.aeu import CRIOProxy, OperatingMode
56
- from egse.aeu.aeu import is_aeu_cs_active
57
- from egse.control import Failure
58
- from egse.hk import read_conversion_dict, convert_hk_names
59
- from egse.metrics import define_metrics
60
- from egse.ni.alarms.cdaq9375 import cdaq9375Proxy
61
- from egse.ni.alarms.cdaq9375_cs import is_cdaq9375_cs_active
62
- from egse.powermeter.ni.cdaq9184 import cdaq9184Proxy
63
- from egse.powermeter.ni.cdaq9184_cs import is_cdaq9184_cs_active
64
- from egse.settings import Settings
65
- from egse.setup import Setup, load_setup
66
- from egse.storage import StorageProxy
67
- from egse.storage import is_storage_manager_active
68
- from egse.storage.persistence import CSV
69
- from egse.system import SignalCatcher
70
- from egse.system import flatten_dict
71
- from egse.system import format_datetime
72
- from egse.tcs.tcs import TCSProxy
73
- from egse.tcs.tcs import is_tcs_cs_active
74
- from egse.tempcontrol.keithley.daq6510 import DAQ6510Proxy
75
- from egse.tempcontrol.keithley.daq6510 import count_number_of_channels
76
- from egse.tempcontrol.keithley.daq6510 import get_channel_names
77
- from egse.tempcontrol.keithley.daq6510_cs import is_daq6510_cs_active
78
- from egse.tempcontrol.srs.ptc10 import ptc10Proxy
79
- from egse.tempcontrol.srs.ptc10_cs import is_ptc10_cs_active
80
-
81
- LOGGER = logging.getLogger(__name__)
82
-
83
- DAS = Settings.load("Data Acquisition System")
84
-
85
-
86
- def load_setup_from_input_file(input_file: str):
87
- """Loads a Setup YAML file from disk."""
88
- input_file = Path(input_file).resolve()
89
-
90
- if not input_file.exists():
91
- click.echo(f"ERROR: Input file ({input_file}) doesn't exists.")
92
- return None
93
-
94
- return Setup.from_yaml_file(input_file)
95
-
96
-
97
- class Config:
98
- def __init__(self):
99
- self.verbose = False
100
- self.debug = False
101
-
102
-
103
- pass_config = click.make_pass_decorator(Config, ensure=True)
104
-
105
-
106
- @click.group()
107
- @click.option("--verbose", is_flag=True, help="print out more info to the terminal.")
108
- @click.option("--debug", is_flag=True, help="set the logging output to DEBUG mode.")
109
- @pass_config
110
- def cli(config, verbose, debug):
111
- config.verbose = verbose
112
- config.debug = debug
113
-
114
-
115
- @cli.command()
116
- @click.option(
117
- "--count", default=None, help="how many samples should be taken for each measurement"
118
- )
119
- @click.option(
120
- "--interval", default=None, help="what is the time interval between scans [seconds]"
121
- )
122
- @click.option(
123
- "--delay", default=None, help="what is the time delay between measurements [seconds]"
124
- )
125
- @click.option(
126
- "--channel-list",
127
- default=None,
128
- help='a channel_list as understood by the device, e.g. "(@101:105)"',
129
- )
130
- @click.option(
131
- "--background/--no-background", "-bg/-no-bg", default=False,
132
- help="start the data acquisition in the background"
133
- )
134
- @click.argument("input_file", type=str, required=False)
135
- @pass_config
136
- def daq6510(config, count, interval, delay, channel_list, background: bool, input_file: str):
137
- """
138
- Run the Data Acquisition System for the DAQ6510.
139
-
140
- INPUT_FILE: YAML file containing the Setup for the DAQ6510 [optional]
141
-
142
- Note: When this command runs in the background, send an INTERRUPT SIGNAL with the kill command
143
- to terminate. Never send a KILL SIGNAL (9) because then the process will not properly be
144
- unregistered from the storage manager.
145
-
146
- $ kill -INT <PID>
147
-
148
- """
149
-
150
- if input_file:
151
- setup = load_setup_from_input_file(input_file)
152
- else:
153
- setup = load_setup()
154
-
155
- if setup is None:
156
- LOGGER.error("ERROR: Could not load setup.")
157
- sys.exit(1)
158
-
159
- hk_conversion_table = read_conversion_dict("DAS-DAQ6510", use_site=True, setup=setup)
160
- column_names = list(hk_conversion_table.values())
161
-
162
- if background:
163
- cmd = "das daq6510"
164
- cmd += f" --count {count}"
165
- cmd += f" --interval {interval}"
166
- cmd += f" --delay {delay}"
167
- cmd += f" --channel-list '{channel_list}'" if channel_list else ""
168
- cmd += f" {input_file}" if input_file else ""
169
- LOGGER.info(f"Invoking background command: {cmd}")
170
- invoke.run(cmd, disown=True)
171
- return
172
-
173
- multiprocessing.current_process().name = "das-daq6510"
174
-
175
- if config.debug:
176
- logging.basicConfig(level=logging.DEBUG, format=Settings.LOG_FORMAT_FULL)
177
-
178
- if not is_daq6510_cs_active():
179
- LOGGER.error("The DAQ6510 Control Server is not running, start the 'daq6510_cs' command "
180
- "before running the data acquisition.")
181
- return
182
-
183
- if not is_storage_manager_active():
184
- LOGGER.error("The storage manager is not running, start the core services "
185
- "before running the data acquisition.")
186
- return
187
-
188
- if config.verbose:
189
- LOGGER.info(setup)
190
-
191
- if "DAQ6510" not in setup.gse:
192
- LOGGER.error("ERROR: no DAQ6510 entry in the loaded Setup.")
193
- sys.exit(1)
194
-
195
- if not channel_list:
196
- channel_list = setup.gse.DAQ6510.channels
197
-
198
- if not count:
199
- count = setup.gse.DAQ6510.route.scan.COUNT.SCAN
200
-
201
- if not interval:
202
- interval = setup.gse.DAQ6510.route.scan.INTERVAL
203
-
204
- if not delay:
205
- delay = setup.gse.DAQ6510.route.delay
206
-
207
- count, interval, delay = int(count), int(interval), int(delay)
208
-
209
- channel_count = count_number_of_channels(channel_list)
210
- channel_names = get_channel_names(channel_list)
211
-
212
- DAQ_METRICS = {}
213
- for channel in channel_names:
214
- metrics_name = hk_conversion_table[channel]
215
- DAQ_METRICS[metrics_name] = Gauge(f"{metrics_name}",
216
- f"The current measure for the sensor connected to channel {channel} "
217
- f"({metrics_name}) on the DAQ6510")
218
-
219
- start_http_server(DAS.METRICS_PORT_DAQ6510)
220
-
221
- # Initialize some variables that will be used for registration to the Storage Manager
222
-
223
- origin = "DAS-DAQ6510"
224
- persistence_class = CSV
225
- prep = {
226
- "mode": "a",
227
- "ending": "\n",
228
- "column_names": ["timestamp", *column_names],
229
- }
230
-
231
- killer = SignalCatcher()
232
-
233
- with DAQ6510Proxy() as daq, StorageProxy() as storage:
234
- daq.reset()
235
-
236
- dt = datetime.now(tz=timezone.utc)
237
- daq.set_time(dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second)
238
- LOGGER.info(f"DAQ6510 date and time set: {daq.get_time()}")
239
-
240
- storage.register({"origin": origin, "persistence_class": persistence_class, "prep": prep})
241
-
242
- storage.save({"origin": origin, "data": f"# columns: {column_names}"})
243
-
244
- for sensor in setup.gse.DAQ6510.sensors:
245
- for function in setup.gse.DAQ6510.sensors[sensor]:
246
- sense = {
247
- function.upper(): [
248
- (key, value)
249
- for key, value in flatten_dict(
250
- setup.gse.DAQ6510.sensors[sensor][function]
251
- ).items()
252
- if key != "channels"
253
- ]
254
- }
255
- function_channel_list = setup.gse.DAQ6510.sensors[sensor][function].channels
256
- if config.verbose:
257
- LOGGER.info(f"{sense=}")
258
- LOGGER.info(f"{function_channel_list=}")
259
- daq.configure_sensors(channel_list=function_channel_list, sense=sense)
260
-
261
- LOGGER.info(f"global: {channel_list=}, {channel_count=}")
262
-
263
- daq.setup_measurements(channel_list=channel_list)
264
-
265
- while True:
266
- try:
267
- response = daq.perform_measurement(
268
- channel_list=channel_list, count=count, interval=interval
269
- )
270
-
271
- if killer.term_signal_received:
272
- break
273
-
274
- if not response:
275
- LOGGER.warning("Received an empty response from the DAQ6510, "
276
- "check the connection with the device.")
277
- LOGGER.warning(f"Response: {response=}")
278
- time.sleep(1.0)
279
- continue
280
-
281
- if isinstance(response, Failure):
282
- LOGGER.warning(f"Received a Failure from the DAQ6510 Control Server:")
283
- LOGGER.warning(f"Response: {response}")
284
- time.sleep(1.0)
285
- continue
286
-
287
- # Process and save the response
288
-
289
- # LOGGER.debug(f"{response=}")
290
-
291
- dts = response[0][1].strip()
292
- dt = datetime.strptime(dts[:-3], "%m/%d/%Y %H:%M:%S.%f")
293
- datetime_string = format_datetime(dt.replace(tzinfo=timezone.utc))
294
-
295
- data = {hk_conversion_table[measure[0]]: float(measure[2]) for measure in response}
296
-
297
- data.update({"timestamp": datetime_string})
298
-
299
- # FIXME: we probably need to do something with the units...
300
-
301
- units = [measure[3] for measure in response]
302
-
303
- # LOGGER.debug(f"{data=}")
304
-
305
- storage.save({"origin": origin, "data": data})
306
-
307
- # Now extract channels from the response to update the metrics
308
-
309
- for channel in [measure[0] for measure in response]:
310
- metrics_name = hk_conversion_table[channel]
311
- DAQ_METRICS[metrics_name].set(data[metrics_name])
312
-
313
- # wait for the next measurement to be done (delay)
314
-
315
- time.sleep(delay)
316
-
317
- except KeyboardInterrupt:
318
- LOGGER.debug("Interrupt received, terminating...")
319
- break
320
- except Exception as exc:
321
- LOGGER.warning(f"DAS Exception: {exc}", exc_info=True)
322
- LOGGER.warning("Got a corrupt response from the DAQ6510. "
323
- "Check log messages for 'DAS Exception'.")
324
- time.sleep(1.0)
325
- continue
326
-
327
- storage.unregister({"origin": origin})
328
-
329
- # todo: start PTC10 automatically when when its CS starts. In click options below? background?
330
- # todo: add disable_heater_error
331
- @cli.command()
332
- @click.option(
333
- "--background/--no-background", "-bg/-no-bg", default=False,
334
- help="start the data acquisition in the background"
335
- )
336
- @click.option(
337
- "--user_regulation", default=None, help="activate ptc10 regulation with the given parameter as temperature setpoint (float)"
338
- )
339
- # todo: voir pour option auto_regulation is_fkag=True valeur par défaut
340
- @click.option(
341
- "--auto_regulation", is_flag=True, default=None, help="if this option is given, activate ptc10 regulation with survival mode (i.e. with T_min_NOP as temperature setpoint)"
342
- )
343
- @click.argument("input_file", type=str, required=False)
344
- @pass_config
345
- def ptc10(config, user_regulation: float, auto_regulation: int, background: bool, input_file: str):
346
- """
347
- Run the Data Acquisition System for the DAQ6510.
348
-
349
- INPUT_FILE: YAML file containing the Setup for the DAQ6510 [optional]
350
-
351
- Note: When this command runs in the background, send an INTERRUPT SIGNAL with the kill command
352
- to terminate. Never send a KILL SIGNAL (9) because then the process will not properly be
353
- unregistered from the storage manager.
354
-
355
- $ kill -INT <PID>
356
-
357
- """
358
-
359
- if background:
360
- cmd = "das ptc10"
361
- cmd += f" --user_regulation {user_regulation}"
362
- cmd += f" --auto_regulation {auto_regulation}"
363
- cmd += f" {input_file}" if input_file else ""
364
- LOGGER.info(f"Invoking background command: {cmd}")
365
- invoke.run(cmd, disown=True)
366
- return
367
-
368
- multiprocessing.current_process().name = "das-ptc10"
369
-
370
- if config.debug:
371
- logging.basicConfig(level=logging.DEBUG, format=Settings.LOG_FORMAT_FULL)
372
-
373
- if not is_ptc10_cs_active():
374
- LOGGER.error("The PTC10 Control Server is not running, start the 'ptc10_cs' command "
375
- "before running the data acquisition.")
376
- return
377
-
378
- if not is_storage_manager_active():
379
- LOGGER.error("The storage manager is not running, start the core services "
380
- "before running the data acquisition.")
381
- return
382
-
383
- if input_file:
384
- setup = load_setup_from_input_file(input_file)
385
- else:
386
- setup = load_setup()
387
-
388
- if setup is None:
389
- LOGGER.error("ERROR: Could not load setup.")
390
- sys.exit(1)
391
-
392
- if config.verbose:
393
- LOGGER.info(setup)
394
-
395
- if "PTC10" not in setup.gse:
396
- LOGGER.error("ERROR: no PTC10 entry in the loaded Setup.")
397
- sys.exit(1)
398
-
399
- channel_names = list(setup.gse.PTC10.channel_names.values()) # defined in config file
400
-
401
- # Creation of list HK_names used to store HK.
402
- site_id = setup.site_id # Name of the TH
403
-
404
- HK_names = ["G" + site_id + "_" + sensor_name for sensor_name in channel_names[:4]]
405
- units = ["ampere", "watt", "volt"]
406
- for unit in units:
407
- HK_names.extend(["G" + site_id + "_" + name + "_" + unit for name in channel_names[-3:]])
408
- HK_names.insert(0, HK_names.pop(2)) # I move GIAS_TTS_BiP_01 at the beginning of the list HK_names.
409
- # HK_names is ['GIAS_TTS_BiP_01', 'GIAS_TRP2', 'GIAS_TRP3', 'GIAS_TRP4', 'GIAS_H1_ampere', 'GIAS_H2_ampere', 'GIAS_H3_ampere', 'GIAS_H1_watt', 'GIAS_H2_watt', 'GIAS_H3_watt', 'GIAS_H1_volt', 'GIAS_H2_volt', 'GIAS_H3_volt']
410
-
411
- # Creation of Prometheus METRICS in a dictionnary from TM dictionnary
412
- PTC_METRICS = define_metrics("DAS-PTC10", setup=setup)
413
-
414
- if not list(PTC_METRICS.keys()) == HK_names: # Check if names in setup file (used for HK names) and names defined in TM dictionary for metrics names are same
415
- LOGGER.error("The names of HK defined in the current setup file " + setup.get_id() + " are not the same than those in TM dictionary for metrics")
416
-
417
- start_http_server(DAS.METRICS_PORT_PTC10)
418
-
419
- # Initialize some variables that will be used for registration to the Storage Manager
420
-
421
- origin = "DAS-PTC10"
422
- persistence_class = CSV
423
- prep = {
424
- "mode": "a",
425
- "ending": "\n",
426
- "header": "PTC10 First Connection Tests",
427
- "column_names": ["timestamp", *PTC_METRICS],
428
- }
429
-
430
- killer = SignalCatcher()
431
-
432
- with ptc10Proxy() as ptc, StorageProxy() as storage:
433
-
434
- storage.register({"origin": origin, "persistence_class": persistence_class, "prep": prep})
435
-
436
- # Renaming the names of channels in PTC10 device with names defined in the setup file
437
- old_channel_names = ptc.get_names() # old_channel_names is a tuple of 2 lists with the names of inputs (4 sensors)
438
- # in the first list and the names of outputs (3 heaters) in the second list
439
- old_channel_names = old_channel_names[0] + old_channel_names[1] # Now old_channel_names is a long list of 7 elements (4 inputs/sensors
440
- # and 3 outputs/heaters)
441
- for old_name, new_name in zip(old_channel_names, channel_names):
442
- ptc.set_name(old_name,new_name)
443
-
444
- # Setting the input for each heater
445
- for output_ch, input in zip([1, 2, 3], setup.gse.PTC10.heater_input):
446
- new_input = setup.gse.PTC10.heater_input[input]
447
- ptc.set_heater_input(output_ch, new_input)
448
-
449
- # Configure units before limits (because configuring units modifies limits)
450
- ptc.output_unit(setup.gse.PTC10.heater_unit)
451
-
452
- # Setting limits
453
- low_limit = setup.gse.PTC10.heater_limit.low
454
- high_limit = setup.gse.PTC10.heater_limit.high
455
- for output_ch in [1, 2, 3]:
456
- ptc.output_limit(output_ch, low_limit, high_limit)
457
-
458
- # Setting PID coefficients
459
- i = 0
460
- for pid in setup.gse.PTC10.PID:
461
- PID_list = list(setup.gse.PTC10.PID[pid].values())
462
- i += 1
463
- ptc.set_PID(input_ch=i, output_ch=i, PID=PID_list)
464
-
465
- # Setting the resistance of the heater in Ohm (manually measured with ohmmeter and written in the setup file)
466
- R = setup.gse.PTC10.heater_Ohm
467
-
468
- # Time update from egse server
469
- ptc.update_time()
470
- is_on_time = True
471
-
472
- while True:
473
- try:
474
-
475
- # Update time of PTC10 every first of the month to avoid a time lag after several days and a time desynchronisation.
476
- day = time.gmtime()[2]
477
- if day >= 2:
478
- is_on_time = False
479
- if day == 1 and not is_on_time:
480
- ptc.update_time()
481
- is_on_time = True
482
-
483
- if user_regulation and auto_regulation:
484
- LOGGER.warning("Only 1 option is expected (user_regulation OR auto_regulation) but both were given.\nTerminating... ")
485
- break
486
-
487
- if user_regulation: # If user_regulation is given, then run the function set_stable() with "user_regulation" as temperature setpoint
488
- try:
489
- ptc.set_stable(float(user_regulation))
490
- except ValueError:
491
- LOGGER.warning("ValueError: user_regulation must be a number.\nTerminating...")
492
- break
493
- if auto_regulation: # If auto_regulation is given, then run the function set_survival() (i.e. with T_min_NOP as temperature setpoint)
494
- ptc.set_survival()
495
-
496
- # Acquirement of PTC10 time for HK and PTC10 values (temperatures and heaters)
497
- try:
498
- response = [ptc.get_time()] + ptc.read_temperature() + ptc.read_heater()[0]
499
- # Sometimes randomly PTC10 doesn't return the time and there is a Failure, so to avoid
500
- # a bad type in the column timestamp, if there is a Failure, HK are not saved for this
501
- # time and the code go back at the top of the while loop thanks to exceptions.
502
- except TypeError:
503
- LOGGER.warning("TYPE ERROR")
504
- continue
505
- except ValueError:
506
- LOGGER.warning("VALUE ERROR")
507
- continue
508
-
509
- if killer.term_signal_received:
510
- break
511
-
512
- if not response:
513
- LOGGER.warning("Received an empty response from the PTC10, "
514
- "check the connection with the device.")
515
- LOGGER.warning(f"Response: {response=}")
516
- time.sleep(1.0)
517
- continue
518
-
519
- if isinstance(response, Failure):
520
- LOGGER.warning(f"Received a Failure from the PTC10 Control Server:")
521
- LOGGER.warning(f"Response: {response}")
522
- time.sleep(1.0)
523
- continue
524
-
525
- # Process and save the response
526
-
527
- response.insert(1, response.pop(3)) # I move the value of TTS_BiP_01 at the beginning of the list response.
528
-
529
- # Calculation of power : P = RI²
530
- for i in [5, 6, 7]:
531
- response.append(R * response[i]**2)
532
-
533
- # Calculation of voltage : U = RI
534
- for i in [5, 6, 7]:
535
- response.append(R * response[i])
536
-
537
- hk_dict = {"timestamp": response[0]}
538
- hk_dict.update({k: v for k, v in zip(HK_names, response[1:])})
539
-
540
- LOGGER.debug(f"{response=}")
541
-
542
- LOGGER.debug(hk_dict)
543
-
544
- # Saving HK with PTC10 time as timestamp
545
- storage.save({"origin": origin, "data": hk_dict})
546
-
547
- # Now set the values in the metrics
548
- hk_dict.pop("timestamp")
549
- for key, value in hk_dict.items():
550
- PTC_METRICS[key].set(value)
551
-
552
-
553
- except KeyboardInterrupt:
554
- LOGGER.debug("Interrupt received, terminating...")
555
- break
556
- except Exception as exc:
557
- LOGGER.warning(f"DAS Exception: {exc}", exc_info=True)
558
- LOGGER.warning("Got a corrupt response from the PTC10. "
559
- "Check log messages for 'DAS Exception'.")
560
- time.sleep(1.0)
561
- continue
562
-
563
- ptc.disable_all()
564
- storage.unregister({"origin": origin})
565
-
566
-
567
- @cli.command()
568
- @click.option(
569
- "--use-all-hk", is_flag=True,
570
- help=("Use get_all_housekeeping() method to read telemetry from the TCS EGSE. "
571
- "The device must not be in remote control mode for this.")
572
- )
573
- @click.option(
574
- "--interval", default=10, help="what is the time delay between measurements [seconds]"
575
- )
576
- @click.option(
577
- "--background/--no-background", "-bg/-no-bg", default=False,
578
- help="start the data acquisition in the background"
579
- )
580
- @pass_config
581
- def tcs(config, use_all_hk, interval, background):
582
- """
583
- Run the Data Acquisition System for the TCS EGSE.
584
-
585
- Note: When this command runs in the background, send an INTERRUPT SIGNAL with the kill command
586
- to terminate. Never send a KILL SIGNAL (9) because then the process will not properly be
587
- unregistered from the storage manager.
588
-
589
- $ kill -INT <PID>
590
-
591
- """
592
-
593
- rich.print(
594
- "[red]WARNING[/red]: This function of the DAS has been deprecated and is replaced by the "
595
- "TCSTelemetry process which is automatically started by the tcs_cs. The `das tcs` will be "
596
- "removed shortly.")
597
-
598
- return
599
-
600
- if background:
601
- cmd = "das tcs"
602
- cmd += " --use-all-hk" if use_all_hk else ""
603
- cmd += f" --interval {interval}"
604
- LOGGER.info(f"Invoking background command: {cmd}")
605
- invoke.run(cmd, disown=True)
606
- return
607
-
608
- multiprocessing.current_process().name = "das-tcs"
609
-
610
- if config.debug:
611
- logging.basicConfig(level=logging.DEBUG, format=Settings.LOG_FORMAT_FULL)
612
-
613
- start_http_server(DAS.METRICS_PORT_TCS)
614
-
615
- if not is_tcs_cs_active():
616
- LOGGER.error("The TCS Control Server is not running, start the 'tcs_cs' command "
617
- "before running the data acquisition.")
618
- return
619
-
620
- if not is_storage_manager_active():
621
- LOGGER.error("The storage manager is not running, start the core services "
622
- "before running the data acquisition.")
623
- return
624
-
625
- killer = SignalCatcher()
626
-
627
- with TCSProxy() as tcs_proxy, StorageProxy() as storage:
628
-
629
- # Not all HK parameters are always sent with the periodic telemetry, so we
630
- # use the know parameters names. Since we further on pass the values as a dictionary
631
- # to the storage, values which are not in `names` are silently ignored.
632
-
633
- names = patterns.keys()
634
-
635
- # For each of the names, create also a timestamp column for that name
636
-
637
- columns = list(itertools.chain.from_iterable((x + '_ts', x) for x in names))
638
-
639
- # Initialize some variables that will be used for registration to the Storage Manager
640
- # Use the names in the header of the CSV file as column names.
641
-
642
- origin = "DAS-TCS"
643
- persistence_class = CSV
644
- prep = {
645
- "mode": "a",
646
- "ending": "\n",
647
- "header": "TCS EGSE First Connection Tests",
648
- "column_names": columns,
649
- }
650
-
651
- storage.register({"origin": origin, "persistence_class": persistence_class, "prep": prep})
652
-
653
- while True:
654
- try:
655
- data = tcs_proxy.get_all_housekeeping() if use_all_hk else tcs_proxy.get_data()
656
- if killer.term_signal_received:
657
- break
658
-
659
- if isinstance(data, Failure):
660
- LOGGER.warning(f"Received a Failure from the TCS EGSE Control Server:")
661
- LOGGER.warning(f"Response: {data}")
662
- time.sleep(1.0)
663
- continue
664
-
665
- LOGGER.debug(f"received {len(data or [])} data items")
666
-
667
- if data is None:
668
- continue
669
-
670
- data = process_data(data)
671
- storage.save({"origin": origin, "data": data})
672
-
673
- time.sleep(interval)
674
-
675
- except KeyboardInterrupt:
676
- LOGGER.debug("Interrupt received, terminating...")
677
- break
678
-
679
- storage.unregister({"origin": origin})
680
-
681
-
682
- TCS_AMBIENT_RTD = Gauge(
683
- "tcs_ambient_rtd", "The current ambient temperature on the TCS EGSE"
684
- )
685
- TCS_INTERNAL_RTD = Gauge(
686
- "tcs_internal_rtd", "The current internal temperature off the TCS EGSE"
687
- )
688
- TCS_FEE_RTD_1 = Gauge(
689
- "tcs_fee_rtd_1", "The TRP22 sensor for control channel 1"
690
- )
691
- TCS_FEE_RTD_2 = Gauge(
692
- "tcs_fee_rtd_2", "The TRP22 sensor for control channel 2"
693
- )
694
- TCS_FEE_RTD_3 = Gauge(
695
- "tcs_fee_rtd_3", "The TRP22 sensor for control channel 3"
696
- )
697
- TCS_TOU_RTD_1 = Gauge(
698
- "tcs_tou_rtd_1", "The TRP1 sensor for control channel 1"
699
- )
700
- TCS_TOU_RTD_2 = Gauge(
701
- "tcs_tou_rtd_2", "The TRP1 sensor for control channel 2"
702
- )
703
- TCS_TOU_RTD_3 = Gauge(
704
- "tcs_tou_rtd_3", "The TRP1 sensor for control channel 3"
705
- )
706
- TCS_CH1_IOUT = Gauge(
707
- "tcs_ch1_iout", "channel 1 iout"
708
- )
709
- TCS_CH1_POUT = Gauge(
710
- "tcs_ch1_pout", "channel 1 pout"
711
- )
712
- TCS_CH1_VOUT = Gauge(
713
- "tcs_ch1_vout", "channel 1 pout"
714
- )
715
- TCS_CH2_IOUT = Gauge(
716
- "tcs_ch2_iout", "channel 2 iout"
717
- )
718
- TCS_CH2_POUT = Gauge(
719
- "tcs_ch2_pout", "channel 2 pout"
720
- )
721
- TCS_CH2_VOUT = Gauge(
722
- "tcs_ch2_vout", "channel 2 pout"
723
- )
724
-
725
-
726
- def process_data(data: List) -> dict:
727
- """
728
- Process the output of the `get_data()` and the `get_all_housekeeping()` commands. Telemetry
729
- parameters can occur multiple times, only the last entry is retained.
730
-
731
- This function also updates the metrics that are requested by Prometheus.
732
-
733
- Args:
734
- data: the data as returned by get_data() and get_all_housekeeping().
735
-
736
- Returns:
737
- an up-to-date dictionary with the parameter values and their timestamps.
738
- """
739
-
740
- processed_data = {}
741
-
742
- # Create a proper dictionary with the last updated telemetry values.
743
- # We expect 3 entries: name, date, and value
744
-
745
- for item in data:
746
-
747
- if len(item) == 3:
748
- value = extract_value(item[0], item[2])
749
- processed_data.update({f"{item[0]}_ts": item[1], item[0]: value})
750
- else:
751
- click.echo("WARNING: incorrect format in data response from TCS EGSE.")
752
-
753
- # Fill in the metrics that will be monitored by Prometheus
754
-
755
- for name, metric in (
756
- ("ambient_rtd", TCS_AMBIENT_RTD),
757
- ("internal_rtd", TCS_INTERNAL_RTD),
758
- ("fee_rtd_1", TCS_FEE_RTD_1),
759
- ("fee_rtd_2", TCS_FEE_RTD_2),
760
- ("fee_rtd_3", TCS_FEE_RTD_3),
761
- ("tou_rtd_1", TCS_TOU_RTD_1),
762
- ("tou_rtd_2", TCS_TOU_RTD_2),
763
- ("tou_rtd_3", TCS_TOU_RTD_3),
764
- ("ch1_iout", TCS_CH1_IOUT),
765
- ("ch1_pout", TCS_CH1_POUT),
766
- ("ch1_vout", TCS_CH1_VOUT),
767
- ("ch2_iout", TCS_CH2_IOUT),
768
- ("ch2_pout", TCS_CH2_POUT),
769
- ("ch2_vout", TCS_CH2_VOUT),
770
- ):
771
- if name in processed_data:
772
- metric.set(processed_data[name])
773
-
774
- return processed_data
775
-
776
-
777
- # Define different regex patterns, e.g. for temperature, time, power, etc.
778
-
779
- temperature_pattern = re.compile(r'(.*) ºC')
780
- seconds_pattern = re.compile(r'(.*) s')
781
- milliseconds_pattern = re.compile(r'(.*) ms')
782
- current_pattern = re.compile(r'(.*) A \[(.*) Apk\]')
783
- voltage_pattern = re.compile(r'(.*) V')
784
- voltage_peak_pattern = re.compile(r'(.*) V \[(.*) Vpk\]')
785
- power_pattern = re.compile(r'(.*) mW \[(.*) mWavg\]')
786
- storage_pattern = re.compile(r'\[(.*)\]')
787
- match_all_pattern = re.compile(r'(.*)')
788
-
789
- # Assign parsing patterns to each of the parameters that need specific parsing.
790
-
791
- patterns = {
792
- 'ambient_rtd': temperature_pattern,
793
- 'ch1_clkheater_period': milliseconds_pattern,
794
- 'ch1_clkheater_ticks': seconds_pattern,
795
- 'ch1_iout': current_pattern,
796
- 'ch1_pid_proctime': seconds_pattern,
797
- 'ch1_pid_sp': temperature_pattern,
798
- 'ch1_pid_ts': seconds_pattern,
799
- 'ch1_pout': power_pattern,
800
- 'ch1_pwm_ontime': milliseconds_pattern,
801
- 'ch1_pwm_proctime': seconds_pattern,
802
- 'ch1_tav': temperature_pattern,
803
- 'ch1_vdc': voltage_pattern,
804
- 'ch1_vout': voltage_peak_pattern,
805
- 'ch2_clkheater_period': milliseconds_pattern,
806
- 'ch2_clkheater_ticks': seconds_pattern,
807
- 'ch2_iout': current_pattern,
808
- 'ch2_pid_proctime': seconds_pattern,
809
- 'ch2_pid_sp': temperature_pattern,
810
- 'ch2_pid_ts': seconds_pattern,
811
- 'ch2_pout': power_pattern,
812
- 'ch2_pwm_ontime': milliseconds_pattern,
813
- 'ch2_pwm_proctime': seconds_pattern,
814
- 'ch2_tav': temperature_pattern,
815
- 'ch2_vdc': voltage_pattern,
816
- 'ch2_vout': voltage_peak_pattern,
817
- 'fee_rtd_1': temperature_pattern,
818
- 'fee_rtd_2': temperature_pattern,
819
- 'fee_rtd_3': temperature_pattern,
820
- 'fee_rtd_tav': temperature_pattern,
821
- 'internal_rtd': temperature_pattern,
822
- 'ni9401_external_clkheater_period': seconds_pattern,
823
- 'ni9401_external_clkheater_timeout': seconds_pattern,
824
- 'psu_vdc': voltage_pattern,
825
- 'spare_rtd_1': temperature_pattern,
826
- 'spare_rtd_2': temperature_pattern,
827
- 'spare_rtd_3': temperature_pattern,
828
- 'spare_rtd_tav': temperature_pattern,
829
- 'storage_mmi': storage_pattern,
830
- 'storage_realtime': storage_pattern,
831
- 'tou_rtd_1': temperature_pattern,
832
- 'tou_rtd_2': temperature_pattern,
833
- 'tou_rtd_3': temperature_pattern,
834
- 'tou_rtd_tav': temperature_pattern,
835
- }
836
-
837
-
838
- def extract_value(key, value):
839
- """
840
- Extract the actual value from the string containing the value and unit plus potential
841
- additional info. Parsing is done with dedicated regular expressions per parameter, e.g.
842
- parsing a temperature takes the 'ºC' into account when extracting the actual value.
843
-
844
- Args:
845
- key (str): name of the parameter
846
- value (str): the value as returned by the TCS EGSE
847
- """
848
-
849
- if key not in patterns:
850
- return value
851
-
852
- match = patterns[key].search(value)
853
- if match is not None:
854
- value = match.group(1)
855
- return value
856
-
857
- @cli.command()
858
- @click.option(
859
- "--use-all-hk", is_flag=True,
860
- help=("Use get_all_housekeeping() method to read telemetry from the CDAQ. "
861
- "The device must not be in remote control mode for this.")
862
- )
863
- @click.option(
864
- "--interval", default=1, help="what is the time delay between measurements [seconds]"
865
- )
866
- @click.option(
867
- "--background/--no-background", "-bg/-no-bg", default=False,
868
- help="start the data acquisition in the background"
869
- )
870
- @pass_config
871
- def cdaq(config, use_all_hk, interval, background):
872
- """
873
- Run the Data Acquisition System for the CDAQ.
874
-
875
- INPUT_FILE: YAML file containing the Setup for the CDAQ [optional]
876
-
877
- Note: When this command runs in the background, send an INTERRUPT SIGNAL with the kill command
878
- to terminate. Never send a KILL SIGNAL (9) because then the process will not properly be
879
- unregistered from the storage manager.
880
-
881
- $ kill -INT <PID>
882
-
883
- """
884
-
885
- setup = load_setup()
886
-
887
- if background:
888
- cmd = "das cdaq-photo"
889
- cmd += " --use-all-hk" if use_all_hk else ""
890
- cmd += f" --interval {interval}"
891
- LOGGER.info(f"Invoking background command: {cmd}")
892
- invoke.run(cmd, disown=True)
893
- return
894
-
895
- multiprocessing.current_process().name = "das-cdaq-photodiodes"
896
-
897
- if config.debug:
898
- logging.basicConfig(level=logging.DEBUG, format=Settings.LOG_FORMAT_FULL)
899
-
900
- if not is_cdaq9184_cs_active():
901
- LOGGER.error("The cdaq Control Server is not running, start the 'cdaq_cs' command "
902
- "before running the data acquisition.")
903
- return
904
-
905
- if not is_storage_manager_active():
906
- LOGGER.error("The storage manager is not running, start the core services "
907
- "before running the data acquisition.")
908
- return
909
-
910
- metrics_cdaq = define_metrics("DAS-CDAQ-PHOTODIODES", setup=setup)
911
- hk_names = ["GIAS_OGSE2_PHOTOD_1", "GIAS_OGSE2_PHOTOD_2", "GIAS_OGSE2_TAMPLI_1", "GIAS_OGSE2_TAMPLI_2",
912
- "GIAS_OGSE2_TSPHERE", "GIAS_OGSE2_GAMPLI_1", "GIAS_OGSE2_GAMPLI_2"]
913
-
914
-
915
- # The unit for photodiodes is V, for temperatures is °C and without unit for gains
916
-
917
- start_http_server(DAS.METRICS_PORT_CDAQ)
918
-
919
- # Initialize some variables that will be used for registration to the Storage Manager
920
-
921
- origin = "DAS-CDAQ-PHOTODIODES"
922
- persistence_class = CSV
923
- prep = {
924
- "mode": "a",
925
- "ending": "\n",
926
- "header": "CDAQ First Connection Tests",
927
- "column_names": ["timestamp", *metrics_cdaq],
928
- }
929
-
930
- killer = SignalCatcher()
931
-
932
- with cdaq9184Proxy() as cdaq, StorageProxy() as storage:
933
-
934
- # Use the names in the header of the CSV file as column names.
935
-
936
- storage.register({"origin": origin, "persistence_class": persistence_class, "prep": prep})
937
-
938
- while True:
939
- try:
940
- response = cdaq.read_values()
941
-
942
- if killer.term_signal_received:
943
- break
944
- if not response:
945
- LOGGER.warning("Received an empty response from the CDAQ, "
946
- "check the connection with the device.")
947
- LOGGER.warning(f"Response: {response=}")
948
- time.sleep(1.0)
949
- continue
950
- if isinstance(response, Failure):
951
- LOGGER.warning(f"Received a Failure from the CDAQ Control Server:")
952
- LOGGER.warning(f"Response: {response}")
953
- time.sleep(1.0)
954
- continue
955
-
956
- reformatted_response = reformat_cdaq_values(response)
957
- values = reformatted_response[2:]
958
- hk_dict = {key: value for key, value in zip(hk_names, values)}
959
- timestamp = format_datetime(datetime.strptime(reformatted_response[0] + '-' + reformatted_response[1], "%y/%m/%d-%H:%M:%S.%f"))
960
- data = [timestamp] + values
961
- storage.save({"origin": origin, "data": data})
962
-
963
- for key, value in hk_dict.items():
964
- metrics_cdaq[key].set(value)
965
-
966
- # time.sleep(interval)
967
-
968
- except KeyboardInterrupt:
969
- LOGGER.debug("Interrupt received, terminating...")
970
- break
971
-
972
- except Exception as exc:
973
- LOGGER.warning(f"DAS Exception: {exc}", exc_info=True)
974
- LOGGER.warning("Got a corrupt response from the CDAQ. "
975
- "Check log messages for 'DAS Exception'.")
976
- time.sleep(1.0)
977
- continue
978
-
979
- storage.unregister({"origin": origin})
980
-
981
-
982
- def reformat_cdaq_values(data_to_be_reformatted: list) -> list:
983
- data = data_to_be_reformatted
984
- if len(data) != 35:
985
- LOGGER.error(f"Data received from Labview has not the expected length ({len(data)} but expected 35).")
986
- else:
987
- # The next elements (see the names in the headers) are not wanted so I delete them:
988
- # 1) Filtre_Roue_1, Filtre_Roue_2, Shutter, FEMTO_1_BIAS, FEMTO_2_BIAS, FEMTO_1_Input_Current,
989
- # FEMTO_2_Input_Current (the 7 last elements)
990
- # 2) Temp_4 to Temp_8 (elements from index 16 to 25)
991
- # 3) FEMTO_1_OVERLOAD and FEMTO_2_OVERLOAD (elements at indexes 4, 5, 8 and 9)
992
-
993
- # 1)
994
- del data[-7:]
995
- # 2)
996
- del data[16:26]
997
- # 3)
998
- for i in [9, 8, 5, 4]:
999
- del data[i]
1000
-
1001
- # Only mean is wanted, not deviation. So I delete all deviation elements
1002
- # which are at indexes [3, 5, 7, 9, 11 ( = list(range(3, 12, 2)) )
1003
- for index_to_delete in sorted(list(range(3, 12, 2)), reverse=True): # I delete in the reverse order
1004
- del data[index_to_delete]
1005
-
1006
- # The 2 first elements of data are date as str type. I leave them as str type. I convert the other elements of
1007
- # data (which are relevant values) from str to float.
1008
- data = data[:2] + [float(value) for value in data[2:]]
1009
-
1010
- return data
1011
-
1012
-
1013
- @cli.command()
1014
- @click.option(
1015
- "--background/--no-background", "-bg/-no-bg", default=False,
1016
- help="start the data acquisition in the background"
1017
- )
1018
- @pass_config
1019
- def cdaq_alarms(config, background):
1020
- """
1021
- Run the Data Acquisition System for the CDAQ alarms (CDAQ9375).
1022
-
1023
- INPUT_FILE: YAML file containing the Setup for the CDAQ [optional]
1024
-
1025
- Note: When this command runs in the background, send an INTERRUPT SIGNAL with the kill command
1026
- to terminate. Never send a KILL SIGNAL (9) because then the process will not properly be
1027
- unregistered from the storage manager.
1028
-
1029
- $ kill -INT <PID>
1030
-
1031
- """
1032
-
1033
- setup = load_setup()
1034
-
1035
- if background:
1036
- cmd = "das cdaq-alarms"
1037
- LOGGER.info(f"Invoking background command: {cmd}")
1038
- invoke.run(cmd, disown=True)
1039
- return
1040
-
1041
- multiprocessing.current_process().name = "das-cdaq-alarms"
1042
-
1043
- if config.debug:
1044
- logging.basicConfig(level=logging.DEBUG, format=Settings.LOG_FORMAT_FULL)
1045
-
1046
- if not is_cdaq9375_cs_active():
1047
- LOGGER.error("The cdaq9375 Control Server is not running, start the 'cdaq9375_cs' command "
1048
- "before running the data acquisition.")
1049
- return
1050
-
1051
- if not is_tcs_cs_active():
1052
- LOGGER.error("The TCS Control Server is not running, start the 'tcs_cs' command "
1053
- "before running the data acquisition.")
1054
- return
1055
-
1056
- if not is_aeu_cs_active(name="CRIO", timeout=1):
1057
- LOGGER.error("The AEU Control Server is not running, start the 'aeu_cs' command "
1058
- "before running the data acquisition.")
1059
- return
1060
-
1061
- if not is_storage_manager_active():
1062
- LOGGER.error("The storage manager is not running, start the core services "
1063
- "before running the data acquisition.")
1064
- return
1065
-
1066
- metrics_cdaq_alarms = define_metrics("DAS-CDAQ-ALARMS", setup=setup)
1067
-
1068
- start_http_server(DAS.METRICS_PORT_CDAQ_ALARMS)
1069
-
1070
- # Initialize some variables that will be used for registration to the Storage Manager
1071
-
1072
- origin = "DAS-CDAQ-ALARMS"
1073
- persistence_class = CSV
1074
- prep = {
1075
- "mode": "a",
1076
- "ending": "\n",
1077
- "header": "CDAQ-ALARMS First Connection Tests",
1078
- "column_names": ["timestamp", *metrics_cdaq_alarms],
1079
- }
1080
-
1081
- killer = SignalCatcher()
1082
-
1083
- with cdaq9375Proxy() as cdaq, StorageProxy() as storage, TCSProxy() as tcs_proxy, CRIOProxy() as aeu_crio:
1084
-
1085
- # Use the names in the header of the CSV file as column names.
1086
-
1087
- storage.register({"origin": origin, "persistence_class": persistence_class, "prep": prep})
1088
-
1089
- alarms_temperature = setup.gse.CDAQ_alarms.alarms_temperature
1090
-
1091
- trp1_min_op = alarms_temperature.trp1_min_op
1092
- trp1_max_op = alarms_temperature.trp1_max_op
1093
- trp1_min_nop = alarms_temperature.trp1_min_nop
1094
- trp1_max_nop = alarms_temperature.trp1_max_nop
1095
- trp22_min_op = alarms_temperature.trp22_min_op
1096
- trp22_max_op = alarms_temperature.trp22_max_op
1097
- trp22_min_nop = alarms_temperature.trp22_min_nop
1098
- trp22_max_nop = alarms_temperature.trp22_max_nop
1099
-
1100
- alarm_exp1 = False # Low Temp NOP
1101
- alarm_exp2 = False # High Temp NOP
1102
- alarm_exp3 = False # low/High Temp OP
1103
- alarm_exp4 = False # UPS alarm (UPS_Arrakis_alarm_summary or UPS_Ix_alarm_summary)
1104
- c3 = 0 # Counter number triggers alarm EXP3
1105
-
1106
- while True:
1107
- try:
1108
- response = cdaq.get_tvac_and_ups_state()
1109
-
1110
- if killer.term_signal_received:
1111
- break
1112
- if not response:
1113
- LOGGER.warning("Received an empty response from the CDAQ9375, "
1114
- "check the connection with the device.")
1115
- LOGGER.warning(f"Response: {response=}")
1116
- time.sleep(1.0)
1117
- continue
1118
- if isinstance(response, Failure):
1119
- LOGGER.warning(f"Received a Failure from the CDAQ9375 Control Server:")
1120
- LOGGER.warning(f"Response: {response}")
1121
- time.sleep(1.0)
1122
- continue
1123
-
1124
- # EXP4
1125
- if any([response["UPS_Ix_alarm_summary"], response["UPS_Ix_power_supply_absence"],
1126
- response["UPS_Arrakis_alarm_summary"], response["UPS_Arrakis_power_supply_absence"]]):
1127
- alarm_exp4 = True
1128
- else:
1129
- alarm_exp4 = False
1130
-
1131
- try:
1132
- trp1_avg = tcs_proxy.get_housekeeping_value("tou_rtd_tav").value
1133
-
1134
- if not trp1_avg:
1135
- LOGGER.warning("Received an empty response from the TCS, "
1136
- "check the connection with the device.")
1137
- LOGGER.warning(f"Response: {trp1_avg=}")
1138
- time.sleep(1.0)
1139
- continue
1140
- if isinstance(trp1_avg, Failure):
1141
- LOGGER.warning(f"Received a Failure from the TCS EGSE Control Server:")
1142
- LOGGER.warning(f"Response: {trp1_avg}")
1143
- time.sleep(1.0)
1144
- continue
1145
-
1146
- trp1_avg = float(trp1_avg)
1147
-
1148
- except ValueError:
1149
- LOGGER.warning(f"TRP1 Value Error in cdaq alarms: trp1_avg should be a number, got {trp1_avg}."
1150
- f"\nTerminating...")
1151
- if trp1_avg == "tbd":
1152
- LOGGER.warning("Got TBD for TRP1_AVG.\nCheck if the task is well running.\nTerminating...")
1153
- break
1154
-
1155
- try:
1156
- trp22_avg = tcs_proxy.get_housekeeping_value("fee_rtd_tav").value
1157
-
1158
- if not trp22_avg:
1159
- LOGGER.warning("Received an empty response from the TCS, "
1160
- "check the connection with the device.")
1161
- LOGGER.warning(f"Response: {trp22_avg=}")
1162
- time.sleep(1.0)
1163
- continue
1164
- if isinstance(trp22_avg, Failure):
1165
- LOGGER.warning(f"Received a Failure from the TCS EGSE Control Server:")
1166
- LOGGER.warning(f"Response: {trp22_avg}")
1167
- time.sleep(1.0)
1168
- continue
1169
-
1170
- trp22_avg = float(trp22_avg)
1171
-
1172
- except ValueError:
1173
- LOGGER.warning(f"TRP22_AVG ValueError: trp22_avg should be a number, got {trp22_avg}."
1174
- f"\nTerminating...")
1175
- if trp22_avg == "tbd":
1176
- LOGGER.warning("Got TBD for TRP22_AVG.\nCheck if the task is well running.\nTerminating...")
1177
- break
1178
-
1179
-
1180
- aeu_standby = aeu_crio.get_operating_mode() == OperatingMode.STANDBY # True means aeu is in standby mode
1181
-
1182
- if aeu_standby:
1183
- alarm_exp3 = False
1184
- c3 = 0
1185
-
1186
-
1187
- # EXP1
1188
- if trp1_avg < trp1_min_nop or trp22_avg < trp22_min_nop:
1189
- alarm_exp1 = True
1190
- else:
1191
- alarm_exp1 = False
1192
-
1193
- # EXP2
1194
- if trp1_avg > trp1_max_nop or trp22_avg > trp22_max_nop:
1195
- alarm_exp2 = True
1196
- else:
1197
- alarm_exp2 = False
1198
-
1199
- # EXP3
1200
- else:
1201
- if any([trp1_avg < trp1_min_op, trp1_avg > trp1_max_op,
1202
- trp22_avg < trp22_min_op, trp22_avg > trp22_max_op]):
1203
- alarm_exp3 = True
1204
- c3 += 1
1205
- else:
1206
- alarm_exp3 = False
1207
- c3 = 0
1208
-
1209
- alarm_exp_dict = {"alarm_EXP1": int(alarm_exp1),
1210
- "alarm_EXP2": int(alarm_exp2),
1211
- "alarm_EXP3": int(alarm_exp3),
1212
- "alarm_EXP4": int(alarm_exp4)}
1213
- response.update(alarm_exp_dict)
1214
- hk_conversion_table = read_conversion_dict("DAS-CDAQ-ALARMS", setup=setup)
1215
- hk_dict = convert_hk_names(response, hk_conversion_table)
1216
- storage.save({"origin": origin, "data": hk_dict})
1217
-
1218
- hk_dict.pop("timestamp")
1219
- for key, value in hk_dict.items():
1220
- metrics_cdaq_alarms[key].set(value)
1221
-
1222
- alarm_exp3 = c3 > 3 # Send SMS via TVAC only if EXP3 is triggered more than 3 consecutive times
1223
- cdaq.send_egse_state_to_tvac(alarm_exp1, alarm_exp2, alarm_exp3, alarm_exp4)
1224
-
1225
- except KeyboardInterrupt:
1226
- LOGGER.debug("Interrupt received, terminating...")
1227
- break
1228
-
1229
- except Exception as exc:
1230
- LOGGER.warning(f"DAS Exception: {exc}", exc_info=True)
1231
- LOGGER.warning("Got a corrupt hk_dict from the CDAQ. "
1232
- "Check log messages for 'DAS Exception'.")
1233
- time.sleep(1.0)
1234
- continue
1235
-
1236
- storage.unregister({"origin": origin})
1237
-
1238
-
1239
- if __name__ == "__main__":
1240
- cli()