diff --git a/Source/Plugins/NWBFormat/NWBFormat.cpp b/Source/Plugins/NWBFormat/NWBFormat.cpp index ecb504c57db9c96653e85239afd5d4d8354b958e..dea14b24618a0741263cbb04c9b022a32884f58b 100644 --- a/Source/Plugins/NWBFormat/NWBFormat.cpp +++ b/Source/Plugins/NWBFormat/NWBFormat.cpp @@ -284,6 +284,33 @@ bool NWBFile::startNewRecording(int recordingNumber, const Array<ContinuousGroup eventDataSets.add(tsStruct.release()); } + basePath = rootPath + "/events/sync_messages"; + ancestry.clearQuick(); + ancestry.add("Timeseries"); + ancestry.add("AnnotationSeries"); + String desc = "Stores recording start timestamps for each processor in text format"; + if (!createTimeSeriesBase(basePath, "Autogenerated messages", desc, desc, ancestry)) return false; + tsStruct = new TimeSeries(); + tsStruct->basePath = basePath; + dSet = createDataSet(BaseDataType::STR(100), 0, 1, basePath + "/data"); + if (dSet == nullptr) + { + std::cerr << "Error creating dataset for sync messages" << std::endl; + return false; + } + else + { + createDataAttributes(basePath, NAN, NAN, "n/a"); + } + tsStruct->baseDataSet = dSet; + dSet = createTimestampDataSet(basePath, 1); + if (dSet == nullptr) return false; + tsStruct->timestampDataSet = dSet; + + dSet = createDataSet(BaseDataType::U8, 0, 1, basePath + "/control"); + if (dSet == nullptr) return false; + tsStruct->controlDataSet = dSet; + syncMsgDataSet = tsStruct; return true; } @@ -309,10 +336,13 @@ bool NWBFile::startNewRecording(int recordingNumber, const Array<ContinuousGroup tsStruct = eventDataSets[i]; CHECK_ERROR(setAttribute(BaseDataType::U64, &(tsStruct->numSamples), tsStruct->basePath, "num_samples")); } + + CHECK_ERROR(setAttribute(BaseDataType::U64, &(syncMsgDataSet->numSamples), syncMsgDataSet->basePath, "num_samples")); continuousDataSets.clear(); spikeDataSets.clear(); eventDataSets.clear(); + syncMsgDataSet = nullptr; } void NWBFile::writeData(int datasetID, int channel, int nSamples, const float* data, float bitVolts) @@ -425,6 +455,15 @@ bool NWBFile::startNewRecording(int recordingNumber, const Array<ContinuousGroup eventDataSets[eventID]->numSamples += 1; } + void NWBFile::writeTimestampSyncText(uint16 sourceID, int64 timestamp, float sourceSampleRate, String text) + { + CHECK_ERROR(syncMsgDataSet->baseDataSet->writeDataBlock(1, BaseDataType::STR(text.length()), text.toUTF8())); + double timeSec = timestamp / sourceSampleRate; + CHECK_ERROR(syncMsgDataSet->timestampDataSet->writeDataBlock(1, BaseDataType::F64, &timeSec)); + CHECK_ERROR(syncMsgDataSet->controlDataSet->writeDataBlock(1, BaseDataType::U8, &sourceID)); + syncMsgDataSet->numSamples += 1; + } + String NWBFile::getFileName() { diff --git a/Source/Plugins/NWBFormat/NWBFormat.h b/Source/Plugins/NWBFormat/NWBFormat.h index 2ffb6d3b31b5c58463bd1253978e85365ea06c81..bf5fb79b26a3caeeeb8741146e2c20b09d8e3627 100644 --- a/Source/Plugins/NWBFormat/NWBFormat.h +++ b/Source/Plugins/NWBFormat/NWBFormat.h @@ -55,6 +55,7 @@ namespace NWBRecording void writeTimestamps(int datasetID, int nSamples, const double* data); void writeSpike(int electrodeId, const SpikeChannel* channel, const SpikeEvent* event); void writeEvent(int eventID, const EventChannel* channel, const Event* event); + void writeTimestampSyncText(uint16 sourceID, int64 timestamp, float sourceSampleRate, String text); String getFileName() override; void setXmlText(const String& xmlText); @@ -84,7 +85,7 @@ namespace NWBRecording OwnedArray<TimeSeries> continuousDataSets; OwnedArray<TimeSeries> spikeDataSets; OwnedArray<TimeSeries> eventDataSets; - + ScopedPointer<TimeSeries> syncMsgDataSet; const String* xmlText; const String identifierText; diff --git a/Source/Plugins/NWBFormat/NWBRecording.cpp b/Source/Plugins/NWBFormat/NWBRecording.cpp index 4737a8083f0d6310869001ec89fb15fea45c9a72..59473f86a5feb658261a9fe24bba5b553c3d5b24 100644 --- a/Source/Plugins/NWBFormat/NWBRecording.cpp +++ b/Source/Plugins/NWBFormat/NWBRecording.cpp @@ -166,7 +166,7 @@ void NWBRecordEngine::writeEvent(int eventIndex, const MidiMessage& event) void NWBRecordEngine::writeTimestampSyncText(uint16 sourceID, uint16 sourceIdx, int64 timestamp, float sourceSampleRate, String text) { - + recordFile->writeTimestampSyncText(sourceID, timestamp, sourceSampleRate, text); } void NWBRecordEngine::addSpikeElectrode(int index,const SpikeChannel* elec)