2023-08-18 08:11:14 +00:00
|
|
|
"""
|
|
|
|
Loading/saving NWB Schema yaml files
|
|
|
|
"""
|
|
|
|
from pathlib import Path
|
2023-08-19 05:09:28 +00:00
|
|
|
from typing import TypedDict, List, Dict
|
2023-08-18 08:11:14 +00:00
|
|
|
from pprint import pprint
|
2023-08-19 05:09:28 +00:00
|
|
|
import warnings
|
2023-08-18 08:11:14 +00:00
|
|
|
|
|
|
|
from linkml_runtime.loaders import yaml_loader
|
|
|
|
import yaml
|
|
|
|
|
2023-08-22 04:43:02 +00:00
|
|
|
from nwb_schema_language import Namespaces, Group, Dataset
|
|
|
|
from nwb_linkml.namespaces import NamespaceRepo, NWB_CORE_REPO, HDMF_COMMON_REPO
|
2023-08-19 05:09:28 +00:00
|
|
|
from nwb_linkml.maps import preload
|
|
|
|
from nwb_linkml.map import PHASES, Map
|
2023-08-22 04:43:02 +00:00
|
|
|
from nwb_linkml.adapters.namespaces import NamespacesAdapter
|
|
|
|
from nwb_linkml.adapters.schema import SchemaAdapter
|
2023-08-19 05:09:28 +00:00
|
|
|
|
|
|
|
|
|
|
|
def load_yaml(path:Path) -> dict:
|
|
|
|
with open(path, 'r') as file:
|
|
|
|
ns_dict = yaml.safe_load(file)
|
|
|
|
|
|
|
|
# apply maps
|
|
|
|
maps = [m for m in Map.instances if m.phase == PHASES.postload]
|
|
|
|
for amap in maps:
|
|
|
|
ns_dict = amap.apply(ns_dict)
|
|
|
|
return ns_dict
|
2023-08-18 08:11:14 +00:00
|
|
|
|
|
|
|
def load_namespaces(path:Path|NamespaceRepo) -> Namespaces:
|
|
|
|
if isinstance(path, NamespaceRepo):
|
|
|
|
path = path.provide_from_git()
|
|
|
|
|
2023-08-19 05:09:28 +00:00
|
|
|
ns_dict = load_yaml(path)
|
|
|
|
|
|
|
|
|
|
|
|
namespaces = yaml_loader.load(ns_dict, target_class=Namespaces)
|
2023-08-18 08:11:14 +00:00
|
|
|
return namespaces
|
|
|
|
|
2023-08-19 05:09:28 +00:00
|
|
|
|
2023-08-18 08:11:14 +00:00
|
|
|
|
2023-08-22 04:43:02 +00:00
|
|
|
def load_schema_file(path:Path) -> SchemaAdapter:
|
2023-08-19 05:09:28 +00:00
|
|
|
source = load_yaml(path)
|
2023-08-18 08:11:14 +00:00
|
|
|
|
2023-08-22 04:43:02 +00:00
|
|
|
datasets = []
|
2023-08-18 08:11:14 +00:00
|
|
|
|
|
|
|
for dataset in source.get('datasets', []):
|
|
|
|
try:
|
2023-08-22 04:43:02 +00:00
|
|
|
datasets.append(Dataset(**dataset))
|
2023-08-18 08:11:14 +00:00
|
|
|
except Exception as e:
|
|
|
|
pprint(dataset)
|
|
|
|
raise e
|
|
|
|
|
2023-08-22 04:43:02 +00:00
|
|
|
groups = []
|
2023-08-19 05:09:28 +00:00
|
|
|
for group in source.get('groups', []):
|
|
|
|
try:
|
2023-08-22 04:43:02 +00:00
|
|
|
groups.append(Group(**group))
|
2023-08-19 05:09:28 +00:00
|
|
|
except Exception as e:
|
|
|
|
pprint(group)
|
|
|
|
raise e
|
|
|
|
|
2023-08-22 04:43:02 +00:00
|
|
|
schema = SchemaAdapter(
|
|
|
|
path=path,
|
|
|
|
datasets=datasets,
|
|
|
|
groups=groups
|
|
|
|
)
|
2023-08-18 08:11:14 +00:00
|
|
|
return schema
|
|
|
|
|
2023-08-22 04:43:02 +00:00
|
|
|
def load_namespace_schema(namespace: Namespaces, path:Path=Path('.')) -> NamespacesAdapter:
|
2023-08-19 05:09:28 +00:00
|
|
|
"""
|
|
|
|
Load all schema referenced by a namespace file
|
|
|
|
|
|
|
|
Args:
|
|
|
|
namespace (:class:`.Namespace`):
|
|
|
|
path (:class:`pathlib.Path`): Location of the namespace file - all relative paths are interpreted relative to this
|
|
|
|
|
|
|
|
Returns:
|
2023-08-22 04:43:02 +00:00
|
|
|
:class:`.NamespacesAdapter`
|
2023-08-19 05:09:28 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
path = Path(path).resolve()
|
|
|
|
if path.is_file():
|
|
|
|
# given the namespace file itself, so find paths relative to its directory
|
|
|
|
path = path.parent
|
|
|
|
|
2023-08-22 04:43:02 +00:00
|
|
|
sch = []
|
|
|
|
for ns in namespace.namespaces:
|
2023-08-19 05:09:28 +00:00
|
|
|
for schema in ns.schema_:
|
|
|
|
if schema.source is None:
|
|
|
|
warnings.warn(f"No source specified for {schema}")
|
|
|
|
continue
|
|
|
|
yml_file = (path / schema.source).resolve()
|
2023-08-22 04:43:02 +00:00
|
|
|
sch.append(load_schema_file(yml_file))
|
|
|
|
|
|
|
|
adapter = NamespacesAdapter(
|
|
|
|
namespaces=namespace,
|
|
|
|
schemas=sch
|
|
|
|
)
|
2023-08-19 05:09:28 +00:00
|
|
|
|
2023-08-22 04:43:02 +00:00
|
|
|
return adapter
|
2023-08-19 05:09:28 +00:00
|
|
|
|
2023-08-22 04:43:02 +00:00
|
|
|
def load_nwb_core() -> NamespacesAdapter:
|
2023-08-19 05:09:28 +00:00
|
|
|
# First get hdmf-common:
|
|
|
|
hdmf_ns_file = HDMF_COMMON_REPO.provide_from_git()
|
|
|
|
hdmf_ns = load_namespaces(hdmf_ns_file)
|
|
|
|
hdmf_schema = load_namespace_schema(hdmf_ns, hdmf_ns_file)
|
|
|
|
|
2023-08-18 23:33:06 +00:00
|
|
|
namespace_file = NWB_CORE_REPO.provide_from_git()
|
|
|
|
ns = load_namespaces(namespace_file)
|
2023-08-19 05:09:28 +00:00
|
|
|
schema = load_namespace_schema(ns, namespace_file)
|
|
|
|
|
2023-08-22 04:43:02 +00:00
|
|
|
schema.imported.append(hdmf_schema)
|
|
|
|
|
|
|
|
return schema
|
2023-08-19 05:09:28 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2023-08-18 23:33:06 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-08-18 08:11:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|