heptokens 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- heptokens-0.1.0/.gitattributes +2 -0
- heptokens-0.1.0/.github/workflows/cd.yml +36 -0
- heptokens-0.1.0/.gitignore +35 -0
- heptokens-0.1.0/.pre-commit-config.yaml +17 -0
- heptokens-0.1.0/PKG-INFO +446 -0
- heptokens-0.1.0/README.md +429 -0
- heptokens-0.1.0/pixi.lock +4612 -0
- heptokens-0.1.0/profiles/local/config.yaml +6 -0
- heptokens-0.1.0/profiles/s3df/config.yaml +15 -0
- heptokens-0.1.0/pyproject.toml +80 -0
- heptokens-0.1.0/src/heptokens/__init__.py +0 -0
- heptokens-0.1.0/src/heptokens/callbacks/__init__.py +0 -0
- heptokens-0.1.0/src/heptokens/callbacks/finetuning.py +89 -0
- heptokens-0.1.0/src/heptokens/callbacks/monitor.py +88 -0
- heptokens-0.1.0/src/heptokens/callbacks/recon.py +91 -0
- heptokens-0.1.0/src/heptokens/conf/__init__.py +0 -0
- heptokens-0.1.0/src/heptokens/conf/callbacks/classify.yaml +33 -0
- heptokens-0.1.0/src/heptokens/conf/callbacks/encode.yaml +42 -0
- heptokens-0.1.0/src/heptokens/conf/callbacks/finetune.yaml +20 -0
- heptokens-0.1.0/src/heptokens/conf/callbacks/new_modality_encode.yaml +37 -0
- heptokens-0.1.0/src/heptokens/conf/callbacks/pretrain.yaml +24 -0
- heptokens-0.1.0/src/heptokens/conf/fit_preprocessors.yaml +20 -0
- heptokens-0.1.0/src/heptokens/conf/hydra/default.yaml +16 -0
- heptokens-0.1.0/src/heptokens/conf/model/classifier.yaml +12 -0
- heptokens-0.1.0/src/heptokens/conf/model/diffusion_vqvae.yaml +40 -0
- heptokens-0.1.0/src/heptokens/conf/model/feature_classifier.yaml +19 -0
- heptokens-0.1.0/src/heptokens/conf/model/new_modality_vqvae.yaml +24 -0
- heptokens-0.1.0/src/heptokens/conf/model/set2vec_vqvae.yaml +40 -0
- heptokens-0.1.0/src/heptokens/conf/model/token_classifier.yaml +23 -0
- heptokens-0.1.0/src/heptokens/conf/model/transformer_vqvae.yaml +40 -0
- heptokens-0.1.0/src/heptokens/conf/model/vector_classifier.yaml +21 -0
- heptokens-0.1.0/src/heptokens/conf/model/vqvae.yaml +30 -0
- heptokens-0.1.0/src/heptokens/conf/tokenize.yaml +20 -0
- heptokens-0.1.0/src/heptokens/conf/train.yaml +46 -0
- heptokens-0.1.0/src/heptokens/data/__init__.py +0 -0
- heptokens-0.1.0/src/heptokens/data/base.py +95 -0
- heptokens-0.1.0/src/heptokens/data/collation.py +185 -0
- heptokens-0.1.0/src/heptokens/data/flat_array.py +153 -0
- heptokens-0.1.0/src/heptokens/data/structured_array.py +519 -0
- heptokens-0.1.0/src/heptokens/data/transforms.py +221 -0
- heptokens-0.1.0/src/heptokens/export_tokens.py +245 -0
- heptokens-0.1.0/src/heptokens/fit_preprocessors.py +141 -0
- heptokens-0.1.0/src/heptokens/models/__init__.py +0 -0
- heptokens-0.1.0/src/heptokens/models/classifier.py +95 -0
- heptokens-0.1.0/src/heptokens/models/coders.py +382 -0
- heptokens-0.1.0/src/heptokens/models/new_modality_coders.py +134 -0
- heptokens-0.1.0/src/heptokens/models/optimisers.py +213 -0
- heptokens-0.1.0/src/heptokens/models/token_classifier.py +573 -0
- heptokens-0.1.0/src/heptokens/models/transformer.py +217 -0
- heptokens-0.1.0/src/heptokens/models/utils.py +185 -0
- heptokens-0.1.0/src/heptokens/models/vq_vae.py +243 -0
- heptokens-0.1.0/src/heptokens/train.py +103 -0
- heptokens-0.1.0/src/heptokens/utils/__init__.py +0 -0
- heptokens-0.1.0/src/heptokens/utils/hydra.py +201 -0
- heptokens-0.1.0/src/heptokens/utils/lightning.py +163 -0
- heptokens-0.1.0/src/heptokens/utils/schedulers.py +113 -0
- heptokens-0.1.0/src/heptokens/utils/torch_utils.py +519 -0
- heptokens-0.1.0/tests/conftest.py +37 -0
- heptokens-0.1.0/tests/test_configs.py +62 -0
- heptokens-0.1.0/tests/test_export_pos_tokens.py +128 -0
- heptokens-0.1.0/tests/test_integration.py +151 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: CD
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
pull_request:
|
|
6
|
+
push:
|
|
7
|
+
branches: [main]
|
|
8
|
+
release:
|
|
9
|
+
types: [published]
|
|
10
|
+
jobs:
|
|
11
|
+
dist:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v7
|
|
15
|
+
with:
|
|
16
|
+
fetch-depth: 0
|
|
17
|
+
- uses: hynek/build-and-inspect-python-package@v3.0.1
|
|
18
|
+
publish:
|
|
19
|
+
needs: [dist]
|
|
20
|
+
environment: pypi
|
|
21
|
+
permissions:
|
|
22
|
+
id-token: write
|
|
23
|
+
attestations: write
|
|
24
|
+
contents: read
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
if: github.event_name == 'release' && github.event.action == 'published'
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/download-artifact@v8
|
|
29
|
+
with:
|
|
30
|
+
name: Packages
|
|
31
|
+
path: dist
|
|
32
|
+
- name: Generate artifact attestation for sdist and wheel
|
|
33
|
+
uses: actions/attest@v4
|
|
34
|
+
with:
|
|
35
|
+
subject-path: dist/*
|
|
36
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# pixi environments
|
|
2
|
+
.pixi/*
|
|
3
|
+
!.pixi/config.toml
|
|
4
|
+
|
|
5
|
+
# Snakemake files
|
|
6
|
+
.snakemake/
|
|
7
|
+
|
|
8
|
+
# Python cache files
|
|
9
|
+
__pycache__/
|
|
10
|
+
*.py[cod]
|
|
11
|
+
*$py.class
|
|
12
|
+
# Distribution / packaging
|
|
13
|
+
.Python
|
|
14
|
+
build/
|
|
15
|
+
develop-eggs/
|
|
16
|
+
dist/
|
|
17
|
+
downloads/
|
|
18
|
+
eggs/
|
|
19
|
+
.eggs/
|
|
20
|
+
lib/
|
|
21
|
+
lib64/
|
|
22
|
+
parts/
|
|
23
|
+
sdist/
|
|
24
|
+
var/
|
|
25
|
+
wheels/
|
|
26
|
+
pip-wheel-metadata/
|
|
27
|
+
share/python-wheels/
|
|
28
|
+
*.egg-info/
|
|
29
|
+
|
|
30
|
+
# VsCode settings
|
|
31
|
+
.vscode/
|
|
32
|
+
|
|
33
|
+
# Plots and other results
|
|
34
|
+
plot/
|
|
35
|
+
results/
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
repos:
|
|
3
|
+
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
|
4
|
+
rev: v0.11.13
|
|
5
|
+
hooks:
|
|
6
|
+
- id: ruff
|
|
7
|
+
args: [--fix, --show-fixes, --exit-non-zero-on-fix]
|
|
8
|
+
- id: ruff-format
|
|
9
|
+
- repo: https://github.com/lyz-code/yamlfix
|
|
10
|
+
rev: 1.16.1
|
|
11
|
+
hooks:
|
|
12
|
+
- id: yamlfix
|
|
13
|
+
- repo: https://github.com/adrienverge/yamllint.git
|
|
14
|
+
rev: v1.37.1
|
|
15
|
+
hooks:
|
|
16
|
+
- id: yamllint
|
|
17
|
+
args: [-d, '{extends: relaxed, rules: {line-length: disable}}']
|
heptokens-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: heptokens
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Author: Samuel Klein, Jeffrey Krupa, Michael Kagan
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Requires-Dist: awkward>=2.8
|
|
7
|
+
Requires-Dist: h5py>=3.13
|
|
8
|
+
Requires-Dist: hydra-core>=1.3
|
|
9
|
+
Requires-Dist: lightning>=2.5
|
|
10
|
+
Requires-Dist: omegaconf>=2.3
|
|
11
|
+
Requires-Dist: rich>=14
|
|
12
|
+
Requires-Dist: scikit-learn>=1.3
|
|
13
|
+
Requires-Dist: torch>=2.4
|
|
14
|
+
Requires-Dist: uproot>=5.7
|
|
15
|
+
Requires-Dist: vector-quantize-pytorch
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
# heptokens
|
|
19
|
+
|
|
20
|
+
[](https://pytorch.org/)
|
|
21
|
+
[](https://lightning.ai/)
|
|
22
|
+
[](https://hydra.cc/)
|
|
23
|
+
[](https://wandb.ai)
|
|
24
|
+
[](https://pixi.sh)
|
|
25
|
+
|
|
26
|
+
Tokenize HEP physics objects (jets, tracks, calorimeter clusters, …) with residual VQ-VAEs.
|
|
27
|
+
|
|
28
|
+
`heptokens` is an installable Python library. It ships:
|
|
29
|
+
- **Data classes** — generic HDF5 datasets and Lightning DataModules for structured (object + constituent) and flat (dense, maskless) data.
|
|
30
|
+
- **VQ-VAE model** — `LitVqVae` wrapping `ResidualVQ` with pluggable encoder/decoder.
|
|
31
|
+
- **CLI entry points** — `heptokens-fit-preprocessors`, `heptokens-train`, and `heptokens-export` for Hydra-configured preprocessing, training, and tokenization runs.
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
### 1. Install
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
pip install heptokens
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Or, for development with a [Pixi](https://pixi.sh/latest/installation/)-managed environment:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
git clone <repo>
|
|
45
|
+
cd heptokens
|
|
46
|
+
pixi shell # activates the environment
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### 2. Write your datamodule config
|
|
50
|
+
|
|
51
|
+
Create a YAML file describing your data. This is the only config you must supply — the library bundles everything else (model, callbacks, trainer).
|
|
52
|
+
|
|
53
|
+
```yaml
|
|
54
|
+
# my_configs/datamodule/my_jets.yaml
|
|
55
|
+
_target_: heptokens.data.structured_array.StructuredArrayModule
|
|
56
|
+
data_path: /path/to/data.h5
|
|
57
|
+
obj_group: jets
|
|
58
|
+
set_group: tracks
|
|
59
|
+
obj_features: [pt, eta, phi]
|
|
60
|
+
set_features: [pt, deta, dphi, d0, z0]
|
|
61
|
+
label_key: HadronConeExclTruthLabelID
|
|
62
|
+
mask_key: valid
|
|
63
|
+
train_frac: 0.7
|
|
64
|
+
val_frac: 0.15
|
|
65
|
+
test_frac: 0.15
|
|
66
|
+
batch_size: 1024
|
|
67
|
+
num_workers: 4
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Your HDF5 must have this layout (see `StructuredArrayHDF5Dataset` for full docs):
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
<obj_group>/
|
|
74
|
+
<feature>: float [N]
|
|
75
|
+
<label_key>: int [N]
|
|
76
|
+
<set_group>/
|
|
77
|
+
<feature>: float [N, max_elements]
|
|
78
|
+
<mask_key>: bool [N, max_elements]
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### 3. Fit preprocessors
|
|
82
|
+
|
|
83
|
+
The VQ-VAE expects normalised inputs. Use the `heptokens-fit-preprocessors` CLI to fit sklearn scalers on your training data and save them as joblib files:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
heptokens-fit-preprocessors -cd /path/to/my_configs \
|
|
87
|
+
datamodule=my_jets \
|
|
88
|
+
output_dir=resources
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Dataset-specific options (which modes to fit, which features to log-scale, etc.) live in a `preprocessing:` block inside your datamodule config so they don't need to be repeated on every invocation:
|
|
92
|
+
|
|
93
|
+
```yaml
|
|
94
|
+
# my_configs/datamodule/my_jets.yaml
|
|
95
|
+
_target_: heptokens.data.structured_array.StructuredArrayModule
|
|
96
|
+
set_features: [pt, deta, dphi, d0, z0]
|
|
97
|
+
...
|
|
98
|
+
preprocessing:
|
|
99
|
+
cst_modes: [quantile, log_quantile]
|
|
100
|
+
cst_log_feature_indices: [pt] # resolved via set_features — no separate feature list needed
|
|
101
|
+
fit_jets: true
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Then just run:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
heptokens-fit-preprocessors -cd /path/to/my_configs \
|
|
108
|
+
datamodule=my_jets \
|
|
109
|
+
output_dir=resources
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Individual keys can still be overridden on the CLI with `datamodule.preprocessing.<key>=...`:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
heptokens-fit-preprocessors -cd /path/to/my_configs \
|
|
116
|
+
datamodule=my_jets \
|
|
117
|
+
datamodule.preprocessing.cst_modes=[quantile,log_quantile]
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
This saves `resources/cst_<mode>.joblib` (and `resources/jet_<mode>.joblib` when `fit_jets=true`) and writes `resources/preprocessor_config.yaml` with the file paths. Then add them to your datamodule config:
|
|
121
|
+
|
|
122
|
+
```yaml
|
|
123
|
+
# append to my_configs/datamodule/my_jets.yaml
|
|
124
|
+
transforms:
|
|
125
|
+
preprocess:
|
|
126
|
+
_target_: heptokens.data.collation.preprocess_batch
|
|
127
|
+
_partial_: true
|
|
128
|
+
cst_fn:
|
|
129
|
+
_target_: joblib.load
|
|
130
|
+
filename: resources/cst_quantiles.joblib
|
|
131
|
+
jet_fn:
|
|
132
|
+
_target_: joblib.load
|
|
133
|
+
filename: resources/jet_quantiles.joblib
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
See [Preprocessing](#preprocessing) for available modes and details.
|
|
137
|
+
|
|
138
|
+
### 4. Train
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
heptokens-train -cd /path/to/my_configs \
|
|
142
|
+
datamodule=my_jets \
|
|
143
|
+
project_name=my_project \
|
|
144
|
+
network_name=run_01 \
|
|
145
|
+
output_dir=results
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### 5. Export tokens
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
heptokens-export -cd /path/to/my_configs \
|
|
152
|
+
datamodule=my_jets \
|
|
153
|
+
ckpt_path=results/my_project/run_01/checkpoints/last.ckpt \
|
|
154
|
+
output_dir=results/tokens
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Output is an `.npz` with `indices [N, n_csts, num_quantizers]`, `labels [N]`, and `codebooks [Q, K, D]`.
|
|
158
|
+
|
|
159
|
+
### Python API
|
|
160
|
+
|
|
161
|
+
For scripting or notebooks without Hydra:
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
from heptokens.data.structured_array import StructuredArrayHDF5Dataset
|
|
165
|
+
from heptokens.models.vq_vae import LitVqVae
|
|
166
|
+
from heptokens.models.coders import Encoder, Decoder
|
|
167
|
+
import lightning as L
|
|
168
|
+
from torch.utils.data import DataLoader
|
|
169
|
+
|
|
170
|
+
ds = StructuredArrayHDF5Dataset(
|
|
171
|
+
"data.h5",
|
|
172
|
+
obj_group="jets", set_group="tracks",
|
|
173
|
+
obj_features=["pt", "eta", "phi"],
|
|
174
|
+
set_features=["pt", "eta", "phi"],
|
|
175
|
+
mask_key="valid", label_key=None,
|
|
176
|
+
)
|
|
177
|
+
loader = DataLoader(ds, batch_size=256, shuffle=True)
|
|
178
|
+
|
|
179
|
+
sample = next(iter(loader))["csts"] # [B, N, 3]
|
|
180
|
+
model = LitVqVae(
|
|
181
|
+
encoder=Encoder, decoder=Decoder,
|
|
182
|
+
codebook_size=512, codebook_dim=64, num_quantizers=4,
|
|
183
|
+
data_sample=sample,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
trainer = L.Trainer(max_epochs=10, logger=False)
|
|
187
|
+
trainer.fit(model, loader)
|
|
188
|
+
|
|
189
|
+
batch = next(iter(loader))
|
|
190
|
+
z_q, indices, _ = model.encode(batch) # indices: [B, N, num_quantizers]
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## CLI Reference
|
|
194
|
+
|
|
195
|
+
All three commands are Hydra-based. Use `-cd` to point at your experiment's config directory containing the `datamodule/` folder. All other configs (model, callbacks, trainer) are bundled.
|
|
196
|
+
|
|
197
|
+
### Full workflow
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
# 1. Fit scalers on training data
|
|
201
|
+
heptokens-fit-preprocessors -cd /path/to/my_configs \
|
|
202
|
+
datamodule=my_jets \
|
|
203
|
+
output_dir=resources
|
|
204
|
+
|
|
205
|
+
# 2. Wire the saved joblib paths into your datamodule config
|
|
206
|
+
# (see resources/preprocessor_config.yaml for the generated snippet)
|
|
207
|
+
|
|
208
|
+
# 3. Train the VQ-VAE
|
|
209
|
+
heptokens-train -cd /path/to/my_configs \
|
|
210
|
+
datamodule=my_jets \
|
|
211
|
+
project_name=my_project \
|
|
212
|
+
network_name=run_01 \
|
|
213
|
+
output_dir=results
|
|
214
|
+
|
|
215
|
+
# 4. Export tokens from a trained checkpoint
|
|
216
|
+
heptokens-export -cd /path/to/my_configs \
|
|
217
|
+
datamodule=my_jets \
|
|
218
|
+
ckpt_path=results/my_project/run_01/checkpoints/last.ckpt \
|
|
219
|
+
output_dir=results/tokens
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
```bash
|
|
223
|
+
# Without installing (pixi environment):
|
|
224
|
+
pixi run python -m heptokens.fit_preprocessors -cd /path/to/my/configs datamodule=my_jets ...
|
|
225
|
+
pixi run python -m heptokens.train -cd /path/to/my/configs datamodule=my_jets ...
|
|
226
|
+
pixi run python -m heptokens.export_tokens -cd /path/to/my/configs datamodule=my_jets ...
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Bundled configs — `heptokens-train` / `heptokens-export`
|
|
230
|
+
|
|
231
|
+
| Group | Location | Description |
|
|
232
|
+
|---|---|---|
|
|
233
|
+
| `model` | `src/heptokens/conf/model/` | `vqvae`, `transformer_vqvae`, `classifier`, … |
|
|
234
|
+
| `callbacks` | `src/heptokens/conf/callbacks/` | `pretrain`, `encode`, `classify`, … |
|
|
235
|
+
|
|
236
|
+
`datamodule` is not bundled — it is experiment-specific. See `StructuredArrayModule` in `src/heptokens/data/structured_array.py` for the constructor args.
|
|
237
|
+
|
|
238
|
+
### Bundled configs — `heptokens-fit-preprocessors`
|
|
239
|
+
|
|
240
|
+
The command ships `src/heptokens/conf/fit_preprocessors.yaml` with these key options:
|
|
241
|
+
|
|
242
|
+
Top-level keys (set on the CLI or in your own `fit_preprocessors.yaml`):
|
|
243
|
+
|
|
244
|
+
| Key | Default | Description |
|
|
245
|
+
|---|---|---|
|
|
246
|
+
| `output_dir` | `resources` | Directory to write joblib files and the config snippet |
|
|
247
|
+
| `max_batches` | — | Limit training batches used for fitting (null = full dataset) |
|
|
248
|
+
|
|
249
|
+
`preprocessing:` block keys (set inside your datamodule config, or via `datamodule.preprocessing.<key>=...` on the CLI):
|
|
250
|
+
|
|
251
|
+
| Key | Default | Description |
|
|
252
|
+
|---|---|---|
|
|
253
|
+
| `cst_modes` | `[quantile, standard]` | Scaler modes to fit for constituents |
|
|
254
|
+
| `jet_modes` | `[quantile, standard]` | Scaler modes to fit for jet-level features |
|
|
255
|
+
| `fit_jets` | `false` | Set `true` to also fit jet-level scalers |
|
|
256
|
+
| `cst_log_feature_indices` | — | Features to log-scale before the main transform (names resolved via `set_features`, or indices) |
|
|
257
|
+
| `jet_log_feature_indices` | — | Same for jet features (names resolved via `obj_features`) |
|
|
258
|
+
| `n_quantiles` | `500` | Number of quantiles for `QuantileTransformer` |
|
|
259
|
+
| `log_offset` | `1.0` | Offset in `log(x + offset)` |
|
|
260
|
+
|
|
261
|
+
### Output layout
|
|
262
|
+
|
|
263
|
+
```
|
|
264
|
+
<output_dir>/<project_name>/<network_name>/
|
|
265
|
+
checkpoints/
|
|
266
|
+
full_config.yaml # saved for reproducibility / resume
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Resuming a run
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
heptokens-train -cd /path/to/my/configs \
|
|
273
|
+
full_resume=true ckpt_flag=last.ckpt \
|
|
274
|
+
output_dir=... project_name=... network_name=...
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
Or from an explicit checkpoint path:
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
heptokens-train -cd /path/to/my/configs \
|
|
281
|
+
full_resume=false ckpt_path=/abs/path/to/last.ckpt \
|
|
282
|
+
datamodule=my_atlas output_dir=... project_name=... network_name=...
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
## Repository Layout
|
|
286
|
+
|
|
287
|
+
```
|
|
288
|
+
src/heptokens/
|
|
289
|
+
data/
|
|
290
|
+
structured_array.py # StructuredArrayHDF5Dataset / StructuredArrayModule
|
|
291
|
+
flat_array.py # FlatArrayHDF5Dataset / FlatArrayModule (dense, no mask)
|
|
292
|
+
base.py # BaseMapModule (shared DataLoader logic)
|
|
293
|
+
collation.py, transforms.py
|
|
294
|
+
models/
|
|
295
|
+
vq_vae.py # LitVqVae
|
|
296
|
+
coders.py # Encoder, Decoder (base classes + default MLP impl)
|
|
297
|
+
new_modality_coders.py # template for custom encoders/decoders
|
|
298
|
+
classifier.py, transformer.py, …
|
|
299
|
+
conf/ # bundled Hydra configs (model, callbacks)
|
|
300
|
+
callbacks/ # Lightning callbacks
|
|
301
|
+
utils/
|
|
302
|
+
train.py # heptokens-train entry point
|
|
303
|
+
export_tokens.py # heptokens-export entry point
|
|
304
|
+
fit_preprocessors.py # heptokens-fit-preprocessors entry point
|
|
305
|
+
tests/
|
|
306
|
+
profiles/ # Slurm executor profiles for pixi tasks
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## Adding a New Modality
|
|
310
|
+
|
|
311
|
+
A modality is any input representation with its own data format, token definition, and reconstruction metric. The VQ-VAE core (`LitVqVae`, `ResidualVQ`) is modality-agnostic and never changes.
|
|
312
|
+
|
|
313
|
+
### Token strategy
|
|
314
|
+
|
|
315
|
+
| Data type | Token strategy |
|
|
316
|
+
|---|---|
|
|
317
|
+
| Sparse set (tracks, clusters, PFOs) | One token per object. Boolean validity mask for variable-length padding. |
|
|
318
|
+
| Dense grid (η-φ image, calorimeter towers) | Fixed-size patching in `__getitem__`. Each patch is one token. No mask needed if all patches are always valid. |
|
|
319
|
+
|
|
320
|
+
### Checklist
|
|
321
|
+
|
|
322
|
+
**1. Dataset / DataModule** — `src/heptokens/data/<modality>.py`
|
|
323
|
+
|
|
324
|
+
See `StructuredArrayModule` or `FlatArrayModule` for reference implementations.
|
|
325
|
+
- `MyDataset.__getitem__` returns a dict: constituent tensor + optional bool mask.
|
|
326
|
+
- `MyDataModule` extends `BaseMapModule`; implement `setup()` and `get_data_sample()`.
|
|
327
|
+
|
|
328
|
+
**2. Encoder / Decoder** — `src/heptokens/models/<modality>_coders.py`
|
|
329
|
+
|
|
330
|
+
Start from `src/heptokens/models/new_modality_coders.py`.
|
|
331
|
+
- Extend `Encoder` and `Decoder` from `heptokens.models.coders`.
|
|
332
|
+
- `Encoder.forward(batch)` → `[B, N, codebook_dim]`, masked positions zeroed.
|
|
333
|
+
- `Decoder.compute_loss(z_q, batch)` → scalar loss.
|
|
334
|
+
- Set `self.input_key` and `self.mask_key` to match your dataset's output keys.
|
|
335
|
+
|
|
336
|
+
**3. Model config** — `src/heptokens/conf/model/<modality>_vqvae.yaml`
|
|
337
|
+
|
|
338
|
+
Start from `src/heptokens/conf/model/new_modality_vqvae.yaml`.
|
|
339
|
+
Point `encoder._target_` and `decoder._target_` at your new classes.
|
|
340
|
+
|
|
341
|
+
**4. Datamodule config** — in your experiment repo's config directory
|
|
342
|
+
|
|
343
|
+
```yaml
|
|
344
|
+
# my_configs/datamodule/my_modality.yaml
|
|
345
|
+
_target_: heptokens.data.<modality>.MyDataModule
|
|
346
|
+
data_path: /path/to/data.h5
|
|
347
|
+
batch_size: 512
|
|
348
|
+
num_workers: 4
|
|
349
|
+
# ... your fields
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
**5. Callbacks config** *(optional)* — `src/heptokens/conf/callbacks/<modality>_encode.yaml`
|
|
353
|
+
|
|
354
|
+
For physical-space reconstruction metrics, subclass `BaseReconstructionMonitor`:
|
|
355
|
+
|
|
356
|
+
```python
|
|
357
|
+
from heptokens.callbacks.recon import BaseReconstructionMonitor
|
|
358
|
+
|
|
359
|
+
class MyMonitor(BaseReconstructionMonitor):
|
|
360
|
+
def __init__(self, inverse_fn, **kwargs):
|
|
361
|
+
super().__init__(input_key="my_key", mask_key=None, **kwargs)
|
|
362
|
+
self.inverse_fn = inverse_fn
|
|
363
|
+
|
|
364
|
+
def compute_and_log_metrics(self, trainer, pl_module, batch, batch_idx):
|
|
365
|
+
import torch as T
|
|
366
|
+
with T.no_grad():
|
|
367
|
+
z_q = pl_module.encode(batch)[0]
|
|
368
|
+
recon = pl_module.decode(z_q, batch)
|
|
369
|
+
orig = self.inverse_fn(batch["my_key"].cpu())
|
|
370
|
+
reco = self.inverse_fn(recon.cpu())
|
|
371
|
+
pl_module.log("val/my_mae_unscaled", T.mean(T.abs(orig - reco)))
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
**Train:**
|
|
375
|
+
|
|
376
|
+
```bash
|
|
377
|
+
heptokens-train -cd /path/to/my/configs \
|
|
378
|
+
model=<modality>_vqvae callbacks=<modality>_encode \
|
|
379
|
+
datamodule=<modality> trainer.max_epochs=30
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Common pitfalls
|
|
383
|
+
|
|
384
|
+
- **`input_key` mismatch**: The encoder reads `batch[self.input_key]`. Set it consistently in the dataset and encoder.
|
|
385
|
+
- **`n_classes` not needed for VQ-VAE**: Omit or set to `null` in your datamodule config.
|
|
386
|
+
- **Mask dtype**: The mask must be `bool`, shape `[B, N]`. Float/int masks will silently produce wrong results.
|
|
387
|
+
- **Dense grids**: Make sure `N` (number of patches) is fixed across samples so batches stack without a mask.
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
## Preprocessing
|
|
392
|
+
|
|
393
|
+
The VQ-VAE expects normalised inputs. The library provides sklearn-based scalers in `heptokens.data.transforms` and a batch-level application function in `heptokens.data.collation`. The workflow is: **fit offline → save as joblib → load in your Hydra config** (shown in [Quick Start step 3](#3-fit-preprocessors)).
|
|
394
|
+
|
|
395
|
+
### How it connects
|
|
396
|
+
|
|
397
|
+
`BaseMapModule` accepts a `transforms` kwarg. When set, it wraps the DataLoader's collate function so transforms run on every batch automatically — no manual intervention at train time.
|
|
398
|
+
|
|
399
|
+
### Available modes (`create_preprocessing_transformer`)
|
|
400
|
+
|
|
401
|
+
| Mode | Description |
|
|
402
|
+
|------|-------------|
|
|
403
|
+
| `"quantile"` | `QuantileTransformer` on all features |
|
|
404
|
+
| `"standard"` | `StandardScaler` on all features |
|
|
405
|
+
| `"log_quantile"` | Log-scale selected features, then quantile-transform all |
|
|
406
|
+
| `"log_standard"` | Log-scale selected features, then standard-scale all |
|
|
407
|
+
|
|
408
|
+
Parameters: `mode`, `log_feature_indices` (which features to log-scale), `n_quantiles`, `log_offset`.
|
|
409
|
+
|
|
410
|
+
### Inverse transforms
|
|
411
|
+
|
|
412
|
+
For evaluating reconstruction quality in physical units:
|
|
413
|
+
|
|
414
|
+
```python
|
|
415
|
+
from heptokens.data.collation import inverse_preprocess_batch
|
|
416
|
+
|
|
417
|
+
original = inverse_preprocess_batch(batch, cst_fn=cst_scaler, jet_fn=jet_scaler)
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
---
|
|
421
|
+
|
|
422
|
+
## Troubleshooting
|
|
423
|
+
|
|
424
|
+
### DataLoader workers exit unexpectedly
|
|
425
|
+
- Set `num_workers=0` to confirm worker issue.
|
|
426
|
+
- Set `pin_memory=False` if worker shutdown appears unstable.
|
|
427
|
+
|
|
428
|
+
### Training becomes slow
|
|
429
|
+
- Tune `num_workers`, `batch_size`, `pin_memory`.
|
|
430
|
+
- Avoid `reload_dataloaders_every_n_epochs=1` on iterable datasets unless necessary.
|
|
431
|
+
|
|
432
|
+
### W&B run lands under wrong account
|
|
433
|
+
- Override `logger.entity=<username_or_team>` when calling `heptokens-train`.
|
|
434
|
+
|
|
435
|
+
### Debugger uses wrong Python interpreter
|
|
436
|
+
- Use `.vscode/launch.json` with `"python": "${workspaceFolder}/.pixi/envs/default/bin/python"`.
|
|
437
|
+
|
|
438
|
+
---
|
|
439
|
+
|
|
440
|
+
## Resources
|
|
441
|
+
- [Pixi documentation](https://pixi.sh/)
|
|
442
|
+
- [Reproducible Machine Learning Workflows for Scientists, Matthew Feickert, 2025](https://carpentries-incubator.github.io/reproducible-ml-workflows/)
|
|
443
|
+
- [Good ML project structure](https://github.com/mattcleigh/JetSSL-Lite/tree/master)
|
|
444
|
+
|
|
445
|
+
## Contributors
|
|
446
|
+
Jeffrey Krupa, Samuel Klein, Michael Kagan
|