Note
Go to the end to download the full example code.
Adding/Removing Containers from an NWB File¶
This tutorial explains how to add and remove containers from an existing NWB file and either write the data back to the same file or export the data to a new file.
Adding objects to an NWB file in read/write mode¶
PyNWB supports adding container objects to an existing NWB file - that is, reading data from an NWB file, adding a
container object, such as a new TimeSeries
object, and writing the modified
NWBFile
back to the same file path on disk. To do so:
open the file with an
NWBHDF5IO
object in read/write mode (mode='r+'
ormode='a'
)read the
NWBFile
add container objects to the
NWBFile
object
For example:
import datetime
import numpy as np
from pynwb import NWBHDF5IO, NWBFile, TimeSeries
# first, write a test NWB file
nwbfile = NWBFile(
session_description="demonstrate adding to an NWB file",
identifier="NWB123",
session_start_time=datetime.datetime.now(),
)
filename = "nwbfile.nwb"
with NWBHDF5IO(filename, "w") as io:
io.write(nwbfile)
# open the NWB file in r+ mode
with NWBHDF5IO(filename, "r+") as io:
read_nwbfile = io.read()
# create a TimeSeries and add it to the file under the acquisition group
data = list(range(100, 200, 10))
timestamps = np.arange(10, dtype=float)
test_ts = TimeSeries(
name="test_timeseries", data=data, unit="m", timestamps=timestamps
)
read_nwbfile.add_acquisition(test_ts)
# write the modified NWB file
io.write(read_nwbfile)
# confirm the file contains the new TimeSeries in acquisition
with NWBHDF5IO(filename, "r") as io:
read_nwbfile = io.read()
print(read_nwbfile)
Note
You cannot remove objects from an NWB file using the above method.
Modifying an NWB file in this way has limitations. The destination file path must be the same as the source
file path, and it is not possible to remove objects from an NWB file. You can use the
NWBHDF5IO.export
method, detailed below, to modify an NWB file in these ways.
Exporting a written NWB file to a new file path¶
Use the NWBHDF5IO.export
method to read data from an existing NWB file,
modify the data, and write the modified data to a new file path. Modifications to the data can be additions or
removals of objects, such as TimeSeries
objects. This is especially useful if you
have raw data and processed data in the same NWB file and you want to create a new NWB file with all the contents of
the original file except for the raw data for sharing with collaborators.
To remove existing containers, use the pop
method on any
LabelledDict
object, such as NWBFile.acquisition
, NWBFile.processing
,
NWBFile.analysis
, NWBFile.processing
, NWBFile.scratch
, NWBFile.devices
, NWBFile.stimulus
,
NWBFile.stimulus_template
, NWBFile.electrode_groups
, NWBFile.imaging_planes
,
NWBFile.icephys_electrodes
, NWBFile.ogen_sites
, NWBFile.lab_meta_data
,
and ProcessingModule
objects.
For example:
# first, create a test NWB file with a TimeSeries in the acquisition group
nwbfile = NWBFile(
session_description="demonstrate export of an NWB file",
identifier="NWB123",
session_start_time=datetime.datetime.now(),
)
data1 = list(range(100, 200, 10))
timestamps1 = np.arange(10, dtype=float)
test_ts1 = TimeSeries(
name="test_timeseries1", data=data1, unit="m", timestamps=timestamps1
)
nwbfile.add_acquisition(test_ts1)
# then, create a processing module for processed behavioral data
nwbfile.create_processing_module(
name="behavior", description="processed behavioral data"
)
data2 = list(range(100, 200, 10))
timestamps2 = np.arange(10, dtype=float)
test_ts2 = TimeSeries(
name="test_timeseries2", data=data2, unit="m", timestamps=timestamps2
)
nwbfile.processing["behavior"].add(test_ts2)
# write these objects to an NWB file
filename = "nwbfile.nwb"
with NWBHDF5IO(filename, "w") as io:
io.write(nwbfile)
# read the written file
export_filename = "exported_nwbfile.nwb"
with NWBHDF5IO(filename, mode="r") as read_io:
read_nwbfile = read_io.read()
# add a new TimeSeries to the behavior processing module
data3 = list(range(100, 200, 10))
timestamps3 = np.arange(10, dtype=float)
test_ts3 = TimeSeries(
name="test_timeseries3", data=data3, unit="m", timestamps=timestamps3
)
read_nwbfile.processing["behavior"].add(test_ts3)
# use the pop method to remove the original TimeSeries from the acquisition group
read_nwbfile.acquisition.pop("test_timeseries1")
# use the pop method to remove a TimeSeries from a processing module
read_nwbfile.processing["behavior"].data_interfaces.pop("test_timeseries2")
# call the export method to write the modified NWBFile instance to a new file path.
# the original file is not modified
with NWBHDF5IO(export_filename, mode="w") as export_io:
export_io.export(src_io=read_io, nwbfile=read_nwbfile)
# confirm the exported file does not contain TimeSeries with names 'test_timeseries1' or 'test_timeseries2'
# but does contain a new TimeSeries in processing['behavior'] with name 'test_timeseries3'
with NWBHDF5IO(export_filename, "r") as io:
read_nwbfile = io.read()
print(read_nwbfile)
print(read_nwbfile.processing["behavior"])
Note
TimeIntervals
objects, such as NWBFile.epochs
, NWBFile.trials
,
NWBFile.invalid_times
, and custom TimeIntervals
objects cannot be
removed (popped) from NWBFile.intervals
.
Warning
Removing an object from an NWBFile may break links and references within the file and across files.
This is analogous to having shortcuts/aliases to a file on your filesystem and then deleting the file.
Extra caution should be taken when removing heavily referenced items such as
Device
objects,
ElectrodeGroup
objects, the electrodes table, and the
PlaneSegmentation
table.
Exporting with new object IDs¶
When exporting a read NWB file to a new file path, the object IDs within the original NWB file will be copied to the
new file. To make the exported NWB file contain a new set of object IDs, call
generate_new_id
on your NWBFile
object.
This will generate a new object ID for the NWBFile
object and all of the objects within
the NWB file.
export_filename = "exported_nwbfile.nwb"
with NWBHDF5IO(filename, mode="r") as read_io:
read_nwbfile = read_io.read()
read_nwbfile.generate_new_id()
with NWBHDF5IO(export_filename, mode="w") as export_io:
export_io.export(src_io=read_io, nwbfile=read_nwbfile)
For more information about the export functionality, see Exporting NWB files
and the PyNWB documentation for NWBHDF5IO.export
.
For more information about editing a file in place, see Editing NWB files.