pymodaq 4.2.4__py3-none-any.whl → 5.0.0__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.
Potentially problematic release.
This version of pymodaq might be problematic. Click here for more details.
- pymodaq/__init__.py +30 -23
- pymodaq/control_modules/daq_move.py +27 -14
- pymodaq/control_modules/daq_move_ui.py +28 -12
- pymodaq/control_modules/daq_viewer.py +38 -28
- pymodaq/control_modules/daq_viewer_ui.py +6 -6
- pymodaq/control_modules/mocks.py +1 -1
- pymodaq/control_modules/move_utility_classes.py +19 -10
- pymodaq/control_modules/utils.py +18 -12
- pymodaq/control_modules/viewer_utility_classes.py +13 -4
- pymodaq/dashboard.py +164 -115
- pymodaq/examples/custom_app.py +13 -16
- pymodaq/examples/custom_viewer.py +6 -6
- pymodaq/examples/function_plotter.py +13 -12
- pymodaq/examples/parameter_ex.py +50 -25
- pymodaq/examples/tcp_client.py +1 -1
- pymodaq/extensions/__init__.py +1 -1
- pymodaq/extensions/bayesian/bayesian_optimisation.py +15 -12
- pymodaq/extensions/bayesian/utils.py +10 -10
- pymodaq/extensions/console.py +10 -13
- pymodaq/extensions/{daq_logger.py → daq_logger/daq_logger.py} +36 -56
- pymodaq/{utils/db/db_logger → extensions/daq_logger/db}/db_logger.py +16 -15
- pymodaq/{utils/db/db_logger → extensions/daq_logger/db}/db_logger_models.py +2 -0
- pymodaq/{utils/h5modules → extensions/daq_logger}/h5logging.py +7 -8
- pymodaq/extensions/daq_scan.py +153 -247
- pymodaq/extensions/daq_scan_ui.py +11 -9
- pymodaq/extensions/h5browser.py +8 -8
- pymodaq/extensions/pid/__init__.py +6 -3
- pymodaq/extensions/pid/daq_move_PID.py +4 -2
- pymodaq/extensions/pid/pid_controller.py +15 -12
- pymodaq/extensions/pid/utils.py +10 -5
- pymodaq/extensions/utils.py +5 -3
- pymodaq/post_treatment/load_and_plot.py +10 -7
- pymodaq/resources/preset_default.xml +1 -1
- pymodaq/utils/array_manipulation.py +4 -384
- pymodaq/utils/calibration_camera.py +12 -9
- pymodaq/utils/chrono_timer.py +7 -5
- pymodaq/utils/config.py +3 -450
- pymodaq/utils/daq_utils.py +6 -708
- pymodaq/utils/data.py +9 -2774
- pymodaq/utils/exceptions.py +0 -4
- pymodaq/utils/gui_utils/__init__.py +8 -8
- pymodaq/utils/gui_utils/loader_utils.py +38 -0
- pymodaq/utils/gui_utils/utils.py +6 -138
- pymodaq/utils/h5modules/__init__.py +0 -4
- pymodaq/utils/h5modules/module_saving.py +15 -8
- pymodaq/utils/leco/__init__.py +2 -2
- pymodaq/utils/leco/daq_move_LECODirector.py +2 -2
- pymodaq/utils/leco/daq_xDviewer_LECODirector.py +2 -2
- pymodaq/utils/leco/director_utils.py +2 -2
- pymodaq/utils/leco/leco_director.py +3 -3
- pymodaq/utils/leco/pymodaq_listener.py +2 -2
- pymodaq/utils/leco/utils.py +1 -1
- pymodaq/utils/logger.py +4 -76
- pymodaq/utils/managers/batchscan_manager.py +16 -19
- pymodaq/utils/managers/modules_manager.py +10 -7
- pymodaq/utils/managers/overshoot_manager.py +3 -5
- pymodaq/utils/managers/preset_manager.py +37 -15
- pymodaq/utils/managers/preset_manager_utils.py +11 -9
- pymodaq/utils/managers/remote_manager.py +12 -10
- pymodaq/utils/math_utils.py +4 -572
- pymodaq/utils/parameter/__init__.py +4 -11
- pymodaq/utils/parameter/utils.py +4 -299
- pymodaq/utils/scanner/scan_config.py +1 -1
- pymodaq/utils/scanner/scan_factory.py +16 -12
- pymodaq/utils/{plotting → scanner}/scan_selector.py +19 -20
- pymodaq/utils/scanner/scanner.py +10 -8
- pymodaq/utils/scanner/scanners/_1d_scanners.py +8 -5
- pymodaq/utils/scanner/scanners/_2d_scanners.py +5 -5
- pymodaq/utils/scanner/scanners/sequential.py +8 -8
- pymodaq/utils/scanner/scanners/tabular.py +9 -9
- pymodaq/utils/scanner/utils.py +6 -4
- pymodaq/utils/svg/svg_viewer2D.py +3 -4
- pymodaq/utils/tcp_ip/serializer.py +64 -16
- pymodaq/utils/tcp_ip/tcp_server_client.py +10 -8
- {pymodaq-4.2.4.dist-info → pymodaq-5.0.0.dist-info}/METADATA +5 -3
- pymodaq-5.0.0.dist-info/RECORD +123 -0
- pymodaq/post_treatment/process_to_scalar.py +0 -263
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/1d.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/2d.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/3d.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Add2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Add_Step.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Approve.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Approve_All.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Browse_Dir_Path.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Calculator.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/ChnGroup.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/ChnNum.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/ChnText.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/ChnTime.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/ChnWave.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Close3.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/CollapseAll.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/CollapseAll_32.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/ColorPicker.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Contract.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Create.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/DeleteLayer.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/EditOpen.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/EditRedo.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/EditUndo.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Ellipse.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/EllipseFilled.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Error.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/ErrorMessage.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Error_16.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Exit.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Expand.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/ExpandAll.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/ExpandAll_32.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/FFT.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/HLM.ico +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Help.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Help_32.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Histogram.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/LUT_LookUpTable.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/MagnifyingGlass.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/MagnifyingGlass_24.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Marker.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Math.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/MeasurementStudio_32.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Move.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/MoveDown.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/MoveUp.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Multiply.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/NewFile.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/NewLayer.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/New_File.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/New_Folder.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open_1D.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open_2D.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open_File.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open_File_32.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Open_sim.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Options.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Oscilloscope.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Oscilloscope_16.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Pass.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/RGB.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Rectangle.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/RectangleFilled.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Redo.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Refresh.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Refresh2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Refresh_32.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Region.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Rendezvous.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/SELECT.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Save.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/SaveAll.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/SaveAll_32.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/SaveAs.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/SaveAs_32.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Save_24.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Save_32.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Search.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/SelectPolygon.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Select_24.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Settings.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Snap&Save.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Snapshot.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Snapshot2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Snapshot2_16.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Snapshot2_32.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Spreadsheet.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Statistics.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Statistics2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Status.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Subtract.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Vision.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Volts.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Wait2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Zoom_1_1.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Zoom_in.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Zoom_out.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/Zoom_to_Selection.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/abort.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/advanced2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/autoscale.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/b_icon.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/back.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/bg_icon.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/camera.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/camera_snap.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/cartesian.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/clear2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/clear_ROI.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/close2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/cluster2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/color.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/color2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/continuous.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/data.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/delay.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/download.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/download2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/error2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/ethernet.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/exit2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/fan.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/filter2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/g_icon.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/gear2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/go_to.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/go_to_1.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/go_to_2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/grab.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/graph.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/greenLight2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/greenLight2_32.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/green_light.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/grey_icon.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/greyscale.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/help1.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/help1_32.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/home2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/information2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/ini.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/integrator.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/joystick.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_green.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_green_16.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_red.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_red_16.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_yellow.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/light_yellow_16.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/limiter.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/load_ROI.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/meshPlot.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/meter.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/meter2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/meter_32.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/move_contour.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/move_straight_line.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/movie.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/multi_point.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/multiplexer.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/new.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/openArrow.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/openTree.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/oscilloscope2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/oscilloscope3.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/overlay.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/pass2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/pass2_16.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/pass_32.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/pause.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/permute.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/phase.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/play.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/polar.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/pole_zero.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/powerMeter.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/powerSwitch.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/powerSwitch_16.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/print2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/print2_32.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/properties.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/r_icon.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/radiocontrolbutton.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/read2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/red_light.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/remove.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/reset.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/rgb_icon.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/robot.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/rotation2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/run2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/run_all.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/saturation.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/saveTree.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/save_ROI.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/scale_horizontally.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/scale_vertically.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/search2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/select2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/select_all.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/select_all2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/select_none.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/sequence.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/sequence2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/snap.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/sort_ascend.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/spectrumAnalyzer.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/start.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/status_cancelled.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop3.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/stop_all.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/sum.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/surfacePlot.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/tree.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/updateTree.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/utility2.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/utility_small.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/vector.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/verify.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/video.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/wait.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/waterfallPlot.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/watershed.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/yellow_light.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/zip_file.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/zoomAuto.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/Icon_Library/zoomReset.png +0 -0
- pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.bat +0 -2
- pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources.qrc +0 -234
- pymodaq/resources/QtDesigner_Ressources/QtDesigner_ressources_rc.py +0 -127150
- pymodaq/resources/QtDesigner_Ressources/icons.svg +0 -142
- pymodaq/resources/VERSION +0 -1
- pymodaq/resources/config_template.toml +0 -94
- pymodaq/resources/triangulation_data.npy +0 -0
- pymodaq/utils/abstract/__init__.py +0 -48
- pymodaq/utils/db/__init__.py +0 -0
- pymodaq/utils/db/db_logger/__init__.py +0 -0
- pymodaq/utils/enums.py +0 -76
- pymodaq/utils/factory.py +0 -82
- pymodaq/utils/gui_utils/custom_app.py +0 -133
- pymodaq/utils/gui_utils/dock.py +0 -107
- pymodaq/utils/gui_utils/file_io.py +0 -93
- pymodaq/utils/gui_utils/layout.py +0 -34
- pymodaq/utils/gui_utils/list_picker.py +0 -38
- pymodaq/utils/gui_utils/widgets/__init__.py +0 -5
- pymodaq/utils/gui_utils/widgets/label.py +0 -24
- pymodaq/utils/gui_utils/widgets/lcd.py +0 -111
- pymodaq/utils/gui_utils/widgets/push.py +0 -149
- pymodaq/utils/gui_utils/widgets/qled.py +0 -62
- pymodaq/utils/gui_utils/widgets/spinbox.py +0 -24
- pymodaq/utils/gui_utils/widgets/table.py +0 -263
- pymodaq/utils/gui_utils/widgets/tree_layout.py +0 -188
- pymodaq/utils/gui_utils/widgets/tree_toml.py +0 -102
- pymodaq/utils/h5modules/backends.py +0 -1022
- pymodaq/utils/h5modules/browsing.py +0 -625
- pymodaq/utils/h5modules/data_saving.py +0 -1105
- pymodaq/utils/h5modules/exporter.py +0 -119
- pymodaq/utils/h5modules/exporters/__init__.py +0 -0
- pymodaq/utils/h5modules/exporters/base.py +0 -111
- pymodaq/utils/h5modules/exporters/flimj.py +0 -63
- pymodaq/utils/h5modules/exporters/hyperspy.py +0 -143
- pymodaq/utils/h5modules/saving.py +0 -866
- pymodaq/utils/h5modules/utils.py +0 -115
- pymodaq/utils/managers/action_manager.py +0 -489
- pymodaq/utils/managers/parameter_manager.py +0 -282
- pymodaq/utils/managers/roi_manager.py +0 -726
- pymodaq/utils/messenger.py +0 -66
- pymodaq/utils/parameter/ioxml.py +0 -542
- pymodaq/utils/parameter/pymodaq_ptypes/__init__.py +0 -38
- pymodaq/utils/parameter/pymodaq_ptypes/bool.py +0 -31
- pymodaq/utils/parameter/pymodaq_ptypes/date.py +0 -126
- pymodaq/utils/parameter/pymodaq_ptypes/filedir.py +0 -143
- pymodaq/utils/parameter/pymodaq_ptypes/itemselect.py +0 -265
- pymodaq/utils/parameter/pymodaq_ptypes/led.py +0 -44
- pymodaq/utils/parameter/pymodaq_ptypes/list.py +0 -150
- pymodaq/utils/parameter/pymodaq_ptypes/numeric.py +0 -18
- pymodaq/utils/parameter/pymodaq_ptypes/pixmap.py +0 -175
- pymodaq/utils/parameter/pymodaq_ptypes/slide.py +0 -145
- pymodaq/utils/parameter/pymodaq_ptypes/table.py +0 -135
- pymodaq/utils/parameter/pymodaq_ptypes/tableview.py +0 -149
- pymodaq/utils/parameter/pymodaq_ptypes/text.py +0 -142
- pymodaq/utils/plotting/__init__.py +0 -0
- pymodaq/utils/plotting/data_viewers/__init__.py +0 -10
- pymodaq/utils/plotting/data_viewers/base.py +0 -286
- pymodaq/utils/plotting/data_viewers/viewer.py +0 -274
- pymodaq/utils/plotting/data_viewers/viewer0D.py +0 -298
- pymodaq/utils/plotting/data_viewers/viewer1D.py +0 -826
- pymodaq/utils/plotting/data_viewers/viewer1Dbasic.py +0 -231
- pymodaq/utils/plotting/data_viewers/viewer2D.py +0 -1118
- pymodaq/utils/plotting/data_viewers/viewer2D_basic.py +0 -146
- pymodaq/utils/plotting/data_viewers/viewerND.py +0 -800
- pymodaq/utils/plotting/gant_chart.py +0 -123
- pymodaq/utils/plotting/image_viewer.py +0 -97
- pymodaq/utils/plotting/items/__init__.py +0 -0
- pymodaq/utils/plotting/items/axis_scaled.py +0 -93
- pymodaq/utils/plotting/items/crosshair.py +0 -94
- pymodaq/utils/plotting/items/image.py +0 -388
- pymodaq/utils/plotting/navigator.py +0 -353
- pymodaq/utils/plotting/plotter/plotter.py +0 -94
- pymodaq/utils/plotting/plotter/plotters/__init__.py +0 -0
- pymodaq/utils/plotting/plotter/plotters/matplotlib_plotters.py +0 -134
- pymodaq/utils/plotting/plotter/plotters/qt_plotters.py +0 -78
- pymodaq/utils/plotting/utils/__init__.py +0 -0
- pymodaq/utils/plotting/utils/axes_viewer.py +0 -88
- pymodaq/utils/plotting/utils/filter.py +0 -585
- pymodaq/utils/plotting/utils/lineout.py +0 -226
- pymodaq/utils/plotting/utils/plot_utils.py +0 -579
- pymodaq/utils/plotting/utils/signalND.py +0 -1347
- pymodaq/utils/plotting/widgets.py +0 -76
- pymodaq/utils/qvariant.py +0 -12
- pymodaq/utils/slicing.py +0 -63
- pymodaq/utils/units.py +0 -216
- pymodaq-4.2.4.dist-info/RECORD +0 -438
- /pymodaq/{post_treatment/daq_analysis → extensions/daq_logger}/__init__.py +0 -0
- /pymodaq/{utils/abstract/logger.py → extensions/daq_logger/abstract.py} +0 -0
- /pymodaq/{resources/QtDesigner_Ressources → extensions/daq_logger/db}/__init__.py +0 -0
- {pymodaq-4.2.4.dist-info → pymodaq-5.0.0.dist-info}/WHEEL +0 -0
- {pymodaq-4.2.4.dist-info → pymodaq-5.0.0.dist-info}/entry_points.txt +0 -0
- {pymodaq-4.2.4.dist-info → pymodaq-5.0.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,1022 +0,0 @@
|
|
|
1
|
-
# -*- coding: utf-8 -*-
|
|
2
|
-
"""
|
|
3
|
-
Created the 15/11/2022
|
|
4
|
-
|
|
5
|
-
@author: Sebastien Weber
|
|
6
|
-
"""
|
|
7
|
-
import numpy as np
|
|
8
|
-
import importlib
|
|
9
|
-
import pickle
|
|
10
|
-
from typing import Dict
|
|
11
|
-
|
|
12
|
-
from pymodaq.utils.logger import set_logger, get_module_name
|
|
13
|
-
from pymodaq.utils.config import Config
|
|
14
|
-
from pymodaq.utils.daq_utils import capitalize, JsonConverter
|
|
15
|
-
from pymodaq.utils import daq_utils as utils
|
|
16
|
-
from pymodaq.utils.enums import BaseEnum, enum_checker
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
config = Config()
|
|
20
|
-
logger = set_logger(get_module_name(__file__))
|
|
21
|
-
|
|
22
|
-
backends_available = []
|
|
23
|
-
|
|
24
|
-
# default backend
|
|
25
|
-
is_tables = True
|
|
26
|
-
try:
|
|
27
|
-
import tables
|
|
28
|
-
backends_available.append('tables')
|
|
29
|
-
except Exception as e: # pragma: no cover
|
|
30
|
-
logger.warning(str(e))
|
|
31
|
-
is_tables = False
|
|
32
|
-
|
|
33
|
-
is_h5py = True
|
|
34
|
-
# other possibility
|
|
35
|
-
try:
|
|
36
|
-
import h5py
|
|
37
|
-
backends_available.append('h5py')
|
|
38
|
-
except Exception as e: # pragma: no cover
|
|
39
|
-
logger.warning(str(e))
|
|
40
|
-
is_h5py = False
|
|
41
|
-
|
|
42
|
-
is_h5pyd = True
|
|
43
|
-
# this one is to be used for remote reading/writing towards a HSDS server (or h5serv), see HDFGroup
|
|
44
|
-
try:
|
|
45
|
-
import h5pyd
|
|
46
|
-
backends_available.append('h5pyd')
|
|
47
|
-
except Exception as e: # pragma: no cover
|
|
48
|
-
logger.warning(str(e))
|
|
49
|
-
is_h5pyd = False
|
|
50
|
-
|
|
51
|
-
if not (is_tables or is_h5py or is_h5pyd):
|
|
52
|
-
logger.exception('No valid hdf5 backend has been installed, please install either pytables or h5py')
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
class NodeError(Exception):
|
|
56
|
-
pass
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
class SaveType(BaseEnum):
|
|
60
|
-
scan = 0
|
|
61
|
-
detector = 1
|
|
62
|
-
logger = 2
|
|
63
|
-
custom = 3
|
|
64
|
-
actuator = 4
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
class GroupType(BaseEnum):
|
|
68
|
-
detector = 0
|
|
69
|
-
actuator = 1
|
|
70
|
-
data = 2
|
|
71
|
-
ch = 3
|
|
72
|
-
scan = 4
|
|
73
|
-
external_h5 = 5
|
|
74
|
-
data_dim = 6
|
|
75
|
-
data_logger = 7
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
class InvalidExport(Exception):
|
|
79
|
-
pass
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
def check_mandatory_attrs(attr_name, attr):
|
|
83
|
-
"""for cross compatibility between different backends. If these attributes have binary value, then decode them
|
|
84
|
-
|
|
85
|
-
Parameters
|
|
86
|
-
----------
|
|
87
|
-
attr_name
|
|
88
|
-
attr
|
|
89
|
-
|
|
90
|
-
Returns
|
|
91
|
-
-------
|
|
92
|
-
|
|
93
|
-
"""
|
|
94
|
-
if attr_name == 'TITLE' or attr_name == 'CLASS' or attr_name == 'EXTDIM':
|
|
95
|
-
if isinstance(attr, bytes):
|
|
96
|
-
return attr.decode()
|
|
97
|
-
else:
|
|
98
|
-
return attr
|
|
99
|
-
else:
|
|
100
|
-
return attr
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
def get_attr(node, attr_name, backend='tables'):
|
|
104
|
-
if backend == 'tables':
|
|
105
|
-
if attr_name is not None:
|
|
106
|
-
attr = node._v_attrs[attr_name]
|
|
107
|
-
attr = check_mandatory_attrs(attr_name, attr)
|
|
108
|
-
return JsonConverter.json2object(attr)
|
|
109
|
-
else:
|
|
110
|
-
attrs = dict([])
|
|
111
|
-
for attr_name in node._v_attrs._v_attrnames:
|
|
112
|
-
attrval = node._v_attrs[attr_name]
|
|
113
|
-
attrval = check_mandatory_attrs(attr_name, attrval)
|
|
114
|
-
attrs[attr_name] = JsonConverter.json2object(attrval)
|
|
115
|
-
return attrs
|
|
116
|
-
else:
|
|
117
|
-
if attr_name is not None:
|
|
118
|
-
attr = node.attrs[attr_name]
|
|
119
|
-
attr = check_mandatory_attrs(attr_name, attr)
|
|
120
|
-
return JsonConverter.json2object(attr)
|
|
121
|
-
else:
|
|
122
|
-
attrs = dict([])
|
|
123
|
-
for attr_name in node.attrs.keys():
|
|
124
|
-
attrval = node.attrs[attr_name]
|
|
125
|
-
attrval = check_mandatory_attrs(attr_name, attrval)
|
|
126
|
-
attrs[attr_name] = JsonConverter.json2object(attrval)
|
|
127
|
-
return attrs
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
def set_attr(node, attr_name, attr_value, backend='tables'):
|
|
131
|
-
if backend == 'tables':
|
|
132
|
-
node._v_attrs[attr_name] = JsonConverter.object2json(attr_value)
|
|
133
|
-
else:
|
|
134
|
-
node.attrs[attr_name] = JsonConverter.object2json(attr_value)
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
class InvalidGroupType(Exception):
|
|
138
|
-
pass
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
class InvalidSave(Exception):
|
|
142
|
-
pass
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
class InvalidGroupDataType(Exception):
|
|
146
|
-
pass
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
class InvalidDataType(Exception):
|
|
150
|
-
pass
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
class InvalidDataDimension(Exception):
|
|
154
|
-
pass
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
class InvalidScanType(Exception):
|
|
158
|
-
pass
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
class Node(object):
|
|
162
|
-
def __init__(self, node, backend):
|
|
163
|
-
if isinstance(node, Node): # to ovoid recursion if one call Node(Node()) or even more
|
|
164
|
-
self._node = node.node
|
|
165
|
-
else:
|
|
166
|
-
self._node = node
|
|
167
|
-
self.backend = backend
|
|
168
|
-
self._attrs = Attributes(self, backend)
|
|
169
|
-
|
|
170
|
-
def __str__(self):
|
|
171
|
-
# Get this class name
|
|
172
|
-
classname = self.__class__.__name__
|
|
173
|
-
# The title
|
|
174
|
-
title = self.attrs['TITLE']
|
|
175
|
-
return "%s (%s) %r" % \
|
|
176
|
-
(self.path, classname, title)
|
|
177
|
-
|
|
178
|
-
@property
|
|
179
|
-
def node(self):
|
|
180
|
-
return self._node
|
|
181
|
-
|
|
182
|
-
def __eq__(self, other):
|
|
183
|
-
return self.node == other.node
|
|
184
|
-
|
|
185
|
-
@property
|
|
186
|
-
def parent_node(self) -> 'GROUP':
|
|
187
|
-
if self.path == '/':
|
|
188
|
-
return None
|
|
189
|
-
mod = importlib.import_module('.backends', 'pymodaq.utils.h5modules')
|
|
190
|
-
|
|
191
|
-
if self.backend == 'tables':
|
|
192
|
-
p = self.node._v_parent
|
|
193
|
-
else:
|
|
194
|
-
p = self.node.parent
|
|
195
|
-
klass = get_attr(p, 'CLASS', self.backend)
|
|
196
|
-
_cls = getattr(mod, klass)
|
|
197
|
-
return _cls(p, self.backend)
|
|
198
|
-
|
|
199
|
-
@property
|
|
200
|
-
def h5file(self):
|
|
201
|
-
if self.backend == 'tables':
|
|
202
|
-
return self.node._v_file
|
|
203
|
-
else:
|
|
204
|
-
return self.node.file
|
|
205
|
-
|
|
206
|
-
def to_h5_backend(self) -> 'H5Backend':
|
|
207
|
-
h5_backend = H5Backend(self.backend)
|
|
208
|
-
h5_backend.h5file = self.h5file
|
|
209
|
-
return h5_backend
|
|
210
|
-
|
|
211
|
-
def set_attr(self, key, value):
|
|
212
|
-
self.attrs[key] = value
|
|
213
|
-
|
|
214
|
-
def get_attr(self, item):
|
|
215
|
-
return self.attrs[item]
|
|
216
|
-
|
|
217
|
-
@property
|
|
218
|
-
def attrs(self):
|
|
219
|
-
return self._attrs
|
|
220
|
-
|
|
221
|
-
@property
|
|
222
|
-
def name(self):
|
|
223
|
-
"""return node name
|
|
224
|
-
"""
|
|
225
|
-
if self.backend == 'tables':
|
|
226
|
-
return self._node._v_name
|
|
227
|
-
else:
|
|
228
|
-
path = self._node.name
|
|
229
|
-
if path == '/':
|
|
230
|
-
return path
|
|
231
|
-
else:
|
|
232
|
-
return path.split('/')[-1]
|
|
233
|
-
|
|
234
|
-
@property
|
|
235
|
-
def title(self):
|
|
236
|
-
return self.attrs['TITLE']
|
|
237
|
-
|
|
238
|
-
@property
|
|
239
|
-
def path(self):
|
|
240
|
-
"""return node path
|
|
241
|
-
Parameters
|
|
242
|
-
----------
|
|
243
|
-
node (str or node instance), see h5py and pytables documentation on nodes
|
|
244
|
-
|
|
245
|
-
Returns
|
|
246
|
-
-------
|
|
247
|
-
str : full path of the node
|
|
248
|
-
"""
|
|
249
|
-
if self.backend == 'tables':
|
|
250
|
-
return self._node._v_pathname
|
|
251
|
-
else:
|
|
252
|
-
return self._node.name
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
class GROUP(Node):
|
|
256
|
-
def __init__(self, node, backend):
|
|
257
|
-
super().__init__(node, backend)
|
|
258
|
-
|
|
259
|
-
def __str__(self):
|
|
260
|
-
"""Return a short string representation of the group.
|
|
261
|
-
"""
|
|
262
|
-
|
|
263
|
-
pathname = self.path
|
|
264
|
-
classname = self.__class__.__name__
|
|
265
|
-
title = self.attrs['TITLE']
|
|
266
|
-
return "%s (%s) %r" % (pathname, classname, title)
|
|
267
|
-
|
|
268
|
-
def __repr__(self):
|
|
269
|
-
"""Return a detailed string representation of the group.
|
|
270
|
-
"""
|
|
271
|
-
|
|
272
|
-
rep = [
|
|
273
|
-
'%r (%s)' % (childname, child.__class__.__name__)
|
|
274
|
-
for (childname, child) in self.children().items()
|
|
275
|
-
]
|
|
276
|
-
childlist = '[%s]' % (', '.join(rep))
|
|
277
|
-
|
|
278
|
-
return "%s\n children := %s" % (str(self), childlist)
|
|
279
|
-
|
|
280
|
-
def children(self) -> Dict[str, Node]:
|
|
281
|
-
"""Get a dict containing all children node hanging from self whith their name as keys
|
|
282
|
-
|
|
283
|
-
Returns
|
|
284
|
-
-------
|
|
285
|
-
dict: keys are children node names, values are the children nodes
|
|
286
|
-
|
|
287
|
-
See Also
|
|
288
|
-
--------
|
|
289
|
-
children_name
|
|
290
|
-
"""
|
|
291
|
-
mod = importlib.import_module('.backends', 'pymodaq.utils.h5modules')
|
|
292
|
-
children = dict([])
|
|
293
|
-
if self.backend == 'tables':
|
|
294
|
-
for child_name, child in self.node._v_children.items():
|
|
295
|
-
klass = get_attr(child, 'CLASS', self.backend)
|
|
296
|
-
if 'ARRAY' in klass:
|
|
297
|
-
_cls = getattr(mod, klass)
|
|
298
|
-
else:
|
|
299
|
-
_cls = GROUP
|
|
300
|
-
children[child_name] = _cls(child, self.backend)
|
|
301
|
-
else:
|
|
302
|
-
for child_name, child in self.node.items():
|
|
303
|
-
|
|
304
|
-
klass = get_attr(child, 'CLASS', self.backend)
|
|
305
|
-
if 'ARRAY' in klass:
|
|
306
|
-
_cls = getattr(mod, klass)
|
|
307
|
-
else:
|
|
308
|
-
_cls = GROUP
|
|
309
|
-
children[child_name] = _cls(child, self.backend)
|
|
310
|
-
return children
|
|
311
|
-
|
|
312
|
-
def get_child(self, name: str) -> Node:
|
|
313
|
-
return self.children()[name]
|
|
314
|
-
|
|
315
|
-
def children_name(self):
|
|
316
|
-
"""Gets the sorted list of children name hanging from self
|
|
317
|
-
|
|
318
|
-
Returns
|
|
319
|
-
-------
|
|
320
|
-
list: list of name of the children
|
|
321
|
-
"""
|
|
322
|
-
if self.backend == 'tables':
|
|
323
|
-
return sorted(list(self.node._v_children.keys()))
|
|
324
|
-
else:
|
|
325
|
-
return sorted(list(self.node.keys()))
|
|
326
|
-
pass
|
|
327
|
-
|
|
328
|
-
def remove_children(self):
|
|
329
|
-
children_dict = self.children()
|
|
330
|
-
for child_name in children_dict:
|
|
331
|
-
if self.backend == 'tables':
|
|
332
|
-
children_dict[child_name].node._f_remove(recursive=True)
|
|
333
|
-
else:
|
|
334
|
-
self.node.__delitem__(child_name)
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
class CARRAY(Node):
|
|
338
|
-
def __init__(self, node, backend):
|
|
339
|
-
super().__init__(node, backend)
|
|
340
|
-
self._array = node
|
|
341
|
-
|
|
342
|
-
@property
|
|
343
|
-
def array(self):
|
|
344
|
-
return self._array
|
|
345
|
-
|
|
346
|
-
def __repr__(self):
|
|
347
|
-
"""This provides more metainfo in addition to standard __str__"""
|
|
348
|
-
|
|
349
|
-
return """%s
|
|
350
|
-
shape := %s
|
|
351
|
-
dtype := %s""" % (self, str(self.attrs['shape']), self.attrs['dtype'])
|
|
352
|
-
|
|
353
|
-
def __getitem__(self, item):
|
|
354
|
-
return self._array.__getitem__(item)
|
|
355
|
-
|
|
356
|
-
def __setitem__(self, key, value):
|
|
357
|
-
self._array.__setitem__(key, value)
|
|
358
|
-
|
|
359
|
-
def read(self):
|
|
360
|
-
if self.backend == 'tables':
|
|
361
|
-
return self._array.read()
|
|
362
|
-
else:
|
|
363
|
-
return self._array[:]
|
|
364
|
-
|
|
365
|
-
def __len__(self):
|
|
366
|
-
if self.backend == 'tables':
|
|
367
|
-
return self.array.nrows
|
|
368
|
-
else:
|
|
369
|
-
return len(self.array)
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
class EARRAY(CARRAY):
|
|
373
|
-
def __init__(self, array, backend):
|
|
374
|
-
super().__init__(array, backend)
|
|
375
|
-
|
|
376
|
-
def append(self, data: np.ndarray, expand=True):
|
|
377
|
-
""" appends a ndarray after the current data in the enlargeable array
|
|
378
|
-
|
|
379
|
-
Considering the shape length of the enlargeable array is n+1
|
|
380
|
-
|
|
381
|
-
The data to append could be:
|
|
382
|
-
|
|
383
|
-
* a single element (without the enlargeable shape index that is always the first
|
|
384
|
-
index, that is of shape length n). In that case the first index of the enlargeable array
|
|
385
|
-
is increased by one.
|
|
386
|
-
* an ensemble of elements (a ndarray) of shape length of (n+1).
|
|
387
|
-
|
|
388
|
-
Parameters
|
|
389
|
-
----------
|
|
390
|
-
data: np.ndarray
|
|
391
|
-
the data array to append to the enlargeable node
|
|
392
|
-
expand: bool
|
|
393
|
-
If True the data array will have its shape expanded by one dim
|
|
394
|
-
|
|
395
|
-
"""
|
|
396
|
-
if not isinstance(data, np.ndarray):
|
|
397
|
-
raise TypeError('The appended object should be a ndarray')
|
|
398
|
-
if len(self.attrs['shape']) > 1 and data.shape == self.attrs['shape'][1:]:
|
|
399
|
-
shape = [1]
|
|
400
|
-
shape.extend(data.shape)
|
|
401
|
-
data = data.reshape(shape)
|
|
402
|
-
extended_first_index = 1
|
|
403
|
-
else:
|
|
404
|
-
extended_first_index = data.shape[0]
|
|
405
|
-
if expand and (len(data.shape) == 1 and not data.shape == (1, )):
|
|
406
|
-
data = np.expand_dims(data, 1)
|
|
407
|
-
self.append_backend(data)
|
|
408
|
-
|
|
409
|
-
sh = list(self.attrs['shape'])
|
|
410
|
-
sh[0] += extended_first_index
|
|
411
|
-
self.attrs['shape'] = tuple(sh)
|
|
412
|
-
|
|
413
|
-
def append_backend(self, data):
|
|
414
|
-
if self.backend == 'tables':
|
|
415
|
-
self.array.append(data)
|
|
416
|
-
else:
|
|
417
|
-
self.array.resize(self.array.len() + 1, axis=0)
|
|
418
|
-
self.array[-1] = data
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
class VLARRAY(EARRAY):
|
|
422
|
-
def __init__(self, array, backend):
|
|
423
|
-
super().__init__(array, backend)
|
|
424
|
-
|
|
425
|
-
def append(self, data):
|
|
426
|
-
self.append_backend(data)
|
|
427
|
-
|
|
428
|
-
sh = list(self.attrs['shape'])
|
|
429
|
-
sh[0] += 1
|
|
430
|
-
self.attrs['shape'] = tuple(sh)
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
class StringARRAY(VLARRAY):
|
|
434
|
-
def __init__(self, array, backend):
|
|
435
|
-
super().__init__(array, backend)
|
|
436
|
-
|
|
437
|
-
def __getitem__(self, item):
|
|
438
|
-
return self.array_to_string(super().__getitem__(item))
|
|
439
|
-
|
|
440
|
-
def read(self):
|
|
441
|
-
data_list = super().read()
|
|
442
|
-
return [self.array_to_string(data) for data in data_list]
|
|
443
|
-
|
|
444
|
-
def append(self, string):
|
|
445
|
-
data = self.string_to_array(string)
|
|
446
|
-
super().append(data)
|
|
447
|
-
|
|
448
|
-
def array_to_string(self, array):
|
|
449
|
-
return pickle.loads(array)
|
|
450
|
-
|
|
451
|
-
def string_to_array(self, string):
|
|
452
|
-
return np.frombuffer(pickle.dumps(string), np.uint8)
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
class Attributes(object):
|
|
456
|
-
def __init__(self, node, backend='tables'):
|
|
457
|
-
self._node = node
|
|
458
|
-
self.backend = backend
|
|
459
|
-
|
|
460
|
-
def __getitem__(self, item):
|
|
461
|
-
if item == 'title':
|
|
462
|
-
item = item.upper()
|
|
463
|
-
attr = get_attr(self._node.node, item, backend=self.backend)
|
|
464
|
-
# if isinstance(attr, bytes):
|
|
465
|
-
# attr = attr.decode()
|
|
466
|
-
return attr
|
|
467
|
-
|
|
468
|
-
def __setitem__(self, key, value):
|
|
469
|
-
if key == 'title':
|
|
470
|
-
key = key.upper()
|
|
471
|
-
set_attr(self._node.node, key, value, backend=self.backend)
|
|
472
|
-
|
|
473
|
-
def __iter__(self):
|
|
474
|
-
self._iter_index = 0
|
|
475
|
-
return self
|
|
476
|
-
|
|
477
|
-
def __next__(self):
|
|
478
|
-
if self._iter_index < len(self):
|
|
479
|
-
self._iter_index += 1
|
|
480
|
-
return self.attrs_name[self._iter_index-1]
|
|
481
|
-
else:
|
|
482
|
-
raise StopIteration
|
|
483
|
-
|
|
484
|
-
def __len__(self):
|
|
485
|
-
return len(self.attrs_name)
|
|
486
|
-
|
|
487
|
-
def to_dict(self) -> dict:
|
|
488
|
-
"""Returns attributes name/value as a dict"""
|
|
489
|
-
attrs_dict = dict()
|
|
490
|
-
for name in self.attrs_name:
|
|
491
|
-
attrs_dict[name] = self[name]
|
|
492
|
-
return attrs_dict
|
|
493
|
-
|
|
494
|
-
@property
|
|
495
|
-
def node(self):
|
|
496
|
-
return self._node
|
|
497
|
-
|
|
498
|
-
@property
|
|
499
|
-
def attrs_name(self):
|
|
500
|
-
if self.backend == 'tables':
|
|
501
|
-
return [k for k in self.node.node._v_attrs._v_attrnames]
|
|
502
|
-
else:
|
|
503
|
-
return [k for k in self.node.node.attrs.keys()]
|
|
504
|
-
|
|
505
|
-
def __str__(self):
|
|
506
|
-
"""The string representation for this object."""
|
|
507
|
-
|
|
508
|
-
# The pathname
|
|
509
|
-
if self.backend == 'tables':
|
|
510
|
-
pathname = self._node.node._v_pathname
|
|
511
|
-
else:
|
|
512
|
-
pathname = self._node.node.name
|
|
513
|
-
# Get this class name
|
|
514
|
-
classname = self.__class__.__name__
|
|
515
|
-
# The attribute names
|
|
516
|
-
attrnumber = len([n for n in self.attrs_name])
|
|
517
|
-
return "%s.attrs (%s), %s attributes" % \
|
|
518
|
-
(pathname, classname, attrnumber)
|
|
519
|
-
|
|
520
|
-
def __repr__(self):
|
|
521
|
-
attrnames = self.attrs_name
|
|
522
|
-
if len(attrnames):
|
|
523
|
-
rep = ['%s := %s' % (attr, str(self[attr]))
|
|
524
|
-
for attr in attrnames]
|
|
525
|
-
attrlist = '[%s]' % (',\n '.join(rep))
|
|
526
|
-
|
|
527
|
-
return "%s:\n %s" % (str(self), attrlist)
|
|
528
|
-
else:
|
|
529
|
-
return str(self)
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
class H5Backend:
|
|
533
|
-
def __init__(self, backend='tables'):
|
|
534
|
-
|
|
535
|
-
self._h5file = None
|
|
536
|
-
self.backend = backend
|
|
537
|
-
self.file_path = None
|
|
538
|
-
self.compression = None
|
|
539
|
-
if backend == 'tables':
|
|
540
|
-
if is_tables:
|
|
541
|
-
self.h5_library = tables
|
|
542
|
-
else:
|
|
543
|
-
raise ImportError('the pytables module is not present')
|
|
544
|
-
elif backend == 'h5py':
|
|
545
|
-
if is_h5py:
|
|
546
|
-
self.h5_library = h5py
|
|
547
|
-
else:
|
|
548
|
-
raise ImportError('the h5py module is not present')
|
|
549
|
-
elif backend == 'h5pyd':
|
|
550
|
-
if is_h5pyd:
|
|
551
|
-
self.h5_library = h5pyd
|
|
552
|
-
else:
|
|
553
|
-
raise ImportError('the h5pyd module is not present')
|
|
554
|
-
|
|
555
|
-
@property
|
|
556
|
-
def h5file(self):
|
|
557
|
-
return self._h5file
|
|
558
|
-
|
|
559
|
-
@h5file.setter
|
|
560
|
-
def h5file(self, file):
|
|
561
|
-
self.file_path = file.filename
|
|
562
|
-
self._h5file = file
|
|
563
|
-
|
|
564
|
-
@property
|
|
565
|
-
def filename(self):
|
|
566
|
-
return self._h5file.filename
|
|
567
|
-
|
|
568
|
-
def isopen(self):
|
|
569
|
-
if self._h5file is None:
|
|
570
|
-
return False
|
|
571
|
-
if self.backend == 'tables':
|
|
572
|
-
return bool(self._h5file.isopen)
|
|
573
|
-
elif self.backend == 'h5py':
|
|
574
|
-
return bool(self._h5file.id.valid)
|
|
575
|
-
else:
|
|
576
|
-
return self._h5file.id.http_conn is not None
|
|
577
|
-
|
|
578
|
-
def close_file(self):
|
|
579
|
-
"""Flush data and close the h5file
|
|
580
|
-
"""
|
|
581
|
-
try:
|
|
582
|
-
if self._h5file is not None:
|
|
583
|
-
self.flush()
|
|
584
|
-
if self.isopen():
|
|
585
|
-
self._h5file.close()
|
|
586
|
-
except Exception as e:
|
|
587
|
-
print(e) # no big deal
|
|
588
|
-
|
|
589
|
-
def open_file(self, fullpathname, mode='r', title='PyMoDAQ file', **kwargs):
|
|
590
|
-
self.file_path = fullpathname
|
|
591
|
-
if self.backend == 'tables':
|
|
592
|
-
self._h5file = self.h5_library.open_file(str(fullpathname), mode=mode, title=title, **kwargs)
|
|
593
|
-
if mode == 'w':
|
|
594
|
-
self.root().attrs['pymodaq_version'] = utils.get_version()
|
|
595
|
-
return self._h5file
|
|
596
|
-
else:
|
|
597
|
-
self._h5file = self.h5_library.File(str(fullpathname), mode=mode, **kwargs)
|
|
598
|
-
|
|
599
|
-
if mode == 'w':
|
|
600
|
-
self.root().attrs['TITLE'] = title
|
|
601
|
-
self.root().attrs['pymodaq_version'] = utils.get_version()
|
|
602
|
-
return self._h5file
|
|
603
|
-
|
|
604
|
-
def save_file_as(self, filenamepath='h5copy.txt'):
|
|
605
|
-
if self.backend == 'tables':
|
|
606
|
-
self.h5file.copy_file(str(filenamepath))
|
|
607
|
-
else:
|
|
608
|
-
raise Warning(f'Not possible to copy the file with the "{self.backend}" backend')
|
|
609
|
-
|
|
610
|
-
def root(self):
|
|
611
|
-
if self.backend == 'tables':
|
|
612
|
-
return GROUP(self._h5file.get_node('/'), self.backend)
|
|
613
|
-
else:
|
|
614
|
-
return GROUP(self._h5file, self.backend)
|
|
615
|
-
|
|
616
|
-
def get_attr(self, node, attr_name=None):
|
|
617
|
-
if isinstance(node, Node):
|
|
618
|
-
node = node.node
|
|
619
|
-
return get_attr(node, attr_name, self.backend)
|
|
620
|
-
|
|
621
|
-
def set_attr(self, node, attr_name, attr_value):
|
|
622
|
-
if isinstance(node, Node):
|
|
623
|
-
node = node.node
|
|
624
|
-
return set_attr(node, attr_name, attr_value, self.backend)
|
|
625
|
-
|
|
626
|
-
def has_attr(self, node, attr_name):
|
|
627
|
-
return attr_name in self.get_node(node).attrs.attrs_name
|
|
628
|
-
|
|
629
|
-
def flush(self):
|
|
630
|
-
if self._h5file is not None:
|
|
631
|
-
self._h5file.flush()
|
|
632
|
-
|
|
633
|
-
def define_compression(self, compression, compression_opts):
|
|
634
|
-
"""Define cmpression library and level of compression
|
|
635
|
-
Parameters
|
|
636
|
-
----------
|
|
637
|
-
compression: (str) either gzip and zlib are supported here as they are compatible
|
|
638
|
-
but zlib is used by pytables while gzip is used by h5py
|
|
639
|
-
compression_opts (int) : 0 to 9 0: None, 9: maximum compression
|
|
640
|
-
"""
|
|
641
|
-
#
|
|
642
|
-
if self.backend == 'tables':
|
|
643
|
-
if compression == 'gzip':
|
|
644
|
-
compression = 'zlib'
|
|
645
|
-
self.compression = self.h5_library.Filters(complevel=compression_opts, complib=compression)
|
|
646
|
-
else:
|
|
647
|
-
if compression == 'zlib':
|
|
648
|
-
compression = 'gzip'
|
|
649
|
-
self.compression = dict(compression=compression, compression_opts=compression_opts)
|
|
650
|
-
|
|
651
|
-
def get_set_group(self, where, name, title=''):
|
|
652
|
-
"""Retrieve or create (if absent) a node group
|
|
653
|
-
Get attributed to the class attribute ``current_group``
|
|
654
|
-
|
|
655
|
-
Parameters
|
|
656
|
-
----------
|
|
657
|
-
where: str or node
|
|
658
|
-
path or parent node instance
|
|
659
|
-
name: str
|
|
660
|
-
group node name
|
|
661
|
-
title: str
|
|
662
|
-
node title
|
|
663
|
-
|
|
664
|
-
Returns
|
|
665
|
-
-------
|
|
666
|
-
group: group node
|
|
667
|
-
"""
|
|
668
|
-
if isinstance(where, Node):
|
|
669
|
-
where = where.node
|
|
670
|
-
|
|
671
|
-
if name not in list(self.get_children(where)):
|
|
672
|
-
if self.backend == 'tables':
|
|
673
|
-
group = self._h5file.create_group(where, name, title)
|
|
674
|
-
else:
|
|
675
|
-
group = self.get_node(where).node.create_group(name)
|
|
676
|
-
group.attrs['TITLE'] = title
|
|
677
|
-
group.attrs['CLASS'] = 'GROUP'
|
|
678
|
-
|
|
679
|
-
else:
|
|
680
|
-
group = self.get_node(where, name)
|
|
681
|
-
return GROUP(group, self.backend)
|
|
682
|
-
|
|
683
|
-
def get_group_by_title(self, where, title):
|
|
684
|
-
if isinstance(where, Node):
|
|
685
|
-
where = where.node
|
|
686
|
-
|
|
687
|
-
node = self.get_node(where).node
|
|
688
|
-
for child_name in self.get_children(node):
|
|
689
|
-
child = node[child_name]
|
|
690
|
-
if 'TITLE' in self.get_attr(child):
|
|
691
|
-
if self.get_attr(child, 'TITLE') == title and self.get_attr(child, 'CLASS') == 'GROUP':
|
|
692
|
-
return GROUP(child, self.backend)
|
|
693
|
-
return None
|
|
694
|
-
|
|
695
|
-
def is_node_in_group(self, where, name):
|
|
696
|
-
"""
|
|
697
|
-
Check if a given node with name is in the group defined by where (comparison on lower case strings)
|
|
698
|
-
Parameters
|
|
699
|
-
----------
|
|
700
|
-
where: (str or node)
|
|
701
|
-
path or parent node instance
|
|
702
|
-
name: (str)
|
|
703
|
-
group node name
|
|
704
|
-
|
|
705
|
-
Returns
|
|
706
|
-
-------
|
|
707
|
-
bool
|
|
708
|
-
True if node exists, False otherwise
|
|
709
|
-
"""
|
|
710
|
-
if isinstance(where, Node):
|
|
711
|
-
where = where.node
|
|
712
|
-
|
|
713
|
-
return name.lower() in [name.lower() for name in self.get_children(where)]
|
|
714
|
-
|
|
715
|
-
def get_node(self, where, name=None) -> Node:
|
|
716
|
-
if isinstance(where, Node):
|
|
717
|
-
where = where.node
|
|
718
|
-
try:
|
|
719
|
-
if self.backend == 'tables':
|
|
720
|
-
node = self._h5file.get_node(where, name)
|
|
721
|
-
else:
|
|
722
|
-
if name is not None:
|
|
723
|
-
if isinstance(where, str):
|
|
724
|
-
where += f'/{name}'
|
|
725
|
-
node = self._h5file.get(where)
|
|
726
|
-
else:
|
|
727
|
-
where = where.get(name)
|
|
728
|
-
node = where
|
|
729
|
-
else:
|
|
730
|
-
if isinstance(where, str):
|
|
731
|
-
node = self._h5file.get(where)
|
|
732
|
-
else:
|
|
733
|
-
node = where
|
|
734
|
-
except Exception as e:
|
|
735
|
-
raise NodeError(str(e))
|
|
736
|
-
|
|
737
|
-
if 'CLASS' not in self.get_attr(node):
|
|
738
|
-
self.set_attr(node, 'CLASS', 'GROUP')
|
|
739
|
-
return GROUP(node, self.backend)
|
|
740
|
-
else:
|
|
741
|
-
attr = self.get_attr(node, 'CLASS')
|
|
742
|
-
if 'ARRAY' not in attr:
|
|
743
|
-
return GROUP(node, self.backend)
|
|
744
|
-
elif attr == 'CARRAY':
|
|
745
|
-
return CARRAY(node, self.backend)
|
|
746
|
-
elif attr == 'EARRAY':
|
|
747
|
-
return EARRAY(node, self.backend)
|
|
748
|
-
elif attr == 'VLARRAY':
|
|
749
|
-
if self.get_attr(node, 'subdtype') == 'string':
|
|
750
|
-
return StringARRAY(node, self.backend)
|
|
751
|
-
else:
|
|
752
|
-
return VLARRAY(node, self.backend)
|
|
753
|
-
|
|
754
|
-
def get_node_name(self, node):
|
|
755
|
-
"""return node name
|
|
756
|
-
Parameters
|
|
757
|
-
----------
|
|
758
|
-
node (str or node instance), see h5py and pytables documentation on nodes
|
|
759
|
-
|
|
760
|
-
Returns
|
|
761
|
-
-------
|
|
762
|
-
str: name of the node
|
|
763
|
-
"""
|
|
764
|
-
if isinstance(node, Node):
|
|
765
|
-
node = node.node
|
|
766
|
-
return self.get_node(node).name
|
|
767
|
-
|
|
768
|
-
def get_node_path(self, node):
|
|
769
|
-
"""return node path
|
|
770
|
-
Parameters
|
|
771
|
-
----------
|
|
772
|
-
node (str or node instance), see h5py and pytables documentation on nodes
|
|
773
|
-
|
|
774
|
-
Returns
|
|
775
|
-
-------
|
|
776
|
-
str : full path of the node
|
|
777
|
-
"""
|
|
778
|
-
if isinstance(node, Node):
|
|
779
|
-
node = node.node
|
|
780
|
-
return self.get_node(node).path
|
|
781
|
-
|
|
782
|
-
def get_parent_node(self, node):
|
|
783
|
-
if node == self.root():
|
|
784
|
-
return None
|
|
785
|
-
if isinstance(node, Node):
|
|
786
|
-
node = node.node
|
|
787
|
-
|
|
788
|
-
if self.backend == 'tables':
|
|
789
|
-
return self.get_node(node._v_parent)
|
|
790
|
-
else:
|
|
791
|
-
return self.get_node(node.parent)
|
|
792
|
-
|
|
793
|
-
def get_children(self, where):
|
|
794
|
-
"""Get a dict containing all children node hanging from where with their name as keys and types among Node,
|
|
795
|
-
CARRAY, EARRAY, VLARRAY or StringARRAY
|
|
796
|
-
|
|
797
|
-
Parameters
|
|
798
|
-
----------
|
|
799
|
-
where (str or node instance)
|
|
800
|
-
see h5py and pytables documentation on nodes, and Node objects of this module
|
|
801
|
-
|
|
802
|
-
Returns
|
|
803
|
-
-------
|
|
804
|
-
dict: keys are children node names, values are the children nodes
|
|
805
|
-
|
|
806
|
-
See Also
|
|
807
|
-
--------
|
|
808
|
-
:meth:`.GROUP.children_name`
|
|
809
|
-
|
|
810
|
-
"""
|
|
811
|
-
where = self.get_node(where) # return a node object in case where is a string
|
|
812
|
-
if isinstance(where, Node):
|
|
813
|
-
where = where.node
|
|
814
|
-
|
|
815
|
-
mod = importlib.import_module('.backends', 'pymodaq.utils.h5modules')
|
|
816
|
-
children = dict([])
|
|
817
|
-
if self.backend == 'tables':
|
|
818
|
-
for child_name, child in where._v_children.items():
|
|
819
|
-
klass = get_attr(child, 'CLASS', self.backend)
|
|
820
|
-
if 'ARRAY' in klass:
|
|
821
|
-
_cls = getattr(mod, klass)
|
|
822
|
-
else:
|
|
823
|
-
_cls = GROUP
|
|
824
|
-
children[child_name] = _cls(child, self.backend)
|
|
825
|
-
else:
|
|
826
|
-
for child_name, child in where.items():
|
|
827
|
-
klass = get_attr(child, 'CLASS', self.backend)
|
|
828
|
-
if 'ARRAY' in klass:
|
|
829
|
-
_cls = getattr(mod, klass)
|
|
830
|
-
else:
|
|
831
|
-
_cls = GROUP
|
|
832
|
-
children[child_name] = _cls(child, self.backend)
|
|
833
|
-
return children
|
|
834
|
-
|
|
835
|
-
def walk_nodes(self, where):
|
|
836
|
-
where = self.get_node(where) # return a node object in case where is a string
|
|
837
|
-
yield where
|
|
838
|
-
for gr in self.walk_groups(where):
|
|
839
|
-
for child in self.get_children(gr).values():
|
|
840
|
-
yield child
|
|
841
|
-
|
|
842
|
-
def walk_groups(self, where):
|
|
843
|
-
where = self.get_node(where) # return a node object in case where is a string
|
|
844
|
-
if where.attrs['CLASS'] != 'GROUP':
|
|
845
|
-
return None
|
|
846
|
-
if self.backend == 'tables':
|
|
847
|
-
for ch in self.h5file.walk_groups(where.node):
|
|
848
|
-
yield self.get_node(ch)
|
|
849
|
-
else:
|
|
850
|
-
stack = [where]
|
|
851
|
-
yield where
|
|
852
|
-
while stack:
|
|
853
|
-
obj = stack.pop()
|
|
854
|
-
children = [child for child in self.get_children(obj).values() if child.attrs['CLASS'] == 'GROUP']
|
|
855
|
-
for child in children:
|
|
856
|
-
stack.append(child)
|
|
857
|
-
yield child
|
|
858
|
-
|
|
859
|
-
def read(self, array, *args, **kwargs):
|
|
860
|
-
if isinstance(array, CARRAY):
|
|
861
|
-
array = array.array
|
|
862
|
-
if self.backend == 'tables':
|
|
863
|
-
return array.read()
|
|
864
|
-
else:
|
|
865
|
-
return array[:]
|
|
866
|
-
|
|
867
|
-
def create_carray(self, where, name, obj=None, title=''):
|
|
868
|
-
if isinstance(where, Node):
|
|
869
|
-
where = where.node
|
|
870
|
-
if obj is None:
|
|
871
|
-
raise ValueError('Data to be saved as carray cannot be None')
|
|
872
|
-
dtype = obj.dtype
|
|
873
|
-
if self.backend == 'tables':
|
|
874
|
-
array = CARRAY(self._h5file.create_carray(where, name, obj=obj,
|
|
875
|
-
title=title,
|
|
876
|
-
filters=self.compression), self.backend)
|
|
877
|
-
else:
|
|
878
|
-
if self.compression is not None:
|
|
879
|
-
array = CARRAY(self.get_node(where).node.create_dataset(name, data=obj, **self.compression),
|
|
880
|
-
self.backend)
|
|
881
|
-
else:
|
|
882
|
-
array = CARRAY(self.get_node(where).node.create_dataset(name, data=obj), self.backend)
|
|
883
|
-
array.array.attrs['TITLE'] = title
|
|
884
|
-
array.array.attrs[
|
|
885
|
-
'CLASS'] = 'CARRAY' # direct writing using h5py to be compatible with pytable automatic class writing as binary
|
|
886
|
-
array.attrs['shape'] = obj.shape
|
|
887
|
-
array.attrs['dtype'] = dtype.name
|
|
888
|
-
array.attrs['subdtype'] = ''
|
|
889
|
-
array.attrs['backend'] = self.backend
|
|
890
|
-
return array
|
|
891
|
-
|
|
892
|
-
def create_earray(self, where, name, dtype, data_shape=None, title=''):
|
|
893
|
-
"""create enlargeable arrays from data with a given shape and of a given type. The array is enlargeable along
|
|
894
|
-
the first dimension
|
|
895
|
-
"""
|
|
896
|
-
if isinstance(where, Node):
|
|
897
|
-
where = where.node
|
|
898
|
-
dtype = np.dtype(dtype)
|
|
899
|
-
shape = [0]
|
|
900
|
-
if data_shape is not None:
|
|
901
|
-
shape.extend(list(data_shape))
|
|
902
|
-
shape = tuple(shape)
|
|
903
|
-
|
|
904
|
-
if self.backend == 'tables':
|
|
905
|
-
atom = self.h5_library.Atom.from_dtype(dtype)
|
|
906
|
-
array = EARRAY(self._h5file.create_earray(where, name, atom, shape=shape, title=title,
|
|
907
|
-
filters=self.compression), self.backend)
|
|
908
|
-
else:
|
|
909
|
-
maxshape = [None]
|
|
910
|
-
if data_shape is not None:
|
|
911
|
-
maxshape.extend(list(data_shape))
|
|
912
|
-
maxshape = tuple(maxshape)
|
|
913
|
-
if self.compression is not None:
|
|
914
|
-
array = EARRAY(
|
|
915
|
-
self.get_node(where).node.create_dataset(name, shape=shape, dtype=dtype, maxshape=maxshape,
|
|
916
|
-
**self.compression), self.backend)
|
|
917
|
-
else:
|
|
918
|
-
array = EARRAY(
|
|
919
|
-
self.get_node(where).node.create_dataset(name, shape=shape, dtype=dtype, maxshape=maxshape),
|
|
920
|
-
self.backend)
|
|
921
|
-
array.array.attrs['TITLE'] = title
|
|
922
|
-
array.array.attrs[
|
|
923
|
-
'CLASS'] = 'EARRAY' # direct writing using h5py to be compatible with pytable automatic class writing as binary
|
|
924
|
-
array.array.attrs['EXTDIM'] = 0
|
|
925
|
-
array.attrs['shape'] = shape
|
|
926
|
-
array.attrs['dtype'] = dtype.name
|
|
927
|
-
array.attrs['subdtype'] = ''
|
|
928
|
-
array.attrs['backend'] = self.backend
|
|
929
|
-
return array
|
|
930
|
-
|
|
931
|
-
def create_vlarray(self, where, name, dtype, title=''):
|
|
932
|
-
"""create variable data length and type and enlargeable 1D arrays
|
|
933
|
-
|
|
934
|
-
Parameters
|
|
935
|
-
----------
|
|
936
|
-
where: (str) group location in the file where to create the array node
|
|
937
|
-
name: (str) name of the array
|
|
938
|
-
dtype: (dtype) numpy dtype style, for particular case of strings, use dtype='string'
|
|
939
|
-
title: (str) node title attribute (written in capitals)
|
|
940
|
-
|
|
941
|
-
Returns
|
|
942
|
-
-------
|
|
943
|
-
array
|
|
944
|
-
|
|
945
|
-
"""
|
|
946
|
-
if isinstance(where, Node):
|
|
947
|
-
where = where.node
|
|
948
|
-
if dtype == 'string':
|
|
949
|
-
dtype = np.dtype(np.uint8)
|
|
950
|
-
subdtype = 'string'
|
|
951
|
-
else:
|
|
952
|
-
dtype = np.dtype(dtype)
|
|
953
|
-
subdtype = ''
|
|
954
|
-
if self.backend == 'tables':
|
|
955
|
-
atom = self.h5_library.Atom.from_dtype(dtype)
|
|
956
|
-
if subdtype == 'string':
|
|
957
|
-
array = StringARRAY(self._h5file.create_vlarray(where, name, atom, title=title,
|
|
958
|
-
filters=self.compression), self.backend)
|
|
959
|
-
else:
|
|
960
|
-
array = VLARRAY(self._h5file.create_vlarray(where, name, atom, title=title,
|
|
961
|
-
filters=self.compression), self.backend)
|
|
962
|
-
else:
|
|
963
|
-
maxshape = (None,)
|
|
964
|
-
if self.backend == 'h5py':
|
|
965
|
-
dt = self.h5_library.vlen_dtype(dtype)
|
|
966
|
-
else:
|
|
967
|
-
dt = h5pyd.special_dtype(dtype)
|
|
968
|
-
if self.compression is not None:
|
|
969
|
-
if subdtype == 'string':
|
|
970
|
-
array = StringARRAY(self.get_node(where).node.create_dataset(name, (0,), dtype=dt,
|
|
971
|
-
**self.compression, maxshape=maxshape),
|
|
972
|
-
self.backend)
|
|
973
|
-
else:
|
|
974
|
-
array = VLARRAY(self.get_node(where).node.create_dataset(name, (0,), dtype=dt, **self.compression,
|
|
975
|
-
maxshape=maxshape), self.backend)
|
|
976
|
-
else:
|
|
977
|
-
if subdtype == 'string':
|
|
978
|
-
array = StringARRAY(self.get_node(where).node.create_dataset(name, (0,), dtype=dt,
|
|
979
|
-
maxshape=maxshape), self.backend)
|
|
980
|
-
else:
|
|
981
|
-
array = VLARRAY(self.get_node(where).node.create_dataset(name, (0,), dtype=dt,
|
|
982
|
-
maxshape=maxshape), self.backend)
|
|
983
|
-
array.array.attrs['TITLE'] = title
|
|
984
|
-
array.array.attrs[
|
|
985
|
-
'CLASS'] = 'VLARRAY' # direct writing using h5py to be compatible with pytable automatic class writing as binary
|
|
986
|
-
array.array.attrs['EXTDIM'] = 0
|
|
987
|
-
array.attrs['shape'] = (0,)
|
|
988
|
-
array.attrs['dtype'] = dtype.name
|
|
989
|
-
array.attrs['subdtype'] = subdtype
|
|
990
|
-
array.attrs['backend'] = self.backend
|
|
991
|
-
return array
|
|
992
|
-
|
|
993
|
-
def add_group(self, group_name, group_type: GroupType, where, title='', metadata=dict([])) -> GROUP:
|
|
994
|
-
"""
|
|
995
|
-
Add a node in the h5 file tree of the group type
|
|
996
|
-
Parameters
|
|
997
|
-
----------
|
|
998
|
-
group_name: (str) a custom name for this group
|
|
999
|
-
group_type: str or GroupType enum
|
|
1000
|
-
one of the possible values of GroupType
|
|
1001
|
-
where: (str or node) parent node where to create the new group
|
|
1002
|
-
metadata: (dict) extra metadata to be saved with this new group node
|
|
1003
|
-
|
|
1004
|
-
Returns
|
|
1005
|
-
-------
|
|
1006
|
-
(node): newly created group node
|
|
1007
|
-
"""
|
|
1008
|
-
if isinstance(where, Node):
|
|
1009
|
-
where = where.node
|
|
1010
|
-
|
|
1011
|
-
group_type = enum_checker(GroupType, group_type)
|
|
1012
|
-
|
|
1013
|
-
if group_name in self.get_children(self.get_node(where)):
|
|
1014
|
-
node = self.get_node(where, group_name)
|
|
1015
|
-
|
|
1016
|
-
else:
|
|
1017
|
-
node = self.get_set_group(where, utils.capitalize(group_name), title)
|
|
1018
|
-
node.attrs['type'] = group_type.name.lower()
|
|
1019
|
-
for metadat in metadata:
|
|
1020
|
-
node.attrs[metadat] = metadata[metadat]
|
|
1021
|
-
node.attrs['backend'] = self.backend
|
|
1022
|
-
return node
|