Source code for nwb2bids.bids_models._dataset_description
import importlib.metadata
import json
import typing
import pydantic
import typing_extensions
from ._base_metadata_model import BaseMetadataModel
class GeneratedByItem(BaseMetadataModel):
"""
Schema for a single GeneratedBy entry in BIDS dataset_description.json.
Represents provenance information about a pipeline or process that generated the dataset.
See Also
--------
https://bids-specification.readthedocs.io/en/stable/glossary.html#generatedby-metadata
"""
Name: str = pydantic.Field(
description="Name of the pipeline or process that generated the outputs.",
)
Version: str = pydantic.Field(
description="Version of the pipeline.",
)
Description: str = pydantic.Field(
description="Plain-text description of the pipeline or process that generated the outputs.",
)
CodeURL: str = pydantic.Field(
description="URL where the code used to generate the dataset may be found.",
)
class GeneratedByNwb2bids(GeneratedByItem):
"""
nwb2bids-specific GeneratedBy entry with defaults for the nwb2bids pipeline.
"""
Name: str = pydantic.Field(default="nwb2bids")
Version: str = pydantic.Field(default_factory=lambda: importlib.metadata.version(distribution_name="nwb2bids"))
Description: str = pydantic.Field(default="Tool to reorganize NWB files into a BIDS directory layout.")
CodeURL: str = pydantic.Field(default="https://github.com/con/nwb2bids")
[docs]
class DatasetDescription(BaseMetadataModel):
"""
Schema for the dataset description in BIDS format.
"""
Name: str | None = pydantic.Field(description="Name of the dataset.", default=None)
BIDSVersion: str | None = pydantic.Field(
description="The version of the BIDS standard that was used.",
pattern=r"^\d+\.\d+(?:\.\d+)?$",
)
HEDVersion: str | None = pydantic.Field(
description="The version of the HED standard that was used.",
pattern=r"^\d+\.\d+(?:\.\d+)?$",
)
Description: str | None = pydantic.Field(
description="Description of the dataset.",
default=None,
)
DatasetType: typing.Literal["raw", "derivative"] = pydantic.Field(
description="The interpretation of the dataset.",
default="raw",
)
Authors: list[str] | None = pydantic.Field(
description="List of individuals who contributed to the creation/curation of the dataset.",
default=None,
)
License: typing.Literal["CC-BY-4.0", "CC0-1.0"] | None = pydantic.Field(
description="License under which the dataset is released.",
default=None,
)
GeneratedBy: list[GeneratedByItem] | None = pydantic.Field(
description="Provenance information - pipelines that generated this dataset.",
default=None,
)
[docs]
def model_post_init(self, context: typing.Any, /) -> None:
generated_by_nwb2bids = GeneratedByNwb2bids()
if self.GeneratedBy is None:
self.GeneratedBy = [generated_by_nwb2bids]
else:
self.GeneratedBy.append(generated_by_nwb2bids)
[docs]
@pydantic.model_validator(mode="after")
def validate_exactly_one_nwb2bids(self) -> typing_extensions.Self:
if self.GeneratedBy is not None:
nwb2bids_count = sum(1 for item in self.GeneratedBy if item.Name == "nwb2bids")
if nwb2bids_count != 1:
raise ValueError(f"GeneratedBy must contain exactly one nwb2bids entry, found {nwb2bids_count}")
return self
[docs]
@classmethod
@pydantic.validate_call
def from_file_path(cls, file_path: pydantic.FilePath) -> typing_extensions.Self | None:
"""
Load the BIDS dataset description from a JSON file.
Parameters
----------
file_path : FilePath
Path to the JSON file containing the dataset metadata.
Returns
-------
BidsDatasetMetadata or None
An instance of DatasetDescription populated with data from the file.
"""
with file_path.open(mode="r") as file_stream:
dictionary = json.load(fp=file_stream)
dataset_description_content = dictionary.get("dataset_description", None)
if dataset_description_content is None:
return None
dataset_metadata = cls(**dataset_description_content)
return dataset_metadata