
Research
/Security News
Critical Vulnerability in NestJS Devtools: Localhost RCE via Sandbox Escape
A flawed sandbox in @nestjs/devtools-integration lets attackers run code on your machine via CSRF, leading to full Remote Code Execution (RCE).
Calculation of real Zernike polynomials values, associated PSFs, plotting of their profiles in polar coordinates
This project is designed to compute the parameters, real values, and properties of Zernike polynomials using both exact (analytical) and recursive equations.
The recursive and tabular equations, along with essential reference information, are sourced from the following articles: [1],
[2] and [3].
The possibly useful functionality for further usage include: conversion between common indexing schemes (OSA / Noll / Fringe), radial / angular / polynomial
real values calculation along with their derivatives, plotting the circular 2D or 3D profile of single or sum of polynomials, fitting the arbitrary phase
profile specified on the circle aperture by the set of polynomials (see the description below).
For the complete list of implemented methods for Zernike polynomial, please refer to ZernPol API documentation.
For the implemented 2D PSF calculation as the class, please refer to ZernPol API documentation.
Note: if you're viewing this README on the PyPI website, images will not be displayed - only fallback descriptions will be shown. For the complete and correctly formatted README, please visit the GitHub repository.
It was supposed at the project start, that the recursive equations would be the faster way to calculate real values of high order polynomials in comparison
to usage of their exact definition (that used the sum of factorials, see the Wiki article for details).
However, it's turned out during the development and tests, that sum of factorials computation (based on Python built-in math.factorial method) even for high
orders (> 10th order) provides sufficiently fast calculation of radial polynomials.
On other hand, I found that for polynomials with radial orders higher than 46th order the exact equation with factorials starts providing ambiguous results
due to the big integer coefficients (exceeding the size of Python built-in int type) produced by factorials. Thus, it turns out that the stable way to get
polynomial (radial) values for these orders is to use the recursive equations for retain stability of calculation along with the drawback of fast
decreasing of the computational performance with the increased radial order.
For installation of this package, use the command: pip install zernpy
For updating already installed package: pip install --upgrade zernpy or pip install -U zernpy
For installation, the numpy and matplotlib libraries are required.
For running tests, the pytest library is required for automatic recognition of tests stored in package folders.
Simply run the command pytest in the command line from the project folder root. It should collect 10 tests and automatically run them.
The useful calculation methods are written as the instance and static methods. The first ones are accessible after initialization of a class instance by providing characteristic orders (see the Zernike polynomial definition, e.g. in Wiki):
from zernpy import ZernPol
zp = ZernPol(m=-2, n=2)
Alternative initializations using other indices: ZernPol(osa_index=3), ZernPol(noll_index=5), ZernPol(fringe_index=6)
For details, please, refer to the API Dictionary provided on the GitHub page (see "Documentation" tab on pypi).
Random generated set of Zernike polynomials plotted on an image - as the sample for testing the fitting procedure:
This image is assumed to contain phases wrapped in a circular aperture, used function for generation: generate_random_phases(...) from the main zernikepol module.
Below is profile made by calculation of fitted Zernike polynomials:
The function used for fitting: fit_polynomials(...) from the main zernikepol module.
This function could be useful for making approximation of any image containing phases recorded by the optical system
to the sum of Zernike polynomials. Check the detailed description of functions in the API dictionary, available on
the separate tab on the GitHub page of this repository.
The function fit_polynomials_vectors(...) allows to fit composed in vectors (arrays with single dimension) phases
recorded in polar coordinates (provided separately also in vectors) to the provided set of Zernike polynomials. This is analogous
to the procedure described above, but this function doesn't perform any cropping or phases pre-selection.
Import statement for using the scripts the mentioned functions:
from zernpy import generate_polynomials, fit_polynomials, generate_random_phases, generate_phases_image, fit_polynomials_vectors
Or for importing all available functions and base class in one statement:
from zernpy import *
Note that the function generate_polynomials(...) returns tuple with OSA indexed polynomials as instances of the ZernPol class, starting from the 'Piston' polynomial.
The 2D PSF kernel is calculated from the diffraction integral over the round pupil plane and described as Zernike polynomial phase distribution for the focal point (no Z-axis dependency). The used references are listed in the docstring of the calculate_psf_kernel() method.
The sample of calculated PSF for Vertical Trefoil:
Initialization and usage of the class instance (basic usage with default calculation parameters, such as the kernel size):
from zernpy import ZernPSF, ZernPol
zpsf = ZernPSF(ZernPol(m=1, n=3)) # horizontal coma
NA = 0.95; wavelength = 0.55; expansion_coeff = -0.26; pixel_physical_size = 0.2*wavelength # example of physical properties
zpsf.set_physical_properties(NA, wavelength, expansion_coeff, pixel_physical_size) # provide physical properties of the system
kernel = zpsf.calculate_psf_kernel(normalized=True) # get the kernel as the square normalized matrix
Check the API documentation for other available methods.
Similarly to the code above, it's possible to calculate the PSF associated with the sum profile of several polynomials:
from zernpy import ZernPSF, ZernPol
zp1 = ZernPol(m=-1, n=3); zp2 = ZernPol(m=2, n=4); zp3 = ZernPol(m=0, n=4); pols = (zp1, zp2, zp3); coeffs = (0.5, 0.21, 0.15)
zpsf_pic = ZernPSF(pols); zpsf_pic.set_physical_props(NA=0.65, wavelength=0.6, expansion_coeff=coeffs, pixel_physical_size=0.6/5.0)
zpsf_pic.calculate_psf_kernel(); zpsf_pic.plot_kernel("Sum of Polynomials Profile")
The resulting profile is:
It's possible to accelerate the calculation of a kernel by installing the numba library in the same Python environment and providing the appropriate flags in a calculation method, similar to the following code snippet:
from zernpy import force_get_psf_compilation, ZernPol, ZernPSF
force_get_psf_compilation() # optional precompilation of calculation methods for further using of their compiled forms
NA = 0.95; wavelength = 0.55; pixel_size = wavelength / 4.6; ampl = -0.16
zp = ZernPol(m=0, n=2); zpsf = ZernPSF(zp)
zpsf.set_physical_props(NA, wavelength, ampl, pixel_size)
zpsf.calculate_psf_kernel(accelerated=True)
By default, the kernel size is overestimated to guarantee that all significant points of kernel will be calculated. Also, kernel size is growing with the polynomial orders and its amplitude. To reduce the size of kernel, from ver. 0.0.15, it's possible to call the method crop_kernel. Example of the code:
from zernpy import ZernPSF, ZernPol
zpsf = ZernPSF(zernpol=(ZernPol(m=0, n=4))) # Spherical aberration
zpsf.set_physical_props(NA=1.25, wavelength=0.5, expansion_coeff=0.47, pixel_physical_size=0.5/5.0)
zpsf.calculate_psf_kernel(accelerated=True, verbose_info=True); zpsf.plot_kernel("Not Cropped")
zpsf.crop_kernel(min_part_of_max=0.025) # rows and columns containing less than 2.5% of kernel max will be cropped out
zpsf.plot_kernel("Cropped")
Original kernel with size (23, 23) for Spherical aberration:
Cropped kernel with size (15, 15) for Spherical aberration:
FAQs
Calculation of real Zernike polynomials values, associated PSFs, plotting of their profiles in polar coordinates
We found that zernpy demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
/Security News
A flawed sandbox in @nestjs/devtools-integration lets attackers run code on your machine via CSRF, leading to full Remote Code Execution (RCE).
Product
Customize license detection with Socket’s new license overlays: gain control, reduce noise, and handle edge cases with precision.
Product
Socket now supports Rust and Cargo, offering package search for all users and experimental SBOM generation for enterprise projects.