cgse 2024.7.0__py3-none-any.whl → 2025.0.2__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.2.dist-info/METADATA +38 -0
  4. cgse-2025.0.2.dist-info/RECORD +5 -0
  5. {cgse-2024.7.0.dist-info → cgse-2025.0.2.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
@@ -1,1279 +0,0 @@
1
- """
2
- The referenceFrames module provides the class :code:`ReferenceFrames` which defines the affine transformation
3
- for bringing one reference frame to another.
4
-
5
- .. todo:: The tests in methods like getPassiveTransformationTo using '==' should be looked at again and maybe
6
- changed into using the 'is' operator. This because we now have __eq__ implemented.
7
-
8
- @author: Pierre Royer
9
- """
10
- import logging
11
- import random
12
- import string
13
- import textwrap
14
-
15
- import numpy as np
16
- import transforms3d as t3
17
-
18
- import egse.coordinates.transform3d_addon as t3add
19
- from egse.coordinates.point import Point
20
- from egse.coordinates.rotationMatrix import RotationMatrix
21
- from egse.decorators import deprecate
22
- from egse.exceptions import InvalidOperationError
23
-
24
- LOGGER = logging.getLogger(__name__)
25
-
26
-
27
- def transformationToString(transformation):
28
- """Helper function: prints out a transformation (numpy ndarray) in a condensed form on one line."""
29
-
30
- if isinstance(transformation, np.ndarray):
31
- if np.allclose(transformation, ReferenceFrame._I):
32
- return "Identity"
33
- msg = np.array2string(
34
- transformation,
35
- separator=",",
36
- suppress_small=True,
37
- formatter={"float_kind": lambda x: "%.2f" % x},
38
- ).replace("\n", "")
39
- return msg
40
-
41
- # We do not want to raise an Exception here since this is mainly used in logging messages
42
- # and doesn't really harm the execution of the program.
43
- return f"ERROR: expected transformation to be an ndarray, type={type(transformation)}"
44
-
45
-
46
- class ReferenceFrame(object):
47
- """
48
- A Reference Frame defined in reference frame "ref", i.e.
49
- defined by the affine transformation bringing the reference frame "ref" onto "self".
50
-
51
- By default, "ref" is the master refence frame, defined as the identity matrix.
52
-
53
- :param transformation: 4x4 affine transformation matrix defining this system in "ref" system
54
- :type transformation: numpy array
55
-
56
- :param ref: reference system in which this new reference frame is defined
57
- :type ref: ReferenceFrame
58
-
59
- :param name: name the reference frame so it can be referenced, set to 'master' when None
60
- :type name: str
61
-
62
- :param rot_config:
63
- * Is set when using creator ReferenceFrame.fromTranslationRotation()
64
- * In other cases, is set to a default "szyx"
65
- (rotations around static axes z, y and x in this order)
66
- In these other cases, it has no real direct influence,
67
- except for methods returning the rotation vector (e.g. getRotationVector)
68
- It is therefore always recommended to pass it to the constructor, even when
69
- constructing the ReferenceFrame directly from a transformation matrix
70
- :type rot_config: str
71
-
72
- Both the ``transformation`` and the ``ref`` parameters are mandatory.
73
-
74
- If the reference frame is None, the master reference frame is created.
75
-
76
- The master reference frame:
77
-
78
- * is defined by the identity transformation matrix
79
- * has itself as a reference
80
-
81
- For convenience we provide the following factory methods:
82
-
83
- createMaster()
84
- Create a Master Reference Frame
85
-
86
- createRotation(..)
87
- Create a new Reference Frame that is rotated with respect to the given reference frame
88
-
89
- createTranslation(..)
90
- Create a new Reference Frame that is a translation with respect to the given reference frame
91
- """
92
-
93
- _I = np.identity(4)
94
- _MASTER = None
95
- _ROT_CONFIG_DEFAULT = "sxyz"
96
- _names_used = [None, "Master"]
97
- _strict_naming = False
98
- _ACTIVE_DEFAULT = True
99
-
100
- def __new__(cls, transformation, ref, name=None, rot_config=_ROT_CONFIG_DEFAULT):
101
- """Create a new ReferenceFrame class."""
102
-
103
- LOGGER.debug(
104
- f"transformation={transformationToString(transformation)}, ref={ref!r}, name={name}, rot_config={rot_config}"
105
- )
106
-
107
- if ref is None:
108
- msg = (
109
- "No reference frame was given, if you planned to create a Master Reference Frame, "
110
- "use ReferenceFrame.createMaster(). "
111
- )
112
- LOGGER.error(msg)
113
- raise ValueError(msg, "REF_IS_NONE")
114
-
115
- if not isinstance(ref, cls):
116
- msg = f"The 'ref' keyword argument is not a ReferenceFrame object, but {type(ref)}"
117
- LOGGER.error(msg)
118
- raise ValueError(msg, "REF_IS_NOT_CLS")
119
-
120
- if name == "Master":
121
- msg = (
122
- "The 'name' argument cannot be 'Master' unless a Master instance should be created, "
123
- "in that case, use ReferenceFrame.createMaster()"
124
- )
125
- LOGGER.error(msg)
126
- raise ValueError(msg, "MASTER_NAME_USED")
127
-
128
- if transformation is None:
129
- msg = "The 'transformation' argument can not be None, please provide a proper transformation for this reference frame."
130
- LOGGER.error(msg)
131
- raise ValueError(msg, "TRANSFORMATION_IS_NONE")
132
-
133
- if not isinstance(transformation, np.ndarray):
134
- msg = f"The 'transformation' argument shall be a Numpy ndarray [not a {type(transformation)}], please provide a proper transformation for this reference frame."
135
- LOGGER.error(msg)
136
- raise ValueError(msg, "TRANSFORMATION_IS_NOT_NDARRAY")
137
-
138
- if rot_config is None:
139
- msg = "The 'rot_config' keyword argument can not be None, do not specify it when you want to use the default value."
140
- LOGGER.error(msg)
141
- raise ValueError(msg)
142
-
143
- _instance = super(ReferenceFrame, cls).__new__(cls)
144
-
145
- return _instance
146
-
147
- def __init__(self, transformation, ref, name=None, rot_config=_ROT_CONFIG_DEFAULT):
148
- """Initialize the ReferenceFrame object """
149
-
150
- self.debug = False
151
-
152
- LOGGER.debug(
153
- f"transformation={transformationToString(transformation)}, ref={ref!r}, name={name}, rot_config={rot_config}"
154
- )
155
-
156
- # All argument testing is done in the __new__() method and we should be save here.
157
-
158
- self.ref = ref
159
- self.name = self.__createName(name)
160
- self.transformation = transformation
161
- self.rot_config = rot_config
162
-
163
- self.definition = [self.transformation, self.ref, self.name]
164
-
165
- self.x = self.getAxis("x")
166
- self.y = self.getAxis("y")
167
- self.z = self.getAxis("z")
168
-
169
- self.linkedTo = {}
170
- self.referenceFor = []
171
-
172
- ref.referenceFor.append(self)
173
-
174
- return
175
-
176
- def find_master(self):
177
- return self.findMaster()
178
-
179
- def findMaster(self):
180
- """
181
- Returns the Master frame for this reference frame. The Master frame is always at the end
182
- of the path following the references.
183
-
184
- Returns:
185
- The master frame.
186
- """
187
-
188
- frame = self
189
- while not frame.isMaster():
190
- frame = frame.ref
191
- return frame
192
-
193
- @classmethod
194
- def createMaster(cls):
195
- """
196
- Create a master reference frame.
197
-
198
- A master reference frame is defined with respect to itself and is initialised with the
199
- identity matrix.
200
-
201
- The master frame is automatically given the name "Master".
202
- """
203
- ref_master = super(ReferenceFrame, cls).__new__(cls)
204
- ref_master.name = "Master"
205
- ref_master.ref = ref_master
206
- ref_master.transformation = cls._I
207
- ref_master.rot_config = cls._ROT_CONFIG_DEFAULT
208
- ref_master.initialized = True
209
- ref_master.debug = False
210
- ref_master.linkedTo = {}
211
- ref_master.referenceFor = []
212
-
213
- LOGGER.debug(
214
- f"NEW MASTER CREATED: {id(ref_master)}, ref = {id(ref_master.ref)}, "
215
- f"name = {ref_master.name}"
216
- )
217
-
218
- return ref_master
219
-
220
- @classmethod
221
- def __createName(cls, name: str = None):
222
-
223
- if name is None:
224
- while name in cls._names_used:
225
- name = "F" + "".join(random.choices(string.ascii_uppercase, k=3))
226
- return name
227
-
228
- if cls._strict_naming:
229
-
230
- # generate a unique name
231
-
232
- old_name = name
233
-
234
- while name in cls._names_used:
235
- name = "F" + "".join(random.choices(string.ascii_uppercase, k=3))
236
-
237
- LOGGER.warning(
238
- f"name ('{old_name}') is already defined, since strict naming is applied, "
239
- f"a new unique name was created: {name}"
240
- )
241
-
242
- else:
243
-
244
- if name in cls._names_used:
245
- LOGGER.log(
246
- 0,
247
- f"name ('{name}') is already defined, now you have more than one "
248
- f"ReferenceFrame with the same name.",
249
- )
250
-
251
- cls._names_used.append(name)
252
- return name
253
-
254
- @classmethod
255
- def fromTranslation(cls, transx, transy, transz, ref, name=None):
256
- """
257
- Create a ReferenceFrame from a translation with respect to the given reference frame.
258
-
259
- :param transx: translation along the x-axis
260
- :type transx: float
261
-
262
- :param transy: translation along the y-axis
263
- :type transy: float
264
-
265
- :param transz: translation along the z-axis
266
- :type transz: float
267
-
268
- :param ref: reference frame with respect to which the translation is performed. If no ref is given
269
- the rotation is with respect to the master reference frame
270
- :type ref: ReferenceFrame
271
-
272
- :param name: a simple convenient name to identify the reference frame. If no name is provided
273
- a random name of four characters starting with 'F' will be generated.
274
- :type name: str
275
-
276
- :return: a reference frame
277
- """
278
- adef = np.identity(4)
279
- adef[:3, 3] = [transx, transy, transz]
280
-
281
- if ref is None:
282
- raise ValueError(
283
- "The ref argument can not be None, provide a master or another reference frame."
284
- )
285
-
286
- return cls(transformation=adef, ref=ref, name=name)
287
-
288
- @classmethod
289
- def fromRotation(
290
- cls,
291
- rotx,
292
- roty,
293
- rotz,
294
- ref,
295
- name=None,
296
- rot_config=_ROT_CONFIG_DEFAULT,
297
- active=_ACTIVE_DEFAULT,
298
- degrees=True,
299
- ):
300
- """
301
- Create a ReferenceFrame from a rotation with respect to the given reference frame.
302
-
303
- :param rotx: rotation around the x-axis
304
- :type rotx: float
305
-
306
- :param roty: rotation around the y-axis
307
- :type roty: float
308
-
309
- :param rotz: rotation around the z-axis
310
- :type rotz: float
311
-
312
- :param ref: reference frame with respect to which the rotation is performed. If no ref is given
313
- the rotation is with respect to the master reference frame
314
- :type ref: ReferenceFrame
315
-
316
- :param name: a simple convenient name to identify the reference frame. If no name is provided
317
- a random name of four characters starting with 'F' will be generated.
318
- :type name: str
319
-
320
- :return: a reference frame
321
- """
322
- # Convention (rotating axes, in order xyz)
323
-
324
- # rot_config = cls._ROT_CONFIG_DEFAULT
325
-
326
- # Rotation amplitude
327
-
328
- # Rotation
329
- if degrees:
330
- rotx = np.deg2rad(rotx)
331
- roty = np.deg2rad(roty)
332
- rotz = np.deg2rad(rotz)
333
-
334
- rotation = RotationMatrix(rotx, roty, rotz, rot_config, active=active)
335
-
336
- # Defaults for zoom & shear
337
-
338
- zdef = np.array([1, 1, 1])
339
- sdef = np.array([0, 0, 0])
340
-
341
- translation = [0, 0, 0]
342
-
343
- TT = t3.affines.compose(T=translation, R=rotation.R, Z=zdef, S=sdef)
344
-
345
- if ref is None:
346
- raise ValueError(
347
- "The ref argument can not be None, provide a master or another reference frame."
348
- )
349
-
350
- return cls(transformation=TT, ref=ref, name=name, rot_config=rot_config)
351
-
352
- @staticmethod
353
- def fromPoints(points, plane="xy", name=None, usesvd=True, verbose=True):
354
- """
355
- fromPoints(points, plane="xy", name=None, usesvd=True,verbose=True)
356
-
357
- Finds the best fitting "plane" plane to all points in "points" and builds a ReferenceFrame
358
- considering the fitted plane as the 'xy' plane of the new system
359
-
360
- fitPlane must be in ['xy','yz','zx']
361
- """
362
- return points.bestFittingPlane(fitPlane=plane, usesvd=usesvd, verbose=verbose)
363
-
364
- @classmethod
365
- def fromTranslationRotation(
366
- cls,
367
- translation,
368
- rotation,
369
- ref,
370
- name=None,
371
- rot_config=_ROT_CONFIG_DEFAULT,
372
- active=_ACTIVE_DEFAULT,
373
- degrees=True,
374
- ):
375
- """fromTranslationRotation(cls,translation,rotation, ref=None,name=None, rot_config=_ROT_CONFIG_DEFAULT,active=_ACTIVE_DEFAULT, degrees=True)
376
-
377
- Construct a ReferenceFrame from a translation and a rotation (vectors!)
378
-
379
- translation : translation vector : 3 x 1 = tx, ty, tz
380
- rotation : rotation vector : 3 x 1 = rx, ry, rz
381
-
382
- rot_config : convention for the rotation, see rotationMatrix.__doc__
383
-
384
- degrees : if True, input values are assumed in degrees, otherwise radians
385
- """
386
- # Translation
387
- translation = np.array(translation)
388
- # Zoom - unit
389
- zdef = np.array([1, 1, 1])
390
- # Shear
391
- sdef = np.array([0, 0, 0])
392
- # Rotation
393
- if degrees:
394
- rotation = np.array([np.deg2rad(item) for item in rotation])
395
- rotx, roty, rotz = rotation
396
- #
397
- rmat = RotationMatrix(rotx, roty, rotz, rot_config=rot_config, active=active)
398
- #
399
- # transformation = t3.affines.compose(translation,rmat.R,Z=zdef,S=sdef)
400
-
401
- if ref is None:
402
- raise ValueError(
403
- "The ref argument can not be None, provide a master or another reference frame."
404
- )
405
-
406
- return cls(
407
- transformation=t3.affines.compose(translation, rmat.R, Z=zdef, S=sdef),
408
- ref=ref,
409
- name=name,
410
- rot_config=rot_config,
411
- )
412
-
413
- def getTranslationVector(self):
414
- """
415
- getTranslationVector()
416
-
417
- Returns the translation defining this reference frame (from self.ref to self)
418
- """
419
- return self.transformation[:3, 3]
420
-
421
- def getRotationVector(self, degrees=True, active=_ACTIVE_DEFAULT):
422
- """
423
- getRotationVector()
424
-
425
- Returns the rotation (vector) defining this reference frame (from self.ref to self)
426
- degrees : if true, rotation angles are expressed in degrees
427
- """
428
- rotation = t3.euler.mat2euler(self.transformation, axes=self.rot_config)
429
- if degrees:
430
- rotation = np.array([np.rad2deg(item) for item in rotation])
431
- return rotation
432
-
433
- def getTranslationRotationVectors(self, degrees=True, active=_ACTIVE_DEFAULT):
434
- """getTranslationRotationVectors()
435
- Returns the translation and rotation (vectors) defining this reference frame (from self.ref to self)
436
- degrees : if true, rotation angles are expressed in degrees
437
- """
438
- translation = self.getTranslationVector()
439
- rotation = self.getRotationVector(degrees=degrees, active=active)
440
- return translation, rotation
441
-
442
- def getRotationMatrix(self):
443
- """
444
- getRotationMatrix()
445
-
446
- Returns the rotation (matrix) defining this reference frame (from self.ref to self)
447
- """
448
- result = self.transformation.copy()
449
- result[:3, 3] = [0.0, 0.0, 0.0]
450
- return result
451
-
452
- def __repr__(self):
453
- return f"ReferenceFrame(transformation={transformationToString(self.transformation)}, ref={self.ref.name}, name={self.name}, rot_config={self.rot_config})"
454
-
455
- def __str__(self):
456
- msg = textwrap.dedent(
457
- f"""\
458
- ReferenceFrame
459
- name : {self.name}
460
- reference : {self.ref.name}
461
- rot_config : {self.rot_config}
462
- links : {[key.name for key in self.linkedTo.keys()]}
463
- transformation:
464
- [{np.round(self.transformation[0], 3)}
465
- {np.round(self.transformation[1], 3)}
466
- {np.round(self.transformation[2], 3)}
467
- {np.round(self.transformation[3], 3)}]
468
- translation : {np.round(self.getTranslationVector(),3)}
469
- rotation : {np.round(self.getRotationVector(),3)}"""
470
- )
471
- return msg
472
-
473
- @deprecate(
474
- reason=(
475
- "I do not see the added value of changing the name and "
476
- "the current method has the side effect to change the name "
477
- "to a random string when the name argument is already used."
478
- ),
479
- alternative="the constructor argument to set the name already of the object.",
480
- )
481
- def setName(self, name=None):
482
- """
483
- Set or change the name of a reference frame.
484
-
485
- ..note: this method is deprecated
486
-
487
- :param str name: the new name for the reference frame, if None, a random name will be generated.
488
-
489
- :raises InvalidOperationError: when you try to change the name of the Master reference frame
490
- """
491
- if self.isMaster():
492
- raise InvalidOperationError(
493
- "You try to change the name of the Master reference frame, which is not allowed."
494
- )
495
- self.name = self.__createName(name)
496
-
497
- def addLink(self, ref, transformation=None, _stop=False):
498
- """
499
- adds a link between self and ref in self.linkedTo and ref.linkedTo
500
- """
501
-
502
- # DONE: set the inverse transformation in the ref to this
503
- # ref.linkedTo[self] = t3add.affine_inverse(transformation)
504
- # TODO:
505
- # remove the _stop keyword
506
-
507
- # TODO: deprecate transformation as an input variable
508
- # linkedTo can become a list of reference frames, with no transformation
509
- # associated to the link. The tfo associated to a link is already
510
- # checked in real time whenever the link is addressed
511
- if transformation is None:
512
- transformation = self.getActiveTransformationTo(ref)
513
- else:
514
- LOGGER.info("Deprecation warning: transformation will be automatically set to "
515
- "the current relation between {self.name} and {ref.name}")
516
- LOGGER.flash_flood("Requested:")
517
- LOGGER.flash_flood(np.round(transformation, decimals=3))
518
- LOGGER.flash_flood("Auto (enforced):")
519
-
520
- transformation = self.getActiveTransformationTo(ref)
521
-
522
- LOGGER.flash_flood(np.round(transformation, decimals=3))
523
-
524
- self.linkedTo[ref] = transformation
525
-
526
- # TODO simplify this when transformation is deprecated
527
- # it becomes ref.linkedTo[self] = ref.getActiveTransformationTo(self)
528
- ref.linkedTo[self] = t3add.affine_inverse(transformation)
529
-
530
- def removeLink(self, ref):
531
- """
532
- Remove the link between self and ref, both ways.
533
- """
534
-
535
- # First remove the entry in ref to this
536
-
537
- if self in ref.linkedTo:
538
- del ref.linkedTo[self]
539
-
540
- # Then remove the entry in this to ref
541
-
542
- if ref in self.linkedTo:
543
- del self.linkedTo[ref]
544
-
545
- def getPassiveTransformationTo(self, targetFrame):
546
- """
547
- getPassiveTransformationTo(self,targetFrame)
548
- == getPointTransformationTo(self,targetFrame)
549
-
550
- returns the transformation to apply to a Point (defined in self) to express it in targetFrame
551
-
552
- Passive transformation : the point is static, we change the reference frame around it
553
- """
554
- LOGGER.flash_flood("PASSIVE TO self {self.name} target {targetFrame.name}")
555
- if targetFrame is self:
556
- """
557
- Nothing to do here, we already have the right coordinates
558
- """
559
- LOGGER.flash_flood("case 1")
560
- result = np.identity(4)
561
-
562
- elif targetFrame.ref is self:
563
- """
564
- The target frame is defined in self => the requested transformation is the targetFrame definition
565
- """
566
- LOGGER.flash_flood("=== 2 start ===")
567
- result = t3add.affine_inverse(targetFrame.transformation)
568
- LOGGER.flash_flood("=== 2 end ===")
569
- elif targetFrame.ref is self.ref:
570
- """
571
- targetFrame and self are defined wrt the same reference frame
572
- We want
573
- self --> targetFrame
574
- We know
575
- targetFrame.ref --> targetFrame (= targetFrame.transformation)
576
- self.ref --> self (= self.transformation)
577
- That is
578
- self --> self.ref is targetFrame.ref --> targetFrame
579
- inverse(definition) targetFrame definition
580
-
581
- """
582
- LOGGER.flash_flood("=== 3 start ===")
583
- LOGGER.flash_flood(" ref \n{0}".format(self.ref))
584
- LOGGER.flash_flood("===")
585
- LOGGER.flash_flood("self \n{0}".format(self))
586
- LOGGER.flash_flood("===")
587
- LOGGER.flash_flood("targetFrame \n{0}".format(targetFrame))
588
- LOGGER.flash_flood("===")
589
-
590
- selfToRef = self.transformation
591
- LOGGER.flash_flood("selfToRef \n{0}".format(selfToRef))
592
-
593
- # refToRef = I
594
-
595
- refToTarget = t3add.affine_inverse(targetFrame.transformation)
596
- LOGGER.flash_flood("refToTarget \n{0}".format(refToTarget))
597
-
598
- result = np.dot(refToTarget, selfToRef)
599
- LOGGER.flash_flood("result \n{0}".format(result))
600
- LOGGER.flash_flood("=== 3 end ===")
601
- else:
602
- """
603
- We are after the transformation from
604
- self --> targetFrame
605
- ==
606
- self --> self.ref --> targetFrame.ref --> targetFrame
607
-
608
- We know
609
- targetFrame.ref --> targetFrame (targetFrame.transformation)
610
- self.ref --> self (self.transformation)
611
- but
612
- targetFrame.ref != self.ref
613
- so we need
614
- self.ref --> targetFrame.ref
615
- then we can compose
616
- self --> self.ref --> targetFrame.ref --> targetFrame
617
-
618
- Note: the transformation self.ref --> targetFrame.ref is acquired recursively
619
- This relies on the underlying assumption that there exists
620
- one unique reference frame that source and self can be linked to
621
- (without constraints on the number of links necessary), i.e.
622
- that, from a frame to its reference or the opposite, there exists
623
- a path between self and targetFrame. That is equivalent to
624
- the assumption that the entire set of reference frames is connex,
625
- i.e. defined upon a unique master reference frame.
626
- """
627
- LOGGER.flash_flood("=== 4 start ===")
628
- selfToRef = self.transformation
629
- selfRefToTargetRef = self.ref.getPassiveTransformationTo(targetFrame.ref)
630
- refToTarget = t3add.affine_inverse(targetFrame.transformation)
631
- result = np.dot(refToTarget, np.dot(selfRefToTargetRef, selfToRef))
632
- LOGGER.flash_flood("=== 4 end ===")
633
-
634
- return result
635
-
636
- def getPassiveTranslationRotationVectorsTo(
637
- self, targetFrame, degrees=True
638
- ): # , active=_ACTIVE_DEFAULT):
639
- """
640
- getPassiveTranslationRotationVectorsTo(self,ref,degrees=True)
641
-
642
- extracts rotation vector from the result of getPassiveTransformationTo(target)
643
- """
644
- transformation = self.getPassiveTransformationTo(targetFrame)
645
- rotation = t3.euler.mat2euler(transformation, axes=self.rot_config)
646
- if degrees:
647
- rotation = np.array([np.rad2deg(item) for item in rotation])
648
- translation = transformation[:3, 3]
649
- return translation, rotation
650
-
651
- def getPassiveTranslationVectorTo(self, targetFrame, degrees=True):
652
- """
653
- getPassiveTranslationRotationVectorsTo(self,ref,degrees=True)
654
-
655
- extracts translation vector from the result of getPassiveTransformationTo(target)
656
- """
657
- return self.getPassiveTranslationRotationVectorsTo(targetFrame, degrees=degrees)[0]
658
-
659
- def getPassiveRotationVectorTo(self, targetFrame, degrees=True):
660
- """
661
- getPassiveTranslationRotationVectorsTo(self,targetFrame,degrees=True)
662
-
663
- extracts rotation vector from the result of getPassiveTransformationTo(targetFrame)
664
- """
665
- return self.getPassiveTranslationRotationVectorsTo(targetFrame, degrees=degrees)[1]
666
-
667
- def getPassiveTransformationFrom(self, source):
668
- """
669
- getPassiveTransformationFrom(self,source)
670
- == getPointTransformationTo(self,source)
671
-
672
- INPUT
673
- source : is a ReferenceFrame object
674
-
675
- OUTPUT
676
- returns the transformation matrix that, applied to a point defined
677
- in source returns its coordinates in self
678
- """
679
- LOGGER.flash_flood("PASSIVE FROM self {self.name} source {source.name}")
680
- return source.getPassiveTransformationTo(self)
681
-
682
- def getPassiveTranslationRotationVectorsFrom(
683
- self, source, degrees=True
684
- ): # , active=_ACTIVE_DEFAULT):
685
- """
686
- getPassiveTranslationRotationVectorsFrom(self,source, degrees=True)
687
-
688
- extracts rotation vector from the result of getPassiveTransformationTo(target)
689
- """
690
- transformation = self.getPassiveTransformationFrom(source)
691
- rotation = t3.euler.mat2euler(transformation, axes=self.rot_config)
692
- if degrees:
693
- rotation = np.array([np.rad2deg(item) for item in rotation])
694
- translation = transformation[:3, 3]
695
- return translation, rotation
696
-
697
- def getPassiveTranslationVectorFrom(self, source, degrees=True):
698
- """
699
- getPassiveTranslationVectorFrom(self,source, degrees=True)
700
-
701
- extracts translation vector from the result of getPassiveTransformationFrom(source)
702
- """
703
- return self.getPassiveTranslationRotationVectorsFrom(source, degrees=degrees)[0]
704
-
705
- def getPassiveRotationVectorFrom(self, source, degrees=True):
706
- """
707
- getPassiveTranslationRotationVectorsFrom(self,source,degrees=True)
708
-
709
- extracts rotation vector from the result of getPassiveTransformationFrom(source)
710
- """
711
- return self.getPassiveTranslationRotationVectorsFrom(source, degrees=degrees)[1]
712
-
713
- def getActiveTransformationTo(self, target):
714
- """
715
- Return the transformation matrix from this reference frame (``self``) to
716
- the target reference frame.
717
-
718
- Applying this transformation to the ``self`` ReferenceFrame would render it
719
- identical to target.
720
-
721
- Applying this transformation to a point defined in ``self`` would move it to
722
- the same coordinates in target.
723
-
724
- :param target: is a ReferenceFrame object
725
-
726
- :return: the transformation matrix that defines the reference frame ``target``
727
- in ``self``, the current reference frame. The transformation from self
728
- to target
729
-
730
- """
731
- LOGGER.flash_flood("ACTIVE TO self {self.name} target {target.name}")
732
- return target.getPassiveTransformationTo(self)
733
-
734
- def getActiveTranslationRotationVectorsTo(
735
- self, targetFrame, degrees=True
736
- ): # ,active=_ACTIVE_DEFAULT):
737
- """
738
- getActiveTranslationRotationVectorsTo(self,ref,degrees=True)
739
-
740
- extracts rotation vector from the result of getActiveTransformationTo(target)
741
- """
742
- transformation = self.getActiveTransformationTo(targetFrame)
743
- rotation = t3.euler.mat2euler(transformation, axes=self.rot_config)
744
- if degrees:
745
- rotation = np.array([np.rad2deg(item) for item in rotation])
746
- translation = transformation[:3, 3]
747
- return translation, rotation
748
-
749
- def getActiveTranslationVectorTo(self, targetFrame, degrees=True):
750
- """
751
- getActiveTranslationRotationVectorsTo(self,ref,degrees=True)
752
-
753
- extracts translation vector from the result of getActiveTransformationTo(target)
754
- """
755
- return self.getActiveTranslationRotationVectorsTo(targetFrame, degrees=degrees)[0]
756
-
757
- def getActiveRotationVectorTo(self, targetFrame, degrees=True):
758
- """
759
- getActiveTranslationRotationVectorsTo(self,targetFrame,degrees=True)
760
-
761
- extracts rotation vector from the result of getActiveTransformationTo(targetFrame)
762
- """
763
- return self.getActiveTranslationRotationVectorsTo(targetFrame, degrees=degrees)[1]
764
-
765
- def getActiveTransformationFrom(self, source):
766
- """
767
- Applying this transformation to the ``source`` ReferenceFrame
768
- would render it identical to self.
769
-
770
- Applying this transformation to a point defined in source
771
- would move it to the same coordinates in self.
772
-
773
- :param source: is a ReferenceFrame object
774
-
775
- :return: the transformation matrix that defines this reference frame in ``source``,
776
- i.e. the transformation from ``source`` to ``self``
777
-
778
- """
779
- LOGGER.flash_flood("ACTIVE FROM self {self.name} source {source.name}")
780
- return self.getPassiveTransformationTo(source)
781
-
782
- def getActiveTranslationRotationVectorsFrom(
783
- self, source, degrees=True
784
- ): # ,active=_ACTIVE_DEFAULT):
785
- """
786
- getActiveTranslationRotationVectorsFrom(self,source, degrees=True)
787
-
788
- extracts rotation vector from the result of getActiveTransformationTo(target)
789
- """
790
- transformation = self.getActiveTransformationFrom(source)
791
- rotation = t3.euler.mat2euler(transformation, axes=self.rot_config)
792
- if degrees:
793
- rotation = np.array([np.rad2deg(item) for item in rotation])
794
- translation = transformation[:3, 3]
795
- return translation, rotation
796
-
797
- def getActiveTranslationVectorFrom(self, source, degrees=True):
798
- """
799
- getActiveTranslationVectorFrom(self,source, degrees=True)
800
-
801
- extracts translation vector from the result of getActiveTransformationFrom(source)
802
- """
803
- return self.getActiveTranslationRotationVectorsFrom(source, degrees=degrees)[0]
804
-
805
- def getActiveRotationVectorFrom(self, source, degrees=True):
806
- """
807
- getActiveTranslationRotationVectorsFrom(self,source,degrees=True)
808
-
809
- extracts rotation vector from the result of getActiveTransformationFrom(source)
810
- """
811
- return self.getActiveTranslationRotationVectorsFrom(source, degrees=degrees)[1]
812
-
813
- def _findEnds(self, frame, visited=[], ends=[], verbose=True, level=1):
814
- """
815
- PURPOSE
816
- Identify the 'linked_frames':
817
- frames that are linked, either directly or indirectly (via mult. links) to "frame"
818
- --> returned as visited
819
- Identify subset of 'linked_frames of which the reference does not belong to linked_frames
820
- --> returned as 'finalEnds'
821
- """
822
- LOGGER.flash_flood(
823
- f"{level:-2d}{2*level*' '} Current: {frame.name} -- ends: {[f.name for f in ends]} -- visited {[f.name for f in visited]}"
824
- )
825
- # if verbose: print (f"{level:-2d}{2*level*' '} Current: {frame.name} -- ends: {[f.name for f in ends]} -- visited {[f.name for f in visited]}")
826
-
827
- # Establish the set of 'linked_frames' (variable 'visited')
828
- # The recursive process below keeps unwanted (non-endFrames), namely the
829
- # frames that are not directly, but well indirectly linked to their reference
830
- # This case is solved further down
831
- if frame not in visited:
832
- visited.append(frame)
833
- if verbose and level:
834
- level += 1
835
- if frame.ref not in frame.linkedTo:
836
- ends.append(frame)
837
- LOGGER.flash_flood(f"{(10+2*level)*' '}{frame.name}: new end")
838
- # if verbose: LOGGER.info(f"{(10+2*level)*' '}{frame.name}: new end")
839
- for linkedFrame in frame.linkedTo:
840
- ends, visited = self._findEnds(
841
- linkedFrame, visited=visited, ends=ends, verbose=verbose, level=level
842
- )
843
-
844
- # If frame.ref was linked to frame via an indirect route, reject it
845
- finalEnds = []
846
- for aframe in ends:
847
- if aframe.ref not in ends:
848
- finalEnds.append(aframe)
849
- return finalEnds, visited
850
-
851
- def setTransformation(
852
- self, transformation, updated=None, preserveLinks=True, _relative=False, verbose=True
853
- ):
854
- """
855
- setTransformation(self,transformation, updated=None, preserveLinks=True,_relative=False, verbose=True)
856
-
857
- Alter the definition of this coordinate system
858
-
859
- If other systems are linked to this one, their definition must be updated accordingly
860
- The link set between two ref. Frames A & B is the active transformation matrix from A to B
861
- A.addLink(B, matrix)
862
- A.getActiveTransformationTo(B) --> matrix
863
-
864
- The way to update the definition of the present system, and of those linked to it
865
- depends on the structure of those links.
866
-
867
- We define
868
- - the target frame as the one we want to move / redefine
869
- - 'linkedFrames' as those directly, or indirectly (i.e. via multiple links)
870
- linked to the target frame
871
- - endFrames as the subset of linkedFrames which are not linked to their reference (directly or indirectly)
872
- - sideFrames as the set of frames whose reference is a linkedFrame, but not themselves belonging to the linkedFrames
873
-
874
- We can demonstrate that updating the endFrames (Block A below) is sufficient to represent
875
- the movement of the target frame and all frames directly or indirectly linked to it.
876
-
877
- This may nevertheless have perverse effects for sideFrames. Indeed,
878
- their reference will (directly or implicitely) be redefined, but they shouldn't:
879
- they are not linked to their reference --> their location in space (e.g. wrt the master frame)
880
- should not be affected by the movement of the target frame. This is the aim of block B.
881
-
882
- For a completely robust solution, 2 steps must be taken
883
- BLOCK A. apply the rigt transformation to all "endFrames"
884
- BLOCK B. Check for frames
885
- using any of the "visited" frames as a reference
886
- not linked to its reference
887
- Correct its so that it doesn't move (it shouldn't be affected by the requested movement)
888
- This demands a "referenceFor" array property
889
-
890
- """
891
- # Ruthless, enforced redefinition of one system. Know what you do, or stay away.
892
- # Semi-unpredictible side effets if the impacted frame has links!
893
- if preserveLinks == False:
894
- self.transformation = transformation
895
- return
896
-
897
- if updated is None:
898
- updated = []
899
-
900
- # visitedFrames = all frames which can be reached from self via invariant links
901
- # endFrames = subset of visitedFrames that are at the end of a chain, and must be updated
902
- # in order to properly represent the requested movement
903
- endFrames, visitedFrames = self._findEnds(frame=self, visited=[], ends=[], verbose=verbose)
904
- if verbose:
905
- LOGGER.info(
906
- f"Visited sub-system {[f.name for f in visitedFrames]}"
907
- )
908
- LOGGER.info(f"End-frames (movement necessary) {[f.name for f in endFrames]}")
909
-
910
- # All updates are done by relative movements
911
- # so we must first compute the relative movement corresponding to the requested absolute movement
912
- if _relative == False:
913
- ## virtual = what self should become after the (absolute) movement
914
- ## it allows to compute the relative transformation to be applied and work in relative further down
915
- virtual = ReferenceFrame(
916
- transformation, ref=self.ref, name="virtual", rot_config=self.rot_config
917
- )
918
- request = self.getActiveTransformationTo(virtual)
919
- del virtual
920
- else:
921
- # If this method is called by applyTransformation,
922
- # we are facing a request for a relative movement
923
- # In that case the input is directly what we want
924
- request = transformation
925
-
926
- # BLOCK B. Check for frames that were impacted but shouldn't have been and correct them
927
- # B1. List of frames demanding a correction
928
- # 'impacted' are frames having their reference inside the rigid structure moving, but not linked to it
929
- # If nothing is done, the movement will implicitely displace them, which is not intended
930
-
931
- ### Impacted shall not contain frames that are linked to self (== to any frame in visitedFrames) via any route...
932
- ### We check if the impacted frames are in visitedFrames:
933
- ### it is enough to know it's connected to the entire 'solid body' in which self belongs
934
- impacted = []
935
- for frame in visitedFrames:
936
- for child in frame.referenceFor:
937
- # Version 1 : too simple (restores too many frames)
938
- #if child not in frame.linkedTo:
939
-
940
- # Version 2 : overkill
941
- #child_ends, child_visited = child._findEnds(frame=child,visited=[],ends=[],verbose=verbose)
942
- #if frame not in child_visited:
943
-
944
- # Version 3 : just check if the child belongs to the rigid structure...
945
- if child not in visitedFrames:
946
- impacted.append(child)
947
-
948
- LOGGER.debug(f"Impacted (not moving, defined in moving) {[f.name for f in impacted]}")
949
-
950
- # B2. save the location of all impacted frames
951
- # tempReference has the only purpose of avoiding that every frame must know the master
952
- # It could be any frame without links and defined wrt the master, but the master isn't known here...
953
- # TODO : confirm that the master isn't known (e.g. via cls._MASTER)
954
- tempMaster = self.findMaster()
955
- toRestore = {}
956
- for frame in impacted:
957
- toRestore[frame] = ReferenceFrame(
958
- frame.getActiveTransformationFrom(tempMaster),
959
- ref=tempMaster,
960
- name=frame.name + "toRestore",
961
- rot_config=frame.rot_config,
962
- )
963
-
964
- # BLOCK A. apply the rigt transformation to all "endFrames"
965
- """
966
- ### Ensure that "Untouched" remains unaffected regardless of the update order of the endFrames
967
- selfUntouched = ReferenceFrame(
968
- transformation = self.getActiveTransformationFrom(tempMaster),
969
- ref=tempMaster,
970
- name=self.name + "_fixed",
971
- rot_config=self.rot_config,
972
- )
973
- """
974
-
975
- selfUntouched = ReferenceFrame(
976
- transformation=self.transformation,
977
- ref=self.ref,
978
- name=self.name + "_fixed",
979
- rot_config=self.rot_config,
980
- )
981
-
982
- for bottom in endFrames:
983
-
984
- up = bottom.getActiveTransformationTo(selfUntouched)
985
- down = selfUntouched.getActiveTransformationTo(bottom)
986
-
987
- relativeTransformation = up @ request @ down
988
-
989
- LOGGER.flash_flood(
990
- f"\nAdjusting {bottom.name} to {self.name}\nUpdated {[i.name for i in updated]}"
991
- )
992
- LOGGER.flash_flood(f"\ninput transformation \n{np.round(transformation,3)}")
993
- LOGGER.flash_flood(
994
- f"\nup \n{np.round(up,3)}\ntransformation\n{np.round(request,3)}\ndown\n{np.round(down,3)}"
995
- )
996
- LOGGER.flash_flood(f"\nrelativeTransformation \n{np.round(relativeTransformation,3)}")
997
-
998
- bottom.transformation = bottom.transformation @ relativeTransformation
999
-
1000
- updated.append(bottom)
1001
-
1002
- for frame in visitedFrames:
1003
- if frame not in updated:
1004
- updated.append(frame)
1005
-
1006
- # Block B
1007
- # B3. Correction
1008
- # we must set preserveLinks to False to prevent cascading impact from this update
1009
- # if X1 is impacted with
1010
- # X1.ref = E1 X1 --> X2 (simple link) E2.ref = X2
1011
- # where X1 and X2 are "external frames" and E1 and E2 are "endFrames" that will hence move
1012
- # X1 was impacted by the move of E1, but X2 wasn't
1013
- # ==> wrt master, neither X1 nor X2 should have moved, but X1 did (via its ref)
1014
- # and hence its link with X2 is now corrupt
1015
- # We need to move X1 back to its original location wrt master
1016
- # if we preserved the links while doing that,
1017
- # we will move X2, which shouldn't move
1018
- # (it didn't have to, it didn't and the goal is to restore the validity of the links)
1019
- #
1020
- # Direct restoration or the impacted frames at their original location
1021
-
1022
- for frame in toRestore:
1023
- frame.transformation = frame.ref.getActiveTransformationTo(toRestore[frame])
1024
-
1025
- del toRestore
1026
-
1027
- return
1028
-
1029
- def setTranslationRotation(
1030
- self,
1031
- translation,
1032
- rotation,
1033
- rot_config=_ROT_CONFIG_DEFAULT,
1034
- active=_ACTIVE_DEFAULT,
1035
- degrees=True,
1036
- preserveLinks=True,
1037
- ):
1038
- """
1039
- setTranslationRotation(self,translation,rotation,rot_config=_ROT_CONFIG_DEFAULT, active=_ACTIVE_DEFAULT, degrees=True, preserveLinks=True)
1040
-
1041
- Same as setTransformation, but input = translation and rotation vectors rather than affine transformation matrix
1042
- """
1043
- # Translation
1044
- translation = np.array(translation)
1045
- # Zoom - unit
1046
- zdef = np.array([1, 1, 1])
1047
- # Shear
1048
- sdef = np.array([0, 0, 0])
1049
- # Rotation
1050
- if degrees:
1051
- rotation = np.array([np.deg2rad(item) for item in rotation])
1052
-
1053
- rotx, roty, rotz = rotation
1054
-
1055
- rmat = RotationMatrix(rotx, roty, rotz, rot_config=rot_config, active=active)
1056
-
1057
- LOGGER.flash_flood(t3.affines.compose(translation, rmat.R, Z=zdef, S=sdef))
1058
-
1059
- transformation = t3.affines.compose(translation, rmat.R, Z=zdef, S=sdef)
1060
-
1061
- self.setTransformation(transformation, preserveLinks=preserveLinks, _relative=False)
1062
- return
1063
-
1064
- def applyTransformation(self, transformation, updated=None, preserveLinks=True):
1065
- """
1066
- applyTransformation(self,transformation)
1067
-
1068
- Applies the transformation to the current reference frame's definition
1069
-
1070
- self.transformation := transformation @ self.transformation
1071
- """
1072
- if updated is None:
1073
- updated = []
1074
-
1075
- self.setTransformation(
1076
- transformation=transformation,
1077
- updated=updated,
1078
- preserveLinks=preserveLinks,
1079
- _relative=True,
1080
- )
1081
-
1082
- def applyTranslationRotation(
1083
- self,
1084
- translation,
1085
- rotation,
1086
- rot_config=None,
1087
- active=_ACTIVE_DEFAULT,
1088
- degrees=True,
1089
- preserveLinks=True,
1090
- ):
1091
- """
1092
- applyTranslationRotation(self,translation,rotation,rot_config=None,active=_ACTIVE_DEFAULT,degrees=True, preserveLinks=True)
1093
-
1094
- Builds transformation from input translation and rotation, then applies this transformation
1095
- """
1096
- if rot_config is None:
1097
- rot_config = self.rot_config
1098
-
1099
- # Translation
1100
- translation = np.array(translation)
1101
- # Zoom - unit
1102
- zdef = np.array([1, 1, 1])
1103
- # Shear
1104
- sdef = np.array([0, 0, 0])
1105
- # Rotation
1106
- if degrees:
1107
- rotation = np.array([np.deg2rad(item) for item in rotation])
1108
- rotx, roty, rotz = rotation
1109
- #
1110
- rmat = RotationMatrix(rotx, roty, rotz, rot_config=rot_config, active=active)
1111
- #
1112
- transformation = t3.affines.compose(translation, rmat.R, Z=zdef, S=sdef)
1113
- #
1114
- self.applyTransformation(transformation, preserveLinks=preserveLinks)
1115
- return
1116
-
1117
- def getAxis(self, axis, name=None):
1118
- """
1119
- INPUT
1120
- axis : in ['x','y','z']
1121
-
1122
- OUTPUT
1123
- Returns an object of class Point, corresponding to the vector defining
1124
- the axis of choice in self.
1125
- The output can be used with the Point methods to express that axis in any reference frame
1126
- """
1127
- haxis = {}
1128
- haxis["x"] = [1, 0, 0]
1129
- haxis["y"] = [0, 1, 0]
1130
- haxis["z"] = [0, 0, 1]
1131
- if name is None:
1132
- name = self.name + axis
1133
- return Point(haxis[axis], ref=self, name=name)
1134
-
1135
- def getNormal(self, name=None):
1136
- """
1137
- getNormal(self,name=None)
1138
-
1139
- Returns a unit vector normal to the X-Y plane (= [0,0,1] = getAxis('z'))
1140
- """
1141
- return Point([0, 0, 1], ref=self, name=name)
1142
-
1143
- def getOrigin(self, name=None):
1144
- """
1145
- OUTPUT
1146
- Returns an object of class Point, corresponding to the vector defining the origin in 'self', i.e. [0,0,0]
1147
- The output can be used with the Point methods to express that axis in any reference frame
1148
- """
1149
- return Point([0, 0, 0], ref=self, name=name)
1150
-
1151
- def is_master(self):
1152
- return self.isMaster()
1153
-
1154
- def isMaster(self):
1155
- """
1156
- A Master reference frame is a reference frame that refers to itself, and the
1157
- transformation is the Identity matrix.
1158
- """
1159
- tr = self.transformation
1160
-
1161
- if (
1162
- (self.name == self.ref.name)
1163
- and (tr.shape[0] == tr.shape[1])
1164
- and np.allclose(tr, np.eye(tr.shape[0]))
1165
- ):
1166
- return True
1167
- return False
1168
-
1169
- def isSame(self, other):
1170
- """
1171
- Returns True if the two reference frames are the same except for their name.
1172
-
1173
- Two Reference Frames are considered the same when:
1174
-
1175
- * their transformation matrices are equal
1176
- * the reference frame is equal
1177
- * the rot_config is equal
1178
- * the name may be different
1179
-
1180
- .. todo:: This needs further work and testing!
1181
- """
1182
-
1183
- if other is self:
1184
- LOGGER.debug(
1185
- "self and other are the same object (beware: this message might occur with recursion from self.ref != self.other)"
1186
- )
1187
- return True
1188
-
1189
- if isinstance(other, ReferenceFrame):
1190
- LOGGER.flash_flood(f"comparing {self.name} and {other.name}")
1191
- if not np.array_equal(self.transformation, other.transformation):
1192
- LOGGER.flash_flood("self.transformation not equals other.transformation")
1193
- return False
1194
- if self.rot_config != other.rot_config:
1195
- LOGGER.flash_flood("self.rot_config not equals other.rot_config")
1196
- return False
1197
- # The following tests are here to prevent recursion to go infinite when self and other
1198
- # point to itself
1199
- if self.ref is self and other.ref is other:
1200
- LOGGER.flash_flood("both self.ref and other.ref point to themselves")
1201
- pass
1202
- else:
1203
- LOGGER.flash_flood("one of self.ref or other.ref doesn't points to itself")
1204
- if self.ref != other.ref:
1205
- LOGGER.flash_flood("self.ref not equals other.ref")
1206
- return False
1207
- if self.name is not other.name:
1208
- LOGGER.flash_flood(
1209
- f"When checking two reference frames for equality, only their names differ: '{self.name}' not equals '{other.name}'"
1210
- )
1211
- pass
1212
- return True
1213
- return NotImplemented
1214
-
1215
- def __eq__(self, other):
1216
- """
1217
- Overrides the default implementation, which basically checks for id(self) == id(other).
1218
-
1219
- Two Reference Frames are considered equal when:
1220
-
1221
- * their transformation matrices are equal
1222
- * the reference frame is equal
1223
- * the rot_config is equal
1224
- * do we want to insist on the name being equal?
1225
- YES - for strict testing
1226
- NO - this might need a new method like isSame(self, other) where the criteria are relaxed
1227
-
1228
-
1229
- .. todo:: This needs further work and testing!
1230
- """
1231
-
1232
- if other is self:
1233
- LOGGER.debug(
1234
- "self and other are the same object (beware: this message might occur with recursion from self.ref != self.other)"
1235
- )
1236
- return True
1237
-
1238
- if isinstance(other, ReferenceFrame):
1239
- LOGGER.flash_flood(f"comparing {self.name} and {other.name}")
1240
- if not np.array_equal(self.transformation, other.transformation):
1241
- LOGGER.flash_flood("self.transformation not equals other.transformation")
1242
- return False
1243
- if self.rot_config != other.rot_config:
1244
- LOGGER.flash_flood("self.rot_config not equals other.rot_config")
1245
- return False
1246
- # The following tests are here to prevent recursion to go infinite when self and other
1247
- # point to itself
1248
- if self.ref is self and other.ref is other:
1249
- LOGGER.flash_flood("both self.ref and other.ref point to themselves")
1250
- pass
1251
- else:
1252
- LOGGER.flash_flood("one of self.ref or other.ref doesn't points to itself")
1253
- if self.ref != other.ref:
1254
- LOGGER.flash_flood("self.ref not equals other.ref")
1255
- return False
1256
- if self.name is not other.name:
1257
- LOGGER.flash_flood(
1258
- f"When checking two reference frames for equality, only their names differ: '{self.name}' not equals '{other.name}'"
1259
- )
1260
- return False
1261
- return True
1262
- return NotImplemented
1263
-
1264
- def __hash__(self):
1265
- """Overrides the default implementation"""
1266
- hash_number = (id(self.rot_config) + id(self.ref) + id(self.name)) // 16
1267
- return hash_number
1268
-
1269
- def __copy__(self):
1270
-
1271
- LOGGER.debug(
1272
- f'Copying {self!r} unless {self.name} is "Master" in which case the Master itself is returned.'
1273
- )
1274
-
1275
- if self.isMaster():
1276
- LOGGER.debug(f"Returning Master itself instead of a copy.")
1277
- return self
1278
-
1279
- return ReferenceFrame(self.transformation, self.ref, self.name, self.rot_config)