Windows and Tiles

DASCore offers three windowing models:

you want use what comes back
a value per sample, from the samples around it Patch.rolling a patch shaped like the input
a transform of each window, kept as windows Patch.stft, or Patch.tile_apply with mode="stack" a patch with a window axis
each window transformed and the windows blended back Patch.tile_apply a patch shaped like the input

Window lengths use coordinate units or samples (samples=True). overlap accepts a count, duration, percentage, or per-dimension mapping.

Tiles, blended

tile_apply passes an [n_tiles, *window] array to a function and blends its same-shaped result with complementary tapers. An identity function reconstructs the input exactly. This example applies windowed automatic gain control:

import numpy as np
import matplotlib.pyplot as plt

import dascore as dc
from dascore.units import percent

patch = dc.get_example_patch("example_event_2").pass_filter(time=(1, 300))


def agc(tiles):
    """Scale every tile to unit RMS."""
    rms = np.sqrt(np.mean(tiles**2, axis=(1, 2), keepdims=True))
    return tiles / np.where(rms > 0, rms, 1)


normalized = patch.tile_apply(agc, time=0.02, distance=40)

fig, axes = plt.subplots(1, 2, figsize=(12, 5), sharey=True)
for ax, pa, title in zip(axes, [patch, normalized], ["band-passed", "AGC, 20 ms by 40 m"]):
    scale = np.percentile(np.abs(pa.data), 99)
    pa.viz.waterfall(ax=ax, scale=scale, scale_type="absolute", cmap="bwr")
    ax.set_title(title)
fig.tight_layout()

The adaptive spectral filter uses the same machinery with spectral weighting.

Tiles, kept

With mode="stack", tiles remain separate. Windowed dimensions become tile-center axes, {dim}_start and {dim}_stop record physical cell edges in the dimension’s units, and tile samples use {dim}_offset. Process the stack as a patch, then reassemble it. Paired physical bounds require monotonic row order; explicitly drop the public bounds before an arbitrary tile permutation. Private reconstruction indices follow the rows and still allow reassembly.

tiles = patch.tile_apply(lambda x: x, mode="stack", time=0.02, distance=40)
print(tiles.dims, tiles.shape)

# Drop every tile whose energy is in the lowest quarter, then blend back.
# The mean keeps the offset axes at length one, so a per-tile flag
# broadcasts back over every sample of its tile.
energy = (tiles**2).mean(dim=("distance_offset", "time_offset"))
quiet = energy.data < np.percentile(energy.data, 25)
kept = tiles.new(data=np.where(quiet, 0, tiles.data))
denoised = kept.reassemble()
assert denoised.shape == patch.shape
('distance', 'time', 'distance_offset', 'time_offset') (32, 12, 40, 200)

An unchanged stack reassembles exactly. stft transforms the offset axes; istft inverts them and reassembles.

A compiled function, one tile at a time

A Numba-compiled function receives one tile at a time in parallel. This supports any number of dimensions and mode="stack", with a one-time compilation cost per process.

import numba


@numba.njit
def agc_tile(tile):
    rms = np.sqrt(np.mean(tile * tile))
    return tile / rms if rms > 0 else tile


normalized = patch.tile_apply(agc_tile, time=0.02, distance=40)

A window on the way in

By default only blending is tapered. Set analysis to window each tile before the function; blending uses the window’s dual so identity remains exact and overlap may exceed half the window.

def keep_strongest(tiles):
    """Keep the largest quarter of each tile's f-k coefficients."""
    spectra = np.fft.rfft2(tiles)
    cutoff = np.percentile(np.abs(spectra), 75, axis=(1, 2), keepdims=True)
    return np.fft.irfft2(np.where(np.abs(spectra) < cutoff, 0, spectra), s=tiles.shape[1:])


local_fk = patch.tile_apply(keep_strongest, analysis="hann", overlap=75 * percent, time=0.02, distance=40)
assert local_fk.shape == patch.shape

What a tile sees

Tiles extend before the data with zero padding so every contributing tile exists. Overlap defaults to half the window and cannot exceed half with blend-only tapers; analysis windows may overlap as far as SciPy can invert them. get_window supplies supported taper shapes.