Metadata-Version: 2.4
Name: hamlet-toolkit
Version: 0.1.1
Summary: Experimental Hamiltonian inference from STM/STS data with simulation and machine learning
Author: Greta Lupi
License-Expression: GPL-3.0-or-later
Project-URL: Repository, https://github.com/GretaLupi/hamlet-toolkit
Project-URL: Issues, https://github.com/GretaLupi/hamlet-toolkit/issues
Project-URL: Documentation, https://github.com/GretaLupi/hamlet-toolkit/blob/main/docs/user-guide.md
Project-URL: Changelog, https://github.com/GretaLupi/hamlet-toolkit/blob/main/CHANGELOG.md
Keywords: hamiltonian-learning,spin-chains,heisenberg-model,spectroscopy,inverse-problems,scanning-tunneling-microscopy,dmrg
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Physics
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: matplotlib>=3.7
Requires-Dist: numpy>=1.24
Requires-Dist: pandas>=2.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: scipy>=1.10
Requires-Dist: scikit-learn>=1.3
Provides-Extra: io
Provides-Extra: ml
Requires-Dist: tensorflow>=2.13; extra == "ml"
Provides-Extra: gpu
Requires-Dist: tensorflow[and-cuda]>=2.14; sys_platform == "linux" and extra == "gpu"
Provides-Extra: simulation
Requires-Dist: dmrgpy>=0.1.0; extra == "simulation"
Provides-Extra: tune
Requires-Dist: optuna>=3.0; extra == "tune"
Provides-Extra: all
Requires-Dist: matplotlib>=3.7; extra == "all"
Requires-Dist: pandas>=2.0; extra == "all"
Requires-Dist: tensorflow>=2.13; extra == "all"
Requires-Dist: optuna>=3.0; extra == "all"
Requires-Dist: dmrgpy>=0.1.0; extra == "all"
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == "dev"
Requires-Dist: pytest>=7.4; extra == "dev"
Requires-Dist: ruff>=0.6; extra == "dev"
Requires-Dist: twine>=5.1; extra == "dev"
Dynamic: license-file

<p align="center">
  <img src="https://raw.githubusercontent.com/GretaLupi/hamlet-toolkit/main/assets/logos/hamlet-logo.png" alt="HamLeT — Hamiltonian Learning Toolkit" width="390">
</p>

# HamLeT

[![PyPI](https://img.shields.io/pypi/v/hamlet-toolkit.svg?color=087f8c)](https://pypi.org/project/hamlet-toolkit/)
[![Python](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12%20%7C%203.13-087f8c.svg)](https://www.python.org/downloads/)
[![License: GPL v3](https://img.shields.io/badge/license-GPLv3-087f8c.svg)](https://github.com/GretaLupi/hamlet-toolkit/blob/main/LICENSE)

HamLeT (Hamiltonian Learning Toolkit) is an experimental-facing framework for
inferring Hamiltonians and physical parameters from scanning tunnelling
microscopy and spectroscopy data. It connects raw-data inspection and
preprocessing to simulated dataset generation, supervised model training,
model matching, inference, and reproducible reports.

Spin chains are HamLeT's first fully implemented application. Its modular
experiment → simulation → learning → inference workflow is designed for
Hamiltonian-learning problems based on STM/STS measurements.

HamLeT **0.1.0 is a complete, working toolkit for spin-chain Hamiltonian
inference**. Its spin-chain workflows are implemented end to end and extensively
tested: experimentalists can import site-resolved STM/STS measurements, inspect
and crop spectra, match compatible pretrained models, generate simulated
training data, train their own estimators, infer couplings, and export results.
Physical energies are expressed in meV; at the DMRGPy simulator boundary,
`1 DMRGPy energy unit = 10 meV`.

## How it works, in one picture

<p align="center">
  <img src="https://raw.githubusercontent.com/GretaLupi/hamlet-toolkit/main/assets/figures/pipeline.png" alt="Simulate, measure, infer: a dynamical correlator becomes per-site dI/dV, and a model reads the couplings back out" width="100%">
</p>

**Simulate.** For a spin chain whose couplings you choose, exact
diagonalisation or DMRG gives the site-resolved dynamical spin correlator
S<sub>ii</sub>(ω) — the left panel, sites up the axis and bias across it. Each
bright band is an excitation of the chain, and where it sits and how much
weight it carries at each site is what the couplings determine.

**Measure.** An STM integrates that correlator: d*I*/d*V* at bias *V* collects
every excitation below *eV*, so each band in the left panel becomes a step in
the middle one. This is the form your own data arrives in, and the form the
simulated dataset is built to match.

**Infer.** A model trained on thousands of such simulated chains reads the
couplings back out of a single measured spectrum. The right panel recovers
J1<sub>xy</sub>, J2, J3 and Jz for a chain the model never saw during
training — grey is the truth, teal what it returned.

Every number in that figure is produced by this package; regenerate it with
`python scripts/make_readme_figures.py`.

## Start with the interface

HamLeT needs **Python 3.10 or newer**. Check what you have with
`python --version`.

Pick the install that matches what you want to do — the difference is which
models you can run, and whether you can simulate your own training data.

```bash
# Look at measurements and use the shipped ridge and random-forest models
python -m pip install hamlet-toolkit

# ...and the Keras models, including the local-window model that works on
# chains of any length
python -m pip install "hamlet-toolkit[ml]"

# ...and dataset generation, which you need to train a model for your own
# system rather than reuse a shipped one
python -m pip install "hamlet-toolkit[simulation]"

# everything above at once
python -m pip install "hamlet-toolkit[all]"
```

Then:

```bash
hamlet gui
```

Two things worth knowing before choosing. **The base install cannot generate a
dataset**, so training a model for your own system needs `[simulation]`, which
pulls DMRGPy and through it Julia — the heaviest dependency here. And **if you
already have TensorFlow or DMRGPy in your environment, the plain install is
enough**: HamLeT imports whatever it finds, so the extras exist only to fetch
those packages for people who do not have them, and naming one you already
satisfy risks pip upgrading a build you chose deliberately.

Of the three published models, two run on the base install; the
variable-length local-window model is a Keras model and needs `[ml]`. Whichever
you install, the interface lists exactly which models it can load.

The local browser interface guides the full workflow:

1. select a prepared measurement or a folder containing one Nanonis
   `.dat`/`.txt` spectrum per site;
2. inspect every site and choose the visible bias cutoff;
3. check whether a shipped or locally trained model matches the system, chain
   length, view, cutoff, and preprocessing contract;
4. reuse it, or generate a dataset and train ridge, random-forest, MLP, or CNN
   models from the interface;
5. inspect held-out simulated-test fidelity and per-parameter errors before
   applying a newly trained model;
6. infer the couplings and export a LaTeX/PDF summary for a colleague,
   an HTML report, a plot, a CSV, and a JSON result.

It binds to localhost and does not upload measurements elsewhere. Long jobs run
in the background. Close it with the **Stop server** button or `Ctrl+C`.

<p align="center">
  <img src="https://raw.githubusercontent.com/GretaLupi/hamlet-toolkit/main/assets/figures/interface-overview.png" alt="The HamLeT interface: six cards, each naming what it needs and how long it takes" width="88%">
</p>

Every page says what it needs and how long it will take before you start, so a
long run is never a surprise.

<p align="center">
  <img src="https://raw.githubusercontent.com/GretaLupi/hamlet-toolkit/main/assets/figures/interface-model-match.png" alt="The compatibility check: each model with the family it assumes, whether it is usable, and the reason it was refused" width="88%">
</p>

**A model is refused with a reason, not silently applied.** Each one is listed
with the family of Hamiltonian it assumes and what it needs of the sample: the
wrong bias cutoff, a chain length it was never trained on, or — for a model
trained with impurities at specific sites — a sample that has not been declared
to have them. Which family to assume is yours to choose, since spectra do not
decide it; what a model requires of the sample is not.

<p align="center">
  <img src="https://raw.githubusercontent.com/GretaLupi/hamlet-toolkit/main/assets/figures/interface-results.png" alt="Inferred couplings for an eight-site chain: bond values with model spread, the chain diagram, and the coupling table" width="88%">
</p>

The couplings come back with the spread across ensemble members, a table you
can export, and the analysis window and chain length the model was applied
under. Read that spread as disagreement between trained members, not as a
calibrated error bar — [the theory notes](https://github.com/GretaLupi/hamlet-toolkit/blob/main/docs/theory.md#5-what-a-trained-models-numbers-mean) say why.

The *Start here* page lists every folder it writes to, and `hamlet where`
prints the same layout from the terminal: `results/` beside a source checkout,
`~/.hamlet/workspace/` for an installed package, or `HAMLET_WORKSPACE`.

Dataset generation is the stage that costs hours, and every chain is
independent. Local runs can use several cores; cluster runs use a scheduler
array with one job per simulated chain and start training only after the whole
array succeeds. The result does not depend on execution order. See
[Making generation faster](https://github.com/GretaLupi/hamlet-toolkit/blob/main/docs/user-guide.md#making-generation-faster),
which also covers why a GPU makes this stage *slower*.

## Installation options

The base installation includes the interface, experimental I/O, plotting,
ridge and random-forest models, and the published reference-model catalog —
all three model artifacts ship in the package, though loading the Keras one
needs `[ml]`.

```bash
python -m pip install "hamlet-toolkit[ml]"          # Keras MLP and CNN
python -m pip install "hamlet-toolkit[simulation]"  # DMRGPy generation
python -m pip install "hamlet-toolkit[tune]"        # Optuna search
python -m pip install "hamlet-toolkit[all]"         # all optional features
python -m pip install "hamlet-toolkit[gpu]"         # CUDA TensorFlow, Linux only
```

`[gpu]` is not part of `[all]`, and is worth reading about before installing:
the CUDA wheels are several gigabytes, only the Keras models can use a card,
and dataset generation — the long stage — is CPU-bound and gains nothing from
one. `hamlet compute` reports what this machine will actually use for each
stage, and why. See [Using a GPU](https://github.com/GretaLupi/hamlet-toolkit/blob/main/docs/user-guide.md#using-a-gpu).

For development from a clone:

```bash
python -m pip install -e ".[dev,ml,simulation,tune]"
pytest
```

## Supported workflows

| Workflow | Model view | Current status |
| --- | --- | --- |
| Bond-inhomogeneous Heisenberg | three-site local windows; variable chain length | validated workflow; published Keras ensemble |
| Homogeneous Heisenberg `J1-J2` | complete chain; exactly L=8 | published random-forest reference model; simulation-validated |
| XXZ `J1-J2-J3` with impurity-assisted DMI | complete chain; exactly L=8 | published ridge reference model; experimental-design workflow |

Global models are chain-length specific. Local sliding-window models can be
applied to other lengths when the stored model contract is otherwise
compatible. HamLeT reports a mismatch instead of padding spectra or silently
changing the cutoff.

Each shipped artifact has a model card under
[`src/hamlet/resources/models`](https://github.com/GretaLupi/hamlet-toolkit/tree/main/src/hamlet/resources/models) documenting its
training distribution, expected observable, accuracy, and limitations.

The pretrained bond-inhomogeneous model is the model developed for:

> G. Lupi, S. Ravuri, C. Zhao, W. Zhang, C. Roncaglia, R. Liu, X. Feng,
> D. Passerone, P. Ruffieux, R. Fasel, J. L. Lado and G. Catarina, *Learning
> Inhomogeneous Heisenberg Hamiltonians in Nanographene Spin Chains*, (2026),
> [arXiv:2606.29281](https://arxiv.org/abs/2606.29281).

Please cite that work when using this model. Its
[model card](https://github.com/GretaLupi/hamlet-toolkit/blob/main/src/hamlet/resources/models/inhomogeneous_heisenberg_l12_keras_mlp_standard_v1/MODEL_CARD.md)
contains the full author list, BibTeX entry, training provenance, and validity
range.

### Work this package builds on

The uniform spin-chain Hamiltonians and the impurity-tomography route to
parameters that are otherwise hidden come from:

> G. Lupi and J. L. Lado, *Hamiltonian-learning quantum magnets with nonlocal
> impurity tomography*, [Phys. Rev. Applied **23**, 054077
> (2025)](https://doi.org/10.1103/PhysRevApplied.23.054077).

> N. Karjalainen, G. Lupi, R. Koch, A. O. Fumega and J. L. Lado, *Hamiltonian
> learning quantum magnets with dynamical impurity tomography*, [Phys. Rev.
> Research **8**, 033281 (2026)](https://doi.org/10.1103/cw27-2qqd).

**The models trained for those papers are not distributed with this package.**
HamLeT implements the same families of Hamiltonians and the same measurement
logic, so you can generate a dataset and train an equivalent model yourself,
but any pretrained artifact shipped here is listed under
[`src/hamlet/resources/models`](https://github.com/GretaLupi/hamlet-toolkit/tree/main/src/hamlet/resources/models) and is not one of
theirs. Please cite these papers if you use the impurity route or the uniform
chain families; the estimators you train are your own.

## Command line

The same workflow can be scripted with YAML configurations:

```bash
hamlet modes
hamlet inspect-experiment path/to/measurement.csv
hamlet run examples/quickstart_l8.yaml --dry-run
hamlet run examples/quickstart_l8.yaml
```

See the [user guide](https://github.com/GretaLupi/hamlet-toolkit/blob/main/docs/user-guide.md) for raw-file import, cutoff selection,
dataset generation, model tuning, cluster execution, inference, and reports,
and [the theory notes](https://github.com/GretaLupi/hamlet-toolkit/blob/main/docs/theory.md) for the Hamiltonians, the measurement
model, and what the reported scores mean.
The small [L=8 notebook](https://github.com/GretaLupi/hamlet-toolkit/blob/main/notebooks/04_l8_three_mode_workflow.ipynb) is the
reproducible Python example; notebooks are tutorials, not the test suite.

## Scientific scope

The [theory notes](https://github.com/GretaLupi/hamlet-toolkit/blob/main/docs/theory.md) state the Hamiltonians, the correlator and
dI/dV relation, the metric definitions, and the assumptions behind all of them.

Reference-model scores describe held-out simulated data unless a model card
explicitly says otherwise. Ensemble spread measures disagreement between
trained members; it is not a calibrated confidence interval. A measurement
must satisfy the artifact contract before its predictions are physically
interpretable.

Uniform z-directed DMI cannot be identified from the supported on-site
autocorrelator in a symmetry-preserving chain. HamLeT therefore exposes the
impurity-assisted design route instead of offering a misleading ordinary DMI
model. See the [DMI experiment specification](https://github.com/GretaLupi/hamlet-toolkit/blob/main/docs/dmi-experiment-spec.md).

## Project information

- Theory and assumptions: [docs/theory.md](https://github.com/GretaLupi/hamlet-toolkit/blob/main/docs/theory.md)
- Changes: [CHANGELOG.md](https://github.com/GretaLupi/hamlet-toolkit/blob/main/CHANGELOG.md)
- Contributing: [CONTRIBUTING.md](https://github.com/GretaLupi/hamlet-toolkit/blob/main/CONTRIBUTING.md)
- Releasing: [docs/releasing.md](https://github.com/GretaLupi/hamlet-toolkit/blob/main/docs/releasing.md)
- Security reports: [SECURITY.md](https://github.com/GretaLupi/hamlet-toolkit/blob/main/SECURITY.md)
- Citation metadata: [CITATION.cff](https://github.com/GretaLupi/hamlet-toolkit/blob/main/CITATION.cff)

HamLeT is distributed under the [GNU General Public License v3.0 or
later](https://github.com/GretaLupi/hamlet-toolkit/blob/main/LICENSE).
