Source code for pylorenzmie.theory.Aberrated

from pylorenzmie.theory.LorenzMie import LorenzMie
from pylorenzmie.theory.Particle import Particle
from pylorenzmie.lib.types import Coordinates, Field, Properties
import numpy as np


[docs] def Aberrated(base_class: type) -> type: '''Return an aberrated subclass of a LorenzMie calculator. The returned class extends :meth:`scattered_field` to multiply the scattered field by a Zernike spherical-aberration phase mask evaluated at the pupil plane. Parameters ---------- base_class : type A :class:`~pylorenzmie.theory.LorenzMie` subclass to extend. Returns ------- AberratedLorenzMie : type New class inheriting from *base_class*. ''' class AberratedLorenzMie(base_class): '''LorenzMie subclass with Zernike spherical aberration. Inherits from the base class supplied to :func:`Aberrated`. Parameters ---------- spherical : float, optional Zernike spherical-aberration coefficient [waves]. Default: 0 (no aberration). ''' def __init__(self, *args, spherical: float = 0., **kwargs) -> None: super().__init__(*args, **kwargs) self.spherical = spherical @LorenzMie.properties.getter def properties(self) -> Properties: return {**super().properties, 'spherical': self.spherical} def _aperture(self, z_p: float) -> float: NA = self.instrument.numerical_aperture n_m = self.instrument.n_m return 2. * NA * z_p / n_m def _aberration(self, r_p: Coordinates) -> Field: '''Zernike spherical-aberration phase mask for particle at r_p.''' omega = self._aperture(r_p[2]) if omega == 0. or self.spherical == 0.: return 1. x = (self.coordinates[0] - r_p[0]) / omega y = (self.coordinates[1] - r_p[1]) / omega rhosq = x * x + y * y phase = 6. * rhosq * (rhosq - 1.) + 1. phase *= -self.spherical return np.exp(1j * phase) def scattered_field(self, particle: Particle, **kwargs) -> Field: '''Scattered field including spherical aberration.''' field = super().scattered_field(particle, **kwargs) r_p = particle.r_p + particle.r_0 return field * self._aberration(r_p) return AberratedLorenzMie
AberratedLorenzMie = Aberrated(LorenzMie) if __name__ == '__main__': # pragma: no cover AberratedLorenzMie.example(spherical=0.9)