diff --git a/Source/Processors/Editors/SpikeSorterEditor.cpp b/Source/Processors/Editors/SpikeSorterEditor.cpp index fc286491a21271086d24fdf91c9cbd0b50208886..fc7340e4a73795bdd69d14d4ae94df87ab03aa23 100644 --- a/Source/Processors/Editors/SpikeSorterEditor.cpp +++ b/Source/Processors/Editors/SpikeSorterEditor.cpp @@ -431,6 +431,8 @@ void SpikeSorterEditor::buttonEvent(Button* button) processor->addProbes(ProbeType,numProbes, nElectrodes,nChansPerElectrode, firstElectrodeOffset,interelectrodeDistance); refreshElectrodeList(); + + getEditorViewport()->makeEditorVisible(this, true, true); return; diff --git a/Source/Processors/SpikeSortBoxes.cpp b/Source/Processors/SpikeSortBoxes.cpp index 8c972882a6a5bc317930d5e19d2034154c8b51f7..d399221d3c44ee497f09df699ef418d0061d1990 100644 --- a/Source/Processors/SpikeSortBoxes.cpp +++ b/Source/Processors/SpikeSortBoxes.cpp @@ -1743,8 +1743,9 @@ float PCAjob::pythag(float a, float b) { V (not V transpose) is output as the matrix V[nCols][nCols]. */ int PCAjob::svdcmp(float **a, int nRows, int nCols, float *w, float **v) { - int flag,i,its,j,jj,k,l,nm; - float anorm,c,f,g,h,s,scale,x,y,z,*rv1; + + int flag, i, its, j, jj, k, l, nm; + float anorm, c, f, g, h, s, scale, x, y, z, *rv1; rv1 = new float[nCols]; if(rv1 == NULL) { @@ -1753,14 +1754,14 @@ int PCAjob::svdcmp(float **a, int nRows, int nCols, float *w, float **v) { } g = scale = anorm = 0.0; - for(i=0;i<nCols;i++) { + for(i = 0; i < nCols; i++) { l = i+1; rv1[i] = scale*g; g = s = scale = 0.0; if(i < nRows) { - for(k=i;k<nRows;k++) scale += fabs(a[k][i]); + for(k = i; k < nRows; k++) scale += fabs(a[k][i]); if(scale) { - for(k=i;k<nRows;k++) { + for(k = i; k < nRows; k++) { a[k][i] /= scale; s += a[k][i] * a[k][i]; } @@ -1768,20 +1769,21 @@ int PCAjob::svdcmp(float **a, int nRows, int nCols, float *w, float **v) { g = -SIGN(sqrt(s),f); h = f * g - s; a[i][i] = f - g; - for(j=l;j<nCols;j++) { - for(s=0.0,k=i;k<nRows;k++) s += a[k][i] * a[k][j]; + for(j = l; j < nCols; j++) { + for(s = 0.0, k = i; k < nRows; k++) s += a[k][i] * a[k][j]; f = s / h; - for(k=i;k<nRows;k++) a[k][j] += f * a[k][i]; + for(k = i; k < nRows; k++) a[k][j] += f * a[k][i]; } - for(k=i;k<nRows;k++) a[k][i] *= scale; + for(k = i; k < nRows; k++) a[k][i] *= scale; } } w[i] = scale * g; g = s = scale = 0.0; if(i < nRows && i != nCols-1) { - for(k=l;k<nCols;k++) scale += fabs(a[i][k]); + for(k = l; k < nCols; k++) scale += fabs(a[i][k]); if(scale) { - for(k=l;k<nCols;k++) { + for(k = l; k < nCols; k++) + { a[i][k] /= scale; s += a[i][k] * a[i][k]; } @@ -1939,8 +1941,8 @@ void PCAjob::computeCov() { // allocate and zero cov = new float*[dim]; - float *mean = new float[dim]; - for (int k=0;k<dim;k++) { + float* mean = new float[dim]; + for (int k = 0;k < dim; k++) { cov[k] = new float[dim]; for (int j=0;j<dim;j++) { @@ -1981,6 +1983,13 @@ void PCAjob::computeCov() } delete mean; + // delete covariances + for (int k = 0; k < dim; k++) + delete cov[k]; + + delete(cov); + cov = nullptr; + } std::vector<int> sort_indexes( std::vector<float> v) @@ -1993,16 +2002,15 @@ std::vector<int> sort_indexes( std::vector<float> v) idx[i] = i; } - //// NEED TO FIX THIS:::: -- Linux compiler doesn't understand syntax! - // sort indexes based on comparing values in v - // sort( - // idx.begin(), - // idx.end(), - // [&v](size_t i1, size_t i2) - // { - // return v[i1] > v[i2]; - // } - // ); + //sort indexes based on comparing values in v + sort( + idx.begin(), + idx.end()//, + //[&v](size_t i1, size_t i2) + //{ + // return v[i1] > v[i2]; + //} + ); return idx; } @@ -2015,30 +2023,23 @@ void PCAjob::computeSVD() sigvalues = new float[dim]; eigvec = new float*[dim]; - for (int k=0;k<dim;k++) { + for (int k = 0; k < dim; k++) { eigvec[k] = new float[dim]; for (int j=0;j<dim;j++) { eigvec[k][j] = 0; } } - - svdcmp(cov, dim, dim, sigvalues,eigvec ); - // find the two largest eigen values - for (int k=0;k<dim;k++) - delete cov[k]; - delete(cov); - cov=nullptr; + svdcmp(cov, dim, dim, sigvalues, eigvec); + - std::vector<float> sig; - sig.resize(dim); - for (int k=0;k<dim;k++) - sig[k] = sigvalues[k]; - + std::vector<float> sig; + sig.resize(dim); + for (int k = 0; k < dim; k++) + sig[k] = sigvalues[k]; - std::vector<int> sortind = sort_indexes(sig); // @@ -2076,7 +2077,7 @@ void PCAjob::computeSVD() *pc2max = max2 + 1.5 * (max2-min2); // clear memory - for (int k=0;k<dim;k++) + for (int k = 0; k < dim; k++) { delete eigvec[k]; } diff --git a/Source/Processors/SpikeSorter.cpp b/Source/Processors/SpikeSorter.cpp index 12b317ed4df9408b435919f83f25f281b1b61461..7eb8cf1a08e7d63b89b551305706d2f3a0890f09 100644 --- a/Source/Processors/SpikeSorter.cpp +++ b/Source/Processors/SpikeSorter.cpp @@ -188,13 +188,19 @@ void SpikeSorter::updateSettings() double ContinuousBufferLengthSec = 5; channelBuffers = new ContinuousCircularBuffer(numChannels,SamplingRate,1, ContinuousBufferLengthSec); - // instead, we pass things now in this new form: - for (int k = 0; k < electrodes.size(); k++) + for (int i = 0; i < electrodes.size(); i++) { - String eventlog = "NewElectrode "+String(electrodes[k]->electrodeID) + " "+String(electrodes[k]->numChannels)+" "; - for (int j=0;j<electrodes[k]->numChannels;j++) - eventlog += String(electrodes[k]->channels[j])+ " "+electrodes[k]->name; - //addNetworkEventToQueue(StringTS(eventlog)); + + Channel* ch = new Channel(this, i); + //ch->isEventChannel = true; + ch->eventType = SPIKE_BASE_CODE + electrodes[i]->numChannels; + ch->name = electrodes[i]->name; + + eventChannels.add(ch); + // String eventlog = "NewElectrode "+String(electrodes[k]->electrodeID) + " "+String(electrodes[k]->numChannels)+" "; + // for (int j=0;j<electrodes[k]->numChannels;j++) + // eventlog += String(electrodes[k]->channels[j])+ " "+electrodes[k]->name; + // //addNetworkEventToQueue(StringTS(eventlog)); } mut.exit(); @@ -319,14 +325,14 @@ void SpikeSorter::addNewUnit(int electrodeID, int newUnitID, uint8 r, uint8 g, u { String eventlog = "NewUnit "+String(electrodeID) + " "+String(newUnitID)+" "+String(r)+" "+String(g)+" "+String(b); //addNetworkEventToQueue(StringTS(eventlog)); - updateSinks( electrodeID, newUnitID, r,g,b,true); + //updateSinks( electrodeID, newUnitID, r,g,b,true); } void SpikeSorter::removeUnit(int electrodeID, int unitID) { String eventlog = "RemoveUnit "+String(electrodeID) + " "+String(unitID); //addNetworkEventToQueue(StringTS(eventlog)); - updateSinks( electrodeID, unitID, 0,0,0,false); + //updateSinks( electrodeID, unitID, 0,0,0,false); } @@ -335,7 +341,7 @@ void SpikeSorter::removeAllUnits(int electrodeID) { String eventlog = "RemoveAllUnits "+String(electrodeID); //addNetworkEventToQueue(StringTS(eventlog)); - updateSinks( electrodeID,true); + //updateSinks( electrodeID,true); } RHD2000Thread* SpikeSorter::getRhythmAccess() @@ -397,171 +403,13 @@ void SpikeSorter::assignDACtoChannel(int dacOutput, int channel) } } - -void SpikeSorter::updateSinks(int electrodeID, int unitID, uint8 r, uint8 g, uint8 b, bool addRemove) -{ - // inform sinks about a new unit - ProcessorGraph *gr = getProcessorGraph(); - Array<GenericProcessor*> p = gr->getListOfProcessors(); - // for (int k=0;k<p.size();k++) - // { - // if (p[k]->getName() == "PSTH") - // { - // PeriStimulusTimeHistogramNode *node = (PeriStimulusTimeHistogramNode*)p[k]; - // if (node->trialCircularBuffer != nullptr) - // { - // if (addRemove) - // { - // // add electrode - // node->trialCircularBuffer->addNewUnit(electrodeID,unitID,r,g,b); - // } else - // { - // // remove electrode - // node->trialCircularBuffer->removeUnit(electrodeID,unitID); - // } - // ((PeriStimulusTimeHistogramEditor *) node->getEditor())->updateCanvas(); - // } - // } - // } -} - -void SpikeSorter::updateSinks(int electrodeID, bool rem) -{ - // inform sinks about a removal of all units - ProcessorGraph *g = getProcessorGraph(); - Array<GenericProcessor*> p = g->getListOfProcessors(); - // for (int k=0;k<p.size();k++) - // { - // if (p[k]->getName() == "PSTH") - // { - // PeriStimulusTimeHistogramNode *node = (PeriStimulusTimeHistogramNode*)p[k]; - // if (node->trialCircularBuffer != nullptr) - // { - // if (rem) - // { - // node->trialCircularBuffer->removeAllUnits(electrodeID); - // } - // (((PeriStimulusTimeHistogramEditor *) node->getEditor()))->updateCanvas(); - // } - // } - // if (p[k]->getName() == "Spike Viewer") - // { - // SpikeDisplayNode* node = (SpikeDisplayNode*)p[k]; - // node->syncWithSpikeSorter(); - // } - // } -} - -void SpikeSorter::updateSinks(int electrodeID, int channelindex, int newchannel) -{ - // inform sinks about a channel change - ProcessorGraph *g = getProcessorGraph(); - Array<GenericProcessor*> p = g->getListOfProcessors(); - // for (int k=0;k<p.size();k++) - // { - // if (p[k]->getName() == "PSTH") - // { - // PeriStimulusTimeHistogramNode *node = (PeriStimulusTimeHistogramNode*)p[k]; - // if (node->trialCircularBuffer != nullptr) - // { - // node->trialCircularBuffer->channelChange(electrodeID, channelindex,newchannel); - // } - // } - // if (p[k]->getName() == "Spike Viewer") - // { - // SpikeDisplayNode* node = (SpikeDisplayNode*)p[k]; - // node->syncWithSpikeSorter(); - // } - // } -} - - -void SpikeSorter::updateSinks(Electrode* electrode) -{ - // inform sinks about an electrode add - ProcessorGraph *g = getProcessorGraph(); - Array<GenericProcessor*> p = g->getListOfProcessors(); - // for (int k=0;k<p.size();k++) - // { - // String s = p[k]->getName(); - // if (p[k]->getName() == "PSTH") - // { - // PeriStimulusTimeHistogramNode *node = (PeriStimulusTimeHistogramNode*)p[k]; - // if (node->trialCircularBuffer != nullptr) - // { - // // add electrode - // node->trialCircularBuffer->addNewElectrode(electrode); - // (((PeriStimulusTimeHistogramEditor *) node->getEditor()))->updateCanvas(); - // } - // } - // if (p[k]->getName() == "Spike Viewer") - // { - // SpikeDisplayNode* node = (SpikeDisplayNode*)p[k]; - // node->syncWithSpikeSorter(); - // } - // } -} - -void SpikeSorter::updateSinks(int electrodeID, String NewName) -{ - // inform sinks about an electrode name change - ProcessorGraph *g = getProcessorGraph(); - Array<GenericProcessor*> p = g->getListOfProcessors(); - // for (int k=0;k<p.size();k++) - // { - // String s = p[k]->getName(); - // if (p[k]->getName() == "PSTH") - // { - // PeriStimulusTimeHistogramNode *node = (PeriStimulusTimeHistogramNode*)p[k]; - // if (node->trialCircularBuffer != nullptr) - // { - // // add electrode - // node->trialCircularBuffer->updateElectrodeName(electrodeID, NewName); - // (((PeriStimulusTimeHistogramEditor *) node->getEditor()))->updateCanvas(); - // } - // } - // if (p[k]->getName() == "Spike Viewer") - // { - // SpikeDisplayNode* node = (SpikeDisplayNode*)p[k]; - // node->syncWithSpikeSorter(); - // } - // } -} - - -void SpikeSorter::updateSinks(int electrodeID) -{ - // inform sinks about an electrode removal - ProcessorGraph *g = getProcessorGraph(); - Array<GenericProcessor*> p = g->getListOfProcessors(); - // for (int k=0;k<p.size();k++) - // { - // String s = p[k]->getName(); - // if (p[k]->getName() == "PSTH") - // { - // PeriStimulusTimeHistogramNode *node = (PeriStimulusTimeHistogramNode*)p[k]; - // if (node->trialCircularBuffer != nullptr) - // { - // // remove electrode - // node->trialCircularBuffer->removeElectrode(electrodeID); - // ((PeriStimulusTimeHistogramEditor *) node->getEditor())->updateCanvas(); - // } - // } - // if (p[k]->getName() == "Spike Viewer") - // { - // SpikeDisplayNode* node = (SpikeDisplayNode*)p[k]; - // node->syncWithSpikeSorter(); - // } - // } -} - void SpikeSorter::addElectrode(Electrode* newElectrode) { mut.enter(); resetElectrode(newElectrode); electrodes.add(newElectrode); // inform PSTH sink, if it exists, about this new electrode. - updateSinks(newElectrode); + //updateSinks(newElectrode); mut.exit(); } @@ -605,7 +453,7 @@ bool SpikeSorter::addElectrode(int nChans, String name, double Depth) resetElectrode(newElectrode); electrodes.add(newElectrode); - updateSinks(newElectrode); + //updateSinks(newElectrode); setCurrentElectrodeIndex(electrodes.size()-1); mut.exit(); return true; @@ -654,7 +502,7 @@ bool SpikeSorter::removeElectrode(int index) int idToRemove = electrodes[index]->electrodeID; electrodes.remove(index); - updateSinks(idToRemove); + //(idToRemove); if (electrodes.size() > 0) currentElectrode = electrodes.size()-1; @@ -669,7 +517,7 @@ void SpikeSorter::setElectrodeName(int index, String newName) { mut.enter(); electrodes[index-1]->name = newName; - updateSinks(electrodes[index-1]->electrodeID, newName); + //updateSinks(electrodes[index-1]->electrodeID, newName); mut.exit(); } @@ -685,7 +533,7 @@ void SpikeSorter::setChannel(int electrodeIndex, int channelNum, int newChannel) String eventlog = "ChanelElectrodeChannel " + String(electrodes[electrodeIndex]->electrodeID) + " " + String(channelNum) + " " + String(newChannel); //addNetworkEventToQueue(StringTS(eventlog)); - updateSinks(electrodes[electrodeIndex]->electrodeID, channelNum,newChannel); + //updateSinks(electrodes[electrodeIndex]->electrodeID, channelNum,newChannel); *(electrodes[electrodeIndex]->channels+channelNum) = newChannel; mut.exit(); diff --git a/Source/Processors/SpikeSorter.h b/Source/Processors/SpikeSorter.h index 3df7bddc4edd1ad6c744948e66a2b7ab2185074b..82136225e4c17963071dd4a8f89c6f84d5d0697c 100644 --- a/Source/Processors/SpikeSorter.h +++ b/Source/Processors/SpikeSorter.h @@ -238,19 +238,6 @@ public: /** returns a channel's detection threshold */ double getChannelThreshold(int electrodeNum, int channelNum); - - /** sync PSTH : inform of a new electrode added */ - void updateSinks(Electrode* newElectrode); - /** sync PSTH : inform of an electrode removal */ - void updateSinks(int electrodeID); - /** sync PSTH : inform of a channel swap */ - void updateSinks(int electrodeID, int channelindex, int newchannel); - /** sync PSTH: inform of a new unit added / removed */ - void updateSinks(int electrodeID, int unitID, uint8 r, uint8 g, uint8 b, bool addRemove); - /** sync PSTH: inform of a name change*/ - void updateSinks(int electrodeID, String NewName); - /** sync PSTH: remove all units*/ - void updateSinks(int electrodeID, bool b); /** used to generate messages over the network and to inform PSTH sink */ void addNewUnit(int electrodeID, int newUnitID, uint8 r, uint8 g, uint8 b); diff --git a/Source/Processors/Visualization/SpikeDisplayCanvas.cpp b/Source/Processors/Visualization/SpikeDisplayCanvas.cpp index 7145dca563b4775c91d34def9e2cfcc2d91a21f0..67db2c80ca9c6f5740705461a04ce4d9134fa496 100755 --- a/Source/Processors/Visualization/SpikeDisplayCanvas.cpp +++ b/Source/Processors/Visualization/SpikeDisplayCanvas.cpp @@ -486,12 +486,14 @@ float SpikeDisplay::getRangeForWaveAxis(int plotNum, int axisNum) void SpikeDisplay::setThresholdForWaveAxis(int plotNum, int axisNum, float range) { - return spikePlots[plotNum]->setDisplayThresholdForChannel(axisNum, range); + if (spikePlots.size() > plotNum) + return spikePlots[plotNum]->setDisplayThresholdForChannel(axisNum, range); } void SpikeDisplay::setRangeForWaveAxis(int plotNum, int axisNum, float range) { - return spikePlots[plotNum]->setRangeForChannel(axisNum, range); + if (spikePlots.size() > plotNum) + return spikePlots[plotNum]->setRangeForChannel(axisNum, range); } // ---------------------------------------------------------------- diff --git a/Source/Processors/Visualization/SpikeSorterCanvas.cpp b/Source/Processors/Visualization/SpikeSorterCanvas.cpp index cccddfbff3f9edca6eae7e2cce022ab2dc70219a..170f41189b2c4af5a86e0e85eed5ac063076f1aa 100644 --- a/Source/Processors/Visualization/SpikeSorterCanvas.cpp +++ b/Source/Processors/Visualization/SpikeSorterCanvas.cpp @@ -108,14 +108,14 @@ void SpikeSorterCanvas::beginAnimation() { std::cout << "SpikeSorterCanvas beginning animation." << std::endl; - //startCallbacks(); + startCallbacks(); } void SpikeSorterCanvas::endAnimation() { std::cout << "SpikeSorterCanvas ending animation." << std::endl; - // stopCallbacks(); + stopCallbacks(); } void SpikeSorterCanvas::update() @@ -380,7 +380,7 @@ void SpikeSorterCanvas::buttonClicked(Button* button) // generate new IDs processor->getActiveElectrode()->spikeSort->generateNewIDs(); electrode->spikePlot->updateUnitsFromProcessor(); - processor->updateSinks(electrode->electrodeID,false); + //processor->updateSinks(electrode->electrodeID,false); } else if (button == deleteAllUnits) { // delete unit @@ -1853,20 +1853,20 @@ void PCAProjectionAxes::drawProjectedSpike(SpikeObject s) void PCAProjectionAxes::redraw(bool subsample) { -// Graphics g(projectionImage); -// -// // recompute image -// int w = getWidth(); -// int h = getHeight(); -// projectionImage.clear(juce::Rectangle<int>(0, 0, projectionImage.getWidth(), projectionImage.getHeight()), -// Colours::black); -// -// int dk = (subsample) ? 5 : 1; -// -// for (int k=0;k<bufferSize;k+=dk) -// { -// drawProjectedSpike(spikeBuffer[k]); -// } + Graphics g(projectionImage); + + // recompute image + int w = getWidth(); + int h = getHeight(); + projectionImage.clear(juce::Rectangle<int>(0, 0, projectionImage.getWidth(), projectionImage.getHeight()), + Colours::black); + + int dk = (subsample) ? 5 : 1; + + for (int k=0;k<bufferSize;k+=dk) + { + drawProjectedSpike(spikeBuffer[k]); + } }