cgse 2023.38.0__py3-none-any.whl → 2024.1.3__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.
- README.md +27 -0
- bump.py +77 -0
- cgse-2024.1.3.dist-info/METADATA +41 -0
- cgse-2024.1.3.dist-info/RECORD +5 -0
- {cgse-2023.38.0.dist-info → cgse-2024.1.3.dist-info}/WHEEL +1 -2
- cgse-2023.38.0.dist-info/COPYING +0 -674
- cgse-2023.38.0.dist-info/COPYING.LESSER +0 -165
- cgse-2023.38.0.dist-info/METADATA +0 -144
- cgse-2023.38.0.dist-info/RECORD +0 -649
- cgse-2023.38.0.dist-info/entry_points.txt +0 -75
- cgse-2023.38.0.dist-info/top_level.txt +0 -2
- egse/__init__.py +0 -12
- egse/__main__.py +0 -32
- egse/aeu/aeu.py +0 -5235
- egse/aeu/aeu_awg.yaml +0 -265
- egse/aeu/aeu_crio.yaml +0 -273
- egse/aeu/aeu_cs.py +0 -626
- egse/aeu/aeu_devif.py +0 -321
- egse/aeu/aeu_main_ui.py +0 -912
- egse/aeu/aeu_metrics.py +0 -131
- egse/aeu/aeu_protocol.py +0 -463
- egse/aeu/aeu_psu.yaml +0 -204
- egse/aeu/aeu_ui.py +0 -873
- egse/aeu/arbdata/FccdRead.arb +0 -2
- egse/aeu/arbdata/FccdRead_min_points.arb +0 -2
- egse/aeu/arbdata/HeaterSync_FccdRead.arb +0 -2
- egse/aeu/arbdata/HeaterSync_ccdRead25.arb +0 -2
- egse/aeu/arbdata/HeaterSync_ccdRead31_25.arb +0 -2
- egse/aeu/arbdata/HeaterSync_ccdRead37_50.arb +0 -2
- egse/aeu/arbdata/HeaterSync_ccdRead43_75.arb +0 -2
- egse/aeu/arbdata/HeaterSync_ccdRead50.arb +0 -2
- egse/aeu/arbdata/Heater_FccdRead_min_points.arb +0 -2
- egse/aeu/arbdata/ccdRead25.arb +0 -2
- egse/aeu/arbdata/ccdRead25_150ms.arb +0 -2
- egse/aeu/arbdata/ccdRead31_25.arb +0 -2
- egse/aeu/arbdata/ccdRead31_25_150ms.arb +0 -2
- egse/aeu/arbdata/ccdRead37_50.arb +0 -2
- egse/aeu/arbdata/ccdRead37_50_150ms.arb +0 -2
- egse/aeu/arbdata/ccdRead43_75.arb +0 -2
- egse/aeu/arbdata/ccdRead43_75_150ms.arb +0 -2
- egse/aeu/arbdata/ccdRead50.arb +0 -2
- egse/aeu/arbdata/ccdRead50_150ms.arb +0 -2
- egse/alert/__init__.py +0 -1049
- egse/alert/alertman.yaml +0 -37
- egse/alert/alertman_cs.py +0 -234
- egse/alert/alertman_ui.py +0 -603
- egse/alert/gsm/beaglebone.py +0 -138
- egse/alert/gsm/beaglebone.yaml +0 -51
- egse/alert/gsm/beaglebone_cs.py +0 -108
- egse/alert/gsm/beaglebone_devif.py +0 -130
- egse/alert/gsm/beaglebone_protocol.py +0 -48
- egse/bits.py +0 -318
- egse/camera.py +0 -44
- egse/collimator/__init__.py +0 -0
- egse/collimator/fcul/__init__.py +0 -0
- egse/collimator/fcul/ogse.py +0 -1077
- egse/collimator/fcul/ogse.yaml +0 -14
- egse/collimator/fcul/ogse_cs.py +0 -154
- egse/collimator/fcul/ogse_devif.py +0 -358
- egse/collimator/fcul/ogse_protocol.py +0 -129
- egse/collimator/fcul/ogse_sim.py +0 -431
- egse/collimator/fcul/ogse_ui.py +0 -1108
- egse/command.py +0 -699
- egse/config.py +0 -410
- egse/confman/__init__.py +0 -1015
- egse/confman/confman.yaml +0 -67
- egse/confman/confman_cs.py +0 -239
- egse/confman/confman_ui.py +0 -381
- egse/confman/setup_ui.py +0 -565
- egse/control.py +0 -442
- egse/coordinates/__init__.py +0 -531
- egse/coordinates/avoidance.py +0 -103
- egse/coordinates/cslmodel.py +0 -127
- egse/coordinates/laser_tracker_to_dict.py +0 -120
- egse/coordinates/point.py +0 -707
- egse/coordinates/pyplot.py +0 -195
- egse/coordinates/referenceFrame.py +0 -1279
- egse/coordinates/refmodel.py +0 -737
- egse/coordinates/rotationMatrix.py +0 -85
- egse/coordinates/transform3d_addon.py +0 -419
- egse/csl/__init__.py +0 -50
- egse/csl/commanding.py +0 -78
- egse/csl/icons/hexapod-connected-selected.svg +0 -30
- egse/csl/icons/hexapod-connected.svg +0 -30
- egse/csl/icons/hexapod-homing-selected.svg +0 -68
- egse/csl/icons/hexapod-homing.svg +0 -68
- egse/csl/icons/hexapod-retract-selected.svg +0 -56
- egse/csl/icons/hexapod-retract.svg +0 -51
- egse/csl/icons/hexapod-zero-selected.svg +0 -56
- egse/csl/icons/hexapod-zero.svg +0 -56
- egse/csl/icons/logo-puna.svg +0 -92
- egse/csl/icons/stop.svg +0 -1
- egse/csl/initialisation.py +0 -102
- egse/csl/mech_pos_settings.yaml +0 -18
- egse/das.py +0 -1247
- egse/das.yaml +0 -7
- egse/data/conf/SETUP_CSL_00000_170620_150000.yaml +0 -5
- egse/data/conf/SETUP_CSL_00001_170620_151010.yaml +0 -69
- egse/data/conf/SETUP_CSL_00002_170620_151020.yaml +0 -69
- egse/data/conf/SETUP_CSL_00003_170620_151030.yaml +0 -69
- egse/data/conf/SETUP_CSL_00004_170620_151040.yaml +0 -69
- egse/data/conf/SETUP_CSL_00005_170620_151050.yaml +0 -69
- egse/data/conf/SETUP_CSL_00006_170620_151060.yaml +0 -69
- egse/data/conf/SETUP_CSL_00007_170620_151070.yaml +0 -69
- egse/data/conf/SETUP_CSL_00008_170620_151080.yaml +0 -75
- egse/data/conf/SETUP_CSL_00010_210308_083016.yaml +0 -138
- egse/data/conf/SETUP_INTA_00000_170620_150000.yaml +0 -4
- egse/data/conf/SETUP_SRON_00000_170620_150000.yaml +0 -4
- egse/decorators.py +0 -415
- egse/device.py +0 -269
- egse/dpu/__init__.py +0 -2681
- egse/dpu/ccd_ui.py +0 -508
- egse/dpu/dpu.py +0 -786
- egse/dpu/dpu.yaml +0 -153
- egse/dpu/dpu_cs.py +0 -272
- egse/dpu/dpu_ui.py +0 -668
- egse/dpu/fitsgen.py +0 -2077
- egse/dpu/fitsgen_test.py +0 -752
- egse/dpu/fitsgen_ui.py +0 -399
- egse/dpu/hdf5_model.py +0 -332
- egse/dpu/hdf5_ui.py +0 -277
- egse/dpu/hdf5_viewer.py +0 -506
- egse/dpu/hk_ui.py +0 -468
- egse/dpu_commands.py +0 -81
- egse/dsi/constants.py +0 -220
- egse/dsi/esl.py +0 -870
- egse/dsi/rmap.py +0 -1042
- egse/dsi/rmapci.py +0 -37
- egse/dsi/spw.py +0 -154
- egse/dsi/spw_state.py +0 -29
- egse/dummy.py +0 -258
- egse/dyndummy.py +0 -179
- egse/env.py +0 -278
- egse/exceptions.py +0 -88
- egse/fdir/__init__.py +0 -28
- egse/fdir/fdir_manager.py +0 -85
- egse/fdir/fdir_manager.yaml +0 -51
- egse/fdir/fdir_manager_controller.py +0 -228
- egse/fdir/fdir_manager_cs.py +0 -164
- egse/fdir/fdir_manager_interface.py +0 -25
- egse/fdir/fdir_remote.py +0 -73
- egse/fdir/fdir_remote.yaml +0 -37
- egse/fdir/fdir_remote_controller.py +0 -50
- egse/fdir/fdir_remote_cs.py +0 -97
- egse/fdir/fdir_remote_interface.py +0 -14
- egse/fdir/fdir_remote_popup.py +0 -31
- egse/fee/__init__.py +0 -114
- egse/fee/f_fee_register.yaml +0 -43
- egse/fee/fee.py +0 -631
- egse/fee/feesim.py +0 -750
- egse/fee/n_fee_hk.py +0 -761
- egse/fee/nfee.py +0 -187
- egse/filterwheel/__init__.py +0 -4
- egse/filterwheel/eksma/__init__.py +0 -24
- egse/filterwheel/eksma/fw8smc4.py +0 -661
- egse/filterwheel/eksma/fw8smc4.yaml +0 -121
- egse/filterwheel/eksma/fw8smc4_cs.py +0 -144
- egse/filterwheel/eksma/fw8smc4_devif.py +0 -473
- egse/filterwheel/eksma/fw8smc4_protocol.py +0 -81
- egse/filterwheel/eksma/fw8smc4_ui.py +0 -940
- egse/filterwheel/eksma/fw8smc5.py +0 -111
- egse/filterwheel/eksma/fw8smc5.yaml +0 -105
- egse/filterwheel/eksma/fw8smc5_controller.py +0 -307
- egse/filterwheel/eksma/fw8smc5_cs.py +0 -141
- egse/filterwheel/eksma/fw8smc5_interface.py +0 -65
- egse/filterwheel/eksma/fw8smc5_simulator.py +0 -29
- egse/filterwheel/eksma/fw8smc5_ui.py +0 -1068
- egse/filterwheel/eksma/testpythonfw.py +0 -215
- egse/fov/__init__.py +0 -65
- egse/fov/fov_hk.py +0 -712
- egse/fov/fov_ui.py +0 -861
- egse/fov/fov_ui_controller.py +0 -140
- egse/fov/fov_ui_model.py +0 -200
- egse/fov/fov_ui_view.py +0 -345
- egse/gimbal/__init__.py +0 -32
- egse/gimbal/symetrie/__init__.py +0 -26
- egse/gimbal/symetrie/alpha.py +0 -586
- egse/gimbal/symetrie/generic_gimbal_ui.py +0 -1521
- egse/gimbal/symetrie/gimbal.py +0 -877
- egse/gimbal/symetrie/gimbal.yaml +0 -168
- egse/gimbal/symetrie/gimbal_cs.py +0 -183
- egse/gimbal/symetrie/gimbal_protocol.py +0 -135
- egse/gimbal/symetrie/gimbal_ui.py +0 -361
- egse/gimbal/symetrie/pmac.py +0 -1006
- egse/gimbal/symetrie/pmac_regex.py +0 -83
- egse/graph.py +0 -132
- egse/gui/__init__.py +0 -47
- egse/gui/buttons.py +0 -378
- egse/gui/focalplane.py +0 -1281
- egse/gui/formatter.py +0 -10
- egse/gui/led.py +0 -162
- egse/gui/limitswitch.py +0 -143
- egse/gui/mechanisms.py +0 -588
- egse/gui/states.py +0 -148
- egse/gui/stripchart.py +0 -729
- egse/gui/switch.py +0 -112
- egse/h5.py +0 -274
- egse/help/__init__.py +0 -0
- egse/help/help_ui.py +0 -126
- egse/hexapod/__init__.py +0 -32
- egse/hexapod/symetrie/__init__.py +0 -138
- egse/hexapod/symetrie/alpha.py +0 -874
- egse/hexapod/symetrie/dynalpha.py +0 -1387
- egse/hexapod/symetrie/hexapod_ui.py +0 -1516
- egse/hexapod/symetrie/pmac.py +0 -1010
- egse/hexapod/symetrie/pmac_regex.py +0 -83
- egse/hexapod/symetrie/puna.py +0 -1167
- egse/hexapod/symetrie/puna.yaml +0 -193
- egse/hexapod/symetrie/puna_cs.py +0 -196
- egse/hexapod/symetrie/puna_protocol.py +0 -131
- egse/hexapod/symetrie/puna_ui.py +0 -434
- egse/hexapod/symetrie/punaplus.py +0 -107
- egse/hexapod/symetrie/zonda.py +0 -872
- egse/hexapod/symetrie/zonda.yaml +0 -337
- egse/hexapod/symetrie/zonda_cs.py +0 -172
- egse/hexapod/symetrie/zonda_devif.py +0 -415
- egse/hexapod/symetrie/zonda_protocol.py +0 -119
- egse/hexapod/symetrie/zonda_ui.py +0 -449
- egse/hk.py +0 -765
- egse/icons/aeu-cs-start.svg +0 -117
- egse/icons/aeu-cs-stop.svg +0 -118
- egse/icons/aeu-cs.svg +0 -107
- egse/icons/aeu_cs-started.svg +0 -112
- egse/icons/aeu_cs-stopped.svg +0 -112
- egse/icons/aeu_cs.svg +0 -55
- egse/icons/alert.svg +0 -1
- egse/icons/arrow-double-left.png +0 -0
- egse/icons/arrow-double-right.png +0 -0
- egse/icons/arrow-up.svg +0 -11
- egse/icons/backward.svg +0 -1
- egse/icons/busy.svg +0 -1
- egse/icons/cleaning.svg +0 -115
- egse/icons/color-scheme.svg +0 -1
- egse/icons/cs-connected-alert.svg +0 -91
- egse/icons/cs-connected-disabled.svg +0 -43
- egse/icons/cs-connected.svg +0 -89
- egse/icons/cs-not-connected.svg +0 -44
- egse/icons/double-left-arrow.svg +0 -1
- egse/icons/double-right-arrow.svg +0 -1
- egse/icons/erase-disabled.svg +0 -19
- egse/icons/erase.svg +0 -59
- egse/icons/fitsgen-start.svg +0 -47
- egse/icons/fitsgen-stop.svg +0 -48
- egse/icons/fitsgen.svg +0 -1
- egse/icons/forward.svg +0 -1
- egse/icons/fov-hk-start.svg +0 -33
- egse/icons/fov-hk-stop.svg +0 -37
- egse/icons/fov-hk.svg +0 -1
- egse/icons/front-desk.svg +0 -1
- egse/icons/home-actioned.svg +0 -15
- egse/icons/home-disabled.svg +0 -15
- egse/icons/home.svg +0 -13
- egse/icons/info.svg +0 -1
- egse/icons/invalid.png +0 -0
- egse/icons/led-green.svg +0 -20
- egse/icons/led-grey.svg +0 -20
- egse/icons/led-orange.svg +0 -20
- egse/icons/led-red.svg +0 -20
- egse/icons/led-square-green.svg +0 -134
- egse/icons/led-square-grey.svg +0 -134
- egse/icons/led-square-orange.svg +0 -134
- egse/icons/led-square-red.svg +0 -134
- egse/icons/limit-switch-all-green.svg +0 -115
- egse/icons/limit-switch-all-red.svg +0 -117
- egse/icons/limit-switch-el+.svg +0 -116
- egse/icons/limit-switch-el-.svg +0 -117
- egse/icons/location-marker.svg +0 -1
- egse/icons/logo-dpu.svg +0 -48
- egse/icons/logo-gimbal.svg +0 -112
- egse/icons/logo-huber.svg +0 -23
- egse/icons/logo-ogse.svg +0 -31
- egse/icons/logo-puna.svg +0 -92
- egse/icons/logo-tcs.svg +0 -29
- egse/icons/logo-zonda.svg +0 -66
- egse/icons/maximize.svg +0 -1
- egse/icons/meter.svg +0 -1
- egse/icons/more.svg +0 -45
- egse/icons/n-fee-hk-start.svg +0 -24
- egse/icons/n-fee-hk-stop.svg +0 -25
- egse/icons/n-fee-hk.svg +0 -83
- egse/icons/observing-off.svg +0 -46
- egse/icons/observing-on.svg +0 -46
- egse/icons/open-document-hdf5.png +0 -0
- egse/icons/open-document-hdf5.svg +0 -21
- egse/icons/ops-mode.svg +0 -1
- egse/icons/play-green.svg +0 -17
- egse/icons/plugged-disabled.svg +0 -27
- egse/icons/plugged.svg +0 -21
- egse/icons/pm_ui.svg +0 -1
- egse/icons/power-button-green.svg +0 -27
- egse/icons/power-button-red.svg +0 -27
- egse/icons/power-button.svg +0 -27
- egse/icons/radar.svg +0 -1
- egse/icons/radioactive.svg +0 -2
- egse/icons/reload.svg +0 -1
- egse/icons/remote-control-off.svg +0 -28
- egse/icons/remote-control-on.svg +0 -28
- egse/icons/repeat-blue.svg +0 -15
- egse/icons/repeat.svg +0 -1
- egse/icons/settings.svg +0 -1
- egse/icons/shrink.svg +0 -1
- egse/icons/shutter.svg +0 -1
- egse/icons/sign-off.svg +0 -1
- egse/icons/sign-on.svg +0 -1
- egse/icons/sim-mode.svg +0 -1
- egse/icons/small-buttons-go.svg +0 -20
- egse/icons/small-buttons-minus.svg +0 -51
- egse/icons/small-buttons-plus.svg +0 -51
- egse/icons/sponge.svg +0 -220
- egse/icons/start-button-disabled.svg +0 -84
- egse/icons/start-button.svg +0 -50
- egse/icons/stop-button-disabled.svg +0 -84
- egse/icons/stop-button.svg +0 -50
- egse/icons/stop-red.svg +0 -17
- egse/icons/stop.svg +0 -1
- egse/icons/switch-disabled-square.svg +0 -87
- egse/icons/switch-disabled.svg +0 -15
- egse/icons/switch-off-square.svg +0 -87
- egse/icons/switch-off.svg +0 -72
- egse/icons/switch-on-square.svg +0 -87
- egse/icons/switch-on.svg +0 -61
- egse/icons/temperature-control.svg +0 -44
- egse/icons/th_ui_logo.svg +0 -1
- egse/icons/unplugged.svg +0 -23
- egse/icons/unvalid.png +0 -0
- egse/icons/user-interface.svg +0 -1
- egse/icons/vacuum.svg +0 -1
- egse/icons/valid.png +0 -0
- egse/icons/zoom-to-pixel-dark.svg +0 -64
- egse/icons/zoom-to-pixel-white.svg +0 -36
- egse/images/big-rotation-stage.png +0 -0
- egse/images/connected-100.png +0 -0
- egse/images/cross.svg +0 -6
- egse/images/disconnected-100.png +0 -0
- egse/images/gui-icon.png +0 -0
- egse/images/home.svg +0 -6
- egse/images/info-icon.png +0 -0
- egse/images/led-black.svg +0 -89
- egse/images/led-green.svg +0 -85
- egse/images/led-orange.svg +0 -85
- egse/images/led-red.svg +0 -85
- egse/images/load-icon.png +0 -0
- egse/images/load-setup.png +0 -0
- egse/images/load.png +0 -0
- egse/images/pause.png +0 -0
- egse/images/play-button.svg +0 -8
- egse/images/play.png +0 -0
- egse/images/process-status.png +0 -0
- egse/images/restart.png +0 -0
- egse/images/search.png +0 -0
- egse/images/sma.png +0 -0
- egse/images/start.png +0 -0
- egse/images/stop-button.svg +0 -8
- egse/images/stop.png +0 -0
- egse/images/switch-off.svg +0 -48
- egse/images/switch-on.svg +0 -48
- egse/images/undo.png +0 -0
- egse/images/update-button.svg +0 -11
- egse/imageviewer/exposureselection.py +0 -475
- egse/imageviewer/imageviewer.py +0 -198
- egse/imageviewer/matchfocalplane.py +0 -179
- egse/imageviewer/subfieldposition.py +0 -133
- egse/lampcontrol/__init__.py +0 -4
- egse/lampcontrol/beaglebone/beaglebone.py +0 -178
- egse/lampcontrol/beaglebone/beaglebone.yaml +0 -62
- egse/lampcontrol/beaglebone/beaglebone_cs.py +0 -106
- egse/lampcontrol/beaglebone/beaglebone_devif.py +0 -150
- egse/lampcontrol/beaglebone/beaglebone_protocol.py +0 -73
- egse/lampcontrol/energetiq/__init__.py +0 -22
- egse/lampcontrol/energetiq/eq99.yaml +0 -98
- egse/lampcontrol/energetiq/lampEQ99.py +0 -283
- egse/lampcontrol/energetiq/lampEQ99_cs.py +0 -128
- egse/lampcontrol/energetiq/lampEQ99_devif.py +0 -158
- egse/lampcontrol/energetiq/lampEQ99_encode_decode_errors.py +0 -73
- egse/lampcontrol/energetiq/lampEQ99_protocol.py +0 -69
- egse/lampcontrol/energetiq/lampEQ99_ui.py +0 -465
- egse/lib/CentOS-7/EtherSpaceLink_v34_86.dylib +0 -0
- egse/lib/CentOS-8/ESL-RMAP_v34_86.dylib +0 -0
- egse/lib/CentOS-8/EtherSpaceLink_v34_86.dylib +0 -0
- egse/lib/Debian/ESL-RMAP_v34_86.dylib +0 -0
- egse/lib/Debian/EtherSpaceLink_v34_86.dylib +0 -0
- egse/lib/Debian/libetherspacelink_v35_21.dylib +0 -0
- egse/lib/Linux/ESL-RMAP_v34_86.dylib +0 -0
- egse/lib/Linux/EtherSpaceLink_v34_86.dylib +0 -0
- egse/lib/Ubuntu-20/ESL-RMAP_v34_86.dylib +0 -0
- egse/lib/Ubuntu-20/EtherSpaceLink_v34_86.dylib +0 -0
- egse/lib/gssw/python3-gssw_2.2.3+31f63c9f-1_all.deb +0 -0
- egse/lib/macOS/ESL-RMAP_v34_86.dylib +0 -0
- egse/lib/macOS/EtherSpaceLink_v34_86.dylib +0 -0
- egse/lib/ximc/__pycache__/pyximc.cpython-38 2.pyc +0 -0
- egse/lib/ximc/__pycache__/pyximc.cpython-38.pyc +0 -0
- egse/lib/ximc/libximc.framework/Frameworks/libbindy.dylib +0 -0
- egse/lib/ximc/libximc.framework/Frameworks/libxiwrapper.dylib +0 -0
- egse/lib/ximc/libximc.framework/Headers/ximc.h +0 -5510
- egse/lib/ximc/libximc.framework/Resources/Info.plist +0 -42
- egse/lib/ximc/libximc.framework/Resources/keyfile.sqlite +0 -0
- egse/lib/ximc/libximc.framework/libbindy.so +0 -0
- egse/lib/ximc/libximc.framework/libximc +0 -0
- egse/lib/ximc/libximc.framework/libximc.so +0 -0
- egse/lib/ximc/libximc.framework/libximc.so.7.0.0 +0 -0
- egse/lib/ximc/libximc.framework/libxiwrapper.so +0 -0
- egse/lib/ximc/pyximc.py +0 -922
- egse/listener.py +0 -73
- egse/logger/__init__.py +0 -243
- egse/logger/log_cs.py +0 -321
- egse/metrics.py +0 -98
- egse/mixin.py +0 -464
- egse/monitoring.py +0 -95
- egse/ni/alarms/__init__.py +0 -26
- egse/ni/alarms/cdaq9375.py +0 -300
- egse/ni/alarms/cdaq9375.yaml +0 -89
- egse/ni/alarms/cdaq9375_cs.py +0 -130
- egse/ni/alarms/cdaq9375_devif.py +0 -183
- egse/ni/alarms/cdaq9375_protocol.py +0 -48
- egse/obs_inspection.py +0 -163
- egse/observer.py +0 -41
- egse/obsid.py +0 -163
- egse/powermeter/__init__.py +0 -0
- egse/powermeter/ni/__init__.py +0 -38
- egse/powermeter/ni/cdaq9184.py +0 -224
- egse/powermeter/ni/cdaq9184.yaml +0 -73
- egse/powermeter/ni/cdaq9184_cs.py +0 -130
- egse/powermeter/ni/cdaq9184_devif.py +0 -201
- egse/powermeter/ni/cdaq9184_protocol.py +0 -48
- egse/powermeter/ni/cdaq9184_ui.py +0 -544
- egse/powermeter/thorlabs/__init__.py +0 -25
- egse/powermeter/thorlabs/pm100a.py +0 -380
- egse/powermeter/thorlabs/pm100a.yaml +0 -132
- egse/powermeter/thorlabs/pm100a_cs.py +0 -136
- egse/powermeter/thorlabs/pm100a_devif.py +0 -127
- egse/powermeter/thorlabs/pm100a_protocol.py +0 -80
- egse/powermeter/thorlabs/pm100a_ui.py +0 -725
- egse/process.py +0 -451
- egse/procman/__init__.py +0 -811
- egse/procman/cannot_start_process_popup.py +0 -43
- egse/procman/procman.yaml +0 -49
- egse/procman/procman_cs.py +0 -201
- egse/procman/procman_ui.py +0 -2081
- egse/protocol.py +0 -603
- egse/proxy.py +0 -522
- egse/randomwalk.py +0 -140
- egse/reg.py +0 -585
- egse/reload.py +0 -122
- egse/reprocess.py +0 -675
- egse/resource.py +0 -333
- egse/rst.py +0 -135
- egse/search.py +0 -182
- egse/serialdevice.py +0 -190
- egse/services.py +0 -212
- egse/services.yaml +0 -51
- egse/settings.py +0 -379
- egse/settings.yaml +0 -980
- egse/setup.py +0 -1180
- egse/shutter/__init__.py +0 -0
- egse/shutter/thorlabs/__init__.py +0 -19
- egse/shutter/thorlabs/ksc101.py +0 -205
- egse/shutter/thorlabs/ksc101.yaml +0 -105
- egse/shutter/thorlabs/ksc101_cs.py +0 -136
- egse/shutter/thorlabs/ksc101_devif.py +0 -201
- egse/shutter/thorlabs/ksc101_protocol.py +0 -69
- egse/shutter/thorlabs/ksc101_ui.py +0 -548
- egse/shutter/thorlabs/sc10.py +0 -82
- egse/shutter/thorlabs/sc10.yaml +0 -52
- egse/shutter/thorlabs/sc10_controller.py +0 -81
- egse/shutter/thorlabs/sc10_cs.py +0 -108
- egse/shutter/thorlabs/sc10_interface.py +0 -25
- egse/shutter/thorlabs/sc10_simulator.py +0 -30
- egse/simulator.py +0 -41
- egse/slack.py +0 -61
- egse/socketdevice.py +0 -218
- egse/sockets.py +0 -218
- egse/spw.py +0 -1479
- egse/stages/__init__.py +0 -12
- egse/stages/aerotech/ensemble.py +0 -247
- egse/stages/aerotech/ensemble.yaml +0 -205
- egse/stages/aerotech/ensemble_controller.py +0 -275
- egse/stages/aerotech/ensemble_cs.py +0 -110
- egse/stages/aerotech/ensemble_interface.py +0 -132
- egse/stages/aerotech/ensemble_parameters.py +0 -433
- egse/stages/aerotech/ensemble_simulator.py +0 -27
- egse/stages/aerotech/mgse_sim.py +0 -193
- egse/stages/arun/smd3.py +0 -111
- egse/stages/arun/smd3.yaml +0 -68
- egse/stages/arun/smd3_controller.py +0 -472
- egse/stages/arun/smd3_cs.py +0 -112
- egse/stages/arun/smd3_interface.py +0 -53
- egse/stages/arun/smd3_simulator.py +0 -27
- egse/stages/arun/smd3_stop.py +0 -16
- egse/stages/huber/__init__.py +0 -49
- egse/stages/huber/smc9300.py +0 -904
- egse/stages/huber/smc9300.yaml +0 -63
- egse/stages/huber/smc9300_cs.py +0 -178
- egse/stages/huber/smc9300_devif.py +0 -345
- egse/stages/huber/smc9300_protocol.py +0 -111
- egse/stages/huber/smc9300_sim.py +0 -547
- egse/stages/huber/smc9300_ui.py +0 -973
- egse/state.py +0 -173
- egse/statemachine.py +0 -274
- egse/storage/__init__.py +0 -1004
- egse/storage/persistence.py +0 -2295
- egse/storage/storage.yaml +0 -72
- egse/storage/storage_cs.py +0 -214
- egse/styles/dark.qss +0 -343
- egse/styles/default.qss +0 -48
- egse/synoptics/__init__.py +0 -412
- egse/synoptics/syn.yaml +0 -9
- egse/synoptics/syn_cs.py +0 -195
- egse/system.py +0 -1408
- egse/tcs/__init__.py +0 -14
- egse/tcs/tcs.py +0 -874
- egse/tcs/tcs.yaml +0 -14
- egse/tcs/tcs_cs.py +0 -202
- egse/tcs/tcs_devif.py +0 -292
- egse/tcs/tcs_protocol.py +0 -177
- egse/tcs/tcs_sim.py +0 -177
- egse/tcs/tcs_ui.py +0 -543
- egse/tdms.py +0 -171
- egse/tempcontrol/__init__.py +0 -23
- egse/tempcontrol/agilent/agilent34970.py +0 -109
- egse/tempcontrol/agilent/agilent34970.yaml +0 -44
- egse/tempcontrol/agilent/agilent34970_cs.py +0 -116
- egse/tempcontrol/agilent/agilent34970_devif.py +0 -182
- egse/tempcontrol/agilent/agilent34970_protocol.py +0 -99
- egse/tempcontrol/agilent/agilent34972.py +0 -111
- egse/tempcontrol/agilent/agilent34972.yaml +0 -44
- egse/tempcontrol/agilent/agilent34972_cs.py +0 -117
- egse/tempcontrol/agilent/agilent34972_devif.py +0 -189
- egse/tempcontrol/agilent/agilent34972_protocol.py +0 -101
- egse/tempcontrol/beaglebone/beaglebone.py +0 -342
- egse/tempcontrol/beaglebone/beaglebone.yaml +0 -110
- egse/tempcontrol/beaglebone/beaglebone_cs.py +0 -117
- egse/tempcontrol/beaglebone/beaglebone_protocol.py +0 -135
- egse/tempcontrol/beaglebone/beaglebone_ui.py +0 -681
- egse/tempcontrol/digalox/digalox.py +0 -107
- egse/tempcontrol/digalox/digalox.yaml +0 -36
- egse/tempcontrol/digalox/digalox_cs.py +0 -112
- egse/tempcontrol/digalox/digalox_protocol.py +0 -55
- egse/tempcontrol/keithley/__init__.py +0 -33
- egse/tempcontrol/keithley/daq6510.py +0 -662
- egse/tempcontrol/keithley/daq6510.yaml +0 -105
- egse/tempcontrol/keithley/daq6510_cs.py +0 -163
- egse/tempcontrol/keithley/daq6510_devif.py +0 -343
- egse/tempcontrol/keithley/daq6510_protocol.py +0 -78
- egse/tempcontrol/keithley/daq6510_sim.py +0 -186
- egse/tempcontrol/lakeshore/__init__.py +0 -33
- egse/tempcontrol/lakeshore/lsci.py +0 -361
- egse/tempcontrol/lakeshore/lsci.yaml +0 -162
- egse/tempcontrol/lakeshore/lsci_cs.py +0 -174
- egse/tempcontrol/lakeshore/lsci_devif.py +0 -292
- egse/tempcontrol/lakeshore/lsci_protocol.py +0 -73
- egse/tempcontrol/lakeshore/lsci_ui.py +0 -389
- egse/tempcontrol/ni/__init__.py +0 -0
- egse/tempcontrol/spid/spid.py +0 -109
- egse/tempcontrol/spid/spid.yaml +0 -81
- egse/tempcontrol/spid/spid_controller.py +0 -279
- egse/tempcontrol/spid/spid_cs.py +0 -136
- egse/tempcontrol/spid/spid_protocol.py +0 -107
- egse/tempcontrol/spid/spid_ui.py +0 -727
- egse/tempcontrol/srs/__init__.py +0 -22
- egse/tempcontrol/srs/ptc10.py +0 -875
- egse/tempcontrol/srs/ptc10.yaml +0 -227
- egse/tempcontrol/srs/ptc10_cs.py +0 -128
- egse/tempcontrol/srs/ptc10_devif.py +0 -118
- egse/tempcontrol/srs/ptc10_protocol.py +0 -42
- egse/tempcontrol/srs/ptc10_ui.py +0 -906
- egse/ups/apc/apc.py +0 -236
- egse/ups/apc/apc.yaml +0 -45
- egse/ups/apc/apc_cs.py +0 -101
- egse/ups/apc/apc_protocol.py +0 -125
- egse/user.yaml +0 -7
- egse/vacuum/beaglebone/beaglebone.py +0 -149
- egse/vacuum/beaglebone/beaglebone.yaml +0 -44
- egse/vacuum/beaglebone/beaglebone_cs.py +0 -108
- egse/vacuum/beaglebone/beaglebone_devif.py +0 -164
- egse/vacuum/beaglebone/beaglebone_protocol.py +0 -193
- egse/vacuum/beaglebone/beaglebone_ui.py +0 -638
- egse/vacuum/instrutech/igm402.py +0 -92
- egse/vacuum/instrutech/igm402.yaml +0 -90
- egse/vacuum/instrutech/igm402_controller.py +0 -128
- egse/vacuum/instrutech/igm402_cs.py +0 -108
- egse/vacuum/instrutech/igm402_interface.py +0 -49
- egse/vacuum/instrutech/igm402_simulator.py +0 -36
- egse/vacuum/keller/kellerBus.py +0 -256
- egse/vacuum/keller/leo3.py +0 -102
- egse/vacuum/keller/leo3.yaml +0 -38
- egse/vacuum/keller/leo3_controller.py +0 -83
- egse/vacuum/keller/leo3_cs.py +0 -101
- egse/vacuum/keller/leo3_interface.py +0 -33
- egse/vacuum/mks/evision.py +0 -86
- egse/vacuum/mks/evision.yaml +0 -75
- egse/vacuum/mks/evision_cs.py +0 -101
- egse/vacuum/mks/evision_devif.py +0 -316
- egse/vacuum/mks/evision_interface.py +0 -60
- egse/vacuum/mks/evision_simulator.py +0 -24
- egse/vacuum/mks/evision_ui.py +0 -704
- egse/vacuum/pfeiffer/acp40.py +0 -87
- egse/vacuum/pfeiffer/acp40.yaml +0 -60
- egse/vacuum/pfeiffer/acp40_controller.py +0 -117
- egse/vacuum/pfeiffer/acp40_cs.py +0 -109
- egse/vacuum/pfeiffer/acp40_interface.py +0 -40
- egse/vacuum/pfeiffer/acp40_simulator.py +0 -39
- egse/vacuum/pfeiffer/tc400.py +0 -113
- egse/vacuum/pfeiffer/tc400.yaml +0 -83
- egse/vacuum/pfeiffer/tc400_controller.py +0 -140
- egse/vacuum/pfeiffer/tc400_cs.py +0 -109
- egse/vacuum/pfeiffer/tc400_interface.py +0 -70
- egse/vacuum/pfeiffer/tc400_simulator.py +0 -24
- egse/vacuum/pfeiffer/tpg261.py +0 -81
- egse/vacuum/pfeiffer/tpg261.yaml +0 -66
- egse/vacuum/pfeiffer/tpg261_controller.py +0 -150
- egse/vacuum/pfeiffer/tpg261_cs.py +0 -109
- egse/vacuum/pfeiffer/tpg261_interface.py +0 -60
- egse/vacuum/pfeiffer/tpg261_simulator.py +0 -24
- egse/version.py +0 -174
- egse/visitedpositions.py +0 -398
- egse/windowing.py +0 -213
- egse/zmq/__init__.py +0 -28
- egse/zmq/spw.py +0 -160
- egse/zmq_ser.py +0 -41
- scripts/alerts/cold.yaml +0 -278
- scripts/alerts/example_alerts.yaml +0 -54
- scripts/alerts/transition.yaml +0 -14
- scripts/alerts/warm.yaml +0 -49
- scripts/analyse_n_fee_hk_data.py +0 -44
- scripts/check_hdf5_files.py +0 -192
- scripts/check_register_sync.py +0 -47
- scripts/create_hdf5_report.py +0 -295
- scripts/csl_model.py +0 -436
- scripts/csl_restore_setup.py +0 -230
- scripts/export-grafana-dashboards.py +0 -50
- scripts/fdir/cs_recovery/fdir_cs_recovery.py +0 -59
- scripts/fdir/fdir_table.yaml +0 -70
- scripts/fdir/fdir_test_recovery.py +0 -11
- scripts/fdir/hw_recovery/fdir_agilent_hw_recovery.py +0 -73
- scripts/fdir/limit_recovery/fdir_agilent_limit.py +0 -64
- scripts/fdir/limit_recovery/fdir_bb_heater_limit.py +0 -61
- scripts/fdir/limit_recovery/fdir_ensemble_limit.py +0 -33
- scripts/fdir/limit_recovery/fdir_pressure_limit_recovery.py +0 -71
- scripts/fix_csv.py +0 -80
- scripts/n_fee_supply_voltage_calculation.py +0 -92
- scripts/playground.py +0 -30
- scripts/print_hdf5_hk_data.py +0 -68
- scripts/print_register_map.py +0 -43
- scripts/sron/commanding/control_heaters.py +0 -44
- scripts/sron/commanding/pumpdown.py +0 -46
- scripts/sron/commanding/set_pid_setpoint.py +0 -19
- scripts/sron/commanding/shutdown_bbb_heaters.py +0 -10
- scripts/sron/commanding/shutdown_pumps.py +0 -33
- scripts/sron/tm_gen/tm_gen_agilent.py +0 -38
- scripts/sron/tm_gen/tm_gen_heaters.py +0 -4
- scripts/sron/tm_gen/tm_gen_spid.py +0 -13
- scripts/update_operational_cgse.py +0 -268
- scripts/update_operational_cgse_old.py +0 -273
egse/stages/huber/smc9300_ui.py
DELETED
|
@@ -1,973 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
A Graphical User Interface for monitoring and commanding the HUBER Stages.
|
|
3
|
-
|
|
4
|
-
Start the GUI from your terminal as follows:
|
|
5
|
-
|
|
6
|
-
smc9300_ui [--type proxy|direct|simulator]
|
|
7
|
-
|
|
8
|
-
The application is completely written in Python/Qt5 and can therefore run on any
|
|
9
|
-
platform that supports Python and Qt5.
|
|
10
|
-
|
|
11
|
-
"""
|
|
12
|
-
import argparse
|
|
13
|
-
import logging
|
|
14
|
-
import multiprocessing
|
|
15
|
-
from pathlib import Path
|
|
16
|
-
|
|
17
|
-
import sys
|
|
18
|
-
import textwrap
|
|
19
|
-
import threading
|
|
20
|
-
from typing import Callable
|
|
21
|
-
from typing import Optional
|
|
22
|
-
|
|
23
|
-
from egse.stages.huber.smc9300 import HuberSMC9300Interface
|
|
24
|
-
|
|
25
|
-
multiprocessing.current_process().name = "smc9300_ui"
|
|
26
|
-
|
|
27
|
-
import pyqtgraph as pg
|
|
28
|
-
from PyQt5.QtCore import QSize, QLockFile
|
|
29
|
-
from PyQt5.QtCore import QTime
|
|
30
|
-
from PyQt5.QtCore import QTimer
|
|
31
|
-
from PyQt5.QtCore import Qt
|
|
32
|
-
from PyQt5.QtGui import QIcon
|
|
33
|
-
from PyQt5.QtGui import QIntValidator
|
|
34
|
-
from PyQt5.QtWidgets import QAction, QMessageBox
|
|
35
|
-
from PyQt5.QtWidgets import QApplication
|
|
36
|
-
from PyQt5.QtWidgets import QComboBox
|
|
37
|
-
from PyQt5.QtWidgets import QDialog
|
|
38
|
-
from PyQt5.QtWidgets import QDialogButtonBox
|
|
39
|
-
from PyQt5.QtWidgets import QFrame
|
|
40
|
-
from PyQt5.QtWidgets import QGridLayout
|
|
41
|
-
from PyQt5.QtWidgets import QGroupBox
|
|
42
|
-
from PyQt5.QtWidgets import QHBoxLayout
|
|
43
|
-
from PyQt5.QtWidgets import QLabel
|
|
44
|
-
from PyQt5.QtWidgets import QLineEdit
|
|
45
|
-
from PyQt5.QtWidgets import QMainWindow
|
|
46
|
-
from PyQt5.QtWidgets import QPushButton
|
|
47
|
-
from PyQt5.QtWidgets import QSizePolicy
|
|
48
|
-
from PyQt5.QtWidgets import QVBoxLayout
|
|
49
|
-
from PyQt5.QtWidgets import QWidget
|
|
50
|
-
from prometheus_client import Summary
|
|
51
|
-
from prometheus_client import start_http_server
|
|
52
|
-
|
|
53
|
-
from egse.decorators import deprecate
|
|
54
|
-
from egse.gui import VLine
|
|
55
|
-
from egse.gui import show_warning_message
|
|
56
|
-
from egse.gui.buttons import ToggleButton
|
|
57
|
-
from egse.gui.buttons import TouchButton
|
|
58
|
-
from egse.gui.limitswitch import Indic
|
|
59
|
-
from egse.gui.limitswitch import LimitSwitch
|
|
60
|
-
from egse.gui.stripchart import StripChart
|
|
61
|
-
from egse.help.help_ui import HELP_TOPICS
|
|
62
|
-
from egse.help.help_ui import HelpWindow
|
|
63
|
-
from egse.observer import Observable
|
|
64
|
-
from egse.observer import Observer
|
|
65
|
-
from egse.process import ProcessStatus
|
|
66
|
-
from egse.resource import get_resource
|
|
67
|
-
from egse.settings import Settings
|
|
68
|
-
from egse.stages.huber.smc9300 import HuberSMC9300Controller
|
|
69
|
-
from egse.stages.huber.smc9300 import HuberSMC9300Proxy
|
|
70
|
-
from egse.stages.huber.smc9300 import HuberSMC9300Simulator
|
|
71
|
-
from egse.state import UnknownStateError
|
|
72
|
-
from egse.system import do_every
|
|
73
|
-
|
|
74
|
-
MODULE_LOGGER = logging.getLogger(__name__)
|
|
75
|
-
|
|
76
|
-
SETTINGS = Settings.load("Huber Controller")
|
|
77
|
-
GUI_SETTINGS = Settings.load("SMC9300 GUI")
|
|
78
|
-
|
|
79
|
-
AXIS_NAMES = {
|
|
80
|
-
SETTINGS.BIG_ROTATION_STAGE: "Big Rotation Stage",
|
|
81
|
-
SETTINGS.SMALL_ROTATION_STAGE: "Small Rotation Stage",
|
|
82
|
-
SETTINGS.TRANSLATION_STAGE: "Translation Stage",
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
AXIS_LABELS = {
|
|
86
|
-
SETTINGS.BIG_ROTATION_STAGE: "ROT 01",
|
|
87
|
-
SETTINGS.SMALL_ROTATION_STAGE: "ROT 02",
|
|
88
|
-
SETTINGS.TRANSLATION_STAGE: "TRANS 03",
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
class Stage(QFrame, Observable):
|
|
93
|
-
"""
|
|
94
|
-
Generic GUI Frame for one of the HUBER stages.
|
|
95
|
-
|
|
96
|
-
Args:
|
|
97
|
-
title: The full name of the stage
|
|
98
|
-
label: A short label to identify the stage
|
|
99
|
-
stage_nr: the integer ID for the stage
|
|
100
|
-
"""
|
|
101
|
-
|
|
102
|
-
def __init__(self, title: str, label: str, stage_nr: int, unit: str, unit_long: str):
|
|
103
|
-
|
|
104
|
-
super().__init__()
|
|
105
|
-
|
|
106
|
-
self._title = title
|
|
107
|
-
self._label = label
|
|
108
|
-
self._stage_nr = stage_nr
|
|
109
|
-
self._unit = unit
|
|
110
|
-
self._unit_long = unit_long
|
|
111
|
-
|
|
112
|
-
self._encoder_type = True
|
|
113
|
-
|
|
114
|
-
self.current_position = None
|
|
115
|
-
self.current_position_edit = None
|
|
116
|
-
self.current_encoder_position = None
|
|
117
|
-
|
|
118
|
-
self.movement_type = None
|
|
119
|
-
self.move_button = None
|
|
120
|
-
|
|
121
|
-
self.stripchart = None
|
|
122
|
-
|
|
123
|
-
self.slew_speed_label: QLabel = QLabel()
|
|
124
|
-
|
|
125
|
-
self.limit_switch_state: LimitSwitch = LimitSwitch(size=QSize(15, 15))
|
|
126
|
-
|
|
127
|
-
def create_gui(self):
|
|
128
|
-
|
|
129
|
-
toolbar = StageToolBar(connect=self.axis_settings)
|
|
130
|
-
|
|
131
|
-
group_box = QGroupBox(self._title)
|
|
132
|
-
|
|
133
|
-
# Create the label fields that display the current position and encoder values -------------
|
|
134
|
-
|
|
135
|
-
grid_show = QGridLayout()
|
|
136
|
-
grid_show.setSpacing(0)
|
|
137
|
-
|
|
138
|
-
grid_show.addWidget(QLabel(self._label), 0, 0)
|
|
139
|
-
|
|
140
|
-
self.current_position = QLabel(self)
|
|
141
|
-
self.current_position.setAlignment(Qt.AlignRight)
|
|
142
|
-
self.current_position.setText("0.0000")
|
|
143
|
-
|
|
144
|
-
grid_show.addWidget(self.current_position, 0, 1)
|
|
145
|
-
|
|
146
|
-
self.current_encoder_position = QLabel(self)
|
|
147
|
-
self.current_encoder_position.setAlignment(Qt.AlignRight)
|
|
148
|
-
self.current_encoder_position.setText("0.0000")
|
|
149
|
-
self.current_encoder_position.setStyleSheet("font: 9pt;")
|
|
150
|
-
self.current_encoder_position.mouseReleaseEvent = self.set_encoder_type
|
|
151
|
-
|
|
152
|
-
grid_show.addWidget(self.current_encoder_position, 1, 1)
|
|
153
|
-
|
|
154
|
-
grid_show.addWidget(QLabel(f" {self._unit}"), 0, 2)
|
|
155
|
-
|
|
156
|
-
grid_show.setColumnStretch(1, 10)
|
|
157
|
-
|
|
158
|
-
# Create the edit text field for setting the position --------------------------------------
|
|
159
|
-
|
|
160
|
-
hbox_edit = QHBoxLayout()
|
|
161
|
-
hbox_edit.setContentsMargins(0, 0, 0, 0)
|
|
162
|
-
|
|
163
|
-
self.current_position_edit = QLineEdit(self)
|
|
164
|
-
self.current_position_edit.setAlignment(Qt.AlignRight)
|
|
165
|
-
self.current_position_edit.setText("0.0000")
|
|
166
|
-
|
|
167
|
-
self.movement_type = QComboBox()
|
|
168
|
-
|
|
169
|
-
self.movement_type.addItems(["Absolute", "Relative"])
|
|
170
|
-
self.movement_type.setMinimumContentsLength(8)
|
|
171
|
-
self.movement_type.adjustSize()
|
|
172
|
-
|
|
173
|
-
self.move_button = QPushButton("Move To")
|
|
174
|
-
self.move_button.setToolTip(
|
|
175
|
-
"Perform a relative or absolute movement according to selection in the combobox."
|
|
176
|
-
"<ul>"
|
|
177
|
-
"<li><strong>Relative</strong> moves the stage relative to the current position"
|
|
178
|
-
"<li><strong>Absolute</strong> moves the stage to the given absolute position"
|
|
179
|
-
"</ul>"
|
|
180
|
-
)
|
|
181
|
-
self.move_button.clicked.connect(self.goto_position)
|
|
182
|
-
|
|
183
|
-
hbox_edit.addWidget(QLabel("Set position: "))
|
|
184
|
-
hbox_edit.addWidget(self.current_position_edit)
|
|
185
|
-
hbox_edit.addWidget(QLabel(self._unit))
|
|
186
|
-
hbox_edit.addWidget(self.movement_type)
|
|
187
|
-
hbox_edit.addWidget(self.move_button)
|
|
188
|
-
|
|
189
|
-
vbox = QVBoxLayout()
|
|
190
|
-
vbox.setSpacing(4)
|
|
191
|
-
vbox.addLayout(grid_show)
|
|
192
|
-
vbox.addStretch(1)
|
|
193
|
-
vbox.addLayout(hbox_edit)
|
|
194
|
-
|
|
195
|
-
# Add a StripChart for this stage ----------------------------------------------------------
|
|
196
|
-
|
|
197
|
-
self.stripchart = StripChart(
|
|
198
|
-
labels={"left": ("Position", f"{self._unit_long}"), "bottom": ("Time", "hh:mm:ss")}
|
|
199
|
-
)
|
|
200
|
-
vbox.addWidget(self.stripchart)
|
|
201
|
-
|
|
202
|
-
group_box.setLayout(vbox)
|
|
203
|
-
|
|
204
|
-
# The settings box contains the view on the speed and other settings -----------------------
|
|
205
|
-
|
|
206
|
-
settings_box = QHBoxLayout()
|
|
207
|
-
|
|
208
|
-
settings_box.addWidget(self.limit_switch_state)
|
|
209
|
-
settings_box.addWidget(QLabel("Speed:"))
|
|
210
|
-
settings_box.addWidget(self.slew_speed_label)
|
|
211
|
-
settings_box.addStretch()
|
|
212
|
-
|
|
213
|
-
vbox = QVBoxLayout()
|
|
214
|
-
vbox.setSpacing(4)
|
|
215
|
-
vbox.setContentsMargins(0, 0, 0, 0)
|
|
216
|
-
vbox.addWidget(toolbar)
|
|
217
|
-
vbox.addWidget(group_box)
|
|
218
|
-
vbox.addLayout(settings_box)
|
|
219
|
-
self.setLayout(vbox)
|
|
220
|
-
|
|
221
|
-
def axis_settings(self):
|
|
222
|
-
MODULE_LOGGER.info(f"Handle settings for axis {self._stage_nr}.")
|
|
223
|
-
settings = SettingsDialog(self._stage_nr, self.slew_speed_label.text(), parent=self)
|
|
224
|
-
if rc := settings.exec():
|
|
225
|
-
slew_speed = int(settings.speed_box.text())
|
|
226
|
-
MODULE_LOGGER.debug(f"{rc=}, {slew_speed=}")
|
|
227
|
-
self.actionObservers({"set_speed": (self._stage_nr, slew_speed)})
|
|
228
|
-
|
|
229
|
-
def goto_position(self):
|
|
230
|
-
new_position = float(self.current_position_edit.text())
|
|
231
|
-
movement_type = self.movement_type.currentText()
|
|
232
|
-
|
|
233
|
-
cmd = "move_absolute" if movement_type == "Absolute" else "move_relative"
|
|
234
|
-
|
|
235
|
-
self.actionObservers({cmd: [self._stage_nr, new_position]})
|
|
236
|
-
|
|
237
|
-
def set_encoder_type(self, event):
|
|
238
|
-
self._encoder_type = not self._encoder_type
|
|
239
|
-
|
|
240
|
-
def update_encoder_position(self, position, counter):
|
|
241
|
-
if self._encoder_type:
|
|
242
|
-
self.current_encoder_position.setText(f"{position:.6f}")
|
|
243
|
-
else:
|
|
244
|
-
self.current_encoder_position.setText(f"{counter:.0f}")
|
|
245
|
-
|
|
246
|
-
def update_current_position(self, position):
|
|
247
|
-
self.current_position.setText(f"{position:.4f}")
|
|
248
|
-
|
|
249
|
-
def update_speed(self, speed):
|
|
250
|
-
self.slew_speed_label.setText(f"{speed}")
|
|
251
|
-
|
|
252
|
-
def update_limit_switch_state(self, state: int):
|
|
253
|
-
self.limit_switch_state.set_state(Indic.from_state(state))
|
|
254
|
-
|
|
255
|
-
def update_stripchart(self, time, position):
|
|
256
|
-
self.stripchart.update(time, position)
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
class BigRotationStage(Stage):
|
|
260
|
-
def __init__(self):
|
|
261
|
-
super().__init__(
|
|
262
|
-
AXIS_NAMES[SETTINGS.BIG_ROTATION_STAGE],
|
|
263
|
-
AXIS_LABELS[SETTINGS.BIG_ROTATION_STAGE],
|
|
264
|
-
SETTINGS.BIG_ROTATION_STAGE,
|
|
265
|
-
unit="deg", unit_long="degrees",
|
|
266
|
-
)
|
|
267
|
-
self.create_gui()
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
class SmallRotationStage(Stage):
|
|
271
|
-
def __init__(self):
|
|
272
|
-
super().__init__(
|
|
273
|
-
AXIS_NAMES[SETTINGS.SMALL_ROTATION_STAGE],
|
|
274
|
-
AXIS_LABELS[SETTINGS.SMALL_ROTATION_STAGE],
|
|
275
|
-
SETTINGS.SMALL_ROTATION_STAGE,
|
|
276
|
-
unit="deg", unit_long="degrees",
|
|
277
|
-
)
|
|
278
|
-
self.create_gui()
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
class TranslationStage(Stage):
|
|
282
|
-
def __init__(self):
|
|
283
|
-
super().__init__(
|
|
284
|
-
AXIS_NAMES[SETTINGS.TRANSLATION_STAGE],
|
|
285
|
-
AXIS_LABELS[SETTINGS.TRANSLATION_STAGE],
|
|
286
|
-
SETTINGS.TRANSLATION_STAGE,
|
|
287
|
-
unit="mm", unit_long="millimeter",
|
|
288
|
-
)
|
|
289
|
-
self.create_gui()
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
class StageToolBar(QFrame):
|
|
293
|
-
def __init__(self, connect: Callable = None, parent: Optional[QWidget] = None):
|
|
294
|
-
super().__init__(parent=parent)
|
|
295
|
-
spacer = QWidget()
|
|
296
|
-
spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
|
297
|
-
|
|
298
|
-
toolbar_hbox = QHBoxLayout()
|
|
299
|
-
toolbar_hbox.setContentsMargins(0, 0, 0, 0)
|
|
300
|
-
toolbar_hbox.addWidget(spacer)
|
|
301
|
-
toolbar_hbox.setAlignment(Qt.AlignVCenter)
|
|
302
|
-
|
|
303
|
-
br_settings = TouchButton(
|
|
304
|
-
width=25, height=25, selected=get_resource(":/icons/settings.svg"),
|
|
305
|
-
parent=self
|
|
306
|
-
)
|
|
307
|
-
br_settings.clicked.connect(connect)
|
|
308
|
-
|
|
309
|
-
br_time_window = QComboBox(parent=self)
|
|
310
|
-
br_time_window.addItems(["5s", "10m", "1h", "12h"])
|
|
311
|
-
br_time_window.setCurrentIndex(1)
|
|
312
|
-
|
|
313
|
-
toolbar_hbox.addWidget(br_time_window)
|
|
314
|
-
toolbar_hbox.addWidget(br_settings)
|
|
315
|
-
|
|
316
|
-
self.setLayout(toolbar_hbox)
|
|
317
|
-
self.setContentsMargins(0, 0, 0, 0)
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
class HuberUIView(QMainWindow, Observable):
|
|
321
|
-
def __init__(self):
|
|
322
|
-
super().__init__()
|
|
323
|
-
|
|
324
|
-
# Define those variables that we will need/use in different methods
|
|
325
|
-
|
|
326
|
-
self.homing_action = None
|
|
327
|
-
self.clear_action = None
|
|
328
|
-
self.reconnect_action = None
|
|
329
|
-
self.toolbar = None
|
|
330
|
-
|
|
331
|
-
self.homing = None
|
|
332
|
-
self.clear_errors = None
|
|
333
|
-
self.cs_connection = None
|
|
334
|
-
self.device_connection = None
|
|
335
|
-
self.stop_action = None
|
|
336
|
-
self.help_action = None
|
|
337
|
-
|
|
338
|
-
# Switch to using white background and black foreground for pyqtgraph stripcharts
|
|
339
|
-
# This must be done before the pyqtgraphs are created.
|
|
340
|
-
|
|
341
|
-
pg.setConfigOption("background", "w")
|
|
342
|
-
pg.setConfigOption("foreground", "k")
|
|
343
|
-
|
|
344
|
-
self.big_rotation_stage = BigRotationStage()
|
|
345
|
-
self.small_rotation_stage = SmallRotationStage()
|
|
346
|
-
self.translation_stage = TranslationStage()
|
|
347
|
-
|
|
348
|
-
self.setGeometry(300, 300, 1500, 500)
|
|
349
|
-
self.setWindowTitle("Huber Controller")
|
|
350
|
-
|
|
351
|
-
# The mode_label describes the current mode in which the controller is running.
|
|
352
|
-
# The mode can be Proxy, Simulator, Direct
|
|
353
|
-
|
|
354
|
-
self.mode_label = QLabel("")
|
|
355
|
-
|
|
356
|
-
self.axes = {
|
|
357
|
-
SETTINGS.BIG_ROTATION_STAGE: self.big_rotation_stage,
|
|
358
|
-
SETTINGS.SMALL_ROTATION_STAGE: self.small_rotation_stage,
|
|
359
|
-
SETTINGS.TRANSLATION_STAGE: self.translation_stage,
|
|
360
|
-
}
|
|
361
|
-
|
|
362
|
-
# The main frame in which all the other frames are located, the outer Application frame
|
|
363
|
-
|
|
364
|
-
app_frame = QFrame()
|
|
365
|
-
app_frame.setObjectName("AppFrame")
|
|
366
|
-
|
|
367
|
-
hbox = QHBoxLayout()
|
|
368
|
-
|
|
369
|
-
self.create_toolbar()
|
|
370
|
-
self.create_status_bar()
|
|
371
|
-
|
|
372
|
-
hbox.addWidget(self.big_rotation_stage)
|
|
373
|
-
hbox.addWidget(self.small_rotation_stage)
|
|
374
|
-
hbox.addWidget(self.translation_stage)
|
|
375
|
-
|
|
376
|
-
app_frame.setLayout(hbox)
|
|
377
|
-
|
|
378
|
-
self.setCentralWidget(app_frame)
|
|
379
|
-
|
|
380
|
-
def addObserver(self, observer):
|
|
381
|
-
super().addObserver(observer)
|
|
382
|
-
self.big_rotation_stage.addObserver(observer)
|
|
383
|
-
self.small_rotation_stage.addObserver(observer)
|
|
384
|
-
self.translation_stage.addObserver(observer)
|
|
385
|
-
|
|
386
|
-
def is_cs_action_enabled(self):
|
|
387
|
-
return self.cs_connection.isEnabled()
|
|
388
|
-
|
|
389
|
-
def disable_cs_action(self):
|
|
390
|
-
self.cs_connection.disable()
|
|
391
|
-
|
|
392
|
-
def enable_cs_action(self):
|
|
393
|
-
self.cs_connection.enable()
|
|
394
|
-
|
|
395
|
-
def check_cs_action(self):
|
|
396
|
-
self.cs_connection.set_selected()
|
|
397
|
-
|
|
398
|
-
def uncheck_cs_action(self):
|
|
399
|
-
self.cs_connection.set_selected(False)
|
|
400
|
-
|
|
401
|
-
def check_device_action(self):
|
|
402
|
-
self.device_connection.set_selected()
|
|
403
|
-
|
|
404
|
-
def uncheck_device_action(self):
|
|
405
|
-
self.device_connection.set_selected(False)
|
|
406
|
-
|
|
407
|
-
def set_connection_state(self, state):
|
|
408
|
-
# enable or disable all actions that involve a device or cs connection
|
|
409
|
-
# don't change the action buttons for the device nor the cs, that is handled
|
|
410
|
-
# in the caller because it might be a device connection loss that causes this state
|
|
411
|
-
# or a control server, or both...
|
|
412
|
-
|
|
413
|
-
MODULE_LOGGER.debug(f"{state=}")
|
|
414
|
-
|
|
415
|
-
if state == "connected":
|
|
416
|
-
self.homing.enable()
|
|
417
|
-
self.clear_errors.enable()
|
|
418
|
-
elif state == "disconnected":
|
|
419
|
-
self.homing.disable()
|
|
420
|
-
self.clear_errors.disable()
|
|
421
|
-
else:
|
|
422
|
-
raise UnknownStateError(
|
|
423
|
-
f"Unknown State ({state}), expected 'connected' or 'disconnected'."
|
|
424
|
-
)
|
|
425
|
-
|
|
426
|
-
def create_status_bar(self):
|
|
427
|
-
|
|
428
|
-
self.statusBar().setStyleSheet("border: 0; background-color: #FFF8DC;")
|
|
429
|
-
self.statusBar().setStyleSheet("QStatusBar::item {border: none;}")
|
|
430
|
-
self.statusBar().addPermanentWidget(VLine())
|
|
431
|
-
self.statusBar().addPermanentWidget(self.mode_label)
|
|
432
|
-
|
|
433
|
-
def create_toolbar(self):
|
|
434
|
-
|
|
435
|
-
# The Home action is used to command the Homing to the Hexapod.
|
|
436
|
-
|
|
437
|
-
self.homing = TouchButton(
|
|
438
|
-
name="HOMING",
|
|
439
|
-
status_tip="perform a homing operation (ON ALL THE STAGES)",
|
|
440
|
-
selected=get_resource(":/icons/home.svg"),
|
|
441
|
-
disabled=get_resource(":/icons/home-disabled.svg"),
|
|
442
|
-
)
|
|
443
|
-
self.homing.clicked.connect(self.on_click)
|
|
444
|
-
|
|
445
|
-
# The Clear action is used to command the ClearErrors to the Hexapod.
|
|
446
|
-
|
|
447
|
-
self.clear_errors = TouchButton(
|
|
448
|
-
name="CLEAR-ERRORS",
|
|
449
|
-
status_tip="clear the error list on the controller (FOR ALL STAGES)",
|
|
450
|
-
selected=get_resource(":/icons/erase.svg"),
|
|
451
|
-
disabled=get_resource(":/icons/erase-disabled.svg"),
|
|
452
|
-
)
|
|
453
|
-
self.clear_errors.clicked.connect(self.on_click)
|
|
454
|
-
|
|
455
|
-
# The Reconnect action is used to reconnect to the control server
|
|
456
|
-
|
|
457
|
-
self.cs_connection = ToggleButton(
|
|
458
|
-
name="CS-CONNECT",
|
|
459
|
-
status_tip="connect-disconnect huber stages control server.",
|
|
460
|
-
selected=get_resource(":/icons/cs-connected.svg"),
|
|
461
|
-
not_selected=get_resource(":/icons/cs-not-connected.svg"),
|
|
462
|
-
disabled=get_resource(":/icons/cs-connected-disabled.svg")
|
|
463
|
-
)
|
|
464
|
-
self.cs_connection.clicked.connect(self.on_click)
|
|
465
|
-
|
|
466
|
-
# The Reconnect action is used to reconnect the device
|
|
467
|
-
|
|
468
|
-
self.device_connection = ToggleButton(
|
|
469
|
-
name="DEVICE-CONNECT",
|
|
470
|
-
status_tip="connect-disconnect the huber stages controller",
|
|
471
|
-
selected=get_resource(":/icons/plugged.svg"),
|
|
472
|
-
not_selected=get_resource(":/icons/unplugged.svg"),
|
|
473
|
-
disabled=get_resource(":/icons/plugged-disabled.svg")
|
|
474
|
-
)
|
|
475
|
-
self.device_connection.clicked.connect(self.on_click)
|
|
476
|
-
|
|
477
|
-
# The STOP button is used to immediately stop the current motion
|
|
478
|
-
|
|
479
|
-
stop_button = QIcon(str(get_resource(":/icons/stop.svg")))
|
|
480
|
-
|
|
481
|
-
self.stop_action = QAction(stop_button, "STOP", self)
|
|
482
|
-
self.stop_action.setToolTip("STOP Movement")
|
|
483
|
-
self.stop_action.triggered.connect(self.on_click)
|
|
484
|
-
|
|
485
|
-
# The HELP button is used to show the on-line help in a browser window
|
|
486
|
-
|
|
487
|
-
help_button = QIcon(str(get_resource(":/icons/info.svg")))
|
|
488
|
-
|
|
489
|
-
self.help_action = QAction(help_button, "INFO", self)
|
|
490
|
-
self.help_action.setToolTip("Browse the on-line documentation")
|
|
491
|
-
self.help_action.triggered.connect(self.on_click)
|
|
492
|
-
|
|
493
|
-
# spacer widget to help with aligning STOP button to the right
|
|
494
|
-
|
|
495
|
-
spacer = QWidget()
|
|
496
|
-
spacer.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
|
497
|
-
|
|
498
|
-
self.toolbar = self.addToolBar("MainToolbar")
|
|
499
|
-
self.toolbar.addWidget(self.homing)
|
|
500
|
-
self.toolbar.addWidget(self.clear_errors)
|
|
501
|
-
self.toolbar.addWidget(self.device_connection)
|
|
502
|
-
self.toolbar.addWidget(self.cs_connection)
|
|
503
|
-
self.toolbar.addWidget(spacer)
|
|
504
|
-
self.toolbar.addAction(self.stop_action)
|
|
505
|
-
self.toolbar.addAction(self.help_action)
|
|
506
|
-
|
|
507
|
-
return self.toolbar
|
|
508
|
-
|
|
509
|
-
def update_stripchart(self, axis, time, pos):
|
|
510
|
-
self.axes[axis].stripchart.update(time, pos)
|
|
511
|
-
|
|
512
|
-
def update_status_bar(self, message=None, mode=None, timeout=2000):
|
|
513
|
-
if message:
|
|
514
|
-
self.statusBar().showMessage(message, msecs=timeout)
|
|
515
|
-
if mode:
|
|
516
|
-
self.mode_label.setStyleSheet(
|
|
517
|
-
f"border: 0; " f"color: {'red' if 'Simulator' in mode else 'black'};"
|
|
518
|
-
)
|
|
519
|
-
self.mode_label.setText(f"mode: {mode}")
|
|
520
|
-
self.statusBar().repaint()
|
|
521
|
-
|
|
522
|
-
def update_position(self, axis, position):
|
|
523
|
-
self.axes[axis].update_current_position(position)
|
|
524
|
-
|
|
525
|
-
def update_speed(self, axis, speed):
|
|
526
|
-
self.axes[axis].update_speed(speed)
|
|
527
|
-
|
|
528
|
-
def update_encoder_position(self, axis, position, counter):
|
|
529
|
-
self.axes[axis].update_encoder_position(position, counter)
|
|
530
|
-
|
|
531
|
-
def on_click(self):
|
|
532
|
-
|
|
533
|
-
sender = self.sender()
|
|
534
|
-
|
|
535
|
-
# MODULE_LOGGER.debug(f"sender.text() = {sender.text()}")
|
|
536
|
-
# MODULE_LOGGER.debug(f"sender.isChecked() = {sender.isChecked()}")
|
|
537
|
-
|
|
538
|
-
self.notifyObservers(sender)
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
class SettingsDialog(QDialog):
|
|
542
|
-
|
|
543
|
-
def __init__(self, axis: int, speed: int, parent=None): # <1>
|
|
544
|
-
super().__init__(parent)
|
|
545
|
-
|
|
546
|
-
self.axis = axis
|
|
547
|
-
self.speed = speed
|
|
548
|
-
|
|
549
|
-
self.setWindowTitle(f"Settings for {AXIS_NAMES[axis]}")
|
|
550
|
-
|
|
551
|
-
self.buttons = QDialogButtonBox.Ok | QDialogButtonBox.Cancel
|
|
552
|
-
|
|
553
|
-
self.buttonBox = QDialogButtonBox(self.buttons)
|
|
554
|
-
self.buttonBox.accepted.connect(self.accept)
|
|
555
|
-
self.buttonBox.rejected.connect(self.reject)
|
|
556
|
-
|
|
557
|
-
self.layout = QVBoxLayout()
|
|
558
|
-
hbox = QHBoxLayout()
|
|
559
|
-
message = QLabel("Slew speed:")
|
|
560
|
-
self.speed_box = QLineEdit(f"{self.speed}")
|
|
561
|
-
self.speed_box.setValidator(QIntValidator())
|
|
562
|
-
hbox.addWidget(message)
|
|
563
|
-
hbox.addWidget(self.speed_box)
|
|
564
|
-
self.layout.addLayout(hbox)
|
|
565
|
-
self.layout.addWidget(self.buttonBox)
|
|
566
|
-
self.setLayout(self.layout)
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
class CustomErrorDialog(QDialog):
|
|
570
|
-
def __init__(self, exc: Exception, parent=None):
|
|
571
|
-
super().__init__(parent)
|
|
572
|
-
|
|
573
|
-
self.exc = exc
|
|
574
|
-
|
|
575
|
-
self.title = f"{exc.__class__.__name__}"
|
|
576
|
-
self.setWindowTitle(self.title)
|
|
577
|
-
|
|
578
|
-
self.button_box = QDialogButtonBox(QDialogButtonBox.Ok)
|
|
579
|
-
self.button_box.accepted.connect(self.accept)
|
|
580
|
-
|
|
581
|
-
self.layout = QVBoxLayout()
|
|
582
|
-
message = QLabel(
|
|
583
|
-
textwrap.dedent(
|
|
584
|
-
f"""\
|
|
585
|
-
We caught a {self.exc.__class__.__name__}:
|
|
586
|
-
|
|
587
|
-
{self.exc.args[0]}
|
|
588
|
-
|
|
589
|
-
"""
|
|
590
|
-
))
|
|
591
|
-
self.layout.addWidget(message)
|
|
592
|
-
self.layout.addWidget(self.button_box)
|
|
593
|
-
self.setLayout(self.layout)
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
class HuberUIController(Observer):
|
|
597
|
-
def __init__(self, model, view):
|
|
598
|
-
self.model = model
|
|
599
|
-
self.view: HuberUIView = view
|
|
600
|
-
self.view.addObserver(self)
|
|
601
|
-
|
|
602
|
-
self.help_window = HelpWindow(topic_url=HELP_TOPICS["smc9300_ui"])
|
|
603
|
-
|
|
604
|
-
self._metrics = {
|
|
605
|
-
"execution_time": Summary('ui_update_execution_time_seconds',
|
|
606
|
-
'Time spent updating the values in the GUI', ["type"]),
|
|
607
|
-
}
|
|
608
|
-
|
|
609
|
-
self.states_capture_timer = None
|
|
610
|
-
self.states_capture_timer_interval = GUI_SETTINGS.STATES_TIMER_INTERVAL
|
|
611
|
-
self.stripchart_timer = None
|
|
612
|
-
self.stripchart_timer_interval = GUI_SETTINGS.STRIPCHART_TIMER_INTERVAL
|
|
613
|
-
self.create_timer()
|
|
614
|
-
|
|
615
|
-
try:
|
|
616
|
-
if self.model.is_device_connected():
|
|
617
|
-
mode = self.model.connection_type.capitalize()
|
|
618
|
-
if self.model.is_simulator():
|
|
619
|
-
mode = f"{mode} [Simulator]"
|
|
620
|
-
self.view.update_status_bar(mode=mode)
|
|
621
|
-
self.view.check_device_action()
|
|
622
|
-
else:
|
|
623
|
-
self.view.uncheck_device_action()
|
|
624
|
-
|
|
625
|
-
if self.model.is_cs_connected():
|
|
626
|
-
self.view.check_cs_action()
|
|
627
|
-
else:
|
|
628
|
-
self.view.uncheck_cs_action()
|
|
629
|
-
|
|
630
|
-
MODULE_LOGGER.debug(f"{self.model.is_device_connected()=}, {self.model.is_cs_connected()=}")
|
|
631
|
-
|
|
632
|
-
if model.connection_type in ["direct", "simulator"]:
|
|
633
|
-
view.disable_cs_action()
|
|
634
|
-
|
|
635
|
-
if self.has_connection():
|
|
636
|
-
self.view.set_connection_state("connected")
|
|
637
|
-
self.start_timer()
|
|
638
|
-
else:
|
|
639
|
-
self.view.set_connection_state("disconnected")
|
|
640
|
-
self.stop_timer()
|
|
641
|
-
except NotImplementedError:
|
|
642
|
-
MODULE_LOGGER.warning(
|
|
643
|
-
"There was no connection to the control server during startup, "
|
|
644
|
-
"GUI starts in disconnected mode."
|
|
645
|
-
)
|
|
646
|
-
self.view.uncheck_cs_action()
|
|
647
|
-
self.view.uncheck_device_action()
|
|
648
|
-
self.view.set_connection_state("disconnected")
|
|
649
|
-
|
|
650
|
-
def has_connection(self):
|
|
651
|
-
"""
|
|
652
|
-
Returns True if the controller has a connection to the device. This takes into account
|
|
653
|
-
that the control server might be disabled when the controller is directly connected to
|
|
654
|
-
the device or to a simulator.
|
|
655
|
-
"""
|
|
656
|
-
if self.view.is_cs_action_enabled():
|
|
657
|
-
return bool(self.model.is_device_connected() and self.model.is_cs_connected())
|
|
658
|
-
else:
|
|
659
|
-
return bool(self.model.is_device_connected())
|
|
660
|
-
|
|
661
|
-
def create_timer(self):
|
|
662
|
-
"""Create a Timer that will update the States every second."""
|
|
663
|
-
|
|
664
|
-
self.states_capture_timer = QTimer()
|
|
665
|
-
self.states_capture_timer.timeout.connect(self.update_values)
|
|
666
|
-
self.states_capture_timer.setInterval(self.states_capture_timer_interval)
|
|
667
|
-
|
|
668
|
-
self.stripchart_timer = QTimer()
|
|
669
|
-
self.stripchart_timer.timeout.connect(self.update_stripcharts)
|
|
670
|
-
self.stripchart_timer.setInterval(self.stripchart_timer_interval)
|
|
671
|
-
|
|
672
|
-
def start_timer(self):
|
|
673
|
-
self.states_capture_timer.start()
|
|
674
|
-
self.stripchart_timer.start()
|
|
675
|
-
|
|
676
|
-
def stop_timer(self):
|
|
677
|
-
self.states_capture_timer.stop()
|
|
678
|
-
self.stripchart_timer.stop()
|
|
679
|
-
|
|
680
|
-
def update_values(self):
|
|
681
|
-
|
|
682
|
-
with self._metrics["execution_time"].labels(type="values").time():
|
|
683
|
-
# This method should not be called when not connected, by design!
|
|
684
|
-
|
|
685
|
-
for axis in (
|
|
686
|
-
SETTINGS.BIG_ROTATION_STAGE,
|
|
687
|
-
SETTINGS.SMALL_ROTATION_STAGE,
|
|
688
|
-
SETTINGS.TRANSLATION_STAGE,
|
|
689
|
-
):
|
|
690
|
-
# If there is a communication problem with the server, resulting in a None being
|
|
691
|
-
# returned, we skip also the other updates.
|
|
692
|
-
if (pos := self.model.get_current_position(axis)) is None:
|
|
693
|
-
continue
|
|
694
|
-
self.view.update_position(axis, pos)
|
|
695
|
-
|
|
696
|
-
speed = self.model.get_speed(axis)
|
|
697
|
-
self.view.axes[axis].update_speed(speed)
|
|
698
|
-
|
|
699
|
-
pos = self.model.get_current_encoder_position(axis)
|
|
700
|
-
cnt = self.model.get_current_encoder_counter_value(axis)
|
|
701
|
-
self.view.update_encoder_position(axis, pos, cnt)
|
|
702
|
-
|
|
703
|
-
state = self.model.get_state(axis)
|
|
704
|
-
self.view.axes[axis].update_limit_switch_state(state)
|
|
705
|
-
|
|
706
|
-
def update_stripcharts(self):
|
|
707
|
-
|
|
708
|
-
with self._metrics["execution_time"].labels(type="stripcharts").time():
|
|
709
|
-
for axis in (
|
|
710
|
-
SETTINGS.BIG_ROTATION_STAGE,
|
|
711
|
-
SETTINGS.SMALL_ROTATION_STAGE,
|
|
712
|
-
SETTINGS.TRANSLATION_STAGE,
|
|
713
|
-
):
|
|
714
|
-
if (pos := self.model.get_current_position(axis)) is None:
|
|
715
|
-
continue
|
|
716
|
-
self.view.update_stripchart(axis, QTime.currentTime().msecsSinceStartOfDay(), pos)
|
|
717
|
-
|
|
718
|
-
def update(self, changed_object):
|
|
719
|
-
# This method is part of the Observer protocol and will be called when there is a
|
|
720
|
-
# notification of a change in the Observable.
|
|
721
|
-
|
|
722
|
-
text = changed_object.text()
|
|
723
|
-
|
|
724
|
-
if text == "STOP":
|
|
725
|
-
self.model.stop()
|
|
726
|
-
|
|
727
|
-
if text == "INFO":
|
|
728
|
-
self.help_window.show()
|
|
729
|
-
|
|
730
|
-
if text == "CS-CONNECT":
|
|
731
|
-
if changed_object.is_selected():
|
|
732
|
-
MODULE_LOGGER.debug("Reconnecting the HUBER Stages Control Server.")
|
|
733
|
-
self.model.reconnect_cs()
|
|
734
|
-
if not self.model.has_commands():
|
|
735
|
-
self.model.load_commands()
|
|
736
|
-
self.start_timer()
|
|
737
|
-
if self.model.is_device_connected() and self.model.is_cs_connected():
|
|
738
|
-
self.view.set_connection_state("connected")
|
|
739
|
-
self.view.device_connection.enable()
|
|
740
|
-
else:
|
|
741
|
-
MODULE_LOGGER.debug("Disconnecting the HUBER Stages Control Server.")
|
|
742
|
-
self.stop_timer()
|
|
743
|
-
self.model.disconnect_cs()
|
|
744
|
-
self.view.device_connection.disable()
|
|
745
|
-
self.view.set_connection_state("disconnected")
|
|
746
|
-
return
|
|
747
|
-
|
|
748
|
-
if text == "DEVICE-CONNECT":
|
|
749
|
-
print(f"Pressed {text}")
|
|
750
|
-
|
|
751
|
-
if changed_object.is_selected():
|
|
752
|
-
MODULE_LOGGER.debug("Reconnecting the HUBER Stages controller.")
|
|
753
|
-
if self.model.reconnect_device():
|
|
754
|
-
self.view.set_connection_state("connected")
|
|
755
|
-
if not self.model.has_commands():
|
|
756
|
-
self.model.load_commands()
|
|
757
|
-
self.start_timer()
|
|
758
|
-
else:
|
|
759
|
-
self.view.device_connection.set_selected(False)
|
|
760
|
-
else:
|
|
761
|
-
MODULE_LOGGER.debug("Disconnecting the HUBER Stages Controller.")
|
|
762
|
-
self.stop_timer()
|
|
763
|
-
self.model.disconnect()
|
|
764
|
-
self.view.set_connection_state("disconnected")
|
|
765
|
-
return
|
|
766
|
-
|
|
767
|
-
if text == "HOMING":
|
|
768
|
-
self.model.homing()
|
|
769
|
-
return
|
|
770
|
-
|
|
771
|
-
if text == "CLEAR-ERRORS":
|
|
772
|
-
self.model.clear_error()
|
|
773
|
-
return
|
|
774
|
-
|
|
775
|
-
def do(self, actions):
|
|
776
|
-
# This method is part of the Observer protocol and will be called when there is a
|
|
777
|
-
# action requested by the Observable.
|
|
778
|
-
|
|
779
|
-
for action, value in actions.items():
|
|
780
|
-
MODULE_LOGGER.debug(f"do {action} with {value}")
|
|
781
|
-
if action == "move_absolute":
|
|
782
|
-
axis, position = value
|
|
783
|
-
# MODULE_LOGGER.info(f"do: goto({axis}, {position})")
|
|
784
|
-
try:
|
|
785
|
-
self.model.goto(axis, position)
|
|
786
|
-
except ValueError as exc:
|
|
787
|
-
dialog = CustomErrorDialog(exc, parent=self.view)
|
|
788
|
-
dialog.exec_()
|
|
789
|
-
elif action == "move_relative":
|
|
790
|
-
axis, distance = value
|
|
791
|
-
# MODULE_LOGGER.info(f"do: move({axis}, {distance})")
|
|
792
|
-
self.model.move(axis, distance)
|
|
793
|
-
elif action == "set_speed":
|
|
794
|
-
axis, speed = value
|
|
795
|
-
# MODULE_LOGGER.info(f"do: set_speed({axis=}, {speed=})")
|
|
796
|
-
self.model.set_speed(axis, speed)
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
class HuberUIModel:
|
|
800
|
-
def __init__(self, type_):
|
|
801
|
-
self.connection_type = type_
|
|
802
|
-
|
|
803
|
-
self.huber: HuberSMC9300Interface
|
|
804
|
-
|
|
805
|
-
if self.connection_type == "proxy":
|
|
806
|
-
self.huber = HuberSMC9300Proxy()
|
|
807
|
-
elif self.connection_type == "direct":
|
|
808
|
-
self.huber = HuberSMC9300Controller()
|
|
809
|
-
self.huber.connect()
|
|
810
|
-
elif self.connection_type == "simulator":
|
|
811
|
-
self.huber = HuberSMC9300Simulator()
|
|
812
|
-
else:
|
|
813
|
-
raise ValueError(f"Unknown type of Huber implementation passed into the model: {type}")
|
|
814
|
-
|
|
815
|
-
if self.huber is not None:
|
|
816
|
-
MODULE_LOGGER.debug(f"HUBER Controller initialized as {self.huber.__class__.__name__}")
|
|
817
|
-
|
|
818
|
-
def has_commands(self):
|
|
819
|
-
if self.connection_type == "proxy":
|
|
820
|
-
return True # with the new dynamic_command decorator there are always commands
|
|
821
|
-
return True
|
|
822
|
-
|
|
823
|
-
def load_commands(self):
|
|
824
|
-
if self.connection_type == "proxy":
|
|
825
|
-
return # no need anymore to load commands
|
|
826
|
-
|
|
827
|
-
def is_simulator(self):
|
|
828
|
-
return self.huber.is_simulator()
|
|
829
|
-
|
|
830
|
-
def is_cs_connected(self):
|
|
831
|
-
return self.huber.is_cs_connected() if self.connection_type == "proxy" else False
|
|
832
|
-
|
|
833
|
-
def is_device_connected(self):
|
|
834
|
-
return self.huber.is_connected()
|
|
835
|
-
|
|
836
|
-
def goto(self, axis, position):
|
|
837
|
-
self.huber.goto(axis=axis, position=position, wait=False)
|
|
838
|
-
|
|
839
|
-
def move(self, axis, value):
|
|
840
|
-
self.huber.move(axis=axis, distance=value, wait=False)
|
|
841
|
-
|
|
842
|
-
def homing(self):
|
|
843
|
-
MODULE_LOGGER.warning("Homing done for all HUBER stages.")
|
|
844
|
-
self.huber.goto(axis=SETTINGS.BIG_ROTATION_STAGE, position=0.0, wait=False)
|
|
845
|
-
self.huber.goto(axis=SETTINGS.SMALL_ROTATION_STAGE, position=0.0, wait=False)
|
|
846
|
-
self.huber.goto(axis=SETTINGS.TRANSLATION_STAGE, position=0.0, wait=False)
|
|
847
|
-
|
|
848
|
-
def clear_error(self):
|
|
849
|
-
MODULE_LOGGER.warning("Clearing errors is done for all HUBER stages.")
|
|
850
|
-
self.huber.clear_error(SETTINGS.BIG_ROTATION_STAGE)
|
|
851
|
-
self.huber.clear_error(SETTINGS.SMALL_ROTATION_STAGE)
|
|
852
|
-
self.huber.clear_error(SETTINGS.TRANSLATION_STAGE)
|
|
853
|
-
|
|
854
|
-
def stop(self):
|
|
855
|
-
MODULE_LOGGER.warning("STOP immediately terminates all HUBER stages.")
|
|
856
|
-
self.huber.quit()
|
|
857
|
-
|
|
858
|
-
@deprecate(alternative="reconnect_device")
|
|
859
|
-
def reconnect(self):
|
|
860
|
-
self.reconnect_device()
|
|
861
|
-
|
|
862
|
-
def reconnect_device(self):
|
|
863
|
-
self.huber.reconnect()
|
|
864
|
-
return self.huber.is_connected()
|
|
865
|
-
|
|
866
|
-
def reconnect_cs(self):
|
|
867
|
-
self.huber.reconnect_cs()
|
|
868
|
-
return self.huber.is_cs_connected()
|
|
869
|
-
|
|
870
|
-
def disconnect(self):
|
|
871
|
-
self.huber.disconnect()
|
|
872
|
-
|
|
873
|
-
def disconnect_cs(self):
|
|
874
|
-
self.huber.disconnect_cs()
|
|
875
|
-
|
|
876
|
-
def get_speed(self, axis):
|
|
877
|
-
return self.huber.get_slew_speed(axis)
|
|
878
|
-
|
|
879
|
-
def set_speed(self, axis, speed):
|
|
880
|
-
return self.huber.set_slew_speed(axis, speed)
|
|
881
|
-
|
|
882
|
-
def get_current_position(self, axis):
|
|
883
|
-
return self.huber.get_current_position(axis)
|
|
884
|
-
|
|
885
|
-
def get_current_encoder_position(self, axis):
|
|
886
|
-
return self.huber.get_current_encoder_position(axis)
|
|
887
|
-
|
|
888
|
-
def get_current_encoder_counter_value(self, axis):
|
|
889
|
-
return self.huber.get_current_encoder_counter_value(axis)
|
|
890
|
-
|
|
891
|
-
def get_state(self, axis) -> int:
|
|
892
|
-
return self.huber.get_state(axis)
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
def parse_arguments():
|
|
896
|
-
"""
|
|
897
|
-
Prepare the arguments that are specific for this application.
|
|
898
|
-
"""
|
|
899
|
-
parser = argparse.ArgumentParser()
|
|
900
|
-
parser.add_argument(
|
|
901
|
-
"--type",
|
|
902
|
-
dest="type",
|
|
903
|
-
action="store",
|
|
904
|
-
choices={"proxy", "simulator", "direct"},
|
|
905
|
-
help="Specify Huber implementation you want to connect to.",
|
|
906
|
-
default="proxy",
|
|
907
|
-
)
|
|
908
|
-
parser.add_argument(
|
|
909
|
-
"--profile",
|
|
910
|
-
default=False,
|
|
911
|
-
action="store_true",
|
|
912
|
-
help="Enable info logging messages with method profile information.",
|
|
913
|
-
)
|
|
914
|
-
return parser.parse_args()
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
def main():
|
|
918
|
-
lock_file = QLockFile(str(Path("~/scm9300_ui.app.lock").expanduser()))
|
|
919
|
-
styles_location = get_resource(":/styles/default.qss")
|
|
920
|
-
app_logo = get_resource(":/icons/logo-huber.svg")
|
|
921
|
-
|
|
922
|
-
args = list(sys.argv)
|
|
923
|
-
args[1:1] = ["-stylesheet", str(styles_location)]
|
|
924
|
-
app = QApplication(args)
|
|
925
|
-
app.setWindowIcon(QIcon(str(app_logo)))
|
|
926
|
-
|
|
927
|
-
if lock_file.tryLock(100):
|
|
928
|
-
|
|
929
|
-
process_status = ProcessStatus()
|
|
930
|
-
|
|
931
|
-
timer_thread = threading.Thread(target=do_every, args=(10, process_status.update))
|
|
932
|
-
timer_thread.daemon = True
|
|
933
|
-
timer_thread.start()
|
|
934
|
-
|
|
935
|
-
start_http_server(GUI_SETTINGS.METRICS_PORT)
|
|
936
|
-
|
|
937
|
-
args = parse_arguments()
|
|
938
|
-
|
|
939
|
-
if args.profile:
|
|
940
|
-
Settings.set_profiling(True)
|
|
941
|
-
|
|
942
|
-
if args.type == "proxy":
|
|
943
|
-
proxy = HuberSMC9300Proxy()
|
|
944
|
-
if not proxy.ping():
|
|
945
|
-
description = "Could not connect to Stages Control Server"
|
|
946
|
-
info_text = (
|
|
947
|
-
"The GUI will start, but the connection button will show a disconnected state. "
|
|
948
|
-
"Please check if the Control Server is running and start the server if needed. "
|
|
949
|
-
"Otherwise, check if the correct HOSTNAME for the control server is set in the "
|
|
950
|
-
"Settings.yaml "
|
|
951
|
-
"configuration file."
|
|
952
|
-
)
|
|
953
|
-
|
|
954
|
-
show_warning_message(description, info_text)
|
|
955
|
-
|
|
956
|
-
view = HuberUIView()
|
|
957
|
-
model = HuberUIModel(args.type)
|
|
958
|
-
HuberUIController(model, view)
|
|
959
|
-
|
|
960
|
-
view.show()
|
|
961
|
-
sys.exit(app.exec_())
|
|
962
|
-
else:
|
|
963
|
-
error_message = QMessageBox()
|
|
964
|
-
error_message.setIcon(QMessageBox.Warning)
|
|
965
|
-
error_message.setWindowTitle("Error")
|
|
966
|
-
error_message.setText("The SCM9300 GUI application is already running!")
|
|
967
|
-
error_message.setStandardButtons(QMessageBox.Ok)
|
|
968
|
-
|
|
969
|
-
return error_message.exec()
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
if __name__ == "__main__":
|
|
973
|
-
main()
|