Skip to content

Commit

Permalink
Merge branch 'dev' into fix/optical-series-optional-fields
Browse files Browse the repository at this point in the history
  • Loading branch information
rly authored Feb 20, 2025
2 parents 1b3fc9a + f3b3306 commit fa59027
Show file tree
Hide file tree
Showing 21 changed files with 206 additions and 5 deletions.
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ docs/build/
docs/source/pynwb.*.rst


# Virtual Environment
venv/
env/
ENV/

# setuptools
build/
dist/
Expand Down Expand Up @@ -81,4 +86,4 @@ _version.py
.core_typemap_version
core_typemap.pkl

venv/
venv/
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## PyNWB 3.0.0 (Upcoming)

### Enhancements and minor changes
- Added `__all__` to modules. @bendichter [#2021](https://github.com/NeurodataWithoutBorders/pynwb/pull/2021)
- Added `pynwb.read_nwb` convenience method to simplify reading an NWBFile written with any backend @h-mayorquin [#1994](https://github.com/NeurodataWithoutBorders/pynwb/pull/1994)

### Bug fixes
Expand Down
38 changes: 38 additions & 0 deletions docs/gallery/advanced_io/plot_editing.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,41 @@
"synthetic_timeseries_renamed",
"/analysis/synthetic_timeseries_renamed",
)

##############################################
# Adding datasets to existing groups
# ----------------------------------
# You can add new datasets to existing groups using PyNWB by calling ``set_modified()``.
# Here's an example of adding a genotype to a Subject:

from pynwb import NWBFile, NWBHDF5IO
from pynwb.file import Subject

# First, let's create a file with a Subject that is missing the genotype, which is optional
nwbfile = NWBFile(
session_description="example file with subject",
identifier="EXAMPLE_ID",
session_start_time=datetime.now(tzlocal()),
session_id="LONELYMTN",
subject=Subject(
subject_id="mouse001",
species="Mus musculus",
age="P30D",
)
)

with NWBHDF5IO("test_edit3.nwb", "w") as io:
io.write(nwbfile)

# Now add the genotype using PyNWB and set_modified()
with NWBHDF5IO("test_edit3.nwb", "a") as io:
nwbfile = io.read()
nwbfile.subject.genotype = "Sst-IRES-Cre"
nwbfile.subject.set_modified() # Required to mark the container as modified
io.write(nwbfile)

# Verify the dataset was added
with NWBHDF5IO("test_edit3.nwb", "r") as io:
nwbfile = io.read()
print(f"Subject genotype: {nwbfile.subject.genotype}")
# Output: Subject genotype: Sst-IRES-Cre
3 changes: 3 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
autoclass_content = 'both'
autodoc_docstring_signature = True
autodoc_member_order = 'bysource'
autodoc_default_options = {
'ignore-module-all': True, # Continue documenting classes not in __all__
}

# -- General configuration -----------------------------------------------------

Expand Down
26 changes: 26 additions & 0 deletions src/pynwb/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,32 @@ def read_nwb(**kwargs):
from hdmf.data_utils import DataChunkIterator # noqa: F401,E402
from hdmf.backends.hdf5 import H5DataIO # noqa: F401,E402

__all__ = [
# Functions
'get_type_map',
'get_manager',
'load_namespaces',
'available_namespaces',
'register_class',
'register_map',
'get_class',
'load_type_config',
'get_loaded_type_config',
'unload_type_config',
'read_nwb',
'get_nwbfile_version',

# Classes
'NWBHDF5IO',
'NWBContainer',
'NWBData',
'TimeSeries',
'ProcessingModule',
'NWBFile',
'DataChunkIterator',
'H5DataIO'
]



from ._due import due, BibTeX # noqa: E402
Expand Down
11 changes: 11 additions & 0 deletions src/pynwb/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@
from .core import NWBDataInterface, MultiContainerInterface, NWBData


__all__ = [
'ProcessingModule',
'TimeSeries',
'Image',
'ImageReferences',
'Images',
'TimeSeriesReferenceVectorData',
'TimeSeriesReference'
]


@register_class('ProcessingModule', CORE_NAMESPACE)
class ProcessingModule(MultiContainerInterface):
""" Processing module. This is a container for one or more containers
Expand Down
11 changes: 11 additions & 0 deletions src/pynwb/behavior.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,17 @@
from .misc import IntervalSeries
from .base import TimeSeries

__all__ = [
'SpatialSeries',
'BehavioralEpochs',
'BehavioralEvents',
'BehavioralTimeSeries',
'PupilTracking',
'EyeTracking',
'CompassDirection',
'Position'
]


@register_class('SpatialSeries', CORE_NAMESPACE)
class SpatialSeries(TimeSeries):
Expand Down
11 changes: 11 additions & 0 deletions src/pynwb/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,17 @@
from pynwb import get_type_map


__all__ = [
'NWBMixin',
'NWBContainer',
'NWBDataInterface',
'NWBData',
'ScratchData',
'NWBTable',
'MultiContainerInterface'
]


def _not_parent(arg):
return arg['name'] != 'parent'

Expand Down
1 change: 1 addition & 0 deletions src/pynwb/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from . import register_class, CORE_NAMESPACE
from .core import NWBContainer

__all__ = ['Device']

@register_class('Device', CORE_NAMESPACE)
class Device(NWBContainer):
Expand Down
10 changes: 10 additions & 0 deletions src/pynwb/ecephys.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@
from .core import NWBContainer, NWBDataInterface, MultiContainerInterface
from .device import Device

__all__ = [
'ElectrodeGroup',
'ElectricalSeries',
'SpikeEventSeries',
'EventDetection',
'LFP',
'FilteredEphys',
'FeatureExtraction'
]


@register_class('ElectrodeGroup', CORE_NAMESPACE)
class ElectrodeGroup(NWBContainer):
Expand Down
1 change: 1 addition & 0 deletions src/pynwb/epoch.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from . import register_class, CORE_NAMESPACE
from .base import TimeSeries, TimeSeriesReferenceVectorData, TimeSeriesReference

__all__ = ['TimeIntervals']

@register_class('TimeIntervals', CORE_NAMESPACE)
class TimeIntervals(DynamicTable):
Expand Down
10 changes: 10 additions & 0 deletions src/pynwb/file.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@
from .core import NWBContainer, NWBDataInterface, MultiContainerInterface, ScratchData, LabelledDict


__all__ = [
'LabMetaData',
'Subject',
'NWBFile',
'ElectrodeTable',
'TrialTable',
'InvalidTimesTable'
]


def _not_parent(arg):
return arg['name'] != 'parent'

Expand Down
18 changes: 18 additions & 0 deletions src/pynwb/icephys.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,24 @@
from .core import NWBContainer
from .device import Device

__all__ = [
'IntracellularElectrode',
'PatchClampSeries',
'CurrentClampSeries',
'IZeroClampSeries',
'CurrentClampStimulusSeries',
'VoltageClampSeries',
'VoltageClampStimulusSeries',
'IntracellularElectrodesTable',
'IntracellularStimuliTable',
'IntracellularResponsesTable',
'IntracellularRecordingsTable',
'SimultaneousRecordingsTable',
'SequentialRecordingsTable',
'RepetitionsTable',
'ExperimentalConditionsTable'
]


def ensure_unit(self, name, current_unit, unit, nwb_version):
"""A helper to ensure correct unit used.
Expand Down
10 changes: 10 additions & 0 deletions src/pynwb/image.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,16 @@
from .device import Device


__all__ = [
'ImageSeries',
'IndexSeries',
'OpticalSeries',
'GrayscaleImage',
'RGBImage',
'RGBAImage'
]


@register_class('ImageSeries', CORE_NAMESPACE)
class ImageSeries(TimeSeries):
'''
Expand Down
7 changes: 7 additions & 0 deletions src/pynwb/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,13 @@
from .ecephys import ElectrodeGroup
from hdmf.common import DynamicTable, DynamicTableRegion

__all__ = [
'AnnotationSeries',
'AbstractFeatureSeries',
'IntervalSeries',
'Units',
'DecompositionSeries'
]

@register_class('AnnotationSeries', CORE_NAMESPACE)
class AnnotationSeries(TimeSeries):
Expand Down
4 changes: 4 additions & 0 deletions src/pynwb/ogen.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
from .core import NWBContainer
from .device import Device

__all__ = [
'OptogeneticStimulusSite',
'OptogeneticSeries'
]

@register_class('OptogeneticStimulusSite', CORE_NAMESPACE)
class OptogeneticStimulusSite(NWBContainer):
Expand Down
14 changes: 14 additions & 0 deletions src/pynwb/ophys.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,20 @@
from .core import NWBContainer, MultiContainerInterface, NWBDataInterface
from .device import Device

__all__ = [
'OpticalChannel',
'ImagingPlane',
'OnePhotonSeries',
'TwoPhotonSeries',
'CorrectedImageStack',
'MotionCorrection',
'PlaneSegmentation',
'ImageSegmentation',
'RoiResponseSeries',
'DfOverF',
'Fluorescence'
]


@register_class('OpticalChannel', CORE_NAMESPACE)
class OpticalChannel(NWBContainer):
Expand Down
1 change: 1 addition & 0 deletions src/pynwb/resources.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from . import get_type_map as tm
from hdmf.utils import docval, get_docval

__all__ = ['HERD']

class HERD(hdmf_HERD):
"""
Expand Down
13 changes: 13 additions & 0 deletions src/pynwb/spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,19 @@
from . import CORE_NAMESPACE


__all__ = [
'NWBRefSpec',
'NWBAttributeSpec',
'NWBLinkSpec',
'NWBDtypeSpec',
'NWBDatasetSpec',
'NWBGroupSpec',
'NWBNamespace',
'NWBNamespaceBuilder',
'export_spec' # Re-exported from hdmf.spec.write
]


def __swap_inc_def(cls):
args = get_docval(cls.__init__)
clsname = 'NWB%s' % cls.__name__
Expand Down
8 changes: 4 additions & 4 deletions src/pynwb/testing/icephys_testutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@ def create_icephys_testfile(filename=None, add_custom_columns=True, randomize_da
:param randomize_data: Randomize data values in the stimulus and response
:type randomize_data: bool
:returns: NWBFile object with icephys data created for writing. NOTE: If filename is provided then
the file is written to disk, but the function does not read the file back. If
you want to use the file from disk then you will need to read it with NWBHDF5IO.
:rtype: NWBFile
:returns: :py:class:`~pynwb.file.NWBFile` object with icephys data created for writing. NOTE: If filename is
provided then the file is written to disk, but the function does not read the file back. If
you want to use the file from disk then you will need to read it with :py:class:`~pynwb.NWBHDF5IO`.
:rtype: :py:class:`~pynwb.file.NWBFile`
"""
nwbfile = NWBFile(
session_description='my first synthetic recording',
Expand Down
6 changes: 6 additions & 0 deletions src/pynwb/validate.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@
from pynwb.spec import NWBDatasetSpec, NWBGroupSpec, NWBNamespace


__all__ = [
'validate',
'get_cached_namespaces_to_validate'
]


def _print_errors(validation_errors: list):
if validation_errors:
print(" - found the following errors:", file=sys.stderr)
Expand Down

0 comments on commit fa59027

Please sign in to comment.