def test_transforms_correctly_with_polarization_rotation(self): # We test that rotating the lab frame correctly rotates # the polarization. # If we rotate (x0, y0) -> (y1, -x1), then the polarization # in the new coordinates should be # E1x = E0y, E1y = -E1x scatterer = sphere medium_wavevec = 2 * np.pi / wavelen medium_index = index theory = MieLens() krho = np.linspace(0, 100, 11) phi_0 = 0 * krho + np.pi / 180.0 # a small component along y phi_1 = phi_0 - np.pi / 2 kz = np.full_like(krho, 20.0) pol_0 = xr.DataArray([1.0, 0, 0]) pos_0 = np.array([krho, phi_0, kz]) pol_1 = xr.DataArray([0, -1.0, 0]) pos_1 = np.array([krho, phi_1, kz]) args = (scatterer, medium_wavevec, medium_index) fields_0 = theory._raw_fields(pos_0, *args, pol_0) fields_1 = theory._raw_fields(pos_1, *args, pol_1) self.assertTrue(np.allclose(fields_1[0], fields_0[1], **TOLS)) self.assertTrue(np.allclose(fields_1[1], -fields_0[0], **TOLS))
def _get_theory_and_scaling(self, params): if self.theory == 'mielens': theory = MieLens(lens_angle=params['lens_angle']) # 0.0015 ms scaling = 1.0 elif self.theory == 'mieonly': theory = Mie() scaling = params['alpha'] elif self.theory == 'mielensalpha': theory = MieLens(lens_angle=params['lens_angle']) # 0.0015 ms scaling = params['alpha'] return theory, scaling
def test_calculate_scattered_field_lensmie_same_as_mielens(self): detector = test_common.xschema_lens scatterer = test_common.sphere medium_wavevec = 2 * np.pi / test_common.wavelen medium_index = test_common.index illum_polarization = test_common.xpolarization theory_old = MieLens(lens_angle=LENS_ANGLE) theory_new = LENSMIE fields_old = theory_old.calculate_scattered_field(scatterer, detector) fields_new = theory_new.calculate_scattered_field(scatterer, detector) assert_allclose(fields_old, fields_new, atol=5e-3)
def test_holopy_hologram_equal_to_exact_calculation(self): # Checks that phase shifts and wrappers for mielens are correct theory_mielens = MieLens() illum_wavelength = 0.66 # 660 nm red light k = 2 * np.pi / illum_wavelength center = (10, 10, 5.) kwargs = {'particle_kz': center[2] * k, 'index_ratio': 1.2, 'size_parameter': 0.5 * k, 'lens_angle': theory_mielens.lens_angle} detector = detector_grid(10, 2.0) x = detector.x.values.reshape(-1, 1) - center[0] y = detector.y.values.reshape(1, -1) - center[1] rho = np.sqrt(x**2 + y**2) phi = np.arctan2(y, x) calculator = mielensfunctions.MieLensCalculator(**kwargs) scatterer = Sphere(n=kwargs['index_ratio'], r=kwargs['size_parameter'] / k, center=center) holo_calculate = calculator.calculate_total_intensity(k * rho, phi) holo_holopy = calc_holo( detector, scatterer, illum_wavelen=illum_wavelength, medium_index=1., illum_polarization=(1, 0), theory=theory_mielens) is_ok = np.allclose(holo_calculate, holo_holopy.values.squeeze(), **TOLS) self.assertTrue(is_ok)
def compare_fit_holo(data, fit_scatterer, fit_lens_angle): guess_holo = hologram2array( calc_holo(data, fit_scatterer, theory=MieLens(lens_angle=fit_lens_angle))) data_holo = hologram2array(data) compare_imgs(data_holo, guess_holo, ['Data', 'Model'])
def _forward(self, pars, detector): """ Compute a forward model (the hologram) Parameters ----------- pars: list Values for each parameter used to compute the hologram. Ordering is given by self._parameters detector: xarray dimensions of the resulting hologram. Metadata taken from detector if not given explicitly when instantiating self. """ alpha = read_map(self._maps['model'], pars)['alpha'] optics_kwargs = self._find_optics(pars, detector) scatterer = self._scatterer_from_parameters(pars) theory_kwargs = read_map(self._maps['theory'], pars) # FIXME would be nice to have access to the interpolator kwargs theory = MieLens(**theory_kwargs) try: return calc_holo(detector, scatterer, theory=theory, scaling=alpha, **optics_kwargs) except InvalidScatterer: return -np.inf
def test_raises_error_if_multiple_z_values(self): theory = MieLens() np.random.seed(10) positions = np.random.randn(3, 10) # the zs will differ by chance self.assertRaises( ValueError, theory._raw_fields, positions, sphere, 1.0, 1.33, xschema.illum_polarization)
def calculate_models(data, fits): fitholos = [ calc_holo(datum, fit.scatterer, theory=MieLens(lens_angle=fit.parameters['lens_angle'])) if fit is not None else 0 * datum + 1 for datum, fit in zip(data, fits) ] return fitholos
def calc_model(cls, data, params, theory_type='mielens'): scatterer = cls._make_scatterer(params) if theory_type == 'mielens': theory = MieLens(lens_angle=params['lens_angle']) scaling = 1.0 else: theory = Mie() scaling = params['alpha'] model = calc_holo(data, scatterer, theory=theory, scaling=scaling) return model
def test_raw_fields_similar_mielens_ypolarization(self): detector = SMALL_DETECTOR scatterer = test_common.sphere medium_wavevec = 2 * np.pi / test_common.wavelen medium_index = test_common.index illum_polarization = xr.DataArray([0, 1.0, 0]) theory_old = MieLens(lens_angle=LENS_ANGLE) pos_old = theory_old._transform_to_desired_coordinates( detector, scatterer.center, wavevec=medium_wavevec) theory_new = LENSMIE pos_new = theory_new._transform_to_desired_coordinates( detector, scatterer.center, wavevec=medium_wavevec) args = (scatterer, medium_wavevec, medium_index, illum_polarization) f0x, f0y, f0z = theory_old._raw_fields(pos_old, *args) fx, fy, fz = theory_new._raw_fields(pos_new, *args) assert_allclose(f0x, fx, atol=2e-3) assert_allclose(f0y, fy, atol=2e-3) assert_allclose(f0z, fz, atol=2e-3)
def test_can_calculate_for_positive_and_negative_z(self): theory = MieLens() ka = 5.0 radius = ka * wavelen * 0.5 / np.pi sphere_index = 1.59 is_ok = [] for kz in [-50., 0., 50.]: center = (0, 0, kz * wavelen * 0.5 / np.pi) this_sphere = Sphere(n=sphere_index, r=radius, center=center) holo = calc_holo(xschema, this_sphere, index, wavelen, xpolarization, theory=theory) is_ok.append(holo.data.ptp() > 0) self.assertTrue(all(is_ok))
def evaluate_model(self, params): scatterer = self.make_scatterer(params) if self.theory == 'mieonly': theory = Mie() else: theory = MieLens(lens_angle=params['lens_angle']) if self.theory == 'mielens': scaling = 1.0 else: scaling = params['alpha'] model = calc_holo(self.data, scatterer, theory=theory, scaling=scaling) return model
def test_mielens_multiple_returns_nonzero(self): scatterers = [ Sphere(n=1.59, r=5e-7, center=(1e-6, -1e-6, 10e-6)), Sphere(n=1.59, r=1e-6, center=[8e-6, 5e-6, 5e-6]), Sphere(n=1.59 + 0.0001j, r=5e-7, center=[5e-6, 10e-6, 3e-6]), ] sphere_collection = Spheres(scatterers=scatterers) theory = MieLens() schema = yschema holo = calc_holo(schema, sphere_collection, index, wavelen, theory=theory) self.assertTrue(holo is not None) self.assertTrue(holo.values.std() > 0)
def calculate_central_lobe_at(zs): illum_wavelength = 0.66 # 660 nm red light k = 2 * np.pi / illum_wavelength detector = detector_grid(4, 2.0) central_lobes = [] for z in zs: center = (0, 0, z) scatterer = Sphere(n=1.59, r=0.5, center=center) holo = calc_holo( detector, scatterer, illum_wavelen=illum_wavelength, medium_index=1.33, illum_polarization=(1, 0), theory=MieLens()) central_lobe = holo.values.squeeze()[0, 0] central_lobes.append(central_lobe) return np.array(central_lobes)
def test_mielens_x_polarization_differs_from_y(self): # test holograms for orthogonal polarizations; make sure they're # not the same, nor too different from one another. theory = MieLens() holo_x = calc_holo(xschema, sphere, index, wavelen, illum_polarization=xpolarization, theory=theory) holo_y = calc_holo(yschema, sphere, index, wavelen, illum_polarization=ypolarization, theory=theory) # the two arrays should not be equal self.assertFalse(np.allclose(holo_x, holo_y, **SOFTTOLS)) # but their max and min values should be very close # (really exact because we lose no symmetry from the grid) self.assertTrue(np.isclose(holo_x.max(), holo_y.max(), **MEDTOLS)) self.assertTrue(np.isclose(holo_x.min(), holo_y.min(), **MEDTOLS))
def forward(self, pars, detector): """ Compute a forward model (the hologram) Parameters ----------- pars: dict(string, float) Dictionary containing values for each parameter used to compute the hologram. Possible parameters are given by self.parameters. detector: xarray dimensions of the resulting hologram. Metadata taken from detector if not given explicitly when instantiating self. """ optics_kwargs, scatterer = self._optics_scatterer(pars, detector) # We need the lens parameter(s) for the theory: theory_kwargs = {name: self._get_parameter(name, pars, detector) for name in self.theory_params} # FIXME would be nice to have access to the interpolator kwargs theory = MieLens(**theory_kwargs) try: return calc_holo(detector, scatterer, theory=theory, scaling=1.0, **optics_kwargs) except InvalidScatterer: return -np.inf
def make_stack_figures(data, fits, n=None, r=None, z_positions=None): scatterers = [fit.scatterer for fit in fits] z = [fit.scatterer.center[2] for fit in fits] if z_positions is None else z_positions for scatterer, z_pos in zip(scatterers, z): scatterer.n = n if n is not None else scatterer.n scatterer.r = r if r is not None else scatterer.r scatterer.center[ 2] = z_pos if z_positions is not None else scatterer.center[2] model_holos = [ calc_holo(dt, scatterer, theory=MieLens(lens_angle=1.0)) for dt, scatterer in zip(data, scatterers) ] data_stack_xz = np.vstack([dt.values.squeeze()[50, :] for dt in data]) data_stack_yz = np.vstack([dt.values.squeeze()[:, 50] for dt in data]) model_stack_xz = np.vstack( [holo.values.squeeze()[50, :] for holo in model_holos]) model_stack_yz = np.vstack( [holo.values.squeeze()[:, 50] for holo in model_holos]) return data_stack_xz, data_stack_yz, model_stack_xz, model_stack_yz
def test_mielens_is_close_to_mieonly(self): """Tests that a mielens hologram is similar to a mie-only hologram.""" theory_mielens = MieLens() theory_mieonly = Mie() holo_mielens = calc_holo( xschema, sphere, index, wavelen, xpolarization, theory=theory_mielens) holo_mieonly = calc_holo( xschema, sphere, index, wavelen, xpolarization, scaling=1.0, theory=theory_mieonly) # the two arrays should not be equal self.assertFalse(np.allclose(holo_mielens, holo_mieonly, **TOLS)) # but their max and min values should be close: ptp_close_ish = np.isclose( holo_mielens.values.ptp(), holo_mieonly.values.ptp(), atol=0.1) # and their median should be close: median_close_ish = np.isclose( np.median(holo_mielens), np.median(holo_mieonly), atol=0.1) self.assertTrue(ptp_close_ish) self.assertTrue(median_close_ish)
def test_does_not_crash(self): theory = MieLens() holo = calc_holo(xschema, sphere, index, wavelen, xpolarization, theory=theory) self.assertTrue(holo is not None)