Skip to content

Commit 8de7fef

Browse files
authored
Merge pull request #136 from open-ephys-plugins/issue-134
Automatically search for calibration files for Neuropixels probes
2 parents bce0067 + 6b31520 commit 8de7fef

File tree

8 files changed

+380
-37
lines changed

8 files changed

+380
-37
lines changed

Source/Devices/Neuropixels1e.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,7 @@ void NeuropixelsV1eBackgroundUpdater::run()
6565
}
6666
catch (const error_str& e)
6767
{
68-
LOGE(e.what());
69-
AlertWindow::showMessageBox(MessageBoxIconType::WarningIcon, "Error Writing Shift Registers", e.what());
68+
Onix1::showWarningMessageBoxAsync("Error Writing Shift Registers", e.what());
7069
result = false;
7170
return;
7271
}

Source/OnixSource.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,7 @@ bool OnixSource::configureDevice(OnixDeviceVector& sources,
159159
}
160160
catch (const error_str& e)
161161
{
162-
LOGE(e.what());
163-
AlertWindow::showMessageBox(MessageBoxIconType::WarningIcon, "Configuration Error", e.what());
162+
Onix1::showWarningMessageBoxAsync("Configuration Error", e.what());
164163

165164
return false;
166165
}
@@ -285,7 +284,7 @@ bool OnixSource::checkHubFirmwareCompatibility(std::shared_ptr<Onix1> context, d
285284
auto majorVersion = (firmwareVersion & 0xFF00) >> 8;
286285
auto minorVersion = firmwareVersion & 0xFF;
287286

288-
LOGD("Breakout board firmware version: v", majorVersion, ".", minorVersion);
287+
LOGC("Breakout board firmware version: v", majorVersion, ".", minorVersion);
289288

290289
if (majorVersion != RequiredMajorVersion)
291290
{
@@ -418,7 +417,7 @@ bool OnixSource::initializeDevices(device_map_t deviceTable, bool updateStreamIn
418417

419418
auto EEPROM = std::make_unique<HeadStageEEPROM>(index, context);
420419
uint32_t hsid = EEPROM->GetHeadStageID();
421-
LOGD("Detected headstage ", onix_hub_str(hsid));
420+
LOGC("Detected headstage ", onix_hub_str(hsid));
422421

423422
if (hsid == ONIX_HUB_HSNP2E)
424423
{

Source/UI/NeuropixelsV1Interface.cpp

Lines changed: 169 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,35 @@ NeuropixelsV1Interface::NeuropixelsV1Interface(std::shared_ptr<Neuropixels1> d,
7777
infoLabel->setJustificationType(Justification::topLeft);
7878
addAndMakeVisible(infoLabel.get());
7979

80+
searchForCalibrationFilesButton = std::make_unique<ToggleButton>("Search for calibration files automatically");
81+
searchForCalibrationFilesButton->setBounds(infoLabel->getX() + 2, infoLabel->getBottom() + 5, 350, 20);
82+
searchForCalibrationFilesButton->addListener(this);
83+
searchForCalibrationFilesButton->setTooltip("Open a file dialog to choose a folder that contains all calibration files. The calibration file(s) that matches your probe will automatically be selected if it exists in this folder.");
84+
addAndMakeVisible(searchForCalibrationFilesButton.get());
85+
86+
calibrationFolderLabel = std::make_unique<Label>("calibrationFolderLabel", "Calibration Folder");
87+
calibrationFolderLabel->setBounds(searchForCalibrationFilesButton->getX(), searchForCalibrationFilesButton->getBottom() + 5, 240, 16);
88+
calibrationFolderLabel->setColour(Label::textColourId, Colours::black);
89+
addAndMakeVisible(calibrationFolderLabel.get());
90+
91+
calibrationFolder = std::make_unique<TextEditor>("CALIBRATION FOLDER");
92+
calibrationFolder->setEnabled(false);
93+
calibrationFolder->setBounds(calibrationFolderLabel->getX(), calibrationFolderLabel->getBottom() + 2, calibrationFolderLabel->getWidth(), 20);
94+
calibrationFolder->setColour(Label::textColourId, Colours::black);
95+
calibrationFolder->addListener(this);
96+
addAndMakeVisible(calibrationFolder.get());
97+
98+
calibrationFolderButton = std::make_unique<UtilityButton>("...");
99+
calibrationFolderButton->setBounds(calibrationFolder->getRight() + 3, calibrationFolder->getY(), 26, calibrationFolder->getHeight() + 2);
100+
calibrationFolderButton->setRadius(1.0f);
101+
calibrationFolderButton->addListener(this);
102+
calibrationFolderButton->setTooltip("Open a file dialog to choose the calibration folder path to automatically search for probe calibration files.");
103+
addAndMakeVisible(calibrationFolderButton.get());
104+
105+
calibrationFolderChooser = std::make_unique<FileChooser>("Select Gain Calibration Folder.", File());
106+
80107
adcCalibrationFileLabel = std::make_unique<Label>("adcCalibrationFileLabel", "ADC Calibration File");
81-
adcCalibrationFileLabel->setBounds(infoLabel->getX(), infoLabel->getBottom() + 15, 240, 16);
108+
adcCalibrationFileLabel->setBounds(calibrationFolder->getX(), calibrationFolder->getBottom() + 15, calibrationFolderLabel->getWidth(), calibrationFolderLabel->getHeight());
82109
adcCalibrationFileLabel->setColour(Label::textColourId, Colours::black);
83110
addAndMakeVisible(adcCalibrationFileLabel.get());
84111

@@ -96,7 +123,7 @@ NeuropixelsV1Interface::NeuropixelsV1Interface(std::shared_ptr<Neuropixels1> d,
96123
adcCalibrationFileButton->setTooltip("Open a file dialog to choose the ADC calibration file for this probe.");
97124
addAndMakeVisible(adcCalibrationFileButton.get());
98125

99-
adcCalibrationFileChooser = std::make_unique<FileChooser>("Select ADC Calibration file.", File(), "*_ADCCalibration.csv");
126+
adcCalibrationFileChooser = std::make_unique<FileChooser>("Select ADC Calibration file.", File(), std::string("*") + AdcCalibrationFilename);
100127

101128
gainCalibrationFileLabel = std::make_unique<Label>("gainCalibrationFileLabel", "Gain Calibration File");
102129
gainCalibrationFileLabel->setBounds(adcCalibrationFile->getX(), adcCalibrationFile->getBottom() + 3, adcCalibrationFile->getWidth(), adcCalibrationFile->getHeight());
@@ -117,7 +144,7 @@ NeuropixelsV1Interface::NeuropixelsV1Interface(std::shared_ptr<Neuropixels1> d,
117144
gainCalibrationFileButton->setTooltip("Open a file dialog to choose the Gain calibration file for this probe.");
118145
addAndMakeVisible(gainCalibrationFileButton.get());
119146

120-
gainCalibrationFileChooser = std::make_unique<FileChooser>("Select Gain Calibration file.", File(), "*_gainCalValues.csv");
147+
gainCalibrationFileChooser = std::make_unique<FileChooser>("Select Gain Calibration file.", File(), std::string("*") + GainCalibrationFilename);
121148

122149
probeInterfaceRectangle = std::make_unique<DrawableRectangle>();
123150
probeInterfaceRectangle->setFill(Colours::darkgrey);
@@ -507,6 +534,8 @@ NeuropixelsV1Interface::NeuropixelsV1Interface(std::shared_ptr<Neuropixels1> d,
507534
addAndMakeVisible(activityViewComponent.get());
508535

509536
updateSettings();
537+
538+
setCalibrationFolderEnabledState(false);
510539
}
511540

512541
drawLegend();
@@ -534,20 +563,26 @@ void NeuropixelsV1Interface::updateInfoString()
534563
std::string deviceString, infoString;
535564

536565
auto npx = std::static_pointer_cast<Neuropixels1>(device);
566+
auto sn = npx->getProbeSerialNumber();
537567

538568
if (device != nullptr)
539569
{
540570
deviceString = "Neuropixels 1.0 Probe";
541571

542572
infoString += "\n";
543573
infoString += "Probe Number: ";
544-
infoString += std::to_string(npx->getProbeSerialNumber());
574+
infoString += std::to_string(sn);
545575
infoString += "\n";
546576
infoString += "\n";
547577
}
548578

549579
deviceLabel->setText(deviceString, dontSendNotification);
550580
infoLabel->setText(infoString, dontSendNotification);
581+
582+
if (searchForCalibrationFilesButton->getToggleState())
583+
{
584+
searchForCalibrationFiles(calibrationFolder->getText().toStdString(), sn);
585+
}
551586
}
552587

553588
void NeuropixelsV1Interface::comboBoxChanged(ComboBox* comboBox)
@@ -556,7 +591,6 @@ void NeuropixelsV1Interface::comboBoxChanged(ComboBox* comboBox)
556591

557592
if (!editor->acquisitionIsActive)
558593
{
559-
auto npx = std::static_pointer_cast<Neuropixels1>(device);
560594
auto settings = npx->settings[0].get();
561595

562596
if (comboBox == electrodeConfigurationComboBox.get())
@@ -686,7 +720,6 @@ void NeuropixelsV1Interface::buttonClicked(Button* button)
686720
deviceEnableButton->setLabel(disabledButtonText);
687721
}
688722

689-
updateInfoString();
690723
repaint();
691724

692725
CoreServices::updateSignalChain(editor);
@@ -801,10 +834,6 @@ void NeuropixelsV1Interface::buttonClicked(Button* button)
801834
{
802835
adcCalibrationFile->setText(adcCalibrationFileChooser->getResult().getFullPathName());
803836
}
804-
else
805-
{
806-
adcCalibrationFile->setText("");
807-
}
808837

809838
std::static_pointer_cast<Neuropixels1>(device)->setAdcCalibrationFilePath(adcCalibrationFile->getText().toStdString());
810839
}
@@ -814,15 +843,128 @@ void NeuropixelsV1Interface::buttonClicked(Button* button)
814843
{
815844
gainCalibrationFile->setText(gainCalibrationFileChooser->getResult().getFullPathName());
816845
}
817-
else
846+
847+
std::static_pointer_cast<Neuropixels1>(device)->setGainCalibrationFilePath(gainCalibrationFile->getText().toStdString());
848+
}
849+
else if (button == searchForCalibrationFilesButton.get())
850+
{
851+
setCalibrationFolderEnabledState(button->getToggleState());
852+
853+
if (button->getToggleState())
818854
{
819-
gainCalibrationFile->setText("");
855+
searchForCalibrationFiles(calibrationFolder->getText().toStdString(), std::static_pointer_cast<Neuropixels1>(device)->getProbeSerialNumber());
820856
}
857+
}
858+
else if (button == calibrationFolderButton.get())
859+
{
860+
if (calibrationFolderChooser->browseForDirectory())
861+
{
862+
calibrationFolder->setText(calibrationFolderChooser->getResult().getFullPathName());
863+
searchForCalibrationFiles(calibrationFolder->getText().toStdString(), std::static_pointer_cast<Neuropixels1>(device)->getProbeSerialNumber());
864+
}
865+
}
866+
}
821867

822-
std::static_pointer_cast<Neuropixels1>(device)->setGainCalibrationFilePath(gainCalibrationFile->getText().toStdString());
868+
void NeuropixelsV1Interface::textEditorTextChanged(TextEditor& editor)
869+
{
870+
if (editor.getName() == gainCalibrationFile->getName())
871+
{
872+
std::static_pointer_cast<Neuropixels1>(device)->setGainCalibrationFilePath(editor.getText().toStdString());
873+
}
874+
else if (editor.getName() == adcCalibrationFile->getName())
875+
{
876+
std::static_pointer_cast<Neuropixels1>(device)->setAdcCalibrationFilePath(editor.getText().toStdString());
877+
}
878+
}
879+
880+
std::string NeuropixelsV1Interface::searchDirectoryForAdcCalibrationFile(std::string folder, uint64_t sn)
881+
{
882+
return searchDirectoryForCalibrationFile(folder, std::to_string(sn) + AdcCalibrationFilename, sn);
883+
}
884+
885+
std::string NeuropixelsV1Interface::searchDirectoryForGainCalibrationFile(std::string folder, uint64_t sn)
886+
{
887+
return searchDirectoryForCalibrationFile(folder, std::to_string(sn) + GainCalibrationFilename, sn);
888+
}
889+
890+
std::string NeuropixelsV1Interface::searchDirectoryForCalibrationFile(std::string folder, std::string filename, uint64_t sn)
891+
{
892+
if (folder == "" || sn == 0)
893+
return "";
894+
895+
File rootDirectory = File(folder);
896+
897+
if (!rootDirectory.isDirectory())
898+
{
899+
Onix1::showWarningMessageBoxAsync("Invalid Directory", "The path given for the calibration files directory is invalid. Please try setting it again.");
900+
return "";
901+
}
902+
903+
auto calibrationFiles = searchDirectoryForFile(rootDirectory, filename, NeuropixelsCalibrationFileRecursiveLevels);
904+
905+
if (calibrationFiles.size() != 1)
906+
{
907+
std::string msg = "Expected to find 1 file matching '" + filename +
908+
"', but found " + std::to_string(calibrationFiles.size()) + " instead.";
909+
910+
if (calibrationFiles.size() > 1)
911+
{
912+
msg += " Check console for all files discovered.";
913+
}
914+
915+
Onix1::showWarningMessageBoxAsync("Wrong Number of Calibration Files", msg);
916+
return "";
917+
}
918+
919+
return calibrationFiles[0].getFullPathName().toStdString();
920+
}
921+
922+
void NeuropixelsV1Interface::setCalibrationFolderEnabledState(bool enabledState)
923+
{
924+
float alphaEnabled = 1.0, alphaDisabled = 0.25;
925+
926+
if (!enabledState)
927+
{
928+
calibrationFolder->setAlpha(alphaDisabled);
929+
calibrationFolderButton->setEnabled(false);
930+
931+
adcCalibrationFile->setAlpha(alphaEnabled);
932+
adcCalibrationFileButton->setEnabled(true);
933+
934+
gainCalibrationFile->setAlpha(alphaEnabled);
935+
gainCalibrationFileButton->setEnabled(true);
936+
}
937+
else
938+
{
939+
calibrationFolder->setAlpha(alphaEnabled);
940+
calibrationFolderButton->setEnabled(true);
941+
942+
adcCalibrationFile->setAlpha(alphaDisabled);
943+
adcCalibrationFileButton->setEnabled(false);
944+
945+
gainCalibrationFile->setAlpha(alphaDisabled);
946+
gainCalibrationFileButton->setEnabled(false);
823947
}
824948
}
825949

950+
void NeuropixelsV1Interface::searchForCalibrationFiles(std::string folder, uint64_t sn)
951+
{
952+
if (!device->isEnabled())
953+
return;
954+
955+
auto file = searchDirectoryForGainCalibrationFile(folder, sn);
956+
957+
if (file != "")
958+
gainCalibrationFile->setText(file);
959+
else
960+
return;
961+
962+
file = searchDirectoryForAdcCalibrationFile(folder, sn);
963+
964+
if (file != "")
965+
adcCalibrationFile->setText(file);
966+
}
967+
826968
std::vector<int> NeuropixelsV1Interface::getSelectedElectrodes() const
827969
{
828970
std::vector<int> electrodeIndices;
@@ -898,6 +1040,12 @@ void NeuropixelsV1Interface::setInterfaceEnabledState(bool enabledState)
8981040

8991041
if (loadSettingsButton != nullptr)
9001042
loadSettingsButton->setEnabled(enabledState);
1043+
1044+
if (searchForCalibrationFilesButton != nullptr)
1045+
searchForCalibrationFilesButton->setEnabled(enabledState);
1046+
1047+
if (calibrationFolderButton != nullptr)
1048+
calibrationFolderButton->setEnabled(enabledState);
9011049
}
9021050

9031051
void NeuropixelsV1Interface::startAcquisition()
@@ -1020,6 +1168,10 @@ void NeuropixelsV1Interface::saveParameters(XmlElement* xml)
10201168

10211169
xmlNode->setAttribute("isEnabled", bool(device->isEnabled()));
10221170

1171+
xmlNode->setAttribute("searchForCalibrationFiles", searchForCalibrationFilesButton->getToggleState());
1172+
1173+
xmlNode->setAttribute("calibrationFolder", calibrationFolder->getText());
1174+
10231175
xmlNode->setAttribute("adcCalibrationFile", npx->getAdcCalibrationFilePath());
10241176
xmlNode->setAttribute("gainCalibrationFile", npx->getGainCalibrationFilePath());
10251177

@@ -1088,6 +1240,10 @@ void NeuropixelsV1Interface::loadParameters(XmlElement* xml)
10881240

10891241
npx->setEnabled(xmlNode->getBoolAttribute("isEnabled"));
10901242

1243+
searchForCalibrationFilesButton->setToggleState(xmlNode->getBoolAttribute("searchForCalibrationFiles", false), sendNotification);
1244+
1245+
calibrationFolder->setText(xmlNode->getStringAttribute("calibrationFolder", ""));
1246+
10911247
npx->setAdcCalibrationFilePath(xmlNode->getStringAttribute("adcCalibrationFile").toStdString());
10921248
npx->setGainCalibrationFilePath(xmlNode->getStringAttribute("gainCalibrationFile").toStdString());
10931249

Source/UI/NeuropixelsV1Interface.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ namespace OnixSourcePlugin
5151

5252
void buttonClicked(Button*) override;
5353
void comboBoxChanged(ComboBox*) override;
54+
void textEditorTextChanged(TextEditor&) override;
5455

5556
void startAcquisition() override;
5657

@@ -77,6 +78,9 @@ namespace OnixSourcePlugin
7778

7879
bool acquisitionIsActive = false;
7980

81+
static constexpr char* GainCalibrationFilename = "_gainCalValues.csv";
82+
static constexpr char* AdcCalibrationFilename = "_ADCCalibration.csv";
83+
8084
std::unique_ptr<ComboBox> electrodeConfigurationComboBox;
8185
std::unique_ptr<ComboBox> lfpGainComboBox;
8286
std::unique_ptr<ComboBox> apGainComboBox;
@@ -94,6 +98,20 @@ namespace OnixSourcePlugin
9498
std::unique_ptr<Label> filterLabel;
9599
std::unique_ptr<Label> activityViewLabel;
96100

101+
std::unique_ptr<Label> calibrationFolderLabel;
102+
std::unique_ptr<ToggleButton> searchForCalibrationFilesButton;
103+
std::unique_ptr<FileChooser> calibrationFolderChooser;
104+
std::unique_ptr<TextEditor> calibrationFolder;
105+
std::unique_ptr<UtilityButton> calibrationFolderButton;
106+
107+
void setCalibrationFolderEnabledState(bool enabledState);
108+
109+
static std::string searchDirectoryForGainCalibrationFile(std::string folder, uint64_t sn);
110+
static std::string searchDirectoryForAdcCalibrationFile(std::string folder, uint64_t sn);
111+
static std::string searchDirectoryForCalibrationFile(std::string folder, std::string filename, uint64_t sn);
112+
113+
void searchForCalibrationFiles(std::string, uint64_t);
114+
97115
std::unique_ptr<Label> adcCalibrationFileLabel;
98116
std::unique_ptr<Label> gainCalibrationFileLabel;
99117

Source/UI/NeuropixelsV2eInterface.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ void NeuropixelsV2eInterface::buttonClicked(Button* button)
102102
deviceEnableButton->setLabel(disabledButtonText);
103103
}
104104

105-
updateInfoString();
106105
repaint();
107106

108107
CoreServices::updateSignalChain(editor);

0 commit comments

Comments
 (0)