コード例 #1
0
def gaussian_smooth(f, sigma=1, truncate=4.0, mode='reflect'):
    """
    Gaussian smooth function.

    Parameters
    ----------
    f : Function
        The left-hand side of the smoothing kernel, that is the smoothed Function.
    sigma : float, optional
        Standard deviation. Default is 1.
    truncate : float, optional
        Truncate the filter at this many standard deviations. Default is 4.0.
    mode : str, optional
        The function initialisation mode. 'constant' and 'reflect' are
        accepted. Default mode is 'reflect'.
    """
    class ObjectiveDomain(dv.SubDomain):

        name = 'objective_domain'

        def __init__(self, lw):
            super(ObjectiveDomain, self).__init__()
            self.lw = lw

        def define(self, dimensions):
            return {d: ('middle', l, l) for d, l in zip(dimensions, self.lw)}

    def create_gaussian_weights(sigma, lw):
        weights = [
            w / w.sum()
            for w in (np.exp(-0.5 / s**2 * (np.linspace(-l, l, 2 * l + 1))**2)
                      for s, l in zip(sigma, lw))
        ]
        processed = []
        for w in weights:
            temp = list(w)
            while len(temp) < 2 * max(lw) + 1:
                temp.insert(0, 0)
                temp.append(0)
            processed.append(np.array(temp))
        return as_tuple(processed)

    def fset(f, g):
        indices = [slice(l, -l, 1) for _, l in zip(g.dimensions, lw)]
        slices = (slice(None, None, 1), ) * g.ndim
        if isinstance(f, np.ndarray):
            f[slices] = g.data[tuple(indices)]
        elif isinstance(f, dv.Function):
            f.data[slices] = g.data[tuple(indices)]
        else:
            raise NotImplementedError

    try:
        # NOTE: required if input is an np.array
        dtype = f.dtype.type
        shape = f.shape
    except AttributeError:
        dtype = f.dtype
        shape = f.shape_global

    # TODO: Add s = 0 dim skip option
    lw = tuple(int(truncate * float(s) + 0.5) for s in as_tuple(sigma))

    if len(lw) == 1 and len(lw) < f.ndim:
        lw = f.ndim * (lw[0], )
        sigma = f.ndim * (as_tuple(sigma)[0], )
    elif len(lw) == f.ndim:
        sigma = as_tuple(sigma)
    else:
        raise ValueError("`sigma` must be an integer or a tuple of length" +
                         " `f.ndim`.")

    # Create the padded grid:
    objective_domain = ObjectiveDomain(lw)
    shape_padded = tuple([np.array(s) + 2 * l for s, l in zip(shape, lw)])
    grid = dv.Grid(shape=shape_padded, subdomains=objective_domain)

    f_c = dv.Function(name='f_c',
                      grid=grid,
                      space_order=2 * max(lw),
                      coefficients='symbolic',
                      dtype=dtype)
    f_o = dv.Function(name='f_o', grid=grid, dtype=dtype)

    weights = create_gaussian_weights(sigma, lw)

    mapper = {}
    for d, l, w in zip(f_c.dimensions, lw, weights):
        lhs = []
        rhs = []
        options = []

        lhs.append(f_o)
        rhs.append(dv.generic_derivative(f_c, d, 2 * l, 1))
        coeffs = dv.Coefficient(1, f_c, d, w)
        options.append({
            'coefficients': dv.Substitutions(coeffs),
            'subdomain': grid.subdomains['objective_domain']
        })

        lhs.append(f_c)
        rhs.append(f_o)
        options.append({'subdomain': grid.subdomains['objective_domain']})

        mapper[d] = {'lhs': lhs, 'rhs': rhs, 'options': options}

    # Note: we impose the smoother runs on the host as there's generally not
    # enough parallelism to be performant on a device
    platform = 'cpu64'

    initialize_function(f_c,
                        f,
                        lw,
                        mapper=mapper,
                        mode='reflect',
                        name='smooth',
                        platform=platform)

    fset(f, f_c)
    return f
コード例 #2
0
ファイル: builtins.py プロジェクト: lapps-ufrn/devito
def gaussian_smooth(f, sigma=1, _order=4, mode='reflect'):
    """
    Gaussian smooth function.
    """
    class ObjectiveDomain(dv.SubDomain):

        name = 'objective_domain'

        def __init__(self, lw):
            super(ObjectiveDomain, self).__init__()
            self.lw = lw

        def define(self, dimensions):
            return {d: ('middle', self.lw, self.lw) for d in dimensions}

    def fset(f, g):
        indices = [slice(lw, -lw, 1) for _ in g.grid.dimensions]
        slices = (slice(None, None, 1), ) * len(g.grid.dimensions)
        if isinstance(f, np.ndarray):
            f[slices] = g.data[tuple(indices)]
        elif isinstance(f, dv.Function):
            f.data[slices] = g.data[tuple(indices)]
        else:
            raise NotImplementedError

    lw = int(_order * sigma + 0.5)

    # Create the padded grid:
    objective_domain = ObjectiveDomain(lw)
    try:
        shape_padded = np.array(f.grid.shape) + 2 * lw
    except AttributeError:
        shape_padded = np.array(f.shape) + 2 * lw
    grid = dv.Grid(shape=shape_padded, subdomains=objective_domain)

    f_c = dv.Function(name='f_c',
                      grid=grid,
                      space_order=2 * lw,
                      coefficients='symbolic',
                      dtype=np.int32)
    f_o = dv.Function(name='f_o',
                      grid=grid,
                      coefficients='symbolic',
                      dtype=np.int32)

    weights = np.exp(-0.5 / sigma**2 * (np.linspace(-lw, lw, 2 * lw + 1))**2)
    weights = weights / weights.sum()

    mapper = {}
    for d in f_c.dimensions:
        lhs = []
        rhs = []
        options = []

        lhs.append(f_o)
        rhs.append(dv.generic_derivative(f_c, d, 2 * lw, 1))
        coeffs = dv.Coefficient(1, f_c, d, weights)
        options.append({
            'coefficients': dv.Substitutions(coeffs),
            'subdomain': grid.subdomains['objective_domain']
        })
        lhs.append(f_c)
        rhs.append(f_o)
        options.append({'subdomain': grid.subdomains['objective_domain']})

        mapper[d] = {'lhs': lhs, 'rhs': rhs, 'options': options}

    initialize_function(f_c,
                        f.data[:],
                        lw,
                        mapper=mapper,
                        mode='reflect',
                        name='smooth')

    fset(f, f_c)

    return f