Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NWB Loader #10

Merged
merged 22 commits into from
Sep 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
b555ccb
testing nwb file, and experimenting with yaml format
sneakers-the-rat Aug 30, 2024
49585e4
working on grpah loading of nwb files
sneakers-the-rat Aug 31, 2024
3641d33
split up fixtures and nwb fixture in particular, add --clean pytest o…
sneakers-the-rat Sep 2, 2024
53c415d
lint
sneakers-the-rat Sep 2, 2024
a693427
codespell
sneakers-the-rat Sep 2, 2024
97135c1
update models to correctly handle ElementIdentifiers
sneakers-the-rat Sep 3, 2024
ee35e59
exclude metadata vars from column and category checks
sneakers-the-rat Sep 3, 2024
676d42d
instantiate ValidationError according to https://github.com/pydantic/…
sneakers-the-rat Sep 3, 2024
cd3d7ca
model update
sneakers-the-rat Sep 3, 2024
d1498a3
checkpointing working on model loading. it's a sloggggggggg
sneakers-the-rat Sep 3, 2024
8078492
CHECKPOINT WITH IT WORKING before cleanup and model regeneration
sneakers-the-rat Sep 4, 2024
27b5ddd
updating model generation methods, still some models being converted …
sneakers-the-rat Sep 4, 2024
000ddde
Updating model generation methods to make both loader tests and hdmf …
sneakers-the-rat Sep 11, 2024
dfcb395
regenerate models
sneakers-the-rat Sep 11, 2024
3f360c2
use in-repo version of models
sneakers-the-rat Sep 11, 2024
b76b0fd
bump nwb-models version
sneakers-the-rat Sep 11, 2024
1f1325e
bump version of dependant nwb-models
sneakers-the-rat Sep 11, 2024
d31ac29
clean up old hdf5 reader methods, fix truncate_hdf5 method, make prop…
sneakers-the-rat Sep 12, 2024
bb59c9d
remove unused code, nocover some debug arms
sneakers-the-rat Sep 12, 2024
91b2abf
working thru tests for nwb file
sneakers-the-rat Sep 12, 2024
95fbce1
add id to index name on aligneddynamictable correctly
sneakers-the-rat Sep 12, 2024
0eeea4c
lint
sneakers-the-rat Sep 12, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 4 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ jobs:
nwb_models/pyproject.toml

- name: Install dependencies
run: pip install -e .[tests]
run: |
pip install -e .[tests]
pip install -e ../nwb_schema_language
pip install -e ../nwb_models
working-directory: nwb_linkml

- name: Run Tests
Expand Down
4 changes: 4 additions & 0 deletions docs/meta/todo.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ Remove monkeypatches/overrides once PRs are closed
Tests
- [ ] Ensure schemas and pydantic modules in repos are up to date

Loading
- [ ] Top-level containers are still a little janky, eg. how `ProcessingModule` just accepts
extra args rather than properly abstracting `value` as a `__getitem__(self, key) -> T:`

## Docs TODOs

```{todolist}
Expand Down
2 changes: 1 addition & 1 deletion nwb_linkml/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def parse_adapter_blocks(document: Document) -> Generator[Region, None, None]:

doctest_parser = Sybil(
parsers=[DocTestParser(optionflags=ELLIPSIS + NORMALIZE_WHITESPACE), PythonCodeBlockParser()],
patterns=["*.py"],
patterns=["providers/git.py"],
)

pytest_collect_file = (adapter_parser + doctest_parser).pytest()
166 changes: 116 additions & 50 deletions nwb_linkml/pdm.lock

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions nwb_linkml/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ license = {text = "AGPL-3.0"}
readme = "README.md"
requires-python = "<3.13,>=3.10"
dependencies = [
"nwb-models>=0.1.0",
"nwb-models>=0.2.0",
"pyyaml>=6.0",
"linkml-runtime>=1.7.7",
"nwb-schema-language>=0.1.3",
Expand All @@ -22,9 +22,10 @@ dependencies = [
"pydantic-settings>=2.0.3",
"tqdm>=4.66.1",
'typing-extensions>=4.12.2;python_version<"3.11"',
"numpydantic>=1.3.3",
"numpydantic>=1.5.0",
"black>=24.4.2",
"pandas>=2.2.2",
"networkx>=3.3",
]

[project.urls]
Expand All @@ -44,6 +45,7 @@ tests = [
"pytest-cov<5.0.0,>=4.1.0",
"sybil>=6.0.3",
"requests-cache>=1.2.1",
"pynwb>=2.8.1",
]
dev = [
"nwb-linkml[tests]",
Expand Down
14 changes: 14 additions & 0 deletions nwb_linkml/src/nwb_linkml/adapters/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
Base class for adapters
"""

import os
import sys
from abc import abstractmethod
from dataclasses import dataclass, field
Expand Down Expand Up @@ -101,6 +102,19 @@ class Adapter(BaseModel):
"""Abstract base class for adapters"""

_logger: Optional[Logger] = None
_debug: Optional[bool] = None

@property
def debug(self) -> bool:
"""
Whether we are in debug mode, which adds extra metadata in generated elements.

Set explicitly via ``_debug`` , or else checks for the truthiness of the
environment variable ``NWB_LINKML_DEBUG``
"""
if self._debug is None:
self._debug = bool(os.environ.get("NWB_LINKML_DEBUG", False))
return self._debug

@property
def logger(self) -> Logger:
Expand Down
19 changes: 17 additions & 2 deletions nwb_linkml/src/nwb_linkml/adapters/attribute.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from nwb_linkml.adapters.adapter import Adapter, BuildResult, is_1d
from nwb_linkml.adapters.array import ArrayAdapter
from nwb_linkml.maps import Map
from nwb_linkml.maps.dtype import handle_dtype
from nwb_linkml.maps.dtype import handle_dtype, inlined
from nwb_schema_language import Attribute


Expand Down Expand Up @@ -104,6 +104,7 @@ def apply(cls, attr: Attribute, res: Optional[BuildResult] = None) -> BuildResul
range=handle_dtype(attr.dtype),
description=attr.doc,
required=attr.required,
inlined=inlined(attr.dtype),
**cls.handle_defaults(attr),
)
return BuildResult(slots=[slot])
Expand Down Expand Up @@ -151,6 +152,7 @@ def apply(cls, attr: Attribute, res: Optional[BuildResult] = None) -> BuildResul
multivalued=multivalued,
description=attr.doc,
required=attr.required,
inlined=inlined(attr.dtype),
**expressions,
**cls.handle_defaults(attr),
)
Expand All @@ -171,7 +173,10 @@ def build(self) -> "BuildResult":
Build the slot definitions, every attribute should have a map.
"""
map = self.match()
return map.apply(self.cls)
res = map.apply(self.cls)
if self.debug: # pragma: no cover - only used in development
res = self._amend_debug(res, map)
return res

def match(self) -> Optional[Type[AttributeMap]]:
"""
Expand All @@ -195,3 +200,13 @@ def match(self) -> Optional[Type[AttributeMap]]:
return None
else:
return matches[0]

def _amend_debug(
self, res: BuildResult, map: Optional[Type[AttributeMap]] = None
) -> BuildResult: # pragma: no cover - only used in development
map_name = "None" if map is None else map.__name__
for cls in res.classes:
cls.annotations["attribute_map"] = {"tag": "attribute_map", "value": map_name}
for slot in res.slots:
slot.annotations["attribute_map"] = {"tag": "attribute_map", "value": map_name}
return res
16 changes: 14 additions & 2 deletions nwb_linkml/src/nwb_linkml/adapters/classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,13 @@ def build_base(self, extra_attrs: Optional[List[SlotDefinition]] = None) -> Buil
# Get vanilla top-level attributes
kwargs["attributes"].extend(self.build_attrs(self.cls))

if self.debug: # pragma: no cover - only used in development
kwargs["annotations"] = {}
kwargs["annotations"]["group_adapter"] = {
"tag": "group_adapter",
"value": "container_slot",
}

if extra_attrs is not None:
if isinstance(extra_attrs, SlotDefinition):
extra_attrs = [extra_attrs]
Expand Down Expand Up @@ -230,18 +237,23 @@ def build_name_slot(self) -> SlotDefinition:
ifabsent=f"string({name})",
equals_string=equals_string,
range="string",
identifier=True,
)
else:
name_slot = SlotDefinition(name="name", required=True, range="string")
name_slot = SlotDefinition(name="name", required=True, range="string", identifier=True)
return name_slot

def build_self_slot(self) -> SlotDefinition:
"""
If we are a child class, we make a slot so our parent can refer to us
"""
return SlotDefinition(
slot = SlotDefinition(
name=self._get_slot_name(),
description=self.cls.doc,
range=self._get_full_name(),
inlined=True,
**QUANTITY_MAP[self.cls.quantity],
)
if self.debug: # pragma: no cover - only used in development
slot.annotations["group_adapter"] = {"tag": "group_adapter", "value": "self_slot"}
return slot
Loading
Loading