Metadata-Version: 2.4
Name: atlaslevels
Version: 0.3.0
Summary: Tools for working with atlas ontologies and custom hierarchy levels.
Author: Ingvild
License-Expression: MIT
Project-URL: Homepage, https://github.com/ingvildeb/atlaslevels
Project-URL: Repository, https://github.com/ingvildeb/atlaslevels
Project-URL: Issues, https://github.com/ingvildeb/atlaslevels/issues
Keywords: atlas,ontology,neuroscience,allen-brain-atlas,hierarchy,brain-regions
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Operating System :: OS Independent
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pandas>=2.0
Requires-Dist: PyYAML>=6.0
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == "dev"
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: twine>=5.0; extra == "dev"
Dynamic: license-file

# atlaslevels

`atlaslevels` is a Python package for working with atlas ontologies and curated hierarchy bundles across projects. It streamlines loading atlas metadata, defining and validating hierarchy levels as ordered parent-children sets, resolving region IDs, names and color codes, and selecting biologically meaningful region sets for different levels of analysis.

## Docs

- [Domain spec](./docs/domain_spec.md)
- [Schema spec](./docs/schema_spec.md)
- [Validation spec](./docs/validation_spec.md)
- [API sketch](./docs/api_sketch.md)

## Installation

Install the package:

```bash
pip install atlaslevels
```

For local development in this repo:

```bash
pip install -e .
```

For local development with test/build tools:

```bash
pip install -e .[dev]
```

## Allen Support

`atlaslevels` includes built-in support for use of the Allen CCFv3 ontology. The packaged Allen preset currently uses `ccfv3-2022`. This matters for validation and completeness semantics, because `atlaslevels` evaluates spatial coverage against the metadata that specifies which regions has voxel support in that specific atlas version.

Curated Allen CCFv3 hierarchy bundles include:
- `allen_gm`: Hierarchy bundle with seven increasingly coarse levels (CustomLevel1_gm through CustomLevel7_gm) of grey matter regions.
- `allen_wm`: Hierarchy bundle with a single level (CustomLevel1_wm) highlighting fine white matter regions while collapsing grey matter and ventricular systems.

You can load the full ontology directly with:

```python
from atlaslevels import load_preset_ontology

ontology = load_preset_ontology("allen_ccfv3")
```

You can also load the curated bundles:

```python
from atlaslevels import load_preset_bundle

bundle = load_preset_bundle("allen_gm")
bundle.list_levels()
bundle.get_parent_names("CustomLevel1_gm")
```

### Support for different ID systems
The package also includes a preset Allen-to-KimLab16bit ID map for workflows that need to convert between original Allen IDs and the 16bit labels used in some of the atlases published by the KimLab.

```python
from atlaslevels import load_preset_id_map

id_map = load_preset_id_map("allen_ccfv3_allen_to_kimlab16bit")
kimlab_id = id_map.convert(526157192)
allen_id = id_map.invert().convert(20040)
```

### Parent regions with voxels
A few regions in the Allen CCFv3 are both parent regions and have direct voxel support. This means that the parent region is not completely represented by the combination of all its children, which may matter for some workflows. `atlaslevels` can optionally include parent residual regions in child-expansion results.

List descendants under a selected parent in a level:

```python
from atlaslevels import load_preset_bundle

bundle = load_preset_bundle("allen_gm")

children = bundle.get_child_names("CustomLevel2_gm", parent="Main olfactory bulb")
print(children)
```

Output:

```python
[
    "Main olfactory bulb, glomerular layer",
    "Main olfactory bulb, granule layer",
    "Main olfactory bulb, inner plexiform layer",
    "Main olfactory bulb, mitral layer",
    "Main olfactory bulb, outer plexiform layer",
]
```

Include the parent itself when it is a parent residual:

```python
from atlaslevels import load_preset_bundle

bundle = load_preset_bundle("allen_gm")

children_plus_residual = bundle.get_child_names(
    "CustomLevel2_gm",
    parent="Main olfactory bulb",
    include_parent_residual=True,
)
print(children_plus_residual)
```

Output:

```python
[
    "Main olfactory bulb, glomerular layer",
    "Main olfactory bulb, granule layer",
    "Main olfactory bulb, inner plexiform layer",
    "Main olfactory bulb, mitral layer",
    "Main olfactory bulb, outer plexiform layer",
    "Main olfactory bulb",
]
```

## Supported Workflows

The primary supported workflow for `atlaslevels` v0.3.0 is loading packaged presets such as:

- `load_preset_ontology("allen_ccfv3")`
- `load_preset_bundle("allen_gm")`
- `load_preset_bundle("allen_wm")`

Custom bundle loading is also supported through the documented YAML schema.

Custom ontology loading is possible, but it currently expects canonicalized input rather than acting as a general-purpose ontology importer.

In particular:

- `AtlasOntology.from_json(...)` expects the current nested JSON structure described by the code and examples
- `AtlasOntology.from_records(...)` expects canonical node records plus matching `AtlasMetadata.node_metadata`
- `HierarchyBundle.from_yaml(...)` and `HierarchyBundle.from_dict(...)` are the more mature custom-loading entry points

Future versions will simplify and improve documentation of the import of custom ontologies and hierarchy bundles.

## Core Objects

The current package revolves around a small set of core objects:

- `AtlasMetadata`
  Atlas-level provenance and configuration, loaded from YAML.
- `AtlasNode`
  One canonical ontology node with ID, parent, name, acronym, color, and direct-voxel flag.
- `AtlasOntology`
  The rooted ontology tree plus region lookup and structural queries.
- `HierarchyLevel`
  One hierarchy level defined by an ordered list of parent region IDs.
- `HierarchyBundle`
  A family of hierarchy levels tied to one ontology, with query helpers for parent/child selection and mapping.
- `ValidationIssue` / `ValidationResult`
  Structured validation outputs.

## Main Methods

The most useful methods at a glance are:

- `AtlasMetadata.from_yaml(path)`
- `AtlasOntology.from_json(path, metadata=...)`
- `HierarchyBundle.from_yaml(path, ontology=...)`
- `load_preset_ontology(name)`
- `load_preset_bundle(name)`
- `load_preset_id_map(name)`
- `validate_ontology(ontology)`
- `validate_bundle(bundle, ontology)`

On `AtlasOntology`:

- `get_node(node_id)`
- `get_parent(node_id)`
- `get_children(node_id)`
- `get_ancestors(node_id)`
- `get_descendants(node_id)`
- `is_ancestor(ancestor_id, node_id)`
- `is_descendant(descendant_id, node_id)`
- `get_name(node_id)`
- `get_acronym(node_id)`
- `get_color(node_id)`
- `has_direct_voxel_support(node_id)`
- `is_parent_residual(node_id)`
- `resolve_name(name)`
- `resolve_acronym(acronym)`

On `HierarchyBundle`:

- `list_levels()`
- `get_level(level_name)`
- `get_parent_ids(level_name)`
- `get_parent_names(level_name)`
- `get_parent_acronyms(level_name)`
- `map_region_to_level_parent(region, level_name)`
- `get_child_ids(level_name, parent, spatial_only=False, include_parent_residual=False)`
- `get_child_names(level_name, parent, spatial_only=False, include_parent_residual=False)`
- `get_child_acronyms(level_name, parent, spatial_only=False, include_parent_residual=False)`

## Example Usage

Load a built-in ontology preset:

```python
from atlaslevels import load_preset_ontology

ontology = load_preset_ontology("allen_ccfv3")

print(ontology.get_name(315))
print(ontology.get_children(184))
print(ontology.is_ancestor(315, 68))
```

Load a built-in hierarchy bundle preset:

```python
from atlaslevels import load_preset_bundle

bundle = load_preset_bundle("allen_gm")

print([level.level_name for level in bundle.list_levels()])
print(bundle.get_parent_names("CustomLevel4_gm"))
```

Map a region to its parent at a chosen level:

```python
from atlaslevels import load_preset_bundle

bundle = load_preset_bundle("allen_gm")

parent_id = bundle.map_region_to_level_parent(68, "CustomLevel1_gm")
parent_name = bundle.ontology.get_name(parent_id) if parent_id is not None else None

print(parent_id, parent_name)
```

Load a custom ontology and bundle explicitly:

```python
from atlaslevels import AtlasMetadata, AtlasOntology, HierarchyBundle, validate_bundle

metadata = AtlasMetadata.from_yaml("atlas_metadata.yaml")
ontology = AtlasOntology.from_json("ontology.json", metadata=metadata)
bundle = HierarchyBundle.from_yaml("my_bundle.yaml", ontology=ontology)

result = validate_bundle(bundle, ontology)
result.raise_if_errors()
```

## Local Integration Tests

The default test suite uses the small in-repo fixtures plus the packaged full Allen preset.

Run the test suite with:

```bash
python -m pytest -q
```


