Source code for pylorenzmie.theory.Dimer
from pylorenzmie.theory.Cluster import Cluster
from pylorenzmie.theory.Sphere import Sphere
from pylorenzmie.lib.lmtypes import Properties
from dataclasses import dataclass
import numpy as np
[docs]
@dataclass
class Dimer(Cluster):
'''A touching pair of identical spheres for Lorenz-Mie microscopy.
Positions two :class:`~pylorenzmie.theory.Sphere` objects symmetrically
about the cluster center, separated by twice the sphere radius.
Orientation is specified as elevation and azimuthal angles.
Inherits from :class:`~pylorenzmie.theory.Cluster`.
Parameters
----------
a_p : float, optional
Radius of each sphere [μm]. Default: 0.75.
n_p : float, optional
Refractive index of each sphere. Default: 1.45.
k_p : float, optional
Imaginary part of the refractive index. Default: 0.
theta : float, optional
Elevation angle of the dimer axis above the xy-plane [rad].
``theta = 0`` → axis in the xy-plane; ``theta = pi/2`` → axis
along z. Default: pi/4.
phi : float, optional
Azimuthal angle of the dimer axis in the xy-plane [rad].
Default: 0.
magnification : float, optional
Instrument magnification [μm/pixel], used to convert the sphere
radius to a pixel-space separation. Default: 0.048.
'''
a_p: float = 0.75
n_p: float = 1.45
k_p: float = 0.
theta: float = np.pi / 4.
phi: float = 0.
magnification: float = 0.048
def __post_init__(self) -> None:
p = dict(a_p=self.a_p, n_p=self.n_p, k_p=self.k_p)
self.particles = [Sphere(**p), Sphere(**p)]
self.update_positions()
def __setattr__(self, key: str, value: object) -> None:
super().__setattr__(key, value)
if key in ('a_p', 'n_p', 'k_p'):
for p in self.particles:
setattr(p, key, value)
if key in ('a_p', 'theta', 'phi', 'magnification'):
self.update_positions()
@Cluster.properties.getter
def properties(self) -> Properties:
return {'x_p': self.x_p, 'y_p': self.y_p, 'z_p': self.z_p,
'a_p': self.a_p, 'n_p': self.n_p, 'k_p': self.k_p,
'theta': self.theta, 'phi': self.phi}
[docs]
def update_positions(self) -> None:
'''Set sphere positions from current orientation and radius.
Places each sphere at ±(a_p / magnification) pixels from the
cluster center along the dimer axis.
'''
if len(self.particles) != 2:
return
axis = np.array([np.cos(self.theta) * np.cos(self.phi),
np.cos(self.theta) * np.sin(self.phi),
np.sin(self.theta)])
offset = (self.a_p / self.magnification) * axis
self.particles[0].r_p = offset
self.particles[1].r_p = -offset
[docs]
@classmethod
def example(cls) -> None: # pragma: no cover
from pylorenzmie.theory import Instrument, LorenzMie
import matplotlib.pyplot as plt
shape = (301, 301)
coordinates = LorenzMie.meshgrid(shape)
instrument = Instrument()
instrument.magnification = 0.048
instrument.numerical_aperture = 1.45
instrument.wavelength = 0.447
instrument.n_m = 1.340
dimer = cls(magnification=instrument.magnification)
dimer.a_p = 0.5
dimer.n_p = 1.42
dimer.r_p = [150., 150., 250.]
dimer.theta = np.pi / 4.
dimer.phi = np.pi / 4.
model = LorenzMie(coordinates=coordinates,
particle=dimer,
instrument=instrument)
plt.imshow(model.hologram().reshape(shape), cmap='gray')
plt.show()
if __name__ == '__main__': # pragma: no cover
Dimer.example()