Skip to content

Commit

Permalink
Add saving/loading ContinuousChannel type
Browse files Browse the repository at this point in the history
  • Loading branch information
medengineer committed Oct 22, 2024
1 parent a664142 commit 65733f2
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 7 deletions.
7 changes: 6 additions & 1 deletion Source/FileSource/NWBFileSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,13 +154,18 @@ void NWBFileSource::fillRecordInfo()
data = dataSource.openDataSet ("channel_conversion");
data.read (ccArray.getData(), PredType::NATIVE_FLOAT);

HeapBlock<uint8> ctArray (dims[1]);
data = dataSource.openDataSet ("channel_type");
data.read (ctArray.getData(), PredType::NATIVE_UINT8);

try
{
for (int k = 0; k < dims[1]; k++)
{
RecordedChannelInfo c;
c.name = "CH" + String (k);
c.bitVolts = ccArray[k] * 1e6;
c.bitVolts = ccArray[k] * 1e6; //TOFIX? Scaling should depend on channel type?
c.type = ctArray[k];
info.channels.add (c);
}
infoArray.add (info);
Expand Down
41 changes: 37 additions & 4 deletions Source/RecordEngine/NWBFormat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,15 +118,16 @@ TimeSeries::TimeSeries (String rootPath, String name, String description_)
{
}

ecephys::ElectricalSeries::ElectricalSeries (String rootPath, String name, String description_, int channel_count_, Array<float> channel_conversion_)
ecephys::ElectricalSeries::ElectricalSeries (String rootPath, String name, String description_, int channel_count_, Array<float> channel_conversion_, Array<uint8> channel_type_)
: TimeSeries (rootPath, name, description_),
channel_conversion (channel_conversion_),
channel_type (channel_type_),
channel_count (channel_count_)
{
}

ecephys::SpikeEventSeries::SpikeEventSeries (String rootPath, String name, String description_, int channel_count, Array<float> channel_conversion_)
: ecephys::ElectricalSeries (rootPath, name, description_, channel_count, channel_conversion_)
ecephys::SpikeEventSeries::SpikeEventSeries (String rootPath, String name, String description_, int channel_count, Array<float> channel_conversion_, Array<uint8> channel_type_)
: ecephys::ElectricalSeries (rootPath, name, description_, channel_count, channel_conversion_, channel_type_)
{
}

Expand Down Expand Up @@ -187,6 +188,12 @@ bool NWBFile::startNewRecording (
+ String (group[0]->getSourceNodeId())
+ "." + group[0]->getStreamName();

Array<uint8> channel_type;
for (int ch = 0; ch < group.size(); ch++)
{
channel_type.add (group[ch]->getChannelType());
}

String fullPath = "general/extracellular_ephys/" + groupName;
createGroup (fullPath);
setAttributeStr ("description", fullPath, "description");
Expand Down Expand Up @@ -217,7 +224,8 @@ bool NWBFile::startNewRecording (
groupName,
"Stores continuously sampled voltage data from an extracellular ephys recording",
group.size(),
channel_conversion);
channel_conversion,
channel_type);

if (recordingNumber == 0)
if (! createTimeSeriesBase (electricalSeries))
Expand Down Expand Up @@ -255,6 +263,12 @@ bool NWBFile::startNewRecording (
return false;
writeChannelConversions (electricalSeries);

electricalSeries->channelTypesDataSet = createChannelTypesDataSet (electricalSeries->basePath + "/channel_type", "Channel types for all channels", CHUNK_XSIZE);

if (electricalSeries->channelTypesDataSet == nullptr)
return false;
writeChannelTypes (electricalSeries);

electricalSeries->electrodeDataSet = createElectrodeDataSet (electricalSeries->basePath + "/electrodes", "Electrode index for each channel", CHUNK_XSIZE);

if (electricalSeries->electrodeDataSet == nullptr)
Expand Down Expand Up @@ -573,6 +587,15 @@ void NWBFile::writeChannelConversions (ecephys::ElectricalSeries* electricalSeri
CHECK_ERROR (electricalSeries->channelConversionDataSet->writeDataBlock (conversions.size(), BaseDataType::F32, &conversions[0]));
}

void NWBFile::writeChannelTypes (ecephys::ElectricalSeries* electricalSeries)
{
std::vector<uint8> channel_type;
for (auto i : electricalSeries->channel_type)
channel_type.push_back (i);

CHECK_ERROR (electricalSeries->channelTypesDataSet->writeDataBlock (channel_type.size(), BaseDataType::U8, &channel_type[0]));
}

void NWBFile::writeElectrodes (ecephys::ElectricalSeries* electricalSeries, Array<int> electrodeInds)
{
std::vector<int> electrodeNumbers;
Expand Down Expand Up @@ -759,6 +782,16 @@ HDF5RecordingData* NWBFile::createChannelConversionDataSet (String path, String
return elSet;
}

HDF5RecordingData* NWBFile::createChannelTypesDataSet (String path, String description, int chunk_size)
{
HDF5RecordingData* elSet = createDataSet (BaseDataType::U8, 1, chunk_size, path);
if (! elSet)
std::cerr << "Error creating electrode dataset in " << path << std::endl;
else
CHECK_ERROR (setAttributeStr (description, path, "description"));
return elSet;
}

HDF5RecordingData* NWBFile::createElectrodeDataSet (String path, String description, int chunk_size)
{
HDF5RecordingData* elSet = createDataSet (BaseDataType::I32, 1, chunk_size, path);
Expand Down
16 changes: 14 additions & 2 deletions Source/RecordEngine/NWBFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,17 +78,23 @@ namespace ecephys
{
public:
/** Constructor */
ElectricalSeries (String rootPath, String name, String description, int channel_count, Array<float> channel_conversion);
ElectricalSeries (String rootPath, String name, String description, int channel_count, Array<float> channel_conversion, Array<uint8> channel_type);

/** Holds the sample number for each sample (relative to the start of acquisition) */
ScopedPointer<HDF5RecordingData> channelConversionDataSet;

/** Holds the channel types */
ScopedPointer<HDF5RecordingData> channelTypesDataSet;

/** Holds the DynamicTableRegion index of each electrode */
ScopedPointer<HDF5RecordingData> electrodeDataSet;

/** Channel conversion values */
Array<float> channel_conversion;

/** Channel types */
Array<uint8> channel_type;

/** Number of channels to write */
int channel_count;

Expand All @@ -103,7 +109,7 @@ namespace ecephys
{
public:
/** Constructor */
SpikeEventSeries (String rootPath, String name, String description, int channel_count, Array<float> channel_conversion);
SpikeEventSeries (String rootPath, String name, String description, int channel_count, Array<float> channel_conversion, Array<uint8> channel_type = {});

/** Get neurodata_type */
virtual String getNeurodataType() override { return "SpikeEventSeries"; }
Expand Down Expand Up @@ -178,6 +184,9 @@ class NWBFile : public HDF5FileBase
/** Writes channel conversion values */
void writeChannelConversions (ecephys::ElectricalSeries* series);

/** Writes channel types */
void writeChannelTypes (ecephys::ElectricalSeries* series);

/** Writes a spike event*/
void writeSpike (int electrodeId, const SpikeChannel* channel, const Spike* event);

Expand Down Expand Up @@ -239,6 +248,9 @@ class NWBFile : public HDF5FileBase
/** Creates a dataset for electrode indices */
HDF5RecordingData* createChannelConversionDataSet (String basePath, String description, int chunk_size);

/** Creates a dataset for channel types */
HDF5RecordingData* createChannelTypesDataSet (String basePath, String description, int chunk_size);

/** Adds attributes (e.g. conversion, resolution) to a continuous dataset */
void createDataAttributes (String basePath, float conversion, float resolution, String unit);

Expand Down

0 comments on commit 65733f2

Please sign in to comment.