Skip to content

Commit cbe6494

Browse files
authored
Merge pull request #152 from open-ephys-plugins/issue-151
Add Neuropixels 2.0 Single Shank Probes
2 parents f87261f + be5c8eb commit cbe6494

17 files changed

+794
-609
lines changed

Source/Devices/Neuropixels1.cpp

Lines changed: 58 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ Neuropixels1::Neuropixels1 (std::string name, std::string hubName, OnixDeviceTyp
4747
{
4848
}
4949

50-
void Neuropixels1::setSettings (ProbeSettings<NeuropixelsV1Values::numberOfChannels, NeuropixelsV1Values::numberOfElectrodes>* settings_, int index)
50+
void Neuropixels1::setSettings (ProbeSettings* settings_, int index)
5151
{
5252
if (index >= settings.size())
5353
{
@@ -58,47 +58,55 @@ void Neuropixels1::setSettings (ProbeSettings<NeuropixelsV1Values::numberOfChann
5858
settings[index]->updateProbeSettings (settings_);
5959
}
6060

61-
std::vector<int> Neuropixels1::selectElectrodeConfiguration (int electrodeConfigurationIndex)
61+
std::vector<int> Neuropixels1::selectElectrodeConfiguration (int electrodeConfigurationIndex, ProbeType probeType)
6262
{
6363
std::vector<int> selection;
6464

65-
if (electrodeConfigurationIndex == (int32_t) ElectrodeConfiguration::BankA)
65+
if (probeType == ProbeType::NPX_V1)
6666
{
67-
for (int i = 0; i < 384; i++)
68-
selection.emplace_back (i);
69-
}
70-
else if (electrodeConfigurationIndex == (int32_t) ElectrodeConfiguration::BankB)
71-
{
72-
for (int i = 384; i < 768; i++)
73-
selection.emplace_back (i);
74-
}
75-
else if (electrodeConfigurationIndex == (int32_t) ElectrodeConfiguration::BankC)
76-
{
77-
for (int i = 576; i < 960; i++)
78-
selection.emplace_back (i);
79-
}
80-
else if (electrodeConfigurationIndex == (int32_t) ElectrodeConfiguration::SingleColumn)
81-
{
82-
for (int i = 0; i < 384; i += 2)
83-
selection.emplace_back (i);
84-
85-
for (int i = 385; i < 768; i += 2)
86-
selection.emplace_back (i);
87-
}
88-
else if (electrodeConfigurationIndex == (int32_t) ElectrodeConfiguration::Tetrodes)
89-
{
90-
for (int i = 0; i < 384; i += 8)
67+
if (electrodeConfigurationIndex == (int32_t) ElectrodeConfiguration::BankA)
9168
{
92-
for (int j = 0; j < 4; j++)
93-
selection.emplace_back (i + j);
69+
for (int i = 0; i < 384; i++)
70+
selection.emplace_back (i);
9471
}
72+
else if (electrodeConfigurationIndex == (int32_t) ElectrodeConfiguration::BankB)
73+
{
74+
for (int i = 384; i < 768; i++)
75+
selection.emplace_back (i);
76+
}
77+
else if (electrodeConfigurationIndex == (int32_t) ElectrodeConfiguration::BankC)
78+
{
79+
for (int i = 576; i < 960; i++)
80+
selection.emplace_back (i);
81+
}
82+
else if (electrodeConfigurationIndex == (int32_t) ElectrodeConfiguration::SingleColumn)
83+
{
84+
for (int i = 0; i < 384; i += 2)
85+
selection.emplace_back (i);
9586

96-
for (int i = 388; i < 768; i += 8)
87+
for (int i = 385; i < 768; i += 2)
88+
selection.emplace_back (i);
89+
}
90+
else if (electrodeConfigurationIndex == (int32_t) ElectrodeConfiguration::Tetrodes)
9791
{
98-
for (int j = 0; j < 4; j++)
99-
selection.emplace_back (i + j);
92+
for (int i = 0; i < 384; i += 8)
93+
{
94+
for (int j = 0; j < 4; j++)
95+
selection.emplace_back (i + j);
96+
}
97+
98+
for (int i = 388; i < 768; i += 8)
99+
{
100+
for (int j = 0; j < 4; j++)
101+
selection.emplace_back (i + j);
102+
}
100103
}
101104
}
105+
else
106+
{
107+
LOGE ("Invalid probe type given for a Neuropixels 2.0 device: ", ProbeTypeString.at (probeType));
108+
return selection;
109+
}
102110

103111
assert (selection.size() == numberOfChannels && "Invalid number of selected channels.");
104112

@@ -169,9 +177,9 @@ void Neuropixels1::updateLfpOffsets (std::array<float, numLfpSamples>& samples,
169177
}
170178
}
171179

172-
void Neuropixels1::defineMetadata (ProbeSettings<numberOfChannels, numberOfElectrodes>* settings)
180+
void Neuropixels1::defineMetadata (ProbeSettings* settings, ProbeType probeType)
173181
{
174-
settings->probeType = ProbeType::NPX_V1;
182+
settings->probeType = probeType;
175183
settings->probeMetadata.name = "Neuropixels 1.0";
176184

177185
std::vector<std::array<float, 2>> shankOutline {
@@ -200,13 +208,6 @@ void Neuropixels1::defineMetadata (ProbeSettings<numberOfChannels, numberOfElect
200208
settings->probeMetadata.num_adcs = 32; // NB: Is this right for 1.0e?
201209
settings->probeMetadata.adc_bits = 10; // NB: Is this right for 1.0e?
202210

203-
settings->availableBanks = {
204-
Bank::A,
205-
Bank::B,
206-
Bank::C,
207-
Bank::NONE // disconnected
208-
};
209-
210211
Array<float> xpositions = { 27.0f, 59.0f, 11.0f, 43.0f };
211212

212213
for (int i = 0; i < numberOfElectrodes; i++)
@@ -296,8 +297,6 @@ void Neuropixels1::defineMetadata (ProbeSettings<numberOfChannels, numberOfElect
296297
settings->electrodeConfigurationIndex = (int32_t) ElectrodeConfiguration::BankA;
297298
auto selection = selectElectrodeConfiguration (settings->electrodeConfigurationIndex);
298299
settings->selectElectrodes (selection);
299-
300-
settings->isValid = true;
301300
}
302301

303302
uint64_t Neuropixels1::getProbeSerialNumber (int index)
@@ -529,3 +528,19 @@ void Neuropixels1::setGainCalibrationFilePath (std::string filepath)
529528
{
530529
gainCalibrationFilePath = filepath;
531530
}
531+
532+
bool Neuropixels1::validateProbeTypeAndPartNumber()
533+
{
534+
if (! NeuropixelsProbeMetadata::validateProbeTypeAndPartNumber (settings[0]->probeType, probeMetadata))
535+
{
536+
Onix1::showWarningMessageBoxAsync ("Probe Type / Number Mismatch",
537+
"The selected probe type is " + ProbeTypeString.at (settings[0]->probeType)
538+
+ "', but the connected probe is '" + NeuropixelsProbeMetadata::getProbeTypeString (probeMetadata.getProbePartNumber())
539+
+ "'. Please select the correct probe type to match the connected probe."
540+
+ ".\n\nProbe serial number: " + std::to_string (probeMetadata.getProbeSerialNumber()));
541+
return false;
542+
}
543+
544+
return true;
545+
}
546+

Source/Devices/Neuropixels1.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,12 @@ class Neuropixels1 : public INeuropixel<NeuropixelsV1Values::numberOfChannels, N
4747
void setGainCalibrationFilePath (std::string filepath);
4848

4949
// INeuropixels methods
50-
void defineMetadata (ProbeSettings<numberOfChannels, numberOfElectrodes>* settings) override;
50+
void defineMetadata (ProbeSettings* settings, ProbeType probeType) override;
5151

5252
/** Select a preset electrode configuration, based on the index of the given enum */
53-
std::vector<int> selectElectrodeConfiguration (int electrodeConfigurationIndex) override;
53+
std::vector<int> selectElectrodeConfiguration (int electrodeConfigurationIndex, ProbeType probeType = ProbeType::NPX_V1) override;
5454

55-
void setSettings (ProbeSettings<numberOfChannels, numberOfElectrodes>* settings_, int index = 0) override;
55+
void setSettings (ProbeSettings* settings_, int index = 0) override;
5656

5757
uint64_t getProbeSerialNumber (int index = 0) override;
5858
std::string getProbePartNumber (int index = 0) override;
@@ -133,6 +133,8 @@ class Neuropixels1 : public INeuropixel<NeuropixelsV1Values::numberOfChannels, N
133133
void updateLfpOffsets (std::array<float, numLfpSamples>&, int64);
134134
void updateApOffsets (std::array<float, numApSamples>&, int64);
135135

136+
bool validateProbeTypeAndPartNumber ();
137+
136138
enum class ElectrodeConfiguration : int32_t
137139
{
138140
BankA = 0,

Source/Devices/Neuropixels1e.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ Neuropixels1e::Neuropixels1e (std::string name, std::string hubName, const oni_d
107107
"lfp");
108108
streamInfos.add (lfpStream);
109109

110-
defineMetadata (settings[0].get());
110+
defineMetadata (settings[0].get(), ProbeType::NPX_V1);
111111

112112
adcCalibrationFilePath = "None";
113113
gainCalibrationFilePath = "None";
@@ -197,6 +197,9 @@ void Neuropixels1e::resetProbe()
197197

198198
bool Neuropixels1e::updateSettings()
199199
{
200+
if (! validateProbeTypeAndPartNumber())
201+
return false;
202+
200203
auto updater = NeuropixelsV1eBackgroundUpdater (this);
201204

202205
return updater.updateSettings() && adcValues.size() == NeuropixelsV1Values::AdcCount;

Source/Devices/Neuropixels1f.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ Neuropixels1f::Neuropixels1f (std::string name, std::string hubName, const oni_d
9595
"lfp");
9696
streamInfos.add (lfpStream);
9797

98-
defineMetadata (settings[0].get());
98+
defineMetadata (settings[0].get(), ProbeType::NPX_V1);
9999

100100
adcCalibrationFilePath = "None";
101101
gainCalibrationFilePath = "None";
@@ -153,6 +153,9 @@ int Neuropixels1f::configureDevice()
153153

154154
bool Neuropixels1f::updateSettings()
155155
{
156+
if (! validateProbeTypeAndPartNumber())
157+
return false;
158+
156159
auto updater = NeuropixelsV1fBackgroundUpdater (this);
157160

158161
return updater.updateSettings() && adcValues.size() == NeuropixelsV1Values::AdcCount;

Source/Devices/Neuropixels2e.cpp

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ using namespace OnixSourcePlugin;
2727
Neuropixels2e::Neuropixels2e (std::string name, std::string hubName, const oni_dev_idx_t deviceIdx_, std::shared_ptr<Onix1> ctx_)
2828
: OnixDevice (name, hubName, Neuropixels2e::getDeviceType(), deviceIdx_, ctx_, true),
2929
I2CRegisterContext (ProbeI2CAddress, deviceIdx_, ctx_),
30-
INeuropixel (NeuropixelsV2eValues::numberOfSettings, NeuropixelsV2eValues::numberOfShanks)
30+
INeuropixel (NeuropixelsV2eValues::numberOfSettings, NeuropixelsV2eValues::quadShankCount)
3131
{
3232
frameCount.fill (0);
3333
sampleNumber.fill (0);
3434

3535
for (int i = 0; i < NeuropixelsV2eValues::numberOfSettings; i++)
3636
{
37-
defineMetadata (settings[i].get());
37+
defineMetadata (settings[i].get(), ProbeType::NPX_V2_QUAD_SHANK);
3838
}
3939

4040
for (int i = 0; i < NumberOfProbes; i++)
@@ -98,13 +98,11 @@ void Neuropixels2e::selectElectrodesAcrossShanks (std::vector<int>& selection, i
9898
}
9999
}
100100

101-
std::vector<int> Neuropixels2e::selectElectrodeConfiguration (int electrodeConfigurationIndex)
101+
std::vector<int> Neuropixels2e::selectElectrodeConfiguration (int electrodeConfigurationIndex, ProbeType probeType)
102102
{
103-
static int numberOfElectrodesAcrossShanks = 96;
104-
105103
std::vector<int> selection;
106104

107-
if (numberOfShanks == 1)
105+
if (probeType == ProbeType::NPX_V2_SINGLE_SHANK)
108106
{
109107
if (electrodeConfigurationIndex == (int32_t) ElectrodeConfigurationSingleShank::BankA)
110108
{
@@ -124,8 +122,10 @@ std::vector<int> Neuropixels2e::selectElectrodeConfiguration (int electrodeConfi
124122
selectElectrodesInRange (selection, bankDOffset, numberOfChannels);
125123
}
126124
}
127-
else if (numberOfShanks == 4)
125+
else if (probeType == ProbeType::NPX_V2_QUAD_SHANK)
128126
{
127+
static int numberOfElectrodesAcrossShanks = 96;
128+
129129
if (electrodeConfigurationIndex == (int32_t) ElectrodeConfigurationQuadShank::Shank1BankA)
130130
{
131131
selectElectrodesInRange (selection, 0, numberOfChannels);
@@ -227,6 +227,10 @@ std::vector<int> Neuropixels2e::selectElectrodeConfiguration (int electrodeConfi
227227
selectElectrodesAcrossShanks (selection, numberOfElectrodesAcrossShanks * 12, numberOfElectrodesAcrossShanks);
228228
}
229229
}
230+
else
231+
{
232+
LOGE ("Invalid probe type given for a Neuropixels 2.0 device: ", ProbeTypeString.at (probeType));
233+
}
230234

231235
return selection;
232236
}
@@ -342,6 +346,16 @@ bool Neuropixels2e::updateSettings()
342346
{
343347
if (probeMetadata[i].getProbeSerialNumber() != 0)
344348
{
349+
if (! NeuropixelsProbeMetadata::validateProbeTypeAndPartNumber (settings[i]->probeType, probeMetadata[i]))
350+
{
351+
Onix1::showWarningMessageBoxAsync ("Probe Type Mismatch",
352+
"The selected probe type is '" + ProbeTypeString.at (settings[i]->probeType)
353+
+ "', but the connected probe is '" + NeuropixelsProbeMetadata::getProbeTypeString (probeMetadata[i].getProbePartNumber())
354+
+ "'. Please select the correct probe type to match the connected probe."
355+
+ ".\n\nProbe serial number: " + std::to_string (probeMetadata[i].getProbeSerialNumber()));
356+
return false;
357+
}
358+
345359
if (gainCorrectionFilePath[i] == "None" || gainCorrectionFilePath[i] == "")
346360
{
347361
Onix1::showWarningMessageBoxAsync ("Missing File", "Missing gain correction file for probe " + std::to_string (probeMetadata[i].getProbeSerialNumber()));
@@ -598,7 +612,7 @@ void Neuropixels2e::processFrames()
598612
}
599613
}
600614

601-
void Neuropixels2e::writeConfiguration (ProbeSettings<numberOfChannels, numberOfElectrodes>* settings)
615+
void Neuropixels2e::writeConfiguration (ProbeSettings* settings)
602616
{
603617
auto baseBits = makeBaseBits (getReference (settings->referenceIndex));
604618
writeShiftRegister (SR_CHAIN5, baseBits[0]);
@@ -716,7 +730,7 @@ Neuropixels2e::BaseBitsArray Neuropixels2e::makeBaseBits (NeuropixelsV2Reference
716730
return baseBits;
717731
}
718732

719-
Neuropixels2e::ShankBitsArray Neuropixels2e::makeShankBits (NeuropixelsV2Reference reference, std::array<ElectrodeMetadata, numberOfElectrodes> channelMap)
733+
Neuropixels2e::ShankBitsArray Neuropixels2e::makeShankBits (NeuropixelsV2Reference reference, std::vector<ElectrodeMetadata> channelMap)
720734
{
721735
ShankBitsArray shankBits;
722736

@@ -766,7 +780,7 @@ Neuropixels2e::ShankBitsArray Neuropixels2e::makeShankBits (NeuropixelsV2Referen
766780
return shankBits;
767781
}
768782

769-
void Neuropixels2e::setSettings (ProbeSettings<NeuropixelsV2eValues::numberOfChannels, NeuropixelsV2eValues::numberOfElectrodes>* settings_, int index)
783+
void Neuropixels2e::setSettings (ProbeSettings* settings_, int index)
770784
{
771785
if (index >= settings.size())
772786
{
@@ -777,12 +791,13 @@ void Neuropixels2e::setSettings (ProbeSettings<NeuropixelsV2eValues::numberOfCha
777791
settings[index]->updateProbeSettings (settings_);
778792
}
779793

780-
void Neuropixels2e::defineMetadata (ProbeSettings<numberOfChannels, numberOfElectrodes>* settings)
794+
void Neuropixels2e::defineMetadata (ProbeSettings* settings, ProbeType probeType)
781795
{
782-
auto shankCount = NeuropixelsV2eValues::numberOfShanks;
796+
settings->probeType = probeType;
783797

784-
settings->probeType = ProbeType::NPX_V2;
785-
settings->probeMetadata.name = "Neuropixels 2.0e" + (shankCount == 1) ? " - Single Shank" : " - Quad Shank";
798+
auto shankCount = probeType == ProbeType::NPX_V2_QUAD_SHANK ? NeuropixelsV2eValues::quadShankCount : NeuropixelsV2eValues::singleShankCount;
799+
800+
settings->probeMetadata.name = "Neuropixels 2.0e" + (probeType == ProbeType::NPX_V2_QUAD_SHANK) ? " - Single Shank" : " - Quad Shank";
786801

787802
constexpr float shankTipY = 0.0f;
788803
constexpr float shankBaseY = 155.0f;
@@ -827,14 +842,6 @@ void Neuropixels2e::defineMetadata (ProbeSettings<numberOfChannels, numberOfElec
827842
settings->probeMetadata.num_adcs = 24;
828843
settings->probeMetadata.adc_bits = 12;
829844

830-
settings->availableBanks = {
831-
Bank::A,
832-
Bank::B,
833-
Bank::C,
834-
Bank::D,
835-
Bank::NONE // disconnected
836-
};
837-
838845
for (int i = 0; i < settings->probeMetadata.electrodes_per_shank * settings->probeMetadata.shank_count; i++)
839846
{
840847
ElectrodeMetadata metadata;
@@ -1099,14 +1106,18 @@ void Neuropixels2e::defineMetadata (ProbeSettings<numberOfChannels, numberOfElec
10991106
settings->apFilterState = false;
11001107

11011108
settings->electrodeConfigurationIndex = (int32_t) ElectrodeConfigurationSingleShank::BankA;
1102-
auto selection = selectElectrodeConfiguration (settings->electrodeConfigurationIndex);
1109+
auto selection = selectElectrodeConfiguration (settings->electrodeConfigurationIndex, probeType);
11031110
settings->selectElectrodes (selection);
11041111

11051112
settings->availableReferences.add ("Ext");
1106-
settings->availableReferences.add ("Tip1");
11071113

1108-
if (shankCount == 4)
1114+
if (probeType == ProbeType::NPX_V2_SINGLE_SHANK)
1115+
{
1116+
settings->availableReferences.add ("Tip");
1117+
}
1118+
else if (probeType == ProbeType::NPX_V2_QUAD_SHANK)
11091119
{
1120+
settings->availableReferences.add ("Tip1");
11101121
settings->availableReferences.add ("Tip2");
11111122
settings->availableReferences.add ("Tip3");
11121123
settings->availableReferences.add ("Tip4");

0 commit comments

Comments
 (0)