opticalib 2.0.0__tar.gz → 2.2.0__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.
- opticalib-2.2.0/CITATION.bib +10 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/MANIFEST.in +6 -4
- {opticalib-2.0.0/opticalib.egg-info → opticalib-2.2.0}/PKG-INFO +45 -23
- {opticalib-2.0.0 → opticalib-2.2.0}/README.md +12 -1
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/__init__.py +12 -16
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/__version__.py +1 -1
- opticalib-2.2.0/opticalib/analyzer/__init__.py +13 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/analyzer/image_processing.py +49 -20
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/analyzer/signals.py +9 -10
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/analyzer/timeseries.py +10 -28
- opticalib-2.2.0/opticalib/core/__init__.py +17 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/core/_configurations/configuration.yaml +4 -1
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/core/_types.py +85 -16
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/core/config.py +99 -22
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/core/data_classes.py +20 -5
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/core/exceptions.py +9 -1
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/core/root.py +32 -42
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/devices/_API/alpaoAPI.py +185 -64
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/devices/_API/base_devices.py +24 -11
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/devices/_API/i4dAPI.py +5 -2
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/devices/_API/piAPI.py +41 -17
- opticalib-2.2.0/opticalib/devices/__init__.py +33 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/devices/cameras.py +8 -13
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/devices/deformable_mirrors.py +151 -128
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/devices/interferometer.py +63 -37
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/devices/wfs.py +7 -19
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/dmutils/__actuator_identification_wip.py +4 -4
- opticalib-2.2.0/opticalib/dmutils/__init__.py +33 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/dmutils/__pupil_calibration_wip.py +1 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/dmutils/flattening.py +63 -66
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/dmutils/iff_preparation.py +30 -54
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/dmutils/iff_processing.py +71 -60
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/dmutils/slaving.py +18 -11
- opticalib-2.2.0/opticalib/ground/__init__.py +13 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/ground/_stitching_algorithm.py +16 -16
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/ground/geometry.py +18 -13
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/ground/logger.py +17 -28
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/ground/modal_decomposer.py +24 -45
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/ground/osutils.py +19 -13
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/ground/reconstructor.py +64 -10
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/ground/roi.py +40 -20
- opticalib-2.2.0/opticalib/gui/__init__.py +56 -0
- opticalib-2.2.0/opticalib/gui/activity.py +1069 -0
- opticalib-2.2.0/opticalib/gui/app.py +1377 -0
- opticalib-2.2.0/opticalib/gui/kernel.py +1177 -0
- opticalib-2.2.0/opticalib/gui/kernel_backend.py +63 -0
- opticalib-2.2.0/opticalib/gui/kernel_side.py +510 -0
- opticalib-2.2.0/opticalib/gui/plugins.py +130 -0
- opticalib-2.2.0/opticalib/gui/procedures/__init__.py +14 -0
- opticalib-2.2.0/opticalib/gui/procedures/alignment.py +129 -0
- opticalib-2.2.0/opticalib/gui/procedures/base.py +732 -0
- opticalib-2.2.0/opticalib/gui/procedures/dm_calibration.py +381 -0
- opticalib-2.2.0/opticalib/gui/procedures/params.py +684 -0
- opticalib-2.2.0/opticalib/gui/procedures/phasing.py +190 -0
- opticalib-2.2.0/opticalib/gui/procedures/stitching.py +116 -0
- opticalib-2.2.0/opticalib/gui/procedures/timeseries.py +123 -0
- opticalib-2.2.0/opticalib/gui/resources/opticalib.ico +0 -0
- opticalib-2.2.0/opticalib/gui/resources/opticalib.png +0 -0
- opticalib-2.2.0/opticalib/gui/resources/opticalib.svg +25 -0
- opticalib-2.2.0/opticalib/gui/theme.py +598 -0
- opticalib-2.2.0/opticalib/gui/widgets/__init__.py +9 -0
- opticalib-2.2.0/opticalib/gui/widgets/common.py +144 -0
- opticalib-2.2.0/opticalib/gui/widgets/config_editor.py +556 -0
- opticalib-2.2.0/opticalib/gui/widgets/connect_dialog.py +262 -0
- opticalib-2.2.0/opticalib/gui/widgets/data_browser.py +314 -0
- opticalib-2.2.0/opticalib/gui/widgets/device_panel.py +857 -0
- opticalib-2.2.0/opticalib/gui/widgets/device_registry.py +735 -0
- opticalib-2.2.0/opticalib/gui/widgets/plot_viewer.py +839 -0
- opticalib-2.2.0/opticalib/gui/widgets/workspace.py +218 -0
- opticalib-2.2.0/opticalib/procedures/__init__.py +21 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/procedures/alignment.py +24 -101
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/procedures/iff.py +41 -27
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/procedures/phasing.py +10 -5
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/procedures/stitching.py +20 -16
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/simulator/_API/__init__.py +2 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/simulator/_API/base_fake_adopticadm.py +74 -79
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/simulator/_API/base_fake_alpao.py +28 -85
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/simulator/_API/base_petalmirror.py +14 -54
- opticalib-2.2.0/opticalib/simulator/_API/base_simulated_dm.py +378 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/simulator/__init__.py +2 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/simulator/factory.py +3 -3
- opticalib-2.2.0/opticalib/simulator/fake_dms.py +278 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/simulator/fake_interf.py +5 -5
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/visualization.py +108 -7
- {opticalib-2.0.0 → opticalib-2.2.0/opticalib.egg-info}/PKG-INFO +45 -23
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib.egg-info/SOURCES.txt +39 -4
- opticalib-2.2.0/opticalib.egg-info/entry_points.txt +5 -0
- opticalib-2.2.0/opticalib.egg-info/requires.txt +43 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib.egg-info/top_level.txt +0 -1
- opticalib-2.2.0/pyproject.toml +103 -0
- opticalib-2.2.0/setup.cfg +4 -0
- opticalib-2.2.0/setup_calpy.py +724 -0
- opticalib-2.2.0/tests/README.md +110 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/conftest.py +53 -3
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_analyzer_images_processing.py +24 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_core_read_config.py +78 -1
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_core_root.py +2 -2
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_devices_deformable_mirrors.py +1 -1
- opticalib-2.2.0/tests/test_devices_interferometer.py +93 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_dmutils_flattening.py +2 -2
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_dmutils_iff_acquisition_preparation.py +6 -6
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_dmutils_iff_module.py +2 -2
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_dmutils_iff_processing.py +51 -7
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_ground_roi.py +166 -0
- opticalib-2.2.0/tests/test_gui_activity.py +134 -0
- opticalib-2.2.0/tests/test_gui_app.py +217 -0
- opticalib-2.2.0/tests/test_gui_config_editor.py +232 -0
- opticalib-2.2.0/tests/test_gui_devices.py +448 -0
- opticalib-2.2.0/tests/test_gui_kernel_bridge.py +310 -0
- opticalib-2.2.0/tests/test_gui_kernel_side.py +303 -0
- opticalib-2.2.0/tests/test_gui_procedures.py +470 -0
- opticalib-2.2.0/tests/test_gui_widgets.py +399 -0
- opticalib-2.2.0/tests/test_setup_calpy.py +230 -0
- opticalib-2.0.0/opticalib/analyzer/__init__.py +0 -3
- opticalib-2.0.0/opticalib/core/__init__.py +0 -21
- opticalib-2.0.0/opticalib/devices/__init__.py +0 -45
- opticalib-2.0.0/opticalib/dmutils/__init__.py +0 -44
- opticalib-2.0.0/opticalib/ground/__init__.py +0 -30
- opticalib-2.0.0/opticalib/gui/__init__.py +0 -22
- opticalib-2.0.0/opticalib/gui/app.py +0 -1534
- opticalib-2.0.0/opticalib/procedures/__init__.py +0 -27
- opticalib-2.0.0/opticalib/simulator/_API/_rbf_gpu.py +0 -367
- opticalib-2.0.0/opticalib/simulator/fake_dms.py +0 -867
- opticalib-2.0.0/opticalib.egg-info/entry_points.txt +0 -2
- opticalib-2.0.0/opticalib.egg-info/requires.txt +0 -18
- opticalib-2.0.0/requirements.txt +0 -18
- opticalib-2.0.0/setup.cfg +0 -28
- opticalib-2.0.0/setup.py +0 -48
- opticalib-2.0.0/setup_calpy.py +0 -276
- opticalib-2.0.0/tests/test_setup_calpy.py +0 -54
- {opticalib-2.0.0 → opticalib-2.2.0}/LICENSE +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/__init_script__/initCalpy.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/core/decorators.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/core/fitsarray.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/devices/_API/__init__.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/devices/_API/micAPI.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/devices/_API/splattAPI.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/dmutils/_misc.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/procedures/measurements.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/py.typed +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/simulator/_API/alpao_conf.yaml +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib/simulator/_API/simdata.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/opticalib.egg-info/dependency_links.txt +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/__init__.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_analyzer_signals.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_analyzer_timeseries.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_core_dataclass.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_core_exceptions.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_core_fits.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_dmutils_slaving.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_ground_computerec.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_ground_geometry.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_ground_logger.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_ground_modal_decomposer.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_ground_osutils.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_measurements.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_simulator_factory_functions.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_simulator_simdata.py +0 -0
- {opticalib-2.0.0 → opticalib-2.2.0}/tests/test_typings.py +0 -0
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
@misc{opticalib,
|
|
2
|
+
doi = {10.20371/INAF/SW/2026_00013},
|
|
3
|
+
url = {https://openscience.inaf.it/?page_id=696},
|
|
4
|
+
author = {{Pietro Ferraiuolo} and {Marco Xompero} and {Runa Briguglio} and {Matteo Menessini}},
|
|
5
|
+
language = {en},
|
|
6
|
+
title = {OPTICALIB: A Python Framework for Adaptive Optics Experimentation},
|
|
7
|
+
publisher = {O.A. Arcetri},
|
|
8
|
+
year = {2025},
|
|
9
|
+
copyright = {MIT License}
|
|
10
|
+
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
include README.md
|
|
2
|
-
include
|
|
2
|
+
include LICENSE
|
|
3
|
+
include CITATION.bib
|
|
3
4
|
include opticalib/core/_configurations/configuration.yaml
|
|
4
|
-
include setup_calpy.py
|
|
5
|
-
include opticalib/__init_script__/initCalpy.py
|
|
6
5
|
include opticalib/simulator/_API/alpao_conf.yaml
|
|
7
|
-
|
|
6
|
+
include opticalib/__init_script__/initCalpy.py
|
|
7
|
+
recursive-include opticalib/gui/resources *.svg *.png *.ico
|
|
8
|
+
graft tests
|
|
9
|
+
global-exclude __pycache__ *.py[cod]
|
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opticalib
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: This package is a python interface for laboratory adaptive optics systems, with a focus on the calibration of deformable mirrors (DMs) and the acquisition of wavefront data using wavefront sensors.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
Author-email: Adaptive Optics Group - INAF - Osservatorio Astrofisico di Arcetri <pietro.ferraiuolo@inaf.it>
|
|
6
|
+
Maintainer-email: Pietro Ferraiuolo <pietro.ferraiuolo@inaf.it>
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/ArcetriAdaptiveOptics/opticalib
|
|
9
|
+
Project-URL: Repository, https://github.com/ArcetriAdaptiveOptics/opticalib
|
|
10
|
+
Project-URL: Issues, https://github.com/ArcetriAdaptiveOptics/opticalib/issues
|
|
10
11
|
Classifier: Programming Language :: Python :: 3
|
|
11
|
-
Classifier:
|
|
12
|
-
Classifier: Operating System ::
|
|
12
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
13
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
14
|
+
Classifier: Operating System :: MacOS
|
|
13
15
|
Requires-Python: >=3.10
|
|
14
16
|
Description-Content-Type: text/markdown
|
|
15
17
|
License-File: LICENSE
|
|
@@ -22,31 +24,43 @@ Requires-Dist: pipython
|
|
|
22
24
|
Requires-Dist: photutils
|
|
23
25
|
Requires-Dist: scipy
|
|
24
26
|
Requires-Dist: ruamel.yaml
|
|
27
|
+
Requires-Dist: PyYAML
|
|
25
28
|
Requires-Dist: Pyro4
|
|
26
29
|
Requires-Dist: h5py
|
|
27
30
|
Requires-Dist: jdcal
|
|
28
31
|
Requires-Dist: tqdm
|
|
29
32
|
Requires-Dist: matplotlib
|
|
30
|
-
Requires-Dist: xupy
|
|
31
33
|
Requires-Dist: numpy
|
|
32
|
-
Requires-Dist:
|
|
33
|
-
Requires-Dist:
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
34
|
+
Requires-Dist: rbfgpu
|
|
35
|
+
Requires-Dist: xupy>=2.0
|
|
36
|
+
Requires-Dist: ipython
|
|
37
|
+
Provides-Extra: gui
|
|
38
|
+
Requires-Dist: PySide6-Essentials; extra == "gui"
|
|
39
|
+
Requires-Dist: QtPy; extra == "gui"
|
|
40
|
+
Requires-Dist: qtconsole; extra == "gui"
|
|
41
|
+
Requires-Dist: ipykernel; extra == "gui"
|
|
42
|
+
Requires-Dist: jupyter_client; extra == "gui"
|
|
43
|
+
Requires-Dist: pyqtgraph; extra == "gui"
|
|
44
|
+
Requires-Dist: qtawesome; extra == "gui"
|
|
45
|
+
Requires-Dist: psutil; extra == "gui"
|
|
46
|
+
Provides-Extra: cuda12
|
|
47
|
+
Requires-Dist: xupy[cuda12]>=2.0; extra == "cuda12"
|
|
48
|
+
Provides-Extra: cuda13
|
|
49
|
+
Requires-Dist: xupy[cuda13]>=2.0; extra == "cuda13"
|
|
50
|
+
Provides-Extra: test
|
|
51
|
+
Requires-Dist: pytest; extra == "test"
|
|
52
|
+
Requires-Dist: pytest-cov; extra == "test"
|
|
53
|
+
Provides-Extra: dev
|
|
54
|
+
Requires-Dist: opticalib[gui,test]; extra == "dev"
|
|
55
|
+
Requires-Dist: flake8; extra == "dev"
|
|
41
56
|
Dynamic: license-file
|
|
42
|
-
Dynamic: maintainer
|
|
43
|
-
Dynamic: requires-dist
|
|
44
|
-
Dynamic: requires-python
|
|
45
|
-
Dynamic: summary
|
|
46
57
|
|
|
47
58
|
# OptiCalib : python framework for OPTical CALibration of deformable mirrors and AO experimentation
|
|
48
59
|
|
|
49
60
|

|
|
61
|
+
[](https://pypi.org/project/opticalib/)
|
|
62
|
+
[](https://pypi.org/project/opticalib/)
|
|
63
|
+
[](LICENSE)
|
|
50
64
|
|
|
51
65
|
`Adaptive Optics Group, INAF - Osservatorio Astrofisico di Arcetri`
|
|
52
66
|
|
|
@@ -78,6 +92,14 @@ The latests, stable, version can be installed from pypi:
|
|
|
78
92
|
pip install opticalib
|
|
79
93
|
```
|
|
80
94
|
|
|
95
|
+
The base install contains everything needed to talk to the hardware, run the simulators and the calibration routines, and use the `calpy` shell. Two optional extras add the rest:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
pip install "opticalib[gui]" # the graphical interface (calpy --gui / OptiCalib)
|
|
99
|
+
pip install "opticalib[cuda13]" # GPU backend (CuPy, via xupy); use cuda12 for CUDA 12.x
|
|
100
|
+
pip install "opticalib[gui,cuda13]" # extras can be combined
|
|
101
|
+
```
|
|
102
|
+
|
|
81
103
|
The in-development version can be installed directly from this repository:
|
|
82
104
|
|
|
83
105
|
```bash
|
|
@@ -113,7 +135,7 @@ dm = opt.AlpaoDm(820) # set in the configuration file
|
|
|
113
135
|
# an Influence Function by just doing
|
|
114
136
|
|
|
115
137
|
tn = dmutils.iff_module.iffDataAcquisition(dm, interf) # Optional paramenters
|
|
116
|
-
# are `
|
|
138
|
+
# are `modeslist, modesAmplitude, template`, which if not specified are
|
|
117
139
|
# read from the configuration file
|
|
118
140
|
```
|
|
119
141
|
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
# OptiCalib : python framework for OPTical CALibration of deformable mirrors and AO experimentation
|
|
2
2
|
|
|
3
3
|

|
|
4
|
+
[](https://pypi.org/project/opticalib/)
|
|
5
|
+
[](https://pypi.org/project/opticalib/)
|
|
6
|
+
[](LICENSE)
|
|
4
7
|
|
|
5
8
|
`Adaptive Optics Group, INAF - Osservatorio Astrofisico di Arcetri`
|
|
6
9
|
|
|
@@ -32,6 +35,14 @@ The latests, stable, version can be installed from pypi:
|
|
|
32
35
|
pip install opticalib
|
|
33
36
|
```
|
|
34
37
|
|
|
38
|
+
The base install contains everything needed to talk to the hardware, run the simulators and the calibration routines, and use the `calpy` shell. Two optional extras add the rest:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install "opticalib[gui]" # the graphical interface (calpy --gui / OptiCalib)
|
|
42
|
+
pip install "opticalib[cuda13]" # GPU backend (CuPy, via xupy); use cuda12 for CUDA 12.x
|
|
43
|
+
pip install "opticalib[gui,cuda13]" # extras can be combined
|
|
44
|
+
```
|
|
45
|
+
|
|
35
46
|
The in-development version can be installed directly from this repository:
|
|
36
47
|
|
|
37
48
|
```bash
|
|
@@ -67,7 +78,7 @@ dm = opt.AlpaoDm(820) # set in the configuration file
|
|
|
67
78
|
# an Influence Function by just doing
|
|
68
79
|
|
|
69
80
|
tn = dmutils.iff_module.iffDataAcquisition(dm, interf) # Optional paramenters
|
|
70
|
-
# are `
|
|
81
|
+
# are `modeslist, modesAmplitude, template`, which if not specified are
|
|
71
82
|
# read from the configuration file
|
|
72
83
|
```
|
|
73
84
|
|
|
@@ -5,20 +5,15 @@ OPTICALIB: adaptive OPTIcs package for dm CALIBration
|
|
|
5
5
|
Author(s)
|
|
6
6
|
---------
|
|
7
7
|
- Pietro Ferraiuolo : pietro.ferraiuolo@inaf.it
|
|
8
|
+
- Runa Briguglio: runa.briguglio@inaf.it
|
|
9
|
+
- Marco Xompero: marco.xompero@inaf.it
|
|
10
|
+
- Matteo Menessini: matteo.menessini@inaf.it
|
|
8
11
|
|
|
9
12
|
Description
|
|
10
13
|
-----------
|
|
11
|
-
|
|
14
|
+
OptiCalib is a package for the control of laboratory instrumentations, like
|
|
12
15
|
Interferometers and Deformable Mirrors. It also provides tools for the
|
|
13
16
|
analysis of wavefronts and images.
|
|
14
|
-
|
|
15
|
-
How to Use:
|
|
16
|
-
-----------
|
|
17
|
-
```python
|
|
18
|
-
> import opticalib
|
|
19
|
-
> interf = opticalib.PhaseCam('193.206.155.218', 8011)
|
|
20
|
-
> img = interf.acquire_map()
|
|
21
|
-
```
|
|
22
17
|
"""
|
|
23
18
|
|
|
24
19
|
from __future__ import annotations
|
|
@@ -34,13 +29,6 @@ from .core.root import (
|
|
|
34
29
|
from .core import config
|
|
35
30
|
from .core import _types as typings
|
|
36
31
|
from .core.fitsarray import fits_array
|
|
37
|
-
from .devices import *
|
|
38
|
-
from .devices.interferometer import _4DInterferometer
|
|
39
|
-
|
|
40
|
-
get_camera_settings = _4DInterferometer.get_camera_settings
|
|
41
|
-
get_frame_rate = _4DInterferometer.get_frame_rate
|
|
42
|
-
|
|
43
|
-
del _4DInterferometer
|
|
44
32
|
|
|
45
33
|
from . import (
|
|
46
34
|
analyzer,
|
|
@@ -51,6 +39,14 @@ from . import (
|
|
|
51
39
|
visualization,
|
|
52
40
|
)
|
|
53
41
|
|
|
42
|
+
from .devices.interferometer import _4DInterferometer
|
|
43
|
+
|
|
44
|
+
get_camera_settings = _4DInterferometer.get_camera_settings
|
|
45
|
+
get_frame_rate = _4DInterferometer.get_frame_rate
|
|
46
|
+
del _4DInterferometer
|
|
47
|
+
|
|
48
|
+
from .devices import *
|
|
49
|
+
|
|
54
50
|
vis = visualization
|
|
55
51
|
|
|
56
52
|
__all__ = [
|
|
@@ -9,7 +9,7 @@ Pietro Ferraiuolo
|
|
|
9
9
|
__title__ = "opticalib"
|
|
10
10
|
__long_title__ = "OPTICALIB : python framework for OPTIcal CALIBration of deformable mirrors and adaptive optics experimentation"
|
|
11
11
|
__description__ = "This package is a python interface for laboratory adaptive optics systems, with a focus on the calibration of deformable mirrors (DMs) and the acquisition of wavefront data using wavefront sensors."
|
|
12
|
-
__version__ = "2.
|
|
12
|
+
__version__ = "2.2.0"
|
|
13
13
|
__author__ = "Adaptive Optics Group - INAF - Osservatorio Astrofisico di Arcetri"
|
|
14
14
|
__maintainer__ = "Pietro Ferraiuolo"
|
|
15
15
|
__author_email__ = "pietro.ferraiuolo@inaf.it"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
from .image_processing import *
|
|
2
|
+
from .signals import *
|
|
3
|
+
from .timeseries import *
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def _get_safe_interf_fullframe():
|
|
7
|
+
from ..devices.interferometer import _4DInterferometer
|
|
8
|
+
|
|
9
|
+
func = _4DInterferometer.into_full_frame
|
|
10
|
+
return func
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
into_4d_full_frame = _get_safe_interf_fullframe()
|
|
@@ -1,21 +1,14 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
Analyzer — offline image, cube and signal processing
|
|
3
|
+
=====================================================
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
-
|
|
5
|
+
Offline analysis of acquired data: single-frame reduction, cube-level
|
|
6
|
+
processing (push-pull, rebin, piston unwrap), spectral analysis (PSD,
|
|
7
|
+
periodograms, Fourier filtering) and time-series diagnostics.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
These are pure functions — they take arrays in and give arrays (or
|
|
10
|
+
numbers) out, with no device access and no persisted state.
|
|
11
11
|
|
|
12
|
-
This module provides utilities to process masked optical phase maps and
|
|
13
|
-
image cubes, including piston unwrapping, push-pull reduction, rebinning,
|
|
14
|
-
Zernike-mode removal, Fourier-domain filtering, and power spectral density
|
|
15
|
-
analysis.
|
|
16
|
-
|
|
17
|
-
The functions are designed to operate on Opticalib typing aliases and
|
|
18
|
-
``fitsarray``-compatible masked arrays used across the analysis pipeline.
|
|
19
12
|
"""
|
|
20
13
|
|
|
21
14
|
import xupy as _xp
|
|
@@ -27,6 +20,38 @@ from ..ground import osutils as osu, modal_decomposer as _md
|
|
|
27
20
|
from scipy import stats as _stats, fft as _fft, ndimage as _ndimage
|
|
28
21
|
|
|
29
22
|
|
|
23
|
+
def pad_image_to_shape(
|
|
24
|
+
img: _ot.ImageData,
|
|
25
|
+
shape: tuple[int, int],
|
|
26
|
+
offset: tuple[int, int],
|
|
27
|
+
fill_value: float = 0.0,
|
|
28
|
+
) -> _ot.ImageData:
|
|
29
|
+
"""
|
|
30
|
+
Pads an image to a specified shape with a given offset and fill value.
|
|
31
|
+
|
|
32
|
+
Parameters
|
|
33
|
+
----------
|
|
34
|
+
img : _ot.ImageData
|
|
35
|
+
The image to be padded.
|
|
36
|
+
shape : tuple[int, int]
|
|
37
|
+
The target shape (height, width) for the padded image.
|
|
38
|
+
offset : tuple[int, int]
|
|
39
|
+
The (y, x) offset at which to place the original image in the padded image.
|
|
40
|
+
fill_value : float, optional
|
|
41
|
+
The value to fill the padded areas with. Default is 0.
|
|
42
|
+
|
|
43
|
+
Returns
|
|
44
|
+
-------
|
|
45
|
+
padded_img : _ot.ImageData
|
|
46
|
+
The padded image.
|
|
47
|
+
"""
|
|
48
|
+
padded_img = _np.full(shape, fill_value)
|
|
49
|
+
y, x = offset
|
|
50
|
+
h, w = _np.shape(img)
|
|
51
|
+
padded_img[y : y + h, x : x + w] = img.data
|
|
52
|
+
return padded_img
|
|
53
|
+
|
|
54
|
+
|
|
30
55
|
def frame(idx: int, mylist: list[_ot.ImageData] | _ot.CubeData) -> _ot.ImageData:
|
|
31
56
|
"""
|
|
32
57
|
Returns a single frame from a list of files or from a cube.
|
|
@@ -213,12 +238,13 @@ def push_pull_reduction_algorithm(
|
|
|
213
238
|
Parameters
|
|
214
239
|
----------
|
|
215
240
|
imagelist : list of ImageData | CubeData
|
|
216
|
-
List of images for the PushPull acquisition, organized according to the
|
|
241
|
+
List of images for the PushPull acquisition, organized according to the
|
|
242
|
+
template.
|
|
217
243
|
template: int | ArrayLike
|
|
218
244
|
Template for the PushPull acquisition.
|
|
219
245
|
normalization : float | int, optional
|
|
220
|
-
Normalization factor for the final image. If None, the normalization
|
|
221
|
-
is set to the template length minus one.
|
|
246
|
+
Normalization factor for the final image. If None, the normalization
|
|
247
|
+
factor is set to the template length minus one.
|
|
222
248
|
|
|
223
249
|
Returns
|
|
224
250
|
-------
|
|
@@ -231,7 +257,7 @@ def push_pull_reduction_algorithm(
|
|
|
231
257
|
# Template weights computation
|
|
232
258
|
w = _xp.asarray(
|
|
233
259
|
template.astype(_np.result_type(template, imagelist[0].data), copy=True),
|
|
234
|
-
dtype=
|
|
260
|
+
dtype=_ot.compute_float(),
|
|
235
261
|
)
|
|
236
262
|
if n_images > 2:
|
|
237
263
|
w[1:-1] *= 2.0
|
|
@@ -239,9 +265,9 @@ def push_pull_reduction_algorithm(
|
|
|
239
265
|
master_mask = _np.logical_or.reduce([ima.mask for ima in imagelist])
|
|
240
266
|
# Compute weighted sum over realizations on raw data
|
|
241
267
|
stack = _xp.stack(
|
|
242
|
-
[_xp.asarray(ima.data, dtype=
|
|
268
|
+
[_xp.asarray(ima.data, dtype=_ot.compute_float()) for ima in imagelist],
|
|
243
269
|
axis=0,
|
|
244
|
-
dtype=
|
|
270
|
+
dtype=_ot.compute_float(),
|
|
245
271
|
) # (n, H, W)
|
|
246
272
|
image = _xp.asnumpy(_xp.tensordot(w, stack, axes=(0, 0))) # (H, W)
|
|
247
273
|
|
|
@@ -262,6 +288,7 @@ def create_cube(fl_or_il: list[str], register: bool = False) -> _ot.CubeData:
|
|
|
262
288
|
----------
|
|
263
289
|
fl_or_il : list of str
|
|
264
290
|
Either:
|
|
291
|
+
|
|
265
292
|
- the list of image file paths;
|
|
266
293
|
- a list of ImageData.
|
|
267
294
|
register : int or tuple, optional
|
|
@@ -865,6 +892,8 @@ def rebin2_d_array(
|
|
|
865
892
|
|
|
866
893
|
|
|
867
894
|
__all__ = [
|
|
895
|
+
"pad_image_to_shape",
|
|
896
|
+
# "into_4d_full_frame",
|
|
868
897
|
"frame",
|
|
869
898
|
"unwrap_piston",
|
|
870
899
|
"unwrap_image",
|
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
Signal-processing utilities — FFT, PSD, filtering and periodograms
|
|
3
|
+
==================================================================
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
Functions for frequency-domain analysis: Fourier filtering, power spectral
|
|
6
|
+
density estimation, periodogram computation and signal detrending. All
|
|
7
|
+
functions operate on plain arrays and return plain arrays.
|
|
8
8
|
|
|
9
|
-
Description
|
|
10
|
-
-----------
|
|
11
|
-
|
|
12
|
-
Module containing functions for signal processing and frequency analysis within
|
|
13
|
-
the Opticalib framework.
|
|
14
9
|
"""
|
|
15
10
|
|
|
16
11
|
import numpy as _np
|
|
@@ -45,6 +40,7 @@ def extract_frequency_spectrum(
|
|
|
45
40
|
Axis along which to compute the FFT (default: -1, last axis).
|
|
46
41
|
window : str or None, optional
|
|
47
42
|
Window function to apply before FFT to reduce spectral leakage:
|
|
43
|
+
|
|
48
44
|
- None: No windowing (rectangular window)
|
|
49
45
|
- "hann": Hann window (default, good general purpose)
|
|
50
46
|
- "hamming": Hamming window
|
|
@@ -52,17 +48,20 @@ def extract_frequency_spectrum(
|
|
|
52
48
|
- "tukey": Tukey window
|
|
53
49
|
detrend : str or None, optional
|
|
54
50
|
Detrending method applied before FFT:
|
|
51
|
+
|
|
55
52
|
- None: No detrending
|
|
56
53
|
- "constant": Remove mean (default)
|
|
57
54
|
- "linear": Remove linear trend
|
|
58
55
|
scaling : str, optional
|
|
59
56
|
Scaling of the power spectral density:
|
|
57
|
+
|
|
60
58
|
- "density": Power spectral density (default)
|
|
61
59
|
- "magnitude": Magnitude spectrum
|
|
62
60
|
|
|
63
61
|
Returns
|
|
64
62
|
-------
|
|
65
63
|
dict with keys:
|
|
64
|
+
|
|
66
65
|
- "frequencies" : 1D ndarray
|
|
67
66
|
Frequency axis in Hz
|
|
68
67
|
- "magnitude" : ndarray
|
|
@@ -1,32 +1,11 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
Description
|
|
11
|
-
-----------
|
|
12
|
-
|
|
13
|
-
This module provides functions to handle and analyze time series data in the context of Optical Imaging.
|
|
14
|
-
It includes utilities for frame extraction, averaging frames, saving and loading averaged images,
|
|
15
|
-
computing running differences, calculating running means, and estimating structure functions from
|
|
16
|
-
time series data.
|
|
17
|
-
|
|
18
|
-
Functions:
|
|
19
|
-
- frame: Retrieve a single frame from a list or cube.
|
|
20
|
-
- average_frames: Average multiple frames to create an averaged image.
|
|
21
|
-
- save_average: Save the averaged image to a file.
|
|
22
|
-
- open_average: Load an averaged image from a file.
|
|
23
|
-
- running_diff: Compute the running difference between frames with optional zernike removal.
|
|
24
|
-
- timevec: Generate a time vector for a set of frames based on their timestamps.
|
|
25
|
-
- running_mean: Calculate the running mean of a 1D array.
|
|
26
|
-
- structfunc: Compute the structure function for a given time series.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
This module is part of the OPTICALIB library and relies on other modules within the package for data handling and processing.
|
|
2
|
+
Time-series analysis — frame extraction, running statistics, structure functions
|
|
3
|
+
================================================================================
|
|
4
|
+
|
|
5
|
+
Utilities for handling time-ordered data: frame extraction and averaging,
|
|
6
|
+
running differences and means, structure-function estimation, and
|
|
7
|
+
timestamp-based time-vector generation.
|
|
8
|
+
|
|
30
9
|
"""
|
|
31
10
|
|
|
32
11
|
import os as _os
|
|
@@ -139,6 +118,7 @@ def save_average(
|
|
|
139
118
|
be passed on
|
|
140
119
|
**kwargs : additional optional arguments
|
|
141
120
|
The same arguments as `average_frames`, to specify the averaging method.
|
|
121
|
+
|
|
142
122
|
- first : int, optional
|
|
143
123
|
Index number of the first file to consider. If None, the first file in
|
|
144
124
|
the list is considered.
|
|
@@ -210,6 +190,7 @@ def running_diff(
|
|
|
210
190
|
----------
|
|
211
191
|
tn_or_fl : str or list[str] or list[ImageData] or CubeData
|
|
212
192
|
It can either be:
|
|
193
|
+
|
|
213
194
|
- a tracking number where the frames to process are;
|
|
214
195
|
- a list of strings with the file list of images to process;
|
|
215
196
|
- a list of ImageData objects;
|
|
@@ -408,6 +389,7 @@ def noise_pushpull(
|
|
|
408
389
|
----------
|
|
409
390
|
tn_or_fl : str | list[ImageData] | list[str] | CubeData
|
|
410
391
|
The data to be processed. Can be either:
|
|
392
|
+
|
|
411
393
|
- A tracking number (str)
|
|
412
394
|
- A list of file paths (str)
|
|
413
395
|
- A list of ImageData objects
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Core — configuration, data folders, shared types and I/O
|
|
3
|
+
========================================================
|
|
4
|
+
|
|
5
|
+
The :mod:`opticalib.core` package is the foundation of the library. It
|
|
6
|
+
owns the YAML configuration file, the on-disk data folder tree, the
|
|
7
|
+
exception hierarchy, shared decorators, structured data classes for
|
|
8
|
+
passing calibration results between components, and the FITS-aware masked
|
|
9
|
+
array wrappers.
|
|
10
|
+
|
|
11
|
+
Every other area of the library depends on core. Importing it reads
|
|
12
|
+
``AOCONF``, opens the configuration file, and calls
|
|
13
|
+
:func:`~opticalib.core.root.create_folder_tree` — set the environment
|
|
14
|
+
variable before import (or use the ``calpy`` entry point, which handles
|
|
15
|
+
it automatically).
|
|
16
|
+
|
|
17
|
+
"""
|
|
@@ -61,11 +61,14 @@ DEVICES:
|
|
|
61
61
|
DEFORMABLE.MIRRORS:
|
|
62
62
|
AlpaoXXX:
|
|
63
63
|
# AlpaoDM serial number, BAX<YYY>
|
|
64
|
-
|
|
64
|
+
serial_number:
|
|
65
65
|
# Parent folder containing Lib64/ (e.g. .../Linux/Samples/Python3)
|
|
66
66
|
sdk_folder_path:
|
|
67
67
|
# Folder containing the .acfg hardware config file (sets ACECFG env var)
|
|
68
68
|
acfg_path:
|
|
69
|
+
# IP and PORT needed for the plico_dm backend
|
|
70
|
+
plico_ip:
|
|
71
|
+
plico_port:
|
|
69
72
|
diameter:
|
|
70
73
|
slave_ids: []
|
|
71
74
|
border_ids: []
|
|
@@ -1,19 +1,32 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
2
|
+
Type System — structural type aliases and device protocols for OptiCalib
|
|
3
|
+
========================================================================
|
|
4
|
+
|
|
5
|
+
OptiCalib is deliberately *hardware agnostic*. Instead of coupling
|
|
6
|
+
algorithms to concrete classes, this module defines **structural type
|
|
7
|
+
aliases** and **Protocol classes** that describe the *shape* and
|
|
8
|
+
*capabilities* an object must have.
|
|
9
|
+
|
|
10
|
+
Two complementary layers:
|
|
11
|
+
|
|
12
|
+
**Data aliases** — ``MatrixLike``, ``MaskData``, ``ImageData``,
|
|
13
|
+
``CubeData``, ``FitsData`` — capture what array-shaped payloads look like
|
|
14
|
+
(dimensionality, presence of a mask, FITS serialisability). Every alias
|
|
15
|
+
is a :class:`~typing.TypeVar` bound to a :class:`~typing.Protocol`, so
|
|
16
|
+
static type checkers verify compatibility without any inheritance
|
|
17
|
+
relationship.
|
|
18
|
+
|
|
19
|
+
**Device protocols** — ``InterferometerDevice``, ``WFSDevice``,
|
|
20
|
+
``CameraDevice``, ``DeformableMirrorDevice`` and their ``Fake*``
|
|
21
|
+
counterparts — specify the *methods* a device must expose. Any object
|
|
22
|
+
that structurally matches the protocol can be passed where the alias is
|
|
23
|
+
expected, whether it is a real driver, a simulator, or a test double.
|
|
24
|
+
|
|
25
|
+
The module is re-exported publicly as ``opticalib.typings``.
|
|
26
|
+
|
|
27
|
+
Because the aliases are structural (not nominal), ``isinstance(x,
|
|
28
|
+
ImageData)`` does **not** work. Use :func:`isinstance_` instead — it
|
|
29
|
+
dispatches to the correct runtime check for the given name.
|
|
17
30
|
|
|
18
31
|
"""
|
|
19
32
|
|
|
@@ -39,7 +52,10 @@ if TYPE_CHECKING:
|
|
|
39
52
|
#################################
|
|
40
53
|
## DATA TYPES AND TYPE ALIASES ##
|
|
41
54
|
#################################
|
|
55
|
+
#: A reconstructor object used to convert raw interferometer frames into
|
|
56
|
+
#: phase maps, or ``None`` when no reconstruction is needed.
|
|
42
57
|
Reconstructor: TypeAlias = Union["ComputeReconstructor", None]
|
|
58
|
+
#: Any plain Python number, i.e. an ``int``, a ``float`` or a ``complex``.
|
|
43
59
|
Number: TypeAlias = Union[int, float, complex]
|
|
44
60
|
|
|
45
61
|
|
|
@@ -82,10 +98,21 @@ class _CubeProtocol(Protocol):
|
|
|
82
98
|
def __array__(self) -> ArrayLike: ...
|
|
83
99
|
|
|
84
100
|
|
|
101
|
+
#: A generic 2-D matrix, i.e. any object with a ``shape`` that can be
|
|
102
|
+
#: indexed, such as a ``numpy.ndarray`` or a nested list. Used for command matrices,
|
|
103
|
+
#: command histories and other plain numeric tables.
|
|
85
104
|
MatrixLike = TypeVar("MatrixLike", bound=_MatrixProtocol)
|
|
105
|
+
#: A 2-D boolean (or integer 0/1) mask, typically marking which pixels lie
|
|
106
|
+
#: outside the pupil or region of interest.
|
|
86
107
|
MaskData = TypeVar("MaskData", bound=_MatrixProtocol)
|
|
108
|
+
#: A single 2-D image with a mask attached, such as a phase map returned by
|
|
109
|
+
#: an interferometer. In practice this is a ``numpy.ma.MaskedArray``.
|
|
87
110
|
ImageData = TypeVar("ImageData", bound=_ImageDataProtocol)
|
|
111
|
+
#: A 3-D stack of masked images, with shape ``(ny, nx, n_frames)``, such as
|
|
112
|
+
#: the set of influence functions measured for a deformable mirror.
|
|
88
113
|
CubeData = TypeVar("CubeData", bound=_CubeProtocol)
|
|
114
|
+
#: An array (masked or not) that can be saved to and loaded from a FITS file,
|
|
115
|
+
#: e.g. a :class:`~opticalib.core.fitsarray.FitsArray`.
|
|
89
116
|
FitsData = TypeVar("FitsData", _FitsArrayProtocol, _FitsMaskedArrayProtocol)
|
|
90
117
|
|
|
91
118
|
|
|
@@ -118,8 +145,13 @@ class _WFSProtocol(Protocol):
|
|
|
118
145
|
def acquire_detector(self, **kwargs: dict[str, Any]) -> ImageData: ...
|
|
119
146
|
|
|
120
147
|
|
|
148
|
+
#: Any interferometer, real or simulated, that can acquire phase maps and
|
|
149
|
+
#: capture/produce raw frame sequences.
|
|
121
150
|
InterferometerDevice = TypeVar("InterferometerDevice", bound=_InterfProtocol)
|
|
151
|
+
#: Any camera that can acquire frames and get/set its exposure time.
|
|
122
152
|
CameraDevice = TypeVar("CameraDevice", bound=_CameraProtocol)
|
|
153
|
+
#: Any wavefront sensor that can acquire phase maps, pupil images and raw
|
|
154
|
+
#: detector frames.
|
|
123
155
|
WFSDevice = TypeVar("WFSDevice", bound=_WFSProtocol)
|
|
124
156
|
|
|
125
157
|
|
|
@@ -130,7 +162,7 @@ class _DMProtocol(Protocol):
|
|
|
130
162
|
def set_shape(self, cmd: MatrixLike, differential: bool) -> None: ...
|
|
131
163
|
def get_shape(self) -> ArrayLike: ...
|
|
132
164
|
def upload_cmd_history(
|
|
133
|
-
self, cmdhist: MatrixLike, *,
|
|
165
|
+
self, cmdhist: MatrixLike, *, slaving: bool | str = False
|
|
134
166
|
) -> None: ...
|
|
135
167
|
def run_cmd_history(
|
|
136
168
|
self,
|
|
@@ -162,14 +194,22 @@ class _FakeInterfProtocol(_InterfProtocol, Protocol):
|
|
|
162
194
|
def toggle_shape_removal(self, modes: list[int]) -> None: ...
|
|
163
195
|
|
|
164
196
|
|
|
197
|
+
#: Any deformable mirror, real or simulated, that can apply a shape, read it
|
|
198
|
+
#: back, and run a timed history of commands.
|
|
165
199
|
DeformableMirrorDevice = TypeVar("DeformableMirrorDevice", bound=_DMProtocol)
|
|
200
|
+
#: A simulated deformable mirror. It is a ``DeformableMirrorDevice`` that
|
|
201
|
+
#: also exposes its internal mask, Zernike generator and computed wavefront.
|
|
166
202
|
FakeDeformableMirrorDevice = TypeVar(
|
|
167
203
|
"FakeDeformableMirrorDevice", bound=_FakeDMProtocol
|
|
168
204
|
)
|
|
205
|
+
#: A simulated interferometer. It is an ``InterferometerDevice`` that also
|
|
206
|
+
#: offers live-view controls (surface view, noise, shape removal, ...).
|
|
169
207
|
FakeInterferometerDevice = TypeVar(
|
|
170
208
|
"FakeInterferometerDevice", bound=_FakeInterfProtocol
|
|
171
209
|
)
|
|
172
210
|
|
|
211
|
+
#: Any device object, with no required methods. Used where a function works
|
|
212
|
+
#: with whichever instrument it is given.
|
|
173
213
|
GenericDevice = TypeVar("GenericDevice")
|
|
174
214
|
|
|
175
215
|
#######################
|
|
@@ -399,3 +439,32 @@ class InstanceCheck:
|
|
|
399
439
|
|
|
400
440
|
|
|
401
441
|
isinstance_ = InstanceCheck.isinstance_
|
|
442
|
+
|
|
443
|
+
######################
|
|
444
|
+
## Helper Functions ##
|
|
445
|
+
######################
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
def get_device_type(device: object) -> str:
|
|
449
|
+
if isinstance_(device, "InterferometerDevice"):
|
|
450
|
+
return "interf"
|
|
451
|
+
elif isinstance_(device, "WFSDevice"):
|
|
452
|
+
return "wfs"
|
|
453
|
+
elif isinstance_(device, "CameraDevice"):
|
|
454
|
+
return "camera"
|
|
455
|
+
return device._name
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
def compute_float():
|
|
459
|
+
"""
|
|
460
|
+
Floating dtype for numerical work on the active xupy backend.
|
|
461
|
+
|
|
462
|
+
``float32`` on GPU (CuPy) for speed, ``float64`` on CPU (NumPy). This is
|
|
463
|
+
what the removed ``xupy.float`` alias used to resolve to; it is evaluated
|
|
464
|
+
at call time, so it follows ``xupy.use_cpu()`` / ``xupy.use_gpu()``.
|
|
465
|
+
"""
|
|
466
|
+
import xupy as xp
|
|
467
|
+
|
|
468
|
+
dtype = xp.float32 if xp.on_gpu else xp.float64
|
|
469
|
+
del xp
|
|
470
|
+
return dtype
|