def transfer_many(objects, shape, pixel_size, energy, exponent=False, offset=None, queue=None, out=None, t=None, check=True, block=False): """Compute transmission from more *objects*. If *exponent* is True, compute only the exponent, if it is False, evaluate the exponent. Use *shape* (y, x), *pixel_size*, *energy*, *offset* as (y, x), OpenCL command *queue*, *out* array, time *t*, check the sampling if *check* is True and wait for OpenCL kernels if *block* is True. Returned *out* array is different from the input one because of the pyopencl.clmath behavior. """ if queue is None: queue = cfg.OPENCL.queue if out is None: out = cl_array.zeros(queue, shape, cfg.PRECISION.np_cplx) u_sample = cl_array.Array(queue, shape, cfg.PRECISION.np_cplx) lam = energy_to_wavelength(energy) for i, sample in enumerate(objects): out += sample.transfer(shape, pixel_size, energy, exponent=True, offset=offset, t=t, queue=queue, out=u_sample, check=False, block=block) if check and not is_wavefield_sampling_ok(out, queue=queue): LOG.error('Insufficient transmission function sampling') # Apply the exponent if not exponent: out = clmath.exp(out, queue=queue) return out
def exp(t: Tensor) -> Tensor: """Returns a natural exponent of a tensor.""" if t.gpu: return Tensor(clmath.exp(t._data), gpu=True) return Tensor(np.exp(t._data))
def transfer_many(objects, shape, pixel_size, energy, exponent=False, offset=None, queue=None, out=None, t=None, check=True, block=False): """Compute transmission from more *objects*. If *exponent* is True, compute only the exponent, if it is False, evaluate the exponent. Use *shape* (y, x), *pixel_size*, *energy*, *offset* as (y, x), OpenCL command *queue*, *out* array, time *t*, check the sampling if *check* is True and wait for OpenCL kernels if *block* is True. Returned *out* array is different from the input one because of the pyopencl.clmath behavior. """ if queue is None: queue = cfg.OPENCL.queue if out is None: out = cl_array.zeros(queue, shape, cfg.PRECISION.np_cplx) u_sample = cl_array.Array(queue, shape, cfg.PRECISION.np_cplx) lam = energy_to_wavelength(energy) for i, sample in enumerate(objects): try: out += sample.transfer(shape, pixel_size, energy, exponent=True, offset=offset, t=t, queue=queue, out=u_sample, check=False, block=block) except NotImplementedError: LOG.debug('%s does not support real space transfer', sample) if check and not is_wavefield_sampling_ok(out, queue=queue): LOG.error('Insufficient transmission function sampling') # Apply the exponent if not exponent: out = clmath.exp(out, queue=queue) return out
def _evaluate(self, valuation, cache): if id(self) not in cache: q = pl.qs[0] op = self.ops[0]._evaluate(valuation, cache) maxes, ids = misc.max(q, op, axis=1, keepdims=True) self.y, ev = bcast.bcast_add(op, -maxes) ev.wait() self.y = clmath.exp(self.y) ysum = misc.sum(q, self.y, axis=1, keepdims=True) bcast.bcast_div(self.y, ysum, out=self.y) cache[id(self)] = self.y return cache[id(self)]
def bump(discr, queue, t=0): source_center = np.array([0.0, 0.05]) source_width = 0.05 source_omega = 3 nodes = discr.volume_discr.nodes().with_queue(queue) center_dist = join_fields([ nodes[0] - source_center[0], nodes[1] - source_center[1], ]) return (np.cos(source_omega * t) * clmath.exp(-np.dot(center_dist, center_dist) / source_width**2))
def transfer(thickness, refractive_index, wavelength, exponent=False, queue=None, out=None, check=True, block=False): """Transfer *thickness* (can be either a numpy or pyopencl array) with *refractive_index* and given *wavelength*. If *exponent* is True, compute the exponent of the function without applying the wavenumber. Use command *queue* for computation and *out* pyopencl array. If *block* is True, wait for the kernel to finish. If *check* is True, the function is checked for aliasing artefacts. Returned *out* array is different from the input one because of the pyopencl.clmath behavior. """ if queue is None: queue = cfg.OPENCL.queue if isinstance(thickness, cl_array.Array): thickness_mem = thickness else: prep = thickness.simplified.magnitude.astype(cfg.PRECISION.np_float) thickness_mem = cl_array.to_device(queue, prep) if out is None: out = cl_array.Array(queue, thickness_mem.shape, cfg.PRECISION.np_cplx) if exponent or check: wavenumber = cfg.PRECISION.np_float(2 * np.pi / wavelength.simplified.magnitude) ev = cfg.OPENCL.programs['physics'].transmission_add(queue, thickness_mem.shape[::-1], None, out.data, thickness_mem.data, cfg.PRECISION.np_cplx( refractive_index), wavenumber, np.int32(1)) if check and not is_wavefield_sampling_ok(out, queue=queue): LOG.error('Insufficient transmission function sampling') if not exponent: # Apply the exponent out = clmath.exp(out, queue=queue) else: ev = cfg.OPENCL.programs['physics'].transfer(queue, thickness_mem.shape[::-1], None, out.data, thickness_mem.data, cfg.PRECISION.np_cplx(refractive_index), cfg.PRECISION.np_float( wavelength.simplified.magnitude)) if block: ev.wait() return out
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 if out is None: out = cl_array.Array(queue, shape, dtype=cfg.PRECISION.np_cplx) 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) phase = self.phase_profile != "plane" parabola = self.phase_profile == "parabola" compute_exponent = exponent or check and phase self._transfer_real(shape, center, ps, energy, compute_exponent, phase, parabola, out, queue, block) if compute_exponent: 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) return out
def exp(a, out=None): #TODO: work with out res = clmath.exp(a, queue=queue) #np.exp(*args, **kwargs) res.__class__ = myclArray res.reinit() return res
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
def exp(self): outimgcl = self.clone_empty() outimgcl.clarray = clmath.exp(self.clarray) return outimgcl
def _evaluate(self, valuation, cache): if id(self) not in cache: x = self.ops[0]._evaluate(valuation, cache) cache[id(self)] = 1.0 / (1 + clmath.exp(-x)) return cache[id(self)]
def _rev_grad(self, valuation, adjoint, gradient, cache): ex = cache[id(self.ops[0])] self.ops[0]._rev_grad(valuation, adjoint * clmath.exp(ex), gradient, cache)
def _fwd_grad(self, wrt, valuation, cache): ex = cache[id(self.ops[0])] dex = self.ops[0]._fwd_grad(wrt, valuation, cache) return clmath.exp(ex) * dex
def _evaluate(self, valuation, cache): if id(self) not in cache: cache[id(self)] = clmath.exp(self.ops[0]._evaluate( valuation, cache)) return cache[id(self)]