structured-optics 0.3__tar.gz → 0.4.1__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 (24) hide show
  1. structured_optics-0.4.1/LICENSE +28 -0
  2. structured_optics-0.4.1/PKG-INFO +93 -0
  3. structured_optics-0.4.1/README.md +79 -0
  4. {structured_optics-0.3 → structured_optics-0.4.1}/pyproject.toml +4 -2
  5. structured_optics-0.4.1/structured_optics/slmdisplay.py +160 -0
  6. structured_optics-0.4.1/structured_optics/struct_opt.py +1527 -0
  7. {structured_optics-0.3 → structured_optics-0.4.1}/structured_optics/utils.py +27 -0
  8. structured_optics-0.4.1/structured_optics.egg-info/PKG-INFO +93 -0
  9. {structured_optics-0.3 → structured_optics-0.4.1}/structured_optics.egg-info/SOURCES.txt +2 -0
  10. {structured_optics-0.3 → structured_optics-0.4.1}/structured_optics.egg-info/requires.txt +1 -1
  11. structured_optics-0.3/PKG-INFO +0 -9
  12. structured_optics-0.3/structured_optics/slmdisplay.py +0 -85
  13. structured_optics-0.3/structured_optics/struct_opt.py +0 -580
  14. structured_optics-0.3/structured_optics.egg-info/PKG-INFO +0 -9
  15. {structured_optics-0.3 → structured_optics-0.4.1}/setup.cfg +0 -0
  16. {structured_optics-0.3 → structured_optics-0.4.1}/setup.py +0 -0
  17. {structured_optics-0.3 → structured_optics-0.4.1}/structured_optics/__init__.py +0 -0
  18. {structured_optics-0.3 → structured_optics-0.4.1}/structured_optics/algebra_utils.py +0 -0
  19. {structured_optics-0.3 → structured_optics-0.4.1}/structured_optics/hologram.py +0 -0
  20. {structured_optics-0.3 → structured_optics-0.4.1}/structured_optics/modes.py +0 -0
  21. {structured_optics-0.3 → structured_optics-0.4.1}/structured_optics/polarization.py +0 -0
  22. {structured_optics-0.3 → structured_optics-0.4.1}/structured_optics/prop_methods.py +0 -0
  23. {structured_optics-0.3 → structured_optics-0.4.1}/structured_optics.egg-info/dependency_links.txt +0 -0
  24. {structured_optics-0.3 → structured_optics-0.4.1}/structured_optics.egg-info/top_level.txt +0 -0
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, <Your Altilano Cristino Barbosa>
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,93 @@
1
+ Metadata-Version: 2.4
2
+ Name: structured_optics
3
+ Version: 0.4.1
4
+ Summary: Package for Structured Light simulation
5
+ Author: Altilano C. Barbosa
6
+ License-Expression: BSD-3-Clause
7
+ Requires-Python: >=3.9
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: numpy
11
+ Requires-Dist: scipy
12
+ Requires-Dist: screeninfo
13
+ Dynamic: license-file
14
+
15
+ # structured-optics
16
+
17
+ A Python library for generating, propagating, and analyzing structured light beams
18
+ (Hermite-Gaussian, Laguerre-Gaussian, Bessel, Ince-Gaussian, fiber LP modes, and more)
19
+ on a discretized transverse grid.
20
+
21
+ [![PyPI version](https://img.shields.io/pypi/v/structured-optics.svg)](https://pypi.org/project/structured-optics/)
22
+
23
+ [![License: BSD-3-Clause](https://img.shields.io/badge/License-BSD--3--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
24
+
25
+ ## Features
26
+
27
+ - **Mode generation**: Hermite-Gaussian, Laguerre-Gaussian, Bessel, Gaussian-Bessel,
28
+ Ince-Gaussian (even/odd/helical), fractional OAM, fiber LP modes, and geometric
29
+ apertures (circle, square, triangle).
30
+ - **Propagation**: Fresnel, Fraunhofer, and incoherent propagation methods.
31
+ - **Polarization**: vector beams with Ex/Ey/Ez components, Jones-matrix optics
32
+ (waveplates, polarizers).
33
+ - **Optical elements**: lenses (spherical, astigmatic, tilted), slits, irises,
34
+ and other amplitude/phase masks.
35
+ - **Analysis**: power, intensity and phase profiles, centroid, beam size (std),
36
+ angular sections, and modal decomposition (HG/LG/Bessel basis projections).
37
+ - **Holography**: SLM and DMD hologram generation for experimental beam shaping.
38
+
39
+ ## Installation
40
+
41
+ ```bash
42
+ pip install structured-optics
43
+ ```
44
+
45
+ ## Quick start
46
+
47
+ ```python
48
+ import structured_optics as so
49
+
50
+ # Create a beam on a 10mm x 10mm (2*5e-3) grid with 256x256 points
51
+ beam = so.Beam(nix=5e-3, Dx=256, waist=1e-3, lamb=1064e-9)
52
+
53
+ # Set the field to a Laguerre-Gaussian mode with l=2, p=0
54
+ beam.lg(l=2, p=0)
55
+
56
+ # Propagate 10 cm and check total power
57
+ beam.propagate(z=0.1, method='fresnel')
58
+ print(beam.Power())
59
+
60
+ # Look at the intensity profile
61
+ import matplotlib.pyplot as plt
62
+ plt.pcolormesh(beam.x, beam.y, beam.int_profile())
63
+ plt.show()
64
+ ```
65
+
66
+ ## Documentation
67
+
68
+ Full API documentation, including all mode types, propagation methods, and
69
+ optical elements, is available at:
70
+
71
+ Soon...
72
+
73
+ ## Requirements
74
+
75
+ - Python 3.9+
76
+ - numpy
77
+ - scipy
78
+ - screeninfo
79
+
80
+
81
+
82
+ ## Contributing
83
+
84
+ Issues and pull requests are welcome at
85
+ [github.com/Altilano/structured-optics](https://github.com/Altilano/structured-optics).
86
+
87
+ ## License
88
+
89
+ This project is licensed under the BSD-3-Clause License. See `LICENSE` for details.
90
+
91
+ ## Citation
92
+
93
+
@@ -0,0 +1,79 @@
1
+ # structured-optics
2
+
3
+ A Python library for generating, propagating, and analyzing structured light beams
4
+ (Hermite-Gaussian, Laguerre-Gaussian, Bessel, Ince-Gaussian, fiber LP modes, and more)
5
+ on a discretized transverse grid.
6
+
7
+ [![PyPI version](https://img.shields.io/pypi/v/structured-optics.svg)](https://pypi.org/project/structured-optics/)
8
+
9
+ [![License: BSD-3-Clause](https://img.shields.io/badge/License-BSD--3--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
10
+
11
+ ## Features
12
+
13
+ - **Mode generation**: Hermite-Gaussian, Laguerre-Gaussian, Bessel, Gaussian-Bessel,
14
+ Ince-Gaussian (even/odd/helical), fractional OAM, fiber LP modes, and geometric
15
+ apertures (circle, square, triangle).
16
+ - **Propagation**: Fresnel, Fraunhofer, and incoherent propagation methods.
17
+ - **Polarization**: vector beams with Ex/Ey/Ez components, Jones-matrix optics
18
+ (waveplates, polarizers).
19
+ - **Optical elements**: lenses (spherical, astigmatic, tilted), slits, irises,
20
+ and other amplitude/phase masks.
21
+ - **Analysis**: power, intensity and phase profiles, centroid, beam size (std),
22
+ angular sections, and modal decomposition (HG/LG/Bessel basis projections).
23
+ - **Holography**: SLM and DMD hologram generation for experimental beam shaping.
24
+
25
+ ## Installation
26
+
27
+ ```bash
28
+ pip install structured-optics
29
+ ```
30
+
31
+ ## Quick start
32
+
33
+ ```python
34
+ import structured_optics as so
35
+
36
+ # Create a beam on a 10mm x 10mm (2*5e-3) grid with 256x256 points
37
+ beam = so.Beam(nix=5e-3, Dx=256, waist=1e-3, lamb=1064e-9)
38
+
39
+ # Set the field to a Laguerre-Gaussian mode with l=2, p=0
40
+ beam.lg(l=2, p=0)
41
+
42
+ # Propagate 10 cm and check total power
43
+ beam.propagate(z=0.1, method='fresnel')
44
+ print(beam.Power())
45
+
46
+ # Look at the intensity profile
47
+ import matplotlib.pyplot as plt
48
+ plt.pcolormesh(beam.x, beam.y, beam.int_profile())
49
+ plt.show()
50
+ ```
51
+
52
+ ## Documentation
53
+
54
+ Full API documentation, including all mode types, propagation methods, and
55
+ optical elements, is available at:
56
+
57
+ Soon...
58
+
59
+ ## Requirements
60
+
61
+ - Python 3.9+
62
+ - numpy
63
+ - scipy
64
+ - screeninfo
65
+
66
+
67
+
68
+ ## Contributing
69
+
70
+ Issues and pull requests are welcome at
71
+ [github.com/Altilano/structured-optics](https://github.com/Altilano/structured-optics).
72
+
73
+ ## License
74
+
75
+ This project is licensed under the BSD-3-Clause License. See `LICENSE` for details.
76
+
77
+ ## Citation
78
+
79
+
@@ -4,8 +4,10 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "structured_optics"
7
- version = "0.3"
7
+ version = "0.4.1"
8
8
  description = "Package for Structured Light simulation"
9
+ readme = "README.md"
10
+ license = "BSD-3-Clause"
9
11
  requires-python = ">=3.9"
10
12
  authors = [
11
13
  { name = "Altilano C. Barbosa" }
@@ -14,5 +16,5 @@ authors = [
14
16
  dependencies = [
15
17
  "numpy",
16
18
  "scipy",
17
- "PyQt6"
19
+ "screeninfo"
18
20
  ]
@@ -0,0 +1,160 @@
1
+ """import sys
2
+ import numpy as np
3
+ from PyQt6.QtWidgets import QApplication, QLabel
4
+ from PyQt6.QtGui import QImage, QPixmap
5
+ from PyQt6.QtCore import Qt
6
+
7
+ class My_SLM(QLabel):
8
+ def __init__(self, screen_index=0):
9
+ self.app = QApplication.instance() or QApplication(sys.argv)
10
+ super().__init__()
11
+
12
+ screens = self.app.screens()
13
+ if screen_index >= len(screens):
14
+ raise ValueError("Invalid screen index")
15
+
16
+ screen = screens[screen_index]
17
+
18
+ # Force native window creation (CRITICAL on Linux)
19
+ self.setAttribute(Qt.WidgetAttribute.WA_NativeWindow)
20
+
21
+ self.setWindowFlags(
22
+ Qt.WindowType.FramelessWindowHint
23
+ )
24
+
25
+ self.show() # must come before windowHandle()
26
+
27
+ self.windowHandle().setScreen(screen)
28
+ geo = screen.geometry()
29
+
30
+ # Store logical screen size
31
+ self.width = geo.width()
32
+ self.height = geo.height()
33
+ self.setGeometry(geo)
34
+
35
+ self.showFullScreen()
36
+
37
+ self._img_ref = None
38
+
39
+
40
+ def update_image(self, img: np.ndarray):
41
+
42
+ #img:
43
+ # - (H, W) uint8 → grayscale
44
+ # - (H, W, 3) uint8 → RGB
45
+
46
+ if img.dtype != np.uint8:
47
+ raise TypeError("Image must be uint8")
48
+
49
+ self._img_ref = img # keep reference alive
50
+
51
+ if img.ndim == 2:
52
+ h, w = img.shape
53
+ stride = img.strides[0]
54
+
55
+ qimg = QImage(
56
+ img.data,
57
+ w,
58
+ h,
59
+ stride,
60
+ QImage.Format.Format_Grayscale8
61
+ )
62
+
63
+ elif img.ndim == 3 and img.shape[2] == 3:
64
+ h, w, _ = img.shape
65
+ stride = img.strides[0]
66
+
67
+ qimg = QImage(
68
+ img.data,
69
+ w,
70
+ h,
71
+ stride,
72
+ QImage.Format.Format_RGB888
73
+ )
74
+ else:
75
+ raise ValueError("Image must be (H,W) or (H,W,3)")
76
+
77
+ self.setPixmap(QPixmap.fromImage(qimg))
78
+ self.app.processEvents()
79
+
80
+ def close(self):
81
+ if not self.isVisible():
82
+ return
83
+ self.hide()
84
+ self.setParent(None) # detach from Qt ownership
85
+ self.deleteLater() """
86
+
87
+ import tkinter as tk
88
+ import numpy as np
89
+ from screeninfo import get_monitors
90
+
91
+
92
+ class My_SLM:
93
+ """
94
+ Fullscreen numpy-array display on a chosen physical monitor.
95
+ Uses plain tkinter (stdlib) - the image is shown as ordinary
96
+ CPU-composited window content, the same way PyQt6's QLabel/QPixmap
97
+ did. Unlike an OpenGL surface (pyglet/GLFW), this never becomes a
98
+ GPU flip-model surface, so it doesn't trigger the driver-level
99
+ scanout switch that causes the display to briefly flash/resync.
100
+ """
101
+
102
+ def __init__(self, screen_index: int = 0):
103
+ monitors = get_monitors()
104
+ if screen_index >= len(monitors):
105
+ raise ValueError("Invalid screen index")
106
+
107
+ m = monitors[screen_index]
108
+ self.width, self.height = m.width, m.height
109
+
110
+ self.root = tk.Tk()
111
+ self.root.overrideredirect(True) # borderless
112
+ self.root.geometry(f"{self.width}x{self.height}+{m.x}+{m.y}")
113
+ self.root.attributes("-topmost", True)
114
+ self.root.configure(bg="black")
115
+
116
+ self.label = tk.Label(self.root, bd=0, highlightthickness=0, bg="black")
117
+ self.label.pack(fill="both", expand=True)
118
+
119
+ self.root.update_idletasks()
120
+ self.root.update()
121
+
122
+ self._photo_ref = None # keep the PhotoImage alive (Tk drops it otherwise)
123
+ self._img_ref = None
124
+
125
+ def update_image(self, img: np.ndarray):
126
+ """
127
+ img:
128
+ - (H, W) uint8 -> grayscale
129
+ - (H, W, 3) uint8 -> RGB
130
+ """
131
+ if img.dtype != np.uint8:
132
+ raise TypeError("Image must be uint8")
133
+
134
+ img = np.ascontiguousarray(img)
135
+ self._img_ref = img # keep a reference alive
136
+
137
+ if img.ndim == 2:
138
+ h, w = img.shape
139
+ header = f"P5\n{w} {h}\n255\n".encode()
140
+ elif img.ndim == 3 and img.shape[2] == 3:
141
+ h, w, _ = img.shape
142
+ header = f"P6\n{w} {h}\n255\n".encode()
143
+ else:
144
+ raise ValueError("Image must be (H,W) or (H,W,3)")
145
+
146
+ # Build a raw PGM/PPM blob in memory - Tk's built-in photo image
147
+ # reader parses this directly in C, so no PIL/Pillow dependency
148
+ # and no per-pixel Python loop.
149
+ data = header + img.tobytes()
150
+ photo = tk.PhotoImage(data=data)
151
+
152
+ self._photo_ref = photo
153
+ self.label.configure(image=photo)
154
+
155
+ self.root.update()
156
+
157
+ def close(self):
158
+ self.root.destroy()
159
+
160
+