topolino 0.1.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.
topolino-0.1.0/LICENSE ADDED
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2025, Dream Beam
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,30 @@
1
+ Metadata-Version: 2.4
2
+ Name: topolino
3
+ Version: 0.1.0
4
+ Summary: Fourier optics and wave propagation utilities
5
+ Author-email: Rachel Migdal <rmigdal2007@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Repository, https://github.com/dream-beam/Topolino
8
+ Keywords: fourier optics,wave propagation,physics,optics
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Topic :: Scientific/Engineering :: Physics
13
+ Requires-Python: >=3.10
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENSE
16
+ Requires-Dist: numpy
17
+ Requires-Dist: scikit-image
18
+ Provides-Extra: dev
19
+ Requires-Dist: jupyter; extra == "dev"
20
+ Requires-Dist: matplotlib; extra == "dev"
21
+ Dynamic: license-file
22
+
23
+ # Topolino
24
+ ramigdal@lbl.gov, awojdyla@lbl.gov
25
+ ![Topolino](assets/topolino_logo.png)
26
+
27
+ This repository is a Python toolkit for exploring paraxial wave propagation and related optical phenomena. At its core is a Fresnel propagator `propTF` that uses NumPy's FFT to propagate a complex field through space. The package includes routines for generating Gaussian beams, extracting the RMS beam radius from intensity moments, and directly comparing the numerical propagation to the analytical Gaussian‑beam law.
28
+ A collection of Jupyter notebooks demonstrates a range of topics: a thin‑lens model, creation and propagation of spiral beams, diffraction patterns of transmission gratings, and a full grating‑experiment simulation that includes a light source, propagation to a grating, and observation of resulting orders. The notebooks expose parameters (wavelength , aperture size, grating period, vortex charge, ...), visualize results with 1‑D plots, RMS‑size versus distance curves, and 2‑D intensity maps, and provide side‑by‑side comparisons with analytical predictions where available.
29
+
30
+ ![Propagation](assets/propagation.png)
@@ -0,0 +1,8 @@
1
+ # Topolino
2
+ ramigdal@lbl.gov, awojdyla@lbl.gov
3
+ ![Topolino](assets/topolino_logo.png)
4
+
5
+ This repository is a Python toolkit for exploring paraxial wave propagation and related optical phenomena. At its core is a Fresnel propagator `propTF` that uses NumPy's FFT to propagate a complex field through space. The package includes routines for generating Gaussian beams, extracting the RMS beam radius from intensity moments, and directly comparing the numerical propagation to the analytical Gaussian‑beam law.
6
+ A collection of Jupyter notebooks demonstrates a range of topics: a thin‑lens model, creation and propagation of spiral beams, diffraction patterns of transmission gratings, and a full grating‑experiment simulation that includes a light source, propagation to a grating, and observation of resulting orders. The notebooks expose parameters (wavelength , aperture size, grating period, vortex charge, ...), visualize results with 1‑D plots, RMS‑size versus distance curves, and 2‑D intensity maps, and provide side‑by‑side comparisons with analytical predictions where available.
7
+
8
+ ![Propagation](assets/propagation.png)
@@ -0,0 +1,35 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "topolino"
7
+ version = "0.1.0"
8
+ description = "Fourier optics and wave propagation utilities"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = "MIT"
12
+ authors = [
13
+ { name = "Rachel Migdal", email = "rmigdal2007@gmail.com" },
14
+ ]
15
+ keywords = ["fourier optics", "wave propagation", "physics", "optics"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Intended Audience :: Science/Research",
19
+ "Programming Language :: Python :: 3",
20
+ "Topic :: Scientific/Engineering :: Physics",
21
+ ]
22
+ dependencies = [
23
+ "numpy",
24
+ "scikit-image",
25
+ ]
26
+
27
+ [project.urls]
28
+ Repository = "https://github.com/dream-beam/Topolino"
29
+
30
+ [tool.setuptools.packages.find]
31
+ where = ["."]
32
+ include = ["topolino*"]
33
+
34
+ [project.optional-dependencies]
35
+ dev = ["jupyter", "matplotlib"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,11 @@
1
+ from .fourier import ft, ift, fs, setfreq
2
+ from .propagation import propTF, propTF2
3
+ from .beam import gaussian, rms_width, generate_speckle
4
+ from .analysis import azimuthal_avg, circsum
5
+
6
+ __all__ = [
7
+ "ft", "ift", "fs", "setfreq",
8
+ "propTF", "propTF2",
9
+ "gaussian", "rms_width", "generate_speckle",
10
+ "azimuthal_avg", "circsum",
11
+ ]
@@ -0,0 +1,36 @@
1
+ import numpy as np
2
+ from skimage.transform import warp_polar
3
+
4
+
5
+ def azimuthal_avg(data_2d):
6
+ """
7
+ Azimuthal average of a 2D square image.
8
+
9
+ Parameters
10
+ ----------
11
+ data_2d : 2D ndarray
12
+ Square array (intensity or amplitude).
13
+
14
+ Returns
15
+ -------
16
+ 1D ndarray
17
+ Radial profile from centre to edge (length = floor((N+1)/2) - 1).
18
+ """
19
+ Np = int(np.floor((len(data_2d) + 1) / 2))
20
+ return np.sum(warp_polar(data_2d), axis=0)[: Np - 1]
21
+
22
+
23
+ def circsum(field):
24
+ """
25
+ Radial power spectrum via azimuthal sum of |field|².
26
+
27
+ Parameters
28
+ ----------
29
+ field : 2D ndarray
30
+ Complex or real field.
31
+
32
+ Returns
33
+ -------
34
+ 1D ndarray
35
+ """
36
+ return np.sum(warp_polar(np.abs(field) ** 2), axis=0)
@@ -0,0 +1,94 @@
1
+ import numpy as np
2
+
3
+ from .fourier import ft, ift, fs
4
+ from .propagation import propTF
5
+
6
+
7
+ def gaussian(x, mean, fwhm):
8
+ """
9
+ 1D Gaussian parameterised by FWHM.
10
+
11
+ Parameters
12
+ ----------
13
+ x : array_like
14
+ Evaluation points (any units).
15
+ mean : float
16
+ Centre (same units as x).
17
+ fwhm : float
18
+ Full width at half maximum (same units as x).
19
+
20
+ Returns
21
+ -------
22
+ ndarray
23
+ """
24
+ sigma = fwhm / (2 * np.sqrt(2 * np.log(2)))
25
+ return np.exp(-((x - mean) / (np.sqrt(2) * sigma)) ** 2)
26
+
27
+
28
+ def rms_width(field, x):
29
+ """
30
+ RMS width of a 1D field distribution.
31
+
32
+ Parameters
33
+ ----------
34
+ field : array_like
35
+ Complex or real field (intensity is |field|²).
36
+ x : array_like
37
+ Spatial axis (same length as field).
38
+
39
+ Returns
40
+ -------
41
+ float
42
+ RMS width in the same units as x.
43
+ """
44
+ x = np.asarray(x)
45
+ I = np.abs(field) ** 2
46
+ I = I / I.sum()
47
+ xc = np.sum(I * x)
48
+ return np.sqrt(np.sum(I * (x - xc) ** 2))
49
+
50
+
51
+ def generate_speckle(dx_m, Dx_m, z_m, fwhm_m=500e-6, lambda_m=1e-6, fc_cpm=1e6, wfe_w=1 / 20):
52
+ """
53
+ Simulate a speckle intensity pattern after free-space propagation.
54
+
55
+ Parameters
56
+ ----------
57
+ dx_m : float
58
+ Pixel size in metres.
59
+ Dx_m : float
60
+ Field extent in metres.
61
+ z_m : float
62
+ Propagation distance in metres.
63
+ fwhm_m : float
64
+ Beam FWHM at the source plane (metres).
65
+ lambda_m : float
66
+ Wavelength (metres).
67
+ fc_cpm : float
68
+ Speckle spatial-frequency cutoff (cycles per metre).
69
+ wfe_w : float
70
+ Wavefront error amplitude in waves (peak-to-valley).
71
+
72
+ Returns
73
+ -------
74
+ I : 2D ndarray
75
+ Intensity at the output plane.
76
+ """
77
+ x_m = np.linspace(-Dx_m / 2, Dx_m / 2, int(np.ceil(Dx_m / dx_m)))
78
+ N = len(x_m)
79
+ X_m, Y_m = np.meshgrid(x_m, x_m)
80
+
81
+ f_cpm = fs(x_m)
82
+ Fx, Fy = np.meshgrid(f_cpm, f_cpm)
83
+
84
+ GFILT = gaussian(Fx, 0, fc_cpm) * gaussian(Fy, 0, fc_cpm)
85
+
86
+ noise = np.random.randn(N, N)
87
+ noise_filt = np.abs(ift(ft(noise) * GFILT))
88
+ noise_filt = noise_filt / np.std(noise_filt)
89
+
90
+ E0 = gaussian(X_m, 0, fwhm_m) * gaussian(Y_m, 0, fwhm_m)
91
+ E1 = E0 * np.exp(1j * 2 * np.pi * noise_filt * wfe_w)
92
+
93
+ E2 = propTF(E1, Dx_m, lambda_m, z_m)
94
+ return np.abs(E2) ** 2
@@ -0,0 +1,49 @@
1
+ import numpy as np
2
+
3
+
4
+ def ft(t):
5
+ """Centered 2D FFT: ifftshift → fft2 → fftshift."""
6
+ return np.fft.fftshift(np.fft.fft2(np.fft.ifftshift(t)))
7
+
8
+
9
+ def ift(t):
10
+ """Centered 2D IFFT: ifftshift → ifft2 → fftshift."""
11
+ return np.fft.fftshift(np.fft.ifft2(np.fft.ifftshift(t)))
12
+
13
+
14
+ def fs(t):
15
+ """Frequency axis (cycles per unit) matching a centered spatial axis t."""
16
+ N = len(t)
17
+ df = 1 / (t[-1] - t[0])
18
+ return np.fft.fftshift(
19
+ np.array([df * n if n < N / 2 else df * (n - N) for n in range(N)])
20
+ )
21
+
22
+
23
+ def setfreq(px_size_m, img_size_m):
24
+ """
25
+ Build spatial and frequency axes for a square image.
26
+
27
+ Parameters
28
+ ----------
29
+ px_size_m : float
30
+ Pixel size in metres.
31
+ img_size_m : float
32
+ Full image extent in metres.
33
+
34
+ Returns
35
+ -------
36
+ dx_m, Dx_m, f_cpm, px_size_m, x_m, Nfft, df_cpm, Df_cpm
37
+ """
38
+ dx_m = px_size_m
39
+ Dx_m = img_size_m
40
+ x_m = np.linspace(-Dx_m / 2, Dx_m / 2, int(Dx_m / dx_m) + 1)
41
+ f_sample = 1 / (x_m[1] - x_m[0])
42
+ Nfft = len(x_m)
43
+ df_cpm = f_sample / Nfft
44
+ f_cpm = np.linspace(0, f_sample - df_cpm, Nfft) - (
45
+ f_sample - np.mod(Nfft, 2) * df_cpm
46
+ ) / 2
47
+ df_cpm = f_cpm[1] - f_cpm[0]
48
+ Df_cpm = f_cpm[-1] - f_cpm[0]
49
+ return dx_m, Dx_m, f_cpm, px_size_m, x_m, Nfft, df_cpm, Df_cpm
@@ -0,0 +1,69 @@
1
+ import numpy as np
2
+
3
+ from .fourier import ft, fs
4
+
5
+
6
+ def propTF(E_in, L_m, lambda_m, z_m):
7
+ """
8
+ Angular-spectrum (transfer-function) Fresnel propagation — square window.
9
+
10
+ Parameters
11
+ ----------
12
+ E_in : 2D array
13
+ Input complex field.
14
+ L_m : float
15
+ Full side length of the square window in metres.
16
+ lambda_m : float
17
+ Wavelength in metres.
18
+ z_m : float
19
+ Propagation distance in metres.
20
+
21
+ Returns
22
+ -------
23
+ E_out : 2D array
24
+ Output complex field at distance z_m.
25
+ """
26
+ Nx, Ny = np.shape(E_in)
27
+ dx = L_m / Nx
28
+
29
+ fx = fs(np.arange(Nx) * dx)
30
+ fy = fs(np.arange(Ny) * dx) if Ny > 2 else np.zeros(1)
31
+
32
+ FX, FY = np.meshgrid(fx, fy)
33
+ H = np.exp(-1j * np.pi * lambda_m * z_m * (FX**2 + FY**2))
34
+
35
+ return ft(ft(E_in) * H)
36
+
37
+
38
+ def propTF2(E_in, Lx_m, Ly_m, lambda_m, z_m):
39
+ """
40
+ Angular-spectrum Fresnel propagation — rectangular window.
41
+
42
+ Parameters
43
+ ----------
44
+ E_in : 2D array (Ny, Nx)
45
+ Input complex field.
46
+ Lx_m, Ly_m : float
47
+ Physical window sizes in x and y (metres).
48
+ lambda_m : float
49
+ Wavelength in metres.
50
+ z_m : float
51
+ Propagation distance in metres.
52
+
53
+ Returns
54
+ -------
55
+ E_out : 2D array
56
+ Output complex field at distance z_m.
57
+ """
58
+ Ny, Nx = E_in.shape
59
+ dx = Lx_m / Nx
60
+ dy = Ly_m / Ny
61
+
62
+ fx = np.fft.fftshift(np.fft.fftfreq(Nx, d=dx))
63
+ fy = np.fft.fftshift(np.fft.fftfreq(Ny, d=dy))
64
+ FX, FY = np.meshgrid(fx, fy)
65
+
66
+ H = np.exp(-1j * np.pi * lambda_m * z_m * (FX**2 + FY**2))
67
+
68
+ Uin = np.fft.fft2(np.fft.fftshift(E_in))
69
+ return np.fft.ifftshift(np.fft.ifft2(H * Uin))
@@ -0,0 +1,30 @@
1
+ Metadata-Version: 2.4
2
+ Name: topolino
3
+ Version: 0.1.0
4
+ Summary: Fourier optics and wave propagation utilities
5
+ Author-email: Rachel Migdal <rmigdal2007@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Repository, https://github.com/dream-beam/Topolino
8
+ Keywords: fourier optics,wave propagation,physics,optics
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Topic :: Scientific/Engineering :: Physics
13
+ Requires-Python: >=3.10
14
+ Description-Content-Type: text/markdown
15
+ License-File: LICENSE
16
+ Requires-Dist: numpy
17
+ Requires-Dist: scikit-image
18
+ Provides-Extra: dev
19
+ Requires-Dist: jupyter; extra == "dev"
20
+ Requires-Dist: matplotlib; extra == "dev"
21
+ Dynamic: license-file
22
+
23
+ # Topolino
24
+ ramigdal@lbl.gov, awojdyla@lbl.gov
25
+ ![Topolino](assets/topolino_logo.png)
26
+
27
+ This repository is a Python toolkit for exploring paraxial wave propagation and related optical phenomena. At its core is a Fresnel propagator `propTF` that uses NumPy's FFT to propagate a complex field through space. The package includes routines for generating Gaussian beams, extracting the RMS beam radius from intensity moments, and directly comparing the numerical propagation to the analytical Gaussian‑beam law.
28
+ A collection of Jupyter notebooks demonstrates a range of topics: a thin‑lens model, creation and propagation of spiral beams, diffraction patterns of transmission gratings, and a full grating‑experiment simulation that includes a light source, propagation to a grating, and observation of resulting orders. The notebooks expose parameters (wavelength , aperture size, grating period, vortex charge, ...), visualize results with 1‑D plots, RMS‑size versus distance curves, and 2‑D intensity maps, and provide side‑by‑side comparisons with analytical predictions where available.
29
+
30
+ ![Propagation](assets/propagation.png)
@@ -0,0 +1,13 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ topolino/__init__.py
5
+ topolino/analysis.py
6
+ topolino/beam.py
7
+ topolino/fourier.py
8
+ topolino/propagation.py
9
+ topolino.egg-info/PKG-INFO
10
+ topolino.egg-info/SOURCES.txt
11
+ topolino.egg-info/dependency_links.txt
12
+ topolino.egg-info/requires.txt
13
+ topolino.egg-info/top_level.txt
@@ -0,0 +1,6 @@
1
+ numpy
2
+ scikit-image
3
+
4
+ [dev]
5
+ jupyter
6
+ matplotlib
@@ -0,0 +1 @@
1
+ topolino