Beispiel #1
0
    def __init__(self,
                 sim_fp,
                 x_size,
                 y_size,
                 h5_data,
                 nm_per_pixel,
                 zmn,
                 wavelength=pf_wavelength,
                 refractive_index=pf_refractive_index,
                 numerical_aperture=pf_numerical_aperture,
                 pf_size=pf_size,
                 geo_sim_pf=True):
        """
        zmn is a list of lists containing the zernike mode terms, e.g.
            [[1.3, 2, 2]] for pure astigmatism.
        wavelength is the mean emission wavelength in nm.
        """
        super(PupilFunction, self).__init__(sim_fp, x_size, y_size, h5_data,
                                            nm_per_pixel)
        self.saveJSON({
            "psf": {
                "class": "PupilFunction",
                "geo_sim_pf": str(geo_sim_pf),
                "nm_per_pixel": str(nm_per_pixel),
                "numerical_aperture": str(numerical_aperture),
                "pf_size": str(pf_size),
                "refactrive_index": str(refractive_index),
                "wavelength": str(wavelength),
                "zmn": str(zmn)
            }
        })

        if geo_sim_pf:
            self.geo = pupilMath.GeometrySim(pf_size, nm_per_pixel * 0.001,
                                             wavelength * 0.001,
                                             refractive_index,
                                             numerical_aperture)
        else:
            self.geo = pupilMath.Geometry(pf_size, nm_per_pixel * 0.001,
                                          wavelength * 0.001, refractive_index,
                                          numerical_aperture)

        self.pf = self.geo.createFromZernike(1.0, zmn)
        self.psf_size = self.geo.r.shape[0]

        if ((self.psf_size % 2) == 0):
            self.margin = int(self.psf_size / 2) + 1
        else:
            self.margin = int(self.psf_size / 2) + 2

        self.im_size_x = self.x_size + 2 * self.margin
        self.im_size_y = self.y_size + 2 * self.margin
Beispiel #2
0
    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 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)
Beispiel #4
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)
Beispiel #5
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)