Skip to main content

Findakin

Find a kin for every spectrum.

Findakin answers population questions about collections of astronomical spectra: which look alike, what structure they form, which stand out, which changed in time, and which representation (encoder) is the most physical. It is a local Python library built on spectro-kernel (one spectrum → one vector) and LanceDB (an embedded, versioned, columnar store with a vector index). No server, no account: your spectra stay on your disk.

Status: 0.2 alpha, API may still change. Findakin started as a hosted web application (FastAPI + MongoDB + Qdrant + React, retired in October 2026) and was rebuilt as a local-first library. Landing page: findakin.lelain.net · Documentation: findakin.lelain.net/docs.

spectro-kernel  = algorithms on ONE spectrum   (embeddings, I/O, lines, RV, reduction…)
Findakin        = questions on MANY spectra    (index, neighbours, clusters, anomalies,
                                                trajectories, encoder benchmarks)

406 pro-am spectra of three stars read back as spectra: mean and spread per star on a common grid

Three stars of a pro-am campaign (STAROS) read back as spectra after ingestion, embedding and grouping. The documentation works through this population and through 566 SDSS stars, with provenance.

Install

pip install findakin                 # core: store, ingestion, kernel recipes, k-NN, analysis toolbox
pip install "findakin[viz]"          # + the Plotly views (maps, overlays, cluster means, trajectories…)
pip install "findakin[analysis]"     # + UMAP, HDBSCAN, self-organising maps (minisom)
pip install "findakin[vo]"           # + spectra fetched from Virtual Observatory archives (ESO, MAST, CADC…)
pip install "findakin[encoders]"     # + local PyTorch encoders (spectro-kernel embed_pretrained)
pip install "findakin[mcp]"          # + findakin-mcp: the store served to Claude or any MCP client, locally

Python ≥ 3.11.

Quick start

from findakin import Store

st = Store.open("~/findakin/store")                 # a directory; created if missing

# 1. ingest — FITS (BeSS / ISIS / specINTI / Demetra dialects), CSV, JSON, TXT.
#    Spectra are deduplicated by content; metadata (object, time, instrument,
#    observer, site, resolution, coverage) is extracted from the headers.
report = st.ingest_folder("~/spectra/staros", source="staros", tags=["campaign:staros"])
print(report)                                       # 406 files → 406 added, 0 duplicates, 0 errors
st.ingest_vo("https://archive.eso.org/ssap", target="HD 189733", limit=60)   # or from a Virtual Observatory archive
print(st.resolve_objects())                         # 31 spellings → 3 SIMBAD identifiers (main_id), 6 left to you
st.set_object("adraconis", "alf Dra")               # a manual alias; then the series follow the identifiers
st.set_series()
st.measure("snr_der")                               # the kernel measures each spectrum; findakin keeps the values

# 2. embed — any spectro-kernel strategy; several encoders coexist for the same spectra
enc = st.embed(strategy="dct", dim=256, norm_method="z_score")   # → 'dct:v1:256:nogrid:z_score'
enc_ll = st.embed(strategy="log_lambda", dim=256)                 # Doppler-robust recipe
# tip: with min_max the continuum term dominates the vector and every pair scores ≈ 0.99;
# z_score (zero mean) or continuum_subtracted let the lines drive the similarity.

#    a named common grid, stored once: every spectrum resampled on 6545–6580 Å, the sharper
#    ones degraded to R = 8000 at constant R; encoders and flux matrices read the same rows
st.define_grid("halpha", 6545, 6580, resolution=8000)
st.apply_grid("halpha")                                           # 399 added; 345 degraded, 35 coarser, 19 R unknown
enc_ha = st.embed(strategy="dct", dim=64, norm_method="z_score", grid="halpha")   # → 'dct:v1:64:halpha:z_score'
st.create_index(enc)                                              # a vector index, for 10^5+ vectors

# 3. ask
st.neighbours("~/spectra/new_alfdra.fits", k=10, encoder=enc)          # k-NN by file…
st.neighbours(some_id, k=10, encoder=enc, where="resolution > 15000")   # …or by id, filtered
ids, X = st.vectors(enc, where="main_id = 'alf Dra'")                   # numpy matrix for analysis
pop = st.define_population("alfdra-2023", "main_id = 'alf Dra' AND t_mjd BETWEEN 59945 AND 60310")
ids, X = pop.vectors(enc)                                                # the same, with a name that results keep
st.near_duplicates(enc)                                                  # the same observation stored twice?

from findakin.analysis import cluster_embeddings, cluster_stability, detect_anomalies, decompose, series_trajectory
res = cluster_embeddings(X, method="agglomerative", n_clusters=2)     # Ward; linkage kept for a dendrogram
cluster_stability(X, method="agglomerative", n_clusters=2)           # is the partition reproducible?
weird = detect_anomalies(X, method="urf", contamination=0.05)        # unsupervised random forest weirdness
stack = st.flux_matrix(grid="halpha", where="series_id = 'alf Dra'") # the spectra on the grid
pca = decompose(stack.flux, "pca", n_components=5)                   # eigenspectra + reconstruction error
ids_s, t, XS = st.series("alf Dra", enc)                              # one series in time order
tr = series_trajectory(XS, t, ids=ids_s, period=51.42)               # outliers, change points, orbital phase

# 4. look — every view is a Plotly figure (pip install "findakin[viz]")
from findakin import viz
viz.cluster_spectra(stack.wavelength, stack.flux, res.labels)        # clusters read back as spectra
viz.leakage_view(project_embeddings(X).points, meta, by=("object", "instrument"))
viz.trajectory_plot(tr, x="phase", y=pca.weights[:, 0])             # the orbit, folded

Every method is glue over scikit-learn, scipy, astropy, minisom or plotly, cites its reference in the docstring, and returns a result aligned with the input ids.

Same verbs on the command line:

findakin ingest ~/spectra/alphadra --source staros --tag campaign:alphadra
findakin fetch https://archive.eso.org/ssap --target "HD 189733" --limit 60
findakin resolve --series
findakin measure snr_der
findakin embed --strategy dct --dim 256
findakin grid define halpha --wl-min 6545 --wl-max 6580 --resolution 8000 && findakin grid apply halpha
findakin embed --strategy dct --dim 64 --norm-method z_score --grid halpha
findakin index dct:v1:256:nogrid:min_max
findakin search ~/spectra/new_alfdra.fits -k 10 -e dct:v1:64:halpha:z_score
findakin population define alfdra "main_id = 'alf Dra'"
findakin notebook campaign --data ~/spectra/alphadra        # a notebook to start from
claude mcp add findakin -- findakin-mcp --store ~/findakin/store   # then ask Claude about your populations
findakin info

What is in the store

A LanceDB directory, versioned, rebuildable from your files:

Table Content
spectra one row per spectrum: id (content hash), source, object, main_id (resolved), series_id, t_mjd, instrument, spectrograph, observer, site, resolution, wl_min/wl_max, file_uri, tags, raw header (JSON)
objects / populations every spelling met in the headers with its SIMBAD identifier; the named SQL filters with their size and version
flux_native the native wavelength / flux arrays (re-embed with a new encoder without re-reading files)
grids / flux__<grid> the named common grids, and each spectrum on each grid: flux, coverage, native resolution, degraded flag
emb__<encoder> one table per encoder: (id, vector, provenance) — encoder_id = strategy:model_version:dim:grid:norm — with an optional vector index
encoders the encoder registry (config, dimension)
results analyses and kernel measurements stored with their provenance: name, kind, encoder, population, params, {id: value} payload, store version

series_id groups spectra that form a trajectory in time: an object followed over epochs (default), a night of sky spectra (series_from="night", e.g. aurorae), or a folder.

Roadmap (short)

Phase 0 — store, ingestion, kernel encoders, k-NN, CLI ✅ · Phase 2a — population toolbox (clusters + stability, URF anomalies, eigenspectra / NMF, trajectories, SOM), stored results, Plotly views ✅ · Phase 1 — named common λ grids in the store (flux__<grid>, resolution matching at constant R), vector indexes ✅ · Phase 2b — named populations, SIMBAD aliases, notebook templates ✅ · Phase 4 — findakin-mcp over the store, locally ✅ · Phase 3 — learned encoders registry, benchmark with an instrument-leakage score · Phase 5 — thin HTTP façade for applications.

Development

uv venv .venv --python 3.12 && source .venv/bin/activate
uv pip install -e ".[dev]"
pytest -q
ruff check src tests

The landing page lives in website/ (Vite + React, deployed separately).

License

MIT — © 2026 Matthieu Le Lain.

Metadata

Release files for findakin 0.2.7

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

Source distribution (sdist)

Source distribution for findakin 0.2.7
File Size Uploaded Provenance
findakin-0.2.7.tar.gz 159.1 kB With provenance Details

Built distribution (wheel)

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

Total release size: 305.0 kB

Release files / findakin-0.2.7.tar.gz

Download URL findakin-0.2.7.tar.gz
Size 159.1 kB
Tags Source
SHA-256 checksum
How to use checksums
70c6e1e4fd91c7980295bcad532c2245f8ca074d20af0eaa465bd5f5823b5921
BLAKE2b-256 checksum
How to use checksums
4c55ab784a8924ef235db01d7bf3645be5700bc7091e7082d38e0f7829cb2305
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Oct 24, 2026.

Transparency log

Release files / findakin-0.2.7-py3-none-any.whl

Download URL findakin-0.2.7-py3-none-any.whl
Size 145.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ccb2de2e9414029a852a9c0497ffe055c8b2ad36302884a5a5f8181af17c59c5
BLAKE2b-256 checksum
How to use checksums
2e81779605a26e5a06b69d4fd53665c56895b7bb5c8ff67ee77607683a7f2597
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

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 Oct 24, 2026.

Transparency log

Security for findakin 0.2.7

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.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for findakin-0.2.7.tar.gz

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 Oct 24, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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