Exemplo n.º 1
0
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
Exemplo n.º 2
0
    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))
Exemplo n.º 3
0
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
Exemplo n.º 4
0
 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)]
Exemplo n.º 5
0
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))
Exemplo n.º 6
0
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
Exemplo n.º 7
0
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
Exemplo n.º 8
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
        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
Exemplo n.º 9
0
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
Exemplo n.º 10
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
 def exp(self):
   outimgcl = self.clone_empty()
   outimgcl.clarray = clmath.exp(self.clarray)
   return outimgcl
Exemplo n.º 12
0
 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)]
Exemplo n.º 13
0
 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)
Exemplo n.º 14
0
 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
Exemplo n.º 15
0
 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)]