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()                              # data bound at run time
b = Bin()(x)                             # default: agg="mean". also: "count", "max"
m = Measure()(b)                         # default: profile="continuous"
bl = Baseline("ewma", alpha=0.1)(m)      # also: "median", "rolling_mean"
r = Residual("ratio")(m, bl)             # also: "difference", "z"

pipe = Pipeline(x, r)
result = pipe.run(records)

Pipelines are lazy DAGs — define the graph, run it. 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 — the windowed mean during the seizure deviated nearly 14 standard deviations from the scale baseline. 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.1.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.1-py3-none-any.whl (78.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: adelic_signalforge-0.2.1.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.1.tar.gz
Algorithm Hash digest
SHA256 c5d4b2a65f96cb88becd69135e7495ba9a3f4a209a952a10231f4439a72af97b
MD5 85965deedab171679b768873aced9d77
BLAKE2b-256 6e6d3373ae5d60128ce8ff1f827e1b4eccbb31abc3b05d1f99fab376981ef3ff

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for adelic_signalforge-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 cc1a77c66acc7af8fb15b05bf27faba1e7b6f6cf7a4309f5b7f1670b5d028546
MD5 8396bba3373987c31ef226198c71a940
BLAKE2b-256 7ffda5d96e4cedb079f86e8a3e14432f9f7e22ee8c9ace65bbbd439490ba4057

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