Skip to main content

SignalMap

Unsupervised condition monitoring for any recorded signal — with verdicts you can check without trusting us.

License Python Status

You give it healthy data. It learns what healthy looks like and flags deviations. No fault labels, no per-sensor tuning. Vibration, acoustics, current — anything you can record.

The part we care most about: every verdict it produces is a signed receipt that a stranger can verify offline with a script that imports nothing from this project. And where the method cannot honestly decide, it says REFUSED rather than guessing.

Install

python3 -m pip install 'signalmap[all]'   # quote the brackets so zsh does not glob them
signalmap plugins                         # confirm the install

[distill] alone is enough for distill / fit / monitor on .npy and .csv banks. Parquet needs pyarrow, which [all] includes.

Two commands

signalmap fit     --dataset healthy.parquet --healthy-label normal --out detector.pt
signalmap monitor --source replay --dataset live.parquet --detector detector.pt

Nothing is labelled as a fault anywhere in that flow. examples/ reproduces it end to end on public bearing data.

What it actually does, and where it stops

On CWRU bearing data, fitting on 945 healthy frames and monitoring 1183 frames catches 238/238 faults with 2/945 false alarms, fully unsupervised.

That number does not transfer, and we measured it rather than assuming it. On nine domains under one frozen recipe — MIMII, Paderborn, MAFAULDA and two constructed controls — the shipped alarm's gap between faulty and healthy is not above zero in eight of them, and in six it never fires at all.

Worse, the direction is not even stable. On MIMII valve and Paderborn phase current the detector ranks anomalies as more normal than normal (AUC 0.2786 and 0.3172, bootstrap CI clear of 0.5), while on MIMII slider it ranks them the expected way (0.8254). There is a theorem behind that, and it applies to any detector that sees only healthy data:

The score is a function of the healthy distribution alone. Hold the fitted detector fixed, vary only the never-observed anomaly distribution, and the AUC attains every value in [0, 1].

So "far from healthy means faulty" is an assumption, not a result. Read the study → — preregistered before any data was touched, nine domains, signed receipts, ten amendments including our own errors.

What changed because of it

The detector no longer assumes the direction. It starts out refusing:

det = DistilledDetector.fit(spec, healthy_windows)
det.decide(w).verdict            # 'REFUSED' — direction unknown

v = det.calibrate_direction(anchor_windows, labels, groups=recording_ids)
v.sign, v.ci_lo, v.ci_hi         # +1 or -1, only when the CI clears 0.5
det.decide(w).verdict            # now 'ALARM' or 'QUIET'

A handful of labelled anchors settles the direction. Without them, REFUSED is the correct answer, and groups makes the bootstrap resample recordings rather than windows — twenty windows cut from one signal are one observation.

Verdicts you can check without us

Every verdict-producing command writes a signed JSON receipt: the claim, the verdict (INCLUDED / EXCLUDED / PASS / REFUSED), the evidence, the sha256 of every input, and an Ed25519 signature. The signing key stays on your machine; only the public key travels.

The verifier is one file that imports nothing from signalmap — stdlib plus cryptography:

signalmap corpus --out receipts/     # the shipped verdicts

curl -sO https://raw.githubusercontent.com/MrPredic/signalmap/main/tools/verify_receipt.py
pip install cryptography
python3 verify_receipt.py receipts/cwru_rqa.receipt.json
# PASS — verdict INCLUDED, integrity only (NOT authenticity)

python3 verify_receipt.py receipts/cwru_rqa.receipt.json --pubkey <hex>
# PASS — verdict INCLUDED, authentic (pinned key)

Flip one byte in a receipt and verification fails. That does not make a verdict true — it makes it attributable and tamper-evident. Without --pubkey you get integrity only, and the tool says so rather than letting you misread it.

The verifier is hardened against 23 concrete attacks on the gap between the bytes that get signed and the fields a human reads: duplicate JSON keys, NaN/Infinity literals, integers past 2⁵³, unpaired surrogates, non-UTF-8 input, and a pinned-key check that used to compare transcriptions rather than key bytes.

distill: features chosen with a receipt

signalmap distill --bank recordings/ --label-by prefix --out artifacts/spec.json

Searches a compositional feature grammar for the few programs that separate your recordings, under a capacity gate (budget = C × n_recordings). Every run emits a gauntlet receipt: leakage-free nested LOGO accuracy, a group-permutation p-value, a label-shuffle null, and cost per window.

Premium families (--premium rqa,coherence) run as opt-in challengers against the distilled base and enter spec.json only on a CI-solid win. Of the eight preregistered verdicts shipped in this repo, six are exclusions — the mechanism refuses far more often than it admits.

More

  • study/ — the sign-identifiability study: preregistration, theory, receipts, and the bank manifests with the sha256 of all 7623 recordings.
  • examples/ — reproduce the CWRU result and the acoustic and electrical recipes.
  • signalmap plugins — sources, sinks, featurizers and models are all pluggable.
  • Model artifacts (.pt) are a trust boundary: loaded with weights_only=True, arbitrary pickle objects rejected.

Experimental work — cross-modal discovery, compositional search, capture adapters for salvaged hardware — lives behind its own flags and is labelled as experimental where it appears. Nothing on this page depends on it.

Contributing

Bug reports and reproductions are the most useful contributions: if a verdict on your data looks wrong, the receipt makes it checkable, and that is exactly the kind of issue we want. Run pytest -q before opening a PR.

License

Apache-2.0.

Release files for signalmap 0.5.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for signalmap 0.5.3
File Size Uploaded
signalmap-0.5.3.tar.gz 104.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for signalmap 0.5.3
File Interpreter ABI Platform
signalmap-0.5.3-py3-none-any.whl Python 3 none any Details

Total release size: 226.5 kB

Release files / signalmap-0.5.3.tar.gz

Download URL signalmap-0.5.3.tar.gz
Size 104.2 kB
Tags Source
SHA-256 checksum
How to use checksums
8857a0d1a46fcafb7b4524c16ecfc82dfcca4a6a2e6d1eead91948d8f5e2f0d9
BLAKE2b-256 checksum
How to use checksums
3ea67e07692acde38f1593f8a362b24585ee03035232df8f2c3a40da5d8fb6c8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 8, 2026.

Transparency log

Release files / signalmap-0.5.3-py3-none-any.whl

Download URL signalmap-0.5.3-py3-none-any.whl
Size 122.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9b1dc761a409997267d4d9c467566ce0d15a1fa2a0ff98f4285bf0763df4abbe
BLAKE2b-256 checksum
How to use checksums
84042d3d7025b24642d5d414c3bdcdfffa89d2886c8715047278e7a505683c4b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 8, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.5.3 This release

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page