예제 #1
0
 def setUp(self):
     ins = Instrument(magnification=.048, wavelength=.447, n_m=1.335)
     p1 = Sphere(r_p=[150, 150, 200], a_p=1., n_p=1.45)
     p2 = Sphere(r_p=[75, 75, 150], a_p=1.25, n_p=1.61)
     coords = coordinates((201, 201))
     self.model = GeneralizedLorenzMie(coords, [p1, p2], ins)
     self.fast_model = FastGeneralizedLorenzMie(coords, [p1, p2], ins)
     self.cuda_model = CudaGeneralizedLorenzMie(coords, [p1, p2], ins)
예제 #2
0
 def __init__(self, initial, image=None, instrument=None, **kwargs):
     self.df = pd.DataFrame(columns=Feature().model.particle.properties,
                            index=initial.index)
     self.df = self.df.join(pd.DataFrame(columns=['w', 'h']))
     self.df['optimized'] = False
     self.df = self.df.fillna(initial)
     self.image = image
     self.instrument = Instrument(
         **kwargs) if instrument is None else instrument
예제 #3
0
    def __init__(self,
                 model_path=None,
                 instrument=None,
                 config_file=None):

        '''
        Parameters
        ----------
        instrument: instrument object
            Object resprenting the light-scattering instrument
        config: json config file from training
        model_path: str
            path to model.h5 file
        '''
        
        ###################################
        # TensorFlow wizardry
        config = tf.compat.v1.ConfigProto()
        
        # Don't pre-allocate memory; allocate as-needed
        config.gpu_options.allow_growth = True
 
        # Only allow a total of half the GPU memory to be allocated
        config.gpu_options.per_process_gpu_memory_fraction = 0.5
 
        # Create a session with the above options specified.
        tf.compat.v1.keras.backend.set_session(tf.compat.v1.Session(config=config))
        ###################################
        self.params_range = {}
        if instrument is None:
            self.instrument = Instrument()
        else:
            self.instrument = instrument
        if config_file is None:
            self.params_range['z_p'] = [50, 600]
            self.params_range['a_p'] = [0.2, 5.0]
            self.params_range['n_p'] = [1.38, 2.5]
        else:
            ins = config_file['instrument']
            self.instrument.wavelength = ins['wavelength']
            self.instrument.magnification = ins['magnification']
            self.instrument.n_m = ins['n_m']
            particle = config_file['particle']
            self.params_range['z_p'] = particle['z_p']
            self.params_range['a_p'] = particle['a_p']
            self.params_range['n_p'] = particle['n_p']
        if model_path is None:
            self.model=keras.models.Sequential()
            pix = (None, None)
        else:
            loaded = keras.models.load_model(model_path)
            loaded.summary()
            self.model= loaded
            (a,b,c,d) = loaded.input_shape[0]
            pix = (b,c)
        self.pixels = pix
예제 #4
0
 def __init__(self, images=[], detector=None, estimator=None, **kwargs):
     ##        self._detector = None  # should be YOLO
     ##        self.estimator = Estimator(model_path='CNNLorenzMie/keras_models/predict_stamp_fullrange_adamnew_extnoise_lowscale.h5') if estimator is None else estimator
     ##        self.instrument = self.estimator.instrument
     self.detector = detector
     self.estimator = estimator
     self.instrument = Instrument(
         **kwargs) if estimator is None else estimator.instrument
     self._frames = []
     self.set_frames(images)
예제 #5
0
 def __init__(self,
              coordinates=None,
              particle=None,
              instrument=None,
              n_m=None,
              magnification=None,
              wavelength=None):
     '''
     Parameters
     ----------
     coordinates : numpy.ndarray
        [3, npts] array of x, y and z coordinates where field
        is calculated
     particle : Particle
        Object representing the particle scattering light
     instrument : Instrument
        Object resprenting the light-scattering instrument
     n_m : complex, optional
        Refractive index of medium
     magnification : float, optional
        Magnification of microscope [um/pixel]
     wavelength : float, optional
        Vacuum wavelength of light [um]
     '''
     self.coordinates = coordinates
     self.particle = particle
     if instrument is None:
         self.instrument = Instrument()
     else:
         self.instrument = instrument
     if n_m is not None:
         self.instrument.n_m = n_m
     if magnification is not None:
         self.instrument.magnification = magnification
     if wavelength is not None:
         self.instrument.wavelength = wavelength
예제 #6
0
 def __init__(self,
              config_path='',
              meta_path='',
              weight_path='',
              instrument=None):
     self.config_path = config_path
     self.meta_path = meta_path
     self.weight_path = weight_path
     if instrument is None:
         self.instrument = Instrument()
     else:
         self.instrument = instrument
     performDetect(configPath=config_path,
                   weightPath=weight_path,
                   metaPath=meta_path,
                   showImage=False,
                   initOnly=True)
예제 #7
0
class GeneralizedLorenzMie(object):
    '''
    A class that computes scattered light fields

    ...

    Attributes
    ----------
    particle : Particle
        Object representing the particle scattering light
    instrument : Instrument
        Object resprenting the light-scattering instrument
    coordinates : numpy.ndarray
        [3, npts] array of x, y and z coordinates where field
        is calculated

    Methods
    -------
    field(cartesian=True, bohren=True)
        Returns the complex-valued field at each of the coordinates.
    '''
    def __init__(self,
                 coordinates=None,
                 particle=None,
                 instrument=None,
                 n_m=None,
                 magnification=None,
                 wavelength=None):
        '''
        Parameters
        ----------
        coordinates : numpy.ndarray
           [3, npts] array of x, y and z coordinates where field
           is calculated
        particle : Particle
           Object representing the particle scattering light
        instrument : Instrument
           Object resprenting the light-scattering instrument
        n_m : complex, optional
           Refractive index of medium
        magnification : float, optional
           Magnification of microscope [um/pixel]
        wavelength : float, optional
           Vacuum wavelength of light [um]
        '''
        self.coordinates = coordinates
        self.particle = particle
        if instrument is None:
            self.instrument = Instrument()
        else:
            self.instrument = instrument
        if n_m is not None:
            self.instrument.n_m = n_m
        if magnification is not None:
            self.instrument.magnification = magnification
        if wavelength is not None:
            self.instrument.wavelength = wavelength

    @property
    def coordinates(self):
        '''Three-dimensional coordinates at which field is calculated'''
        return self._coordinates

    @coordinates.setter
    def coordinates(self, coordinates):
        try:
            shape = coordinates.shape
        except AttributeError:
            self._coordinates = None
            return
        if coordinates.ndim == 1:
            self._coordinates = np.zeros((3, shape[0]))
            self._coordinates[0, :] = coordinates
        elif shape[0] == 2:
            self._coordinates = np.zeros((3, shape[1]))
            self._coordinates[[0, 1], :] = coordinates
        else:
            self._coordinates = coordinates
        self._allocate(self._coordinates.shape)

    @property
    def particle(self):
        '''Particle responsible for light scattering'''
        return self._particle

    @particle.setter
    def particle(self, particle):
        try:
            if isinstance(particle[0], Particle):
                self._particle = particle
        except TypeError:
            if isinstance(particle, Particle):
                self._particle = particle

    @property
    def instrument(self):
        '''Imaging instrument'''
        return self._instrument

    @instrument.setter
    def instrument(self, instrument):
        if isinstance(instrument, Instrument):
            self._instrument = instrument

    def dumps(self, **kwargs):
        '''Returns JSON string of adjustable properties

        Parameters
        ----------
        Accepts all keywords of json.dumps()

        Returns
        -------
        str : string
            JSON-encoded string of properties
        '''
        return json.dumps(self.properties, **kwargs)
        s = {
            'particle': self.particle.dumps(**kwargs),
            'instrument': self.instrument.dumps(**kwargs)
        }
        return json.dumps(s, **kwargs)

    def loads(self, str):
        '''Loads JSON strong of adjustable properties

        Parameters
        ----------
        str : string
            JSON-encoded string of properties
        '''
        s = json.loads(str)
        self.particle.loads(s['particle'])
        self.instrument.loads(s['instrument'])

    def _allocate(self, shape):
        '''Allocates data structures for calculation'''
        pass

    def compute(self, ab, krv, cartesian=True, bohren=True):
        '''Returns the field scattered by the particle at each coordinate

        Parameters
        ----------
        ab : numpy.ndarray
            [2, norders] Mie scattering coefficients
        krv : numpy.ndarray
            Reduced vector displacements of particle from image coordinates
        cartesian : bool
            If set, return field projected onto Cartesian coordinates.
            Otherwise, return polar projection.
        bohren : bool
            If set, use sign convention from Bohren and Huffman.
            Otherwise, use opposite sign convention.

        Returns
        -------
        field : numpy.ndarray
            [3, npts] array of complex vector values of the
            scattered field at each coordinate.
        '''
        norders = ab.shape[0]  # number of partial waves in sum

        # GEOMETRY
        # 1. particle displacement [pixel]
        # Note: The sign convention used here is appropriate
        # for illumination propagating in the -z direction.
        # This means that a particle forming an image in the
        # focal plane (z = 0) is located at positive z.
        # Accounting for this by flipping the axial coordinate
        # is equivalent to using a mirrored (left-handed)
        # coordinate system.
        shape = krv.shape
        kx = krv[0, :]
        ky = krv[1, :]
        kz = -krv[2, :]

        # 2. geometric factors
        phi = np.arctan2(ky, kx)
        cosphi = np.cos(phi)
        sinphi = np.sin(phi)

        krho = np.sqrt(kx**2 + ky**2)
        theta = np.arctan2(krho, kz)
        costheta = np.cos(theta)
        sintheta = np.sin(theta)

        kr = np.sqrt(krho**2 + kz**2)
        sinkr = np.sin(kr)
        coskr = np.cos(kr)

        # SPECIAL FUNCTIONS
        # starting points for recursive function evaluation ...
        # 1. Riccati-Bessel radial functions, page 478.
        # Particles above the focal plane create diverging waves
        # described by Eq. (4.13) for $h_n^{(1)}(kr)$. These have z > 0.
        # Those below the focal plane appear to be converging from the
        # perspective of the camera. They are descrinbed by Eq. (4.14)
        # for $h_n^{(2)}(kr)$, and have z < 0. We can select the
        # appropriate case by applying the correct sign of the imaginary
        # part of the starting functions...
        if bohren:
            factor = 1.j * np.sign(kz)
        else:
            factor = -1.j * np.sign(kz)
        xi_nm2 = coskr + factor * sinkr  # \xi_{-1}(kr)
        xi_nm1 = sinkr - factor * coskr  # \xi_0(kr)

        # 2. Angular functions (4.47), page 95
        pi_nm1 = 0.  # \pi_0(\cos\theta)
        pi_n = 1.  # \pi_1(\cos\theta)

        # 3. Vector spherical harmonics: [r,theta,phi]
        mo1n = np.empty(shape, complex)
        mo1n[0, :] = 0.j  # no radial component
        ne1n = np.empty(shape, complex)

        # storage for scattered field
        es = np.zeros(shape, complex)

        # COMPUTE field by summing partial waves
        for n in range(1, norders):
            # upward recurrences ...
            # 4. Legendre factor (4.47)
            # Method described by Wiscombe (1980)
            swisc = pi_n * costheta
            twisc = swisc - pi_nm1
            tau_n = pi_nm1 - n * twisc  # -\tau_n(\cos\theta)

            # ... Riccati-Bessel function, page 478
            xi_n = (2. * n - 1.) * (xi_nm1 / kr) - xi_nm2  # \xi_n(kr)

            # ... Deirmendjian's derivative
            dn = (n * xi_n) / kr - xi_nm1

            # vector spherical harmonics (4.50)
            # mo1n[0, :] = 0.j           # no radial component
            mo1n[1, :] = pi_n * xi_n  # ... divided by cosphi/kr
            mo1n[2, :] = tau_n * xi_n  # ... divided by sinphi/kr

            # ... divided by cosphi sintheta/kr^2
            ne1n[0, :] = n * (n + 1.) * pi_n * xi_n
            ne1n[1, :] = tau_n * dn  # ... divided by cosphi/kr
            ne1n[2, :] = pi_n * dn  # ... divided by sinphi/kr

            # prefactor, page 93
            en = 1.j**n * (2. * n + 1.) / n / (n + 1.)

            # the scattered field in spherical coordinates (4.45)
            es += (1.j * en * ab[n, 0]) * ne1n
            es -= (en * ab[n, 1]) * mo1n

            # upward recurrences ...
            # ... angular functions (4.47)
            # Method described by Wiscombe (1980)
            pi_nm1 = pi_n
            pi_n = swisc + ((n + 1.) / n) * twisc

            # ... Riccati-Bessel function
            xi_nm2 = xi_nm1
            xi_nm1 = xi_n
        # n: multipole sum

        # geometric factors were divided out of the vector
        # spherical harmonics for accuracy and efficiency ...
        # ... put them back at the end.
        radialfactor = 1. / kr
        es[0, :] *= cosphi * sintheta * radialfactor**2
        es[1, :] *= cosphi * radialfactor
        es[2, :] *= sinphi * radialfactor

        np.seterr(all='raise')

        # By default, the scattered wave is returned in spherical
        # coordinates.  Project components onto Cartesian coordinates.
        # Assumes that the incident wave propagates along z and
        # is linearly polarized along x
        if cartesian:
            ec = np.empty_like(es)

            ec[0, :] = es[0, :] * sintheta * cosphi
            ec[0, :] += es[1, :] * costheta * cosphi
            ec[0, :] -= es[2, :] * sinphi

            ec[1, :] = es[0, :] * sintheta * sinphi
            ec[1, :] += es[1, :] * costheta * sinphi
            ec[1, :] += es[2, :] * cosphi
            ec[2, :] = es[0, :] * costheta - es[1, :] * sintheta
            return ec
        else:
            return es

    def field(self, cartesian=True, bohren=True):
        '''Return field scattered by particles in the system'''
        if (self.coordinates is None or self.particle is None):
            return None

        k = self.instrument.wavenumber()
        '''
        try:               # one particle in field of view
            krv = k * (self.coordinates - self.particle.r_p[:, None])
            ab = self.particle.ab(self.instrument.n_m,
                                  self.instrument.wavelength)
            field = self.compute(ab, krv,
                                 cartesian=cartesian, bohren=bohren)
            field *= np.exp(-1j * k * self.particle.z_p)
        except AttributeError:  # list of particles
        '''
        for p in np.atleast_1d(self.particle):
            krv = k * (self.coordinates - p.r_p[:, None])
            ab = p.ab(self.instrument.n_m, self.instrument.wavelength)
            this = self.compute(ab, krv, cartesian=cartesian, bohren=bohren)
            this *= np.exp(-1j * k * p.z_p)
            try:
                field += this
            except NameError:
                field = this
        return field
예제 #8
0
    import matplotlib.pyplot as plt

    # Create coordinate grid for image
    x = np.arange(0, 201)
    y = np.arange(0, 201)
    xv, yv = np.meshgrid(x, y)
    xv = xv.flatten()
    yv = yv.flatten()
    zv = np.zeros_like(xv)
    coordinates = np.stack((xv, yv, zv))
    # Place a sphere in the field of view, above the focal plane
    particle = Sphere()
    particle.r_p = [125, 75, 100]
    particle.a_p = 0.5
    particle.n_p = 1.45
    # Form image with default instrument
    instrument = Instrument()
    instrument.magnification = 0.135
    instrument.wavelength = 0.447
    instrument.n_m = 1.335
    k = instrument.wavenumber()
    # Use Generalized Lorenz-Mie theory to compute field
    kernel = GeneralizedLorenzMie(coordinates, particle, instrument)
    field = kernel.field()
    # Compute hologram from field and show it
    field *= np.exp(-1.j * k * particle.z_p)
    field[0, :] += 1.
    hologram = np.sum(np.real(field * np.conj(field)), axis=0)
    plt.imshow(hologram.reshape(201, 201), cmap='gray')
    plt.show()
예제 #9
0
                            'conf': '50%',
                            'bbox': (df.x[j], df.y[j], 201, 201)
                        }))
                out.append(l)
            return out

    from pylorenzmie.theory.Feature import Feature
    import pylorenzmie.detection.circletransform as ct
    import cv2
    import matplotlib.pyplot as plt

    #### First, let's make a detector and an estimator
    det = MyDetector()
    est = MyEstimator(instrument=Instrument(
        wavelength=.447,  #pixels
        magnification=.048,  #microns/pixel
        n_m=1.340,
        dark_count=13,
        background=1.))

    dark_count = 13
    PATH = 'pylorenzmie/tutorials/video_example/8hz_5V_t_const'

    ######  Next, let's get the images from the video and make a Video object:
    ##
    background = cv2.imread(
        'pylorenzmie/tutorials/video_example/background.png')
    background = cv2.cvtColor(background, cv2.COLOR_BGR2GRAY)
    images = []
    cap = cv2.VideoCapture(PATH + '.avi')
    ret, image = cap.read()
    counter = 0