Skip to content

Commit bf9ef1c

Browse files
authored
Merge pull request #162 from open-ephys-plugins/issue-138
Add depth and shank information to Neuropixels channels
2 parents cbe6494 + 1e8d6c4 commit bf9ef1c

File tree

7 files changed

+96
-13
lines changed

7 files changed

+96
-13
lines changed

Source/Devices/Neuropixels1e.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ int Neuropixels1e::configureDevice()
135135

136136
LOGD ("Probe SN: ", probeMetadata.getProbeSerialNumber());
137137

138+
settings[0]->connected = probeMetadata.getProbeSerialNumber() != 0;
139+
138140
return ONI_ESUCCESS;
139141
}
140142

Source/Devices/Neuropixels1f.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ int Neuropixels1f::configureDevice()
127127

128128
LOGD ("Probe SN: ", probeMetadata.getProbeSerialNumber());
129129

130+
settings[0]->connected = probeMetadata.getProbeSerialNumber() != 0;
131+
130132
// Enable device streaming
131133
rc = deviceContext->writeRegister (deviceIdx, 0x8000, 1);
132134
if (rc != ONI_ESUCCESS)

Source/Devices/Neuropixels2e.cpp

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -316,18 +316,22 @@ int Neuropixels2e::configureDevice()
316316
LOGD ("Probe A SN: ", probeMetadata[0].getProbeSerialNumber());
317317
LOGD ("Probe B SN: ", probeMetadata[1].getProbeSerialNumber());
318318

319-
if (probeMetadata[0].getProbeSerialNumber() == 0 && probeMetadata[1].getProbeSerialNumber() == 0)
320-
{
321-
m_numProbes = 0;
322-
throw error_str ("No probes were found connected at address " + std::to_string (getDeviceIdx()));
323-
}
324-
else if (probeMetadata[0].getProbeSerialNumber() != 0 && probeMetadata[1].getProbeSerialNumber() != 0)
319+
m_numProbes = 0;
320+
321+
for(int i = 0; i < NumberOfProbes; i++)
325322
{
326-
m_numProbes = 2;
323+
if (probeMetadata[i].getProbeSerialNumber() != 0)
324+
{
325+
settings[i]->connected = true;
326+
m_numProbes++;
327+
}
328+
else
329+
settings[i]->connected = false;
327330
}
328-
else
331+
332+
if (m_numProbes == 0)
329333
{
330-
m_numProbes = 1;
334+
throw error_str ("No probes were found connected at address " + std::to_string (getDeviceIdx()));
331335
}
332336

333337
streamInfos.clear();
@@ -342,9 +346,9 @@ int Neuropixels2e::configureDevice()
342346

343347
bool Neuropixels2e::updateSettings()
344348
{
345-
for (int i = 0; i < 2; i++)
349+
for (int i = 0; i < NumberOfProbes; i++)
346350
{
347-
if (probeMetadata[i].getProbeSerialNumber() != 0)
351+
if (settings[i]->connected)
348352
{
349353
if (! NeuropixelsProbeMetadata::validateProbeTypeAndPartNumber (settings[i]->probeType, probeMetadata[i]))
350354
{
@@ -416,7 +420,7 @@ bool Neuropixels2e::updateSettings()
416420

417421
for (int i = 0; i < NumberOfProbes; i++)
418422
{
419-
if (probeMetadata[i].getProbeSerialNumber() != 0)
423+
if (settings[i]->connected)
420424
{
421425
selectProbe (serializer.get(), i == 0 ? ProbeASelected : ProbeBSelected);
422426
writeConfiguration (settings[i].get());
@@ -554,7 +558,7 @@ void Neuropixels2e::addSourceBuffers (OwnedArray<DataBuffer>& sourceBuffers)
554558
if (m_numProbes == 1)
555559
{
556560
sourceBuffers.add (new DataBuffer (streamInfos.getFirst().getNumChannels(), (int) streamInfos.getFirst().getSampleRate() * bufferSizeInSeconds));
557-
auto bufferIndex = probeMetadata[0].getProbeSerialNumber() != 0 ? 0 : 1;
561+
auto bufferIndex = settings[0]->connected ? 0 : 1;
558562
amplifierBuffer[bufferIndex] = sourceBuffers.getLast();
559563
}
560564
else

Source/NeuropixelsComponents.h

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,7 @@ struct ProbeSettings
287287
lfpGainIndex = newSettings->lfpGainIndex;
288288
referenceIndex = newSettings->referenceIndex;
289289
apFilterState = newSettings->apFilterState;
290+
connected = newSettings->connected;
290291

291292
selectedBank = newSettings->selectedBank;
292293
selectedShank = newSettings->selectedShank;
@@ -344,6 +345,7 @@ struct ProbeSettings
344345
int lfpGainIndex = 0;
345346
int referenceIndex = 0;
346347
bool apFilterState = false;
348+
bool connected = false;
347349

348350
std::vector<Bank> selectedBank;
349351
std::vector<int> selectedShank;
@@ -562,4 +564,67 @@ static class NeuropixelsV1
562564
return baseConfigs;
563565
}
564566
};
567+
568+
static class NeuropixelsHelpers
569+
{
570+
public:
571+
/** Set all channel metadata, starting with the last (most recently added) channel and working backwards over all selected electrodes */
572+
static void setChannelMetadata (OwnedArray<ContinuousChannel>* continuousChannels, const std::vector<std::unique_ptr<ProbeSettings>>& probeSettings)
573+
{
574+
ContinuousChannel** channels = continuousChannels->end();
575+
channels--;
576+
577+
for (auto it = probeSettings.rbegin(); it != probeSettings.rend(); it++)
578+
{
579+
ProbeSettings* probeSetting = it->get();
580+
581+
if (! probeSetting->connected)
582+
continue;
583+
584+
for (int i = probeSetting->numberOfChannels - 1; i >= 0; i--)
585+
{
586+
auto channel = *channels--;
587+
588+
int globalIndex = probeSetting->selectedElectrode[i];
589+
int shankIndex = probeSetting->electrodeMetadata[globalIndex].shank;
590+
591+
float xpos = probeSetting->electrodeMetadata[globalIndex].xpos;
592+
float ypos = probeSetting->electrodeMetadata[globalIndex].ypos;
593+
594+
// NB: Depth must be a unique value for compatibility with legacy LFP viewer channel sorting algorithm
595+
float depth = ypos + (float)shankIndex * 10000.0f + xpos * 0.001f;
596+
597+
channel->position.x = xpos;
598+
channel->position.y = depth;
599+
600+
channel->group.name = "Shank " + String (shankIndex + 1);
601+
channel->group.number = shankIndex;
602+
603+
// NB: Add real Y position as a metadata descriptor
604+
MetadataDescriptor yposDescriptor (MetadataDescriptor::MetadataType::FLOAT,
605+
1,
606+
"ypos",
607+
"Channel y-position (relative to shank tip)",
608+
"channel.ypos");
609+
610+
MetadataValue yposValue (MetadataDescriptor::MetadataType::FLOAT, 1);
611+
yposValue.setValue (ypos);
612+
613+
channel->addMetadata (yposDescriptor, yposValue);
614+
615+
// NB: Add electrode index as metadata
616+
MetadataDescriptor selectedElectrodeDescriptor (MetadataDescriptor::MetadataType::UINT16,
617+
1,
618+
"electrode_index",
619+
"Electrode index for this channel",
620+
"neuropixels.electrode_index");
621+
622+
MetadataValue selectedElectrodeValue (MetadataDescriptor::MetadataType::UINT16, 1);
623+
selectedElectrodeValue.setValue ((uint16) globalIndex);
624+
625+
channel->addMetadata (selectedElectrodeDescriptor, selectedElectrodeValue);
626+
}
627+
}
628+
}
629+
};
565630
} // namespace OnixSourcePlugin

Source/OnixSource.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,8 @@ void OnixSource::updateSettings (OwnedArray<ContinuousChannel>* continuousChanne
836836
deviceInfos->add (device);
837837

838838
addIndividualStreams (source->streamInfos, dataStreams, deviceInfos, continuousChannels);
839+
840+
NeuropixelsHelpers::setChannelMetadata (continuousChannels, std::static_pointer_cast<Neuropixels1f> (source)->settings);
839841
}
840842
else if (type == OnixDeviceType::BNO || type == OnixDeviceType::POLLEDBNO)
841843
{
@@ -885,6 +887,8 @@ void OnixSource::updateSettings (OwnedArray<ContinuousChannel>* continuousChanne
885887
deviceInfos->add (device);
886888

887889
addIndividualStreams (source->streamInfos, dataStreams, deviceInfos, continuousChannels);
890+
891+
NeuropixelsHelpers::setChannelMetadata (continuousChannels, std::static_pointer_cast<Neuropixels2e> (source)->settings);
888892
}
889893
else if (type == OnixDeviceType::MEMORYMONITOR)
890894
{
@@ -979,6 +983,8 @@ void OnixSource::updateSettings (OwnedArray<ContinuousChannel>* continuousChanne
979983
deviceInfos->add (device);
980984

981985
addIndividualStreams (source->streamInfos, dataStreams, deviceInfos, continuousChannels);
986+
987+
NeuropixelsHelpers::setChannelMetadata (continuousChannels, std::static_pointer_cast<Neuropixels1e> (source)->settings);
982988
}
983989
else if (type == OnixDeviceType::OUTPUTCLOCK)
984990
{

Source/UI/NeuropixelsV1Interface.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -925,6 +925,8 @@ void NeuropixelsV1Interface::selectElectrodes (std::vector<int> electrodes)
925925
{
926926
std::static_pointer_cast<Neuropixels1> (device)->settings[0]->selectElectrodes (electrodes);
927927

928+
CoreServices::updateSignalChain (editor);
929+
928930
repaint();
929931
}
930932

Source/UI/NeuropixelsV2eProbeInterface.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,8 @@ void NeuropixelsV2eProbeInterface::selectElectrodes (std::vector<int> electrodes
682682
{
683683
std::static_pointer_cast<Neuropixels2e> (device)->settings[probeIndex]->selectElectrodes (electrodes);
684684

685+
CoreServices::updateSignalChain (editor);
686+
685687
repaint();
686688
}
687689

0 commit comments

Comments
 (0)