Skip to content
Oakfield Operator Calculus Function Reference Site

Stimulus: Spatial Patterns

These operators share the coordinate mapping and timing controls documented on Stimulus Operators. Most entries use add_stimulus_operator(ctx, field, opts) with the operator-specific type shown below.

add_stimulus_operator(ctx, field, opts)

Generate checker or stripe patterns. Works on complex fields with configurable periods and phase.

add_stimulus_operator(ctx, field, [options]) -> operator

Returns: Operator handle (userdata)

Note: Requires type = "stimulus_checkerboard".

u(x,y)=Asign(sin(2πxPx)sin(2πyPy))eiϕcu(x, y) = A \cdot \text{sign}\left(\sin\left(\frac{2\pi x}{P_x}\right) \cdot \sin\left(\frac{2\pi y}{P_y}\right)\right) \cdot e^{i\phi_c}

where:

  • PxP_x, PyP_y are the periods
  • ϕc\phi_c is the complex phase rotation

Setting one period to infinity produces stripes along that axis.

ParameterTypeDefaultRangeDescription
typestring Must be "stimulus_checkerboard"
amplitudedouble unboundedPattern amplitude (required)
period_xdouble 8.0>0X-axis period (samples)
period_ydouble 8.0>0Y-axis period (samples)
phasedouble 0.0unboundedScalar phase offset
complex_phasedouble 0.0unboundedComplex rotation (radians)
scale_by_dtboolean trueScale by dt
-- Standard checkerboard
ooc.add_stimulus_operator(ctx, field, {
type = "stimulus_checkerboard",
amplitude = 1.0,
period_x = 8,
period_y = 8
})
-- Rectangular cells with complex phase
ooc.add_stimulus_operator(ctx, field, {
type = "stimulus_checkerboard",
amplitude = 0.5,
period_x = 12,
period_y = 6,
complex_phase = 0.75
})
-- Vertical stripes (large period_y)
ooc.add_stimulus_operator(ctx, field, {
type = "stimulus_checkerboard",
amplitude = 0.8,
period_x = 16,
period_y = 1000
})

add_stimulus_operator(ctx, field, opts)

Generate a two-grating Moiré interference pattern by averaging two nearby gratings with slightly different wavenumbers or directions. Produces characteristic beat patterns whose spatial frequency equals the difference of the two grating frequencies.

add_stimulus_operator(ctx, field, [options]) -> operator

Returns: Operator handle (userdata)

Note: Requires type = "stimulus_moire".

Let τ=t+time_offset\tau = t + \text{time\_offset}.

Scalar mode (use_wavevector = false, with mapped coordinate u=ξ(x,y,τ)u=\xi(x,y,\tau)):

θa=kauωaτ+ϕa,θb=kbuωbτ+ϕb\theta_a = k_a u - \omega_a \tau + \phi_a,\quad \theta_b = k_b u - \omega_b \tau + \phi_b Δu=A2[cos(θa)+cos(θb)]\Delta u = \frac{A}{2}\left[\cos(\theta_a) + \cos(\theta_b)\right]

Wavevector mode (use_wavevector = true):

θa=k1xx+k1yyωaτ+ϕa,θb=k2xx+k2yyωbτ+ϕb\theta_a = k_{1x}x + k_{1y}y - \omega_a \tau + \phi_a,\quad \theta_b = k_{2x}x + k_{2y}y - \omega_b \tau + \phi_b Δu=A2[cos(θa)+cos(θb)]\Delta u = \frac{A}{2}\left[\cos(\theta_a) + \cos(\theta_b)\right]

Beat period (scalar mode, kbkak_b \approx k_a):

λbeat=2πkbka\lambda_{\text{beat}} = \frac{2\pi}{|k_b - k_a|}
ParameterTypeDefaultRangeDescription
typestring Must be "stimulus_moire"
amplitudedouble 0.0unboundedAmplitude of the Moiré write (0.0 writes nothing)
wavenumber_adouble 0.0unboundedFirst grating wavenumber (rad/unit)
wavenumber_bdouble 0.0unboundedSecond grating wavenumber (rad/unit)
omega_adouble 0.0unboundedFirst grating angular frequency (rad/s)
omega_bdouble 0.0unboundedSecond grating angular frequency (rad/s)
phase_adouble 0.0unboundedFirst grating phase offset (radians)
phase_bdouble 0.0unboundedSecond grating phase offset (radians)
k1x, k1ydouble 0.0unboundedFirst wavevector components
k2x, k2ydouble 0.0unboundedSecond wavevector components
use_wavevectorboolean falseUse (k1x,k1y)/(k2x,k2y) instead of scalar wavenumbers; also auto-enabled if any wavevector component is nonzero
time_offsetdouble 0.0unboundedAdditional time shift
rotationdouble 0.0unboundedComplex phase rotation on output (radians)
scale_by_dtboolean falseScale writes by dt

For complex fields, the operator writes both cosine and sine components and applies rotation as a complex phase rotation.

When wavevector mode is active and (k1x,k1y) or (k2x,k2y) is exactly zero, runtime substitutes (wavenumber_a, 0) or (wavenumber_b, 0) respectively.

When coord_mode = "separable" (and use_wavevector = false), the operator evaluates one pattern on x and one on y, then combines them with coord_combine ("multiply" or "add").

With use_wavevector = true, the operator uses x,y directly for dot products; origin_*/spacing_* still apply, while coord_mode-specific mapping is bypassed.

Plus coordinate mapping parameters (coord_mode, coord_axis, coord_combine, coord_angle, origin_x/y, spacing_x/y, coord_center_x/y, coord_velocity_x/y, spiral params).

-- Classic 1D Moiré beat pattern
ooc.add_stimulus_operator(ctx, field, {
type = "stimulus_moire",
amplitude = 1.0,
wavenumber_a = 2.2,
wavenumber_b = 2.35
})
-- 2D Moiré with crossed wavevectors
ooc.add_stimulus_operator(ctx, field, {
type = "stimulus_moire",
amplitude = 0.8,
use_wavevector = true,
k1x = 1.9, k1y = 0.7,
k2x = 2.05, k2y = 0.76
})
-- Drifting Moiré (different frequencies)
ooc.add_stimulus_operator(ctx, field, {
type = "stimulus_moire",
amplitude = 0.6,
wavenumber_a = 2.0,
wavenumber_b = 2.1,
omega_a = 0.5,
omega_b = 0.55
})

add_stimulus_operator(ctx, field, opts)

Generate a NeRF-style positional encoding: a superposition of sinusoidal bands with geometrically growing wavenumbers. Provides rich multi-frequency structure useful for forcing spatial complexity and feature initialization.

add_stimulus_operator(ctx, field, [options]) -> operator

Returns: Operator handle (userdata)

Note: Requires type = "stimulus_posenc".

Let τ=t+time_offset\tau = t + \text{time\_offset} and define:

θl=k0γluωτ+ϕ,l=0,,B1\theta_l = k_0\,\gamma^l\,u - \omega \tau + \phi,\quad l=0,\dots,B-1

with encoded sum

E(u,τ)=Iu+l=0B1eiθl,I={1,include_identity=true0,otherwiseE(u,\tau) = I\,u + \sum_{l=0}^{B-1} e^{i\theta_l}, \quad I=\begin{cases} 1,& \text{include\_identity=true}\\ 0,& \text{otherwise} \end{cases}

and injected write

Δu=AB+IE(u,τ).\Delta u = \frac{A}{\sqrt{B+I}}\,E(u,\tau).

Scalar mode uses u=ξ(x,y,τ)u=\xi(x,y,\tau) from coordinate mapping.

Wavevector mode uses u=kxx+kyyu = k_x x + k_y y for the oscillatory bands. When include_identity = true in wavevector mode, the identity term uses uid=(kxx+kyy)/ku_{\text{id}} = (k_x x + k_y y)/\|\mathbf{k}\| (fallback to xx if k=0\|\mathbf{k}\|=0).

Frequency coverage: wavenumbers k0,γk0,γ2k0,,γB1k0k_0, \gamma k_0, \gamma^2 k_0, \ldots, \gamma^{B-1} k_0

ParameterTypeDefaultRangeDescription
typestring Must be "stimulus_posenc"
amplitudedouble 0.0unboundedOverall amplitude (0.0 writes nothing)
base_wavenumberdouble 0.0unboundedBase wavenumber k0k_0 for band 0 (rad/unit)
band_growthdouble 2.0unboundedGeometric frequency growth ratio γ\gamma
bandsinteger 61..64Number of frequency bands BB (clamped to 64)
omegadouble 0.0unboundedTemporal angular frequency (rad/s)
phasedouble 0.0unboundedGlobal phase offset shared by all bands (radians)
time_offsetdouble 0.0unboundedAdditional time shift
rotationdouble 0.0unboundedComplex phase rotation on output (radians)
include_identityboolean falseInclude the identity term ξ(x)\xi(\mathbf{x}) in the sum
scale_by_dtboolean falseScale writes by dt
use_wavevectorboolean falseUse (kx,ky) projection instead of coord mapping; also auto-enabled if nonzero kx or ky is provided
kx, kydouble 0.0unboundedWavevector components; if wavevector mode is active and both are zero, runtime uses (1, 0)

For real fields, only the real component is written. For complex fields, both components are written and rotation is applied.

When coord_mode = "separable" (and use_wavevector = false), the operator evaluates one encoding on x and one on y, then combines them with coord_combine ("multiply" or "add").

With use_wavevector = true, the operator uses x,y directly for projection; origin_*/spacing_* still apply, while coord_mode-specific mapping is bypassed.

Plus coordinate mapping parameters (coord_mode, coord_axis, coord_combine, coord_angle, origin_x/y, spacing_x/y, coord_center_x/y, coord_velocity_x/y, spiral params).

-- Standard 6-band positional encoding
ooc.add_stimulus_operator(ctx, field, {
type = "stimulus_posenc",
amplitude = 0.8,
base_wavenumber = 2.0,
bands = 6,
band_growth = 2.0
})
-- High-resolution 10-band encoding
ooc.add_stimulus_operator(ctx, field, {
type = "stimulus_posenc",
amplitude = 0.5,
base_wavenumber = 0.5,
bands = 10,
band_growth = 2.0
})
-- Temporal oscillation with golden-ratio-like growth
ooc.add_stimulus_operator(ctx, field, {
type = "stimulus_posenc",
amplitude = 0.4,
base_wavenumber = 1.0,
bands = 8,
band_growth = 1.618,
omega = 0.3
})
-- Radial positional encoding
ooc.add_stimulus_operator(ctx, field, {
type = "stimulus_posenc",
amplitude = 0.6,
base_wavenumber = 1.5,
bands = 6,
coord_mode = "radial",
coord_center_x = 128,
coord_center_y = 128
})

add_stimulus_operator(ctx, field, opts)

Generate a structured spectral field using a polar frequency grid with logarithmically-spaced radial bins and uniformly-spaced angular bins. Provides deterministic or randomized-phase coverage of 2D k-space.

add_stimulus_operator(ctx, field, [options]) -> operator

Returns: Operator handle (userdata)

Note: Requires type = "stimulus_log_spectral_grid".

The grid partitions k-space into R×ΘR \times \Theta bins. For each bin (r,θ)(r, \theta), a mode is placed at the bin center kr,θ\mathbf{k}_{r,\theta}:

u(x,t)=Ar=0R1θ=0Θ1wrcos ⁣(kr,θx+ϕr,θ+Ωt)u(\mathbf{x}, t) = A \sum_{r=0}^{R-1} \sum_{\theta=0}^{\Theta-1} w_r \cos\!\left(\mathbf{k}_{r,\theta} \cdot \mathbf{x} + \phi_{r,\theta} + \Omega t\right)

Radial bin centers (log spacing):

kˉr=kmin(kmaxkmin)(r+0.5)/R\bar{k}_r = k_{\min} \cdot \left(\frac{k_{\max}}{k_{\min}}\right)^{(r+0.5)/R}

Angular bin directions (with orientation offset α\alpha):

θ^θ=α+2πθΘ\hat{\theta}_\theta = \alpha + \frac{2\pi \theta}{\Theta}

Per-shell amplitude weighting with spectral slope β\beta: wrkˉrβ/2w_r \propto \bar{k}_r^{-\beta/2}

Phases ϕr,θ\phi_{r,\theta}: random (seeded) when random_phase = true, else 0.

ParameterTypeDefaultRangeDescription
typestring Must be "stimulus_log_spectral_grid"
amplitudedouble unboundedOverall amplitude (required)
k_mindouble 0.2>0Minimum log-grid radius (rad/unit)
k_maxdouble 2.0>0Maximum log-grid radius (rad/unit)
radial_binsinteger 6≥1Number of logarithmic radial bins RR
angular_binsinteger 12≥1Number of angular bins per radial bin Θ\Theta
spectral_slopedouble 0.0unboundedSpectral slope β\beta, PSD kβ\propto \|k\|^{-\beta}
orientationdouble 0.0unboundedGrid orientation angle α\alpha (radians)
orientation_ratedouble 0.0unboundedOrientation drift rate (rad/s)
omegadouble 0.0unboundedTemporal angular frequency (rad/s)
phasedouble 0.0unboundedGlobal phase offset (radians)
time_offsetdouble 0.0unboundedAdditional time shift
rotationdouble 0.0unboundedComplex phase rotation on output (radians)
seedinteger 1≥1Seed for random phase initialization
random_phaseboolean trueRandomize per-mode phases using seed
-- Standard log spectral grid
ooc.add_stimulus_operator(ctx, field, {
type = "stimulus_log_spectral_grid",
amplitude = 0.7,
k_min = 0.2,
k_max = 3.0,
radial_bins = 7,
angular_bins = 16
})
-- Deterministic grid (no random phases)
ooc.add_stimulus_operator(ctx, field, {
type = "stimulus_log_spectral_grid",
amplitude = 0.5,
k_min = 0.3,
k_max = 2.0,
radial_bins = 5,
angular_bins = 8,
random_phase = false
})
-- Rotating spectral grid
ooc.add_stimulus_operator(ctx, field, {
type = "stimulus_log_spectral_grid",
amplitude = 0.6,
k_min = 0.2,
k_max = 3.0,
radial_bins = 6,
angular_bins = 12,
orientation_rate = 0.2
})
-- Pink-noise weighted grid
ooc.add_stimulus_operator(ctx, field, {
type = "stimulus_log_spectral_grid",
amplitude = 0.8,
k_min = 0.1,
k_max = 4.0,
radial_bins = 8,
angular_bins = 16,
spectral_slope = 2.0,
seed = 42
})

add_stimulus_operator(ctx, field, opts)

Generate one-shot reaction-diffusion seed templates for initializing RD systems. Produces spots, stripes, labyrinth, or rings patterns with controllable spatial scale and binary sharpness — applied once at the start of the simulation.

add_stimulus_operator(ctx, field, [options]) -> operator

Returns: Operator handle (userdata)

Note: Requires type = "stimulus_rd_seed". Applied at time = 0 (uses_dt = false).

The seed pattern is synthesized by randomly placing NN primitive shapes (seed_count) and compositing them:

Spots:

f(x)=i=1Nexp ⁣(xci22s2)f(\mathbf{x}) = \sum_{i=1}^{N} \exp\!\left(-\frac{|\mathbf{x} - \mathbf{c}_i|^2}{2 s^2}\right)

Stripes:

f(x)=i=1Nsin(kix+ϕi)f(\mathbf{x}) = \sum_{i=1}^{N} \sin(\mathbf{k}_i \cdot \mathbf{x} + \phi_i)

Labyrinth: Perlin-noise-derived zero-crossings producing maze-like connected regions.

Rings: Concentric Gaussian annuli of randomly varying radii.

Each pattern is then passed through a logistic function:

u(x)=Aσ ⁣(sh(f(x)θ))+bu(\mathbf{x}) = A \cdot \sigma\!\left(s_h \cdot (f(\mathbf{x}) - \theta)\right) + b

where shs_h = seed_sharpness, θ\theta = seed_threshold, bb = seed_bias.

ParameterTypeDefaultRangeDescription
typestring Must be "stimulus_rd_seed"
amplitudedouble unboundedPattern amplitude scale (required)
seed_patternenum "spots"see belowRD seed template
seed_countinteger 24≥1Number of seed primitives
seedinteger 1≥0Random seed controlling layout
seed_scaledouble 6.0(0, 64]Spatial frequency/scale control
seed_thresholddouble 0.5[0, 1]Logistic threshold for edge sharpening
seed_sharpnessdouble 12.0[0.1, 64]Logistic edge sharpness
seed_biasdouble 0.0[-2, 2]Additive baseline applied after synthesis
omegadouble 0.0unboundedTemporal phase drift rate (rad/s)
phasedouble 0.0unboundedGlobal phase offset (radians)
time_offsetdouble 0.0unboundedAdditional time shift
rotationdouble 0.0unboundedComplex phase rotation on output (radians)

Seed pattern options: spots, stripes, labyrinth, rings

Plus coordinate mapping parameters.

-- Spots: classic Turing initial condition
ooc.add_stimulus_operator(ctx, field, {
type = "stimulus_rd_seed",
amplitude = 0.9,
seed_pattern = "spots",
seed_count = 28,
seed = 7
})
-- Labyrinth: maze-like initial topology
ooc.add_stimulus_operator(ctx, field, {
type = "stimulus_rd_seed",
amplitude = 0.8,
seed_pattern = "labyrinth",
seed_count = 32,
seed_scale = 8.0,
seed = 42
})
-- Stripes with sharp edges
ooc.add_stimulus_operator(ctx, field, {
type = "stimulus_rd_seed",
amplitude = 1.0,
seed_pattern = "stripes",
seed_count = 12,
seed_sharpness = 20.0,
seed_scale = 4.0,
seed = 3
})
-- Concentric rings
ooc.add_stimulus_operator(ctx, field, {
type = "stimulus_rd_seed",
amplitude = 0.7,
seed_pattern = "rings",
seed_count = 8,
seed_scale = 10.0,
coord_mode = "radial",
coord_center_x = 128,
coord_center_y = 128,
seed = 5
})

add_stimulus_operator(ctx, field, opts)

Generate rings-and-spokes structure from the combination of log-radius and polar angle. This is useful for spiral masks, spoke wheels, and scale-aware angular patterns.

Experimental: Parameter names and coordinate interactions may change while the log-polar family settles.

add_stimulus_operator(ctx, field, [options]) -> operator

Returns: Operator handle (userdata)

Note: Requires type = "stimulus_log_polar".

The phase is built from log-radius and angle:

ϕ(x,t)=krlog(r+ε)+mθωt+ϕ0\phi(\mathbf{x}, t) = k_r \log(r + \varepsilon) + m\theta - \omega t + \phi_0

where krk_r is radial_frequency, mm is angular_frequency, and ε\varepsilon is radius_floor.

ParameterTypeDefaultDescription
typestring Must be "stimulus_log_polar"
radial_frequencydouble 6.0Coefficient multiplying log(r+ε)\log(r + \varepsilon)
angular_frequencydouble 5.0Coefficient multiplying the polar angle
orientationdouble 0.0Extra frame rotation before polar conversion
orientation_ratedouble 0.0Angular drift rate of the output frame
radius_floordouble 0.25Positive epsilon added before the logarithm

Plus shared coordinate mapping and timing parameters (amplitude, omega, phase, time_offset, rotation, scale_by_dt).

ooc.add_stimulus_operator(ctx, field, {
type = "stimulus_log_polar",
amplitude = 0.8,
radial_frequency = 7.0,
angular_frequency = 4.0
})
ooc.add_stimulus_operator(ctx, field, {
type = "stimulus_log_polar",
amplitude = 0.5,
orientation_rate = 0.2,
radius_floor = 0.1
})