Skip to content
Snippets Groups Projects
Commit 92b54ed5 authored by Aaron Cuevas Lopez's avatar Aaron Cuevas Lopez
Browse files

Move record code on PSTH to recordengine system

parent 340e9597
No related branches found
No related tags found
No related merge requests found
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Express 2013 for Windows Desktop # Visual Studio 2013
VisualStudioVersion = 12.0.21005.1 VisualStudioVersion = 12.0.31101.0
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "open-ephys", "open-ephys.vcxproj", "{9C924D66-7DEC-1AEF-B375-DB8666BFB909}" Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "open-ephys", "open-ephys.vcxproj", "{9C924D66-7DEC-1AEF-B375-DB8666BFB909}"
EndProject EndProject
......
...@@ -278,12 +278,12 @@ void PeriStimulusTimeHistogramEditor::buttonEvent(Button* button) ...@@ -278,12 +278,12 @@ void PeriStimulusTimeHistogramEditor::buttonEvent(Button* button)
PopupMenu m; PopupMenu m;
m.addItem(1,"TTL",true, processor->saveTTLs); /* m.addItem(1,"TTL",true, processor->saveTTLs);
m.addItem(2,"Network Events",true, processor->saveNetworkEvents); m.addItem(2,"Network Events",true, processor->saveNetworkEvents);
m.addItem(7,"Network Events [when recording is off]",true, processor->saveNetworkEventsWhenNotRecording); m.addItem(7,"Network Events [when recording is off]",true, processor->saveNetworkEventsWhenNotRecording);
m.addItem(3,"Eye Tracking",true, processor->saveEyeTracking); m.addItem(3,"Eye Tracking",true, processor->saveEyeTracking);*/
m.addItem(4,"Sorted Spikes: TS only ",true, processor->spikeSavingMode == 1); //m.addItem(4,"Sorted Spikes: TS only ",true, processor->spikeSavingMode == 1);
m.addItem(5,"Sorted Spikes: TS+waveform",true, processor->spikeSavingMode == 2); m.addItem(5,"Sorted Spikes: TS+waveform",true, processor->spikeSavingMode == 2);
m.addItem(6,"All Spikes: TS+waveform",true, processor->spikeSavingMode == 3); m.addItem(6,"All Spikes: TS+waveform",true, processor->spikeSavingMode == 3);
......
...@@ -37,7 +37,6 @@ PeriStimulusTimeHistogramNode::PeriStimulusTimeHistogramNode() ...@@ -37,7 +37,6 @@ PeriStimulusTimeHistogramNode::PeriStimulusTimeHistogramNode()
: GenericProcessor("PSTH"), displayBufferSize(5), redrawRequested(false) : GenericProcessor("PSTH"), displayBufferSize(5), redrawRequested(false)
{ {
trialCircularBuffer = nullptr; trialCircularBuffer = nullptr;
eventFile = nullptr;
isRecording = false; isRecording = false;
saveEyeTracking = saveTTLs = saveNetworkEvents = false; saveEyeTracking = saveTTLs = saveNetworkEvents = false;
saveNetworkEventsWhenNotRecording = false; saveNetworkEventsWhenNotRecording = false;
...@@ -120,6 +119,13 @@ void PeriStimulusTimeHistogramNode::updateSettings() ...@@ -120,6 +119,13 @@ void PeriStimulusTimeHistogramNode::updateSettings()
allocateTrialCircularBuffer(); allocateTrialCircularBuffer();
syncInternalDataStructuresWithSpikeSorter(); syncInternalDataStructuresWithSpikeSorter();
} }
electrodeChannels.clear();
for (int k = 0; k < eventChannels.size(); k++)
{
if ((eventChannels[k]->type == ELECTRODE_CHANNEL) &&
(static_cast<SpikeChannel*>(eventChannels[k]->extraData.get())->dataType == SpikeChannel::Sorted))
electrodeChannels.add(eventChannels[k]);
}
recordNode = getProcessorGraph()->getRecordNode(); recordNode = getProcessorGraph()->getRecordNode();
// diskWriteLock = recordNode->getLock(); // diskWriteLock = recordNode->getLock();
...@@ -136,6 +142,16 @@ bool PeriStimulusTimeHistogramNode::enable() ...@@ -136,6 +142,16 @@ bool PeriStimulusTimeHistogramNode::enable()
std::cout << "PeriStimulusTimeHistogramNode::enable()" << std::endl; std::cout << "PeriStimulusTimeHistogramNode::enable()" << std::endl;
PeriStimulusTimeHistogramEditor* editor = (PeriStimulusTimeHistogramEditor*) getEditor(); PeriStimulusTimeHistogramEditor* editor = (PeriStimulusTimeHistogramEditor*) getEditor();
editor->enable(); editor->enable();
recordNode->registerSpikeSource(this);
for (int i = 0; i < electrodeChannels.size(); i++)
{
SpikeRecordInfo *recElec = new SpikeRecordInfo();
recElec->name = electrodeChannels[i]->name;
recElec->numChannels = static_cast<SpikeChannel*>(electrodeChannels[i]->extraData.get())->numChannels;
recElec->sampleRate = settings.sampleRate;
electrodeChannels[i]->recordIndex = recordNode->addSpikeElectrode(recElec);
}
return true; return true;
...@@ -185,169 +201,6 @@ void PeriStimulusTimeHistogramNode::process(AudioSampleBuffer& buffer, MidiBuffe ...@@ -185,169 +201,6 @@ void PeriStimulusTimeHistogramNode::process(AudioSampleBuffer& buffer, MidiBuffe
void PeriStimulusTimeHistogramNode::dumpStartStopRecordEventToDisk(int64 ts, bool startRecord)
{
const ScopedLock myScopedLock(diskWriteLock);
#define SESSION 10
uint8 eventType = SESSION;
// write event type
fwrite(&eventType, 1,1, eventFile);
// write event size
int16 eventSize = 1 +2+ 8; // start/stop(1) + recordnumber (2) + timestamp (8)
fwrite(&eventSize, 2,1, eventFile);
// write event data
// 1. Start/stop
fwrite(&startRecord, 1,1, eventFile);
// 2. record number
fwrite(&recordingNumber, 2,1, eventFile);
// 3. the software timestamp
fwrite(&ts, 8,1, eventFile);
}
void PeriStimulusTimeHistogramNode::dumpNetworkEventToDisk(String S, int64 ts)
{
const ScopedLock myScopedLock(diskWriteLock);
uint8 eventType = NETWORK;
// write event type
fwrite(&eventType, 1,1, eventFile);
// write event size
int16 eventSize = S.getNumBytesAsUTF8() + 8; // string length + timestamp
fwrite(&eventSize, 2,1, eventFile);
// write event data
// 1. the network event string
fwrite(S.toUTF8(), S.getNumBytesAsUTF8(), 1, eventFile);
// 2. the software timestamp
fwrite(&ts, 8,1, eventFile);
}
void PeriStimulusTimeHistogramNode::dumpSpikeEventToDisk(SpikeObject *s, bool dumpWave)
{
const ScopedLock myScopedLock(diskWriteLock);
uint8 eventType = SPIKE;
// write event type
fwrite(&eventType, 1,1, eventFile);
int16 eventSize = 8+8+2+2+2+2+2 + s->nChannels*4; // ts, ts, sorted id, electrode ID, num channels, num data per channel + 4x gains
if (dumpWave)
eventSize += 2*(s->nSamples*s->nChannels); // uint16 per samples
// write event size
fwrite(&eventSize, 2,1, eventFile);
// write event data
// 1. software ts
fwrite(&s->timestamp_software, 8,1, eventFile);
// 2. hardware ts
fwrite(&s->timestamp, 8,1, eventFile);
// 3. sorted ID
fwrite(&s->sortedId, 2,1, eventFile);
// 4. electrod ID
fwrite(&s->electrodeID, 2,1, eventFile);
// 5. Channel in which threshold was detected
fwrite(&s->channel, 2,1, eventFile);
// 6. num channels
fwrite(&s->nChannels, 2,1, eventFile);
// 7. gains
fwrite(&s->gain, 4,s->nChannels, eventFile);
// 8. num data points per channel
fwrite(&s->nSamples, 2,1, eventFile);
if (dumpWave)
fwrite(&s->data, 2,s->nSamples*s->nChannels, eventFile);
}
void PeriStimulusTimeHistogramNode::dumpTTLeventToDisk(int channel, bool risingEdge, int64 ttl_timestamp_software, int64 ttl_timestamp_hardware, int samplePosition )
{
const ScopedLock myScopedLock(diskWriteLock);
uint8 eventType = TTL;
// write event type
fwrite(&eventType, 1,1, eventFile);
// write event size
int16 eventSize = 1 + 2 + 8 + 8; // rising/falling(1) + software ts (8) + hardware ts (8)
fwrite(&eventSize, 2,1, eventFile);
// write event data
// 1. rising/falling edge
fwrite(&risingEdge, 1, 1, eventFile);
// 2. channel
fwrite(&channel, 2,1,eventFile);
// 2. software ts
fwrite(&ttl_timestamp_software, 8,1, eventFile);
// 3. hardware ts
fwrite(&ttl_timestamp_hardware, 8,1, eventFile);
}
/*
void PeriStimulusTimeHistogramNode::dumpEyeTrackingEventToDisk(EyePosition pos)
{
diskWriteLock->enter();
uint8 eventType = EYE_POSITION;
// write event type
fwrite(&eventType, 1,1, eventFile);
// write event size
int16 eventSize = 8 + 8 + 8 + 8 + 8 +8 +8; // x,y,xc,yc,pupil,timestamp
fwrite(&eventSize, 2,1, eventFile);
// write event data
// 1. eye x position
fwrite(&pos.x, 8,1, eventFile);
// 2. eye y position
fwrite(&pos.y, 8,1, eventFile);
// 3. calibrated eye x position
fwrite(&pos.xc, 8,1, eventFile);
// 4. calibrated eye y position
fwrite(&pos.yc, 8,1, eventFile);
// 5. eye pupil
fwrite(&pos.pupil, 8,1, eventFile);
// 6. software timestamp
fwrite(&pos.software_timestamp, 8,1, eventFile);
// 7. hardware timestamp
fwrite(&pos.hardware_timestamp, 8,1, eventFile);
diskWriteLock->exit();
}
*/
void PeriStimulusTimeHistogramNode::dumpTimestampEventToDisk(int64 softwareTS,int64 hardwareTS)
{
const ScopedLock myScopedLock(diskWriteLock);
uint8 eventType = TIMESTAMP;
// write event type
fwrite(&eventType, 1,1, eventFile);
// write event size
int16 eventSize = 8 + 8; // software ts (8) + hardware ts (8)
fwrite(&eventSize, 2,1, eventFile);
// write event data
// 1. software ts
fwrite(&softwareTS, 8,1, eventFile);
// 2. hardware ts
fwrite(&hardwareTS, 8,1, eventFile);
}
void PeriStimulusTimeHistogramNode::syncInternalDataStructuresWithSpikeSorter() void PeriStimulusTimeHistogramNode::syncInternalDataStructuresWithSpikeSorter()
{ {
Array<Electrode*> electrodes; Array<Electrode*> electrodes;
...@@ -401,13 +254,13 @@ void PeriStimulusTimeHistogramNode::handleNetworkMessage(StringTS s) ...@@ -401,13 +254,13 @@ void PeriStimulusTimeHistogramNode::handleNetworkMessage(StringTS s)
ed->updateCanvas(); ed->updateCanvas();
} }
if (isRecording && saveNetworkEvents) /* if (isRecording && saveNetworkEvents)
{ {
dumpNetworkEventToDisk(s.getString(),s.timestamp); dumpNetworkEventToDisk(s.getString(),s.timestamp);
} else if (!isRecording && saveNetworkEvents && saveNetworkEventsWhenNotRecording) } else if (!isRecording && saveNetworkEvents && saveNetworkEventsWhenNotRecording)
{ {
networkEventsHistory.push(s); networkEventsHistory.push(s);
} }*/
} }
void PeriStimulusTimeHistogramNode::handleEvent(int eventType, MidiMessage& event, int samplePosition) void PeriStimulusTimeHistogramNode::handleEvent(int eventType, MidiMessage& event, int samplePosition)
...@@ -446,7 +299,7 @@ void PeriStimulusTimeHistogramNode::handleEvent(int eventType, MidiMessage& even ...@@ -446,7 +299,7 @@ void PeriStimulusTimeHistogramNode::handleEvent(int eventType, MidiMessage& even
memcpy(&hardware_timestamp, dataptr + 4, 8); // remember to skip first four bytes memcpy(&hardware_timestamp, dataptr + 4, 8); // remember to skip first four bytes
memcpy(&software_timestamp, dataptr + 12, 8); // remember to skip first four bytes memcpy(&software_timestamp, dataptr + 12, 8); // remember to skip first four bytes
if (isRecording) /* if (isRecording)
{ {
if (syncCounter == 0) if (syncCounter == 0)
{ {
...@@ -459,7 +312,7 @@ void PeriStimulusTimeHistogramNode::handleEvent(int eventType, MidiMessage& even ...@@ -459,7 +312,7 @@ void PeriStimulusTimeHistogramNode::handleEvent(int eventType, MidiMessage& even
syncCounter++; syncCounter++;
if (syncCounter > 10) if (syncCounter > 10)
syncCounter = 0; syncCounter = 0;
} }*/
} }
if (eventType == TTL) if (eventType == TTL)
...@@ -476,8 +329,7 @@ void PeriStimulusTimeHistogramNode::handleEvent(int eventType, MidiMessage& even ...@@ -476,8 +329,7 @@ void PeriStimulusTimeHistogramNode::handleEvent(int eventType, MidiMessage& even
//memcpy(&ttl_timestamp_hardware, dataptr+12, 8); //memcpy(&ttl_timestamp_hardware, dataptr+12, 8);
if (ttl_raise) if (ttl_raise)
trialCircularBuffer->addTTLevent(channel,ttl_timestamp_software,ttl_timestamp_hardware, ttl_raise, true); trialCircularBuffer->addTTLevent(channel,ttl_timestamp_software,ttl_timestamp_hardware, ttl_raise, true);
if (isRecording && saveTTLs)
dumpTTLeventToDisk(channel,ttl_raise,ttl_timestamp_software,ttl_timestamp_hardware,samplePosition );
} }
if (eventType == SPIKE) if (eventType == SPIKE)
...@@ -494,12 +346,15 @@ void PeriStimulusTimeHistogramNode::handleEvent(int eventType, MidiMessage& even ...@@ -494,12 +346,15 @@ void PeriStimulusTimeHistogramNode::handleEvent(int eventType, MidiMessage& even
} }
if (isRecording) if (isRecording)
{ {
if (spikeSavingMode == 1 && newSpike.sortedId > 0) if (spikeSavingMode == 1 && newSpike.sortedId > 0)
dumpSpikeEventToDisk(&newSpike, false); recordNode->writeSpike(newSpike, electrodeChannels[newSpike.source]->recordIndex);
//dumpSpikeEventToDisk(&newSpike, false);
else if (spikeSavingMode == 2 && newSpike.sortedId > 0) else if (spikeSavingMode == 2 && newSpike.sortedId > 0)
dumpSpikeEventToDisk(&newSpike, true); recordNode->writeSpike(newSpike, electrodeChannels[newSpike.source]->recordIndex);
//dumpSpikeEventToDisk(&newSpike, true);
else if (spikeSavingMode == 3) else if (spikeSavingMode == 3)
dumpSpikeEventToDisk(&newSpike, true); recordNode->writeSpike(newSpike, electrodeChannels[newSpike.source]->recordIndex);
//dumpSpikeEventToDisk(&newSpike, true);
} }
} }
} }
...@@ -507,136 +362,12 @@ void PeriStimulusTimeHistogramNode::handleEvent(int eventType, MidiMessage& even ...@@ -507,136 +362,12 @@ void PeriStimulusTimeHistogramNode::handleEvent(int eventType, MidiMessage& even
} }
String PeriStimulusTimeHistogramNode::generateHeader()
{
String header = "header.format = 'Open Ephys Data Format'; \n";
header += "header.version = 0.32;";
header += "header.header_bytes = ";
header += String(HEADER_SIZE);
header += ";\n";
header += "header.description = 'each record is size-varying. First is the record size (16-bit), followed by record type (uint8), followed by the actual data (which vary, depending on the type) '; \n";
header += "header.date_created = '";
header += recordNode->generateDateString();
header += "';\n";
header += "header.channel = '";
header += "events";
header += "';\n";
header += "header.channelType = 'Event';\n";
header += "header.sampleRate = ";
// all channels need to have the same sample rate under the current scheme
header += String(getSampleRate());
header += ";\n";
header += "header.blockLength = ";
header += BLOCK_LENGTH;
header += ";\n";
header += "header.bufferSize = ";
header += getAudioComponent()->getBufferSize();
header += ";\n";
header += "header.bitVolts = ";
if (recordNode->channels.size() > 0)
{
header += String(recordNode->channels[0]->bitVolts);
}
else
{
header += String(getDefaultBitVolts());
}
header += ";\n";
Time t;
header += "header.ticksPerSec = ";
header += String(t.getHighResolutionTicksPerSecond());
header += ";\n";
header = header.paddedRight(' ', HEADER_SIZE);
return header;
}
void PeriStimulusTimeHistogramNode::openFile(String filename)
{
std::cout << "OPENING FILE: " << filename << std::endl;
File f = File(filename);
bool fileExists = f.exists();
const ScopedLock myScopedLock(diskWriteLock);
eventFile = fopen(filename.toUTF8(), "ab");
if (!fileExists)
{
// create and write header
std::cout << "Writing header." << std::endl;
String header = generateHeader();
int headerSize = header.getNumBytesAsUTF8();
std::cout << "File ID: " << eventFile << ", number of bytes: " << headerSize << std::endl;
fwrite(header.toUTF8(), header.getNumBytesAsUTF8(), 1, eventFile);
std::cout << "Wrote header." << std::endl;
}
else
{
std::cout << "File already exists, just opening." << std::endl;
}
}
void PeriStimulusTimeHistogramNode::startRecording() void PeriStimulusTimeHistogramNode::startRecording()
{ {
if (!isRecording) isRecording = true;
{
File dataDirectory = recordNode->getDataDirectory();
if (dataDirectory.getFullPathName().length() == 0)
{
// temporary fix in case nothing is returned by the record node.
dataDirectory = File::getSpecialLocation(File::userHomeDirectory);
}
String baseDirectory = dataDirectory.getFullPathName();
String eventChannelFilename = baseDirectory + dataDirectory.separatorString + "all_channels.events";
openFile(eventChannelFilename);
// dump network events that arrived when we weren't recording
if (saveNetworkEventsWhenNotRecording)
{
while (networkEventsHistory.size() > 0)
{
StringTS s = networkEventsHistory.front();
dumpNetworkEventToDisk(s.getString(),s.timestamp);
networkEventsHistory.pop();
}
}
// recordingNumber = recordNode->getRecordingNumber();
Time t;
dumpStartStopRecordEventToDisk(t.getHighResolutionTicks(), true);
isRecording = true;
}
} }
void PeriStimulusTimeHistogramNode::stopRecording() void PeriStimulusTimeHistogramNode::stopRecording()
{ {
if (isRecording) isRecording = false;
{ }
// close files, etc. \ No newline at end of file
const ScopedLock myScopedLock(diskWriteLock);
std::cout << "CLOSING EVENT FILE: " << std::endl;
if (eventFile != nullptr)
fclose(eventFile);
isRecording = false;
}
}
...@@ -90,17 +90,6 @@ public: ...@@ -90,17 +90,6 @@ public:
void handleNetworkMessage(StringTS s); void handleNetworkMessage(StringTS s);
private: private:
FILE* eventFile;
String generateHeader();
void openFile(String filename);
void dumpNetworkEventToDisk(String S, int64 ts);
void dumpSpikeEventToDisk(SpikeObject *s, bool dumpWave);
void dumpTimestampEventToDisk(int64 softwareTS,int64 hardwareTS);
void dumpTTLeventToDisk(int channel,bool risingEdge, int64 ttl_timestamp_software, int64 ttl_timestamp_hardware, int samplePosition );
void dumpStartStopRecordEventToDisk(int64 ts, bool startRecord);
// void dumpEyeTrackingEventToDisk(EyePosition pos);
bool isRecording; bool isRecording;
int displayBufferSize; int displayBufferSize;
bool redrawRequested; bool redrawRequested;
...@@ -109,8 +98,9 @@ private: ...@@ -109,8 +98,9 @@ private:
std::queue<StringTS> networkEventsHistory; std::queue<StringTS> networkEventsHistory;
RecordNode* recordNode; RecordNode* recordNode;
uint16 recordingNumber; // uint16 recordingNumber;
CriticalSection diskWriteLock; CriticalSection diskWriteLock;
Array<Channel*> electrodeChannels;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PeriStimulusTimeHistogramNode); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PeriStimulusTimeHistogramNode);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment