def test_nonlinearity(): # look at superposition of scattering from two large particles; # make sure that this is *not equal* to sum of holograms from # individual scatterers (scattered intensity should be # non-negligible for this case) x2 = x*2 y2 = y*2 z2 = z*2 scaling_alpha = 1.0 r = wavelen # order of wavelength sphere1 = Sphere(n=n, r=r, center = (x, y, z)) sphere2 = Sphere(n=n, r=r, center = (x2, y2, z2)) sc = Spheres(scatterers = [sphere1, sphere2]) holo_1 = calc_holo(xschema, sphere1, index, wavelen, illum_polarization=xpolarization, scaling=scaling_alpha) holo_2 = calc_holo(xschema, sphere2, index, wavelen, illum_polarization=xpolarization, scaling=scaling_alpha) holo_super = calc_holo(xschema, sc, index, wavelen, xpolarization, scaling=scaling_alpha, theory=Mie) # test nonlinearity by subtracting off individual holograms try: assert_array_almost_equal(holo_super - holo_1 + 1, holo_2) except AssertionError: pass # no way to do "assert array not equal" in numpy.testing else: raise AssertionError("Holograms computed for " "wavelength-scale scatterers should " "not superpose linearly")
def test_layered(): l = LayeredSphere(n = (1, 2), t = (1, 1), center = (2, 2, 2)) s = Sphere(n = (1,2), r = (1, 2), center = (2, 2, 2)) sch = detector_grid((10, 10), .2) wavelen = .66 hl = calc_holo(sch, l, index, wavelen, illum_polarization=xpolarization) hs = calc_holo(sch, s, index, wavelen, illum_polarization=xpolarization) assert_obj_close(hl, hs, rtol=0)
def test_subimaged(): # make a dummy image so that we can pretend we are working with # data we want to subimage im = xschema h = calc_holo(im, sphere, index, wavelen, xpolarization) sub = (60, 70), 30 hs = calc_holo(subimage(im, *sub), sphere, index, wavelen, xpolarization) assert_obj_close(subimage(h, *sub), hs)
def test_Mie_multiple(): s1 = Sphere(n = 1.59, r = 5e-7, center = (1e-6, -1e-6, 10e-6)) s2 = Sphere(n = 1.59, r = 1e-6, center=[8e-6,5e-6,5e-6]) s3 = Sphere(n = 1.59+0.0001j, r = 5e-7, center=[5e-6,10e-6,3e-6]) sc = Spheres(scatterers=[s1, s2, s3]) thry = Mie(False) schema = yschema fields = calc_field(schema, sc, index, wavelen, ypolarization, thry) verify(fields, 'mie_multiple_fields') calc_intensity(schema, sc, index, wavelen, ypolarization, thry) holo = calc_holo(schema, sc, index, wavelen, theory=thry) verify(holo, 'mie_multiple_holo') # should throw exception when fed a ellipsoid el = Ellipsoid(n = 1.59, r = (1e-6, 2e-6, 3e-6), center=[8e-6,5e-6,5e-6]) with assert_raises(TheoryNotCompatibleError) as cm: calc_field(schema, el, index, wavelen, theory=Mie) assert_equal(str(cm.exception), "Mie scattering theory can't handle " "scatterers of type Ellipsoid") assert_raises(TheoryNotCompatibleError, calc_field, schema, el, index, wavelen, xpolarization, Mie) assert_raises(TheoryNotCompatibleError, calc_intensity, schema, el, index, wavelen, xpolarization, Mie) assert_raises(TheoryNotCompatibleError, calc_holo, schema, el, index, wavelen, xpolarization, Mie)
def test_radialEscat(): thry_1 = Mie() thry_2 = Mie(False) sphere = Sphere(r = 1e-6, n = 1.4 + 0.01j, center = [10e-6, 10e-6, 1.2e-6]) h1 = calc_holo(xschema, sphere, index, wavelen, illum_polarization=xpolarization) h2 = calc_holo(xschema, sphere, index, wavelen, illum_polarization=xpolarization, theory=thry_2) try: assert_array_almost_equal(h1, h2, decimal=12) except AssertionError: pass # no way to do "assert array not equal" in numpy.testing else: raise AssertionError("Holograms w/ and w/o full radial fields" + " are exactly equal")
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: 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 _forward(self, pars, detector): """ Compute a hologram from pars with dimensions and metadata of detector, scaled by self.alpha. 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 = self._find_optics(pars, detector) scatterer = self._scatterer_from_parameters(pars) try: return calc_holo(detector, scatterer, theory=self.theory, scaling=alpha, **optics) except (MultisphereFailure, TmatrixFailure, InvalidScatterer): return -np.inf
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 test_calc_holo(): s = Sphere(n=1.59, r=.5, center=(0, 0, 1)) t = detector_grid(shape=(2, 2), spacing=.1) thry = Mie(False) h = calc_holo(t, s, 1.33, .66, (1, 0), theory=thry) assert_allclose( h, np.array([[[6.51162661], [5.67743548]], [[5.63554802], [4.89856241]]]))
def test_mie_polarization(): # test holograms for orthogonal polarizations; make sure they're # not the same, nor too different from one another. thry = Mie(False) xholo = calc_holo(xschema, sphere, index, wavelen, illum_polarization=xpolarization, scaling=scaling_alpha) yholo = calc_holo(yschema, sphere, index, wavelen, illum_polarization=ypolarization, scaling=scaling_alpha) # the two arrays should not be equal try: assert_array_almost_equal(xholo, yholo) except AssertionError: pass else: raise AssertionError("Holograms computed for both x- and y-polarized " "light are too similar.") # but their max and min values should be close assert_obj_close(xholo.max(), yholo.max()) assert_obj_close(xholo.min(), yholo.min()) return xholo, yholo
def test_farfield_holo(): # Tests that a far field calculation gives a hologram that is # different from a full radial dependence calculation, but not too different holo_full = calc_holo(xschema, sphere, index, wavelen, xpolarization, scaling=scaling_alpha) holo_far = calc_holo(xschema, sphere, index, wavelen, xpolarization, scaling=scaling_alpha, theory=Mie(False, False)) # the two arrays should not be equal try: assert_array_almost_equal(holo_full, holo_far) except AssertionError: pass else: raise AssertionError("Holograms computed for near and far field " "are too similar.") # but their max and min values should be close assert_obj_close(holo_full.max(), holo_far.max(), .1, context="Near and Far field holograms too different") assert_obj_close(holo_full.min(), holo_far.min(), .1, context="Near and Far field holograms too different")
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 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 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 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_linearity(): # look at superposition of scattering from two point particles; # make sure that this is sum of holograms from individual point # particles (scattered intensity should be negligible for this # case) x2 = x*2 y2 = y*2 z2 = z*2 scaling_alpha = 1.0 r = 1e-2*wavelen # something much smaller than wavelength sphere1 = Sphere(n=n, r=r, center = (x, y, z)) sphere2 = Sphere(n=n, r=r, center = (x2, y2, z2)) sc = Spheres(scatterers = [sphere1, sphere2]) holo_1 = calc_holo(xschema, sphere1, index, wavelen, xpolarization, scaling=scaling_alpha) holo_2 = calc_holo(xschema, sphere2, index, wavelen, xpolarization, scaling=scaling_alpha) holo_super = calc_holo(xschema, sc, index, wavelen, xpolarization, theory=Mie, scaling=scaling_alpha) # make sure we're not just looking at uniform arrays (could # happen if the size is set too small) try: assert_array_almost_equal(holo_1, holo_2, decimal=12) except AssertionError: pass # no way to do "assert array not equal" in numpy.testing else: raise AssertionError("Hologram computed for point particle" + " looks suspiciously close to having" + " no fringes") # Test linearity by subtracting off individual holograms. # This should recover the other hologram assert_array_almost_equal(holo_super - holo_1 + 1, holo_2) assert_array_almost_equal(holo_super - holo_2 + 1, holo_1)
def test_single_sphere(): # single sphere hologram (only tests that functions return) thry = Mie(False) holo = calc_holo(xschema, sphere, index, wavelen, xpolarization, theory=thry, scaling=scaling_alpha) field = calc_field(xschema, sphere, index, wavelen, xpolarization, theory=thry) intensity = calc_intensity(xschema, sphere, medium_index=index, illum_wavelen=wavelen, illum_polarization=xpolarization, theory=thry) verify(holo, 'single_holo') verify(field, 'single_field') # now test some invalid scatterers and confirm that it rejects calculating # for them # large radius (calculation not attempted because it would take forever assert_raises(InvalidScatterer, calc_holo, xschema, Sphere(r=1, n = 1.59, center = (5,5,5)), medium_index=index, illum_wavelen=wavelen)
def forward(self, pars, detector): """ Compute a hologram from pars with dimensions and metadata of detector, scaled by self.alpha. 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. """ alpha = self._get_parameter('alpha', pars, detector) optics, scatterer = self._optics_scatterer(pars, detector) try: return calc_holo(detector, scatterer, theory=self.theory, scaling=alpha, **optics) except (MultisphereFailure, TmatrixFailure, InvalidScatterer): return -np.inf
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 test_large_sphere(): large_sphere_gold=[[[0.96371831],[1.04338683]],[[1.04240049],[0.99605225]]] s=Sphere(n=1.5, r=5, center=(10,10,10)) sch=detector_grid(10,.2) hl=calc_holo(sch, s, illum_wavelen=.66, medium_index=1, illum_polarization=(1,0)) assert_obj_close(np.array(hl[0:2,0:2]),large_sphere_gold)
def test_does_not_crash(self): theory = MieLens() holo = calc_holo(xschema, sphere, index, wavelen, xpolarization, theory=theory) self.assertTrue(holo is not None)