prtools 2.0.0__tar.gz → 2.0.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.
- {prtools-2.0.0/prtools.egg-info → prtools-2.0.1}/PKG-INFO +1 -1
- {prtools-2.0.0 → prtools-2.0.1}/prtools/__init__.py +2 -1
- {prtools-2.0.0 → prtools-2.0.1}/prtools/shape.py +62 -4
- {prtools-2.0.0 → prtools-2.0.1}/prtools/zernike.py +14 -12
- {prtools-2.0.0 → prtools-2.0.1/prtools.egg-info}/PKG-INFO +1 -1
- {prtools-2.0.0 → prtools-2.0.1}/LICENSE +0 -0
- {prtools-2.0.0 → prtools-2.0.1}/NOTICE +0 -0
- {prtools-2.0.0 → prtools-2.0.1}/README.rst +0 -0
- {prtools-2.0.0 → prtools-2.0.1}/prtools/_array_api.py +0 -0
- {prtools-2.0.0 → prtools-2.0.1}/prtools/array.py +0 -0
- {prtools-2.0.0 → prtools-2.0.1}/prtools/convolve.py +0 -0
- {prtools-2.0.0 → prtools-2.0.1}/prtools/cost.py +0 -0
- {prtools-2.0.0 → prtools-2.0.1}/prtools/fourier.py +0 -0
- {prtools-2.0.0 → prtools-2.0.1}/prtools/jax.py +0 -0
- {prtools-2.0.0 → prtools-2.0.1}/prtools/misc.py +0 -0
- {prtools-2.0.0 → prtools-2.0.1}/prtools/morphology.py +0 -0
- {prtools-2.0.0 → prtools-2.0.1}/prtools/segmented.py +0 -0
- {prtools-2.0.0 → prtools-2.0.1}/prtools/sparse.py +0 -0
- {prtools-2.0.0 → prtools-2.0.1}/prtools/stats.py +0 -0
- {prtools-2.0.0 → prtools-2.0.1}/prtools.egg-info/SOURCES.txt +0 -0
- {prtools-2.0.0 → prtools-2.0.1}/prtools.egg-info/dependency_links.txt +0 -0
- {prtools-2.0.0 → prtools-2.0.1}/prtools.egg-info/requires.txt +0 -0
- {prtools-2.0.0 → prtools-2.0.1}/prtools.egg-info/top_level.txt +0 -0
- {prtools-2.0.0 → prtools-2.0.1}/pyproject.toml +0 -0
- {prtools-2.0.0 → prtools-2.0.1}/setup.cfg +0 -0
- {prtools-2.0.0 → prtools-2.0.1}/tests/test_array.py +0 -0
- {prtools-2.0.0 → prtools-2.0.1}/tests/test_convolve.py +0 -0
- {prtools-2.0.0 → prtools-2.0.1}/tests/test_fourier.py +0 -0
- {prtools-2.0.0 → prtools-2.0.1}/tests/test_jax.py +0 -0
|
@@ -219,6 +219,68 @@ def rectangle(shape, width, height, shift=(0, 0), angle=0, antialias=True,
|
|
|
219
219
|
return rect
|
|
220
220
|
|
|
221
221
|
|
|
222
|
+
def ellipse(shape, xradius, yradius, shift=(0,0), angle=0, antialias=True,
|
|
223
|
+
indexing='ij'):
|
|
224
|
+
"""Draw an ellipse
|
|
225
|
+
|
|
226
|
+
Parameters
|
|
227
|
+
----------
|
|
228
|
+
shape : array_like
|
|
229
|
+
Size of output in pixels (nrows, ncols)
|
|
230
|
+
xradius : float
|
|
231
|
+
Semi-axis of the ellipse in pixels in the x (horizontal) direction.
|
|
232
|
+
yradius : float
|
|
233
|
+
Semi-axis of the ellipse in pixels in the y (vertical) direction.
|
|
234
|
+
shift : (2,) array_like, optional
|
|
235
|
+
How far to shift center in float (rows, cols). Default is (0, 0).
|
|
236
|
+
angle : float, optional
|
|
237
|
+
Rotation of the ellipse in degrees counterclockwise from horizontal.
|
|
238
|
+
Default is 0.
|
|
239
|
+
antialias : bool, optional
|
|
240
|
+
If True (default), the shape edges are antialiased.
|
|
241
|
+
indexing : {'ij', 'xy'}, optional
|
|
242
|
+
Matrix ('ij', default) or cartesian ('xy') indexing of output.
|
|
243
|
+
|
|
244
|
+
Returns
|
|
245
|
+
-------
|
|
246
|
+
ndarray
|
|
247
|
+
|
|
248
|
+
Examples
|
|
249
|
+
--------
|
|
250
|
+
.. plot::
|
|
251
|
+
:include-source:
|
|
252
|
+
:context: reset
|
|
253
|
+
:scale: 50
|
|
254
|
+
|
|
255
|
+
>>> ell = prtools.ellipse(shape=(256, 256), xradius=100, yradius=50)
|
|
256
|
+
>>> plt.imshow(ell, cmap='gray')
|
|
257
|
+
|
|
258
|
+
.. plot::
|
|
259
|
+
:include-source:
|
|
260
|
+
:context: reset
|
|
261
|
+
:scale: 50
|
|
262
|
+
|
|
263
|
+
>>> ell = prtools.ellipse(shape=(256, 256), xradius=100, yradius=50, angle=30)
|
|
264
|
+
>>> plt.imshow(ell, cmap='gray')
|
|
265
|
+
|
|
266
|
+
"""
|
|
267
|
+
a, b = yradius, xradius
|
|
268
|
+
rr, cc = mesh(shape, shift, angle, indexing=indexing)
|
|
269
|
+
|
|
270
|
+
rho = np.sqrt((rr / a)**2 + (cc / b)**2)
|
|
271
|
+
grad = np.sqrt((rr / a**2)**2 + (cc / b**2)**2)
|
|
272
|
+
|
|
273
|
+
with np.errstate(divide='ignore', invalid='ignore'):
|
|
274
|
+
dist = (1 - rho) * rho / grad
|
|
275
|
+
dist = np.where(grad == 0, 1.0, dist) # center is always interior
|
|
276
|
+
ell = np.clip(dist + 0.5, 0.0, 1.0)
|
|
277
|
+
|
|
278
|
+
if not antialias:
|
|
279
|
+
ell[ell > 0] = 1
|
|
280
|
+
|
|
281
|
+
return ell
|
|
282
|
+
|
|
283
|
+
|
|
222
284
|
def spider(shape, width, angle=0, shift=(0, 0), antialias=True, indexing='ij'):
|
|
223
285
|
"""Draw a spider
|
|
224
286
|
|
|
@@ -261,10 +323,6 @@ def spider(shape, width, angle=0, shift=(0, 0), antialias=True, indexing='ij'):
|
|
|
261
323
|
return 1 - rectangle(shape, len, width, shift, angle, antialias, indexing)
|
|
262
324
|
|
|
263
325
|
|
|
264
|
-
def ellipse():
|
|
265
|
-
pass
|
|
266
|
-
|
|
267
|
-
|
|
268
326
|
def gauss(shape, sigma, shift=(0, 0), indexing='ij'):
|
|
269
327
|
"""Generate a 2D Gaussian function.
|
|
270
328
|
|
|
@@ -14,7 +14,7 @@ def zernike(mask, index, normalize=True, order='noll', rho=None, theta=None):
|
|
|
14
14
|
Binary mask defining the extent to compute the Zernike polynomial
|
|
15
15
|
over.
|
|
16
16
|
index : int
|
|
17
|
-
|
|
17
|
+
Zernike mode index
|
|
18
18
|
normalize : bool, optional
|
|
19
19
|
If True (default), the output is normalized according to [1]. If False,
|
|
20
20
|
the output value ranges [-1, 1] over the mask.
|
|
@@ -112,8 +112,8 @@ def zernike_compose(mask, coeffs, normalize=True, order='noll', rho=None, theta=
|
|
|
112
112
|
mask : array_like
|
|
113
113
|
Binary mask defining the extent to compute the Zernike polynomial over.
|
|
114
114
|
coeffs : array_like
|
|
115
|
-
List of coefficients corresponding to Zernike indices
|
|
116
|
-
|
|
115
|
+
List of coefficients corresponding to Zernike indices used to create
|
|
116
|
+
the OPD.
|
|
117
117
|
normalize : bool, optional
|
|
118
118
|
If True (default), the output is normalized according to [1]. If False,
|
|
119
119
|
the output value ranges [-1, 1] over the mask.
|
|
@@ -177,7 +177,7 @@ def zernike_basis(mask, modes, vectorize=False, normalize=True, order='noll',
|
|
|
177
177
|
mask : array_like
|
|
178
178
|
Binary mask defining the extent to compute the Zernike polynomial over.
|
|
179
179
|
modes : array_like
|
|
180
|
-
List of modes
|
|
180
|
+
List of modes to return.
|
|
181
181
|
vectorize : bool, optional
|
|
182
182
|
If True, the output is returned as a
|
|
183
183
|
``(length(modes), modes.shape[0]*modes.shape[1])`` array If False
|
|
@@ -228,11 +228,11 @@ def zernike_fit(opd, mask, modes, normalize=True, order='noll', rho=None,
|
|
|
228
228
|
Parameters
|
|
229
229
|
----------
|
|
230
230
|
opd : array_like
|
|
231
|
-
OPD to fit.
|
|
231
|
+
OPD to fit. NaN values in ``opd`` are excluded from the fit.
|
|
232
232
|
mask : array_like
|
|
233
233
|
Binary mask defining the extent to compute the Zernike basis over.
|
|
234
234
|
modes : array_like
|
|
235
|
-
List of modes
|
|
235
|
+
List of modes to fit.
|
|
236
236
|
normalize : bool, optional
|
|
237
237
|
If True (default), the output is normalized according to [1]. If False,
|
|
238
238
|
the output value ranges [-1, 1] over the mask.
|
|
@@ -271,14 +271,16 @@ def zernike_fit(opd, mask, modes, normalize=True, order='noll', rho=None,
|
|
|
271
271
|
[1] Noll, RJ. Zernike polynomials and atmospheric turbulence. J Opt Soc Am 66, 207-211 (1976).
|
|
272
272
|
|
|
273
273
|
"""
|
|
274
|
-
opd = np.asarray(opd)
|
|
274
|
+
opd = np.asarray(opd).ravel()
|
|
275
275
|
mask = np.asarray(mask)
|
|
276
|
-
|
|
277
276
|
basis = zernike_basis(mask, modes, True, normalize, order, rho, theta)
|
|
277
|
+
|
|
278
|
+
# valid data includes all non-NaN values inside the mask
|
|
279
|
+
valid = np.isfinite(opd) & mask.ravel().astype(bool)
|
|
280
|
+
|
|
281
|
+
coeff, *_ = np.linalg.lstsq(basis[:, valid].T, opd[valid], rcond=None)
|
|
278
282
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
return np.einsum('ij,i->j', basis, opd.ravel())
|
|
283
|
+
return coeff
|
|
282
284
|
|
|
283
285
|
|
|
284
286
|
def zernike_remove(opd, mask, modes, order='noll', rho=None, theta=None):
|
|
@@ -291,7 +293,7 @@ def zernike_remove(opd, mask, modes, order='noll', rho=None, theta=None):
|
|
|
291
293
|
mask : array_like
|
|
292
294
|
Binary mask defining the extent to compute the Zernike basis over.
|
|
293
295
|
modes : array_like
|
|
294
|
-
List of modes
|
|
296
|
+
List of modes to remove.
|
|
295
297
|
order : {'noll', 'fringe', 'ansi'}, optional
|
|
296
298
|
Zernike ordering scheme. Default is 'noll'.
|
|
297
299
|
rho : array_like, optional
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|