def test_otf_scaler_1(): """ Test that the C and the Python libraries agree on the calculation of an OTF scaled PSF. """ otf_sigma = 1.8 geo = pupilMath.Geometry(128, 0.1, 0.6, 1.5, 1.4) pf = geo.createFromZernike(1.0, [[1.3, 2, 2]]) pf_c = pfFnC.PupilFunction(geometry=geo) pf_c.setPF(pf) otf_sc = otfSC.OTFScaler(size=geo.size) gsf = geo.gaussianScalingFactor(otf_sigma) psf_py = geo.pfToPSF(pf, [0.0], scaling_factor=gsf) psf_c = pf_c.getPSFIntensity() otf_sc.setScale(gsf) psf_c = otf_sc.scale(psf_c) if False: with tifffile.TiffWriter( storm_analysis.getPathOutputTest( "test_otf_scaler_1.tif")) as tf: tf.save(psf_c.astype(numpy.float32)) tf.save(psf_py.astype(numpy.float32)) assert numpy.allclose(psf_c, psf_py) pf_c.cleanup() otf_sc.cleanup()
def test_otf_scaler_2(): """ Test that the C and the Python libraries agree on the calculation of an OTF scaled PSF at multiple z values. """ otf_sigma = 1.8 geo = pupilMath.Geometry(128, 0.1, 0.6, 1.5, 1.4) pf = geo.createFromZernike(1.0, [[1.3, 2, 2]]) pf_c = pfFnC.PupilFunction(geometry=geo) pf_c.setPF(pf) gsf = geo.gaussianScalingFactor(otf_sigma) otf_sc = otfSC.OTFScaler(size=geo.size) otf_sc.setScale(gsf) for dz in [-0.2, 0.1, 0.0, 0.1, 0.2]: pf_c.translateZ(dz) psf_c = pf_c.getPSFIntensity() psf_c = otf_sc.scale(psf_c) psf_py = geo.pfToPSF(pf, [dz], scaling_factor=gsf) assert numpy.allclose(psf_c, psf_py) pf_c.cleanup() otf_sc.cleanup()
def test_pupilfn_2(): """ Test PF translation. """ dx = 0.5 dy = 0.25 dz = 0.2 geo = pupilMath.Geometry(20, 0.1, 0.6, 1.5, 1.4) pf = geo.createFromZernike(1.0, [[1.3, 2, 2]]) pf_c = pfFnC.PupilFunction(geometry=geo) pf_c.setPF(pf) pf_c.translate(dx, dy, dz) psf_c = pupilMath.intensity(pf_c.getPSF()) defocused = geo.changeFocus(pf, dz) translated = geo.translatePf(defocused, dx, dy) psf_py = pupilMath.intensity(pupilMath.toRealSpace(translated)) if False: with tifffile.TiffWriter( storm_analysis.getPathOutputTest("test_pupilfn_2.tif")) as tf: tf.save(psf_c.astype(numpy.float32)) tf.save(psf_py.astype(numpy.float32)) assert numpy.allclose(psf_c, psf_py) pf_c.cleanup()
def test_pupilfn_3(): """ Test PF X derivative (C library). """ dx = 1.0e-6 geo = pupilMath.Geometry(20, 0.1, 0.6, 1.5, 1.4) pf = geo.createFromZernike(1.0, [[1.3, 2, 2]]) pf_c = pfFnC.PupilFunction(geometry=geo) pf_c.setPF(pf) # Calculate derivative of magnitude as a function of x. psf_c = pf_c.getPSF() psf_c_dx = pf_c.getPSFdx() mag_dx_calc = 2.0 * (numpy.real(psf_c) * numpy.real(psf_c_dx) + numpy.imag(psf_c) * numpy.imag(psf_c_dx)) # Estimate derivative using (f(x+dx) - f(x))/dx mag = pupilMath.intensity(psf_c) pf_c.translate(dx, 0.0, 0.0) mag_dx_est = (pupilMath.intensity(pf_c.getPSF()) - mag) / dx if False: with tifffile.TiffWriter( storm_analysis.getPathOutputTest("test_pupilfn_3.tif")) as tf: #tf.save(mag.astype(numpy.float32)) tf.save(mag_dx_calc.astype(numpy.float32)) tf.save(mag_dx_est.astype(numpy.float32)) tf.save(numpy.abs(mag_dx_calc - mag_dx_est).astype(numpy.float32)) assert numpy.allclose(mag_dx_calc, mag_dx_est, atol=1.0e-6) pf_c.cleanup()
def test_pupilfn_7(): """ Test that PF translation is correct (i.e. independent of size). """ sizes = [10, 20, 40] dx = 1.0 for size in sizes: geo = pupilMath.Geometry(size, 0.1, 0.6, 1.5, 1.4) pf = geo.createFromZernike(1.0, [[1.3, 2, 2]]) pf_c = pfFnC.PupilFunction(geometry=geo) pf_c.setPF(pf) psf_untranslated = numpy.roll(pupilMath.intensity(pf_c.getPSF()), 1, axis=0) pf_c.translate(dx, 0.0, 0.0) psf_translated = pupilMath.intensity(pf_c.getPSF()) if False: with tifffile.TiffWriter( storm_analysis.getPathOutputTest( "test_pupilfn_7.tif")) as tf: tf.save(psf_untranslated.astype(numpy.float32)) tf.save(psf_translated.astype(numpy.float32)) assert numpy.allclose(psf_untranslated, psf_translated) pf_c.cleanup()
def test_pupilfn_6(): """ Test PF Z derivative (C library). """ dz = 1.0e-6 geo = pupilMath.Geometry(20, 0.1, 0.6, 1.5, 1.4) pf = geo.createFromZernike(1.0, [[1.3, 2, 2]]) pf_c = pfFnC.PupilFunction(geometry=geo) pf_c.setPF(pf) # Calculate derivative of magnitude as a function of z. psf_c = pf_c.getPSF() psf_c_dz = pf_c.getPSFdz() mag_dz_calc = 2.0 * (numpy.real(psf_c) * numpy.real(psf_c_dz) + numpy.imag(psf_c) * numpy.imag(psf_c_dz)) # Estimate derivative using (f(z+dz) - f(z))/dz mag = pupilMath.intensity(psf_c) pf_c.translate(0.0, 0.0, dz) mag_dz_est = (pupilMath.intensity(pf_c.getPSF()) - mag) / dz if False: with tifffile.TiffWriter( storm_analysis.getPathOutputTest("test_pupilfn_6.tif")) as tf: #tf.save(mag.astype(numpy.float32)) tf.save(mag_dz_calc.astype(numpy.float32)) tf.save(mag_dz_est.astype(numpy.float32)) tf.save(numpy.abs(mag_dz_calc - mag_dz_est).astype(numpy.float32)) assert (numpy.max(numpy.abs(mag_dz_calc - mag_dz_est))) < 1.0e-6 pf_c.cleanup()
def __init__(self, size, pixel_size, wavelength, imm_index, NA): """ size - The number of pixels in the PSF image, assumed square. pixel_size - The size of the camera pixel in um. wavelength - The wavelength of the flourescence in um. imm_index - The index of the immersion media. NA - The numerical aperature of the objective. """ super(GeometryC, self).__init__(size, pixel_size, wavelength, imm_index, NA) self.otf_sc = otfSC.OTFScaler(size = size) self.pf_c = pfFnC.PupilFunction(geometry = self)
def test_pupilfn_10(): """ Test C library PSF intensity calculation. """ geo = pupilMath.Geometry(20, 0.1, 0.6, 1.5, 1.4) pf = geo.createFromZernike(1.0, [[1.3, -1, 3], [1.3, -2, 2]]) pf_c = pfFnC.PupilFunction(geometry=geo) pf_c.setPF(pf) psf_c = pf_c.getPSFIntensity() psf_py = pupilMath.intensity(pupilMath.toRealSpace(pf)) assert numpy.allclose(psf_c, psf_py) pf_c.cleanup()
def test_pupilfn_11(): """ Test C library PF Z translation function. """ geo = pupilMath.Geometry(20, 0.1, 0.6, 1.5, 1.4) pf = geo.createFromZernike(1.0, [[1.3, -1, 3], [1.3, -2, 2]]) pf_c = pfFnC.PupilFunction(geometry=geo) pf_c.setPF(pf) for dz in [-0.2, 0.1, 0.0, 0.1, 0.2]: pf_c.translateZ(dz) psf_c = pf_c.getPSFIntensity() defocused = geo.changeFocus(pf, dz) psf_py = pupilMath.intensity(pupilMath.toRealSpace(defocused)) assert numpy.allclose(psf_c, psf_py) pf_c.cleanup()
def __init__(self, psf_filename=None, zmax=None, zmin=None, **kwds): kwds["psf_filename"] = psf_filename super(CRPupilFn, self).__init__(**kwds) # Load the pupil function data. with open(psf_filename, 'rb') as fp: pf_data = pickle.load(fp) # Get the pupil function and verify that the type is correct. pf = pf_data['pf'] assert (pf.dtype == numpy.complex128) # Get the pupil function pixel size. self.pupil_size = pf.shape[0] # Create geometry object. if pf_data.get("geo_sim_pf", False): geo = pupilMath.GeometrySim(self.pupil_size, pf_data['pixel_size'], pf_data['wavelength'], pf_data['immersion_index'], pf_data['numerical_aperture']) else: geo = pupilMath.Geometry(self.pupil_size, pf_data['pixel_size'], pf_data['wavelength'], pf_data['immersion_index'], pf_data['numerical_aperture']) # Create C pupil function object. self.pupil_fn_c = pupilFnC.PupilFunction(geo) self.pupil_fn_c.setPF(pf) # Additional initializations. self.zmax = zmax * 1.0e+3 self.zmin = zmin * 1.0e+3 # CR weights approximately every 25nm. self.n_zvals = int(round((self.zmax - self.zmin) / 25.0)) self.delta_xy = self.pixel_size self.delta_z = 1000.0
def __init__(self, pf_filename = None, zmin = None, zmax = None, **kwds): """ Technically a pupil function would cover any z range, but in fitting we are limit it to a finite range. Also, zmin and zmax should be specified in nanometers. """ super(PupilFunction, self).__init__(**kwds) self.zmax = zmax self.zmin = zmin # Load the pupil function data. with open(pf_filename, 'rb') as fp: pf_data = pickle.load(fp) # Get the pupil function and verify that the type is correct. pf = pf_data['pf'] assert (pf.dtype == numpy.complex128) # Get the pupil function size and pixel size. self.pixel_size = pf_data['pixel_size'] self.pupil_size = pf.shape[0] # Create geometry object. if pf_data.get("geo_sim_pf", False): geo = pupilMath.GeometrySim(self.pupil_size, self.pixel_size, pf_data['wavelength'], pf_data['immersion_index'], pf_data['numerical_aperture']) else: geo = pupilMath.Geometry(self.pupil_size, self.pixel_size, pf_data['wavelength'], pf_data['immersion_index'], pf_data['numerical_aperture']) # Create C pupil function object. self.pupil_fn_c = pupilFnC.PupilFunction(geo) self.pupil_fn_c.setPF(pf)
def test_pupilfn_1(): """ Test that the C and the Python library agree on the calculation of the untranslated PSF. """ geo = pupilMath.Geometry(20, 0.1, 0.6, 1.5, 1.4) pf = geo.createFromZernike(1.0, [[1.3, 2, 2]]) pf_c = pfFnC.PupilFunction(geometry=geo) pf_c.setPF(pf) psf_c = pupilMath.intensity(pf_c.getPSF()) psf_py = pupilMath.intensity(pupilMath.toRealSpace(pf)) if False: with tifffile.TiffWriter( storm_analysis.getPathOutputTest("test_pupilfn_1.tif")) as tf: tf.save(psf_c.astype(numpy.float32)) tf.save(psf_py.astype(numpy.float32)) assert numpy.allclose(psf_c, psf_py) pf_c.cleanup()