@@ -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} = \a lpha P_{0} + (1 - \a lpha) \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+
357413if __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