Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 19 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ infrastructure, splits, logging, versioning) stays yours.

**1. Raw events.** Any PyTorch `Dataset` yielding
`raw[i] -> {"event_no": int, "pulses": [P, F] float32, "sensor_key": [P] int}`
(stated canonically in `spine/data/datamodule.py`). Pulses stay raw: the
sampler builds its cutoffs and dt targets in detector units, and
standardization happens later at collate. Columns follow the task's
(stated canonically in `spine/data/datamodule.py`). Pulses stay raw: pretext
tasks make their sampling decisions and build their targets in detector
units, and standardization happens later at collate. Columns follow the task's
`FeatureLayout`, by default `(x, y, z, t, charge)`; pass a different layout
instead of reordering your data. `sensor_key` is a unique integer identity
per sensor carried in the data itself; single PMT detectors can use any
Expand All @@ -46,22 +46,24 @@ stable per sensor id. Reference readers:
`SQLiteDataset` / `LMDBDataset` adapted via
`spine_graphnet.readers.GraphNetRawDataset` (see `examples/graphnet_demo.py`).

**2. A geometry asset.** An `.npz` with per sensor arrays: `xyz [S, 3]` in
the same units as the pulse coordinates, `knn_idx [S, K]` neighbours sorted
by distance (the sampler walks it to the nearest dark sensor, so K must be
large enough that one is always found; the full sorted list is safest), and
one unique integer key array whose name you pass to
`load_geometry(path, sensor_key=...)`. The reader's `sensor_key` values must
resolve through exactly these keys; coordinate matching is deliberately not
supported. `build_geometry_asset` in `examples/graphnet_demo.py` shows a
build from a pulse file.
**2. A geometry asset.** An `.npz` with per sensor arrays: always
`xyz [S, 3]` in the same units as the pulse coordinates, and one unique
integer key array whose name you pass to `load_geometry(path, sensor_key=...)`.
A task can require more; CURTAIN for example needs `knn_idx [S, K]`,
neighbours sorted by distance, to anchor its negatives at the nearest dark
sensor (K large enough that one is always found; the full sorted list is
safest). The reader's `sensor_key` values must resolve through exactly these
keys; coordinate matching is deliberately not supported.
`build_geometry_asset` in `examples/graphnet_demo.py` shows a build from a
pulse file.

**3. Selections.** SPINE owns no split: `fit` takes separate train and val
Datasets and you keep them disjoint. Every selected event must be guaranteed
splittable: pre filter with `spine.pretext.curtain.sampler.can_always_split`
using the same `min_visible`/`min_future` you give the task, and float32
times. `make_sample` raises on events that slip through rather than skipping
them silently.
Datasets and you keep them disjoint. Every selected event must satisfy the
task's sampling requirements; tasks raise on events that fall short instead
of skipping them silently, so pre filter your selection with the task's own
predicate. For CURTAIN that is
`spine.pretext.curtain.sampler.can_always_split`, called with the same
`min_visible`/`min_future` you give the task and float32 times.

**4. Feature scaling.** A `FeatureScaler` subclass (`scale_pulses` and
`scale_positions`, both applying the same xyz factors) for your detector, or
Expand Down
Loading