pymodaq_plugins_beam_shaping 5.3.1__tar.gz → 5.3.2__tar.gz
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.
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/AGENTS.md +5 -1
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/AGENTS_BEAM_SHAPING.md +1 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/PKG-INFO +1 -1
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/scripts/binary_holograms_snapshots.py +4 -1
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/algorithm_reference.rst +43 -1
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/algorithms.rst +53 -5
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/corrections.rst +3 -1
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/data_management.rst +121 -23
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/__init__.py +7 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/algo_base.py +112 -6
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/algorithm_app.py +176 -112
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/algorithms/binary_holograms.py +19 -2
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/algorithms/checker_board.py +6 -2
- pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/algorithms/compensation.py +133 -0
- pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/algorithms/compensations/divide_by_input.py +40 -0
- pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/algorithms/compensations/no_compensation.py +11 -0
- pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/algorithms/ini_phases/random_phase.py +23 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/extensions/spatial_beam_shaping.py +121 -39
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/field/field_loader_app.py +17 -1
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/field/h5.py +22 -5
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/scripts/algorithm_playground.py +23 -9
- pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/scripts/plot_convergence.py +49 -0
- pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/utilities/__init__.py +0 -0
- pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/utilities/h5saving.py +439 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/utilities/headless_algorithms.py +199 -34
- pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/utilities/region_outline.py +59 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/utilities/regions.py +18 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/conftest.py +28 -0
- pymodaq_plugins_beam_shaping-5.3.2/tests/test_algo_app_settings.py +107 -0
- pymodaq_plugins_beam_shaping-5.3.2/tests/test_algo_helpers.py +261 -0
- pymodaq_plugins_beam_shaping-5.3.2/tests/test_algorithm_playground.py +486 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/test_algorithm_status.py +4 -5
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/test_binary_holograms.py +2 -0
- pymodaq_plugins_beam_shaping-5.3.2/tests/test_compensation.py +107 -0
- pymodaq_plugins_beam_shaping-5.3.2/tests/test_custom_apps.py +332 -0
- pymodaq_plugins_beam_shaping-5.3.2/tests/test_region_outline.py +270 -0
- pymodaq_plugins_beam_shaping-5.3.2/tests/test_saved_version.py +69 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/test_shaper_interface.py +109 -0
- pymodaq_plugins_beam_shaping-5.3.1/src/pymodaq_plugins_beam_shaping/algorithms/ini_phases/random_phase.py +0 -10
- pymodaq_plugins_beam_shaping-5.3.1/src/pymodaq_plugins_beam_shaping/utilities/h5saving.py +0 -79
- pymodaq_plugins_beam_shaping-5.3.1/tests/test_algo_helpers.py +0 -61
- pymodaq_plugins_beam_shaping-5.3.1/tests/test_algorithm_playground.py +0 -223
- pymodaq_plugins_beam_shaping-5.3.1/tests/test_custom_apps.py +0 -161
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/.gitattributes +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/.github/workflows/compatibility.yml +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/.github/workflows/python-publish.yml +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/.github/workflows/tests.yml +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/.gitignore +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/CLAUDE.md +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/LICENSE +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/MANIFEST.in +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/README.rst +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/Makefile +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/make.bat +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/requirements.txt +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/scripts/data_browse.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_images/binary_holograms.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_images/calibration.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_images/corrections.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_images/field_loader.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_images/field_tool.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_images/layout.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_images/main_app.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_images/measurement_amplitude.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_images/schema.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_images/setup_field_loader.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/css/layout.css +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/css/overflow.css +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/icons/add_circle.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/icons/deblur.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/icons/equalizer.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/icons/file_open.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/icons/grid_off.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/icons/grid_on.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/icons/ink_eraser.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/icons/ink_eraser_off.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/icons/input.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/icons/save.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/icons/target.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/js/sidebar_toggle.js +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/logo.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_templates/apidoc/module.rst_t +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_templates/apidoc/package.rst_t +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_templates/apidoc/toc.rst_t +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/acknowledgments.rst +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/bibtex.bib +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/conf.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/index.rst +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/installation.rst +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/introduction.rst +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/quick_start.rst +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/redirects.txt +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/references.rst +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/theory.rst +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/troubleshooting.rst +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/tutorials.rst +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/calibration.rst +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/custom_algorithm.rst +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/field_tool.rst +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/fields.rst +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/index.rst +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/interface.rst +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/shapers.rst +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/slmsuite.rst +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/hatch_build.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/icon.ico +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/pyproject.toml +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/readthedocs.yml +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/__init__.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/algo_config.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/algorithms/__init__.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/algorithms/diffractive.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/algorithms/direct.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/algorithms/minimizer.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/algorithms/optim.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/algorithms/projections.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/algorithms/torch_base.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1/src/pymodaq_plugins_beam_shaping/algorithms/ini_phases → pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/algorithms/compensations}/__init__.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/factory.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/ini_phase.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1/src/pymodaq_plugins_beam_shaping/algorithms/stoppings → pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/algorithms/ini_phases}/__init__.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/ini_phases/flat_phase.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/ini_phases/quadratic_phase.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/loss.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/stopping.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1/src/pymodaq_plugins_beam_shaping/field/loaders → pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/algorithms/stoppings}/__init__.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/stoppings/stoppings_base.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/utils.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/daq_move_plugins/__init__.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/daq_move_plugins/daq_move_FocalLength.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/daq_move_plugins/daq_move_MockAutoFocus.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/daq_move_plugins/daq_move_MockShaper.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/daq_move_plugins/daq_move_Zernike.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/daq_viewer_plugins/__init__.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/daq_viewer_plugins/plugins_2D/__init__.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/daq_viewer_plugins/plugins_2D/daq_2Dviewer_MockAutoFocus.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/daq_viewer_plugins/plugins_2D/daq_2Dviewer_MockShaperCamera.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/extensions/__init__.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/field/__init__.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/field/factory.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/field/field.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/field/field_tool_app.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1/src/pymodaq_plugins_beam_shaping/hardware → pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/field/loaders}/__init__.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/field/loaders/dashboard_loader.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/field/loaders/from_functions_loader.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/field/loaders/image_loader.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/field/loaders/save_field_loader.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/field/operations/__init__.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/field/operations/base.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/field/operations/compute.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/field/operations/linear_phase.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/field/operations/log_amplitude.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/field/operations/unwrap.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/field/operations/zernike.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/field/utils.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1/src/pymodaq_plugins_beam_shaping/resources → pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/hardware}/__init__.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/hardware/autofocus.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/hardware/mock_shaper_camera.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/models/OptimizerModelAutoFocus.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/models/__init__.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/models/datamixer_autofocus.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/resources/Cemes - Logo - Sigle - Blanc.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/resources/Papillon_flower_BW_resized.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/resources/Pymodaq.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1/src/pymodaq_plugins_beam_shaping/scanners → pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/resources}/__init__.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/resources/cat_field.h5 +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/resources/cheshirecat_rect.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/resources/config_template.toml +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/resources/darumas_BW_resized.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/resources/dollars.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/resources/dollars.svg +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/resources/face.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/resources/holography.xml +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/resources/holography_calibration.scan +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/resources/mock_holo.xml +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/resources/one_piece.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/resources/osama.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/resources/zernike.png +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1/src/pymodaq_plugins_beam_shaping/scripts → pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/scanners}/__init__.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/scanners/calibration.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1/src/pymodaq_plugins_beam_shaping/slm → pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/scripts}/__init__.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/scripts/calibrate_slm.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/scripts/make_calibration_entry.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/setup/factory.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/setup/setup.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1/src/pymodaq_plugins_beam_shaping/utilities → pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/slm}/__init__.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/utilities/calibrating.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/utilities/corrections.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/utilities/data.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/utilities/masking.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/utilities/shaper.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/utilities/sizing.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/utilities/zernike.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/utils.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/algorithm_entry_points_test.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/element_test.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/field_test.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/pytensor_fft.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/pytorch_fft.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/pytorch_test_v1.ipynb +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/test_algorithms_by_modulator_type.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/test_calibration.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/test_field_tool.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/test_plugin_package_structure.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/test_regions.py +0 -0
- {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tox.ini +0 -0
|
@@ -207,4 +207,8 @@ extensions already does the job and only the conversion of the measurements or o
|
|
|
207
207
|
- [ ] Tests added for new behaviour using a mock controller (no real hardware in CI).
|
|
208
208
|
- [ ] Docstring of each plugin class states: compatible devices, what was tested, PyMoDAQ and OS versions,
|
|
209
209
|
drivers to install.
|
|
210
|
-
- [ ] `README.rst` updated; target PyMoDAQ version stated.
|
|
210
|
+
- [ ] `README.rst` updated; target PyMoDAQ version stated. Keep its section order: a short description, then `Authors`
|
|
211
|
+
(then `Contributors` if needed), then `Instruments` (`Actuators`, `Viewer0D`...). `pymodaq_plugin_manager` reads the
|
|
212
|
+
README from `Authors` to `Instruments` (`extract_authors_from_description` in its `validate.py`), so write nothing
|
|
213
|
+
else before these sections or between them: requirements, installation, hardware notes or differences with
|
|
214
|
+
another branch come after the `Instruments` list.
|
{pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/AGENTS_BEAM_SHAPING.md
RENAMED
|
@@ -30,6 +30,7 @@ close to the template so that it can be updated); this file is what is specific
|
|
|
30
30
|
| `algorithms/factory.py` | `AlgorithmFactory`, `register_algorithms()` and the entry point group `pymodaq_plugins_beam_shaping.algorithms` for third party algorithms. |
|
|
31
31
|
| `algorithms/algorithms/` | The **algorithms**, one module per family (see below). |
|
|
32
32
|
| `algorithms/ini_phases/`, `stoppings/`, `loss.py` | Initial phases, stopping criteria and loss functions used by iterative algorithms. |
|
|
33
|
+
| `algorithms/compensation.py`, `compensations/` | Compensation of the input beam profile (factory like the initial phases, chosen in the AlgoApp settings); an algorithm sets `INPUT_COMPENSATION` to the `Compensations` (StrEnum, add a member for a new compensation) member of its default compensation (None: none) and calls `compensate_target`. |
|
|
33
34
|
| `algorithms/algorithm_app.py` | `AlgoApp`: the widget running an algorithm, owning the masks, the shaper and the fields. |
|
|
34
35
|
| `algorithms/utils.py` | Enums (`AlgoStatus`, `AlgoType`, `ApplyMaskTo`, `LensSetup`). |
|
|
35
36
|
| `utilities/shaper.py` | `Shaper` and `ModulatorType` (phase, amplitude, both), defined in `pymodaq_plugins_utils`; `get_default_shaper()` reads the config. |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: pymodaq_plugins_beam_shaping
|
|
3
|
-
Version: 5.3.
|
|
3
|
+
Version: 5.3.2
|
|
4
4
|
Summary: PyMoDAQ's extension plugin to run optical shaping from various shapers (focusing on amplitude and phase shaping) and the image propagation
|
|
5
5
|
Project-URL: Homepage, https://pymodaq.cnrs.fr
|
|
6
6
|
Project-URL: Documentation , https://pymodaq.cnrs.fr
|
|
@@ -32,7 +32,10 @@ for name in ALGORITHMS:
|
|
|
32
32
|
pg.set_fields(algo, input_field, target_field)
|
|
33
33
|
# the order to filter, as given by the algorithm, in um from the center of the intermediate plane
|
|
34
34
|
y, x = np.array(algo.order_frequency()) * regions.pixel_sizes_in_um(algo.intermediate_pixel_sizes)
|
|
35
|
-
|
|
35
|
+
center_y, center_x = np.array(algo.shape) * regions.pixel_sizes_in_um(algo.intermediate_pixel_sizes) / 2
|
|
36
|
+
# in the frame of the extension: the origin is the corner of the field
|
|
37
|
+
mask = ((center_y + y - MASK_HALF_SIZE, center_y + y + MASK_HALF_SIZE),
|
|
38
|
+
(center_x + x - MASK_HALF_SIZE, center_x + x + MASK_HALF_SIZE))
|
|
36
39
|
pg.set_mask(app, ApplyMaskTo.INTERMEDIATE, mask, 'elliptical')
|
|
37
40
|
pg.run_algorithm(algo)
|
|
38
41
|
output = algo.output_field
|
|
@@ -8,6 +8,10 @@ Sizes of pixels in these settings follow the shaper (see :doc:`shapers`).
|
|
|
8
8
|
Settings shared by the algorithms
|
|
9
9
|
---------------------------------
|
|
10
10
|
|
|
11
|
+
The settings of the algorithm app (initial phase, masks, crosstalk, compensation of the input beam...) and the own
|
|
12
|
+
settings of each algorithm are saved in the configuration file, **per algorithm**, and loaded back when the algorithm
|
|
13
|
+
is selected (an algorithm never run keeps the values of the previous one).
|
|
14
|
+
|
|
11
15
|
Most algorithms start from an *initial phase* of the modulator, which is also a choice in the settings:
|
|
12
16
|
|
|
13
17
|
* **Random**: a random phase.
|
|
@@ -40,7 +44,7 @@ that removes the undiffracted light. Not iterative. Implements the five methods
|
|
|
40
44
|
* ``Diffractive Models``: *Relative Amplitude* (method A), *Scattering* (B), *Davis* (C), *Bolduc* (D) or *Arrizon* (E).
|
|
41
45
|
* ``Order N`` (default 10).
|
|
42
46
|
|
|
43
|
-
OL2014 - Amplitude
|
|
47
|
+
OL2014 - Amplitude-Phase Checkerboard
|
|
44
48
|
-------------------------------------
|
|
45
49
|
|
|
46
50
|
Creates **amplitude and phase** images with a phase-only modulator in a **4f** line with a filter in the Fourier plane,
|
|
@@ -49,6 +53,8 @@ by encoding the complex field on a checkerboard (:cite:t:`mendoza-yero_encoding_
|
|
|
49
53
|
*Settings*:
|
|
50
54
|
|
|
51
55
|
* ``Mask block size (pxls)`` (default 5): size of the blocks of the checkerboard.
|
|
56
|
+
* The input beam is compensated (see *Input compensation* below): the amplitude of the target is divided by the one of
|
|
57
|
+
the beam before the angles of the checkerboard are computed.
|
|
52
58
|
* ``amplitude divider`` (default 1).
|
|
53
59
|
|
|
54
60
|
.. _sec-algo-amplitude-modulation:
|
|
@@ -91,10 +97,17 @@ in the review but not available.
|
|
|
91
97
|
* ``Binarize`` (default checked): the pattern is binarized, as a DMD can only switch its pixels on or off. Unchecked,
|
|
92
98
|
the grey levels of the pattern are kept (the grey off-axis hologram, an ideal modulation not feasible on a DMD, to
|
|
93
99
|
see what the binarization costs).
|
|
100
|
+
* The compensation of the input beam is not a setting of the algorithm: see *Input compensation* below.
|
|
94
101
|
* ``Remove carrier`` (default checked), ``Carrier from`` and ``Carrier factor``: see below.
|
|
95
102
|
* ``Order position``: a read-only text, updated with the periods, giving the position of the order to filter, and the
|
|
96
103
|
slices of a mask around it that can be copied to the slices of the *Intermediate Masking*.
|
|
97
104
|
|
|
105
|
+
What is sent to the modulator is the *SLM field* (``slm_field`` of the algorithm, ``slm`` data): the amplitude pattern
|
|
106
|
+
(0 and 1 for a DMD, 1 for a phase-only modulator) and the phase (0 for an amplitude-only modulator), without the
|
|
107
|
+
corrections that the extension adds when sending. It is not the *modulator field*, the field just after the modulator:
|
|
108
|
+
this one is the input beam times the SLM field, and is the one used to compute the output. The fields of the
|
|
109
|
+
algorithm hold ``slm/phase`` for every type of modulator and ``slm/amplitude`` when an amplitude is sent.
|
|
110
|
+
|
|
98
111
|
The two first orders of the grating carry opposite phases, and this is physical: the order at ``+ν`` carries the phase
|
|
99
112
|
``-φ`` of the target, the one at ``-ν`` (the order (-1, 0) of the review) carries ``+φ``. Select the order that carries
|
|
100
113
|
the phase of the target: the one the *Order position* gives.
|
|
@@ -232,3 +245,32 @@ Minimize and TorchOptim
|
|
|
232
245
|
|
|
233
246
|
*Minimize* only: ``Method`` of the minimizer (default l-bfgs): bfgs, l-bfgs, cg, newton-cg, newton-exact, dogleg,
|
|
234
247
|
trust-ncg, trust-exact or trust-krylov.
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
Input compensation
|
|
251
|
+
------------------
|
|
252
|
+
|
|
253
|
+
The algorithms that compute the pattern of the modulator from the target (*Parallel Lee*, *Superpixel* and the
|
|
254
|
+
checkerboard *OL2014*) give, without compensation, a target multiplied by the amplitude profile of the input beam. The
|
|
255
|
+
group ``Input Compensation`` of the settings of the algorithm app (shown for these algorithms only, like the initial
|
|
256
|
+
phase for the algorithms that have one) chooses what is done:
|
|
257
|
+
|
|
258
|
+
* ``NoCompensation``: the output is the target times the profile of the beam.
|
|
259
|
+
* ``DivideByInput`` (default): the amplitude to encode is the target divided by the input amplitude, scaled so that no
|
|
260
|
+
pixel has to give more than the input. ``Min input level`` (default 0.2: the transmission needed is at most 5 times
|
|
261
|
+
the one at the peak of the beam, a lower level leaves little to the centre) is the fraction of the maximum of the
|
|
262
|
+
input amplitude below which the target cannot be obtained: this *unreachable* region is off (null transmission). For
|
|
263
|
+
*Superpixel* the input is averaged over each superpixel. 4f setups: the magnification only changes the axes, the
|
|
264
|
+
arrays keep their shape.
|
|
265
|
+
|
|
266
|
+
The unreachable region is outlined in red, **as soon as the compensation is chosen** and without running the algorithm,
|
|
267
|
+
on the input and target loaders and on the target views; after a run also on the modulator and output views of the
|
|
268
|
+
extension. It is in the ``unreachable`` data of the algorithm and its fraction of the target is
|
|
269
|
+
``unreachable_fraction``. In a script, ``set_compensation(app, 'DivideByInput', {'min_input_level': 0.3})`` of
|
|
270
|
+
``headless_algorithms`` chooses the compensation and ``algo.preview_unreachable()`` gives the region.
|
|
271
|
+
|
|
272
|
+
A compensation is a class of the package ``algorithms/compensations``, registered with
|
|
273
|
+
``CompensationFactory.register_compensation()``, with its own ``params``, like an initial phase: another type (for
|
|
274
|
+
instance for a 2f setup) is added by writing one more module. An algorithm that uses it sets ``INPUT_COMPENSATION`` to the name of its
|
|
275
|
+
default compensation (``'DivideByInput'`` for the algorithms above, ``None`` for an algorithm that does not use one: the
|
|
276
|
+
group is then hidden) and calls ``self.compensate_target(amplitude)``.
|
|
@@ -36,7 +36,7 @@ BeamShaping itself, then the ones provided by other installed packages (see :doc
|
|
|
36
36
|
- Amplitude images with a phase-only modulator and a filter in the Fourier plane, several diffractive models
|
|
37
37
|
(:cite:t:`Clark2016`).
|
|
38
38
|
* - Direct diffractive modulation
|
|
39
|
-
- OL2014 - Amplitude
|
|
39
|
+
- OL2014 - Amplitude-Phase Checkerboard
|
|
40
40
|
- 4f
|
|
41
41
|
- ❌
|
|
42
42
|
- ✅
|
|
@@ -257,7 +257,7 @@ shaping for the MRAF algorithm using different initial phase type and mixing par
|
|
|
257
257
|
|
|
258
258
|
.. note::
|
|
259
259
|
The metrics (NRMSE, Fidelity, Efficiency) are **automatically saved** in the ``.h5beam`` file under
|
|
260
|
-
``/RawData/
|
|
260
|
+
``/RawData/Shaping/Final/``. See :ref:`h5beam-structure` for details.
|
|
261
261
|
|
|
262
262
|
Algorithms provided by other packages
|
|
263
263
|
-------------------------------------
|
|
@@ -283,19 +283,31 @@ cells one after the other, editing the settings on the way:
|
|
|
283
283
|
target by default. Each field is plotted once loaded (the target with the axes of the modulator plane, the algorithm
|
|
284
284
|
scales it to the target plane: ``pg.plot_field(pg.get_target_field(algo))`` shows it after the next cell);
|
|
285
285
|
* *Algorithm*: ``ALGORITHM`` and ``ALGORITHM_PARAMS``, the name of the algorithm as shown in the extension and the
|
|
286
|
-
values of its parameters, given by name (``'carrier_factor'``), with
|
|
287
|
-
(``'phase
|
|
286
|
+
values of its parameters, given by name (``'carrier_factor'``), with ``/`` for parameters in a group
|
|
287
|
+
(``'phase/load'``). An unknown name raises an error listing the possible ones. ``N_ITERATIONS`` completes the run, and
|
|
288
288
|
``INITIAL_PHASE`` / ``INITIAL_PHASE_PARAMS`` give the initial phase as chosen in the extension, from the initial
|
|
289
289
|
phases factory (``'FlatPhase'``, ``'RandomPhase'``, ``'QuadraticPhase'``...) with its parameters, or a 2D array of the
|
|
290
290
|
shape of the fields;
|
|
291
291
|
* *Snap*: ``pg.snap`` runs one step of the algorithm without any mask and plots the intermediate plane of 4f setups
|
|
292
292
|
(intensity in log scale), to see where the mask has to be placed;
|
|
293
293
|
* *Masks*: set ``APPLY_TARGET_MASK`` or ``APPLY_INTERMEDIATE_MASK`` to ``True`` to apply a mask (algorithms such as
|
|
294
|
-
*Binary Threshold*, *Parallel Lee* and *Superpixel* need the one of the intermediate plane), its region being given in um
|
|
294
|
+
*Binary Threshold*, *Parallel Lee* and *Superpixel* need the one of the intermediate plane), its region being given in um as the slices shown by the extension, in its frame (the origin is the corner of the field), along y then along x, that can be pasted as is (``(slice(1073, 5365, None), slice(1073, 5365, None))``, as text or not; ``((1073, 5365), (1073, 5365))`` is accepted too) (``None``: the default region
|
|
295
295
|
of the extension, centered and covering 2/3 of the effective area of the SLM in the plane, printed to be edited). The cell
|
|
296
296
|
draws the outline of the intermediate mask on the plot of the snap, which is updated (not created again): run it
|
|
297
297
|
again until the mask is right.
|
|
298
298
|
|
|
299
|
+
The *Run* cell can save the output of each iteration: ``SAVE_FIELDS`` (``True`` for all the fields, the amplitude and
|
|
300
|
+
phase of the output and modulator planes and the intensity of the intermediate one, or the names of some of them such
|
|
301
|
+
as ``('modulator/phase',)``) and ``SAVE_METRICS``, both off by default. ``SAVE_FINAL`` saves once, at the end of the run, all the fields and the metrics of the last iteration, as the *Save* action of the extension does, whatever is saved at each iteration. The format is the one of the continuous saving
|
|
302
|
+
of the extension: a group ``/RawData/ShapingXXX`` per run, with the settings of the run, holding one sub group for each kind of data: ``Fields`` (the fields saved at each iteration) and ``Metrics`` (the metrics), each enlarged along its own ``step`` navigation axis, ``Final`` (the fields saved once at the end, without navigation axis, as in the extension's *Save*, whose main group is the same ``Shaping`` group, without index) and the ``Input`` and ``Target`` groups (the fields as used by the algorithm, with the settings of their loaders, as the *Input* and *Target* groups of the extension's *Save*, readable with the same function). The sub groups of the data per iteration and ``Final`` are only created if requested. The settings of the run are saved
|
|
303
|
+
as in the extension: the name of the algorithm, the number of iterations, the initial phase
|
|
304
|
+
and its parameters, the masks (applied or not, type and slices) and the parameters of the algorithm. ``SAVE_FILE`` gives the file (created if needed, the runs being added to it); with ``None``
|
|
305
|
+
a file is created in the PyMoDAQ data folder at the first saved run and holds the next ones. Its path is printed (``algo.saved_h5file``).
|
|
306
|
+
|
|
307
|
+
The script ``scripts/plot_convergence.py`` plots the convergence of the saved metrics (one panel per metric against the iteration) from the ``Metrics`` group of a saved run.
|
|
308
|
+
|
|
309
|
+
During the run of an iterative algorithm, the index of the iteration and the metrics (fitness and efficiency) are printed after each iteration (``verbose=False`` in ``pg.run_algorithm`` to silence it).
|
|
310
|
+
|
|
299
311
|
The last cells run the algorithm, plot an overview as in the extension, then the output field and the intermediate
|
|
300
312
|
plane of 4f setups (its intensity in log scale), and give the results as ``Field`` objects. The overview shows the
|
|
301
313
|
output, modulator and intermediate planes with their amplitude and phase, and the metrics: with ``'qt'`` a dock per field
|
|
@@ -331,3 +343,39 @@ version stays usable.
|
|
|
331
343
|
The parameters of the algorithms are widgets, so a ``QApplication`` is needed. The helpers create it if there is none,
|
|
332
344
|
no event loop is required. Matplotlib must be installed. The algorithm receives the same calls as in the extension
|
|
333
345
|
through a minimal stand-in for it, but the script has not been tested on hardware.
|
|
346
|
+
|
|
347
|
+
Running the same algorithm many times from a script
|
|
348
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
349
|
+
|
|
350
|
+
The cells of the script are thin wrappers around the helpers of ``headless_algorithms``, which can be called from your
|
|
351
|
+
own script to run an algorithm many times with all the settings fixed but a few ones that change from one run to the
|
|
352
|
+
next (a parameter, the seed of the random initial phase, the target...). The shaper and the fields are loaded once, and
|
|
353
|
+
only the algorithm is created again for each run, which is cheap compared to an iteration (a few tens of ms against
|
|
354
|
+
some hundreds of ms for a 1024 x 1024 shaper). Parameters are given as in the script, by name, with ``/`` for groups:
|
|
355
|
+
|
|
356
|
+
.. code-block:: python
|
|
357
|
+
|
|
358
|
+
from pymodaq_plugins_beam_shaping.utilities import headless_algorithms as pg
|
|
359
|
+
|
|
360
|
+
# what stays fixed: loaded once
|
|
361
|
+
app = pg.HeadlessApp(pg.make_shaper())
|
|
362
|
+
input_field = pg.load_field('GaussianIntensity', {}, app)
|
|
363
|
+
target_field = pg.load_field('ImageFiles', {'phase/load': False}, app)
|
|
364
|
+
algo_class = pg.reload_algorithm('Gerchberg-Saxton')
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
def run(n_iterations=100, algo_params=None, ini_phase='RandomPhase', ini_phase_params=None, **saving):
|
|
368
|
+
""" One run with a new algorithm, only what is given differs from the defaults """
|
|
369
|
+
algo = pg.create_algorithm(algo_class, app, algo_params)
|
|
370
|
+
pg.set_fields(algo, input_field, target_field)
|
|
371
|
+
pg.run_algorithm(algo, n_iterations, ini_phase, ini_phase_params, **saving)
|
|
372
|
+
return algo
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
# what changes: here the seed of the random initial phase, one run per value
|
|
376
|
+
for seed in range(5):
|
|
377
|
+
algo = run(n_iterations=3, ini_phase_params=dict(fixed_seed=True, seed=seed))
|
|
378
|
+
print(f'seed {seed}: fitness = {algo.fitness:.4g}, efficiency = {algo.efficiency:.4g}')
|
|
379
|
+
|
|
380
|
+
The saving options of ``pg.run_algorithm`` (``save_fields``, ``save_metrics``, ``h5file``) can be given to ``run``: with
|
|
381
|
+
the same ``h5file`` all the runs are added to a single file, a group per run.
|
|
@@ -23,7 +23,9 @@ Phase Corrections
|
|
|
23
23
|
=================
|
|
24
24
|
|
|
25
25
|
A real setup often features optical aberrations deteriorating the calculated shaping. A correction module (and interface
|
|
26
|
-
see :numref:`FIG-corrections`) is provided to add correction terms to the calculated modulator phase.
|
|
26
|
+
see :numref:`FIG-corrections`) is provided to add correction terms to the calculated modulator phase. As they act on the phase, the corrections (and the :doc:`calibration <calibration>` of the
|
|
27
|
+
phase) are only available, and their actions only shown, if the modulator of the shaper can modulate the phase (phase only
|
|
28
|
+
or phase and amplitude), not for amplitude modulators such as DMDs.
|
|
27
29
|
|
|
28
30
|
.. _sec-corrections-types:
|
|
29
31
|
|
|
@@ -113,6 +113,102 @@ The ``.h5field`` file has the following hierarchy:
|
|
|
113
113
|
|
|
114
114
|
The ``.h5beam`` file has the following hierarchy:
|
|
115
115
|
|
|
116
|
+
.. code-block:: text
|
|
117
|
+
|
|
118
|
+
/
|
|
119
|
+
├── [Global Attributes] # Metadata (date, version, etc.)
|
|
120
|
+
│
|
|
121
|
+
└── RawData/ (GROUP)
|
|
122
|
+
├── @settings: <binary> # **Global configuration** (XML)
|
|
123
|
+
│ # Includes: wavelength, setup_type (2f/4f/no_lens),
|
|
124
|
+
│ # SLM settings, default loaders, etc.
|
|
125
|
+
│
|
|
126
|
+
├── Shaping/ (GROUP) # **One group for the whole session** (no index)
|
|
127
|
+
│ ├── @settings: <binary> # Algorithm name, run settings and algorithm settings (XML)
|
|
128
|
+
│ │
|
|
129
|
+
│ ├── Final/ (GROUP) # Algorithm results (last iteration)
|
|
130
|
+
│ │ ├── Data0D/CH00/Data00 # **NRMSE** (Normalized Root Mean Square Error)
|
|
131
|
+
│ │ │ Data01 # **Efficiency** (beam shaping efficiency)
|
|
132
|
+
│ │ └── Data2D/ (GROUP)
|
|
133
|
+
│ │ ├── CH00/ # **Output Field Amplitude** (Axis00, Axis01: coordinates)
|
|
134
|
+
│ │ ├── CH01/ # **Output Field Phase**
|
|
135
|
+
│ │ ├── CH02/ # **Modulator Amplitude** (sent to SLM)
|
|
136
|
+
│ │ └── CH03/ # **Modulator Phase** (sent to SLM)
|
|
137
|
+
│ │
|
|
138
|
+
│ ├── Input/ (GROUP) # **Input Field** (source beam)
|
|
139
|
+
│ │ ├── @settings: <binary> # Loader app and loader settings (XML)
|
|
140
|
+
│ │ ├── Axis00, Axis01 # Coordinates (m)
|
|
141
|
+
│ │ ├── Data00 (CARRAY) # Amplitude
|
|
142
|
+
│ │ └── Data01 (CARRAY) # Phase
|
|
143
|
+
│ │
|
|
144
|
+
│ ├── Target/ (GROUP) # **Target Field** (desired output), same content as Input
|
|
145
|
+
│ │
|
|
146
|
+
│ └── SLM/ (GROUP) # **SLM Phases**
|
|
147
|
+
│ └── Data2D/ (GROUP) # Phases by channel
|
|
148
|
+
│ ├── CH00/ # **Algorithm Phase** (to be applied to SLM), e.g. (540, 960)
|
|
149
|
+
│ ├── CH01/ # **Quadratic Phase** (curvature correction)
|
|
150
|
+
│ ├── CH02/ # **Linear Phase** (tilt correction)
|
|
151
|
+
│ └── CH03/ # **Zernike Phase** (aberration correction)
|
|
152
|
+
│
|
|
153
|
+
└── Logger (VLARRAY) # Log messages (optional)
|
|
154
|
+
|
|
155
|
+
.. list-table:: **Key Attributes in .h5field**
|
|
156
|
+
:header-rows: 1
|
|
157
|
+
:widths: 30 20 50
|
|
158
|
+
:class: longtable
|
|
159
|
+
|
|
160
|
+
* - **Location**
|
|
161
|
+
- **Attribute**
|
|
162
|
+
- **Description**
|
|
163
|
+
* - ``/``
|
|
164
|
+
- ``date``, ``time``
|
|
165
|
+
- File creation timestamp (format: ``YYYY-MM-DD``, ``HH:MM:SS.microseconds``).
|
|
166
|
+
* - ``/``
|
|
167
|
+
- ``pymodaq_version``, ``pymodaq_data_version``
|
|
168
|
+
- PyMoDAQ and pymodaq_data versions used to create the file.
|
|
169
|
+
* - ``/RawData/Field/Axis00``
|
|
170
|
+
- ``scaling``
|
|
171
|
+
- **Pixel size in meters** (e.g., ``6.494e-06`` for 6.494 µm/pixel).
|
|
172
|
+
* - ``/RawData/Field/Axis00``
|
|
173
|
+
- ``units``
|
|
174
|
+
- Physical unit for the axis (``"m"`` for meters).
|
|
175
|
+
* - ``/RawData/Field/Data00``
|
|
176
|
+
- ``label``
|
|
177
|
+
- **Data type** (``"Amplitude"`` or ``"Phase"``).
|
|
178
|
+
* - ``/RawData/Field/Data00``
|
|
179
|
+
- ``shape``
|
|
180
|
+
- Dimensions of the 2D array (e.g., ``(1024, 1024)``).
|
|
181
|
+
* - ``/RawData/Field``
|
|
182
|
+
- ``settings``
|
|
183
|
+
- **Serialized XML configuration** of the Field Loader (includes loader type, parameters, masking, etc.).
|
|
184
|
+
|
|
185
|
+
.. note::
|
|
186
|
+
- The **amplitude** and **phase** are stored as **separate datasets** (``Data00`` and ``Data01``).
|
|
187
|
+
- The **physical coordinates** (in meters) are defined by ``Axis00`` (X) and ``Axis01`` (Y).
|
|
188
|
+
- The ``scaling`` attribute of each axis gives the **pixel pitch** in meters.
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
.. _h5beam-format:
|
|
193
|
+
|
|
194
|
+
.h5beam Format
|
|
195
|
+
~~~~~~~~~~~~~~
|
|
196
|
+
|
|
197
|
+
**Purpose**: Store a **complete beam shaping session**, including:
|
|
198
|
+
- Input and Target fields.
|
|
199
|
+
- SLM phases (algorithm, quadratic, linear, Zernike).
|
|
200
|
+
- Algorithm results (output field, modulator field, metrics).
|
|
201
|
+
- Global configuration (wavelength, setup type, etc.).
|
|
202
|
+
|
|
203
|
+
**Generated by**: Beam Shaping Extension.
|
|
204
|
+
|
|
205
|
+
.. _h5beam-structure:
|
|
206
|
+
|
|
207
|
+
**HDF5 Structure**
|
|
208
|
+
""""""""""""""""""
|
|
209
|
+
|
|
210
|
+
The ``.h5beam`` file has the following hierarchy:
|
|
211
|
+
|
|
116
212
|
.. code-block:: text
|
|
117
213
|
|
|
118
214
|
/
|
|
@@ -182,43 +278,45 @@ The ``.h5beam`` file has the following hierarchy:
|
|
|
182
278
|
* - **Group**
|
|
183
279
|
- **Purpose**
|
|
184
280
|
- **Key Data**
|
|
185
|
-
* - ``/RawData/Input``
|
|
281
|
+
* - ``/RawData/Shaping/Input``
|
|
186
282
|
- Source beam field
|
|
187
283
|
- Amplitude + Phase (2D arrays)
|
|
188
|
-
* - ``/RawData/Target``
|
|
284
|
+
* - ``/RawData/Shaping/Target``
|
|
189
285
|
- Desired output field
|
|
190
286
|
- Amplitude + Phase (2D arrays)
|
|
191
|
-
* - ``/RawData/
|
|
287
|
+
* - ``/RawData/Shaping/Final/Data0D/CH00``
|
|
192
288
|
- **Performance metrics**
|
|
193
289
|
- NRMSE (``Data00``), Efficiency (``Data01``)
|
|
194
|
-
* - ``/RawData/
|
|
290
|
+
* - ``/RawData/Shaping/Final/Data2D/CH00``
|
|
195
291
|
- **Output field amplitude**
|
|
196
292
|
- 2D array (same size as Input/Target)
|
|
197
|
-
* - ``/RawData/
|
|
293
|
+
* - ``/RawData/Shaping/Final/Data2D/CH01``
|
|
198
294
|
- **Output field phase**
|
|
199
295
|
- 2D array (radians)
|
|
200
|
-
* - ``/RawData/
|
|
296
|
+
* - ``/RawData/Shaping/Final/Data2D/CH02``
|
|
201
297
|
- **Modulator amplitude**
|
|
202
298
|
- 2D array (sent to SLM)
|
|
203
|
-
* - ``/RawData/
|
|
299
|
+
* - ``/RawData/Shaping/Final/Data2D/CH03``
|
|
204
300
|
- **Modulator phase**
|
|
205
301
|
- 2D array (radians)
|
|
206
|
-
* - ``/RawData/SLM/Data2D/CH00``
|
|
302
|
+
* - ``/RawData/Shaping/SLM/Data2D/CH00``
|
|
207
303
|
- **Algorithm phase for SLM**
|
|
208
304
|
- 2D array (shape matches SLM resolution, e.g., 540x960)
|
|
209
|
-
* - ``/RawData/SLM/Data2D/CH01``
|
|
305
|
+
* - ``/RawData/Shaping/SLM/Data2D/CH01``
|
|
210
306
|
- **Quadratic phase correction**
|
|
211
307
|
- 2D array
|
|
212
|
-
* - ``/RawData/SLM/Data2D/CH02``
|
|
308
|
+
* - ``/RawData/Shaping/SLM/Data2D/CH02``
|
|
213
309
|
- **Linear phase correction**
|
|
214
310
|
- 2D array
|
|
215
|
-
* - ``/RawData/SLM/Data2D/CH03``
|
|
311
|
+
* - ``/RawData/Shaping/SLM/Data2D/CH03``
|
|
216
312
|
- **Zernike phase correction**
|
|
217
313
|
- 2D array
|
|
218
314
|
|
|
219
315
|
.. note::
|
|
220
|
-
- The **SLM phases** (``/RawData/SLM/Data2D/``) are **downsampled** to match the SLM resolution (e.g., 960x540 for PLUTO, 1024x768 for LC2012).
|
|
221
|
-
- The **
|
|
316
|
+
- The **SLM phases** (``/RawData/Shaping/SLM/Data2D/``) are **downsampled** to match the SLM resolution (e.g., 960x540 for PLUTO, 1024x768 for LC2012).
|
|
317
|
+
- The **Final/Data2D** results are at the **same resolution as the Input/Target fields** (e.g., 1024x1024).
|
|
318
|
+
- Files written before this layout (groups ``/RawData/Algorithm``, ``Input``, ``Target`` and ``SLM`` directly under ``/RawData``) are still loaded by the extension.
|
|
319
|
+
- Runs of the headless playground (``pg.run_algorithm``) use the same layout, in indexed groups ``/RawData/Shaping000``, ``Shaping001``... with in addition the ``Fields`` and ``Metrics`` groups holding the data saved at each iteration (see :ref:`sec-algorithms-playground`), the SLM group being left out.
|
|
222
320
|
- The ``@settings`` attributes contain **serialized XML configurations** (can be deserialized with ``pymodaq_utils``).
|
|
223
321
|
|
|
224
322
|
|
|
@@ -235,7 +333,7 @@ You can **read `.h5beam` and `.h5field` files programmatically** using `pymodaq_
|
|
|
235
333
|
# Load data from a .h5beam file
|
|
236
334
|
with DataLoader("my_file.h5beam") as loader:
|
|
237
335
|
# Access SLM phases
|
|
238
|
-
phase_data = loader.load_data("/RawData/SLM/Data2D/CH00") # return a DataWithAxes object
|
|
336
|
+
phase_data = loader.load_data("/RawData/Shaping/SLM/Data2D/CH00") # return a DataWithAxes object
|
|
239
337
|
|
|
240
338
|
# Access metadata
|
|
241
339
|
print(phase_data.extra_attributes)
|
|
@@ -333,30 +431,30 @@ HDF5 Attributes Reference
|
|
|
333
431
|
* - **Group**
|
|
334
432
|
- **Purpose**
|
|
335
433
|
- **Key Data**
|
|
336
|
-
* - ``/RawData/
|
|
434
|
+
* - ``/RawData/Shaping/Final/Data0D/CH00``
|
|
337
435
|
- Performance metrics
|
|
338
436
|
- NRMSE (``Data00``), Efficiency (``Data01``)
|
|
339
|
-
* - ``/RawData/
|
|
437
|
+
* - ``/RawData/Shaping/Final/Data2D/CH00``
|
|
340
438
|
- Output field amplitude
|
|
341
439
|
- 2D array (same size as Input/Target)
|
|
342
|
-
* - ``/RawData/
|
|
440
|
+
* - ``/RawData/Shaping/Final/Data2D/CH01``
|
|
343
441
|
- Output field phase
|
|
344
442
|
- 2D array (radians)
|
|
345
|
-
* - ``/RawData/
|
|
443
|
+
* - ``/RawData/Shaping/Final/Data2D/CH02``
|
|
346
444
|
- Modulator amplitude
|
|
347
445
|
- 2D array (sent to SLM)
|
|
348
|
-
* - ``/RawData/
|
|
446
|
+
* - ``/RawData/Shaping/Final/Data2D/CH03``
|
|
349
447
|
- Modulator phase
|
|
350
448
|
- 2D array (radians)
|
|
351
|
-
* - ``/RawData/SLM/Data2D/CH00``
|
|
449
|
+
* - ``/RawData/Shaping/SLM/Data2D/CH00``
|
|
352
450
|
- Algorithm phase for SLM
|
|
353
451
|
- 2D array (SLM resolution, e.g., 540x960)
|
|
354
|
-
* - ``/RawData/SLM/Data2D/CH01``
|
|
452
|
+
* - ``/RawData/Shaping/SLM/Data2D/CH01``
|
|
355
453
|
- Quadratic phase
|
|
356
454
|
- 2D array (curvature correction)
|
|
357
|
-
* - ``/RawData/SLM/Data2D/CH02``
|
|
455
|
+
* - ``/RawData/Shaping/SLM/Data2D/CH02``
|
|
358
456
|
- Linear phase
|
|
359
457
|
- 2D array (tilt correction)
|
|
360
|
-
* - ``/RawData/SLM/Data2D/CH03``
|
|
458
|
+
* - ``/RawData/Shaping/SLM/Data2D/CH03``
|
|
361
459
|
- Zernike phase
|
|
362
460
|
- 2D array (aberration correction)
|
|
@@ -11,6 +11,7 @@ config = Config() # before field loader factory otherwise it will generate an e
|
|
|
11
11
|
from .field import LoaderFactory, register_loaders
|
|
12
12
|
from .algorithms.factory import AlgorithmFactory, register_algorithms
|
|
13
13
|
from .algorithms.ini_phase import register_phases
|
|
14
|
+
from .algorithms.compensation import register_compensations, CompensationFactory
|
|
14
15
|
from .algorithms.stopping import register_stoppings
|
|
15
16
|
|
|
16
17
|
logger = set_logger(get_module_name(__file__))
|
|
@@ -26,6 +27,12 @@ logger.info('Registering Optical Shaping ini phases')
|
|
|
26
27
|
register_phases()
|
|
27
28
|
logger.info('****************************************')
|
|
28
29
|
|
|
30
|
+
logger.info('****************************************')
|
|
31
|
+
logger.info('Registering Optical Shaping compensations of the input beam')
|
|
32
|
+
register_compensations()
|
|
33
|
+
CompensationFactory.check_enum()
|
|
34
|
+
logger.info('****************************************')
|
|
35
|
+
|
|
29
36
|
|
|
30
37
|
logger.info('****************************************')
|
|
31
38
|
logger.info('Registering Optical Shaping stopping criteria')
|
|
@@ -16,6 +16,7 @@ from pymodaq_gui.managers.parameter_manager import ParameterManager
|
|
|
16
16
|
from pymodaq_plugins_beam_shaping.algorithms.utils import (AlgoType, AlgoStatus, ApplyMaskTo,
|
|
17
17
|
LensSetup, CrossTalk, PhaseManipulation)
|
|
18
18
|
from pymodaq_plugins_beam_shaping.field import Field
|
|
19
|
+
from pymodaq_plugins_beam_shaping.algorithms.compensation import CompensationBase, Compensations
|
|
19
20
|
from pymodaq_plugins_beam_shaping.utilities import sizing
|
|
20
21
|
from pymodaq_plugins_beam_shaping.utilities.masking import MaskType
|
|
21
22
|
|
|
@@ -52,6 +53,8 @@ class AlgoBase(AlgoParameterManager, metaclass=ABCMeta):
|
|
|
52
53
|
# the modulators the algorithm can compute a mask for (a shaper modulating both accepts any algorithm)
|
|
53
54
|
MODULATOR_TYPES: tuple[ModulatorType] = (ModulatorType.PHASE, )
|
|
54
55
|
INI_PHASE = True # if True, the algorithm will init an initial phase
|
|
56
|
+
INPUT_COMPENSATION: Optional[Compensations] = None # name of the compensation of the input beam the algorithm starts
|
|
57
|
+
# with (the app lets the user change it), None if the algorithm does not use one
|
|
55
58
|
ITERATIVE = False
|
|
56
59
|
MANUAL_LOOP = True
|
|
57
60
|
RECOMPUTE_ON_CHANGE = False # if True, the algorithm is run again when one of its settings changes
|
|
@@ -77,9 +80,15 @@ class AlgoBase(AlgoParameterManager, metaclass=ABCMeta):
|
|
|
77
80
|
self._target_field = Field(amplitude=np.zeros(sizing.get_effective_needed_field_size(self.shaper)))
|
|
78
81
|
self._input_field = Field(amplitude=np.zeros(sizing.get_effective_needed_field_size(self.shaper)))
|
|
79
82
|
self.intermediate_field: Optional[Field] = None
|
|
83
|
+
self._unreachable_mask: Optional[np.ndarray] = None # where the target cannot be reached, see subclasses
|
|
80
84
|
|
|
81
85
|
self._modulator_field = Field(amplitude=np.zeros(sizing.get_effective_needed_field_size(self.shaper)))
|
|
82
86
|
self._modulator_field.calibrate_axes(self._input_field.pixels_sizes)
|
|
87
|
+
# what has to be sent to the modulator: its phase (without any correction, added when sending) and its
|
|
88
|
+
# amplitude pattern (0 and 1 for a DMD). Not the modulator field, which contains the input beam
|
|
89
|
+
self._slm_field = Field('slm', amplitude=np.ones(self._modulator_field.shape),
|
|
90
|
+
phase=np.zeros(self._modulator_field.shape),
|
|
91
|
+
pixel_sizes=self._input_field.pixels_sizes)
|
|
83
92
|
self._output_field = Field(amplitude=np.zeros(sizing.get_effective_needed_field_size(self.shaper)))
|
|
84
93
|
|
|
85
94
|
self.update_mask = True
|
|
@@ -229,7 +238,89 @@ class AlgoBase(AlgoParameterManager, metaclass=ABCMeta):
|
|
|
229
238
|
self.set_amplitude_in_modulator_plane(field.amplitude)
|
|
230
239
|
|
|
231
240
|
def set_amplitude_in_modulator_plane(self, amplitude: np.ndarray):
|
|
232
|
-
|
|
241
|
+
""" Set the amplitude pattern of an amplitude modulator (0 and 1 for a DMD)
|
|
242
|
+
|
|
243
|
+
The pattern is what is sent to the modulator (see :attr:`slm_amplitude`) whereas the amplitude of the modulator
|
|
244
|
+
field, the field just after the modulator used to compute the output, is the input amplitude times the pattern
|
|
245
|
+
"""
|
|
246
|
+
pattern = np.array(amplitude, dtype=float)
|
|
247
|
+
self._slm_field = Field('slm', amplitude=pattern,
|
|
248
|
+
phase=self._slm_phase_or_zeros(pattern.shape),
|
|
249
|
+
pixel_sizes=self._input_field.pixels_sizes)
|
|
250
|
+
self._modulator_field.amplitude = self._input_field.amplitude * pattern
|
|
251
|
+
|
|
252
|
+
def _slm_phase_or_zeros(self, shape) -> np.ndarray:
|
|
253
|
+
return self._slm_field.phase.copy() if self._slm_field.phase.shape == tuple(shape) else np.zeros(shape)
|
|
254
|
+
|
|
255
|
+
@property
|
|
256
|
+
def slm_field(self) -> Field:
|
|
257
|
+
""" The field to send to the modulator: the phase set by :meth:`set_phase_in_modulator_plane` (wrapped,
|
|
258
|
+
with crosstalk... but without any correction, added when sending) and the amplitude pattern set by
|
|
259
|
+
:meth:`set_amplitude_in_modulator_plane`, 1 everywhere if there is none. It is not the modulator field, the
|
|
260
|
+
field just after the modulator, which is the input field times the SLM field and is used to compute the
|
|
261
|
+
output"""
|
|
262
|
+
modulator_type = ModulatorType(self.shaper.modulator_type)
|
|
263
|
+
if modulator_type == ModulatorType.BOTH:
|
|
264
|
+
return self._slm_field
|
|
265
|
+
field = self._slm_field.deepcopy()
|
|
266
|
+
if modulator_type == ModulatorType.PHASE: # nothing is shaped in amplitude
|
|
267
|
+
field.amplitude = np.ones(field.shape)
|
|
268
|
+
else: # an amplitude modulator has no phase
|
|
269
|
+
field.phase = np.zeros(field.shape)
|
|
270
|
+
return field
|
|
271
|
+
|
|
272
|
+
@property
|
|
273
|
+
def slm_amplitude(self) -> np.ndarray:
|
|
274
|
+
""" The amplitude pattern to send to an amplitude modulator, without the input beam"""
|
|
275
|
+
return self.slm_field.amplitude
|
|
276
|
+
|
|
277
|
+
@property
|
|
278
|
+
def unreachable_mask(self) -> Optional[np.ndarray]:
|
|
279
|
+
""" Boolean array of the pixels where the target cannot be obtained (None: not computed)"""
|
|
280
|
+
return self._unreachable_mask
|
|
281
|
+
|
|
282
|
+
@property
|
|
283
|
+
def unreachable_fraction(self) -> float:
|
|
284
|
+
""" Fraction of the pixels asked by the target that cannot be obtained, see :attr:`unreachable_mask`"""
|
|
285
|
+
if self._unreachable_mask is None:
|
|
286
|
+
return 0.
|
|
287
|
+
asked = self._target_field.amplitude > 0
|
|
288
|
+
return float(np.sum(self._unreachable_mask & asked) / max(np.sum(asked), 1))
|
|
289
|
+
|
|
290
|
+
@property
|
|
291
|
+
def compensation(self) -> Optional[CompensationBase]:
|
|
292
|
+
""" The compensation of the input beam chosen in the app, None if this algorithm does not use one"""
|
|
293
|
+
if self.INPUT_COMPENSATION is None:
|
|
294
|
+
return None
|
|
295
|
+
compensation = getattr(self.parent_app, 'compensation', None)
|
|
296
|
+
if compensation is None: # not chosen in an app: the default one of the algorithm
|
|
297
|
+
from pymodaq_plugins_beam_shaping.utilities.headless_algorithms import make_compensation
|
|
298
|
+
compensation = make_compensation(self.INPUT_COMPENSATION)
|
|
299
|
+
return compensation
|
|
300
|
+
|
|
301
|
+
@property
|
|
302
|
+
def input_block(self) -> int:
|
|
303
|
+
""" Size of the blocks of modulator pixels that see the same input amplitude (a superpixel), 1 if none"""
|
|
304
|
+
return 1
|
|
305
|
+
|
|
306
|
+
def compensate_target(self, target: np.ndarray) -> np.ndarray:
|
|
307
|
+
""" The amplitude to ask to the modulator to get the target, after the compensation of the input beam, and
|
|
308
|
+
the unreachable region it gives (:attr:`unreachable_mask`). The target itself if there is no compensation"""
|
|
309
|
+
compensation = self.compensation
|
|
310
|
+
if compensation is None:
|
|
311
|
+
self._unreachable_mask = None
|
|
312
|
+
return target
|
|
313
|
+
compensated, self._unreachable_mask = compensation.compensate(target, self._input_field.amplitude,
|
|
314
|
+
self.input_block)
|
|
315
|
+
return compensated
|
|
316
|
+
|
|
317
|
+
def preview_unreachable(self) -> Optional[np.ndarray]:
|
|
318
|
+
""" The unreachable region the next run will have, knowing the input beam and the compensation only (None:
|
|
319
|
+
no region)"""
|
|
320
|
+
compensation = self.compensation
|
|
321
|
+
if compensation is None or self._input_field is None or self._input_field.amplitude is None:
|
|
322
|
+
return None
|
|
323
|
+
return compensation.unreachable(self._input_field.amplitude, self.input_block)
|
|
233
324
|
|
|
234
325
|
def set_phase_in_modulator_plane(self, phase: np.ndarray, induced_amplitude: np.ndarray = None):
|
|
235
326
|
if phase.shape == self._modulator_field.shape:
|
|
@@ -243,6 +334,9 @@ class AlgoBase(AlgoParameterManager, metaclass=ABCMeta):
|
|
|
243
334
|
phase = gaussian_filter(phase, self.crosstalk.value)
|
|
244
335
|
|
|
245
336
|
self._modulator_field.phase = phase
|
|
337
|
+
self._slm_field = Field('slm', amplitude=self._slm_field.amplitude if
|
|
338
|
+
self._slm_field.amplitude.shape == phase.shape else np.ones(phase.shape),
|
|
339
|
+
phase=phase, pixel_sizes=self._input_field.pixels_sizes)
|
|
246
340
|
self._modulator_field.amplitude = (
|
|
247
341
|
self._input_field.amplitude.copy() *
|
|
248
342
|
(induced_amplitude if induced_amplitude is not None else 1))
|
|
@@ -305,12 +399,19 @@ class AlgoBase(AlgoParameterManager, metaclass=ABCMeta):
|
|
|
305
399
|
(self._target_field.phase[tuple(slices)]**2 - self._output_field.phase[tuple(slices)]**2) ** 2) /
|
|
306
400
|
np.sum(self._target_field.phase[tuple(slices)] ** 4)))
|
|
307
401
|
|
|
402
|
+
@property
|
|
403
|
+
def input_power(self) -> float:
|
|
404
|
+
""" The power incident on the modulator, the reference of the efficiency: the sum of the intensity of the input
|
|
405
|
+
field. To be subclassed if the algorithm models another illumination"""
|
|
406
|
+
return float(np.sum(self._input_field.intensity))
|
|
407
|
+
|
|
308
408
|
@property
|
|
309
409
|
def efficiency(self) -> float:
|
|
310
|
-
""" Compute efficiency as the ratio between output_field intensity within a given region
|
|
311
|
-
and
|
|
410
|
+
""" Compute the efficiency as the ratio between the output_field intensity within a given region (the target
|
|
411
|
+
mask if applied, else the whole field) and the power incident on the modulator, see :attr:`input_power`
|
|
312
412
|
|
|
313
|
-
|
|
413
|
+
The losses of the setup are therefore counted: the ones of the modulator (the mirrors of a DMD that are off) and
|
|
414
|
+
the ones of the filter in the intermediate plane of a 4f setup, which the output field already went through.
|
|
314
415
|
|
|
315
416
|
To be subclassed if the given implementation below is not correct for your algorithm"""
|
|
316
417
|
if self.apply_mask(ApplyMaskTo.TARGET):
|
|
@@ -318,8 +419,7 @@ class AlgoBase(AlgoParameterManager, metaclass=ABCMeta):
|
|
|
318
419
|
else:
|
|
319
420
|
slices = (...,)
|
|
320
421
|
|
|
321
|
-
return (np.sum(self._output_field.intensity[tuple(slices)]) /
|
|
322
|
-
np.sum(self._output_field.intensity))
|
|
422
|
+
return float(np.sum(self._output_field.intensity[tuple(slices)]) / self.input_power)
|
|
323
423
|
|
|
324
424
|
def fitness_as_dwa(self):
|
|
325
425
|
return DataRaw('fitness', data=[np.array([self.fitness])],
|
|
@@ -358,6 +458,12 @@ class AlgoBase(AlgoParameterManager, metaclass=ABCMeta):
|
|
|
358
458
|
self.modulator_field.amplitude_as_dwa('modulator'),
|
|
359
459
|
self.modulator_field.phase_as_dwa('modulator'),
|
|
360
460
|
])
|
|
461
|
+
dte.append(self.slm_field.phase_as_dwa('slm')) # what is sent to the modulator, whatever its type
|
|
462
|
+
if self.shaper.modulator_type != ModulatorType.PHASE: # an amplitude is sent to the modulator
|
|
463
|
+
dte.append(self.slm_field.amplitude_as_dwa('slm'))
|
|
464
|
+
if self._unreachable_mask is not None:
|
|
465
|
+
dte.append(Field('unreachable', amplitude=self._unreachable_mask.astype(float),
|
|
466
|
+
pixel_sizes=self._modulator_field.pixels_sizes).amplitude_as_dwa('unreachable'))
|
|
361
467
|
if self.intermediate_field is not None:
|
|
362
468
|
dte.append(self.intermediate_field.intensity_as_dwa('intermediate'))
|
|
363
469
|
return dte
|