def test_pupilfn_8():
    """
    Test that pupilfn.make_pupil_fn.makePupilFunction works as expected.
    """
    pf_size = 30
    zmn = [[1.3, 2, 2]]
    z_offset = -0.3
    
    # Create & save pupil function.
    pf_file = storm_analysis.getPathOutputTest("pf_test.pfn")
    makePupilFn.makePupilFunction(pf_file, pf_size, 0.1, zmn, z_offset = z_offset)

    # Load PF.
    with open(pf_file, "rb") as fp:
        pf_data = pickle.load(fp)
        test_pf = pf_data["pf"]

    # Create comparison PF.
    geo = pupilMath.GeometrySim(pf_size,
                                pf_data["pixel_size"],
                                pf_data["wavelength"],
                                pf_data["immersion_index"],
                                pf_data["numerical_aperture"])
    ref_pf = geo.createFromZernike(1.0, zmn)

    # Normalize reference to also have height 1.0 (at z = 0.0).
    psf = pupilMath.intensity(pupilMath.toRealSpace(ref_pf))
    ref_pf = ref_pf * 1.0/math.sqrt(numpy.max(psf))

    # Test that they are the same.
    for z in [-0.2, -0.1, 0.0, 0.1, 0.2]:
        test_psf = pupilMath.intensity(pupilMath.toRealSpace(geo.changeFocus(test_pf, z)))
        ref_psf = pupilMath.intensity(pupilMath.toRealSpace(geo.changeFocus(ref_pf, z - z_offset)))
        #print(numpy.max(numpy.abs(test_psf - ref_psf)))
        assert numpy.allclose(test_psf, ref_psf)
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_4():
    """
    Test PF X derivative (Python 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]])

    # Calculate derivative of magnitude as a function of x.
    psf_py = pupilMath.toRealSpace(pf)
    psf_py_dx = pupilMath.toRealSpace(geo.dx(pf))
    mag_dx_calc = 2.0 * (numpy.real(psf_py) * numpy.real(psf_py_dx) +
                         numpy.imag(psf_py) * numpy.imag(psf_py_dx))

    # Estimate derivative using (f(x+dx) - f(x))/dx
    mag = pupilMath.intensity(psf_py)
    translated = geo.translatePf(pf, dx, 0.0)
    mag_dx_est = (pupilMath.intensity(pupilMath.toRealSpace(translated)) -
                  mag) / dx

    if False:
        with tifffile.TiffWriter(
                storm_analysis.getPathOutputTest("test_pupilfn_4.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)
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_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_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_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_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()
Beispiel #9
0
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 test_pupilfn_4():
    """
    Test PF X derivative (Python 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]])
    
    # Calculate derivative of magnitude as a function of x.
    psf_py = pupilMath.toRealSpace(pf)
    psf_py_dx = pupilMath.toRealSpace(geo.dx(pf))
    mag_dx_calc = 2.0 * (numpy.real(psf_py)*numpy.real(psf_py_dx) + numpy.imag(psf_py)*numpy.imag(psf_py_dx))

    # Estimate derivative using (f(x+dx) - f(x))/dx
    mag = pupilMath.intensity(psf_py)
    translated = geo.translatePf(pf, dx, 0.0)
    mag_dx_est = (pupilMath.intensity(pupilMath.toRealSpace(translated)) - mag)/dx
        
    if False:
        with tifffile.TiffWriter(storm_analysis.getPathOutputTest("test_pupilfn_4.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)
def makePSF(filename, size, pixel_size, zmn, zrange, zstep):
    """
    pixel_size - pixel size in microns.
    zmn - Zernike coefficients.
    zrange - The final zrange will be +- zrange (microns).
    zstep - The z step size in microns.
    """
    #
    # Physical constants. Note that these match the default values for
    # simulator.psf.PupilFunction().
    #
    wavelength = 0.6   # Fluorescence wavelength in microns.
    imm_index = 1.5    # Immersion media index (oil objective).
    NA = 1.4           # Numerical aperture of the objective.

    # Create geometry object.
    geo = pupilMath.Geometry(size,
                             pixel_size,
                             wavelength,
                             imm_index,
                             NA)

    # Create PF.
    pf = geo.createFromZernike(1.0, zmn)

    # Normalize to have height 1.0 (at z = 0.0).
    psf = pupilMath.intensity(pupilMath.toRealSpace(pf))
    pf = pf * 1.0/math.sqrt(numpy.max(psf))
    
    # Verify normalization.
    print("Height:", numpy.max(pupilMath.intensity(pupilMath.toRealSpace(pf))))

    # Create a PSF at each z value.
    z_values = numpy.arange(-zrange, zrange + 0.5*zstep, zstep)
    #print(z_values)
    
    if ((z_values.size%2)==0):
        print("The number of z slices must be an odd number.")
        assert False, "PSF creation failed."
    
    psf = numpy.zeros((z_values.size, size, size))
    for i, z in enumerate(z_values):
        defocused = geo.changeFocus(pf, z)
        psf[i,:,:] = pupilMath.intensity(pupilMath.toRealSpace(defocused))
    
    # Pickle and save.
    psf_dict = {"psf" : psf,
                "pixel_size" : pixel_size,
                "zmax" : 1000.0 * zrange,
                "zmin" : -1000.0 * zrange}

    with open(filename, 'wb') as fp:
        pickle.dump(psf_dict, fp)

    # Also save a .tif version.
    with tifffile.TiffWriter("psf.tif") as tf:
        for i in range(psf.shape[0]):
            tf.save(psf[i,:,:].astype(numpy.float32))
def makePSF(filename, size, pixel_size, zmn, zrange, zstep):
    """
    pixel_size - pixel size in microns.
    zmn - Zernike coefficients.
    zrange - The final zrange will be +- zrange (microns).
    zstep - The z step size in microns.
    """
    #
    # Physical constants. Note that these match the default values for
    # simulator.psf.PupilFunction().
    #
    wavelength = 0.6  # Fluorescence wavelength in microns.
    imm_index = 1.5  # Immersion media index (oil objective).
    NA = 1.4  # Numerical aperture of the objective.

    # Create geometry object.
    geo = pupilMath.Geometry(size, pixel_size, wavelength, imm_index, NA)

    # Create PF.
    pf = geo.createFromZernike(1.0, zmn)

    # Normalize to have height 1.0 (at z = 0.0).
    psf = pupilMath.intensity(pupilMath.toRealSpace(pf))
    pf = pf * 1.0 / math.sqrt(numpy.max(psf))

    # Verify normalization.
    print("Height:", numpy.max(pupilMath.intensity(pupilMath.toRealSpace(pf))))

    # Create a PSF at each z value.
    z_values = numpy.arange(-zrange, zrange + 0.5 * zstep, zstep)
    #print(z_values)

    if ((z_values.size % 2) == 0):
        print("The number of z slices must be an odd number.")
        assert False, "PSF creation failed."

    psf = numpy.zeros((z_values.size, size, size))
    for i, z in enumerate(z_values):
        defocused = geo.changeFocus(pf, z)
        psf[i, :, :] = pupilMath.intensity(pupilMath.toRealSpace(defocused))

    # Pickle and save.
    psf_dict = {
        "psf": psf,
        "pixel_size": pixel_size,
        "zmax": 1000.0 * zrange,
        "zmin": -1000.0 * zrange
    }

    with open(filename, 'wb') as fp:
        pickle.dump(psf_dict, fp)

    # Also save a .tif version.
    with tifffile.TiffWriter("psf.tif") as tf:
        for i in range(psf.shape[0]):
            tf.save(psf[i, :, :].astype(numpy.float32))
Beispiel #13
0
    def getPSFs(self, i3_data):
        """
        The expected form for the i3 data fields are x,y in pixels and z in nanometers.
        """
        image = numpy.zeros((self.im_size_x, self.im_size_y))
        x = i3_data['x']         # Pixels
        y = i3_data['y']         # Pixels
        z = i3_data['z']*0.001   # Expected to be in nanometers.
        a = i3_data['a']

        dx = x - numpy.floor(x)
        dy = y - numpy.floor(y)

        for i in range(x.size):

            ix = int(x[i])
            iy = int(y[i])
            
            if (ix >= 0.0) and (ix < self.x_size) and (iy >= 0.0) and (iy < self.y_size):

                # Shift to the desired z value.
                defocused = self.geo.changeFocus(self.pf, z[i])

                # Translate to the correct sub-pixel position.
                #translated = defocused
                translated = self.geo.translatePf(defocused, dx[i], dy[i])

                # Get real-space intensity.
                psf = pupilMath.intensity(pupilMath.toRealSpace(translated)) * a[i]
                i3_data['h'][i] = numpy.max(psf)
                
                image[ix:ix+self.psf_size,iy:iy+self.psf_size] += psf

        return image[self.margin:self.margin+self.x_size,self.margin:self.margin+self.y_size]
Beispiel #14
0
    def getPSFs(self, i3_data):
        """
        The expected form for the i3 data fields are x,y in pixels and z in nanometers.
        """
        image = numpy.zeros((self.im_size_x, self.im_size_y))
        x = i3_data['x']         # Pixels
        y = i3_data['y']         # Pixels
        z = i3_data['z']*0.001   # Expected to be in nanometers.
        a = i3_data['a']

        dx = x - numpy.floor(x)
        dy = y - numpy.floor(y)

        for i in range(x.size):

            ix = int(x[i])
            iy = int(y[i])
            
            if (ix >= 0.0) and (ix < self.x_size) and (iy >= 0.0) and (iy < self.y_size):

                # Shift to the desired z value.
                defocused = self.geo.changeFocus(self.pf, z[i])

                # Translate to the correct sub-pixel position.
                #translated = defocused
                translated = self.geo.translatePf(defocused, dx[i], dy[i])

                # Get real-space intensity.
                psf = pupilMath.intensity(pupilMath.toRealSpace(translated)) * a[i]
                i3_data['h'][i] = numpy.max(psf)
                
                image[ix:ix+self.psf_size,iy:iy+self.psf_size] += psf

        return image[self.margin:self.margin+self.x_size,self.margin:self.margin+self.y_size]
def test_psf_fft2():
    """
    Test translated PSF calculation.
    """
    dx = 0.5
    dy = 0.25
    dz = 0.2
    [pf_psf, geo, pf] = makePSFAndPF(-0.4, 0.4, 0.05)
    
    pfft = psfFFTC.PSFFFT(pf_psf)
    pfft.translate(dy, dx, dz*(pf_psf.shape[0] - 1)/0.8)
    psf_fft = pfft.getPSF()
    
    defocused = geo.changeFocus(pf, dz)
    translated = geo.translatePf(defocused, dx, dy)
    psf_pf = pupilMath.intensity(pupilMath.toRealSpace(translated))
    
    if False:
        print(numpy.max(numpy.abs(psf_fft - psf_pf)))
        with tifffile.TiffWriter(storm_analysis.getPathOutputTest("test_psf_fft2.tif")) as tf:
            tf.save(psf_fft.astype(numpy.float32))
            tf.save(psf_pf.astype(numpy.float32))

    assert (numpy.max(numpy.abs(psf_fft - psf_pf))) < 1.0e-10

    pfft.cleanup()
Beispiel #16
0
def test_psf_fft2():
    """
    Test translated PSF calculation.
    """
    dx = 0.5
    dy = 0.25
    dz = 0.2
    [pf_psf, geo, pf] = makePSFAndPF(-0.4, 0.4, 0.05)

    pfft = psfFFTC.PSFFFT(pf_psf)
    pfft.translate(dy, dx, dz * (pf_psf.shape[0] - 1) / 0.8)
    psf_fft = pfft.getPSF()

    defocused = geo.changeFocus(pf, dz)
    translated = geo.translatePf(defocused, dx, dy)
    psf_pf = pupilMath.intensity(pupilMath.toRealSpace(translated))

    if False:
        print(numpy.max(numpy.abs(psf_fft - psf_pf)))
        with tifffile.TiffWriter(
                storm_analysis.getPathOutputTest("test_psf_fft2.tif")) as tf:
            tf.save(psf_fft.astype(numpy.float32))
            tf.save(psf_pf.astype(numpy.float32))

    assert (numpy.max(numpy.abs(psf_fft - psf_pf))) < 1.0e-10

    pfft.cleanup()
Beispiel #17
0
    def getPSFs(self, h5_data):
        """
        The expected form for the h5 data fields are x,y in pixels and z in microns.
        """
        image = numpy.zeros((self.im_size_x, self.im_size_y))
        x = h5_data['x'] + 1  # Pixels
        y = h5_data['y'] + 1  # Pixels
        z = h5_data['z']  # Expected to be in microns.
        a = h5_data['sum']

        h5_data['height'] = numpy.zeros(a.size)

        dx = x - numpy.floor(x)
        dy = y - numpy.floor(y)

        for i in range(x.size):

            ix = int(x[i])
            iy = int(y[i])

            if (ix >= 0.0) and (ix < self.x_size) and (iy >= 0.0) and (
                    iy < self.y_size):

                pf = self.pf

                # Apply aberration function if available.
                ab_fn = self.getAberrationFn(z[i])
                if ab_fn is not None:
                    pf = pf * ab_fn

                # Shift to the desired z value.
                defocused = self.geo.changeFocus(pf, z[i])

                # Translate to the correct sub-pixel position.
                #translated = defocused
                translated = self.geo.translatePf(defocused, dx[i], dy[i])

                # Get real-space intensity.
                psf = pupilMath.intensity(
                    pupilMath.toRealSpace(translated)) * a[i]

                # Apply OTF scaling if requested.
                if self.otf_scaler is not None:
                    otf = scipy.fftpack.fftshift(scipy.fftpack.fft2(psf))
                    otf_scaled = otf * self.otf_scaler
                    psf = numpy.abs(scipy.fftpack.ifft2(otf_scaled))

                h5_data['height'][i] = numpy.max(psf)

                image[ix:ix + self.psf_size, iy:iy + self.psf_size] += psf

        return image[self.margin:self.margin + self.x_size,
                     self.margin:self.margin + self.y_size]
def test_pupilfn_8():
    """
    Test that pupilfn.make_pupil_fn.makePupilFunction works as expected.
    """
    pf_size = 30
    zmn = [[1.3, 2, 2]]
    z_offset = -0.3

    # Create & save pupil function.
    pf_file = storm_analysis.getPathOutputTest("pf_test.pfn")
    makePupilFn.makePupilFunction(pf_file,
                                  pf_size,
                                  0.1,
                                  zmn,
                                  z_offset=z_offset)

    # Load PF.
    with open(pf_file, "rb") as fp:
        pf_data = pickle.load(fp)
        test_pf = pf_data["pf"]

    # Create comparison PF.
    geo = pupilMath.GeometrySim(pf_size, pf_data["pixel_size"],
                                pf_data["wavelength"],
                                pf_data["immersion_index"],
                                pf_data["numerical_aperture"])
    ref_pf = geo.createFromZernike(1.0, zmn)

    # Normalize reference to also have height 1.0 (at z = 0.0).
    psf = pupilMath.intensity(pupilMath.toRealSpace(ref_pf))
    ref_pf = ref_pf * 1.0 / math.sqrt(numpy.max(psf))

    # Test that they are the same.
    for z in [-0.2, -0.1, 0.0, 0.1, 0.2]:
        test_psf = pupilMath.intensity(
            pupilMath.toRealSpace(geo.changeFocus(test_pf, z)))
        ref_psf = pupilMath.intensity(
            pupilMath.toRealSpace(geo.changeFocus(ref_pf, z - z_offset)))
        #print(numpy.max(numpy.abs(test_psf - ref_psf)))
        assert numpy.allclose(test_psf, ref_psf)
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()
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()
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 makePSFAndPF(zmin, zmax, zstep):
    """
    Creates the PSF and PF used for testing.
    """
    size = 20
    geo = pupilMath.Geometry(size, 0.1, 0.6, 1.5, 1.4)
    pf = geo.createFromZernike(1.0, [[1.3, 2, 2]])

    z_values = numpy.arange(zmin, zmax + 0.5*zstep, zstep)
    
    psf = numpy.zeros((z_values.size, size, size))
    for i, z in enumerate(z_values):
        defocused = geo.changeFocus(pf, z)
        psf[i,:,:] = pupilMath.intensity(pupilMath.toRealSpace(defocused))

    return [psf, geo, pf]
Beispiel #23
0
def makePSFAndPF(zmin, zmax, zstep):
    """
    Creates the PSF and PF used for testing.
    """
    size = 20
    geo = pupilMath.Geometry(size, 0.1, 0.6, 1.5, 1.4)
    pf = geo.createFromZernike(1.0, [[1.3, 2, 2]])

    z_values = numpy.arange(zmin, zmax + 0.5 * zstep, zstep)

    psf = numpy.zeros((z_values.size, size, size))
    for i, z in enumerate(z_values):
        defocused = geo.changeFocus(pf, z)
        psf[i, :, :] = pupilMath.intensity(pupilMath.toRealSpace(defocused))

    return [psf, geo, pf]
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_psf_fft1():
    """
    Test untranslated PSF calculation.
    """
    [pf_psf, geo, pf] = makePSFAndPF(-0.4, 0.4, 0.05)

    pfft = psfFFTC.PSFFFT(pf_psf)
    psf_fft = pfft.getPSF()
    psf_pf = pupilMath.intensity(pupilMath.toRealSpace(pf))
    
    if False:
        print(numpy.max(numpy.abs(psf_fft - psf_pf)))
        with tifffile.TiffWriter(storm_analysis.getPathOutputTest("test_psf_fft1.tif")) as tf:
            tf.save(psf_fft.astype(numpy.float32))
            tf.save(psf_pf.astype(numpy.float32))

    assert (numpy.max(numpy.abs(psf_fft - psf_pf))) < 1.0e-10

    pfft.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()
Beispiel #27
0
def test_psf_fft1():
    """
    Test untranslated PSF calculation.
    """
    [pf_psf, geo, pf] = makePSFAndPF(-0.4, 0.4, 0.05)

    pfft = psfFFTC.PSFFFT(pf_psf)
    psf_fft = pfft.getPSF()
    psf_pf = pupilMath.intensity(pupilMath.toRealSpace(pf))

    if False:
        print(numpy.max(numpy.abs(psf_fft - psf_pf)))
        with tifffile.TiffWriter(
                storm_analysis.getPathOutputTest("test_psf_fft1.tif")) as tf:
            tf.save(psf_fft.astype(numpy.float32))
            tf.save(psf_pf.astype(numpy.float32))

    assert (numpy.max(numpy.abs(psf_fft - psf_pf))) < 1.0e-10

    pfft.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()
Beispiel #29
0
    def getPSF(self, z_value, shape=None, normalize=False):
        """
        Z value is expected to be in nanometers.
        """
        # Convert z_value to microns.
        z_value = 1.0e-3 * z_value

        # Translate to the correct z value.
        self.pupil_fn_c.translate(0.0, 0.0, z_value)

        # Get the (complex) PSF.
        psf = self.pupil_fn_c.getPSF()

        # Convert to intensity
        psf = pupilMath.intensity(psf)

        # Center into a (larger) array if requested.
        if shape is not None:
            psf_size = psf.shape[0]
            im_size_x = shape[0]
            im_size_y = shape[1]

            start_x = int(im_size_x / 2.0 - psf_size / 2.0)
            start_y = int(im_size_y / 2.0 - psf_size / 2.0)

            end_x = start_x + psf_size
            end_y = start_y + psf_size

            temp = numpy.zeros((im_size_x, im_size_y))
            temp[start_x:end_x, start_y:end_y] = psf

            psf = temp

        # Normalize if requested.
        if normalize:
            psf = psf / numpy.sum(psf)

        return psf
Beispiel #30
0
    def getPSF(self, z_value, shape = None, normalize = False):
        """
        Z value is expected to be in nanometers.
        """
        # Convert z_value to microns.
        z_value = 1.0e-3 * z_value
        
        # Translate to the correct z value.
        self.pupil_fn_c.translate(0.0, 0.0, z_value)

        # Get the (complex) PSF.
        psf = self.pupil_fn_c.getPSF()

        # Convert to intensity
        psf = pupilMath.intensity(psf)

        # Center into a (larger) array if requested.
        if shape is not None:
            psf_size = psf.shape[0]
            im_size_x = shape[0]
            im_size_y = shape[1]

            start_x = int(im_size_x/2.0 - psf_size/2.0)
            start_y = int(im_size_y/2.0 - psf_size/2.0)

            end_x = start_x + psf_size
            end_y = start_y + psf_size

            temp = numpy.zeros((im_size_x, im_size_y))
            temp[start_x:end_x,start_y:end_y] = psf

            psf = temp

        # Normalize if requested.
        if normalize:
            psf = psf/numpy.sum(psf)

        return psf
Beispiel #31
0
 def getPSF(self, z_value):
     self.translate(z_value)
     psf_c = self.pupil_fn_c.getPSF()
     return numpy.transpose(pupilMath.intensity(psf_c))
Beispiel #32
0
 def getPSF(self, z_value):
     self.translate(z_value)
     psf_c = self.pupil_fn_c.getPSF()
     return numpy.transpose(pupilMath.intensity(psf_c))
def makePupilFunction(filename, size, pixel_size, zmn, z_offset = 0.0, geo_sim_pf = True):
    """
    filename - The name of the file to save the pupil function in.
    size - The size of the pupil function in pixels.
    pixel_size - pixel size in microns.
    zmn - Zernike coefficients.
    z_offset - Amount to change the focus by in microns.
    geo_sim_pf - Use the 'simulation' PF with 1/2 the pixel size.
    """    
    # This is a requirement of the C library.
    assert ((size%2)==0)
    
    # Physical constants. Note that these match the default values for
    # simulator.psf.PupilFunction().
    #
    wavelength = 1.0e-3 * simPSF.pf_wavelength  # Fluorescence wavelength in microns.
    imm_index = simPSF.pf_refractive_index      # Immersion media index (oil objective).
    NA = simPSF.pf_numerical_aperture           # Numerical aperture of the objective.

    # Create geometry object.
    if geo_sim_pf:
        geo = pupilMath.GeometrySim(size,
                                    pixel_size,
                                    wavelength,
                                    imm_index,
                                    NA)
        
    else:
        geo = pupilMath.Geometry(size,
                                 pixel_size,
                                 wavelength,
                                 imm_index,
                                 NA)

    # Create PF.
    pf = geo.createFromZernike(1.0, zmn)

    # Normalize to have height 1.0.
    psf = pupilMath.intensity(pupilMath.toRealSpace(pf))
    pf = pf * 1.0/math.sqrt(numpy.max(psf))

    # Verify normalization.
    print("Height:", numpy.max(pupilMath.intensity(pupilMath.toRealSpace(pf))))

    # Heh, if zmn is an empty list the pupil function will be perfectly
    # symmetric at z = 0 and the solver will fail because dz = 0. So we
    # solve this we adding a little noise.
    if (len(zmn) == 0):
        print("Plane wave PF detected! Adding noise to break z = 0 symmetry!")
        n_mag = numpy.real(pf) * 1.0e-3
        pf = pf + n_mag * (numpy.random.uniform(size = pf.shape) - 0.5)
    
    # Change focus by z_offset.
    #
    # The convention is that if z_offset + localization z is the final
    # z position, so if localization z is = -z_offset then you will get
    # the PSF at z = 0.
    #
    pf = geo.changeFocus(pf, -z_offset)

    # Pickle and save.
    pfn_dict = {"pf" : pf,
                "pixel_size" : pixel_size,
                "geo_sim_pf" : geo_sim_pf,
                "wavelength" : wavelength,
                "immersion_index" : imm_index,
                "numerical_aperture" : NA}

    with open(filename, 'wb') as fp:
        pickle.dump(pfn_dict, fp)
Beispiel #34
0
def makePupilFunction(filename,
                      size,
                      pixel_size,
                      zmn,
                      z_offset=0.0,
                      geo_sim_pf=True):
    """
    geo_sim_pf - Use the 'simulation' PF with 1/2 the pixel size.
    pixel_size - pixel size in microns.
    zmn - Zernike coefficients.
    z_offset - Amount to change the focus by in microns.
    """
    # This is a requirement of the C library.
    assert ((size % 2) == 0)

    # Physical constants. Note that these match the default values for
    # simulator.psf.PupilFunction().
    #
    wavelength = 1.0e-3 * simPSF.pf_wavelength  # Fluorescence wavelength in microns.
    imm_index = simPSF.pf_refractive_index  # Immersion media index (oil objective).
    NA = simPSF.pf_numerical_aperture  # Numerical aperture of the objective.

    # Create geometry object.
    if geo_sim_pf:
        geo = pupilMath.GeometrySim(size, pixel_size, wavelength, imm_index,
                                    NA)

    else:
        geo = pupilMath.Geometry(size, pixel_size, wavelength, imm_index, NA)

    # Create PF.
    pf = geo.createFromZernike(1.0, zmn)

    # Normalize to have height 1.0.
    psf = pupilMath.intensity(pupilMath.toRealSpace(pf))
    pf = pf * 1.0 / math.sqrt(numpy.max(psf))

    # Verify normalization.
    print("Height:", numpy.max(pupilMath.intensity(pupilMath.toRealSpace(pf))))

    # Heh, if zmn is an empty list the pupil function will be perfectly
    # symmetric at z = 0 and the solver will fail because dz = 0. So we
    # solve this we adding a little noise.
    if (len(zmn) == 0):
        print("Plane wave PF detected! Adding noise to break z = 0 symmetry!")
        n_mag = numpy.real(pf) * 1.0e-3
        pf = pf + n_mag * (numpy.random.uniform(size=pf.shape) - 0.5)

    # Change focus by z_offset.
    #
    # The convention is that if z_offset + localization z is the final
    # z position, so if localization z is = -z_offset then you will get
    # the PSF at z = 0.
    #
    pf = geo.changeFocus(pf, -z_offset)

    # Pickle and save.
    pfn_dict = {
        "pf": pf,
        "pixel_size": pixel_size,
        "geo_sim_pf": geo_sim_pf,
        "wavelength": wavelength,
        "immersion_index": imm_index,
        "numerical_aperture": NA
    }

    with open(filename, 'wb') as fp:
        pickle.dump(pfn_dict, fp)