Skip to content

Commit 0270db6

Browse files
committed
NEW: Implement an OPR function
1 parent 9517882 commit 0270db6

File tree

1 file changed

+62
-0
lines changed

1 file changed

+62
-0
lines changed

src/tike/ptycho/probe.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,9 +354,71 @@ def gaussian(size, rin=0.8, rout=1.0):
354354
return img
355355

356356

357+
def opr(probe, n, alpha=0.5, S=None, U=None):
358+
"""Regularize multiple probes with orthogonal probe relaxation (OPR).
359+
360+
Corrects for variable illumination across scan positions by regularizing
361+
the probe at each position with the first `n` principal components of
362+
the probes at all positions.
363+
364+
The probes are regularized using a weighted sum as below:
365+
366+
.. math::
367+
$$P_{1} = \alpha P_{0} + (1 - \alpha) \sum_{c=0}^{n}P_0^c$$
368+
369+
where `alpha` is the weighting paramters which determines the relative
370+
importance of the regulariation.
371+
372+
Parameters
373+
----------
374+
probe : (..., nscan // fly, fly, nmodes, probe_shape, probe_shape) complex64
375+
A bunch of probes that need to be regularized.
376+
n : int
377+
The number of components to use for regularization.
378+
379+
Returns
380+
-------
381+
The regularized probes.
382+
383+
References
384+
----------
385+
Odstrcil, M., P. Baksh, S. A. Boden, R. Card, J. E. Chad, J. G. Frey, and
386+
W. S. Brocklesby. 2016. “Ptychographic Coherent Diffractive Imaging with
387+
Orthogonal Probe Relaxation.” Optics Express.
388+
https://doi.org/10.1364/oe.24.008360.
389+
390+
"""
391+
# Flatten the last dimension of the probe and move incoherent mode
392+
# dimension so the position dimensions are in the last two dimensions
393+
probe = cp.moveaxis(probe, -3, 1)
394+
shape = probe.shape
395+
probe = probe.reshape(
396+
-1,
397+
probe.shape[-4] * probe.shape[-3], # scan positions
398+
probe.shape[-2] * probe.shape[-1], # probe dimensions
399+
)
400+
assert probe.shape[-2] > n, 'There cannot be more modes than positions.'
401+
402+
S, U = pca_eig(probe, k=n)
403+
compressed_probe = probe @ U @ U.conj().swapaxes(-1, -2)
404+
compressed_probe /= cp.linalg.norm(compressed_probe, axis=-1, keepdims=True)
405+
compressed_probe *= cp.linalg.norm(probe, axis=-1, keepdims=True)
406+
reg_probe = alpha * probe + (1 - alpha) * compressed_probe
407+
408+
reg_probe = reg_probe.reshape(*shape)
409+
reg_probe = cp.moveaxis(reg_probe, 1, -3)
410+
return reg_probe, S, U
411+
412+
357413
if __name__ == "__main__":
358414
cp.random.seed(0)
359415
x = (cp.random.rand(7, 1, 9, 3, 3) +
360416
1j * cp.random.rand(7, 1, 9, 3, 3)).astype('complex64')
361417
x1 = orthogonalize_eig(x)
362418
assert x1.shape == x.shape, x1.shape
419+
420+
probe_shape = (1, 52, 3, 5, 8, 8)
421+
probe = cp.random.rand(*probe_shape) + 1j * cp.random.rand(*probe_shape)
422+
probe = probe.astype('complex64')
423+
reg_probes = opr(probe, n=7)
424+
assert reg_probes.shape == probe_shape

0 commit comments

Comments
 (0)