Exemplo n.º 1
0
    def compute_slices(self,
                       shape,
                       pixel_size,
                       queue=None,
                       out=None,
                       offset=None):
        """Compute slices with *shape* as (z, y, x), *pixel_size*. Use *queue* and *out* for
        outuput. Offset is the starting point offset as (x, y, z).
        """
        if queue is None:
            queue = cfg.OPENCL.queue
        if out is None:
            out = cl_array.zeros(queue, shape, dtype=np.uint8)

        pixel_size = make_tuple(pixel_size, num_dims=2)
        v_1, v_2, v_3 = self._make_inputs(queue, pixel_size)
        psm = pixel_size.simplified.magnitude
        max_dx = self.max_triangle_x_diff.simplified.magnitude / psm[1]
        if offset is None:
            offset = gutil.make_vfloat3(0, 0, 0)
        else:
            offset = offset.simplified.magnitude
            offset = gutil.make_vfloat3(offset[0] / psm[1], offset[1] / psm[0],
                                        offset[2] / psm[1])

        cfg.OPENCL.programs['mesh'].compute_slices(
            queue, (shape[2], shape[0]), None, v_1.data, v_2.data, v_3.data,
            out.data, np.int32(shape[1]), np.int32(self.num_triangles), offset,
            cfg.PRECISION.np_float(max_dx))

        return out
Exemplo n.º 2
0
    def compute_slices(self, shape, pixel_size, queue=None, out=None, offset=None):
        """Compute slices with *shape* as (z, y, x), *pixel_size*. Use *queue* and *out* for
        outuput. Offset is the starting point offset as (x, y, z).
        """
        if queue is None:
            queue = cfg.OPENCL.queue
        if out is None:
            out = cl_array.zeros(queue, shape, dtype=np.uint8)

        pixel_size = make_tuple(pixel_size, num_dims=2)
        v_1, v_2, v_3 = self._make_inputs(queue, pixel_size)
        psm = pixel_size.simplified.magnitude
        max_dx = self.max_triangle_x_diff.simplified.magnitude / psm[1]
        if offset is None:
            offset = gutil.make_vfloat3(0, 0, 0)
        else:
            offset = offset.simplified.magnitude
            offset = gutil.make_vfloat3(offset[0] / psm[1], offset[1] / psm[0], offset[2] / psm[1])

        cfg.OPENCL.programs['mesh'].compute_slices(queue,
                                                   (shape[2], shape[0]),
                                                   None,
                                                   v_1.data,
                                                   v_2.data,
                                                   v_3.data,
                                                   out.data,
                                                   np.int32(shape[1]),
                                                   np.int32(self.num_triangles),
                                                   offset,
                                                   cfg.PRECISION.np_float(max_dx))


        return out
Exemplo n.º 3
0
    def _transfer_real(self,
                       shape,
                       center,
                       pixel_size,
                       energy,
                       exponent,
                       compute_phase,
                       is_parabola,
                       out,
                       queue,
                       block,
                       flux=1):
        """Compte the actual wavefield. *center*, *pixel_size*, *sample_distance* and *wavelength*
        are all unitless values which can be passed directly to OpenCL kernels.
        """
        cl_center = gutil.make_vfloat3(*center)
        cl_ps = gutil.make_vfloat2(*pixel_size.simplified.magnitude[::-1])
        z_sample = self.sample_distance.simplified.magnitude
        lam = energy_to_wavelength(energy).simplified.magnitude
        kernel = cfg.OPENCL.programs['physics'].make_flat_from_scalar

        ev = kernel(queue, shape[::-1], None, out.data,
                    cfg.PRECISION.np_float(flux), cl_center, cl_ps,
                    cfg.PRECISION.np_float(z_sample),
                    cfg.PRECISION.np_float(lam), np.int32(exponent),
                    np.int32(compute_phase), np.int32(is_parabola))

        if block:
            ev.wait()
Exemplo n.º 4
0
    def _transfer_real(
        self,
        shape,
        center,
        pixel_size,
        energy,
        exponent,
        compute_phase,
        is_parabola,
        out,
        queue,
        block,
        flux=1,
    ):
        flux = (self.get_flux(energy, None, pixel_size).rescale(
            1 / q.s).magnitude.astype(cfg.PRECISION.np_float))
        cl_image = gutil.get_image(flux, queue=queue)

        sampler = cl.Sampler(cfg.OPENCL.ctx, False, cl.addressing_mode.CLAMP,
                             cl.filter_mode.LINEAR)

        cl_center = gutil.make_vfloat3(*center)
        cl_ps = gutil.make_vfloat2(*pixel_size.simplified.magnitude[::-1])
        cl_input_ps = gutil.make_vfloat2(
            *self._pixel_size.simplified.magnitude[::-1])
        z_sample = self.sample_distance.simplified.magnitude
        lam = energy_to_wavelength(energy).simplified.magnitude
        kernel = cfg.OPENCL.programs["physics"].make_flat_from_2D_profile

        ev = kernel(
            queue,
            shape[::-1],
            None,
            out.data,
            cl_image,
            sampler,
            cl_center,
            cl_ps,
            cl_input_ps,
            cfg.PRECISION.np_float(z_sample),
            cfg.PRECISION.np_float(lam),
            np.int32(exponent),
            np.int32(compute_phase),
            np.int32(is_parabola),
        )

        if block:
            ev.wait()
Exemplo n.º 5
0
    def _transfer_real(
        self,
        shape,
        center,
        pixel_size,
        energy,
        exponent,
        compute_phase,
        is_parabola,
        out,
        queue,
        block,
    ):
        """Compute the flat field wavefield. Returned *out* array is different from the input
        one.
        """
        cl_center = gutil.make_vfloat3(*center)
        cl_ps = gutil.make_vfloat2(*pixel_size.simplified.magnitude[::-1])
        fov = np.arange(0, shape[0]) * pixel_size[0] - center[1] * q.m
        angles = np.arctan((fov / self.sample_distance).simplified)
        profile = (self._create_vertical_profile(
            energy, angles, pixel_size[0]).rescale(1 / q.s).magnitude)
        profile = cl_array.to_device(queue,
                                     profile.astype(cfg.PRECISION.np_float))
        z_sample = self.sample_distance.simplified.magnitude
        lam = energy_to_wavelength(energy).simplified.magnitude
        kernel = cfg.OPENCL.programs["physics"].make_flat_from_vertical_profile

        ev = kernel(
            queue,
            shape[::-1],
            None,
            out.data,
            profile.data,
            cl_center,
            cl_ps,
            cfg.PRECISION.np_float(z_sample),
            cfg.PRECISION.np_float(lam),
            np.int32(exponent),
            np.int32(compute_phase),
            np.int32(is_parabola),
        )

        if block:
            ev.wait()
Exemplo n.º 6
0
    def _transfer(self,
                  shape,
                  pixel_size,
                  energy,
                  offset,
                  exponent=False,
                  t=None,
                  queue=None,
                  out=None,
                  check=True,
                  block=False):
        """Compute the flat field wavefield. Returned *out* array is different from the input one."""
        if queue is None:
            queue = cfg.OPENCL.queue

        ps = make_tuple(pixel_size)
        if t is None:
            x, y, z = self.trajectory.control_points.simplified.magnitude[0]
        else:
            x, y, z = self.trajectory.get_point(t).simplified.magnitude
        x += offset[1].simplified.magnitude
        y += offset[0].simplified.magnitude
        center = (x, y, z)
        cl_center = gutil.make_vfloat3(*center)
        cl_ps = gutil.make_vfloat2(*pixel_size.simplified.magnitude[::-1])
        fov = np.arange(0, shape[0]) * ps[0] - y * q.m
        angles = np.arctan((fov / self.sample_distance).simplified)
        profile = self._create_vertical_profile(energy, angles, ps[0]).rescale(
            1 / q.s).magnitude

        profile = cl_array.to_device(queue,
                                     profile.astype(cfg.PRECISION.np_float))
        if out is None:
            out = cl_array.Array(queue, shape, dtype=cfg.PRECISION.np_cplx)

        z_sample = self.sample_distance.simplified.magnitude
        lam = energy_to_wavelength(energy).simplified.magnitude
        phase = self.phase_profile != 'plane'
        parabola = self.phase_profile == 'parabola'
        if exponent or check and phase:
            ev = cfg.OPENCL.programs['physics'].make_flat(
                queue, shape[::-1], None, out.data, profile.data, cl_center,
                cl_ps, cfg.PRECISION.np_float(z_sample),
                cfg.PRECISION.np_float(lam), np.int32(True), np.int32(phase),
                np.int32(parabola))
            if check and phase and not is_wavefield_sampling_ok(out,
                                                                queue=queue):
                LOG.error('Insufficient beam phase sampling')
            if not exponent:
                out = clmath.exp(out, queue=queue)
        else:
            ev = cfg.OPENCL.programs['physics'].make_flat(
                queue, shape[::-1], None,
                out.data, profile.data, cl_center, cl_ps,
                cfg.PRECISION.np_float(z_sample), cfg.PRECISION.np_float(lam),
                np.int32(exponent), np.int32(phase), np.int32(parabola))

        if block:
            ev.wait()

        return out