Beispiel #1
0
    def __init__(self,
                 nx=256,
                 dx=0.1,
                 l=0.68,
                 n=1.33,
                 NA=1.27,
                 f=9000,
                 wavelengths=10,
                 wavelength_halfmax=0.005):

        dx = float(dx)
        self.dx = dx
        l = float(l)
        n = float(n)
        NA = float(NA)
        f = float(f)
        self.nx = nx
        self.ny = nx

        Pupil.__init__(self, l, n, NA, f)

        self.numWavelengths = wavelengths

        # Frequency sampling:
        dk = 1 / (nx * dx)
        # Pupil function pixel grid:
        x, y = _np.mgrid[-nx / 2.:nx / 2., -nx / 2.:nx / 2.] + 0.5
        self.x_pxl = x
        self.y_pxl = y
        self.r_pxl = _msqrt(x**2 + y**2)

        # Pupil function frequency space:
        kx = dk * x
        ky = dk * y
        self.k = _msqrt(kx**2 + ky**2)

        # Axial Fourier space coordinate:
        self.kz = _msqrt((n / l)**2 - self.k**2)
        self.kzs = _np.zeros(
            (self.numWavelengths, self.kz.shape[0], self.kz.shape[1]),
            dtype=self.kz.dtype)
        ls = _np.linspace(l - wavelength_halfmax, l + wavelength_halfmax,
                          self.kzs.shape[0])
        for i in range(0, self.kzs.shape[0]):
            self.kzs[i] = _msqrt((n / ls[i])**2 - self.k**2)

        # Scaled pupil function radial coordinate:
        self.r = self.k / self.k_max

        self.s = self.unit_disk_to_spatial_radial_coordinate(self.r)
        self.alpha = self.spatial_radial_coordinate_to_optical_angle(self.s)
        self.m = self.spatial_radial_coordinate_to_xy_slope(self.alpha)

        # Plane wave:
        self.plane = _np.ones((nx, nx)) + 1j * _np.zeros((nx, nx))
        self.plane[self.k > self.k_max] = 0
        self.pupil_npxl = abs(self.plane.sum())

        self.kx = kx
        self.theta = _np.arctan2(y, x)
Beispiel #2
0
    def __init__(self,
                 nx=256,
                 dx=0.1,
                 l=0.68,
                 n=1.33,
                 NA=1.27,
                 f=3333.33,
                 wavelengths=10,
                 wave_step=0.005):

        dx = float(dx)
        self.dx = dx
        l = float(l)
        n = float(n)
        NA = float(NA)
        f = float(f)
        self.nx = nx
        self.ny = nx
        Pupil.__init__(self, l, n, NA, f)

        self.numWavelengths = wavelengths

        dk = 1 / (nx * dx)
        self.k_pxl = int(self.k_max / dk)
        print("The pixel radius of pupil:", self.k_pxl)
        # Pupil function pixel grid:
        Mx, My = _np.mgrid[-nx / 2.:nx / 2., -nx / 2.:nx / 2.] + 0.5
        self.x_pxl = Mx  # pixel grid in x
        self.y_pxl = My  # pixel grid in y
        self.r_pxl = _msqrt(Mx**2 +
                            My**2)  # why the x,y,r_pxl are dimensionless?
        # Pupil function frequency space:
        kx = dk * Mx
        ky = dk * My
        self.k = _msqrt(
            kx**2 + ky**2)  # This is in the unit of 1/x # this is a 2-D array
        out_pupil = self.k > self.k_max
        # Axial Fourier space coordinate:
        self.kz = _msqrt((n / l)**2 - self.k**2)
        self.kz[out_pupil] = 0
        self.kzs = _np.zeros(
            (self.numWavelengths, self.kz.shape[0], self.kz.shape[1]),
            dtype=self.kz.dtype)
        ls = _np.linspace(l - wave_step, l + wave_step, self.numWavelengths)
        for i in range(0, self.kzs.shape[0]):
            self.kzs[i] = _msqrt((n / ls[i])**2 - self.k**2)
            self.kzs[i, out_pupil] = 0
        # Scaled pupil function radial coordinate:
        self.r = self.k / self.k_max  # Should be dimension-less
        self.s = self.unit_disk_to_spatial_radial_coordinate(
            self.r)  # The real radius of the pupil.

        # Plane wave:
        self.plane = _np.ones((nx, nx)) + 1j * _np.zeros((nx, nx))
        self.plane[self.k > self.k_max] = 0  # Outside the pupil: set to zero
        self.pupil_npxl = abs(self.plane.sum())  # how many non-zero pixels

        self.kx = kx  # This is not used
        self.theta = _np.arctan2(My, Mx)  # Polar coordinate: angle
Beispiel #3
0
    def __init__(self, nx=256, dx=0.1, l=0.68, n=1.33, NA=1.27, f=3333.33, wavelengths=10, wavelength_halfmax=0.005):

        dx = float(dx)
        self.dx = dx
        l = float(l)
        n = float(n)
        NA = float(NA)
        f = float(f)
        self.nx = nx
        self.ny = nx
        Pupil.__init__(self, l, n, NA, f)

        self.numWavelengths = wavelengths

        # Frequency sampling:
        dk = 1/(nx*dx) # What should dx be? 
        self.k_pxl = int(self.k_max/dk)
        print("The pixel radius of pupil:", self.k_pxl)
        # Pupil function pixel grid:
        Mx,My = _np.mgrid[-nx/2.:nx/2.,-nx/2.:nx/2.]+0.5
        self.x_pxl = Mx # pixel grid in x  
        self.y_pxl = My # pixel grid in y
        self.r_pxl = _msqrt(Mx**2+My**2) # why the x,y,r_pxl are dimensionless?
        # Pupil function frequency space: 
        kx = dk*Mx 
        ky = dk*My
        self.k = _msqrt(kx**2+ky**2) # This is in the unit of 1/x # this is a 2-D array 
#         self.k = _msqrt(kx**2+ky**2)# This is in the unit of 1/x # this is a 2-D array 
        out_pupil = self.k>self.k_max
        # Axial Fourier space coordinate:
        self.kz = _msqrt((n/l)**2-self.k**2)
        self.kz[out_pupil] = 0
#         self.kz.imag = 0 # brutal force
        print(self.kz.dtype)
        self.kzs = _np.zeros((self.numWavelengths,self.kz.shape[0],self.kz.shape[1]),dtype=self.kz.dtype)
        ls = _np.linspace(l-wavelength_halfmax,l+wavelength_halfmax,self.numWavelengths)
        for i in range(0,self.kzs.shape[0]):
            self.kzs[i] = _msqrt((n/ls[i])**2-self.k**2)
            self.kzs[i,out_pupil] = 0
#             self.kzs.imag = 0 # brutal force
        # Scaled pupil function radial coordinate:
        self.r = self.k/self.k_max # Should be dimension-less
        self.s = self.unit_disk_to_spatial_radial_coordinate(self.r) # The real radius of the pupil. 
        self.alpha = self.spatial_radial_coordinate_to_optical_angle(self.s)
        self.m = self.spatial_radial_coordinate_to_xy_slope(self.alpha) # Should this be inverted?  And self.m is not used at all...

        # Plane wave:
        self.plane = _np.ones((nx,nx))+1j*_np.zeros((nx,nx))
        self.plane[self.k>self.k_max] = 0 # Outside the pupil: set to zero
        self.pupil_npxl = abs(self.plane.sum()) # how many non-zero pixels

        self.kx = kx # This is not used
        self.theta = _np.arctan2(My,Mx) # Polar coordinate: angle
    def __init__(self, control, im_size, maskRadius, maskCenter, pixelSize, diffLimit, plotWidget,
                 varyZern=False):
        QtCore.QThread.__init__(self)
        self.control = control
        self.pixelSize = pixelSize
        self.diffLimit = diffLimit
        self.maskRadius = maskRadius
        self.maskCenter = maskCenter
        self.plotWidget = plotWidget

        self._on = True
        self._varyZern = varyZern
        self.numZernsToVary = 100
        self._zerns = 0
                                               

        nx,ny = im_size

        if maskCenter[0] > -1 and maskCenter[1]>-1:
            x,y = np.meshgrid(np.arange(nx),np.arange(ny))
            x -= maskCenter[0]
            y -= maskCenter[1]
            r_pxl = _msqrt(x**2 + y**2)
            mask = r_pxl<maskRadius
            self.mask = mask
        else:
            self.mask = None
    def __init__(self,
                 control,
                 im_size,
                 maskRadius,
                 maskCenter,
                 pixelSize,
                 diffLimit,
                 plotWidget,
                 numToVary=100,
                 varyZern=False,
                 wait_time=0.1):
        '''
        Finds sharpness

        Parameters
            :control: class
            :im_size: (int,int)
            :maskRadius: int
            :maskCenter: int
            :pixelSize: int
            :diffLimit: int
                Diffraction limited resolution (in same units as pixelSize)
            :plotWidget:
            :numToVary: int
                Optional
            :varyZern: boolean
                Optional
            :wait_time: float
                Optional. Time between patterns applied to adaptive optics device (seconds)

        Emits signal 'nextModulation(int)' when ready to add new modulation...
            nextModulation takes parameter that counts upward from 0
        Emits signal 'doneAdvancingZern' when done


        '''
        QtCore.QThread.__init__(self)
        self.control = control
        self.pixelSize = pixelSize
        self.diffLimit = diffLimit
        self.maskRadius = maskRadius
        self.maskCenter = maskCenter
        self.plotWidget = plotWidget
        self.wait_time = wait_time
        self._on = True
        self._varyZern = varyZern
        self.numZernsToVary = numToVary
        self._zerns = 0

        nx, ny = im_size

        if maskCenter[0] > -1 and maskCenter[1] > -1:
            x, y = np.meshgrid(np.arange(nx), np.arange(ny))
            x -= maskCenter[0]
            y -= maskCenter[1]
            r_pxl = _msqrt(x**2 + y**2)
            mask = r_pxl < maskRadius
            self.mask = mask
        else:
            self.mask = None
    def __init__(self, control, im_size, maskRadius, maskCenter, pixelSize, diffLimit, plotWidget,
                 varyZern=False):
        QtCore.QThread.__init__(self)
        self.control = control
        self.pixelSize = pixelSize
        self.diffLimit = diffLimit
        self.maskRadius = maskRadius
        self.maskCenter = maskCenter
        self.plotWidget = plotWidget

        self._on = True
        self._varyZern = varyZern
        self.numZernsToVary = 100
        self._zerns = 0
                                               

        nx,ny = im_size

        if maskCenter[0] > -1 and maskCenter[1]>-1:
            x,y = np.meshgrid(np.arange(nx),np.arange(ny))
            x -= maskCenter[0]
            y -= maskCenter[1]
            r_pxl = _msqrt(x**2 + y**2)
            mask = r_pxl<maskRadius
            self.mask = mask
        else:
            self.mask = None
Beispiel #7
0
    def retrievePF(self, bscale=1.00, psf_diam=50, resample=None):
        # an ultrasimplified version
        # comment on 08/12: I am still not convinced of the way of setting background.

        z_offset, zz = psf_zplane(self.PSF, self.dz, self.l /
                                  3.2)  # This should be the reason!!!! >_<
        A = self.PF.plane
        #         z_offset = -z_offset # To deliberately add something wrong
        Mx, My = np.meshgrid(
            np.arange(self.nx) - self.nx / 2.,
            np.arange(self.nx) - self.nx / 2.)
        r_pxl = _msqrt(Mx**2 + My**2)
        bk_inner = 16
        bk_outer = 20
        hcyl = np.array(self.nz *
                        [np.logical_and(r_pxl >= bk_inner, r_pxl < bk_outer)])
        background = np.mean(self.PSF[hcyl]) * bscale
        print("   background = ", background)
        print("   z_offset = ", z_offset)
        if (resample == False):
            PSF_sample = self.PSF
            zs = zz - z_offset
        else:
            PSF_sample = self.PSF[::resample]
            zs = zz[::resample] - z_offset
        complex_PF = self.PF.psf2pf(PSF_sample, zs, background, A, self.nIt)
        Pupil_final = _PupilFunction(complex_PF, self.PF)
        self.pf_complex = Pupil_final.complex
        self.pf_phase = unwrap_phase(Pupil_final.phase)
        self.pf_ampli = Pupil_final.amplitude
Beispiel #8
0
 def compute_pupil_function(z):
     phase = (2*_np.pi*n*(_msqrt(f**2*(1+m**2)-z**2)-m*z))/ \
             (l*_msqrt(1+m**2))
     if coverslip_tilt != 0:
         # Angle between ray and coverslip normal:
         d = _np.arccos(_np.sin(a)*_np.sin(e) * \
                 (_np.cos(t)*_np.cos(g)+_np.sin(t)*_np.sin(g)) + \
                 _np.cos(a)*_np.cos(e))
         # Path length through coverslip:
         p = d / _np.sqrt(1 + (n * _np.sin(d) / ng)**2)
         # The correction collar takes care of none tilt based differences:
         p -= d / _np.sqrt(1 + (n * _np.sin(a) / ng)**2)
         # Path length to phase conversion:
         p *= ng * 2 * _np.pi / l
         phase += p
     PF = _np.sqrt(n_photons / self.pupil_npxl) * _np.exp(1j * phase)
     PF = _np.nan_to_num(PF)
     return self.apply_NA_restriction(PF)
    def __init__(self, control, im_size, maskRadius, maskCenter, pixelSize, diffLimit, plotWidget,
                 numToVary = 100, varyZern=False, wait_time = 0.1):
        '''
        Finds sharpness

        Parameters
            :control: class
            :im_size: (int,int)
            :maskRadius: int
            :maskCenter: int
            :pixelSize: int
            :diffLimit: int
                Diffraction limited resolution (in same units as pixelSize)
            :plotWidget:
            :numToVary: int
                Optional
            :varyZern: boolean
                Optional
            :wait_time: float
                Optional. Time between patterns applied to adaptive optics device (seconds)

        Emits signal 'nextModulation(int)' when ready to add new modulation...
            nextModulation takes parameter that counts upward from 0
        Emits signal 'doneAdvancingZern' when done
        

        '''
        QtCore.QThread.__init__(self)
        self.control = control
        self.pixelSize = pixelSize
        self.diffLimit = diffLimit
        self.maskRadius = maskRadius
        self.maskCenter = maskCenter
        self.plotWidget = plotWidget
        self.wait_time = wait_time
        self._on = True
        self._varyZern = varyZern
        self.numZernsToVary = numToVary
        self._zerns = 0
                                               

        nx,ny = im_size

        if maskCenter[0] > -1 and maskCenter[1]>-1:
            x,y = np.meshgrid(np.arange(nx),np.arange(ny))
            x -= maskCenter[0]
            y -= maskCenter[1]
            r_pxl = _msqrt(x**2 + y**2)
            mask = r_pxl<maskRadius
            self.mask = mask
        else:
            self.mask = None
 def __init__(self, size, cx, cy, d):
     # cx, cy: the pupil center 
     self.cx = float(cx)
     self.cy = float(cy)
     self.d = float(d)
     self.size = size
     self.nx, self.ny = size
     self.x_pxl, self.y_pxl = _np.meshgrid(_np.arange(self.nx),_np.arange(self.ny))
     self.x_pxl -= cx
     self.y_pxl -= cy
     self.r_pxl = _msqrt(self.x_pxl**2+self.y_pxl**2) # the radial coordinate in the unit of 1 (grid number )
     self.r = 2.0*self.r_pxl/d # the radial coordinate coordinate in the unit of length. Theoretically between 0 and 1.
     self.theta = _np.arctan2(self.y_pxl, self.x_pxl)
     self.x = 2.0*self.x_pxl/d # so self.x and y are in the range of (0,1)
     self.y = 2.0*self.y_pxl/d # But, isn't d the same with nx, ny?
        def compute_pupil_function(z):
            phase = (2*_np.pi*n*(_msqrt(f**2*(1+m**2)-z**2)-m*z))/ \
                    (l*_msqrt(1+m**2))
            if coverslip_tilt != 0:
                # Angle between ray and coverslip normal:
                d = _np.arccos(_np.sin(a)*_np.sin(e) * \
                        (_np.cos(t)*_np.cos(g)+_np.sin(t)*_np.sin(g)) + \
                        _np.cos(a)*_np.cos(e))
                # Path length through coverslip:
                p = d/_np.sqrt(1+(n*_np.sin(d)/ng)**2)
                # The correction collar takes care of none tilt based differences:
                p -= d/_np.sqrt(1+(n*_np.sin(a)/ng)**2)
                # Path length to phase conversion:
                p *= ng*2*_np.pi/l
                phase += p
            PF = _np.sqrt(n_photons/self.pupil_npxl)*_np.exp(1j*phase)
            PF = _np.nan_to_num(PF)
            return self.apply_NA_restriction(PF)

            if _np.ndim(z) == 0 or _np.ndim(z) == 2:
                return compute_pupil_function(z)

            elif _np.ndim(z) == 1:
                return _np.array([compute_pupil_function(_) for _ in z])
Beispiel #12
0
    def __init__(self, size, cx, cy, d):

        self.cx = float(cx)
        self.cy = float(cy)
        self.d = float(d)
        self.size = size
        self.ny, self.nx = size
        self.x_pxl, self.y_pxl = _np.meshgrid(_np.arange(self.nx),
                                              _np.arange(self.ny))
        self.x_pxl -= int(self.cx)
        self.y_pxl -= int(self.cy)
        self.r_pxl = _msqrt(self.x_pxl**2 + self.y_pxl**2)
        self.r = 2.0 * self.r_pxl / d
        self.theta = _np.arctan2(self.y_pxl, self.x_pxl)
        self.x = 2.0 * self.x_pxl / d
        self.y = 2.0 * self.y_pxl / d
Beispiel #13
0
    def retrievePF(self, dz, psf_diam):
        # an ultrasimplified version

        z_offset, zz = psf_zplane(self.PSF, dz, self.lcenter/3.2) # This should be the reason!!!! >_<
        A = self.PF.plane
        Mx, My = np.meshgrid(np.arange(self.nx)-self.nx/2., np.arange(self.nx)-self.nx/2.)
        r_pxl = _msqrt(Mx**2 + My**2)
        bk_inner = psf_diam
        bk_outer = (psf_diam+self.nx/2)/2 # updated on 05/15
        hcyl = np.array(self.nz*[np.logical_and(r_pxl>=bk_inner, r_pxl<bk_outer)])
        background = np.mean(self.PSF[hcyl])
        print( "   background = ", background)
        print( "   z_offset = ", z_offset)
        PSF_sample = self.PSF
        zs = zz-z_offset
        complex_PF = self.PF.psf2pf(PSF_sample, zs, background, A, self.nIt)
        Pupil_final = _PupilFunction(complex_PF, self.PF)
        self.pf_complex = Pupil_final.complex
        self.pf_phase = unwrap_phase(Pupil_final.phase)
        self.pf_ampli = Pupil_final.amplitude
Beispiel #14
0
    def background_reset(self, mask, psf_diam):
        '''
        reset the background of the PSF
        mask is the outer diameter
        psf_diam is the inner diameter
        '''
        Mx, My = np.meshgrid(
            np.arange(self.nx) - self.nx / 2.,
            np.arange(self.nx) - self.nx / 2.)
        r_pxl = _msqrt(Mx**2 + My**2)
        bk_inner = psf_diam
        bk_outer = mask
        hcyl = np.array(
            self.nz *
            [np.logical_and(r_pxl >= bk_inner, r_pxl < bk_outer + 1)])
        incyl = np.array(self.nz * [r_pxl < bk_outer])
        background = np.mean(self.PSF[hcyl])
        self.PSF[np.logical_not(incyl)] = background

        return background
Beispiel #15
0
    def spatial_radial_coordinate_to_xy_slope(self, s):

        _mc = _msqrt((self.n * self.f / self.s)**2 - 1)
        return _np.real(_mc) - _np.imag(_mc)
def retrievePF(PSF, dx, dz, l, n, NA, f, nIt, bscale=1.0, neglect_defocus=True,
                   invert=False, wavelengths=1, resetAmp=False,
                   symmeterize=False):

    z_offset = 0
    if neglect_defocus:
            # We try to estimate the axial position of the emitter
            # The coordinates of the brightest pixel
        cz, cx, cy = np.unravel_index(PSF.argmax(), PSF.shape)
            # Intensity trace along z
        i = PSF[:,cx,cy]
            # Get z positions
        nz = PSF.shape[0]
        upper = 0.5*(nz-1)*dz
        z = np.linspace(-upper, upper, nz)
            # Initial fit parameters
        b = np.mean((i[0],i[-1]))
        a = i.max() - b
        w = l/3.2
        p0 = (a,0,w,b)
        def gaussian(z, a, z0, w, b):
            return a * np.exp(-(z-z0)**2/w) + b
            # Fit gaussian to axial intensity trace
        popt, pcov = optimize.curve_fit(gaussian, z, i, p0)
            # Where we think the emitter is axially located:
        z_offset = -1.0*popt[1] #Added on April 3, 2015
#         plt.plot(z, i)
#         plt.plot(z, gaussian(z,*popt))
#         plt.savefig('z_fit.png')
    
    nx,ny = PSF.shape[1:3]
    PF = pupil.Simulation(nx,dx,l,n,NA,f,wavelengths=wavelengths)
#         self, nx=256, dx=0.1, l=0.68, n=1.33, NA=1.27, f=3333.33, wavelengths=10, wavelength_halfmax=0.005
    A = PF.plane
    
    Mx, My = np.meshgrid(np.arange(nx)-nx/2., np.arange(nx)-nx/2.)
    r_pxl = _msqrt(Mx**2 + My**2)
    
    hcyl = np.array(nz*[np.logical_and(r_pxl>=65, r_pxl<76)])
    background = np.mean(PSF[hcyl])*bscale
    print "Finding PF..."
    print "   Using parameters:"
    print "   dz = ", dz
    print "   background = ", background
    print "   z_offset = ", z_offset
    complex_PF = PF.psf2pf(PSF, dz, background, A, nIt, z_offset,
                                        resetAmp=resetAmp,symmeterize=symmeterize)
#       def psf2pf(self, PSF, dz, mu, A, nIterations=10, z_offset=0, use_pyfftw=True, resetAmp=True,
#                symmeterize=False):

    if invert:
        complex_PF = abs(complex_PF) * np.exp(-1*1j*np.angle(complex_PF))

    Pupil_final = _PupilFunction(complex_PF, PF)

    nz = PSF.shape[0]
    upper = 0.5*(nz-1)*dz
    z = np.linspace(-upper, upper, nz)
    psft = PF.pf2psf(complex_PF, z)
#         def psf2pf(self, PSF, dz, mu, A, nIterations=10, z_offset=0, use_pyfftw=True, resetAmp=True,
#                symmeterize=False):
    np.save('retrieved_psf', psft)

    return Pupil_final.phase
Beispiel #17
0
 def spatial_radial_coordinate_to_xy_slope(self, s):
     # what does this one do? What's difference between s and self.s? 
     # This is cot instead of tan.
     _mc = _msqrt((self.n*self.f/self.s)**2-1)
     return _np.real(_mc) - _np.imag(_mc)
 def spatial_radial_coordinate_to_xy_slope(self, s):
     # what does this one do? What's difference between s and self.s? 
     # This is cot instead of tan.
     _mc = _msqrt((self.n*self.f/self.s)**2-1)
     return _np.real(_mc) - _np.imag(_mc)