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.
Files changed (29) hide show
  1. {prtools-2.0.0/prtools.egg-info → prtools-2.0.1}/PKG-INFO +1 -1
  2. {prtools-2.0.0 → prtools-2.0.1}/prtools/__init__.py +2 -1
  3. {prtools-2.0.0 → prtools-2.0.1}/prtools/shape.py +62 -4
  4. {prtools-2.0.0 → prtools-2.0.1}/prtools/zernike.py +14 -12
  5. {prtools-2.0.0 → prtools-2.0.1/prtools.egg-info}/PKG-INFO +1 -1
  6. {prtools-2.0.0 → prtools-2.0.1}/LICENSE +0 -0
  7. {prtools-2.0.0 → prtools-2.0.1}/NOTICE +0 -0
  8. {prtools-2.0.0 → prtools-2.0.1}/README.rst +0 -0
  9. {prtools-2.0.0 → prtools-2.0.1}/prtools/_array_api.py +0 -0
  10. {prtools-2.0.0 → prtools-2.0.1}/prtools/array.py +0 -0
  11. {prtools-2.0.0 → prtools-2.0.1}/prtools/convolve.py +0 -0
  12. {prtools-2.0.0 → prtools-2.0.1}/prtools/cost.py +0 -0
  13. {prtools-2.0.0 → prtools-2.0.1}/prtools/fourier.py +0 -0
  14. {prtools-2.0.0 → prtools-2.0.1}/prtools/jax.py +0 -0
  15. {prtools-2.0.0 → prtools-2.0.1}/prtools/misc.py +0 -0
  16. {prtools-2.0.0 → prtools-2.0.1}/prtools/morphology.py +0 -0
  17. {prtools-2.0.0 → prtools-2.0.1}/prtools/segmented.py +0 -0
  18. {prtools-2.0.0 → prtools-2.0.1}/prtools/sparse.py +0 -0
  19. {prtools-2.0.0 → prtools-2.0.1}/prtools/stats.py +0 -0
  20. {prtools-2.0.0 → prtools-2.0.1}/prtools.egg-info/SOURCES.txt +0 -0
  21. {prtools-2.0.0 → prtools-2.0.1}/prtools.egg-info/dependency_links.txt +0 -0
  22. {prtools-2.0.0 → prtools-2.0.1}/prtools.egg-info/requires.txt +0 -0
  23. {prtools-2.0.0 → prtools-2.0.1}/prtools.egg-info/top_level.txt +0 -0
  24. {prtools-2.0.0 → prtools-2.0.1}/pyproject.toml +0 -0
  25. {prtools-2.0.0 → prtools-2.0.1}/setup.cfg +0 -0
  26. {prtools-2.0.0 → prtools-2.0.1}/tests/test_array.py +0 -0
  27. {prtools-2.0.0 → prtools-2.0.1}/tests/test_convolve.py +0 -0
  28. {prtools-2.0.0 → prtools-2.0.1}/tests/test_fourier.py +0 -0
  29. {prtools-2.0.0 → prtools-2.0.1}/tests/test_jax.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: prtools
3
- Version: 2.0.0
3
+ Version: 2.0.1
4
4
  Summary: Utility functions for image-based phase retrieval
5
5
  Author: Andy Kee
6
6
  License: MIT License
@@ -1,4 +1,4 @@
1
- __version__ = '2.0.0'
1
+ __version__ = '2.0.1'
2
2
 
3
3
 
4
4
  from prtools._array_api import use
@@ -55,6 +55,7 @@ from prtools.shape import (
55
55
  circle,
56
56
  hexagon,
57
57
  rectangle,
58
+ ellipse,
58
59
  spider,
59
60
  sin,
60
61
  waffle
@@ -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
- Noll Zernike index as defined in [1]
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 (Noll ordering)
116
- used to create the OPD.
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 (Noll ordering) to return.
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 (Noll ordering) to fit.
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
- basis = np.linalg.pinv(basis)
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 (Noll ordering) to remove.
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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: prtools
3
- Version: 2.0.0
3
+ Version: 2.0.1
4
4
  Summary: Utility functions for image-based phase retrieval
5
5
  Author: Andy Kee
6
6
  License: MIT License
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