brainstem-nwb 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.
- brainstem_nwb-0.1.0/.gitignore +18 -0
- brainstem_nwb-0.1.0/CHANGELOG.md +99 -0
- brainstem_nwb-0.1.0/LICENSE +22 -0
- brainstem_nwb-0.1.0/PKG-INFO +158 -0
- brainstem_nwb-0.1.0/README.md +116 -0
- brainstem_nwb-0.1.0/docs/cli.md +115 -0
- brainstem_nwb-0.1.0/docs/design/architecture.md +51 -0
- brainstem_nwb-0.1.0/docs/design/decisions.md +92 -0
- brainstem_nwb-0.1.0/docs/design/export-schemas.md +104 -0
- brainstem_nwb-0.1.0/docs/design/ndx-brainstem.md +201 -0
- brainstem_nwb-0.1.0/docs/design/phase4-raw-data.md +89 -0
- brainstem_nwb-0.1.0/docs/extensions.md +131 -0
- brainstem_nwb-0.1.0/docs/index.md +12 -0
- brainstem_nwb-0.1.0/docs/install.md +65 -0
- brainstem_nwb-0.1.0/docs/manifest.md +69 -0
- brainstem_nwb-0.1.0/docs/mapping-spec.md +284 -0
- brainstem_nwb-0.1.0/docs/modalities.md +41 -0
- brainstem_nwb-0.1.0/docs/python-api.md +115 -0
- brainstem_nwb-0.1.0/docs/troubleshooting.md +61 -0
- brainstem_nwb-0.1.0/docs/validation.md +48 -0
- brainstem_nwb-0.1.0/docs/warnings.md +59 -0
- brainstem_nwb-0.1.0/examples/synthetic-ephys/README.md +57 -0
- brainstem_nwb-0.1.0/examples/synthetic-ephys/brainstem-export.json +1418 -0
- brainstem_nwb-0.1.0/examples/synthetic-ephys/brainstem-nwb.toml +9 -0
- brainstem_nwb-0.1.0/pyproject.toml +84 -0
- brainstem_nwb-0.1.0/schemas/manifest-1.0.0.schema.json +2355 -0
- brainstem_nwb-0.1.0/schemas/validation-report-1.0.0.schema.json +162 -0
- brainstem_nwb-0.1.0/scripts/generate_docs.py +26 -0
- brainstem_nwb-0.1.0/scripts/make_contract_export.py +229 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/__init__.py +34 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/_version.py +21 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/cli.py +308 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/config.py +109 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/errors.py +42 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/export.py +539 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/manifest/__init__.py +6 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/manifest/io.py +38 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/manifest/models.py +447 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/manifest/schema.py +33 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/manifest/warnings.py +180 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/mapping/__init__.py +0 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/mapping/acquisitions.py +98 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/mapping/context.py +111 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/mapping/describe.py +249 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/mapping/devices.py +344 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/mapping/docs.py +102 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/mapping/epochs.py +94 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/mapping/extension.py +330 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/mapping/herd.py +108 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/mapping/localization.py +116 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/mapping/manipulations.py +88 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/mapping/notes.py +175 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/mapping/pipeline.py +228 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/mapping/procedures.py +169 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/mapping/registry.py +281 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/mapping/session.py +203 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/mapping/subject.py +204 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/normalize/__init__.py +0 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/normalize/identifiers.py +60 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/normalize/kv.py +53 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/normalize/quantities.py +73 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/normalize/schemas.py +101 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/normalize/text.py +67 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/normalize/timeutil.py +110 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/normalize/units.py +630 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/nwb/__init__.py +0 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/nwb/canonical.py +94 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/nwb/writer.py +295 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/py.typed +0 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/raw/__init__.py +0 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/raw/base.py +49 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/raw/metadata.py +31 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/raw/paths.py +74 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/raw/registry.py +38 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/retrieval/__init__.py +0 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/retrieval/api.py +137 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/retrieval/loader.py +182 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/retrieval/schemas.py +52 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/store/__init__.py +0 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/store/datamodel.py +299 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/store/graph.py +180 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/store/inventory.py +95 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/validation/__init__.py +36 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/validation/checks.py +167 -0
- brainstem_nwb-0.1.0/src/brainstem_nwb/validation/report.py +82 -0
- brainstem_nwb-0.1.0/tests/__init__.py +0 -0
- brainstem_nwb-0.1.0/tests/conftest.py +74 -0
- brainstem_nwb-0.1.0/tests/fixtures/__init__.py +0 -0
- brainstem_nwb-0.1.0/tests/fixtures/builder.py +140 -0
- brainstem_nwb-0.1.0/tests/fixtures/exports/behavior.json +472 -0
- brainstem_nwb-0.1.0/tests/fixtures/exports/edge_cases.json +492 -0
- brainstem_nwb-0.1.0/tests/fixtures/exports/ephys.json +1418 -0
- brainstem_nwb-0.1.0/tests/fixtures/exports/exvivo_specimen.json +516 -0
- brainstem_nwb-0.1.0/tests/fixtures/exports/multisession.json +454 -0
- brainstem_nwb-0.1.0/tests/fixtures/exports/multisubject.json +555 -0
- brainstem_nwb-0.1.0/tests/fixtures/exports/optogenetics.json +758 -0
- brainstem_nwb-0.1.0/tests/fixtures/exports/server_contract_2_1.json +840 -0
- brainstem_nwb-0.1.0/tests/fixtures/exports/server_contract_2_1_session.json +858 -0
- brainstem_nwb-0.1.0/tests/fixtures/exports/session_export.json +396 -0
- brainstem_nwb-0.1.0/tests/fixtures/regen.py +39 -0
- brainstem_nwb-0.1.0/tests/fixtures/scenarios.py +358 -0
- brainstem_nwb-0.1.0/tests/integration/__init__.py +0 -0
- brainstem_nwb-0.1.0/tests/integration/test_modalities.py +49 -0
- brainstem_nwb-0.1.0/tests/test_cli_fetch.py +207 -0
- brainstem_nwb-0.1.0/tests/test_contract.py +96 -0
- brainstem_nwb-0.1.0/tests/test_datamodel.py +158 -0
- brainstem_nwb-0.1.0/tests/test_export.py +208 -0
- brainstem_nwb-0.1.0/tests/test_extension.py +221 -0
- brainstem_nwb-0.1.0/tests/test_loader_store.py +131 -0
- brainstem_nwb-0.1.0/tests/test_mapping.py +293 -0
- brainstem_nwb-0.1.0/tests/test_normalize.py +156 -0
- brainstem_nwb-0.1.0/tests/test_raw.py +57 -0
- brainstem_nwb-0.1.0/tests/test_spec.py +75 -0
- brainstem_nwb-0.1.0/tests/test_tool_alignment.py +34 -0
- brainstem_nwb-0.1.0/tests/test_units.py +139 -0
- brainstem_nwb-0.1.0/tests/test_writer_validation.py +120 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to brainstem-nwb are documented here. The project follows semantic versioning. The mapping version, which tracks changes to what is written to NWB files, is listed separately.
|
|
4
|
+
|
|
5
|
+
## 0.1.0 (2026-11-07)
|
|
6
|
+
|
|
7
|
+
### The BrainSTEM data model is read from the server (mapping version 1.3.0)
|
|
8
|
+
|
|
9
|
+
- brainstem-nwb no longer ships a copy of the BrainSTEM data model. It reads the record types, fields, links and type vocabularies from the server's reference documents (`/reference/data/`), caches them per server for an hour, and uses the cached copy when the server cannot be reached (`DATA_MODEL_CACHED`). `BRAINSTEM_NWB_DATA_MODEL` names a directory with the documents for offline machines; `brainstem-nwb data-model` fetches and shows the model.
|
|
10
|
+
- The manifest's `data_model` names the server, the data model generation, the export format and a checksum of the model used. A generation this release was not written for is reported as `DATA_MODEL_UNSUPPORTED`.
|
|
11
|
+
- Follows the production data model (`specimen-1`): data acquisitions and manipulations link procedures only through their interfaces, as the server's session export does; specimens record `laterality` (no `hemisphere` or `baseline_conditions`).
|
|
12
|
+
- Planned and cancelled sessions get no file (`SESSION_NOT_PERFORMED`); planned and cancelled procedures and specimen procedures are left out of the file and kept in the manifest (`PROCEDURE_NOT_PERFORMED`). Records without a status are performed.
|
|
13
|
+
- The code is MIT. The BrainSTEM data model and schemas are © BrainSTEM, all rights reserved; embedded schemas carry BrainSTEM's notice in the `schemas` table description.
|
|
14
|
+
|
|
15
|
+
### NWB extensions (mapping version 1.2.0)
|
|
16
|
+
|
|
17
|
+
- `--extension brainstem` writes every included BrainSTEM record, with every field and the links between them, as `ndx-brainstem` tables (pre-release extension, 0.2.x; install with `pip install "brainstem-nwb[extensions]"`).
|
|
18
|
+
- With `--extension brainstem`, coordinates of procedures and interfaces in stereotaxic absolute and Allen CCF systems are also written as `ndx-anatomical-localization` tables, linked to their `ndx-brainstem` rows (`--extension localization` is the same option).
|
|
19
|
+
- The `ndx-brainstem` schema table (extension 0.2.0) lists every BrainSTEM JSON schema the file's tables name, with its stable URL. `--embed-schemas` fetches the schemas from the server's public schema service and embeds them. Coordinates get their own `coordinates_schema` column.
|
|
20
|
+
- Materials link directly to their catalog consumable (`catalog_entry`), also when the usage names a stock. Stocks keep only their typed details (batch, titer, volume, aliquots).
|
|
21
|
+
- `--herd` writes ontology terms for species, strains, regions and device models as a HERD zip next to each file.
|
|
22
|
+
- Licenses, data storages and inventories are no longer written to NWB files (NWBFile.protocol lists protocols only); they stay in the manifest.
|
|
23
|
+
- An NWB Inspector check that crashes is reported as a warning, not an error.
|
|
24
|
+
|
|
25
|
+
### Export format 2.1 (mapping version 1.1.0)
|
|
26
|
+
|
|
27
|
+
- **Session exports.** Reads session exports (`export_info.scope`, `session_id`, `project_ids`). `export --session UUID` fetches one session's export through `BrainstemClient.export_session` when the API tools provide it. A session in several projects lists all of them in `experiment_description` and `keywords`.
|
|
28
|
+
- **Catalog records the export now includes:**
|
|
29
|
+
- Brain regions and atlases: electrode-group and stimulus-site `location` from region acronyms, with full names and atlas in descriptions and procedure text.
|
|
30
|
+
- Suppliers: `DeviceModel` with manufacturer and model number for hardware devices and probe designs; suppliers in material descriptions.
|
|
31
|
+
- Publications: `related_publications` DOIs.
|
|
32
|
+
- User names: who performed each procedure, episode personnel, and opt-in `experimenter_source = "session_creator"`.
|
|
33
|
+
- Log entries: `Subject.weight` from the latest weighing before the session.
|
|
34
|
+
- Behavioral paradigms and categories, setup types, regulatory authorities.
|
|
35
|
+
- **Restricted lab resources.** Resources the exporting user cannot read (`export_info.restricted`) are named in the text and reported as `RESTRICTED_LAB_RESOURCES`.
|
|
36
|
+
- **Contract fixtures.** Regenerated from the server's export builder, as a project export and a session export.
|
|
37
|
+
|
|
38
|
+
### First version
|
|
39
|
+
|
|
40
|
+
First release: metadata-only export. Mapping version 1.0.0. Manifest and validation report schemas 1.0.0.
|
|
41
|
+
|
|
42
|
+
#### Input
|
|
43
|
+
|
|
44
|
+
- Reads BrainSTEM project exports (format 2.x), from a downloaded file (`.json` or `.json.gz`) or fetched with `BrainstemClient.export_project()`.
|
|
45
|
+
|
|
46
|
+
#### Export units
|
|
47
|
+
|
|
48
|
+
- One NWB file per session and subject, named `sub-<subject>/sub-<subject>_ses-<session>.nwb`.
|
|
49
|
+
- Each record is attributed to the subject it belongs to, and every decision is documented.
|
|
50
|
+
- Specimen (ex vivo) sessions are supported.
|
|
51
|
+
|
|
52
|
+
#### What is written
|
|
53
|
+
|
|
54
|
+
**Session and subject**
|
|
55
|
+
|
|
56
|
+
- Session fields and project context.
|
|
57
|
+
- `Subject`: species, optionally as an NCBI Taxonomy IRI; strain; sex; date of birth; age; genotype.
|
|
58
|
+
|
|
59
|
+
**Procedures and manipulations**
|
|
60
|
+
|
|
61
|
+
- Surgery, virus and pharmacology narratives, from procedures and their materials.
|
|
62
|
+
- Stimulus notes, from manipulations.
|
|
63
|
+
|
|
64
|
+
**Devices**
|
|
65
|
+
|
|
66
|
+
- Devices from equipment and experimental interfaces.
|
|
67
|
+
- Electrode groups.
|
|
68
|
+
- Optogenetic stimulus sites.
|
|
69
|
+
|
|
70
|
+
**Other**
|
|
71
|
+
|
|
72
|
+
- The epochs table.
|
|
73
|
+
- Ex vivo slices.
|
|
74
|
+
- Behaviors in the notes.
|
|
75
|
+
- A provenance block.
|
|
76
|
+
|
|
77
|
+
#### Manifest and validation
|
|
78
|
+
|
|
79
|
+
- **Conversion manifest:** a value state for every NWB destination, coded warnings, raw-data references, and the records used.
|
|
80
|
+
- **Validation:**
|
|
81
|
+
- pynwb schema validation.
|
|
82
|
+
- NWB Inspector, with the DANDI configuration.
|
|
83
|
+
- BrainSTEM semantic checks.
|
|
84
|
+
- Reports in JSON and text.
|
|
85
|
+
|
|
86
|
+
#### Tools
|
|
87
|
+
|
|
88
|
+
- **CLI:** `export`, `manifest`, `validate`, `fetch`, `mapping`, `schema`.
|
|
89
|
+
- **Python API:** `export_project`, `export_session`, `build_manifest`, `validate_output`, `load_export`, `fetch_export`.
|
|
90
|
+
|
|
91
|
+
#### Reproducibility
|
|
92
|
+
|
|
93
|
+
- Deterministic NWB identifiers.
|
|
94
|
+
- `--reproducible` mode.
|
|
95
|
+
- Idempotent re-runs: files that are already up to date are kept.
|
|
96
|
+
|
|
97
|
+
#### Raw data (Phase 4)
|
|
98
|
+
|
|
99
|
+
- Designed only: the converter protocol, registry, data-path file and NeuroConv metadata hand-off.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Peter C. Petersen - BrainSTEM Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: brainstem-nwb
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Export BrainSTEM experimental metadata to Neurodata Without Borders (NWB) files
|
|
5
|
+
Project-URL: Homepage, https://github.com/brainstem-org/brainstem-nwb
|
|
6
|
+
Project-URL: Documentation, https://github.com/brainstem-org/brainstem-nwb/tree/main/docs
|
|
7
|
+
Project-URL: Issues, https://github.com/brainstem-org/brainstem-nwb/issues
|
|
8
|
+
Author: BrainSTEM Team
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: brainstem,dandi,electronic lab notebook,metadata,neuroscience,nwb
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: brainstem-python-api-tools>=2.1
|
|
23
|
+
Requires-Dist: click>=8.1
|
|
24
|
+
Requires-Dist: nwbinspector>=0.7
|
|
25
|
+
Requires-Dist: pydantic>=2.6
|
|
26
|
+
Requires-Dist: pynwb<5,>=4.0
|
|
27
|
+
Requires-Dist: requests>=2.28
|
|
28
|
+
Requires-Dist: tomli>=2.0; python_version < '3.11'
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: jsonschema>=4.18; extra == 'dev'
|
|
31
|
+
Requires-Dist: mypy>=1.11; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest-cov>=5; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
34
|
+
Requires-Dist: ruff>=0.6; extra == 'dev'
|
|
35
|
+
Provides-Extra: docs
|
|
36
|
+
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
|
|
37
|
+
Provides-Extra: extensions
|
|
38
|
+
Requires-Dist: ndx-brainstem<0.3,>=0.2; extra == 'extensions'
|
|
39
|
+
Provides-Extra: neuroconv
|
|
40
|
+
Requires-Dist: neuroconv[ecephys-minimal]>=0.10; extra == 'neuroconv'
|
|
41
|
+
Description-Content-Type: text/markdown
|
|
42
|
+
|
|
43
|
+
# brainstem-nwb
|
|
44
|
+
|
|
45
|
+
Export experimental metadata from [BrainSTEM](https://www.brainstem.org) to
|
|
46
|
+
[Neurodata Without Borders (NWB)](https://www.nwb.org) files.
|
|
47
|
+
|
|
48
|
+
`brainstem-nwb` reads a BrainSTEM project export and writes one NWB file per session and subject,
|
|
49
|
+
following NWB and DANDI conventions. Each file holds what BrainSTEM knows about the experiment:
|
|
50
|
+
- session and subject
|
|
51
|
+
- surgeries, viruses and drugs
|
|
52
|
+
- devices, electrode groups and optogenetic sites
|
|
53
|
+
- acquisitions, behaviors, manipulations and epochs
|
|
54
|
+
|
|
55
|
+
Alongside the files it writes a versioned **conversion manifest** and a **validation report**.
|
|
56
|
+
|
|
57
|
+
This release exports **metadata only**. Measured data (recordings, video, imaging) is not converted
|
|
58
|
+
yet; the files describe it and point to it. Raw-data conversion with
|
|
59
|
+
[NeuroConv](https://github.com/catalystneuro/neuroconv), starting with flat binary extracellular
|
|
60
|
+
recordings, is designed and planned (see [docs/design/phase4-raw-data.md](docs/design/phase4-raw-data.md)).
|
|
61
|
+
|
|
62
|
+
## Install
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install brainstem-nwb
|
|
66
|
+
# the development version:
|
|
67
|
+
pip install git+https://github.com/brainstem-org/brainstem-nwb
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Python 3.10 or newer. brainstem-nwb reads the BrainSTEM data model from the server at run time, so the
|
|
71
|
+
first export needs network access to www.brainstem.org (or your `--url`); the model is then cached (see
|
|
72
|
+
[installation](docs/install.md#the-brainstem-data-model)). Installing also installs [pynwb](https://github.com/NeurodataWithoutBorders/pynwb),
|
|
73
|
+
[NWB Inspector](https://github.com/NeurodataWithoutBorders/nwbinspector) and the
|
|
74
|
+
[BrainSTEM Python API tools](https://github.com/brainstem-org/brainstem_python_api_tools).
|
|
75
|
+
|
|
76
|
+
## Quick start
|
|
77
|
+
|
|
78
|
+
From a project export downloaded in BrainSTEM (Project → Download → JSON):
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
brainstem-nwb export --export-file brainstem-export.json.gz --output ./nwb/
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Or fetch the export directly (needs read access to the project):
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
brainstem login # once, from the BrainSTEM API tools
|
|
88
|
+
brainstem-nwb export --project PROJECT_UUID --output ./nwb/
|
|
89
|
+
brainstem-nwb export --session SESSION_UUID --output ./nwb/ # one session's export
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
From Python:
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
from brainstem_nwb import export_project
|
|
96
|
+
|
|
97
|
+
result = export_project(project_id="PROJECT_UUID", output_dir="./nwb")
|
|
98
|
+
# or: export_project(export_file="brainstem-export.json.gz", output_dir="./nwb")
|
|
99
|
+
print(result.exit_code, result.manifest.summary)
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
The output directory then contains:
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
nwb/
|
|
106
|
+
sub-<subject>/sub-<subject>_ses-<session>.nwb
|
|
107
|
+
brainstem-nwb-manifest.json what was exported, from which records, with every warning
|
|
108
|
+
validation-report.json / .txt pynwb, NWB Inspector (DANDI configuration) and BrainSTEM checks
|
|
109
|
+
source/brainstem-export-….json.gz the export the files were built from (when fetched)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Other commands:
|
|
113
|
+
- **Dry run:** `brainstem-nwb manifest --export-file … -o manifest.json` writes only the manifest, so you can inspect what would be written.
|
|
114
|
+
- **One session:** `brainstem-nwb export … --session NAME`.
|
|
115
|
+
- **Validate existing files:** `brainstem-nwb validate ./nwb/`.
|
|
116
|
+
|
|
117
|
+
Some NWB fields are not in a BrainSTEM export, so they are never guessed: experimenter, lab and institution. Supply them in a configuration file:
|
|
118
|
+
|
|
119
|
+
```toml
|
|
120
|
+
# brainstem-nwb.toml (use with --config brainstem-nwb.toml)
|
|
121
|
+
[nwbfile]
|
|
122
|
+
experimenter = ["Last, First"]
|
|
123
|
+
lab = "My Lab"
|
|
124
|
+
institution = "My University"
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
A fully reproducible example is in [examples/synthetic-ephys](examples/synthetic-ephys/).
|
|
128
|
+
|
|
129
|
+
## Principles
|
|
130
|
+
|
|
131
|
+
- **Nothing is invented.** No time series, electrode positions or other observations are generated from metadata. Fields BrainSTEM does not have stay empty, and the manifest records why. Each value is marked present, missing, unknown, not applicable or not exported.
|
|
132
|
+
- **Nothing is silently dropped.** Every field of every exported record is accounted for:
|
|
133
|
+
- mapped to NWB,
|
|
134
|
+
- used to link records,
|
|
135
|
+
- or kept in the manifest, with the reason.
|
|
136
|
+
|
|
137
|
+
The [mapping specification](docs/mapping-spec.md) is generated from the code.
|
|
138
|
+
- **Traceable.** Every file carries a provenance block naming its BrainSTEM records, the exporter and mapping versions, and the checksum of the source export. Its NWB identifier is derived from the content, so re-exporting unchanged records gives the same identifier.
|
|
139
|
+
- **Core NWB by default.** With `--extension brainstem`, every BrainSTEM record is also stored losslessly in the file as `ndx-brainstem` tables. See [extensions](docs/extensions.md).
|
|
140
|
+
|
|
141
|
+
## Documentation
|
|
142
|
+
|
|
143
|
+
- [Installation and authentication](docs/install.md)
|
|
144
|
+
- [Quick start and CLI](docs/cli.md) · [Python API](docs/python-api.md)
|
|
145
|
+
- [Mapping specification](docs/mapping-spec.md) · [Warning codes](docs/warnings.md)
|
|
146
|
+
- [Conversion manifest](docs/manifest.md) · [Validation](docs/validation.md)
|
|
147
|
+
- [Supported modalities](docs/modalities.md) · [Troubleshooting](docs/troubleshooting.md)
|
|
148
|
+
- [Architecture](docs/design/architecture.md) · [Design decisions](docs/design/decisions.md)
|
|
149
|
+
- [Contributing](CONTRIBUTING.md) · [Changelog](CHANGELOG.md)
|
|
150
|
+
|
|
151
|
+
## License
|
|
152
|
+
|
|
153
|
+
The code is released under the [MIT License](LICENSE).
|
|
154
|
+
|
|
155
|
+
The BrainSTEM data model and its JSON schemas are not part of this package and are not covered by that
|
|
156
|
+
license: they are © BrainSTEM, all rights reserved ([terms](https://www.brainstem.org/reference/license.md)).
|
|
157
|
+
brainstem-nwb reads them from the BrainSTEM server as an API client. `--embed-schemas` embeds the schemas of a
|
|
158
|
+
file's records unchanged, as a BrainSTEM export does, with BrainSTEM's notice next to them.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# brainstem-nwb
|
|
2
|
+
|
|
3
|
+
Export experimental metadata from [BrainSTEM](https://www.brainstem.org) to
|
|
4
|
+
[Neurodata Without Borders (NWB)](https://www.nwb.org) files.
|
|
5
|
+
|
|
6
|
+
`brainstem-nwb` reads a BrainSTEM project export and writes one NWB file per session and subject,
|
|
7
|
+
following NWB and DANDI conventions. Each file holds what BrainSTEM knows about the experiment:
|
|
8
|
+
- session and subject
|
|
9
|
+
- surgeries, viruses and drugs
|
|
10
|
+
- devices, electrode groups and optogenetic sites
|
|
11
|
+
- acquisitions, behaviors, manipulations and epochs
|
|
12
|
+
|
|
13
|
+
Alongside the files it writes a versioned **conversion manifest** and a **validation report**.
|
|
14
|
+
|
|
15
|
+
This release exports **metadata only**. Measured data (recordings, video, imaging) is not converted
|
|
16
|
+
yet; the files describe it and point to it. Raw-data conversion with
|
|
17
|
+
[NeuroConv](https://github.com/catalystneuro/neuroconv), starting with flat binary extracellular
|
|
18
|
+
recordings, is designed and planned (see [docs/design/phase4-raw-data.md](docs/design/phase4-raw-data.md)).
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install brainstem-nwb
|
|
24
|
+
# the development version:
|
|
25
|
+
pip install git+https://github.com/brainstem-org/brainstem-nwb
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Python 3.10 or newer. brainstem-nwb reads the BrainSTEM data model from the server at run time, so the
|
|
29
|
+
first export needs network access to www.brainstem.org (or your `--url`); the model is then cached (see
|
|
30
|
+
[installation](docs/install.md#the-brainstem-data-model)). Installing also installs [pynwb](https://github.com/NeurodataWithoutBorders/pynwb),
|
|
31
|
+
[NWB Inspector](https://github.com/NeurodataWithoutBorders/nwbinspector) and the
|
|
32
|
+
[BrainSTEM Python API tools](https://github.com/brainstem-org/brainstem_python_api_tools).
|
|
33
|
+
|
|
34
|
+
## Quick start
|
|
35
|
+
|
|
36
|
+
From a project export downloaded in BrainSTEM (Project → Download → JSON):
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
brainstem-nwb export --export-file brainstem-export.json.gz --output ./nwb/
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Or fetch the export directly (needs read access to the project):
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
brainstem login # once, from the BrainSTEM API tools
|
|
46
|
+
brainstem-nwb export --project PROJECT_UUID --output ./nwb/
|
|
47
|
+
brainstem-nwb export --session SESSION_UUID --output ./nwb/ # one session's export
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
From Python:
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
from brainstem_nwb import export_project
|
|
54
|
+
|
|
55
|
+
result = export_project(project_id="PROJECT_UUID", output_dir="./nwb")
|
|
56
|
+
# or: export_project(export_file="brainstem-export.json.gz", output_dir="./nwb")
|
|
57
|
+
print(result.exit_code, result.manifest.summary)
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The output directory then contains:
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
nwb/
|
|
64
|
+
sub-<subject>/sub-<subject>_ses-<session>.nwb
|
|
65
|
+
brainstem-nwb-manifest.json what was exported, from which records, with every warning
|
|
66
|
+
validation-report.json / .txt pynwb, NWB Inspector (DANDI configuration) and BrainSTEM checks
|
|
67
|
+
source/brainstem-export-….json.gz the export the files were built from (when fetched)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Other commands:
|
|
71
|
+
- **Dry run:** `brainstem-nwb manifest --export-file … -o manifest.json` writes only the manifest, so you can inspect what would be written.
|
|
72
|
+
- **One session:** `brainstem-nwb export … --session NAME`.
|
|
73
|
+
- **Validate existing files:** `brainstem-nwb validate ./nwb/`.
|
|
74
|
+
|
|
75
|
+
Some NWB fields are not in a BrainSTEM export, so they are never guessed: experimenter, lab and institution. Supply them in a configuration file:
|
|
76
|
+
|
|
77
|
+
```toml
|
|
78
|
+
# brainstem-nwb.toml (use with --config brainstem-nwb.toml)
|
|
79
|
+
[nwbfile]
|
|
80
|
+
experimenter = ["Last, First"]
|
|
81
|
+
lab = "My Lab"
|
|
82
|
+
institution = "My University"
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
A fully reproducible example is in [examples/synthetic-ephys](examples/synthetic-ephys/).
|
|
86
|
+
|
|
87
|
+
## Principles
|
|
88
|
+
|
|
89
|
+
- **Nothing is invented.** No time series, electrode positions or other observations are generated from metadata. Fields BrainSTEM does not have stay empty, and the manifest records why. Each value is marked present, missing, unknown, not applicable or not exported.
|
|
90
|
+
- **Nothing is silently dropped.** Every field of every exported record is accounted for:
|
|
91
|
+
- mapped to NWB,
|
|
92
|
+
- used to link records,
|
|
93
|
+
- or kept in the manifest, with the reason.
|
|
94
|
+
|
|
95
|
+
The [mapping specification](docs/mapping-spec.md) is generated from the code.
|
|
96
|
+
- **Traceable.** Every file carries a provenance block naming its BrainSTEM records, the exporter and mapping versions, and the checksum of the source export. Its NWB identifier is derived from the content, so re-exporting unchanged records gives the same identifier.
|
|
97
|
+
- **Core NWB by default.** With `--extension brainstem`, every BrainSTEM record is also stored losslessly in the file as `ndx-brainstem` tables. See [extensions](docs/extensions.md).
|
|
98
|
+
|
|
99
|
+
## Documentation
|
|
100
|
+
|
|
101
|
+
- [Installation and authentication](docs/install.md)
|
|
102
|
+
- [Quick start and CLI](docs/cli.md) · [Python API](docs/python-api.md)
|
|
103
|
+
- [Mapping specification](docs/mapping-spec.md) · [Warning codes](docs/warnings.md)
|
|
104
|
+
- [Conversion manifest](docs/manifest.md) · [Validation](docs/validation.md)
|
|
105
|
+
- [Supported modalities](docs/modalities.md) · [Troubleshooting](docs/troubleshooting.md)
|
|
106
|
+
- [Architecture](docs/design/architecture.md) · [Design decisions](docs/design/decisions.md)
|
|
107
|
+
- [Contributing](CONTRIBUTING.md) · [Changelog](CHANGELOG.md)
|
|
108
|
+
|
|
109
|
+
## License
|
|
110
|
+
|
|
111
|
+
The code is released under the [MIT License](LICENSE).
|
|
112
|
+
|
|
113
|
+
The BrainSTEM data model and its JSON schemas are not part of this package and are not covered by that
|
|
114
|
+
license: they are © BrainSTEM, all rights reserved ([terms](https://www.brainstem.org/reference/license.md)).
|
|
115
|
+
brainstem-nwb reads them from the BrainSTEM server as an API client. `--embed-schemas` embeds the schemas of a
|
|
116
|
+
file's records unchanged, as a BrainSTEM export does, with BrainSTEM's notice next to them.
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Command-line interface
|
|
2
|
+
|
|
3
|
+
This page is the reference for every `brainstem-nwb` command and option. `brainstem-nwb --help` and `brainstem-nwb COMMAND --help` show the same options.
|
|
4
|
+
|
|
5
|
+
## `export`
|
|
6
|
+
|
|
7
|
+
Converts a whole project, or some of its sessions, into metadata-only NWB files.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
brainstem-nwb export (--project UUID | --export-file FILE) --output DIR [options]
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Where the records come from
|
|
14
|
+
|
|
15
|
+
| Option | Meaning |
|
|
16
|
+
|---|---|
|
|
17
|
+
| `--project UUID` | Fetch the project's export from BrainSTEM |
|
|
18
|
+
| `--export-file FILE` | Use a downloaded export (`.json` or `.json.gz`, project or session export) |
|
|
19
|
+
| `--session ID\|NAME` | Export only this session; repeat for more. A single `--session UUID` without `--project` or `--export-file` fetches that session's export |
|
|
20
|
+
| `--token`, `--url`, `--headless`, `--no-device-flow`, `--no-background` | Fetching and authentication; see [install.md](install.md) |
|
|
21
|
+
| `--no-save-export` | Do not keep a copy of the fetched export in `DIR/source/` |
|
|
22
|
+
|
|
23
|
+
### What is written
|
|
24
|
+
|
|
25
|
+
| Option | Meaning |
|
|
26
|
+
|---|---|
|
|
27
|
+
| `--config FILE.toml` | Experimenter, lab, institution and subject options ([configuration](#configuration)) |
|
|
28
|
+
| `--dry-run` | Write only `brainstem-nwb-manifest.json` |
|
|
29
|
+
| `--allow-no-subject` | Export sessions that have no subject, without an NWB Subject |
|
|
30
|
+
| `--no-infer-subjects` | When a session lists no subjects, do not take them from its behaviors, procedures and interfaces |
|
|
31
|
+
| `--overwrite` | Replace existing files whose content differs. Files that are identical are kept and reported as `up_to_date` |
|
|
32
|
+
| `--reproducible` | Use the export time as the creation time, so reruns give identical manifests |
|
|
33
|
+
| `--extension brainstem\|localization` | Also write NWB extensions: every BrainSTEM record as `ndx-brainstem` tables, and coordinates as `ndx-anatomical-localization` tables. Repeatable. See [extensions](extensions.md) |
|
|
34
|
+
| `--embed-schemas` | With `--extension brainstem`: fetch the BrainSTEM JSON schemas the records use from the server's public schema service (`--url`) and embed them |
|
|
35
|
+
| `--herd` | Also write ontology terms (NCBITaxon, RRIDs, atlas regions) as a HERD zip next to each file |
|
|
36
|
+
| `--fail-fast` | Stop at the first unit that fails. By default the remaining units are still exported |
|
|
37
|
+
|
|
38
|
+
### Validation and output
|
|
39
|
+
|
|
40
|
+
| Option | Meaning |
|
|
41
|
+
|---|---|
|
|
42
|
+
| `--no-validate` | Skip validation |
|
|
43
|
+
| `--inspector-config dandi\|none` | NWB Inspector configuration. Default: `dandi` |
|
|
44
|
+
| `--fail-on error\|warning` | Which validation severity gives exit code 4 |
|
|
45
|
+
| `--json` | Print the summary as JSON |
|
|
46
|
+
|
|
47
|
+
## `manifest`
|
|
48
|
+
|
|
49
|
+
The same as `export --dry-run`, but the manifest can be written to a single named file:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
brainstem-nwb manifest --export-file export.json -o manifest.json
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## `validate`
|
|
56
|
+
|
|
57
|
+
Validates NWB files, or a directory of them. When the files are in an export directory, they are also checked against the manifest there.
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
brainstem-nwb validate ./nwb/ [--manifest FILE] [--report-dir DIR] [--inspector-config dandi|none] [--fail-on warning]
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## `fetch`
|
|
64
|
+
|
|
65
|
+
Downloads a project or session export to a file, so you can convert it later or offline.
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
brainstem-nwb fetch --project UUID -o export.json.gz
|
|
69
|
+
brainstem-nwb fetch --session UUID -o session-export.json.gz
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## `data-model`
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
brainstem-nwb data-model [--url URL] [--refresh]
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Reads the BrainSTEM data model from the server (or the fresh cached copy), caches it, and shows the server, the data model generation and whether this release supports it, the export format, its checksum and the cache directory. Run it once before working offline. See [the BrainSTEM data model](install.md#the-brainstem-data-model).
|
|
79
|
+
|
|
80
|
+
## `mapping` and `schema`
|
|
81
|
+
|
|
82
|
+
| Command | Prints |
|
|
83
|
+
|---|---|
|
|
84
|
+
| `brainstem-nwb mapping` | The mapping specification (Markdown). `--format json` prints the rules instead; `--warnings` prints the warning codes |
|
|
85
|
+
| `brainstem-nwb schema manifest` | The JSON Schema of the manifest |
|
|
86
|
+
| `brainstem-nwb schema report` | The JSON Schema of the validation report |
|
|
87
|
+
|
|
88
|
+
## Exit codes
|
|
89
|
+
|
|
90
|
+
| Code | Meaning |
|
|
91
|
+
|---|---|
|
|
92
|
+
| 0 | Everything was exported and validated without errors |
|
|
93
|
+
| 1 | Partial export: some sessions could not be exported, or some files failed (see the manifest) |
|
|
94
|
+
| 2 | Usage error, invalid configuration, or unreadable or unsupported export file |
|
|
95
|
+
| 3 | Authentication or retrieval failure, or the data model could not be read and is not cached |
|
|
96
|
+
| 4 | Files were written, but validation found errors (or warnings, with `--fail-on warning`) |
|
|
97
|
+
|
|
98
|
+
If several apply, the highest code is returned.
|
|
99
|
+
|
|
100
|
+
## Configuration
|
|
101
|
+
|
|
102
|
+
Some NWB fields have no source in a BrainSTEM export. They can be set in a TOML file:
|
|
103
|
+
|
|
104
|
+
```toml
|
|
105
|
+
[nwbfile]
|
|
106
|
+
experimenter = ["Last, First", "Other, Person"]
|
|
107
|
+
experimenter_source = "config" # or "session_creator": the user who created the session record, when no
|
|
108
|
+
# experimenter is configured (BrainSTEM records who created a session, not who ran it)
|
|
109
|
+
lab = "My Lab"
|
|
110
|
+
institution = "My University"
|
|
111
|
+
|
|
112
|
+
[subject]
|
|
113
|
+
label_field = "name" # or "name_used_in_storage": used for subject_id and file names
|
|
114
|
+
species_format = "binomial" # or "ncbitaxon": NCBI Taxonomy IRI, preferred by DANDI
|
|
115
|
+
```
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
This page is for contributors and for anyone embedding the exporter. It explains how `brainstem-nwb` is organized and how data moves through it. To change a mapping, see [Contributing](https://github.com/brainstem-org/brainstem-nwb/blob/main/CONTRIBUTING.md); the reasons behind the main choices are in [decisions.md](decisions.md).
|
|
4
|
+
|
|
5
|
+
## Layers
|
|
6
|
+
|
|
7
|
+
The exporter has four layers, and each knows only its neighbours:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
retrieval ─► normalization ─► manifest (NwbPlan) ─► NWB writing ─► validation
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
| Layer | Package | Input → output | Knows about |
|
|
14
|
+
|---|---|---|---|
|
|
15
|
+
| Retrieval | `retrieval/` | project id or file → `ProjectExport` | the BrainSTEM API tools, the export format |
|
|
16
|
+
| Normalization | `store/`, `normalize/` | `ProjectExport` → `RecordStore`, `ExportUnit`s | BrainSTEM records and links |
|
|
17
|
+
| Mapping | `mapping/` | `ExportUnit` → manifest `Unit` with an `NwbPlan` | BrainSTEM and NWB concepts, not HTTP or HDF5 |
|
|
18
|
+
| NWB writing | `nwb/` | `NwbPlan` → `.nwb` file | pynwb only, not BrainSTEM |
|
|
19
|
+
| Validation | `validation/` | `.nwb` (+ manifest unit) → report | pynwb, NWB Inspector, the manifest |
|
|
20
|
+
|
|
21
|
+
`export.py` puts the layers together. `cli.py` and the functions in `__init__.py` are thin wrappers around it.
|
|
22
|
+
|
|
23
|
+
## Data flow
|
|
24
|
+
|
|
25
|
+
1. **Retrieval.** `load_export()` reads a project export (format 2.x) from a file or a dict. `fetch_export()` gets one through `BrainstemClient.export_project()`. The export is the **only** source of BrainSTEM records. This keeps an export reproducible: the export file, the exporter version and the BrainSTEM data model (whose checksum the manifest records) determine the result.
|
|
26
|
+
2. **Record store.** `RecordStore` indexes records by model label and primary key, and builds a reverse index of every foreign key and many-to-many link. The export does not record which model a link points to. That comes from the **inventory**: the BrainSTEM data model, read at run time from the server's reference documents (`store/datamodel.py`) and cached per server; brainstem-nwb ships no copy of it. A link to a record that is not in the export resolves to `Ref(reason="not_in_export")`; it is not an error.
|
|
27
|
+
3. **Units.** `plan_units()` decides which files to write. An NWB file holds one subject, so each session gives one unit per subject. Every record of the session is attributed to the units it belongs to, using documented rules. Each decision is recorded as an `Attribution`, and sessions that cannot be exported become `unit_errors`.
|
|
28
|
+
4. **Mapping.** `map_unit()` runs the mapper modules in order: session, project, people, protocols, subject, procedures, manipulations, acquisitions, devices, electrode groups, optogenetic sites, epochs and notes. Each mapper does two things:
|
|
29
|
+
- fills the `NwbPlan`;
|
|
30
|
+
- records every intended destination as a `FieldMapping` with a value state, and emits coded warnings.
|
|
31
|
+
|
|
32
|
+
Mapper functions declare their `MappingRule`s with `@rules(...)`. The registry generates the mapping specification and backs the coverage test.
|
|
33
|
+
5. **Manifest.** The per-unit results, the source description, coverage and summary make up the `Manifest`. It is written as canonical JSON (`brainstem-nwb-manifest.json`), and a dry run stops here.
|
|
34
|
+
6. **Writing.** `build_nwbfile(plan)` builds a pynwb `NWBFile` from the plan alone. `write_nwbfile()` writes it to a temporary name and moves it into place.
|
|
35
|
+
7. **Validation.** Each file goes through `pynwb.validate`, NWB Inspector (DANDI configuration by default) and the BrainSTEM semantic checks, which compare the file with its manifest unit. Results go to `validation-report.json` and `.txt`.
|
|
36
|
+
|
|
37
|
+
## Identity and reproducibility
|
|
38
|
+
|
|
39
|
+
- The NWB `identifier` is `uuid5(namespace, session id | subject id | mapping version | sha256(plan content))`.
|
|
40
|
+
- It is stable across re-exports of unchanged records.
|
|
41
|
+
- It changes when any written content changes.
|
|
42
|
+
- It ignores when the export was made.
|
|
43
|
+
- `--reproducible` (or `SOURCE_DATE_EPOCH`) takes the creation times from the export, which makes the manifest byte-identical across runs.
|
|
44
|
+
- HDF5 files themselves are not byte-identical (HDF5 object ids are random). Reproducibility tests therefore compare a canonical summary of each file (`nwb/canonical.py`).
|
|
45
|
+
|
|
46
|
+
## Extension points
|
|
47
|
+
|
|
48
|
+
- **New mapping.** Add a mapper function with `@rules(...)` and call it from `mapping/pipeline.py`. The coverage test lists the BrainSTEM fields still unaccounted for.
|
|
49
|
+
- **New BrainSTEM fields or models.** The data model comes from the server, so new fields appear on their own; `tests/test_spec.py` lists the ones the mapping does not account for yet. New record types go into `EXPORT_LABELS`.
|
|
50
|
+
- **Raw data (Phase 4).** Implement `raw.base.RawDataConverter` and register it, either built in or through the `brainstem_nwb.raw_converters` entry-point group. See [phase4-raw-data.md](phase4-raw-data.md).
|
|
51
|
+
- **Web integration (Phase 5).** The server can call `build_manifest(export_dict)` and `export_project(export=export_dict, ...)` directly with the payload of `build_project_export`, with no HTTP involved.
|