Tutorial 4 - NWB Conversion

Neurodata without borders (NWB) is the data standard that we employ for data storage, packaging and sharing. More information about the NWB project can be found here: https://pynwb.readthedocs.io/en/stable/index.html

We have created some basic functionality to package and store imaging+ data into NWB files.

When generated here, the NWB files will automatically store: - Raw imaging data - Imaging microscope parameters - Time series data channels - ROIs and their extracted raw Flu array (if available for imaging+ trial)

These NWB files can be further modified according to NWB specifications and methods. Please refer to the PyNWB documentation for further additions according to your needs.

Below, we demonstrate how to generate a NWB file from an existing imaging+ data object. Note that one .nwb file is created for one imaging trial.

none
[2]:
ipython3
# import necessary modules
from pynwb.file import Subject
from imagingplus.utils.io import import_obj
from imagingplus.utils import nwb

imported imagingplus successfully
        version: 0.2-beta

none
[2]:
ipython3
# setup a Subject corresponding to the imaging trial
subject = Subject(age='P60D', subject_id='HF113',
                  genotype='CamkIIa-GCaMP6s/Niell'
                  )

# load up imaging trial
expobj = import_obj(pkl_path='/mnt/qnap_share/Data/imagingplus-example/imagingplus-test-analysis/HF113_analysis.pkl')
trialobj = expobj.load_trial(expobj.trialIDs[0])


# set some additional metadata required for generating NWB files.
expobj.experimenter = 'P. Shah'
expobj.lab = 'Packer Lab'
expobj.institution = 'University of Oxford'
trialobj.optical_channel_name = 'GCaMP imaging channel'

|- Loaded imagingplus.Experiment object (expID: HF113)agingplus-test-analysis/HF113_analysis.pkl ...


|- Loaded 'HF113 t-001 (TwoPhotonImagingTrial experimental object)'t-analysis/2021-01-31_t-001.pkl ...

none
[3]:
ipython3
# create the nwb file
inwb = nwb.newImagingNWB(expobj=expobj, nwb_subject=subject, trialobj=trialobj, save=True, add_raw_tiff=True, indicator='GCaMP6s')

# options: set `add_raw_tiff` = False to skip adding the raw imaging tiffstack to the new NWB file.
# options: set `save` = False to skip saving the new NWB file.
[NWB processing]: Adding 2photon imaging series to nwb file ...
[NWB processing]: Adding temporal series to nwb file ...

         ** Saving nwb file to: /mnt/qnap_share/Data/imagingplus-example/imagingplus-test-analysis/2021-01-31_t-001.nwb

The NWB file will be saved by default in the same location as the imaging+ analysis object.

To read in a previously collected NWB file, use the readImagingNWB() function from the nwb module.

none
[3]:
ipython3
nwbfilepath = '/mnt/qnap_share/Data/imagingplus-example/imagingplus-test-analysis/2021-01-31_t-001.nwb'

enwb = nwb.readImagingNWB(filename=nwbfilepath)

print(enwb)
[NWB processing]: Reading NWB file from:
         /mnt/qnap_share/Data/imagingplus-example/imagingplus-test-analysis/2021-01-31_t-001.nwb
root pynwb.file.NWBFile at 0x139712757930928
Fields:
  acquisition: {
    ImagingTrial <class 'pynwb.ophys.TwoPhotonSeries'>,
    frame_clock <class 'pynwb.base.TimeSeries'>,
    opto_loopback <class 'pynwb.base.TimeSeries'>,
    shutter_loopback <class 'pynwb.base.TimeSeries'>,
    voltage <class 'pynwb.base.TimeSeries'>
  }
  devices: {
    Bruker 2pPlus <class 'pynwb.device.Device'>
  }
  experimenter: ['P. Shah']
  file_create_date: [datetime.datetime(2022, 10, 21, 17, 5, 6, 732531, tzinfo=tzlocal())]
  identifier: HF113
  imaging_planes: {
    Plane 0 <class 'pynwb.ophys.ImagingPlane'>
  }
  institution: University of Oxford
  lab: Packer Lab
  processing: {
    Pre-processed imaging data <class 'pynwb.base.ProcessingModule'>
  }
  session_description: two photon imaging + LFP dataset
  session_start_time: 2022-10-21 17:05:06.732041+00:00
  subject: subject pynwb.file.Subject at 0x139712760172704
Fields:
  age: P60D
  genotype: CamkIIa-GCaMP6s/Niell
  subject_id: HF113

  timestamps_reference_time: 2022-10-21 17:05:06.732041+00:00

Note

Saving a NWB file: Oddly, once an NWB file is saved, it is difficult to change the location of the NWB file. For example, NWB doesn’t allow the following:

none
[11]:
ipython3
from pynwb import NWBHDF5IO
path = '/mnt/qnap_share/Data/imagingplus-example/imagingplus-test-analysis/2021-01-31_t-001_copy.nwb'
with NWBHDF5IO(path, 'w') as io:
    io.write(enwb)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
/tmp/ipykernel_50119/297517569.py in <module>
      2 path = '/mnt/qnap_share/Data/imagingplus-example/imagingplus-test-analysis/2021-01-31_t-001_copy.nwb'
      3 with NWBHDF5IO(path, 'w') as io:
----> 4     io.write(enwb)

~/anaconda3/envs/plipy39/lib/python3.9/site-packages/hdmf/utils.py in func_call(*args, **kwargs)
    643             def func_call(*args, **kwargs):
    644                 pargs = _check_args(args, kwargs)
--> 645                 return func(args[0], **pargs)
    646         else:
    647             def func_call(*args, **kwargs):

~/anaconda3/envs/plipy39/lib/python3.9/site-packages/hdmf/backends/hdf5/h5tools.py in write(self, **kwargs)
    356
    357         cache_spec = popargs('cache_spec', kwargs)
--> 358         super().write(**kwargs)
    359         if cache_spec:
    360             self.__cache_spec()

~/anaconda3/envs/plipy39/lib/python3.9/site-packages/hdmf/utils.py in func_call(*args, **kwargs)
    643             def func_call(*args, **kwargs):
    644                 pargs = _check_args(args, kwargs)
--> 645                 return func(args[0], **pargs)
    646         else:
    647             def func_call(*args, **kwargs):

~/anaconda3/envs/plipy39/lib/python3.9/site-packages/hdmf/backends/io.py in write(self, **kwargs)
     48         """Write a container to the IO source."""
     49         container = popargs('container', kwargs)
---> 50         f_builder = self.__manager.build(container, source=self.__source, root=True)
     51         self.write_builder(f_builder, **kwargs)
     52

~/anaconda3/envs/plipy39/lib/python3.9/site-packages/hdmf/utils.py in func_call(*args, **kwargs)
    643             def func_call(*args, **kwargs):
    644                 pargs = _check_args(args, kwargs)
--> 645                 return func(args[0], **pargs)
    646         else:
    647             def func_call(*args, **kwargs):

~/anaconda3/envs/plipy39/lib/python3.9/site-packages/hdmf/build/manager.py in build(self, **kwargs)
    165                 else:
    166                     if container.container_source != source:
--> 167                         raise ValueError("Cannot change container_source once set: '%s' %s.%s"
    168                                          % (container.name, container.__class__.__module__,
    169                                             container.__class__.__name__))

ValueError: Cannot change container_source once set: 'root' pynwb.file.NWBFile
none
[ ]:
ipython3