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.
Files changed (206) hide show
  1. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/AGENTS.md +5 -1
  2. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/AGENTS_BEAM_SHAPING.md +1 -0
  3. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/PKG-INFO +1 -1
  4. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/scripts/binary_holograms_snapshots.py +4 -1
  5. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/algorithm_reference.rst +43 -1
  6. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/algorithms.rst +53 -5
  7. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/corrections.rst +3 -1
  8. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/data_management.rst +121 -23
  9. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/__init__.py +7 -0
  10. {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
  11. {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
  12. {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
  13. {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
  14. pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/algorithms/compensation.py +133 -0
  15. pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/algorithms/compensations/divide_by_input.py +40 -0
  16. pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/algorithms/compensations/no_compensation.py +11 -0
  17. pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/algorithms/ini_phases/random_phase.py +23 -0
  18. {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
  19. {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
  20. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/field/h5.py +22 -5
  21. {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
  22. pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/scripts/plot_convergence.py +49 -0
  23. pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/utilities/__init__.py +0 -0
  24. pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/utilities/h5saving.py +439 -0
  25. {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
  26. pymodaq_plugins_beam_shaping-5.3.2/src/pymodaq_plugins_beam_shaping/utilities/region_outline.py +59 -0
  27. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/utilities/regions.py +18 -0
  28. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/conftest.py +28 -0
  29. pymodaq_plugins_beam_shaping-5.3.2/tests/test_algo_app_settings.py +107 -0
  30. pymodaq_plugins_beam_shaping-5.3.2/tests/test_algo_helpers.py +261 -0
  31. pymodaq_plugins_beam_shaping-5.3.2/tests/test_algorithm_playground.py +486 -0
  32. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/test_algorithm_status.py +4 -5
  33. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/test_binary_holograms.py +2 -0
  34. pymodaq_plugins_beam_shaping-5.3.2/tests/test_compensation.py +107 -0
  35. pymodaq_plugins_beam_shaping-5.3.2/tests/test_custom_apps.py +332 -0
  36. pymodaq_plugins_beam_shaping-5.3.2/tests/test_region_outline.py +270 -0
  37. pymodaq_plugins_beam_shaping-5.3.2/tests/test_saved_version.py +69 -0
  38. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/test_shaper_interface.py +109 -0
  39. pymodaq_plugins_beam_shaping-5.3.1/src/pymodaq_plugins_beam_shaping/algorithms/ini_phases/random_phase.py +0 -10
  40. pymodaq_plugins_beam_shaping-5.3.1/src/pymodaq_plugins_beam_shaping/utilities/h5saving.py +0 -79
  41. pymodaq_plugins_beam_shaping-5.3.1/tests/test_algo_helpers.py +0 -61
  42. pymodaq_plugins_beam_shaping-5.3.1/tests/test_algorithm_playground.py +0 -223
  43. pymodaq_plugins_beam_shaping-5.3.1/tests/test_custom_apps.py +0 -161
  44. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/.gitattributes +0 -0
  45. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/.github/workflows/compatibility.yml +0 -0
  46. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/.github/workflows/python-publish.yml +0 -0
  47. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/.github/workflows/tests.yml +0 -0
  48. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/.gitignore +0 -0
  49. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/CLAUDE.md +0 -0
  50. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/LICENSE +0 -0
  51. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/MANIFEST.in +0 -0
  52. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/README.rst +0 -0
  53. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/Makefile +0 -0
  54. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/make.bat +0 -0
  55. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/requirements.txt +0 -0
  56. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/scripts/data_browse.py +0 -0
  57. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_images/binary_holograms.png +0 -0
  58. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_images/calibration.png +0 -0
  59. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_images/corrections.png +0 -0
  60. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_images/field_loader.png +0 -0
  61. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_images/field_tool.png +0 -0
  62. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_images/layout.png +0 -0
  63. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_images/main_app.png +0 -0
  64. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_images/measurement_amplitude.png +0 -0
  65. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_images/schema.png +0 -0
  66. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_images/setup_field_loader.png +0 -0
  67. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/css/layout.css +0 -0
  68. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/css/overflow.css +0 -0
  69. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/icons/add_circle.png +0 -0
  70. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/icons/deblur.png +0 -0
  71. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/icons/equalizer.png +0 -0
  72. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/icons/file_open.png +0 -0
  73. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/icons/grid_off.png +0 -0
  74. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/icons/grid_on.png +0 -0
  75. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/icons/ink_eraser.png +0 -0
  76. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/icons/ink_eraser_off.png +0 -0
  77. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/icons/input.png +0 -0
  78. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/icons/save.png +0 -0
  79. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/icons/target.png +0 -0
  80. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/js/sidebar_toggle.js +0 -0
  81. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_static/logo.png +0 -0
  82. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_templates/apidoc/module.rst_t +0 -0
  83. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_templates/apidoc/package.rst_t +0 -0
  84. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/_templates/apidoc/toc.rst_t +0 -0
  85. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/acknowledgments.rst +0 -0
  86. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/bibtex.bib +0 -0
  87. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/conf.py +0 -0
  88. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/index.rst +0 -0
  89. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/installation.rst +0 -0
  90. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/introduction.rst +0 -0
  91. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/quick_start.rst +0 -0
  92. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/redirects.txt +0 -0
  93. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/references.rst +0 -0
  94. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/theory.rst +0 -0
  95. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/troubleshooting.rst +0 -0
  96. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/tutorials.rst +0 -0
  97. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/calibration.rst +0 -0
  98. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/custom_algorithm.rst +0 -0
  99. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/field_tool.rst +0 -0
  100. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/fields.rst +0 -0
  101. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/index.rst +0 -0
  102. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/interface.rst +0 -0
  103. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/shapers.rst +0 -0
  104. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/docs/src/user_guide/slmsuite.rst +0 -0
  105. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/hatch_build.py +0 -0
  106. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/icon.ico +0 -0
  107. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/pyproject.toml +0 -0
  108. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/readthedocs.yml +0 -0
  109. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/__init__.py +0 -0
  110. {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
  111. {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
  112. {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
  113. {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
  114. {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
  115. {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
  116. {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
  117. {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
  118. {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
  119. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/factory.py +0 -0
  120. {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
  121. {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
  122. {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
  123. {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
  124. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/loss.py +0 -0
  125. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/stopping.py +0 -0
  126. {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
  127. {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
  128. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/algorithms/utils.py +0 -0
  129. {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
  130. {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
  131. {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
  132. {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
  133. {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
  134. {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
  135. {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
  136. {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
  137. {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
  138. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/extensions/__init__.py +0 -0
  139. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/field/__init__.py +0 -0
  140. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/field/factory.py +0 -0
  141. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/field/field.py +0 -0
  142. {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
  143. {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
  144. {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
  145. {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
  146. {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
  147. {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
  148. {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
  149. {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
  150. {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
  151. {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
  152. {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
  153. {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
  154. {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
  155. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/field/utils.py +0 -0
  156. {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
  157. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/hardware/autofocus.py +0 -0
  158. {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
  159. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/models/OptimizerModelAutoFocus.py +0 -0
  160. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/models/__init__.py +0 -0
  161. {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
  162. {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
  163. {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
  164. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/resources/Pymodaq.png +0 -0
  165. {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
  166. {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
  167. {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
  168. {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
  169. {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
  170. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/resources/dollars.png +0 -0
  171. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/resources/dollars.svg +0 -0
  172. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/resources/face.png +0 -0
  173. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/resources/holography.xml +0 -0
  174. {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
  175. {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
  176. {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
  177. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/resources/osama.png +0 -0
  178. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/resources/zernike.png +0 -0
  179. {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
  180. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/scanners/calibration.py +0 -0
  181. {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
  182. {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
  183. {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
  184. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/setup/factory.py +0 -0
  185. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/setup/setup.py +0 -0
  186. {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
  187. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/utilities/calibrating.py +0 -0
  188. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/utilities/corrections.py +0 -0
  189. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/utilities/data.py +0 -0
  190. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/utilities/masking.py +0 -0
  191. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/utilities/shaper.py +0 -0
  192. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/utilities/sizing.py +0 -0
  193. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/utilities/zernike.py +0 -0
  194. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/src/pymodaq_plugins_beam_shaping/utils.py +0 -0
  195. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/algorithm_entry_points_test.py +0 -0
  196. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/element_test.py +0 -0
  197. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/field_test.py +0 -0
  198. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/pytensor_fft.py +0 -0
  199. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/pytorch_fft.py +0 -0
  200. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/pytorch_test_v1.ipynb +0 -0
  201. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/test_algorithms_by_modulator_type.py +0 -0
  202. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/test_calibration.py +0 -0
  203. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/test_field_tool.py +0 -0
  204. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/test_plugin_package_structure.py +0 -0
  205. {pymodaq_plugins_beam_shaping-5.3.1 → pymodaq_plugins_beam_shaping-5.3.2}/tests/test_regions.py +0 -0
  206. {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.
@@ -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.1
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
- mask = ((y - MASK_HALF_SIZE, y + MASK_HALF_SIZE), (x - MASK_HALF_SIZE, x + MASK_HALF_SIZE))
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/Phase Checkerboard
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/Phase Checkerboard
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/Algorithm/``. See :ref:`h5beam-structure` for details.
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 dots for parameters in a group
287
- (``'phase.load'``). An unknown name raises an error listing the possible ones. ``N_ITERATIONS`` completes the run, and
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 around the center of the field (``None``: the default region
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/Algorithm/Data0D/CH00``
287
+ * - ``/RawData/Shaping/Final/Data0D/CH00``
192
288
  - **Performance metrics**
193
289
  - NRMSE (``Data00``), Efficiency (``Data01``)
194
- * - ``/RawData/Algorithm/Data2D/CH00``
290
+ * - ``/RawData/Shaping/Final/Data2D/CH00``
195
291
  - **Output field amplitude**
196
292
  - 2D array (same size as Input/Target)
197
- * - ``/RawData/Algorithm/Data2D/CH01``
293
+ * - ``/RawData/Shaping/Final/Data2D/CH01``
198
294
  - **Output field phase**
199
295
  - 2D array (radians)
200
- * - ``/RawData/Algorithm/Data2D/CH02``
296
+ * - ``/RawData/Shaping/Final/Data2D/CH02``
201
297
  - **Modulator amplitude**
202
298
  - 2D array (sent to SLM)
203
- * - ``/RawData/Algorithm/Data2D/CH03``
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 **Algorithm/Data2D** results are at the **same resolution as the Input/Target fields** (e.g., 1024x1024).
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/Algorithm/Data0D/CH00``
434
+ * - ``/RawData/Shaping/Final/Data0D/CH00``
337
435
  - Performance metrics
338
436
  - NRMSE (``Data00``), Efficiency (``Data01``)
339
- * - ``/RawData/Algorithm/Data2D/CH00``
437
+ * - ``/RawData/Shaping/Final/Data2D/CH00``
340
438
  - Output field amplitude
341
439
  - 2D array (same size as Input/Target)
342
- * - ``/RawData/Algorithm/Data2D/CH01``
440
+ * - ``/RawData/Shaping/Final/Data2D/CH01``
343
441
  - Output field phase
344
442
  - 2D array (radians)
345
- * - ``/RawData/Algorithm/Data2D/CH02``
443
+ * - ``/RawData/Shaping/Final/Data2D/CH02``
346
444
  - Modulator amplitude
347
445
  - 2D array (sent to SLM)
348
- * - ``/RawData/Algorithm/Data2D/CH03``
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
- self._modulator_field.amplitude = amplitude
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 total intensity
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
- Meaningfully only for algorithm using a Target defined mask
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