Beispiel #1
0
def main():
    args = parse_args()
    syris.init()
    # Propagate to 20 cm
    d = 5 * q.cm
    # Compute grid
    n_camera = 256
    n = n_camera * args.supersampling
    shape = (n, n)
    material = get_material("pmma_5_30_kev.mat")
    energy = 15 * q.keV
    ps = 1 * q.um
    ps_hd = ps / args.supersampling
    radius = n / 4.0 * ps_hd

    fmt = "                     Wavelength: {}"
    print(fmt.format(energy_to_wavelength(energy)))
    fmt = "Pixel size used for propagation: {}"
    print(fmt.format(ps_hd.rescale(q.um)))
    print("                  Field of view: {}".format(n *
                                                       ps_hd.rescale(q.um)))
    fmt = "                Sphere diameter: {}"
    print(fmt.format(2 * radius))

    sample = make_sphere(n, radius, pixel_size=ps_hd, material=material)
    projection = sample.project((n, n), ps_hd).get() * 1e6
    projection = decimate(projection, (n_camera, n_camera), average=True).get()
    # Propagation with a monochromatic plane incident wave
    hd = propagate([sample], shape, [energy], d, ps_hd).get()
    ld = decimate(hd, (n_camera, n_camera), average=True).get()

    kernel = compute_tie_kernel(n_camera, ps, d, material, energy)
    mju = material.get_attenuation_coefficient(energy).rescale(1 /
                                                               q.m).magnitude
    f_ld = fft_2(ld)
    f_ld *= get_array(kernel.astype(cfg.PRECISION.np_float))
    retrieved = ifft_2(f_ld).get().real
    retrieved = -1 / mju * np.log(retrieved) * 1e6

    if args.output_thickness:
        imageio.imwrite(args.output_thickness, projection)
    if args.output_projection:
        imageio.imwrite(args.output_projection, ld)
    if args.output_retrieved:
        imageio.imwrite(args.output_retrieved, retrieved)

    show(hd, title="High resolution")
    show(ld, title="Low resolution (detector)")
    show(retrieved, title="Retrieved [um]")
    show(projection, title="Projection [um]")
    show(projection - retrieved, title="Projection - retrieved")
    plt.show()
Beispiel #2
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)
    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)
Beispiel #4
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)
Beispiel #5
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)