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
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
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()
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()
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()
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