diff --git a/docs/Makefile b/docs/Makefile index c09f941..54b0d85 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -15,7 +15,8 @@ help: .PHONY: help Makefile serve: - sphinx-autobuild "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) --watch ../nwb_linkml/src/nwb_linkml --watch ../nwb_schema_language/src/nwb_schema_language + # env variable that makes it so we don't build all the models while in dev mode + SPHINX_MINIMAL="True" sphinx-autobuild "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) --watch ../nwb_linkml/src/nwb_linkml --watch ../nwb_schema_language/src/nwb_schema_language serve_fast: sphinx-autobuild -a "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) --watch ../nwb_linkml/src/nwb_linkml --watch ../nwb_schema_language/src/nwb_schema_language diff --git a/docs/_static/css/custom.css b/docs/_static/css/custom.css new file mode 100644 index 0000000..35aa590 --- /dev/null +++ b/docs/_static/css/custom.css @@ -0,0 +1,7 @@ +.feature { + background-color: var(--color-admonition-title--hint); + padding: 2px 10px; + color: #1a1c1e; + font-style: italic; + border-radius: 4px; +} \ No newline at end of file diff --git a/docs/api/nwb_schema_language/index.md b/docs/api/nwb_schema_language/index.md index 0d6f0a0..017f3a1 100644 --- a/docs/api/nwb_schema_language/index.md +++ b/docs/api/nwb_schema_language/index.md @@ -1,4 +1,4 @@ -# NWB Schema Language +# nwb_schema_language ```{toctree} :maxdepth: 1 diff --git a/docs/conf.py b/docs/conf.py index 929540b..307497f 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -2,6 +2,7 @@ # # For the full list of built-in configuration values, see the documentation: # https://www.sphinx-doc.org/en/master/usage/configuration.html +import pdb # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information @@ -11,23 +12,34 @@ copyright = '2023, Jonny Saunders' author = 'Jonny Saunders' release = 'v0.1.0' +import os +from sphinx.util.tags import Tags +tags: Tags + # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration extensions = [ 'sphinx.ext.graphviz', - "myst_parser", 'sphinx.ext.napoleon', 'sphinx.ext.autodoc', 'sphinxcontrib.autodoc_pydantic', 'sphinx.ext.intersphinx', 'sphinx.ext.doctest', - "sphinx_design" + "sphinx_design", + 'myst_parser', + 'sphinx_togglebutton' ] + templates_path = ['_templates'] -# exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '**/models'] -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + +if os.environ.get('SPHINX_MINIMAL', None) == 'True': + exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '**/models'] + tags.add('minimal') +else: + exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + tags.add('full') @@ -36,6 +48,9 @@ exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] html_theme = 'furo' html_static_path = ['_static'] +html_css_files = [ + 'css/custom.css' +] intersphinx_mapping = { 'python': ('https://docs.python.org/3', None), diff --git a/docs/guide/overview.md b/docs/guide/overview.md new file mode 100644 index 0000000..4bba659 --- /dev/null +++ b/docs/guide/overview.md @@ -0,0 +1 @@ +# Overview \ No newline at end of file diff --git a/docs/index.md b/docs/index.md index b98a836..f7297f6 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,37 +1,315 @@ # nwb-linkml +```{role} feature +``` + +A translation of the [Neurodata Without Borders](https://www.nwb.org/) standard +to [LinkML](https://linkml.io/). + +```{admonition} Quick Links +* [Purpose](purpose) - Why this package exists +* [Overview](overview) - Overview of how it works +* [API Docs](api) - Ok *really* how it works +``` + +`nwb-linkml` is an independent implementation of the standard capable of: + +* Translating schemas written in the {index}`NWB Schema Language` to LinkML. +* Manage multiple versions of NWB schemas with dependencies +* Generating pydantic models from nwb-flavored LinkML +* Read NWB files (including those that use custom, embedded schemas) +* {feature}`Coming Soon` Write/edit NWB files +* {feature}`Coming Soon` Export NWB to a Relational Database +* {feature}`Coming Soon` Export NWB to a Triple Store + +## Samples + +### Reading + +```python +from pathlib import Path +from rich import print +from nwb_linkml.io import HDF5IO + +# find sample data file and read +nwb_file = Path('../nwb_linkml/tests/data/aibs.nwb') +data = HDF5IO(nwb_file).read() +print(data) +``` + +````{admonition} Model Print Output +:class: dropdown + +```{literalinclude} read_output.txt +:language: python +``` +```` + + +### TimeSeries + +(Abbreviated for clarity) + +`````{tab-set} +````{tab-item} NWB schema +```yaml +groups: +- neurodata_type_def: TimeSeries + neurodata_type_inc: NWBDataInterface + doc: General purpose time series. + attributes: + - name: description + dtype: text + default_value: no description + doc: Description of the time series. + required: false + - name: comments + dtype: text + default_value: no comments + doc: Human-readable comments about the TimeSeries. This second descriptive field + can be used to store additional information, or descriptive information if the + primary description field is populated with a computer-readable string. + required: false + datasets: + - name: data + dims: + - - num_times + - - num_times + - num_DIM2 + - - num_times + - num_DIM2 + - num_DIM3 + - - num_times + - num_DIM2 + - num_DIM3 + - num_DIM4 + shape: + - - null + - - null + - null + - - null + - null + - null + - - null + - null + - null + - null + doc: Data values. Data can be in 1-D, 2-D, 3-D, or 4-D. The first dimension + should always represent time. This can also be used to store binary data + (e.g., image frames). This can also be a link to data stored in an external file. + attributes: + - name: conversion + dtype: float32 + default_value: 1.0 + doc: Scalar to multiply each element in data (...) + required: false + - name: timestamps + dtype: float64 + dims: + - num_times + shape: + - null + doc: Timestamps for samples stored in data, in seconds, relative to the + common experiment master-clock stored in NWBFile.timestamps_reference_time. + quantity: '?' + attributes: + - name: interval + dtype: int32 + value: 1 + doc: Value is '1' + - name: unit + dtype: text + value: seconds + doc: Unit of measurement for timestamps, which is fixed to 'seconds'. +``` +```` +````{tab-item} LinkML +```yaml +classes: + TimeSeries: + name: TimeSeries + description: General purpose time series. + is_a: NWBDataInterface + attributes: + name: + name: name + identifier: true + range: string + required: true + description: + name: description + description: Description of the time series. + range: text + comments: + name: comments + description: Human-readable comments about the TimeSeries. This second descriptive + field can be used to store additional information, or descriptive information + if the primary description field is populated with a computer-readable string. + range: text + data: + name: data + description: Data values. Data can be in 1-D, 2-D, 3-D, or 4-D. The first + dimension should always represent time. This can also be used to store binary + data (e.g., image frames). This can also be a link to data stored in an + external file. + multivalued: false + range: TimeSeries__data + required: true + timestamps: + name: timestamps + description: Timestamps for samples stored in data, in seconds, relative to + the common experiment master-clock stored in NWBFile.timestamps_reference_time. + multivalued: false + range: TimeSeries__timestamps__Array + required: false + tree_root: true + + TimeSeries__data: + name: TimeSeries__data + description: Data values. Data can be in 1-D, 2-D, 3-D, or 4-D. The first dimension + should always represent time. This can also be used to store binary data (e.g., + image frames). This can also be a link to data stored in an external file. + attributes: + name: + name: name + ifabsent: string(data) + identifier: true + range: string + required: true + equals_string: data + conversion: + name: conversion + description: Scalar to multiply each element in data to convert it to the + specified 'unit'. If the data are stored in acquisition system units or + other units that require a conversion to be interpretable, multiply the + data by 'conversion' to convert the data to the specified 'unit'. e.g. if + the data acquisition system stores values in this object as signed 16-bit + integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V + to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' + multiplier to get from raw data acquisition values to recorded volts is + 2.5/32768/8000 = 9.5367e-9. + range: float32 + array: + name: array + range: TimeSeries__data__Array + + TimeSeries__data__Array: + name: TimeSeries__data__Array + is_a: Arraylike + attributes: + num_times: + name: num_times + range: AnyType + required: true + num_DIM2: + name: num_DIM2 + range: AnyType + required: false + num_DIM3: + name: num_DIM3 + range: AnyType + required: false + num_DIM4: + name: num_DIM4 + range: AnyType + required: false + + TimeSeries__timestamps__Array: + name: TimeSeries__timestamps__Array + is_a: Arraylike + attributes: + num_times: + name: num_times + range: float64 + required: true +``` +```` +````{tab-item} Pydantic +```python +class TimeSeries(NWBDataInterface): + """ + General purpose time series. + """ + linkml_meta: ClassVar[LinkML_Meta] = Field(LinkML_Meta(tree_root=True), frozen=True) + name: str = Field(...) + description: Optional[str] = Field(None, description="""Description of the time series.""") + comments: Optional[str] = Field(None, description="""Human-readable comments about the TimeSeries. This second descriptive field can be used to store additional information, or descriptive information if the primary description field is populated with a computer-readable string.""") + data: TimeSeriesData = Field(..., description="""Data values. Data can be in 1-D, 2-D, 3-D, or 4-D. The first dimension should always represent time. This can also be used to store binary data (e.g., image frames). This can also be a link to data stored in an external file.""") + timestamps: Optional[NDArray[Shape["* num_times"], Float64]] = Field(None, description="""Timestamps for samples stored in data, in seconds, relative to the common experiment master-clock stored in NWBFile.timestamps_reference_time.""") + +class TimeSeriesData(ConfiguredBaseModel): + """ + Data values. Data can be in 1-D, 2-D, 3-D, or 4-D. The first dimension should always represent time. This can also be used to store binary data (e.g., image frames). This can also be a link to data stored in an external file. + """ + linkml_meta: ClassVar[LinkML_Meta] = Field(LinkML_Meta(), frozen=True) + name: Literal["data"] = Field("data") + conversion: Optional[float] = Field(None, description="""Scalar to multiply each element in data to convert it to the specified 'unit'. If the data are stored in acquisition system units or other units that require a conversion to be interpretable, multiply the data by 'conversion' to convert the data to the specified 'unit'. e.g. if the data acquisition system stores values in this object as signed 16-bit integers (int16 range -32,768 to 32,767) that correspond to a 5V range (-2.5V to 2.5V), and the data acquisition system gain is 8000X, then the 'conversion' multiplier to get from raw data acquisition values to recorded volts is 2.5/32768/8000 = 9.5367e-9.""") + array: Optional[Union[ + NDArray[Shape["* num_times"], Any], + NDArray[Shape["* num_times, * num_DIM2"], Any], + NDArray[Shape["* num_times, * num_DIM2, * num_DIM3"], Any], + NDArray[Shape["* num_times, * num_DIM2, * num_DIM3, * num_DIM4"], Any] + ]] = Field(None) + + +``` +```` + +````` + + + ```{toctree} :caption: Intro :maxdepth: 3 +:hidden: intro/purpose intro/nwb intro/translation ``` +```{toctree} +:caption: Guide +:maxdepth: 1 +:hidden: + +guide/overview +``` + +````{only} minimal ```{toctree} :caption: API :maxdepth: 3 +:hidden: + +api/nwb_linkml/index +api/nwb_schema_language/index +api/nwb_linkml/schema/index +``` +```` + +````{only} full +```{toctree} +:caption: API +:maxdepth: 3 +:hidden: api/nwb_linkml/index api/nwb_schema_language/index api/models/nwb_linkml.models api/nwb_linkml/schema/index ``` - -[//]: # (api/models/nwb_linkml.models) +```` ```{toctree} :caption: Meta +:hidden: -todo -changelog +meta/todo +meta/changelog genindex ``` -## Indices and tables -* {ref}`genindex` -* {ref}`modindex` -* {ref}`search` diff --git a/docs/intro/purpose.md b/docs/intro/purpose.md index 60debf0..3d5ccce 100644 --- a/docs/intro/purpose.md +++ b/docs/intro/purpose.md @@ -3,8 +3,14 @@ If [pynwb](https://pynwb.readthedocs.io/en/stable/) already exists, why `nwb_linkml`? +Two kinds of reasons: + +- using NWB as a test case for a larger infrastructure project, and +- potentially improving the state of NWB itself. + ## A Stepping Stone... +In the (word on how and why we are focusing on NWB as part of a larger project) ## Interoperable Schema Language diff --git a/docs/changelog.md b/docs/meta/changelog.md similarity index 100% rename from docs/changelog.md rename to docs/meta/changelog.md diff --git a/docs/todo.md b/docs/meta/todo.md similarity index 100% rename from docs/todo.md rename to docs/meta/todo.md diff --git a/docs/read_output.txt b/docs/read_output.txt new file mode 100644 index 0000000..fd06205 --- /dev/null +++ b/docs/read_output.txt @@ -0,0 +1,943 @@ +NWBFile( +│ hdf5_path='/', +│ name='root', +│ nwb_version='2.2.2', +│ file_create_date=array([datetime.datetime(2020, 5, 26, 0, 53, 26, 903120, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200)))], +│ dtype=object), +│ identifier='760693773', +│ session_description='Data and metadata for an Ecephys session', +│ session_start_time=datetime.datetime(2018, 10, 26, 12, 59, 23, tzinfo=TzInfo(-07:00)), +│ timestamps_reference_time=datetime.datetime(2018, 10, 26, 12, 59, 23, tzinfo=TzInfo(-07:00)), +│ acquisition={ +│ │ 'raw_running_wheel_rotation': TimeSeries( +│ │ │ hdf5_path='/acquisition/raw_running_wheel_rotation', +│ │ │ name='raw_running_wheel_rotation', +│ │ │ description='no description', +│ │ │ comments='no comments', +│ │ │ data=TimeSeriesData( +│ │ │ │ hdf5_path='/acquisition/raw_running_wheel_rotation/data', +│ │ │ │ object_id=None, +│ │ │ │ name='data', +│ │ │ │ conversion=1.0, +│ │ │ │ resolution=-1.0, +│ │ │ │ unit='radians', +│ │ │ │ array= +│ │ │ ), +│ │ │ starting_time=None, +│ │ │ timestamps=, +│ │ │ control=None, +│ │ │ control_description=None, +│ │ │ sync=None +│ │ ), +│ │ 'running_wheel_signal_voltage': TimeSeries( +│ │ │ hdf5_path='/acquisition/running_wheel_signal_voltage', +│ │ │ name='running_wheel_signal_voltage', +│ │ │ description='no description', +│ │ │ comments='no comments', +│ │ │ data=TimeSeriesData( +│ │ │ │ hdf5_path='/acquisition/running_wheel_signal_voltage/data', +│ │ │ │ object_id=None, +│ │ │ │ name='data', +│ │ │ │ conversion=1.0, +│ │ │ │ resolution=-1.0, +│ │ │ │ unit='V', +│ │ │ │ array= +│ │ │ ), +│ │ │ starting_time=None, +│ │ │ timestamps=, +│ │ │ control=None, +│ │ │ control_description=None, +│ │ │ sync=None +│ │ ), +│ │ 'running_wheel_supply_voltage': TimeSeries( +│ │ │ hdf5_path='/acquisition/running_wheel_supply_voltage', +│ │ │ name='running_wheel_supply_voltage', +│ │ │ description='no description', +│ │ │ comments='no comments', +│ │ │ data=TimeSeriesData( +│ │ │ │ hdf5_path='/acquisition/running_wheel_supply_voltage/data', +│ │ │ │ object_id=None, +│ │ │ │ name='data', +│ │ │ │ conversion=1.0, +│ │ │ │ resolution=-1.0, +│ │ │ │ unit='V', +│ │ │ │ array= +│ │ │ ), +│ │ │ starting_time=None, +│ │ │ timestamps=, +│ │ │ control=None, +│ │ │ control_description=None, +│ │ │ sync=None +│ │ ) +│ }, +│ analysis={}, +│ scratch={}, +│ processing={ +│ │ 'eye_tracking': ProcessingModule( +│ │ │ hdf5_path='/processing/eye_tracking', +│ │ │ name='eye_tracking', +│ │ │ children={ +│ │ │ │ 'cr_ellipse_fits': cr_ellipse_fits( +│ │ │ │ │ hdf5_path='/processing/eye_tracking/cr_ellipse_fits', +│ │ │ │ │ name='cr_ellipse_fits', +│ │ │ │ │ colnames=array(['center_x', 'center_y', 'height', 'phi', 'width', 'timestamps'], +│ dtype=object), +│ │ │ │ │ description='', +│ │ │ │ │ id=dask.array, +│ │ │ │ │ center_x=dask.array, +│ │ │ │ │ center_y=dask.array, +│ │ │ │ │ height=dask.array, +│ │ │ │ │ phi=dask.array, +│ │ │ │ │ width=dask.array, +│ │ │ │ │ timestamps=dask.array, +│ │ │ │ │ vector_data=[], +│ │ │ │ │ vector_index=[] +│ │ │ │ ), +│ │ │ │ 'eye_ellipse_fits': eye_ellipse_fits( +│ │ │ │ │ hdf5_path='/processing/eye_tracking/eye_ellipse_fits', +│ │ │ │ │ name='eye_ellipse_fits', +│ │ │ │ │ colnames=array(['center_x', 'center_y', 'height', 'phi', 'width', 'timestamps'], +│ dtype=object), +│ │ │ │ │ description='', +│ │ │ │ │ id=dask.array, +│ │ │ │ │ center_x=dask.array, +│ │ │ │ │ center_y=dask.array, +│ │ │ │ │ height=dask.array, +│ │ │ │ │ phi=dask.array, +│ │ │ │ │ width=dask.array, +│ │ │ │ │ timestamps=dask.array, +│ │ │ │ │ vector_data=[], +│ │ │ │ │ vector_index=[] +│ │ │ │ ), +│ │ │ │ 'pupil_ellipse_fits': pupil_ellipse_fits( +│ │ │ │ │ hdf5_path='/processing/eye_tracking/pupil_ellipse_fits', +│ │ │ │ │ name='pupil_ellipse_fits', +│ │ │ │ │ colnames=array(['center_x', 'center_y', 'height', 'phi', 'width', 'timestamps'], +│ dtype=object), +│ │ │ │ │ description='', +│ │ │ │ │ id=dask.array, +│ │ │ │ │ center_x=dask.array, +│ │ │ │ │ center_y=dask.array, +│ │ │ │ │ height=dask.array, +│ │ │ │ │ phi=dask.array, +│ │ │ │ │ width=dask.array, +│ │ │ │ │ timestamps=dask.array, +│ │ │ │ │ vector_data=[], +│ │ │ │ │ vector_index=[] +│ │ │ │ ) +│ │ │ } +│ │ ), +│ │ 'eye_tracking_rig_metadata': ProcessingModule( +│ │ │ hdf5_path='/processing/eye_tracking_rig_metadata', +│ │ │ name='eye_tracking_rig_metadata', +│ │ │ children={ +│ │ │ │ 'eye_tracking_rig_metadata': EcephysEyeTrackingRigMetadata( +│ │ │ │ │ hdf5_path='/processing/eye_tracking_rig_metadata/eye_tracking_rig_metadata', +│ │ │ │ │ name='eye_tracking_rig_metadata', +│ │ │ │ │ equipment='NP.1', +│ │ │ │ │ monitor_position=EcephysEyeTrackingRigMetadataMonitorPosition( +│ │ │ │ │ │ hdf5_path='/processing/eye_tracking_rig_metadata/eye_tracking_rig_metadata/monitor_position', +│ │ │ │ │ │ object_id=None, +│ │ │ │ │ │ name='monitor_position', +│ │ │ │ │ │ unit='mm', +│ │ │ │ │ │ array= +│ │ │ │ │ ), +│ │ │ │ │ camera_position=EcephysEyeTrackingRigMetadataCameraPosition( +│ │ │ │ │ │ hdf5_path='/processing/eye_tracking_rig_metadata/eye_tracking_rig_metadata/camera_position', +│ │ │ │ │ │ object_id=None, +│ │ │ │ │ │ name='camera_position', +│ │ │ │ │ │ unit='mm', +│ │ │ │ │ │ array= +│ │ │ │ │ ), +│ │ │ │ │ led_position=EcephysEyeTrackingRigMetadataLedPosition( +│ │ │ │ │ │ hdf5_path='/processing/eye_tracking_rig_metadata/eye_tracking_rig_metadata/led_position', +│ │ │ │ │ │ object_id=None, +│ │ │ │ │ │ name='led_position', +│ │ │ │ │ │ unit='mm', +│ │ │ │ │ │ array= +│ │ │ │ │ ), +│ │ │ │ │ monitor_rotation=EcephysEyeTrackingRigMetadataMonitorRotation( +│ │ │ │ │ │ hdf5_path='/processing/eye_tracking_rig_metadata/eye_tracking_rig_metadata/monitor_rotation', +│ │ │ │ │ │ object_id=None, +│ │ │ │ │ │ name='monitor_rotation', +│ │ │ │ │ │ unit='deg', +│ │ │ │ │ │ array= +│ │ │ │ │ ), +│ │ │ │ │ camera_rotation=EcephysEyeTrackingRigMetadataCameraRotation( +│ │ │ │ │ │ hdf5_path='/processing/eye_tracking_rig_metadata/eye_tracking_rig_metadata/camera_rotation', +│ │ │ │ │ │ object_id=None, +│ │ │ │ │ │ name='camera_rotation', +│ │ │ │ │ │ unit='deg', +│ │ │ │ │ │ array= +│ │ │ │ │ ) +│ │ │ │ ) +│ │ │ } +│ │ ), +│ │ 'filtered_gaze_mapping': ProcessingModule( +│ │ │ hdf5_path='/processing/filtered_gaze_mapping', +│ │ │ name='filtered_gaze_mapping', +│ │ │ children={ +│ │ │ │ 'eye_area': TimeSeries( +│ │ │ │ │ hdf5_path='/processing/filtered_gaze_mapping/eye_area', +│ │ │ │ │ name='eye_area', +│ │ │ │ │ description='no description', +│ │ │ │ │ comments='no comments', +│ │ │ │ │ data=TimeSeriesData( +│ │ │ │ │ │ hdf5_path='/processing/filtered_gaze_mapping/eye_area/data', +│ │ │ │ │ │ object_id=None, +│ │ │ │ │ │ name='data', +│ │ │ │ │ │ conversion=1.0, +│ │ │ │ │ │ resolution=-1.0, +│ │ │ │ │ │ unit='Pixels ^ 2', +│ │ │ │ │ │ array= +│ │ │ │ │ ), +│ │ │ │ │ starting_time=None, +│ │ │ │ │ timestamps=, +│ │ │ │ │ control=None, +│ │ │ │ │ control_description=None, +│ │ │ │ │ sync=None +│ │ │ │ ), +│ │ │ │ 'pupil_area': TimeSeries( +│ │ │ │ │ hdf5_path='/processing/filtered_gaze_mapping/pupil_area', +│ │ │ │ │ name='pupil_area', +│ │ │ │ │ description='no description', +│ │ │ │ │ comments='no comments', +│ │ │ │ │ data=TimeSeriesData( +│ │ │ │ │ │ hdf5_path='/processing/filtered_gaze_mapping/pupil_area/data', +│ │ │ │ │ │ object_id=None, +│ │ │ │ │ │ name='data', +│ │ │ │ │ │ conversion=1.0, +│ │ │ │ │ │ resolution=-1.0, +│ │ │ │ │ │ unit='Pixels ^ 2', +│ │ │ │ │ │ array= +│ │ │ │ │ ), +│ │ │ │ │ starting_time=None, +│ │ │ │ │ timestamps=, +│ │ │ │ │ control=None, +│ │ │ │ │ control_description=None, +│ │ │ │ │ sync=None +│ │ │ │ ), +│ │ │ │ 'screen_coordinates': TimeSeries( +│ │ │ │ │ hdf5_path='/processing/filtered_gaze_mapping/screen_coordinates', +│ │ │ │ │ name='screen_coordinates', +│ │ │ │ │ description='no description', +│ │ │ │ │ comments='no comments', +│ │ │ │ │ data=TimeSeriesData( +│ │ │ │ │ │ hdf5_path='/processing/filtered_gaze_mapping/screen_coordinates/data', +│ │ │ │ │ │ object_id=None, +│ │ │ │ │ │ name='data', +│ │ │ │ │ │ conversion=1.0, +│ │ │ │ │ │ resolution=-1.0, +│ │ │ │ │ │ unit='Centimeters', +│ │ │ │ │ │ array= +│ │ │ │ │ ), +│ │ │ │ │ starting_time=None, +│ │ │ │ │ timestamps=, +│ │ │ │ │ control=None, +│ │ │ │ │ control_description=None, +│ │ │ │ │ sync=None +│ │ │ │ ), +│ │ │ │ 'screen_coordinates_spherical': TimeSeries( +│ │ │ │ │ hdf5_path='/processing/filtered_gaze_mapping/screen_coordinates_spherical', +│ │ │ │ │ name='screen_coordinates_spherical', +│ │ │ │ │ description='no description', +│ │ │ │ │ comments='no comments', +│ │ │ │ │ data=TimeSeriesData( +│ │ │ │ │ │ hdf5_path='/processing/filtered_gaze_mapping/screen_coordinates_spherical/data', +│ │ │ │ │ │ object_id=None, +│ │ │ │ │ │ name='data', +│ │ │ │ │ │ conversion=1.0, +│ │ │ │ │ │ resolution=-1.0, +│ │ │ │ │ │ unit='Degrees', +│ │ │ │ │ │ array= +│ │ │ │ │ ), +│ │ │ │ │ starting_time=None, +│ │ │ │ │ timestamps=, +│ │ │ │ │ control=None, +│ │ │ │ │ control_description=None, +│ │ │ │ │ sync=None +│ │ │ │ ) +│ │ │ } +│ │ ), +│ │ 'optotagging': ProcessingModule( +│ │ │ hdf5_path='/processing/optotagging', +│ │ │ name='optotagging', +│ │ │ children={ +│ │ │ │ 'optogenetic_stimulation': optogenetic_stimulation( +│ │ │ │ │ hdf5_path='/processing/optotagging/optogenetic_stimulation', +│ │ │ │ │ name='optogenetic_stimulation', +│ │ │ │ │ colnames=array(['start_time', 'condition', 'level', 'stop_time', 'stimulus_name', +│ 'duration', 'tags', 'timeseries'], dtype=object), +│ │ │ │ │ description='', +│ │ │ │ │ id=dask.array, +│ │ │ │ │ start_time=dask.array, +│ │ │ │ │ stop_time=dask.array, +│ │ │ │ │ tags=, +│ │ │ │ │ tags_index=dask.array, +│ │ │ │ │ timeseries=, +│ │ │ │ │ timeseries_index=dask.array, +│ │ │ │ │ condition=, +│ │ │ │ │ level=dask.array, +│ │ │ │ │ stimulus_name=, +│ │ │ │ │ duration=dask.array, +│ │ │ │ │ vector_data=[], +│ │ │ │ │ vector_index=[] +│ │ │ │ ), +│ │ │ │ 'optotagging': TimeSeries( +│ │ │ │ │ hdf5_path='/processing/optotagging/optotagging', +│ │ │ │ │ name='optotagging', +│ │ │ │ │ description='no description', +│ │ │ │ │ comments='no comments', +│ │ │ │ │ data=TimeSeriesData( +│ │ │ │ │ │ hdf5_path='/processing/optotagging/optotagging/data', +│ │ │ │ │ │ object_id=None, +│ │ │ │ │ │ name='data', +│ │ │ │ │ │ conversion=1.0, +│ │ │ │ │ │ resolution=-1.0, +│ │ │ │ │ │ unit='seconds', +│ │ │ │ │ │ array= +│ │ │ │ │ ), +│ │ │ │ │ starting_time=None, +│ │ │ │ │ timestamps=, +│ │ │ │ │ control=None, +│ │ │ │ │ control_description=None, +│ │ │ │ │ sync=None +│ │ │ │ ) +│ │ │ } +│ │ ), +│ │ 'raw_gaze_mapping': ProcessingModule( +│ │ │ hdf5_path='/processing/raw_gaze_mapping', +│ │ │ name='raw_gaze_mapping', +│ │ │ children={ +│ │ │ │ 'eye_area': TimeSeries( +│ │ │ │ │ hdf5_path='/processing/raw_gaze_mapping/eye_area', +│ │ │ │ │ name='eye_area', +│ │ │ │ │ description='no description', +│ │ │ │ │ comments='no comments', +│ │ │ │ │ data=TimeSeriesData( +│ │ │ │ │ │ hdf5_path='/processing/raw_gaze_mapping/eye_area/data', +│ │ │ │ │ │ object_id=None, +│ │ │ │ │ │ name='data', +│ │ │ │ │ │ conversion=1.0, +│ │ │ │ │ │ resolution=-1.0, +│ │ │ │ │ │ unit='Pixels ^ 2', +│ │ │ │ │ │ array= +│ │ │ │ │ ), +│ │ │ │ │ starting_time=None, +│ │ │ │ │ timestamps=, +│ │ │ │ │ control=None, +│ │ │ │ │ control_description=None, +│ │ │ │ │ sync=None +│ │ │ │ ), +│ │ │ │ 'pupil_area': TimeSeries( +│ │ │ │ │ hdf5_path='/processing/raw_gaze_mapping/pupil_area', +│ │ │ │ │ name='pupil_area', +│ │ │ │ │ description='no description', +│ │ │ │ │ comments='no comments', +│ │ │ │ │ data=TimeSeriesData( +│ │ │ │ │ │ hdf5_path='/processing/raw_gaze_mapping/pupil_area/data', +│ │ │ │ │ │ object_id=None, +│ │ │ │ │ │ name='data', +│ │ │ │ │ │ conversion=1.0, +│ │ │ │ │ │ resolution=-1.0, +│ │ │ │ │ │ unit='Pixels ^ 2', +│ │ │ │ │ │ array= +│ │ │ │ │ ), +│ │ │ │ │ starting_time=None, +│ │ │ │ │ timestamps=, +│ │ │ │ │ control=None, +│ │ │ │ │ control_description=None, +│ │ │ │ │ sync=None +│ │ │ │ ), +│ │ │ │ 'screen_coordinates': TimeSeries( +│ │ │ │ │ hdf5_path='/processing/raw_gaze_mapping/screen_coordinates', +│ │ │ │ │ name='screen_coordinates', +│ │ │ │ │ description='no description', +│ │ │ │ │ comments='no comments', +│ │ │ │ │ data=TimeSeriesData( +│ │ │ │ │ │ hdf5_path='/processing/raw_gaze_mapping/screen_coordinates/data', +│ │ │ │ │ │ object_id=None, +│ │ │ │ │ │ name='data', +│ │ │ │ │ │ conversion=1.0, +│ │ │ │ │ │ resolution=-1.0, +│ │ │ │ │ │ unit='Centimeters', +│ │ │ │ │ │ array= +│ │ │ │ │ ), +│ │ │ │ │ starting_time=None, +│ │ │ │ │ timestamps=, +│ │ │ │ │ control=None, +│ │ │ │ │ control_description=None, +│ │ │ │ │ sync=None +│ │ │ │ ), +│ │ │ │ 'screen_coordinates_spherical': TimeSeries( +│ │ │ │ │ hdf5_path='/processing/raw_gaze_mapping/screen_coordinates_spherical', +│ │ │ │ │ name='screen_coordinates_spherical', +│ │ │ │ │ description='no description', +│ │ │ │ │ comments='no comments', +│ │ │ │ │ data=TimeSeriesData( +│ │ │ │ │ │ hdf5_path='/processing/raw_gaze_mapping/screen_coordinates_spherical/data', +│ │ │ │ │ │ object_id=None, +│ │ │ │ │ │ name='data', +│ │ │ │ │ │ conversion=1.0, +│ │ │ │ │ │ resolution=-1.0, +│ │ │ │ │ │ unit='Degrees', +│ │ │ │ │ │ array= +│ │ │ │ │ ), +│ │ │ │ │ starting_time=None, +│ │ │ │ │ timestamps=, +│ │ │ │ │ control=None, +│ │ │ │ │ control_description=None, +│ │ │ │ │ sync=None +│ │ │ │ ) +│ │ │ } +│ │ ), +│ │ 'running': ProcessingModule( +│ │ │ hdf5_path='/processing/running', +│ │ │ name='running', +│ │ │ children={ +│ │ │ │ 'running_speed': TimeSeries( +│ │ │ │ │ hdf5_path='/processing/running/running_speed', +│ │ │ │ │ name='running_speed', +│ │ │ │ │ description='no description', +│ │ │ │ │ comments='no comments', +│ │ │ │ │ data=TimeSeriesData( +│ │ │ │ │ │ hdf5_path='/processing/running/running_speed/data', +│ │ │ │ │ │ object_id=None, +│ │ │ │ │ │ name='data', +│ │ │ │ │ │ conversion=1.0, +│ │ │ │ │ │ resolution=-1.0, +│ │ │ │ │ │ unit='cm/s', +│ │ │ │ │ │ array= +│ │ │ │ │ ), +│ │ │ │ │ starting_time=None, +│ │ │ │ │ timestamps=, +│ │ │ │ │ control=None, +│ │ │ │ │ control_description=None, +│ │ │ │ │ sync=None +│ │ │ │ ), +│ │ │ │ 'running_speed_end_times': TimeSeries( +│ │ │ │ │ hdf5_path='/processing/running/running_speed_end_times', +│ │ │ │ │ name='running_speed_end_times', +│ │ │ │ │ description='no description', +│ │ │ │ │ comments='no comments', +│ │ │ │ │ data=TimeSeriesData( +│ │ │ │ │ │ hdf5_path='/processing/running/running_speed_end_times/data', +│ │ │ │ │ │ object_id=None, +│ │ │ │ │ │ name='data', +│ │ │ │ │ │ conversion=1.0, +│ │ │ │ │ │ resolution=-1.0, +│ │ │ │ │ │ unit='cm/s', +│ │ │ │ │ │ array= +│ │ │ │ │ ), +│ │ │ │ │ starting_time=None, +│ │ │ │ │ timestamps=, +│ │ │ │ │ control=None, +│ │ │ │ │ control_description=None, +│ │ │ │ │ sync=None +│ │ │ │ ), +│ │ │ │ 'running_wheel_rotation': TimeSeries( +│ │ │ │ │ hdf5_path='/processing/running/running_wheel_rotation', +│ │ │ │ │ name='running_wheel_rotation', +│ │ │ │ │ description='no description', +│ │ │ │ │ comments='no comments', +│ │ │ │ │ data=TimeSeriesData( +│ │ │ │ │ │ hdf5_path='/processing/running/running_wheel_rotation/data', +│ │ │ │ │ │ object_id=None, +│ │ │ │ │ │ name='data', +│ │ │ │ │ │ conversion=1.0, +│ │ │ │ │ │ resolution=-1.0, +│ │ │ │ │ │ unit='radians', +│ │ │ │ │ │ array= +│ │ │ │ │ ), +│ │ │ │ │ starting_time=None, +│ │ │ │ │ timestamps=, +│ │ │ │ │ control=None, +│ │ │ │ │ control_description=None, +│ │ │ │ │ sync=None +│ │ │ │ ) +│ │ │ } +│ │ ), +│ │ 'stimulus': ProcessingModule( +│ │ │ hdf5_path='/processing/stimulus', +│ │ │ name='stimulus', +│ │ │ children={ +│ │ │ │ 'timestamps': TimeSeries( +│ │ │ │ │ hdf5_path='/processing/stimulus/timestamps', +│ │ │ │ │ name='timestamps', +│ │ │ │ │ description='no description', +│ │ │ │ │ comments='no comments', +│ │ │ │ │ data=TimeSeriesData( +│ │ │ │ │ │ hdf5_path='/processing/stimulus/timestamps/data', +│ │ │ │ │ │ object_id=None, +│ │ │ │ │ │ name='data', +│ │ │ │ │ │ conversion=1.0, +│ │ │ │ │ │ resolution=-1.0, +│ │ │ │ │ │ unit='s', +│ │ │ │ │ │ array= +│ │ │ │ │ ), +│ │ │ │ │ starting_time=None, +│ │ │ │ │ timestamps=, +│ │ │ │ │ control=None, +│ │ │ │ │ control_description=None, +│ │ │ │ │ sync=None +│ │ │ │ ) +│ │ │ } +│ │ ) +│ }, +│ stimulus=NWBFileStimulus( +│ │ hdf5_path=None, +│ │ object_id=None, +│ │ name='stimulus', +│ │ presentation={}, +│ │ templates={} +│ ), +│ general=NWBFileGeneral( +│ │ hdf5_path=None, +│ │ object_id=None, +│ │ name='general', +│ │ data_collection=None, +│ │ experiment_description=None, +│ │ experimenter=None, +│ │ institution='Allen Institute for Brain Science', +│ │ keywords=None, +│ │ lab=None, +│ │ notes=None, +│ │ pharmacology=None, +│ │ protocol=None, +│ │ related_publications=None, +│ │ session_id='760693773', +│ │ slices=None, +│ │ source_script=None, +│ │ stimulus='brain_observatory_1.1', +│ │ surgery=None, +│ │ virus=None, +│ │ nwb_container=[], +│ │ devices={ +│ │ │ 'probeA': EcephysProbe( +│ │ │ │ hdf5_path='/general/devices/probeA', +│ │ │ │ name='probeA', +│ │ │ │ description=None, +│ │ │ │ manufacturer=None, +│ │ │ │ sampling_rate=29999.9700560591, +│ │ │ │ probe_id=769322820 +│ │ │ ), +│ │ │ 'probeB': EcephysProbe( +│ │ │ │ hdf5_path='/general/devices/probeB', +│ │ │ │ name='probeB', +│ │ │ │ description=None, +│ │ │ │ manufacturer=None, +│ │ │ │ sampling_rate=29999.9195957425, +│ │ │ │ probe_id=769322824 +│ │ │ ), +│ │ │ 'probeC': EcephysProbe( +│ │ │ │ hdf5_path='/general/devices/probeC', +│ │ │ │ name='probeC', +│ │ │ │ description=None, +│ │ │ │ manufacturer=None, +│ │ │ │ sampling_rate=29999.9985048795, +│ │ │ │ probe_id=769322827 +│ │ │ ), +│ │ │ 'probeD': EcephysProbe( +│ │ │ │ hdf5_path='/general/devices/probeD', +│ │ │ │ name='probeD', +│ │ │ │ description=None, +│ │ │ │ manufacturer=None, +│ │ │ │ sampling_rate=29999.9228144047, +│ │ │ │ probe_id=769322829 +│ │ │ ), +│ │ │ 'probeE': EcephysProbe( +│ │ │ │ hdf5_path='/general/devices/probeE', +│ │ │ │ name='probeE', +│ │ │ │ description=None, +│ │ │ │ manufacturer=None, +│ │ │ │ sampling_rate=30000.0007890914, +│ │ │ │ probe_id=769322831 +│ │ │ ), +│ │ │ 'probeF': EcephysProbe( +│ │ │ │ hdf5_path='/general/devices/probeF', +│ │ │ │ name='probeF', +│ │ │ │ description=None, +│ │ │ │ manufacturer=None, +│ │ │ │ sampling_rate=30000.0428393552, +│ │ │ │ probe_id=769322833 +│ │ │ ) +│ │ }, +│ │ subject=EcephysSpecimen( +│ │ │ hdf5_path='/general/subject', +│ │ │ name='subject', +│ │ │ age='P110D', +│ │ │ date_of_birth=None, +│ │ │ description=None, +│ │ │ genotype='Sst-IRES-Cre/wt;Ai32(RCL-ChR2(H134R)_EYFP)/wt', +│ │ │ sex='F', +│ │ │ species='Mus musculus', +│ │ │ subject_id='738651046', +│ │ │ weight=None, +│ │ │ specimen_name='Sst-IRES-Cre;Ai32-406808', +│ │ │ age_in_days=110.0, +│ │ │ strain='C57BL/6J' +│ │ ), +│ │ extracellular_ephys=NWBFileGeneralExtracellularEphys( +│ │ │ hdf5_path=None, +│ │ │ object_id=None, +│ │ │ name='extracellular_ephys', +│ │ │ electrode_group=[ +│ │ │ │ EcephysElectrodeGroup( +│ │ │ │ │ hdf5_path='/general/extracellular_ephys/probeA', +│ │ │ │ │ name='probeA', +│ │ │ │ │ description='Ecephys Electrode Group', +│ │ │ │ │ location='See electrode locations', +│ │ │ │ │ position=None, +│ │ │ │ │ has_lfp_data=True, +│ │ │ │ │ probe_id=769322820, +│ │ │ │ │ lfp_sampling_rate=1249.998752335795 +│ │ │ │ ), +│ │ │ │ EcephysElectrodeGroup( +│ │ │ │ │ hdf5_path='/general/extracellular_ephys/probeB', +│ │ │ │ │ name='probeB', +│ │ │ │ │ description='Ecephys Electrode Group', +│ │ │ │ │ location='See electrode locations', +│ │ │ │ │ position=None, +│ │ │ │ │ has_lfp_data=True, +│ │ │ │ │ probe_id=769322824, +│ │ │ │ │ lfp_sampling_rate=1249.996649822605 +│ │ │ │ ), +│ │ │ │ EcephysElectrodeGroup( +│ │ │ │ │ hdf5_path='/general/extracellular_ephys/probeC', +│ │ │ │ │ name='probeC', +│ │ │ │ │ description='Ecephys Electrode Group', +│ │ │ │ │ location='See electrode locations', +│ │ │ │ │ position=None, +│ │ │ │ │ has_lfp_data=True, +│ │ │ │ │ probe_id=769322827, +│ │ │ │ │ lfp_sampling_rate=1249.999937703315 +│ │ │ │ ), +│ │ │ │ EcephysElectrodeGroup( +│ │ │ │ │ hdf5_path='/general/extracellular_ephys/probeD', +│ │ │ │ │ name='probeD', +│ │ │ │ │ description='Ecephys Electrode Group', +│ │ │ │ │ location='See electrode locations', +│ │ │ │ │ position=None, +│ │ │ │ │ has_lfp_data=True, +│ │ │ │ │ probe_id=769322829, +│ │ │ │ │ lfp_sampling_rate=1249.99678393353 +│ │ │ │ ), +│ │ │ │ EcephysElectrodeGroup( +│ │ │ │ │ hdf5_path='/general/extracellular_ephys/probeE', +│ │ │ │ │ name='probeE', +│ │ │ │ │ description='Ecephys Electrode Group', +│ │ │ │ │ location='See electrode locations', +│ │ │ │ │ position=None, +│ │ │ │ │ has_lfp_data=True, +│ │ │ │ │ probe_id=769322831, +│ │ │ │ │ lfp_sampling_rate=1250.000032878805 +│ │ │ │ ), +│ │ │ │ EcephysElectrodeGroup( +│ │ │ │ │ hdf5_path='/general/extracellular_ephys/probeF', +│ │ │ │ │ name='probeF', +│ │ │ │ │ description='Ecephys Electrode Group', +│ │ │ │ │ location='See electrode locations', +│ │ │ │ │ position=None, +│ │ │ │ │ has_lfp_data=True, +│ │ │ │ │ probe_id=769322833, +│ │ │ │ │ lfp_sampling_rate=1250.00178497313 +│ │ │ │ ) +│ │ │ ], +│ │ │ electrodes=NWBFileGeneralExtracellularEphysElectrodes( +│ │ │ │ hdf5_path=None, +│ │ │ │ name='electrodes', +│ │ │ │ colnames=None, +│ │ │ │ description=None, +│ │ │ │ vector_data=[], +│ │ │ │ vector_index=[], +│ │ │ │ x=[], +│ │ │ │ y=[], +│ │ │ │ z=[], +│ │ │ │ imp=[], +│ │ │ │ location=[], +│ │ │ │ filtering=[], +│ │ │ │ group=[], +│ │ │ │ group_name=[], +│ │ │ │ rel_x=[], +│ │ │ │ rel_y=[], +│ │ │ │ rel_z=[], +│ │ │ │ reference=[] +│ │ │ ) +│ │ ), +│ │ intracellular_ephys=None, +│ │ optogenetics={}, +│ │ optophysiology={} +│ ), +│ intervals={ +│ │ 'drifting_gratings_presentations': drifting_gratings_presentations( +│ │ │ hdf5_path='/intervals/drifting_gratings_presentations', +│ │ │ name='drifting_gratings_presentations', +│ │ │ colnames=array(['start_time', 'stop_time', 'stimulus_name', 'stimulus_block', +│ 'temporal_frequency', 'color', 'mask', 'opacity', 'phase', 'size', +│ 'units', 'stimulus_index', 'orientation', 'spatial_frequency', +│ 'contrast', 'tags', 'timeseries'], dtype=object), +│ │ │ description="Presentation times and stimuli details for 'drifting_gratings' stimuli", +│ │ │ id=dask.array, +│ │ │ start_time=dask.array, +│ │ │ stop_time=dask.array, +│ │ │ tags=, +│ │ │ tags_index=dask.array, +│ │ │ timeseries=, +│ │ │ timeseries_index=dask.array, +│ │ │ stimulus_name=, +│ │ │ stimulus_block=dask.array, +│ │ │ temporal_frequency=dask.array, +│ │ │ color=, +│ │ │ mask=, +│ │ │ opacity=dask.array, +│ │ │ phase=, +│ │ │ size=, +│ │ │ units=, +│ │ │ stimulus_index=dask.array, +│ │ │ orientation=dask.array, +│ │ │ spatial_frequency=, +│ │ │ contrast=dask.array, +│ │ │ vector_data=[], +│ │ │ vector_index=[] +│ │ ), +│ │ 'flashes_presentations': flashes_presentations( +│ │ │ hdf5_path='/intervals/flashes_presentations', +│ │ │ name='flashes_presentations', +│ │ │ colnames=array(['start_time', 'stop_time', 'stimulus_name', 'stimulus_block', +│ 'color', 'mask', 'opacity', 'phase', 'size', 'units', +│ 'stimulus_index', 'orientation', 'spatial_frequency', 'contrast', +│ 'tags', 'timeseries'], dtype=object), +│ │ │ description="Presentation times and stimuli details for 'flashes' stimuli", +│ │ │ id=dask.array, +│ │ │ start_time=dask.array, +│ │ │ stop_time=dask.array, +│ │ │ tags=, +│ │ │ tags_index=dask.array, +│ │ │ timeseries=, +│ │ │ timeseries_index=dask.array, +│ │ │ stimulus_name=, +│ │ │ stimulus_block=dask.array, +│ │ │ color=, +│ │ │ mask=, +│ │ │ opacity=dask.array, +│ │ │ phase=, +│ │ │ size=, +│ │ │ units=, +│ │ │ stimulus_index=dask.array, +│ │ │ orientation=dask.array, +│ │ │ spatial_frequency=, +│ │ │ contrast=dask.array, +│ │ │ vector_data=[], +│ │ │ vector_index=[] +│ │ ), +│ │ 'gabors_presentations': gabors_presentations( +│ │ │ hdf5_path='/intervals/gabors_presentations', +│ │ │ name='gabors_presentations', +│ │ │ colnames=array(['start_time', 'stop_time', 'stimulus_name', 'stimulus_block', +│ 'temporal_frequency', 'x_position', 'y_position', 'color', 'mask', +│ 'opacity', 'phase', 'size', 'units', 'stimulus_index', +│ 'orientation', 'spatial_frequency', 'contrast', 'tags', +│ 'timeseries'], dtype=object), +│ │ │ description="Presentation times and stimuli details for 'gabors' stimuli", +│ │ │ id=dask.array, +│ │ │ start_time=dask.array, +│ │ │ stop_time=dask.array, +│ │ │ tags=, +│ │ │ tags_index=dask.array, +│ │ │ timeseries=, +│ │ │ timeseries_index=dask.array, +│ │ │ stimulus_name=, +│ │ │ stimulus_block=dask.array, +│ │ │ temporal_frequency=dask.array, +│ │ │ x_position=dask.array, +│ │ │ y_position=dask.array, +│ │ │ color=, +│ │ │ mask=, +│ │ │ opacity=dask.array, +│ │ │ phase=, +│ │ │ size=, +│ │ │ units=, +│ │ │ stimulus_index=dask.array, +│ │ │ orientation=dask.array, +│ │ │ spatial_frequency=, +│ │ │ contrast=dask.array, +│ │ │ vector_data=[], +│ │ │ vector_index=[] +│ │ ), +│ │ 'natural_movie_one_presentations': natural_movie_one_presentations( +│ │ │ hdf5_path='/intervals/natural_movie_one_presentations', +│ │ │ name='natural_movie_one_presentations', +│ │ │ colnames=array(['start_time', 'stop_time', 'stimulus_name', 'stimulus_block', +│ 'color', 'opacity', 'size', 'units', 'stimulus_index', +│ 'orientation', 'frame', 'contrast', 'tags', 'timeseries'], +│ dtype=object), +│ │ │ description="Presentation times and stimuli details for 'natural_movie_one' stimuli", +│ │ │ id=dask.array, +│ │ │ start_time=dask.array, +│ │ │ stop_time=dask.array, +│ │ │ tags=, +│ │ │ tags_index=dask.array, +│ │ │ timeseries=, +│ │ │ timeseries_index=dask.array, +│ │ │ stimulus_name=, +│ │ │ stimulus_block=dask.array, +│ │ │ color=, +│ │ │ opacity=dask.array, +│ │ │ size=, +│ │ │ units=, +│ │ │ stimulus_index=dask.array, +│ │ │ orientation=dask.array, +│ │ │ frame=dask.array, +│ │ │ contrast=dask.array, +│ │ │ vector_data=[], +│ │ │ vector_index=[] +│ │ ), +│ │ 'natural_movie_three_presentations': natural_movie_three_presentations( +│ │ │ hdf5_path='/intervals/natural_movie_three_presentations', +│ │ │ name='natural_movie_three_presentations', +│ │ │ colnames=array(['start_time', 'stop_time', 'stimulus_name', 'stimulus_block', +│ 'color', 'opacity', 'size', 'units', 'stimulus_index', +│ 'orientation', 'frame', 'contrast', 'tags', 'timeseries'], +│ dtype=object), +│ │ │ description="Presentation times and stimuli details for 'natural_movie_three' stimuli", +│ │ │ id=dask.array, +│ │ │ start_time=dask.array, +│ │ │ stop_time=dask.array, +│ │ │ tags=, +│ │ │ tags_index=dask.array, +│ │ │ timeseries=, +│ │ │ timeseries_index=dask.array, +│ │ │ stimulus_name=, +│ │ │ stimulus_block=dask.array, +│ │ │ color=, +│ │ │ opacity=dask.array, +│ │ │ size=, +│ │ │ units=, +│ │ │ stimulus_index=dask.array, +│ │ │ orientation=dask.array, +│ │ │ frame=dask.array, +│ │ │ contrast=dask.array, +│ │ │ vector_data=[], +│ │ │ vector_index=[] +│ │ ), +│ │ 'natural_scenes_presentations': natural_scenes_presentations( +│ │ │ hdf5_path='/intervals/natural_scenes_presentations', +│ │ │ name='natural_scenes_presentations', +│ │ │ colnames=array(['start_time', 'stop_time', 'stimulus_name', 'stimulus_block', +│ 'stimulus_index', 'frame', 'tags', 'timeseries'], dtype=object), +│ │ │ description="Presentation times and stimuli details for 'natural_scenes' stimuli", +│ │ │ id=dask.array, +│ │ │ start_time=dask.array, +│ │ │ stop_time=dask.array, +│ │ │ tags=, +│ │ │ tags_index=dask.array, +│ │ │ timeseries=, +│ │ │ timeseries_index=dask.array, +│ │ │ stimulus_name=, +│ │ │ stimulus_block=dask.array, +│ │ │ stimulus_index=dask.array, +│ │ │ frame=dask.array, +│ │ │ vector_data=[], +│ │ │ vector_index=[] +│ │ ), +│ │ 'spontaneous_presentations': spontaneous_presentations( +│ │ │ hdf5_path='/intervals/spontaneous_presentations', +│ │ │ name='spontaneous_presentations', +│ │ │ colnames=array(['start_time', 'stop_time', 'stimulus_name', 'tags', 'timeseries'], +│ dtype=object), +│ │ │ description="Presentation times and stimuli details for 'spontaneous' stimuli", +│ │ │ id=dask.array, +│ │ │ start_time=dask.array, +│ │ │ stop_time=dask.array, +│ │ │ tags=, +│ │ │ tags_index=dask.array, +│ │ │ timeseries=, +│ │ │ timeseries_index=dask.array, +│ │ │ stimulus_name=, +│ │ │ vector_data=[], +│ │ │ vector_index=[] +│ │ ), +│ │ 'static_gratings_presentations': static_gratings_presentations( +│ │ │ hdf5_path='/intervals/static_gratings_presentations', +│ │ │ name='static_gratings_presentations', +│ │ │ colnames=array(['start_time', 'stop_time', 'stimulus_name', 'stimulus_block', +│ 'color', 'mask', 'opacity', 'phase', 'size', 'units', +│ 'stimulus_index', 'orientation', 'spatial_frequency', 'contrast', +│ 'tags', 'timeseries'], dtype=object), +│ │ │ description="Presentation times and stimuli details for 'static_gratings' stimuli", +│ │ │ id=dask.array, +│ │ │ start_time=dask.array, +│ │ │ stop_time=dask.array, +│ │ │ tags=, +│ │ │ tags_index=dask.array, +│ │ │ timeseries=, +│ │ │ timeseries_index=dask.array, +│ │ │ stimulus_name=, +│ │ │ stimulus_block=dask.array, +│ │ │ color=, +│ │ │ mask=, +│ │ │ opacity=dask.array, +│ │ │ phase=, +│ │ │ size=, +│ │ │ units=, +│ │ │ stimulus_index=dask.array, +│ │ │ orientation=dask.array, +│ │ │ spatial_frequency=dask.array, +│ │ │ contrast=dask.array, +│ │ │ vector_data=[], +│ │ │ vector_index=[] +│ │ ) +│ }, +│ units=units( +│ │ hdf5_path='/units', +│ │ name='units', +│ │ colnames=array(['quality', 'amplitude_cutoff', 'recovery_slope', 'cluster_id', +│ 'spread', 'velocity_below', 'd_prime', 'nn_miss_rate', +│ 'isolation_distance', 'silhouette_score', 'waveform_halfwidth', +│ 'PT_ratio', 'cumulative_drift', 'isi_violations', 'presence_ratio', +│ 'snr', 'l_ratio', 'amplitude', 'repolarization_slope', +│ 'local_index', 'velocity_above', 'nn_hit_rate', 'peak_channel_id', +│ 'waveform_duration', 'firing_rate', 'max_drift', 'spike_times', +│ 'spike_amplitudes', 'waveform_mean'], dtype=object), +│ │ description='', +│ │ id=dask.array, +│ │ spike_times_index=dask.array, +│ │ spike_times=dask.array, +│ │ waveform_mean=dask.array, +│ │ quality=, +│ │ amplitude_cutoff=dask.array, +│ │ recovery_slope=dask.array, +│ │ cluster_id=dask.array, +│ │ spread=dask.array, +│ │ velocity_below=dask.array, +│ │ d_prime=dask.array, +│ │ nn_miss_rate=dask.array, +│ │ isolation_distance=dask.array, +│ │ silhouette_score=dask.array, +│ │ waveform_halfwidth=dask.array, +│ │ PT_ratio=dask.array, +│ │ cumulative_drift=dask.array, +│ │ isi_violations=dask.array, +│ │ presence_ratio=dask.array, +│ │ snr=dask.array, +│ │ l_ratio=dask.array, +│ │ amplitude=dask.array, +│ │ repolarization_slope=dask.array, +│ │ local_index=dask.array, +│ │ velocity_above=dask.array, +│ │ nn_hit_rate=dask.array, +│ │ peak_channel_id=dask.array, +│ │ waveform_duration=dask.array, +│ │ firing_rate=dask.array, +│ │ max_drift=dask.array, +│ │ spike_amplitudes=dask.array, +│ │ vector_data=[], +│ │ vector_index=[], +│ │ obs_intervals_index=None, +│ │ obs_intervals=None, +│ │ electrodes_index=None, +│ │ electrodes=None, +│ │ electrode_group=[], +│ │ waveform_sd=None +│ ) +) \ No newline at end of file diff --git a/nwb_linkml/src/nwb_linkml/generators/pydantic.py b/nwb_linkml/src/nwb_linkml/generators/pydantic.py index 245af71..2fd1d8e 100644 --- a/nwb_linkml/src/nwb_linkml/generators/pydantic.py +++ b/nwb_linkml/src/nwb_linkml/generators/pydantic.py @@ -76,7 +76,7 @@ def default_template(pydantic_ver: str = "2", extra_classes:Optional[List[Type[B from __future__ import annotations from datetime import datetime, date from enum import Enum -from typing import Dict, Optional, Any, Union, ClassVar, Annotated, TypeVar, List +from typing import Dict, Optional, Any, Union, ClassVar, Annotated, TypeVar, List, TYPE_CHECKING from pydantic import BaseModel as BaseModel, Field""" if pydantic_ver == '2': template += """ @@ -90,6 +90,8 @@ if sys.version_info >= (3, 8): from typing import Literal else: from typing_extensions import Literal +if TYPE_CHECKING: + import numpy as np {% for import_module, import_classes in imports.items() %} from {{ import_module }} import ( @@ -137,6 +139,22 @@ class ConfiguredBaseModel(BaseModel): pass {%- endif -%} """ + ### Getitem + template += """ + + def __getitem__(self, i: slice|int) -> 'np.ndarray': + if hasattr(self, 'array'): + return self.array[i] + else: + return super().__getitem__(i) + + def __setitem__(self, i: slice|int, value: Any): + if hasattr(self, 'array'): + self.array[i] = value + else: + super().__setitem__(i, value) + """ + ### Extra classes if extra_classes is not None: template += """{{ '\n\n' }}""" diff --git a/nwb_linkml/src/nwb_linkml/io/__init__.py b/nwb_linkml/src/nwb_linkml/io/__init__.py index 3b8d330..6ccbf79 100644 --- a/nwb_linkml/src/nwb_linkml/io/__init__.py +++ b/nwb_linkml/src/nwb_linkml/io/__init__.py @@ -1 +1,2 @@ -from nwb_linkml.io import schema \ No newline at end of file +from nwb_linkml.io import schema +from nwb_linkml.io.hdf5 import HDF5IO \ No newline at end of file diff --git a/nwb_linkml/tests/test_generators/test_generator_pydantic.py b/nwb_linkml/tests/test_generators/test_generator_pydantic.py index 3dcb1ba..73624f9 100644 --- a/nwb_linkml/tests/test_generators/test_generator_pydantic.py +++ b/nwb_linkml/tests/test_generators/test_generator_pydantic.py @@ -270,3 +270,17 @@ def test_namespace(imported_schema): assert hasattr(ns, classname) if imported_schema['split']: assert getattr(ns, classname).__module__ == modname + +def test_get_set_item(imported_schema): + """We can get and set without explicitly addressing array""" + cls = imported_schema['core'].MainTopLevel( + array=np.array([[1,2,3],[4,5,6]]) + ) + cls[0] = 50 + assert (cls[0] == 50).all() + assert (cls.array[0] == 50).all() + + cls[1,1] = 100 + assert cls[1,1] == 100 + assert cls.array[1,1] == 100 + diff --git a/poetry.lock b/poetry.lock index 0683324..7d4545b 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2075,6 +2075,22 @@ files = [ {file = "ruamel.yaml.clib-0.2.8.tar.gz", hash = "sha256:beb2e0404003de9a4cab9753a8805a8fe9320ee6673136ed7f04255fe60bb512"}, ] +[[package]] +name = "setuptools" +version = "68.2.2" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "setuptools-68.2.2-py3-none-any.whl", hash = "sha256:b454a35605876da60632df1a60f736524eb73cc47bbc9f3f1ef1b644de74fd2a"}, + {file = "setuptools-68.2.2.tar.gz", hash = "sha256:4ac1475276d2f1c48684874089fefcd83bd7162ddaafb81fac866ba0db282a87"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-hoverxref (<2)", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] + [[package]] name = "shexjsg" version = "0.8.2" @@ -2262,6 +2278,26 @@ theme-pydata = ["pydata-sphinx-theme (>=0.13.0,<0.14.0)"] theme-rtd = ["sphinx-rtd-theme (>=1.0,<2.0)"] theme-sbt = ["sphinx-book-theme (>=1.0,<2.0)"] +[[package]] +name = "sphinx-togglebutton" +version = "0.3.2" +description = "Toggle page content and collapse admonitions in Sphinx." +optional = false +python-versions = "*" +files = [ + {file = "sphinx-togglebutton-0.3.2.tar.gz", hash = "sha256:ab0c8b366427b01e4c89802d5d078472c427fa6e9d12d521c34fa0442559dc7a"}, + {file = "sphinx_togglebutton-0.3.2-py3-none-any.whl", hash = "sha256:9647ba7874b7d1e2d43413d8497153a85edc6ac95a3fea9a75ef9c1e08aaae2b"}, +] + +[package.dependencies] +docutils = "*" +setuptools = "*" +sphinx = "*" +wheel = "*" + +[package.extras] +sphinx = ["matplotlib", "myst-nb", "numpy", "sphinx-book-theme", "sphinx-design", "sphinx-examples"] + [[package]] name = "sphinxcontrib-applehelp" version = "1.0.7" @@ -2610,6 +2646,20 @@ files = [ docs = ["furo", "sphinx", "sphinx-copybutton", "sphinx-inline-tabs", "sphinx-notfound-page", "sphinxext-opengraph"] tests = ["pytest", "pytest-cov"] +[[package]] +name = "wheel" +version = "0.41.2" +description = "A built-package format for Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "wheel-0.41.2-py3-none-any.whl", hash = "sha256:75909db2664838d015e3d9139004ee16711748a52c8f336b52882266540215d8"}, + {file = "wheel-0.41.2.tar.gz", hash = "sha256:0c5ac5ff2afb79ac23ab82bab027a0be7b5dbcf2e54dc50efe4bf507de1f7985"}, +] + +[package.extras] +test = ["pytest (>=6.0.0)", "setuptools (>=65)"] + [[package]] name = "wrapt" version = "1.15.0" @@ -2712,4 +2762,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.11,<3.13" -content-hash = "5dc10e6c1e6ae285bc09c270d0e8015f5705dc53a259096a6b2054e37392da34" +content-hash = "ff4389164e6c41667acfe292fb4898303c356cf07d1dfb0d3ac6d6a29da8a738" diff --git a/pyproject.toml b/pyproject.toml index 566095c..a2f86fa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,6 +21,7 @@ sphinx-autobuild = "^2021.3.14" nwb-linkml = { path = './nwb_linkml', develop = true } nwb_schema_language = { path = './nwb_schema_language', develop = true } sphinx-design = "^0.5.0" +sphinx-togglebutton = "^0.3.2" [build-system]