示例#1
0
    def get_image(self,
                  photons,
                  shot_noise=True,
                  amplifier_noise=True,
                  psf=True,
                  queue=None):
        """Get digital counts image from incoming *photons*. The resulting image is based on the
        incoming photons and dark current. We apply noise based on EMVA 1288 standard according to
        which the variance :math:`\sigma_y^2 = K^2 ( \sigma_e^2 + \sigma_d^2 ) + \sigma_q^2`, where
        :math:`K` is the system gain, :math:`\sigma_e^2` is the poisson- distributed shot noise
        variance, :math:`\sigma_d^2` is the normal distributed electronics noise variance and
        :math:`\sigma_q^2` is the quantization noise variance. If *shot_noise* is False don't apply
        it. If *amplifier_noise* is False don't apply it as well. If *psf* is False don't apply the
        point spread function.
        """
        if self._last_input_shape != photons.shape:
            self._last_input_shape = photons.shape
            self._bin_factor = (photons.shape[0] / self.shape[0],
                                photons.shape[1] / self.shape[1])

        if queue is None:
            queue = cfg.OPENCL.queue

        # Shot noise
        # Adjust dark current for later binning and gain
        dark = float(
            self.dark_current) / self._bin_factor[0] / self._bin_factor[1]
        electrons = dark + gutil.get_host(photons)

        if self._bin_factor != (1, 1):
            if psf:
                sigma = (fwnm_to_sigma(self._bin_factor[0]),
                         fwnm_to_sigma(self._bin_factor[1]))
                small = decimate(electrons,
                                 self.shape,
                                 sigma=sigma,
                                 queue=queue)
            else:
                small = bin_image(electrons, self.shape, queue=queue)
            electrons = gutil.get_host(small)

        if shot_noise:
            electrons = np.random.poisson(electrons)

        if amplifier_noise and self.amplifier_sigma > 0:
            # Add electronics noise
            electrons = np.random.normal(electrons, self.amplifier_sigma)

        counts = self.gain * electrons

        # Cut the values beyond the maximum represented grey value given by
        # bytes per pixel.
        counts[counts > self.max_grey_value] = self.max_grey_value

        # Apply quantization noise
        return counts.astype(self.dtype)
示例#2
0
    def make_source_blur(self, shape, pixel_size, queue=None, block=False):
        """Make geometrical source blurring kernel with *shape* (y, x) size and *pixel_size*. Use
        OpenCL command *queue* and *block* if True.
        """
        l = self.source.sample_distance
        size = self.source.size
        width = (self.propagation_distance * size[1] / l).simplified.magnitude
        height = (self.propagation_distance * size[0] / l).simplified.magnitude
        sigma = (smath.fwnm_to_sigma(height, n=2), smath.fwnm_to_sigma(width, n=2)) * q.m

        return ip.get_gauss_2d(shape, sigma, pixel_size=pixel_size, fourier=True,
                               queue=queue, block=block)
示例#3
0
def make_devices(n, energies, camera=None, highspeed=True, scintillator=None):
    """Create devices with image shape (*n*, *n*), X-ray *energies*, *camera* and use the high speed
    setup if *highspeed* is True.
    """
    shape = (n, n)
    dE = energies[1] - energies[0]

    if not camera:
        vis_wavelengths = np.arange(500, 700) * q.nm
        camera = Camera(11 * q.um, .1, 500, 23, 32, shape, exp_time=1 * q.ms, fps=1000 / q.s,
                        quantum_efficiencies=0.5 * np.ones(len(vis_wavelengths)),
                        wavelengths=vis_wavelengths, dtype=np.float32)
    else:
        vis_wavelengths = camera.wavelengths.rescale(q.nm)

    x = vis_wavelengths.rescale(q.nm).magnitude
    dx = x[1] - x[0]
    if scintillator == 'lso' or not (scintillator or highspeed):
        sigma = fwnm_to_sigma(50)
        emission = np.exp(-(x - 545) ** 2 / (2 * sigma ** 2)) / (sigma * np.sqrt(2 * np.pi))
        lso = get_material('lso_5_30_kev.mat')
        scintillator = Scintillator(13 * q.um,
                                    lso,
                                    36 * np.ones(len(energies)) / q.keV,
                                    energies,
                                    emission / q.nm,
                                    vis_wavelengths,
                                    1.82)
    elif scintillator == 'luag' or (not scintillator and highspeed):
        sigma = fwnm_to_sigma(50)
        emission = np.exp(-(x - 450) ** 2 / (2 * sigma ** 2)) / (sigma * np.sqrt(2 * np.pi))
        luag = get_material('luag.mat')
        scintillator = Scintillator(50 * q.um,
                                    luag,
                                    14 * np.ones(len(energies)) / q.keV,
                                    energies,
                                    emission / q.nm,
                                    vis_wavelengths,
                                    1.84)

    if highspeed:
        # High speed setup
        lens = Lens(3, f_number=1.4, focal_length=50 * q.mm, transmission_eff=0.7, sigma=None)
    else:
        # High resolution setup
        lens = Lens(9, na=0.28, sigma=None)

    detector = Detector(scintillator, lens, camera)
    source_trajectory = Trajectory([(n / 2, n / 2, 0)] * detector.pixel_size)
    bm = make_topotomo(dE=dE, trajectory=source_trajectory, pixel_size=detector.pixel_size)

    return bm, detector
示例#4
0
def decimate(image, shape, sigma=None, average=False, queue=None, block=False):
    """Decimate *image* so that its dimensions match the final *shape*, which has to be a divisor of
    the original shape. Remove low frequencies by a Gaussian filter with *sigma* pixels. If *sigma*
    is None, use the FWHM of one low resolution pixel. Use command *queue*, if *block* is True, wait
    for the copy to finish.
    """
    if queue is None:
        queue = cfg.OPENCL.queue
    image = g_util.get_array(image, queue=queue)
    shape = make_tuple(shape)
    pow_shape = tuple([next_power_of_two(n) for n in image.shape])
    orig_shape = image.shape
    if image.shape != pow_shape:
        image = pad(image, region=(0, 0) + pow_shape, queue=queue)
    if sigma is None:
        sigma = tuple([fwnm_to_sigma(float(image.shape[i]) / shape[i], n=2) for i in range(2)])

    LOG.debug(
        "decimate, shape: %s, final_shape: %s, sigma: %s, average: %s",
        image.shape,
        shape,
        sigma,
        average,
    )

    fltr = get_gauss_2d(image.shape, sigma, fourier=True, queue=queue, block=block)
    image = image.astype(cfg.PRECISION.np_cplx)
    fft_2(image, queue=queue, block=block)
    image *= fltr
    ifft_2(image, queue=queue, block=block)
    image = crop(image.real, (0, 0) + orig_shape, queue=queue, block=block)

    return bin_image(image, shape, average=average, queue=queue, block=block)
示例#5
0
def decimate(image, shape, sigma=None, average=False, queue=None, block=False):
    """Decimate *image* so that its dimensions match the final *shape*, which has to be a divisor of
    the original shape. Remove low frequencies by a Gaussian filter with *sigma* pixels. If *sigma*
    is None, use the FWHM of one low resolution pixel. Use command *queue*, if *block* is True, wait
    for the copy to finish.
    """
    if queue is None:
        queue = cfg.OPENCL.queue
    image = g_util.get_array(image, queue=queue)
    shape = make_tuple(shape)
    pow_shape = tuple([next_power_of_two(n) for n in image.shape])
    orig_shape = image.shape
    if image.shape != pow_shape:
        image = pad(image, region=(0, 0) + pow_shape, queue=queue)
    if sigma is None:
        sigma = tuple([fwnm_to_sigma(float(image.shape[i]) / shape[i], n=2) for i in range(2)])

    LOG.debug('decimate, shape: %s, final_shape: %s, sigma: %s, average: %s', image.shape, shape,
              sigma, average)

    fltr = get_gauss_2d(image.shape, sigma, fourier=True, queue=queue, block=block)
    image = image.astype(cfg.PRECISION.np_cplx)
    fft_2(image, queue=queue, block=block)
    image *= fltr
    ifft_2(image, queue=queue, block=block)
    image = crop(image.real, (0, 0) + orig_shape, queue=queue, block=block)

    return bin_image(image, shape, average=average, queue=queue, block=block)
示例#6
0
    def make_source_blur(self, shape, pixel_size, queue=None, block=False):
        """Make geometrical source blurring kernel with *shape* (y, x) size and *pixel_size*. Use
        OpenCL command *queue* and *block* if True.
        """
        l = self.source.sample_distance
        size = self.source.size
        width = (self.propagation_distance * size[1] / l).simplified.magnitude
        height = (self.propagation_distance * size[0] / l).simplified.magnitude
        sigma = (smath.fwnm_to_sigma(
            height, n=2), smath.fwnm_to_sigma(width, n=2)) * q.m

        return ip.get_gauss_2d(shape,
                               sigma,
                               pixel_size=pixel_size,
                               fourier=True,
                               queue=queue,
                               block=block)
示例#7
0
文件: cameras.py 项目: ufo-kit/syris
    def get_image(self, photons, shot_noise=True, amplifier_noise=True, psf=True, queue=None):
        """Get digital counts image from incoming *photons*. The resulting image is based on the
        incoming photons and dark current. We apply noise based on EMVA 1288 standard according to
        which the variance :math:`\sigma_y^2 = K^2 ( \sigma_e^2 + \sigma_d^2 ) + \sigma_q^2`, where
        :math:`K` is the system gain, :math:`\sigma_e^2` is the poisson- distributed shot noise
        variance, :math:`\sigma_d^2` is the normal distributed electronics noise variance and
        :math:`\sigma_q^2` is the quantization noise variance. If *shot_noise* is False don't apply
        it. If *amplifier_noise* is False don't apply it as well. If *psf* is False don't apply the
        point spread function.
        """
        if self._last_input_shape != photons.shape:
            self._last_input_shape = photons.shape
            self._bin_factor = (photons.shape[0] / self.shape[0], photons.shape[1] / self.shape[1])

        if queue is None:
            queue = cfg.OPENCL.queue

        # Shot noise
        # Adjust dark current for later binning and gain
        dark = float(self.dark_current) / self._bin_factor[0] / self._bin_factor[1]
        electrons = dark + gutil.get_host(photons)

        if self._bin_factor != (1, 1):
            if psf:
                sigma = (fwnm_to_sigma(self._bin_factor[0]), fwnm_to_sigma(self._bin_factor[1]))
                small = decimate(electrons, self.shape, sigma=sigma, queue=queue)
            else:
                small = bin_image(electrons, self.shape, queue=queue)
            electrons = gutil.get_host(small)

        if shot_noise:
            electrons = np.random.poisson(electrons)

        if amplifier_noise and self.amplifier_sigma > 0:
            # Add electronics noise
            electrons = np.random.normal(electrons, self.amplifier_sigma)

        counts = self.gain * electrons

        # Cut the values beyond the maximum represented grey value given by
        # bytes per pixel.
        counts[counts > self.max_grey_value] = self.max_grey_value

        # Apply quantization noise
        return counts.astype(self.dtype)
示例#8
0
文件: physics.py 项目: ufo-kit/syris
        def compute_sigma_component(ps):
            fwtm = compute_aliasing_limit(size, lam, ps, distance,
                                          fov=size * ps, fourier=True)
            if region is not None:
                fwtm_region = compute_aliasing_limit(size, lam, ps, distance, region,
                                                     fourier=True)
                fwtm = min(fwtm_region, fwtm)
            sigma = fwnm_to_sigma(fwtm, n=10)

            return sigma
示例#9
0
def compute_propagator(size, distance, lam, pixel_size, fresnel=True, region=None,
                       apply_phase_factor=False, mollified=True, queue=None, block=False):
    """Create a propagator with (*size*, *size*) dimensions for propagation *distance*, wavelength
    *lam* and *pixel_size*. If *fresnel* is True, use the Fresnel approximation, if it is False, use
    the full propagator (don't approximate the square root). *region* is the diameter of the the
    wavefront area which is capable of interference. If *apply_phase_factor* is True, apply the
    phase factor defined by Fresnel approximation. If *mollified* is True the aliased frequencies
    are suppressed. If command *queue* is specified, execute the kernel on it. If *block* is True,
    wait for the kernel to finish.
    """
    if size % 2:
        raise ValueError('Only even sizes are supported')
    if queue is None:
        queue = cfg.OPENCL.queue

    # Check the sampling
    r_cutoff = compute_aliasing_limit(size, lam, pixel_size, distance, fov=region, fourier=False)
    min_n = 4
    if r_cutoff < min_n:
        LOG.error('Propagator too narrow, propagation distance too small or pixel size too large')
    f_cutoff = compute_aliasing_limit(size, lam, pixel_size, distance, fov=region, fourier=True)
    if f_cutoff < min_n:
        LOG.error('Propagator too wide, propagation distance too large or pixel size too small')

    out = cl_array.Array(queue, (size, size), cfg.PRECISION.np_cplx)
    if apply_phase_factor:
        phase_factor = np.exp(2 * np.pi * distance.simplified / lam.simplified * 1j)
    else:
        phase_factor = 0 + 0j

    ev = cfg.OPENCL.programs['physics'].propagator(queue,
                                                   (size / 2 + 1, size / 2 + 1),
                                                   None,
                                                   out.data,
                                                   cfg.PRECISION.np_float(distance.simplified),
                                                   cfg.PRECISION.np_float(lam.simplified),
                                                   cfg.PRECISION.np_float(pixel_size.simplified),
                                                   g_util.make_vcomplex(phase_factor),
                                                   np.int32(fresnel))
    if block:
        ev.wait()

    if mollified:
        fwtm = compute_aliasing_limit(size, lam, pixel_size, distance,
                                      fov=size * pixel_size, fourier=True)
        if region is not None:
            fwtm_region = compute_aliasing_limit(size, lam, pixel_size, distance, region,
                                                 fourier=True)
            fwtm = min(fwtm_region, fwtm)

        sigma = fwnm_to_sigma(fwtm, n=10)
        mollifier = get_gauss_2d(size, sigma, fourier=False, queue=queue, block=block)
        out = out * mollifier

    return out
示例#10
0
def main():
    args = parse_args()
    syris.init()
    n = 1024
    shape = (n, n)
    ps = 1 * q.um
    tr = Trajectory([(n / 2, n / 2, 0)] * ps, pixel_size=ps)
    energy_center = args.energy_center * q.keV
    fwhm = args.energy_resolution * energy_center
    sigma = smath.fwnm_to_sigma(fwhm, n=2)
    # Make sure we resolve the curve nicely
    energies = np.arange(max(1 * q.keV, energy_center - 2 * fwhm),
                         energy_center + 2 * fwhm, fwhm / 25) * q.keV
    dE = energies[1] - energies[0]
    print 'Energy from, to, step, number:', energies[0], energies[-1], dE, len(
        energies)

    bm = make_topotomo(dE=dE, pixel_size=ps, trajectory=tr)
    spectrum_energies = np.arange(1, 50, 1) * q.keV
    native_spectrum = get_spectrum(bm, spectrum_energies, ps)

    fltr = GaussianFilter(energies, energy_center, sigma)
    gauss = get_gauss(energies.magnitude, energy_center.magnitude,
                      sigma.magnitude)
    filtered_spectrum = get_spectrum(bm, energies, ps) * gauss

    intensity = propagate([bm, fltr], shape, energies, 0 * q.m, ps).get()

    show(intensity,
         title='Intensity for energy range {} - {}'.format(
             energies[0], energies[-1]))

    plt.figure()
    plt.plot(spectrum_energies.magnitude, native_spectrum)
    plt.title('Source Spectrum')
    plt.xlabel('Energy [keV]')
    plt.ylabel('Intensity')

    plt.figure()
    plt.plot(energies.magnitude, gauss)
    plt.title('Gaussian Filter')
    plt.xlabel('Energy [keV]')
    plt.ylabel('Transmitted intensity')

    plt.figure()
    plt.plot(energies.magnitude, filtered_spectrum)
    plt.title('Filtered Spectrum')
    plt.xlabel('Energy [keV]')
    plt.ylabel('Intensity')
    plt.show()
示例#11
0
def main():
    args = parse_args()
    syris.init()
    n = 1024
    shape = (n, n)
    ps = 1 * q.um
    tr = Trajectory([(n / 2, n / 2, 0)] * ps, pixel_size=ps)
    energy_center = args.energy_center * q.keV
    fwhm = args.energy_resolution * energy_center
    sigma = smath.fwnm_to_sigma(fwhm, n=2)
    # Make sure we resolve the curve nicely
    energies = np.arange(max(1 * q.keV, energy_center - 2 * fwhm),
                         energy_center + 2 * fwhm,
                         fwhm / 25) * q.keV
    dE = energies[1] - energies[0]
    print 'Energy from, to, step, number:', energies[0], energies[-1], dE, len(energies)

    bm = make_topotomo(dE=dE, pixel_size=ps, trajectory=tr)
    spectrum_energies = np.arange(1, 50, 1) * q.keV
    native_spectrum = get_spectrum(bm, spectrum_energies, ps)

    fltr = GaussianFilter(energies, energy_center, sigma)
    gauss = get_gauss(energies.magnitude, energy_center.magnitude, sigma.magnitude)
    filtered_spectrum = get_spectrum(bm, energies, ps) * gauss

    intensity = propagate([bm, fltr], shape, energies, 0 * q.m, ps).get()

    show(intensity, title='Intensity for energy range {} - {}'.format(energies[0], energies[-1]))

    plt.figure()
    plt.plot(spectrum_energies.magnitude, native_spectrum)
    plt.title('Source Spectrum')
    plt.xlabel('Energy [keV]')
    plt.ylabel('Intensity')

    plt.figure()
    plt.plot(energies.magnitude, gauss)
    plt.title('Gaussian Filter')
    plt.xlabel('Energy [keV]')
    plt.ylabel('Transmitted intensity')

    plt.figure()
    plt.plot(energies.magnitude, filtered_spectrum)
    plt.title('Filtered Spectrum')
    plt.xlabel('Energy [keV]')
    plt.ylabel('Intensity')
    plt.show()
    def test_varconvolve_gauss(self):
        from scipy.ndimage import gaussian_filter
        n = 128
        shape = (n, n)
        image = np.zeros(shape, dtype=cfg.PRECISION.np_float)
        image[n / 2, n / 2] = 1
        sigmas = np.ones_like(image) * 1e-3
        result = ip.varconvolve_gauss(image, (sigmas, sigmas), normalized=False).get()
        # At least one pixel in the midle must exist (just copies the original image)
        self.assertEqual(1, np.sum(result))

        # Test against the scipy implementation
        sigma = fwnm_to_sigma(5, n=2)
        sigmas = np.ones_like(image) * sigma
        gt = gaussian_filter(image, sigma)
        result = ip.varconvolve_gauss(image, (sigmas, sigmas), normalized=True).get()
        np.testing.assert_almost_equal(gt, result)
示例#13
0
    def test_decimate(self):
        n = 16
        sigma = fwnm_to_sigma(1)
        shape = (n // 2, n // 2)

        image = np.arange(n * n).reshape(n, n).astype(cfg.PRECISION.np_float) // n ** 2
        fltr = get_gauss_2d((n, n), sigma, fourier=True)
        filtered = np.fft.ifft2(np.fft.fft2(image) * fltr).real
        gt = bin_cpu(filtered, shape)

        res = ip.decimate(image, shape, sigma=sigma, average=False).get()
        np.testing.assert_almost_equal(gt, res, decimal=6)

        # With averaging
        res = ip.decimate(image, shape, sigma=sigma, average=True).get()
        gt = gt / 4
        np.testing.assert_almost_equal(gt, res, decimal=6)
示例#14
0
    def apply_blur(self,
                   intensity,
                   distance,
                   pixel_size,
                   queue=None,
                   block=False):
        """Apply source blur based on van Cittert-Zernike theorem at *distance*."""
        fwhm = (distance * self.size / self.sample_distance).simplified
        sigma = smath.fwnm_to_sigma(fwhm, n=2)
        psf = ip.get_gauss_2d(intensity.shape,
                              sigma,
                              pixel_size=pixel_size,
                              fourier=True,
                              queue=queue,
                              block=block)

        return ip.ifft_2(ip.fft_2(intensity) * psf).real
示例#15
0
    def test_decimate(self):
        n = 16
        sigma = fwnm_to_sigma(1)
        shape = (n / 2, n / 2)

        image = np.arange(n * n).reshape(n, n).astype(cfg.PRECISION.np_float) / n ** 2
        fltr = get_gauss_2d((n, n), sigma, fourier=True)
        filtered = np.fft.ifft2(np.fft.fft2(image) * fltr).real
        gt = bin_cpu(filtered, shape)

        res = ip.decimate(image, shape, sigma=sigma, average=False).get()
        np.testing.assert_almost_equal(gt, res, decimal=6)

        # With averaging
        res = ip.decimate(image, shape, sigma=sigma, average=True).get()
        gt = gt / 4
        np.testing.assert_almost_equal(gt, res, decimal=6)
示例#16
0
        def compute_sigma_component(ps):
            fwtm = compute_aliasing_limit(size,
                                          lam,
                                          ps,
                                          distance,
                                          fov=size * ps,
                                          fourier=True)
            if region is not None:
                fwtm_region = compute_aliasing_limit(size,
                                                     lam,
                                                     ps,
                                                     distance,
                                                     region,
                                                     fourier=True)
                fwtm = min(fwtm_region, fwtm)
            sigma = fwnm_to_sigma(fwtm, n=10)

            return sigma
示例#17
0
    def test_gaussian(self):
        energies = np.arange(5, 30, 0.1) * q.keV
        energy = 15 * q.keV
        sigma = fwnm_to_sigma(1, n=2) * q.keV
        energy_10 = energy - sigma_to_fwnm(sigma.magnitude, n=10) / 2 * q.keV
        fltr = GaussianFilter(energies, energy, sigma, peak_transmission=0.5)
        u_0 = 10 + 0j

        u_f = fltr.transfer(None, None, energy)
        u = u_0 * u_f
        self.assertAlmostEqual(np.abs(u) ** 2, 50, places=4)
        u_f = fltr.transfer(None, None, energy_10)
        u = u_0 * u_f
        self.assertAlmostEqual(np.abs(u) ** 2, 5, places=4)

        # Test exponent
        u_f = fltr.transfer(None, None, energy, exponent=True)
        u = u_0 * np.exp(u_f)
        self.assertAlmostEqual(np.abs(u) ** 2, 50, places=4)
        u_f = fltr.transfer(None, None, energy_10, exponent=True)
        u = u_0 * np.exp(u_f)
        self.assertAlmostEqual(np.abs(u) ** 2, 5, places=4)
示例#18
0
    def test_gaussian(self):
        energies = np.arange(5, 30, 0.1) * q.keV
        energy = 15 * q.keV
        sigma = fwnm_to_sigma(1, n=2) * q.keV
        energy_10 = energy - sigma_to_fwnm(sigma.magnitude, n=10) / 2 * q.keV
        fltr = GaussianFilter(energies, energy, sigma, peak_transmission=0.5)
        u_0 = 10 + 0j

        u_f = fltr.transfer(None, None, energy)
        u = u_0 * u_f
        self.assertAlmostEqual(np.abs(u)**2, 50, places=4)
        u_f = fltr.transfer(None, None, energy_10)
        u = u_0 * u_f
        self.assertAlmostEqual(np.abs(u)**2, 5, places=4)

        # Test exponent
        u_f = fltr.transfer(None, None, energy, exponent=True)
        u = u_0 * np.exp(u_f)
        self.assertAlmostEqual(np.abs(u)**2, 50, places=4)
        u_f = fltr.transfer(None, None, energy_10, exponent=True)
        u = u_0 * np.exp(u_f)
        self.assertAlmostEqual(np.abs(u)**2, 5, places=4)
示例#19
0
source_trajectory = Trajectory(pp, velocity=vel)
source_trajectory_stat = Trajectory([(n / 2, n / 2, 0)] * ps)
undu = SpectraSource(SPECTRA_FILE,
                     DISTANCE,
                     dE, (5, 140) * q.um,
                     detector.pixel_size,
                     source_trajectory,
                     phase_profile='sphere',
                     fluctuation=0.06)
undu.trajectory.bind(detector.pixel_size)
#bm = make_topotomo(dE=dE, trajectory=source_trajectory, pixel_size=detector.pixel_size)
#bm.trajectory.bind(detector.pixel_size)

## == GAUSIAN FILTER (MONOCHROMATOR APPROX) ==
fwhm = dE_mono * energy * q.eV
sigma = smath.fwnm_to_sigma(fwhm, n=2)
fltr = GaussianFilter(energies, energy * q.eV, sigma)

# == SAMPLE ===
meshes = read_collada(OBJ_PATH, [(n / 2, n / 2, 0)] * detector.pixel_size,
                      iterations=1)

tr = Trajectory([(0 / 2, 0 / 2, 0)] * detector.pixel_size)

cb = CompositeBody(tr, bodies=meshes)
cb.bind_trajectory(detector.pixel_size)

airm = get_material('air_dry.mat')
cu = get_material('cu.mat')
air_gap = MaterialFilter(3 * q.m, airm)
abs_fltr = MaterialFilter(100 * q.um, cu)
示例#20
0
def main():
    args = parse_args()
    syris.init()
    # Propagate to 20 cm
    d = 20 * q.cm
    # Compute grid
    n_camera = 256
    n = n_camera * args.supersampling
    shape = (n, n)
    material = get_material('pmma_5_30_kev.mat')
    energies = material.energies
    dE = energies[1] - energies[0]
    # Lens with magnification 5 and numerical aperture 0.25
    lens = Lens(5, na=0.25)
    # Considered visible light wavelengths
    vis_wavelengths = np.arange(500, 700) * q.nm
    # Simple camera quantum efficiencies
    cam_qe = 0.1 * np.ones(len(vis_wavelengths))
    camera = Camera(10 * q.um, 0.1, 500, 23, 32, (256, 256), exp_time=args.exposure * q.ms,
                    fps=1 / q.s, quantum_efficiencies=cam_qe, wavelengths=vis_wavelengths,
                    dtype=np.float32)
    # Scintillator emits visible light into a region given by a Gaussian distribution
    x = camera.wavelengths.rescale(q.nm).magnitude
    sigma = fwnm_to_sigma(50)
    emission = np.exp(-(x - 600) ** 2 / (2 * sigma ** 2)) / (sigma * np.sqrt(2 * np.pi))
    # Scintillator 50 um thick, light yield 14 and refractive index 1.84
    luag = get_material('luag.mat')
    scintillator = Scintillator(50 * q.um,
                                luag,
                                14 * np.ones(len(energies)) / q.keV,
                                energies,
                                emission / q.nm,
                                camera.wavelengths,
                                1.84)
    detector = Detector(scintillator, lens, camera)
    # Pixel size used for propagation
    ps = detector.pixel_size / args.supersampling

    fmt = 'Pixel size used for propagation: {}'
    print fmt.format(ps.rescale(q.um))
    fmt = '  Effective detector pixel size: {}'
    print fmt.format(detector.pixel_size.rescale(q.um))
    print '                  Field of view: {}'.format(n * ps.rescale(q.um))

    # Bending magnet source
    trajectory = Trajectory([(n / 2, n / 2, 0)] * ps)
    source = make_topotomo(dE=dE, trajectory=trajectory, pixel_size=ps)

    sample = make_sphere(n, n / 4. * ps, pixel_size=ps, material=material)
    # Propagation with a monochromatic plane incident wave
    coherent = propagate([source, sample], shape, [15 * q.keV], d, ps, t=0 * q.s,
                         detector=detector).get()
    coherent *= camera.exp_time.simplified.magnitude
    # Decimate to fit the effective pixel size of the detector system
    coherent_ld = camera.get_image(coherent, shot_noise=False, amplifier_noise=False)

    # Propagation which takes into account polychromaticity
    poly = propagate([source, sample], shape, range(10, 30) * q.keV, d, ps, t=0 * q.s,
                     detector=detector).get()
    poly *= camera.exp_time.simplified.magnitude
    poly_ld = camera.get_image(poly, shot_noise=args.noise, amplifier_noise=args.noise)

    # Compute and show some of the used propagators
    propagator_10 = get_propagator_psf(n, d, ps, 10 * q.keV)
    propagator_30 = get_propagator_psf(n, d, ps, 30 * q.keV)

    show(coherent, title='Coherent Supersampled')
    show(coherent_ld, title='Coherent Detector')
    show(propagator_10.real, title='Propagator PSF for 10 keV (real part)')
    show(propagator_30.real, title='Propagator PSF for 30 keV (real part)')
    show(poly, title='Polychromatic Supersampled')
    show(poly_ld, title='Polychromatic Detector')
    plt.show()
示例#21
0
    def compute_intensity(self,
                          t_0,
                          t_1,
                          shape,
                          pixel_size,
                          queue=None,
                          block=False,
                          flat=False):
        """Compute intensity between times *t_0* and *t_1*."""

        exp_time = (t_1 - t_0).simplified.magnitude

        if queue is None:
            queue = cfg.OPENCL.queue
        u = cl_array.Array(queue, shape, dtype=cfg.PRECISION.np_cplx)
        u_sample = cl_array.zeros(queue, shape, cfg.PRECISION.np_cplx)
        intensity = cl_array.zeros(queue, shape, cfg.PRECISION.np_float)

        for energy in self.energies:
            u.fill(1)
            for oeid, oe in enumerate(self.oe):

                if flat and oe == self.sample:
                    continue

                u *= oe.transfer(shape,
                                 pixel_size,
                                 energy,
                                 t=t_0,
                                 queue=queue,
                                 out=u_sample,
                                 check=False,
                                 block=block)

                # Propagate and blur optical element when not source
                if self.distances[oeid] != 0 * q.m and oe != self.source:
                    lam = energy_to_wavelength(energy)
                    propagator = compute_propagator(u.shape[0],
                                                    self.distances[oeid],
                                                    lam,
                                                    pixel_size,
                                                    queue=queue,
                                                    block=block,
                                                    mollified=True)

                    ip.fft_2(u, queue=queue, block=block)

                    sdistance = np.sum(self.distances[:oeid + 1])
                    fwhm = (self.distances[oeid] * self.source.size /
                            sdistance).simplified
                    sigma = smath.fwnm_to_sigma(fwhm, n=2)
                    psf = ip.get_gauss_2d(shape,
                                          sigma,
                                          pixel_size=pixel_size,
                                          fourier=True,
                                          queue=queue,
                                          block=block)
                    u *= psf
                    u *= propagator
                    ip.ifft_2(u, queue=queue, block=block)

            intensity += self.detector.convert(abs(u)**2, energy)

        return intensity * exp_time
示例#22
0
def make_devices(n, energies, camera=None, highspeed=True, scintillator=None):
    """Create devices with image shape (*n*, *n*), X-ray *energies*, *camera* and use the high speed
    setup if *highspeed* is True.
    """
    shape = (n, n)
    dE = energies[1] - energies[0]

    if not camera:
        vis_wavelengths = np.arange(500, 700) * q.nm
        camera = Camera(11 * q.um,
                        .1,
                        500,
                        23,
                        32,
                        shape,
                        exp_time=1 * q.ms,
                        fps=1000 / q.s,
                        quantum_efficiencies=0.5 *
                        np.ones(len(vis_wavelengths)),
                        wavelengths=vis_wavelengths,
                        dtype=np.float32)
    else:
        vis_wavelengths = camera.wavelengths.rescale(q.nm)

    x = vis_wavelengths.rescale(q.nm).magnitude
    dx = x[1] - x[0]
    if scintillator == 'lso' or not (scintillator or highspeed):
        sigma = fwnm_to_sigma(50)
        emission = np.exp(-(x - 545)**2 /
                          (2 * sigma**2)) / (sigma * np.sqrt(2 * np.pi))
        lso = get_material('lso_5_30_kev.mat')
        scintillator = Scintillator(13 * q.um, lso,
                                    36 * np.ones(len(energies)) / q.keV,
                                    energies, emission / q.nm, vis_wavelengths,
                                    1.82)
    elif scintillator == 'luag' or (not scintillator and highspeed):
        sigma = fwnm_to_sigma(50)
        emission = np.exp(-(x - 450)**2 /
                          (2 * sigma**2)) / (sigma * np.sqrt(2 * np.pi))
        luag = get_material('luag.mat')
        scintillator = Scintillator(50 * q.um, luag,
                                    14 * np.ones(len(energies)) / q.keV,
                                    energies, emission / q.nm, vis_wavelengths,
                                    1.84)

    if highspeed:
        # High speed setup
        lens = Lens(3,
                    f_number=1.4,
                    focal_length=50 * q.mm,
                    transmission_eff=0.7,
                    sigma=None)
    else:
        # High resolution setup
        lens = Lens(9, na=0.28, sigma=None)

    detector = Detector(scintillator, lens, camera)
    source_trajectory = Trajectory([(n / 2, n / 2, 0)] * detector.pixel_size)
    bm = make_topotomo(dE=dE,
                       trajectory=source_trajectory,
                       pixel_size=detector.pixel_size)

    return bm, detector