Skip to content

Commit

Permalink
update dset creation to take recordingNames as input
Browse files Browse the repository at this point in the history
  • Loading branch information
stephprince committed Sep 11, 2024
1 parent cd2d098 commit 5d59c0b
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 47 deletions.
2 changes: 0 additions & 2 deletions src/Channel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ using namespace AQNWB;

Channel::Channel(const std::string name,
const std::string groupName,
const std::string sourceName,
const SizeType groupIndex,
const SizeType localIndex,
const SizeType globalIndex,
Expand All @@ -17,7 +16,6 @@ Channel::Channel(const std::string name,
const std::string comments)
: name(name)
, groupName(groupName)
, sourceName(sourceName)
, groupIndex(groupIndex)
, localIndex(localIndex)
, globalIndex(globalIndex)
Expand Down
6 changes: 0 additions & 6 deletions src/Channel.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ class Channel
*/
Channel(const std::string name,
const std::string groupName,
const std::string sourceName,
const SizeType groupIndex,
const SizeType localIndex,
const SizeType globalIndex,
Expand Down Expand Up @@ -65,11 +64,6 @@ class Channel
*/
std::string groupName;

/**
* @brief Name of the data source the channel belongs to.
*/
std::string sourceName;

/**
* @brief Index of array group the channel belongs to.
*/
Expand Down
66 changes: 41 additions & 25 deletions src/nwb/NWBFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ Status NWBFile::createFileStructure(std::string description,

Status NWBFile::createElectricalSeries(
std::vector<Types::ChannelVector> recordingArrays,
std::vector<std::string> recordingNames,
const BaseDataType& dataType,
RecordingContainers* recordingContainers,
std::vector<SizeType>& containerIndexes)
Expand All @@ -110,22 +111,33 @@ Status NWBFile::createElectricalSeries(
return Status::Failure;
}

if (recordingNames.size() != recordingArrays.size()) {
return Status::Failure;
}

// Setup electrode table if it was not yet created
bool electrodeTableCreated =
io->objectExists(ElectrodeTable::electrodeTablePath);
if (!electrodeTableCreated) {
elecTable = std::make_unique<ElectrodeTable>(io);
elecTable->initialize();

// Add electrode information to table (does not write to datasets yet)
for (const auto& channelVector : recordingArrays) {
elecTable->addElectrodes(channelVector);
}
}

// Create continuous datasets
for (const auto& channelVector : recordingArrays) {
// Create datasets
for (size_t i = 0; i < recordingArrays.size(); ++i) {
const auto& channelVector = recordingArrays[i];
const std::string& recordingName = recordingNames[i];

// Setup electrodes and devices
std::string groupName = channelVector[0].groupName;
std::string sourceName = channelVector[0].sourceName;
std::string devicePath = "/general/devices/" + sourceName;
std::string electrodePath = "/general/extracellular_ephys/" + sourceName;
std::string electricalSeriesPath = acquisitionPath + "/" + groupName;
std::string devicePath = "/general/devices/" + groupName;
std::string electrodePath = "/general/extracellular_ephys/" + groupName;
std::string electricalSeriesPath = acquisitionPath + "/" + recordingName;

// Check if device exists for groupName, create device and electrode group
// if not
Expand Down Expand Up @@ -153,13 +165,9 @@ Status NWBFile::createElectricalSeries(
containerIndexes.push_back(recordingContainers->containers.size() - 1);
}

// write electrode information to datasets
// (requires that the ElectrodeGroup has been written)
if (!electrodeTableCreated) {
// Add electrode information to table (does not write to datasets yet)
for (const auto& channelVector : recordingArrays) {
elecTable->addElectrodes(channelVector);
}

// write electrode information to datasets
elecTable->finalize();
}

Expand All @@ -168,6 +176,7 @@ Status NWBFile::createElectricalSeries(

Status NWBFile::createSpikeEventSeries(
std::vector<Types::ChannelVector> recordingArrays,
std::vector<std::string> recordingNames,
const BaseDataType& dataType,
RecordingContainers* recordingContainers,
std::vector<SizeType>& containerIndexes)
Expand All @@ -176,22 +185,33 @@ Status NWBFile::createSpikeEventSeries(
return Status::Failure;
}

if (recordingNames.size() != recordingArrays.size()) {
return Status::Failure;
}

// Setup electrode table if it was not yet created
bool electrodeTableCreated =
io->objectExists(ElectrodeTable::electrodeTablePath);
if (!electrodeTableCreated) {
elecTable = std::make_unique<ElectrodeTable>(io);
elecTable->initialize();

// Add electrode information to table (does not write to datasets yet)
for (const auto& channelVector : recordingArrays) {
elecTable->addElectrodes(channelVector);
}
}

// Create continuous datasets
for (const auto& channelVector : recordingArrays) {
// Create datasets
for (size_t i = 0; i < recordingArrays.size(); ++i) {
const auto& channelVector = recordingArrays[i];
const std::string& recordingName = recordingNames[i];

// Setup electrodes and devices
std::string groupName = channelVector[0].groupName;
std::string sourceName = channelVector[0].sourceName;
std::string devicePath = "/general/devices/" + sourceName;
std::string electrodePath = "/general/extracellular_ephys/" + sourceName;
std::string spikeEventSeriesPath = acquisitionPath + "/" + groupName;
std::string groupName = channelVector[0].groupName;
std::string devicePath = "/general/devices/" + groupName;
std::string electrodePath = "/general/extracellular_ephys/" + groupName;
std::string spikeEventSeriesPath = acquisitionPath + "/" + recordingName;

// Check if device exists for groupName, create device and electrode group
// if not
Expand Down Expand Up @@ -228,13 +248,9 @@ Status NWBFile::createSpikeEventSeries(
containerIndexes.push_back(recordingContainers->containers.size() - 1);
}

// write electrode information to datasets
// (requires that the ElectrodeGroup has been written)
if (!electrodeTableCreated) {
// Add electrode information to table (does not write to datasets yet)
for (const auto& channelVector : recordingArrays) {
elecTable->addElectrodes(channelVector);
}

// write electrode information to datasets
elecTable->finalize();
}

Expand Down
4 changes: 4 additions & 0 deletions src/nwb/NWBFile.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ class NWBFile
* @param recordingArrays vector of ChannelVector indicating the electrodes to
* record from. A separate ElectricalSeries will be
* created for each ChannelVector.
* @param recordingNames vector indicating the names of the ElectricalSeries within the acquisition group
* @param dataType The data type of the elements in the data block.
* @param recordingContainers The container to store the created TimeSeries.
* @param containerIndexes The indexes of the containers added to
Expand All @@ -80,6 +81,7 @@ class NWBFile
*/
Status createElectricalSeries(
std::vector<Types::ChannelVector> recordingArrays,
std::vector<std::string> recordingNames,
const BaseDataType& dataType = BaseDataType::I16,
RecordingContainers* recordingContainers = nullptr,
std::vector<SizeType>& containerIndexes = emptyContainerIndexes);
Expand All @@ -90,6 +92,7 @@ class NWBFile
* @param recordingArrays vector of ChannelVector indicating the electrodes to
* record from. A separate ElectricalSeries will be
* created for each ChannelVector.
* @param recordingNames vector indicating the names of the SpikeEventSeries within the acquisition group
* @param dataType The data type of the elements in the data block.
* @param recordingContainers The container to store the created TimeSeries.
* @param containerIndexes The indexes of the containers added to
Expand All @@ -98,6 +101,7 @@ class NWBFile
*/
Status createSpikeEventSeries(
std::vector<Types::ChannelVector> recordingArrays,
std::vector<std::string> recordingNames,
const BaseDataType& dataType = BaseDataType::I16,
RecordingContainers* recordingContainers = nullptr,
std::vector<SizeType>& containerIndexes = emptyContainerIndexes);
Expand Down
4 changes: 2 additions & 2 deletions src/nwb/file/ElectrodeTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ void ElectrodeTable::addElectrodes(std::vector<Channel> channels)
{
// create datasets
for (const auto& ch : channels) {
groupReferences.push_back(groupPathBase + ch.sourceName);
groupNames.push_back(ch.sourceName);
groupReferences.push_back(groupPathBase + ch.groupName);
groupNames.push_back(ch.groupName);
electrodeNumbers.push_back(ch.globalIndex);
locationNames.push_back("unknown");
}
Expand Down
2 changes: 2 additions & 0 deletions tests/examples/testWorkflowExamples.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ TEST_CASE("workflowExamples")

std::vector<Types::ChannelVector> mockRecordingArrays =
getMockChannelArrays();
std::vector<std::string> mockChannelNames = getMockChannelArrayNames("esdata");
std::vector<std::vector<float>> mockData =
getMockData2D(numSamples, numChannels);
std::vector<double> mockTimestamps = getMockTimestamps(numSamples);
Expand All @@ -50,6 +51,7 @@ TEST_CASE("workflowExamples")
// [example_workflow_datasets_snippet]
std::vector<SizeType> containerIndexes;
nwbfile->createElectricalSeries(mockRecordingArrays,
mockChannelNames,
BaseDataType::I16,
recordingContainers.get(),
containerIndexes);
Expand Down
6 changes: 3 additions & 3 deletions tests/testFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ TEST_CASE("ElectrodeTable", "[ecephys]")

std::vector<SizeType> channelIDs = {0, 1, 2};
std::vector<Channel> channels = {
Channel("ch0", "esdata0", "array0", 0, channelIDs[0], 0),
Channel("ch1", "esdata0", "array0", 0, channelIDs[1], 1),
Channel("ch2", "esdata0", "array0", 0, channelIDs[2], 2),
Channel("ch0", "array0", 0, channelIDs[0], 0),
Channel("ch1", "array0", 0, channelIDs[1], 1),
Channel("ch2", "array0", 0, channelIDs[2], 2),
};

NWB::ElectrodeTable electrodeTable(io);
Expand Down
14 changes: 8 additions & 6 deletions tests/testNWBFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,11 @@ TEST_CASE("createElectricalSeries", "[nwb]")

// create Electrical Series
std::vector<Types::ChannelVector> mockArrays = getMockChannelArrays(1, 2);
std::vector<std::string> mockChannelNames = getMockChannelArrayNames("esdata");
std::unique_ptr<NWB::RecordingContainers> recordingContainers =
std::make_unique<NWB::RecordingContainers>();
Status resultCreate = nwbfile.createElectricalSeries(
mockArrays, BaseDataType::F32, recordingContainers.get());
mockArrays, mockChannelNames, BaseDataType::F32, recordingContainers.get());
REQUIRE(resultCreate == Status::Success);

// start recording
Expand Down Expand Up @@ -72,18 +73,18 @@ TEST_CASE("createMultipleEcephysDatasets", "[nwb]")

// create Electrical Series
std::vector<Types::ChannelVector> mockArrays = getMockChannelArrays(1, 2);
std::vector<std::string> mockChannelNames = getMockChannelArrayNames("esdata");
std::unique_ptr<NWB::RecordingContainers> recordingContainers =
std::make_unique<NWB::RecordingContainers>();
Status resultCreateES = nwbfile.createElectricalSeries(
mockArrays, BaseDataType::F32, recordingContainers.get());
mockArrays, mockChannelNames, BaseDataType::F32, recordingContainers.get());
REQUIRE(resultCreateES == Status::Success);

// create SpikeEventSeries
SizeType numSamples = 5;
std::vector<Types::ChannelVector> mockSpikeArrays =
getMockChannelArrays(1, 2, "spikedata");
std::vector<std::string> mockSpikeChannelNames = getMockChannelArrayNames("spikedata");
Status resultCreateSES = nwbfile.createSpikeEventSeries(
mockSpikeArrays, BaseDataType::F32, recordingContainers.get());
mockArrays, mockSpikeChannelNames, BaseDataType::F32, recordingContainers.get());

// start recording
Status resultStart = io->startRecording();
Expand Down Expand Up @@ -134,8 +135,9 @@ TEST_CASE("setCanModifyObjectsMode", "[nwb]")

// test that dataset creation fails after starting the recording
std::vector<Types::ChannelVector> mockArrays = getMockChannelArrays(1, 2);
std::vector<std::string> mockChannelNames = getMockChannelArrayNames("esdata");
Status resultCreatePostStart =
nwbfile.createElectricalSeries(mockArrays, BaseDataType::F32);
nwbfile.createElectricalSeries(mockArrays, mockChannelNames, BaseDataType::F32);
REQUIRE(resultCreatePostStart == Status::Failure);

// stop recording
Expand Down
3 changes: 2 additions & 1 deletion tests/testRecordingWorkflow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ TEST_CASE("writeContinuousData", "[recording]")

std::vector<Types::ChannelVector> mockRecordingArrays =
getMockChannelArrays();
std::vector<std::string> mockChannelNames = getMockChannelArrayNames("esdata");
std::vector<std::vector<float>> mockData =
getMockData2D(numSamples, numChannels);
std::vector<double> mockTimestamps = getMockTimestamps(numSamples);
Expand All @@ -48,7 +49,7 @@ TEST_CASE("writeContinuousData", "[recording]")

// 4. create datasets and add to recording containers
nwbfile->createElectricalSeries(
mockRecordingArrays, BaseDataType::F32, recordingContainers.get());
mockRecordingArrays, mockChannelNames, BaseDataType::F32, recordingContainers.get());

// 5. start the recording
io->startRecording();
Expand Down
14 changes: 12 additions & 2 deletions tests/testUtils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,14 @@ inline std::string getTestFilePath(std::string filename)
inline std::vector<Types::ChannelVector> getMockChannelArrays(
SizeType numChannels = 2,
SizeType numArrays = 2,
std::string groupName = "esdata")
std::string groupName = "array")
{
std::vector<Types::ChannelVector> arrays(numArrays);
for (SizeType i = 0; i < numArrays; i++) {
std::vector<Channel> chGroup;
for (SizeType j = 0; j < numChannels; j++) {
Channel ch("ch" + std::to_string(j),
groupName + std::to_string(i),
"array" + std::to_string(i),
i,
j,
i * numArrays + j);
Expand All @@ -54,6 +53,17 @@ inline std::vector<Types::ChannelVector> getMockChannelArrays(
return arrays;
}

inline std::vector<std::string> getMockChannelArrayNames(
std::string baseName = "esdata",
SizeType numArrays = 2)
{
std::vector<std::string> arrayNames(numArrays);
for (SizeType i = 0; i < numArrays; i++) {
arrayNames[i] = baseName + std::to_string(i);
}
return arrayNames;
}

inline std::vector<float> getMockData1D(SizeType numSamples = 1000)
{
std::vector<float> mockData(numSamples);
Expand Down

0 comments on commit 5d59c0b

Please sign in to comment.