Skip to main content

Open detection of engineered biosignatures in remote hyperspectral imagery

Project description

HyperMix

🔬 HyperMix

Open detection of engineered biosignatures in remote hyperspectral imagery

License: MIT Python PyTorch Tests CI Status Live Observatory Funded by Experiment Foundation

Benchmarking faint engineered reporters in noisy remote hyperspectral cubes, with calibrated uncertainty and explicit baselines.


We can now read living, engineered cells from a drone, ninety meters up (Chemla et al., Nature Biotechnology, 2026). But out in the real world that signal is faint: it hides inside the spectrum of soil, leaves, and water, the atmosphere distorts it, and cheap sensors bury it in noise. A hyperspectral camera hands you a mountain of data, not an answer. Pulling the answer out is an algorithm problem, and that is what HyperMix is for.

HyperMix tests detection and spectral unmixing as regularized inverse problems under unknown natural backgrounds, sparse reference libraries, and low SNR. It is developed by a statistician working in medical imaging, porting the low-SNR, cross-device reconstruction toolkit from retinal OCT to biology at a distance. Everything here is MIT licensed. So far, the learned methods have not robustly surpassed a well-calibrated spatial matched filter; the open benchmark and its negative results are the contribution.

📚 Contents

✨ Highlights

  • 🌍 Physics-based scene simulator with exact ground truth (NumPy only, deterministic).
  • 🛰️ Real-background benchmark on an AVIRIS cube (Indian Pines) via implanted synthetic targets.
  • 🧬 Espectros medidos: endmembers USGS e absorbância de pellets bioHSI para biliverdina/SmURFP e bacterioclorofila a.
  • 🧠 Detector aprendido, avaliado contra baselines por pixel e com suavização espacial em 3 fundos reais.
  • 🧪 Unmixing head that estimates fractional abundance (how much, not just whether).
  • 🎯 Calibrated uncertainty benchmark with Platt scaling, temperature scaling, NLL, Brier, ECE and reliability curves.
  • 🔓 100% open, MIT licensed, reproducible from a clean clone.

🚀 Quickstart

Run it in your browser, no setup: Open In Colab

Or locally:

pip install "hypermix[viz]"     # published package
from hypermix import simulate_scene, spectral_matched_filter, roc_auc

scene = simulate_scene(snr_db=10.0, seed=0)          # cube + full ground truth
score = spectral_matched_filter(scene.cube, scene.reporter)
print("AUC:", roc_auc(score, scene.detection_gt))

Reproduce everything:

python examples/run_demo.py         # simulator + baseline, AUC vs SNR
python scripts/fetch_data.py        # download the real AVIRIS cube
python -m hypermix.benchmark        # full benchmark (synthetic + real)
python scripts/train_detector.py    # train the learned detector (needs ".[train]")
python scripts/run_mismatch_experiment.py  # spectral mismatch robustness
python scripts/realism_experiment.py       # measured spectra + SRF + atmosphere
python scripts/target_variability_experiment.py  # measured target variability
pytest -q                           # 67 tests

Para desenvolver a partir do clone, use pip install -e ".[viz,dev]".

🌐 Web Observatory

Explore a fotografia auditada dos resultados em hypermix-observatory.vercel.app. O painel permite variar target SNR, mismatch espectral e tracks de variabilidade, além de comparar alvo oráculo e alvo laboratorial sob os controles físicos da Fase B.

A interface abre em inglês e oferece as bandeiras dos Estados Unidos e do Brasil no topo para alternar todo o conteúdo entre inglês e português sem sair da página.

O Map Studio permite enviar localmente um PNG, JPEG ou WebP de um mapa de scores e explorar a máscara em diferentes limiares. O brilho é interpretado como score apenas para visualização; imagens RGB não executam inferência HyperMix e nunca são enviadas ao servidor.

O observatório é uma visualização interativa dos artefatos em results/. Ele não treina o modelo nem executa inferência no navegador, e os números não são sincronizados automaticamente. A conclusão honesta permanece visível no produto: o detector aprendido não supera de forma robusta um matched filter espacial bem calibrado neste benchmark.

Para executar ou publicar o app, consulte webapp/README.md.

🧠 Milestone 2: detector aprendido com contexto espacial

hypermix.detector feeds each pixel the scene's own adaptive detector outputs (matched filter, ACE) plus spatial context, z-scored per scene, and a small PyTorch network learns a nonlinear combination. O treinamento usa apenas fundos simulados; os testes usam fundos reais com o mesmo alvo sintético, modelo de mistura linear e gerador de blobs do treino. Portanto, este experimento mede robustez à troca de fundo, não generalização completa para alvos reais. It ships MC-dropout uncertainty.

Learned detector on real background
Fundo real Indian Pines com alvo implantado a target SNR de 5 dB. O painel compara o matched filter por pixel, o detector aprendido e a incerteza estimada.

📊 Benchmarks

Detection AUC on the real Indian Pines background (implanted target, 3 seeds):

Target SNR (dB) Matched filter Matched filter (spatial) ACE 🧠 Learned
20 0.991 0.998 0.878 0.999
10 0.990 0.999 0.878 0.999
5 0.985 0.998 0.870 0.999
0 0.970 0.998 0.849 0.998

Target SNR é definido como a razão entre o RMS da contribuição espectral do alvo, medido nos pixels positivos, e o RMS do ruído aditivo. O baseline espacial aplica ao matched filter um blur gaussiano fixo com sigma=1,5 pixel. Na média das três cenas e quatro níveis de target SNR, o matched filter espacial alcança 0,990 AUC e o detector aprendido 0,987. Portanto, o detector não supera o comparador espacial neste protocolo. A vantagem sobre o MF por pixel, 0,943 AUC, não isola uma vantagem espectral.

🏆 Leaderboard

Detection AUC across 3 real hyperspectral scenes of different sensors and band counts (Indian Pines & Salinas: AVIRIS; Pavia University: ROSIS), 3 seeds. Mean AUC averages over all scenes and target SNR = 20, 10, 5, 0 dB. O detector é treinado apenas em simulação, mas treino e teste compartilham o espectro do repórter, a mistura linear e o prior de blobs. Reproduce: python scripts/make_leaderboard.py.

Rank Method Mean AUC AUC @ 0 dB
1 Matched filter (spatial) 0.990 0.982
2 🧠 Learned detector (HyperMix) 0.987 0.972
3 Matched filter 0.943 0.908
4 ACE 0.860 0.811
5 Spectral Angle Mapper 0.656 0.655

Per-scene AUC @ target SNR de 0 dB. Pavia usa ROSIS; Indian Pines e Salinas usam AVIRIS. A troca de sensor também altera o número de bandas, mas não torna real o alvo implantado:

Method Indian Pines Salinas Pavia U.
Matched filter (spatial) 0.998 0.998 0.951
🧠 Learned detector 0.998 0.998 0.919
Matched filter 0.970 0.969 0.786

Robustez a mismatch espectral

O alvo implantado permanece fixo, mas a assinatura entregue aos detectores é deslocada no eixo normalizado de índices de bandas. AUC média em três cenas, três seeds e target SNR de 5 dB:

Deslocamento MF AUC (queda) MF espacial AUC (queda) Detector AUC (queda)
0% 0.940 (0.000) 0.990 (0.000) 0.987 (0.000)
1% 0.899 (0.041) 0.983 (0.007) 0.973 (0.014)
2,5% 0.781 (0.159) 0.920 (0.070) 0.907 (0.080)
5% 0.647 (0.293) 0.730 (0.260) 0.710 (0.277)

O deslocamento é uma fração da faixa de índices, não uma distância em nanômetros, pois as grades espectrais dos sensores diferem. O experimento mede sensibilidade a mismatch controlado, não substitui validação com espectros medidos. Resultados completos em results/mismatch.md.

Realismo físico opt-in

A Fase B adiciona quatro controles sem alterar os defaults usados nos números da Fase A: espectros medidos, SRF gaussiana parametrizada em nanômetros, atmosfera simples com absorções estruturadas e mistura bilinear generalizada. O artefato results/realism.md usa uma grade simulada calibrada em comprimento de onda, target SNR de 20, 10, 5 e 0 dB e 5 seeds.

Cenário MF MF espacial ACE SAM MF espacial com alvo lab
Controle estilizado, linear 0.952 0.983 0.715 0.907 0.983
Espectros medidos, linear 0.976 0.995 0.719 0.968 0.995
Medidos + SRF 10 nm 0.976 0.994 0.719 0.968 0.995
Medidos + SRF + atmosfera 0.976 0.994 0.719 0.968 0.913
Medidos + SRF + atmosfera + bilinear 0.947 0.983 0.714 0.969 0.906

O alvo oráculo é a assinatura exata depois do sensor e da atmosfera. O alvo laboratorial usa a absorbância medida convertida antes dessas transformações. Por isso, SRF e atmosfera quase não penalizam o MF oráculo, mas o mismatch atmosférico reduz o MF espacial de 0,994 para 0,913. A mistura bilinear reduz o MF espacial oráculo de 0,994 para 0,983.

No teste separado com três fundos reais, o detector aprendido também não obtém vantagem robusta: sob mistura linear, MF espacial 0,986 vs aprendido 0,980; sob mistura bilinear, 0,989 vs 0,992, empate dentro da margem de 0,005. Esses MAT não carregam centros de banda, então o teste não linear real usa alvo por índice espectral e deve ser interpretado apenas como análise de sensibilidade.

Variabilidade do alvo medido

O último teste da arquitetura atual usa um alvo sorteado de bibliotecas medidas, enquanto o MF e as cinco features do detector aprendido recebem apenas um alvo nominal fixo. O baseline de subespaço segue a formulação clássica de matched subspace detection. AUC média em target SNR de 20, 10, 5 e 0 dB, com 6 seeds estratificadas por ponto:

Track MF espacial nominal Subespaço espacial Aprendido MF espacial oráculo
Hospedeiro, SmURFP/biliverdina 0.996 0.967 0.997 0.997
Hospedeiro + sensor + atmosfera 0.993 0.910 0.996 0.995
Qualquer repórter, BChl ou biliverdina 0.907 0.948 0.928 0.996

Nos dois tracks intra-SmURFP, o detector aprendido fica em empate com o MF espacial nominal pela margem de 0,005. No track heterogêneo de qualquer repórter, o subespaço espacial supera o aprendido por 0,020 AUC. Portanto, variabilidade do alvo também não fornece uma vitória robusta para o MLP atual. O track de família não deve ser descrito como variabilidade intra-molécula.

O experimento usa endmembers USGS em cenas implantadas, com grade calibrada de 400-1000 nm. Ele não é validação remota de expressão biológica naturalmente observada. Resultados completos em results/target_variability.md.

🧪 Unmixing: how much, not just whether

Detection asks is the reporter here? Unmixing asks how much? AbundanceUnmixer adds a regression head (same scene-adaptive features) that estimates the target's fractional abundance. A avaliação usa apenas pixels com abundância maior que 0,02 para Pearson r e target MAE, evitando que os zeros do fundo dominem o resultado. Target SNR de 10 dB, média de 3 seeds:

Cena MF target r Unmixer target r MF target MAE Unmixer target MAE
Indian Pines 0.966 0.982 0.0142 0.0081
Salinas 0.979 0.988 0.0073 0.0237
Pavia University 0.796 0.938 0.0177 0.0093

O unmixer tem maior correlação nas três cenas e menor target MAE em duas. Em Salinas, porém, sua target MAE é mais de três vezes a do MF, evidenciando viés de escala que a correlação isolada esconderia. A MAE em todos os pixels também é preservada em results/unmix_eval.md como diagnóstico secundário.

Reproduce: python scripts/train_unmixer.py.

📦 Open spectral dataset

dataset/ contém uma biblioteca aberta em CSV e NPZ: quatro endmembers medidos do USGS, absorbâncias de pellets publicadas no bioHSI e os dois alvos semelhantes a reflectância derivados por Beer-Lambert. A grade de conveniência tem 400-1000 nm em passos de 10 nm; a fonte empacotada preserva 1 nm. Veja o data card. Reconstrua com python scripts/fetch_reference_spectra.py e python scripts/export_dataset.py.

🗺️ Roadmap

  • Milestones 0–2: simulador, baselines, três fundos reais, detector aprendido, realismo físico e auditorias T1/T7.
  • T8: validar em cubos bioHSI com expressão biológica medida, sem implantação digital. Manifesto e downloader rastreável já concluídos.
  • T9: transferir a assinatura de laboratório para o sensor sem rótulos de avaliação.
  • Milestone 3: CI, PyPI, release v0.5.0 e DOI do Zenodo.
  • T10: calibrar abundância e produzir intervalos de predição.
  • Publicação: preprint após T8/T9 e preparação gradual para revisão de software.

O plano completo, com dependências, critérios de aceite e limites honestos, está em ROADMAP.md.

💾 Data

Datasets are downloaded, not committed:

python scripts/fetch_data.py
python scripts/fetch_biohsi.py --list

Indian Pines is a public AVIRIS scene (Purdue University).

Os cubos bioHSI de Chemla et al. são baixados sob demanda para data/biohsi/. O manifesto curado fixa DOI, versão, licença, tamanho e checksum. O download do primeiro conjunto real de 54 m é explícito porque o arquivo possui cerca de 629 MB:

python scripts/fetch_biohsi.py --dataset rg_on_sand_induction_54m.zip
python scripts/biohsi_roi_overlay.py
python scripts/reproduce_biohsi_54m.py

A reprodução HKM requer pip install -e ".[reproduce,viz]". A auditoria que executa a tag externa dos autores também requer o extra hsi.

O protocolo pré-especificado da análise de 54 m está em results/real_target_protocol.md. A primeira porta de reprodução falhou, inclusive ao executar diretamente a tag oficial nas caixas candidatas. Por isso elas não são tratadas como coordenadas confirmadas da Figura 4g e nenhum baseline foi comparado. O diagnóstico está em results/real_target_reproduction_diagnosis.md.

Os espectros compactos de referência são versionados no pacote. As fontes são USGS Spectral Library Version 7 e o arquivo oficial bioHSI associado a Chemla et al.; URLs, licença e checksums estão em hypermix/data/REFERENCE_SPECTRA.md.

⚠️ Honest limitations

  • Os repórteres medidos são absorbâncias inferidas de pellets, não reflectância absoluta de uma superfície observada remotamente. A conversão por Beer-Lambert é explícita, mas ainda é uma hipótese do simulador.
  • Os endmembers USGS são quatro amostras medidas e não cobrem a variabilidade natural de solo, vegetação e água.
  • O matched filter espacial supera o detector aprendido no leaderboard atual; a vantagem sobre baselines por pixel é explicada em grande parte pelo prior espacial de alvos em blob.
  • O leaderboard da Fase A ainda compartilha repórter aproximado, gerador de blobs e mistura linear entre treino e teste. Os fundos são reais a jusante, mas os alvos implantados não são.
  • Mesmo treinado sobre variabilidade medida, o MLP atual só recebe MF, ACE e versões suavizadas calculadas com o alvo nominal. Ele não acessa informação espectral que esses detectores descartam.
  • Um deslocamento espectral de 5% reduz a AUC do detector aprendido em 0,277; ainda não há validação remota independente com variabilidade biológica.
  • Os cubos MAT atuais não incluem os centros de banda. A avaliação física calibrada em nanômetros permanece simulada até obter metadados espectrais rastreáveis para cada cena real.
  • No unmixing de Salinas, maior correlação não implica menor erro: target MAE de 0,0237 no unmixer contra 0,0073 no MF.
  • The first learned model is a small MLP; richer models and a true unmixing head are future work. All numbers, including failures, are tracked in STATUS.md.

📚 Cite

If you use HyperMix, please cite it (see CITATION.cff). A Zenodo DOI is planned for the next release.

📄 License

MIT. See LICENSE. Built with support from the Experiment Foundation Hyperspectral Biology grant.

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

hypermix-0.5.0.tar.gz (94.4 kB view details)

Uploaded Source

Built Distribution

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

hypermix-0.5.0-py3-none-any.whl (82.8 kB view details)

Uploaded Python 3

File details

Details for the file hypermix-0.5.0.tar.gz.

File metadata

  • Download URL: hypermix-0.5.0.tar.gz
  • Upload date:
  • Size: 94.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for hypermix-0.5.0.tar.gz
Algorithm Hash digest
SHA256 4e536805d875d4a35ffa525982a1cfc99e7f8e0af425f90f82cc3783788da0c7
MD5 5fd858836b9f518889273b8be613d295
BLAKE2b-256 8d390fc08825385f916ffbeed430359dd041b9a09b50df74588588706abfb6aa

See more details on using hashes here.

Provenance

The following attestation bundles were made for hypermix-0.5.0.tar.gz:

Publisher: publish-pypi.yml on JVLegend/HyperMix

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file hypermix-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: hypermix-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 82.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for hypermix-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 a8bb453ad75de68d78badcf9bdaa5e0e35deb2c9c92aa2f6c8a284329bb74ae4
MD5 1fb9b17a1797ab0bec7dfb433115ad9e
BLAKE2b-256 7eab930fa135d039d6c465f82b8ff33c8c8ffb184b8e7a0df748a8c228cd419d

See more details on using hashes here.

Provenance

The following attestation bundles were made for hypermix-0.5.0-py3-none-any.whl:

Publisher: publish-pypi.yml on JVLegend/HyperMix

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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