Skip to main content

Multiscale signal analysis on a normalized scale space

Project description

SignalForge

Multiscale signal analysis on a normalized scale space. Give it any ordered sequence and explore its structure across scales — no labels, no training, no domain-specific code.

Install

pip install adelic-signalforge

Or from source:

git clone https://github.com/adelic-ai/signalforge
cd signalforge
uv sync

Explore your data

SignalForge works on CSV data — from a simple two-column time series to multi-channel, multi-entity datasets. Each channel gets its own surface; channels can be combined to derive new ones. Start with something simple:

# Grab VIX volatility data (2005–2012)
curl -o vix.csv "https://fred.stlouisfed.org/graph/fredgraph.csv?id=VIXCLS&cosd=2005-01-01&coed=2012-12-31"

# What's in it?
sf load vix.csv
  file      : vix.csv
  records   : 2,013
  channels  : ['value']
  range     : 0 → 2,085  (span: 2,085)
  est grain : 2

Build a surface

A surface is a 2D grid — time on one axis, analysis scale on the other. One command:

sf surface vix.csv -hm --max-window 360

This produces a multiscale heatmap showing z-score deviations across all scales. The 2008 financial crisis appears as a vertical band of red — visible across every scale simultaneously.

VIX 2005–2012 heatmap

--max-window 360 means "analyze at scales up to 360 bins." The bin size is estimated from the data, and the full set of valid analysis scales is derived from the bins and your window choice — every scale nests cleanly into the others with no boundary artifacts.

Try different baselines

What's the deviation relative to? That's the baseline. Swap it:

sf surface vix.csv -hm --baseline ewma --alpha 0.1
sf surface vix.csv -hm --baseline median --window 20

Don't know what EWMA does? Ask:

sf inspect ewma
  Exponentially Weighted Moving Average
  =====================================

  Formula:  s_t = α · x_t + (1 - α) · s_{t-1}
  Params:   α (alpha): smoothing factor in (0, 1]. Higher = more responsive.
  ...

Available methods: ewma, median, rolling_mean. See sf inspect <name> for any of them.

Score the residual

Remove the baseline and look at what's left:

sf surface vix.csv -hm --baseline ewma --residual ratio
sf surface vix.csv -hm --baseline median --residual z

Residual modes: difference (absolute), ratio (multiplicative), z (normalized by baseline variability). See sf inspect ratio, sf inspect z.

Zoom in

Spotted something interesting? Zoom:

sf surface vix.csv -hm --start-date 2008-01-01 --end-date 2009-12-31
sf surface vix.csv -hm --start 800 --end 1200

The surface is recomputed over the zoomed region — the lattice geometry applies fresh to the subset.

Set up a workspace

When you're doing serious exploration, initialize a workspace:

sf init my_analysis --csv vix.csv --max-window 360
cd my_analysis
sf surface -hm
sf surface -hm --baseline ewma --residual ratio --save output/ratio.png

The workspace stores your config, so you don't repeat flags. Outputs go to output/. You can version your experiments with git.

View the lattice geometry

sf plan equities-daily

Shows the sampling plan — every window, hop, and p-adic coordinate in the lattice. This is the measurement space your surfaces live in.

Compose pipelines in Python

For more control, compose pipelines programmatically using the graph API:

from signalforge.graph import Input, Bin, Measure, Baseline, Residual, Pipeline
from signalforge.domains import timeseries

records = timeseries.ingest("vix.csv")

x = Input()
b = Bin(agg_funcs={"value": {"value": "mean"}})(x)
m = Measure(profile="continuous")(b)
bl = Baseline(method="ewma", alpha=0.1)(m)
r = Residual(mode="ratio")(m, bl)

pipe = Pipeline(x, r)
pipe.resolve(records=records)
result = pipe.build(records)

Pipelines are lazy DAGs — define the graph, resolve the geometry, then build. Branch and merge freely: two baselines, two residuals, stack them into one surface.

What makes this different

Standard multiscale analysis (STFT, wavelets) requires the analyst to choose window sizes. SignalForge derives the measurement space from your declared windows and grain. The valid scales are the divisors of the horizon — a structure from number theory that guarantees artifact-free tiling, perfect nesting, and structural invariance across recordings.

Two signals with the same sampling plan produce surfaces that are directly comparable — no post-hoc normalization needed. This is what makes ML on surfaces meaningful: features at each scale occupy the same structural position in the lattice.

For a detailed comparison with wavelets, STFT, and EMD: docs/comparison.md

What counts as a signal

Anything ordered. Time-stamped sensor data, sequential event logs, daily market prices, clinical recordings, genomic positions. If it has an order and a value, SignalForge can surface its multiscale structure.

Time is not required — event-ordered sequences work with grain=1, where each event is one bin and scales are measured in events rather than time.

docs/domain_guide.md — how to bring your own data

Demonstrated results

SignalForge detected a clinical epileptic seizure at 13.96σ on CHB-MIT EEG data — no training data, no labels, no EEG-specific code. The same pipeline processes INTERMAGNET geomagnetic observatory data unchanged.

docs/empirical_results.md — full results and reproducibility

Documentation

Doc What it covers
Sampling domain The lattice, horizon, grain, why divisors
Scale space Surfaces, coordinates, the geometry of scale
Structural invariance Why surfaces are directly comparable
Comparison STFT, wavelets, EMD vs SignalForge
Pipeline overview Stages, architecture, the graph API
Domain guide Bring your own data
Data guide Downloading datasets, running examples
Operators Transform operators and derived channels
Grain estimation Automatic grain selection
Grain & horizon design Internal design decisions
EEG discovery The seizure detection case study
Empirical results Cross-domain validation

License

Business Source License 1.1. See LICENSE.

Free for non-commercial use (research, personal projects, evaluation). Commercial use requires a license from Adelic — contact shun.honda@adelic.org.

Converts to Apache 2.0 on 2029-03-22.

Citation

If you use SignalForge in published work, a citation entry will be available once the arXiv preprint is posted.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

adelic_signalforge-0.2.0.tar.gz (12.8 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

adelic_signalforge-0.2.0-py3-none-any.whl (77.8 kB view details)

Uploaded Python 3

File details

Details for the file adelic_signalforge-0.2.0.tar.gz.

File metadata

  • Download URL: adelic_signalforge-0.2.0.tar.gz
  • Upload date:
  • Size: 12.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.8.0

File hashes

Hashes for adelic_signalforge-0.2.0.tar.gz
Algorithm Hash digest
SHA256 25bd84e11491a9e4e7b59372276dceb094b980798e12e0b0cf46555cddc67628
MD5 5e93466f04c52f73708518bec48ddae3
BLAKE2b-256 6a23eb1956ac7ba0ead2efba7dba6863bfc310a594a967ad69598faecbab3f39

See more details on using hashes here.

File details

Details for the file adelic_signalforge-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for adelic_signalforge-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a719f3f247b2cf11617b0f1f14693b90e99af1ff21de531b9861a6e8eee63835
MD5 03932038806481ec58b1ad9a39a74f3a
BLAKE2b-256 5f5b82c37a126f25abe9fbfab21e2b5b1f0f91c5b5b9e66ea0780a40b99ef2e5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page