Igor Pro module for reading and writing NeurodataWithoutBorder files

This modules allows to easily write and read valid NeurodataWithoutBorder style HDF5 files. It encapsulates the most commonly used parts of the specification in easy to use functions.

Main features

Installation

  • Quit Igor Pro

  • Install the HDF5 XOP and the HDF5 Browser as described in DisplayHelpTopic "Installing The HDF5 Package"

  • Create the following shortcut in C:\Users\$username\Documents\WaveMetrics\Igor Pro [78] User Files

    • In “Igor Procedures” a shortcut pointing to the basefolder of the IPNWB package

  • Restart Igor Pro

Examples

The following examples show how to read and write into NWB version 1.0.5

writing into NWB

#pragma TextEncoding = "UTF-8"

#define IPNWB_DEFINE_IM
#include "IPNWB_include"

Function NWBWriterExample()

	variable fileID
	string contents, device
	variable version = 1

	// Open a dialog for selecting an HDF5 file name
	HDF5CreateFile fileID as ""

	// fill gi/ti/si with appropriate data for your lab and experiment
	// if you don't care about that info just pass the initialized structures
	STRUCT IPNWB#GeneralInfo gi
	STRUCT IPNWB#ToplevelInfo ti
	STRUCT IPNWB#SubjectInfo si

	// takes care of initializing
	IPNWB#InitToplevelInfo(ti, version)
	IPNWB#InitGeneralInfo(gi)
	IPNWB#InitSubjectInfo(si)

	IPNWB#CreateCommonGroups(fileID, toplevelInfo=ti, generalInfo=gi, subjectInfo=si)

	// If you open an existing NWB file to append to, use the following command
	// to add an modification time entry, is implicitly called in IPNWB#CreateCommonGroups
	// IPNWB#AddModificationTimeEntry(locationID)

	// 1D waves from your measurement program
	// we use fake data here
	Make/FREE/N=1000 AD = (sin(p) + cos(p/10)) * enoise(0.1)
	SetScale/P x, 0, 5e-6, "s"

	// write AD data to the file
	STRUCT IPNWB#WriteChannelParams params
	IPNWB#InitWriteChannelParams(params)

	params.device          = "My Hardware"
	params.clampMode       = 0 // 0 for V_CLAMP_MODE, 1 for I_CLAMP_MODE
	params.channelSuffix   = ""
	params.sweep           = 123
	params.electrodeNumber = 1
	params.electrodeName   = "Nose of the mouse"
	params.stimset         = "My fancy sine curve"
	params.channelType     = 0 // @see IPNWBChannelTypes
	WAVE params.data       = AD

	device = "My selfbuilt DAC"

	IPNWB#CreateIntraCellularEphys(fileID)
	sprintf contents, "Electrode %d", params.ElectrodeNumber
	IPNWB#AddElectrode(fileID, params.electrodeName, version, contents, device)

	// calculate the timepoint of the first wave point relative to the session_start_time
	// last time the wave was modified (UTC)
	params.startingTime  = NumberByKeY("MODTIME", WaveInfo(AD, 0)) - date2secs(-1, -1, -1)
	params.startingTime -= ti.session_start_time // relative to the start of the session
	// we want the timestamp of the beginning of the measurement
	params.startingTime -= IndexToScale(AD, DimSize(AD, 0) - 1, 0)

	IPNWB#AddDevice(fileID, "Device name", version, "My hardware specs")

	STRUCT IPNWB#TimeSeriesProperties tsp
	IPNWB#InitTimeSeriesProperties(tsp, params.channelType, params.clampMode)

	// all values not added are written into the missing_fields dataset
	IPNWB#AddProperty(tsp, "capacitance_fast", 1.0)
	IPNWB#AddProperty(tsp, "capacitance_slow", 1.0)

	// setting chunkedLayout to zero makes writing faster but increases the final filesize
	IPNWB#WriteSingleChannel(fileID, "/acquisition/timeseries", version, params, tsp)

	// write DA, stimulus presentation and stimulus template accordingly
	// ...

	// close file
	IPNWB#H5_CloseFile(fileID)
End

reading from NWB

#pragma TextEncoding = "UTF-8"

#define IPNWB_DEFINE_IM
#include "IPNWB_include"

Function NWBReaderExample()

	variable fileID, groupID, integrityCheck, numChannels, i, version
	string contents, device, listOfDevices, elem, list
	STRUCT IPNWB#TimeSeriesProperties tsp

	// Open a dialog for selecting an HDF5 file name
	fileID = IPNWB#H5_OpenFile("c:\\NWB-Sample-20160216.nwb")
	version = IPNWB#GetNWBMajorVersion(IPNWB#ReadNWBVersion(fileID))

	integrityCheck = IPNWB#CheckIntegrity(fileID)
	printf "NWB integrity check: %s\r", SelectString(integrityCheck, "failed", "passed")

	listOfDevices = IPNWB#ReadDevices(fileID, version)
	printf "List of devices: %s\r", listOfDevices

	list    = IPNWB#ReadAcquisition(fileID, version)
	groupID = IPNWB#OpenAcquisition(fileID, version)

	numChannels = ItemsInList(list)

	printf "\rLoading acquired data (%d)\r", numChannels

	for(i = 0; i < numChannels; i += 1)
		elem = StringFromList(i, list)

		printf "sweep number: %d\r", IPNWB#LoadSweepNumber(groupID, elem, version)

		WAVE wv = IPNWB#LoadDataWave(groupID, elem)
		Duplicate/O wv, $elem

		IPNWB#ReadTimeSeriesProperties(groupID, elem, tsp)
		print tsp
	endfor

	HDF5CloseGroup groupID

	list    = IPNWB#ReadStimulus(fileID)
	groupID = IPNWB#OpenStimulus(fileID)

	numChannels = ItemsInList(list)

	printf "\rLoading presentation data (%d)\r", numChannels

	for(i = 0; i < numChannels; i += 1)
		elem = StringFromList(i, list)

		printf "sweep number: %d\r", IPNWB#LoadSweepNumber(groupID, elem, version)

		WAVE wv = IPNWB#LoadDataWave(groupID, elem)
		Duplicate/O wv, $elem

		IPNWB#ReadTimeSeriesProperties(groupID, elem, tsp)
		print tsp
	endfor

	HDF5CloseGroup groupID

	STRUCT IPNWB#ToplevelInfo toplevelInfo
	IPNWB#ReadTopLevelInfo(fileID, toplevelInfo)
	print toplevelInfo
	print toplevelInfo.file_create_date

	STRUCT IPNWB#GeneralInfo generalInfo
	IPNWB#ReadGeneralInfo(fileID, generalInfo)
	print generalInfo

	STRUCT IPNWB#SubjectInfo subjectInfo
	IPNWB#ReadSubjectInfo(fileID, subjectInfo)
	print subjectInfo

	// close file
	HDF5CloseFile fileID
End

NWB file format description

  • Datasets which originate from Igor Pro waves have the special attributes IGORWaveScaling, IGORWaveType, IGORWaveUnits, IGORWaveNote. These attributes allow easy and convenient loading of the data into Igor Pro back.

  • For AD/DA/TTL groups the naming scheme is data_XXXXX_[AD/DA/TTL] suffix where XXXXX is a running number and suffix the channel number. For some hardware types the suffix includes the TTL line as well. It is important to note that the number of digits in XXXXX is variable und subject to change, and that XXXXX is not the sweep number.

  • In NWB v1, the sweep number is accessible from the source attribute only. Example source contents: Device=ITC18USB_Dev_0;Sweep=0;AD=0;ElectrodeNumber=0;ElectrodeName=0

  • For I=0 clamp mode neither the DA data nor the stimset is saved.

  • Some entries in the following tree are specific to MIES, these are marked as custom entries. Users running MIES are encouraged to use the same NWB layout and extensions.

NWB File Organization

The current major version of the file format is 2. Version 1 is considered supported but deprecated.