A Python port of the Mätzler (2002) Mie-scattering routines (mie, mie_abcd) and the Jacques/Brown getMieScatter wrapper, delivered with a differential test harness that proves the Python results reproduce the original MATLAB numerically — not just "physically plausible," but matched to the original code's own numbers.
The CI badge covers one workflow with four jobs: MATLAB-equivalent verification on GNU Octave, the pytest matrix (3.9/3.11/3.13), notebook execution, and ruff lint.
PASSED. The Python translation was run against the original MATLAB on 714 independent input cases (8 documented usage scenarios, seeded and reproducible). Every compared value agrees within the agreed engineering tolerances — worst relative error ~2×10⁻⁹, driven by high-order complex-argument Bessel functions and independently confirmed to ~10⁻¹² absolute. Validated live against MATLAB R2025a and GNU Octave 11.3, and cross-checked against an independent Bohren–Huffman implementation (~10⁻¹²). The only intentional differences from MATLAB are documented (suppressed console output; a NaN-vs-finite value in the physically-undefined no-scattering case) and affect no verified quantity.
MATLAB reference vs Python port for every numeric output and coefficient
across all fixtures; points lie on the y = x line. Full interactive report:
report.html (open the raw file) — see also the
scenario coverage matrix and branch map.
You need MATLAB or free Octave and Python 3.9+. Three steps:
- Open a terminal in this folder.
- Run one command — macOS/Linux:
./verify.sh· Windows:verify.bat - Read
report.html(opens automatically). A green PASSED banner means every Python result matched the original MATLAB within tolerance; a red FAILED banner names the diverging value.
The script creates a local .venv, installs the Python deps, auto-detects
MATLAB (including /Applications/MATLAB_*.app) or Octave, and rebuilds the
report. Three independent witnesses confirm the migration: a local MATLAB
run (committed under reports/), the client's own MATLAB run via verify.sh,
and a cloud Octave run in CI.
Нужен MATLAB или бесплатный Octave и Python 3.9+. Три шага:
- Откройте терминал в этой папке.
- Одна команда — macOS/Linux:
./verify.sh· Windows:verify.bat - Откройте
report.html(откроется сам). Зелёный PASSED — все результаты Python совпали с исходным MATLAB в пределах допусков; красный FAILED укажет расхождение.
Скрипт сам создаёт .venv, ставит зависимости, находит MATLAB (в т.ч.
/Applications/MATLAB_*.app) или Octave и пересобирает отчёт. Отчёт содержит:
статусы PASS(both/rel/abs), матрицу покрытия сценариев, карту веток, худшие
случаи по относительной и абсолютной погрешности отдельно и SHA-256 корпуса.
General-purpose Python Mie packages (e.g. miepython, PyMieScatt) implement
the Bohren–Huffman algorithm independently and are a fine choice for new work.
This repository does something narrower and, for a migration, more valuable:
it is a provably faithful port of one specific legacy codebase — the exact
mie/mie_abcd/getMieScatter MATLAB a client already has deployed, already
validated against their instruments, and already embedded in downstream
tooling that expects its exact numbers. The deliverable isn't "a Mie
calculator that gets the physics right" — it's evidence that this Python
function returns what that MATLAB function returns, case by case, with the
divergence risks (rounding, special-function branch cuts, indexing) named and
tested. If a generic library already meets your need, use it; this exists for
the case where "close enough physically" isn't good enough and you need to
keep your original code's numbers.
pip install 'git+https://github.com/GrednevMSU/mie-scattering-matlab-to-python'from mie_py import mie, mie_abcd, get_mie_scatter
u = mie(1.33 + 0j, 5.0) # [Re(m), Im(m), x, qext, qsca, qabs, qb, g, qratio]
qsca, g = u[4], u[7]
mus, g, musp = get_mie_scatter( # tissue-optics wrapper -> [mus, g, musp] (cm^-1)
lambda_=0.633, dia=0.05, fv=0.05, npar=1.57 + 0j, nmed=1.33)A runnable tour (usage + both demo scenarios + a verification teaser) is in
notebooks/quickstart.ipynb. The MATLAB↔Python
symbol map is in docs/NAME_MAP.md.
Root holds only what a first-time visitor needs; everything else is grouped by purpose so the structure reads as intentional, not sprawling.
README.md · LICENSE · THIRD_PARTY_NOTICES.md first-minute essentials
verify.sh · verify.bat one-command entry point
report.html the golden, pre-generated report
mie_py/ the Python port (numpy/scipy)
harness/ generate_fixtures.m, run_reference.m, matlab_src/
(ORIGINAL MATLAB, untouched), compare.py, report.py,
plots.py, tolerances.yaml — the whole verification engine
fixtures/ the seeded input corpus + manifest.json (SHA-256)
reference_outputs/ golden MATLAB outputs, committed for MATLAB-free reruns
reports/ live verification_report.md, figures/, archived report versions
docs/ methodology notes, findings, name map, changelogs, whitepaper
tests/ pytest suite against committed MATLAB golden (no MATLAB needed)
bench/ MATLAB-vs-Python timing scripts + committed results
notebooks/ quickstart.ipynb
.github/workflows/ CI: Octave verify + pytest matrix + notebook + lint
Architecture, in one picture:
harness/matlab_src/ (ORIGINAL MATLAB — never modified)
│ harness/generate_fixtures.m ──► fixtures/ + manifest.json (seeded corpus, SHA-256)
│ harness/run_reference.m ──► reference_outputs/ (golden outputs)
▼
┌──────────────────┐ same inputs ┌────────────────────┐
│ MATLAB / Octave │◄────────────────────►│ mie_py/ (PORT) │
└──────────────────┘ └────────────────────┘
\ /
\ harness/compare.py / (tolerances.yaml)
▼ ▼
report.html + reports/verification_report.md (+ figures)
Reproduce the report without MATLAB (uses the committed golden):
docker build -t mie-verify .
docker run --rm -v "$PWD/out:/out" mie-verify # writes out/report.htmlSingle-machine mie() timing (MATLAB R2025a vs Python on this hardware); see
docs/BENCHMARK.md for methodology and caveats.
| x | nmax | Python [µs] | MATLAB [µs] | ratio |
|---|---|---|---|---|
| 1 | 7 | 55.9 | 318.9 | 0.18× |
| 50 | 67 | 335.1 | 593.8 | 0.56× |
| 150 | 173 | 1743 | 1761 | 0.99× |
The port is ~2× faster on short series and reaches parity on long ones. Speed is not a project goal; timing is shown for transparency. Numbers vary with hardware and BLAS.
docs/VERIFICATION_NOTES.md— function inventory, the risk table of every MATLAB↔Python divergence hazard (nmax rounding, half-integer Bessel functions, conjugate transpose, non-scattering singularities…), tolerance justifications, corpus design.docs/ORIGINAL_CODE_FINDINGS.md— documented deviations (F1–F6) and the two review claims that were not defects.THIRD_PARTY_NOTICES.md— provenance and license status of the original MATLAB.docs/whitepaper.md— methodology write-up (placeholder / outline).docs/CORPUS_CHANGELOG.md— audit trail for the fixture corpus itself, independent of the repo's own release history.
Verified envelope: tissue-optics refractive indices (real 1.0–1.6), absorbing
particles up to Im(npar)=0.1, non-absorbing (real) medium, size parameter
x ≤ 150 (dia ≤ 10 µm). Out of domain: x < 0 (matches original by erroring)
and complex nmed (finding F4).
I port legacy MATLAB/Fortran/C numerical code to Python and deliver the proof it still computes the same answers: a reproducible equivalence harness and a report a non-specialist can audit. Engagements come in three tiers (scope below; contact for a quote).
| Basic | Standard | Enterprise | |
|---|---|---|---|
| Port to NumPy/SciPy | ✓ | ✓ | ✓ |
| Bug-for-bug fidelity + documented deviations | ✓ | ✓ | ✓ |
| Seeded fixture corpus + reference runner | ✓ | ✓ | ✓ |
| Per-output tolerances with written justification | ✓ | ✓ | ✓ |
| Single-file HTML pass/fail report | ✓ | ✓ | ✓ |
pytest suite + packaging (pip install) |
✓ | ✓ | |
| Convergence figures + benchmark | ✓ | ✓ | |
| CI (cloud second-engine witness) + Docker | ✓ | ✓ | |
| Extended envelope / edge-case hardening | ✓ | ✓ | |
| Multi-engine cross-validation (MATLAB + Octave) | ✓ | ||
| Whitepaper + methodology write-up | ✓ | ||
| Handover, training, maintenance window | ✓ |
This repository is a worked Basic→Standard example end to end. Prices depend on code size, algorithm complexity, and required envelope — contact for a quote.
Contact: grednevnv@my.msu.ru · github.com/GrednevMSU
License: MIT for the port and harness; harness/matlab_src/ is
third-party — see THIRD_PARTY_NOTICES.md.
