22#include "ui_channelselectionview.h"
46#include <QListWidgetItem>
48#include <QApplication>
50#include <QSignalBlocker>
74, m_pUi(std::make_unique<Ui::ChannelSelectionViewWidget>())
75, m_pChannelInfoModel(pChannelInfoModel)
78 m_sSettingsPath = sSettingsPath;
83 initSelectionSceneView();
104void ChannelSelectionView::initListWidgets()
107 m_pUi->m_listWidget_userDefined->installEventFilter(
this);
108 m_pUi->m_listWidget_selectionGroups->installEventFilter(
this);
111 connect(m_pUi->m_listWidget_selectionGroups, &QListWidget::currentItemChanged,
112 this, &ChannelSelectionView::updateSelectionGroupsList);
116 connect(m_pUi->m_listWidget_userDefined->model(), &QAbstractTableModel::dataChanged,
122void ChannelSelectionView::initSelectionSceneView()
125 m_pSelectionScene =
new SelectionScene(m_pUi->m_graphicsView_layoutPlot);
126 m_pUi->m_graphicsView_layoutPlot->setScene(m_pSelectionScene);
128 connect(m_pSelectionScene, &QGraphicsScene::selectionChanged,
129 this, &ChannelSelectionView::updateUserDefinedChannelsList);
134void ChannelSelectionView::initComboBoxes()
136 m_pUi->m_comboBox_layoutFile->clear();
137 m_pUi->m_comboBox_layoutFile->insertItems(0, QStringList() <<
"babymeg-mag-inner-layer.lout"
138 <<
"babymeg-mag-outer-layer.lout"
140 <<
"Vectorview-grad.lout"
141 <<
"Vectorview-all.lout"
142 <<
"Vectorview-mag.lout"
143 <<
"standard_waveguard64_duke.lout"
148 connect(m_pUi->m_comboBox_layoutFile, &QComboBox::currentTextChanged,
149 this, &ChannelSelectionView::onComboBoxLayoutChanged);
152 QString selectionName(
"Vectorview-all.lout");
157 selectionName = QString(
"mne_browse_raw_vv.sel");
158 loadSelectionGroups(QCoreApplication::applicationDirPath() + selectionName.prepend(
"/../resources/general/selectionGroups/"));
163void ChannelSelectionView::initButtons()
165 connect(m_pUi->m_pushButton_saveSelection, &QPushButton::clicked,
166 this, &ChannelSelectionView::onBtnSaveUserSelection);
168 connect(m_pUi->m_pushButton_loadSelection, &QPushButton::clicked,
169 this, &ChannelSelectionView::onBtnLoadUserSelection);
171 connect(m_pUi->m_pushButton_addToSelectionGroups, &QPushButton::clicked,
172 this, &ChannelSelectionView::onBtnAddToSelectionGroups);
177void ChannelSelectionView::initCheckBoxes()
179 connect(m_pUi->m_checkBox_showBadChannelsAsRed, &QCheckBox::clicked,
187 m_currentlyLoadedFiffChannels = mappedLayoutChNames;
190 m_pUi->m_listWidget_visibleChannels->clear();
193 m_pUi->m_listWidget_selectionGroups->clear();
196 auto it = m_selectionGroupsMap.find(
"All");
197 if (it != m_selectionGroupsMap.end()) {
198 m_selectionGroupsMap.erase(it);
200 m_selectionGroupsMap.insert(
"All", m_currentlyLoadedFiffChannels);
203 for (
auto i = m_selectionGroupsMap.constBegin(); i != m_selectionGroupsMap.constEnd(); i++) {
204 m_pUi->m_listWidget_selectionGroups->insertItem(m_pUi->m_listWidget_selectionGroups->count(), i.key());
208 m_pUi->m_listWidget_selectionGroups->setCurrentItem(
getItemForChName(m_pUi->m_listWidget_selectionGroups,
"All"), QItemSelectionModel::Select);
211 updateSelectionGroupsList(
getItemForChName(m_pUi->m_listWidget_selectionGroups,
"All"),
new QListWidgetItem());
218 QStringList channelList;
219 for (
int i = 0; i < channelIndexList.size(); i++) {
220 QModelIndex nameIndex = m_pChannelInfoModel->index(channelIndexList.at(i).row(), 3);
224 QList<QGraphicsItem*> allSceneItems = m_pSelectionScene->items();
226 for (
int i = 0; i < allSceneItems.size(); i++) {
234 m_pSelectionScene->update();
241 QList<QGraphicsItem*> allSceneItems = m_pSelectionScene->items();
243 for (
int i = 0; i < allSceneItems.size(); i++) {
246 item->setSelected(
true);
248 item->setSelected(
false);
251 m_pSelectionScene->update();
259 QListWidget* targetListWidget;
260 if (m_pUi->m_listWidget_userDefined->count() > 0)
261 targetListWidget = m_pUi->m_listWidget_userDefined;
263 targetListWidget = m_pUi->m_listWidget_visibleChannels;
266 QStringList selectedChannels;
268 for (
int i = 0; i < targetListWidget->count(); i++) {
269 QListWidgetItem* item = targetListWidget->item(i);
270 selectedChannels << item->text();
273 return selectedChannels;
279 const QString& channelName)
281 for (
int i = 0; i < listWidget->count(); i++)
282 if (listWidget->item(i)->text() == channelName)
283 return listWidget->item(i);
285 return new QListWidgetItem();
301 loadLayout(resolveLayoutPath(m_pUi->m_comboBox_layoutFile->currentText()));
308 return m_pUi->m_comboBox_layoutFile->currentText();
315 return m_pUi->m_lineEdit_loadedFile->text();
322 qDebug() <<
"setCurrentLayoutFile:" << currentLayoutFile;
323 const QSignalBlocker blocker(m_pUi->m_comboBox_layoutFile);
324 m_pUi->m_comboBox_layoutFile->setCurrentText(currentLayoutFile);
326 loadLayout(resolveLayoutPath(currentLayoutFile));
334 QStringList badChannelMappedNames;
335 QStringList badChannelList = m_pChannelInfoModel->getBadChannelList();
337 if (m_pUi->m_checkBox_showBadChannelsAsRed->isChecked()) {
338 for (
int i = 0; i < m_pChannelInfoModel->rowCount(); i++) {
339 QModelIndex digIndex = m_pChannelInfoModel->index(i, 3);
342 digIndex = m_pChannelInfoModel->index(i, 1);
345 if (badChannelList.contains(origChName)) {
346 badChannelMappedNames << mappedChName;
351 m_pSelectionScene->repaintItems(m_layoutMap, badChannelMappedNames);
352 m_pSelectionScene->update();
363 QListWidget* targetListWidget;
364 if (m_pUi->m_listWidget_userDefined->count() > 0)
365 targetListWidget = m_pUi->m_listWidget_userDefined;
367 targetListWidget = m_pUi->m_listWidget_visibleChannels;
370 QStringList selectedChannels;
372 for (
int i = 0; i < targetListWidget->count(); i++) {
373 QListWidgetItem* item = targetListWidget->item(i);
374 int indexTemp = m_pChannelInfoModel->getIndexFromMappedChName(item->text());
376 if (indexTemp != -1) {
377 QModelIndex mappedNameIndex = m_pChannelInfoModel->index(indexTemp, 1);
380 selectedChannels << origChName;
382 selectedChannels << item->text();
388 if (!m_pSelectionScene->selectedItems().empty()) {
392 QList<QGraphicsItem*> visibleItemList = m_pSelectionScene->items();
393 QMutableListIterator<QGraphicsItem*> i(visibleItemList);
394 while (i.hasNext()) {
395 if (!i.next()->isVisible()) {
407 if (m_sSettingsPath.isEmpty()) {
411 QSettings settings(
"MNECPP");
415 settings.setValue(m_sSettingsPath + QString(
"/ChannelSelectionView/selectedLayoutFile"),
getCurrentLayoutFile());
416 settings.setValue(m_sSettingsPath + QString(
"/ChannelSelectionView/channelSelectionViewPos"), this->pos());
417 settings.setValue(m_sSettingsPath + QString(
"/ChannelSelectionView/selectedGroupFile"),
getCurrentGroupFile());
424 if (m_sSettingsPath.isEmpty()) {
428 QSettings settings(
"MNECPP");
430 setCurrentLayoutFile(settings.value(m_sSettingsPath + QString(
"/ChannelSelectionView/selectedLayoutFile"),
"Vectorview-all.lout").toString());
431 loadSelectionGroups(QCoreApplication::applicationDirPath() + settings.value(m_sSettingsPath + QString(
"/ChannelSelectionView/selectedGroupFile"),
"mne_browse_raw_vv.sel").toString().prepend(
"/../resources/general/selectionGroups/"));
435 QPoint pos = settings.value(m_sSettingsPath + QString(
"/ChannelSelectionView/channelSelectionViewPos"), QPoint(100, 100)).toPoint();
437 QList<QScreen*> screensList = QGuiApplication::screens();
438 if (screensList.isEmpty()) {
439 move(QPoint(100, 100));
471bool ChannelSelectionView::loadLayout(QString path)
473 qDebug() <<
"loadLayout:" << path;
475 const bool state = layout.has_value();
476 m_layoutMap = state ? layout->channelPositions() : QMap<QString, QPointF>();
479 QList<QVector<float>> inputPoints;
480 QList<QVector<float>> outputPoints;
482 QFile out(
"manualLayout.lout");
484 for (
int i = 0; i < m_pChannelInfoModel->rowCount(); i++) {
485 QModelIndex digIndex = m_pChannelInfoModel->index(i, 1);
488 digIndex = m_pChannelInfoModel->index(i, 8);
491 digIndex = m_pChannelInfoModel->index(i, 4);
496 temp.append(channelDig.x());
497 temp.append(channelDig.y());
498 temp.append(channelDig.z());
499 inputPoints.append(temp);
510 if (inputPoints.size() > 0) {
511 while (numberTries < 10) {
531 for (
int i = 0; i < outputPoints.size(); i++) {
532 if (!m_layoutMap.contains(names.at(i))) {
533 m_layoutMap[names.at(i)] = QPointF(outputPoints.at(i)[0], outputPoints.at(i)[1]);
538 m_pSelectionScene->repaintItems(m_layoutMap, bad);
539 m_pSelectionScene->update();
543 m_pUi->m_graphicsView_layoutPlot->fitInView(m_pSelectionScene->itemsBoundingRect(), Qt::KeepAspectRatio);
557QString ChannelSelectionView::resolveLayoutPath(
const QString& layoutFile)
const
559 if (layoutFile.isEmpty()) {
563 if (QFileInfo(layoutFile).isAbsolute()) {
567 return QCoreApplication::applicationDirPath() + QStringLiteral(
"/../resources/general/2DLayouts/") + layoutFile;
572bool ChannelSelectionView::loadSelectionGroups(QString path)
575 m_pUi->m_listWidget_visibleChannels->clear();
578 m_pUi->m_listWidget_selectionGroups->clear();
581 QString newPath = path;
583 m_selectionGroupsMap.clear();
588 if (!path.isEmpty()) {
589 if (path.contains(
".sel"))
591 if (path.contains(
".mon"))
596 auto it = m_selectionGroupsMap.find(
"All");
597 if (it != m_selectionGroupsMap.end()) {
598 m_selectionGroupsMap.erase(it);
600 m_selectionGroupsMap.insert(
"All", m_currentlyLoadedFiffChannels);
603 for (
int i = 0; i < m_pChannelInfoModel->rowCount(); i++) {
604 QModelIndex digIndex = m_pChannelInfoModel->index(i, 1);
607 digIndex = m_pChannelInfoModel->index(i, 4);
615 it = m_selectionGroupsMap.find(
"All EEG");
616 if (it != m_selectionGroupsMap.end()) {
617 m_selectionGroupsMap.erase(it);
619 m_selectionGroupsMap.insert(
"All EEG", names);
623 for (
auto i = m_selectionGroupsMap.constBegin(); i != m_selectionGroupsMap.constEnd(); i++) {
624 m_pUi->m_listWidget_selectionGroups->insertItem(m_pUi->m_listWidget_selectionGroups->count(), i.key());
628 updateSelectionGroupsList(
getItemForChName(m_pUi->m_listWidget_selectionGroups,
"All"),
new QListWidgetItem());
631 m_pUi->m_listWidget_selectionGroups->setCurrentItem(
getItemForChName(m_pUi->m_listWidget_selectionGroups,
"All"), QItemSelectionModel::Select);
633 m_pUi->m_lineEdit_loadedFile->setText(QFileInfo(path).fileName());
644void ChannelSelectionView::cleanUpMEGChannels()
647 for (
auto i = m_selectionGroupsMap.constBegin(); i != m_selectionGroupsMap.constEnd(); i++) {
648 QStringList channelList = i.value();
651 QMutableStringListIterator stringListIndex(channelList);
652 while (stringListIndex.hasNext()) {
653 stringListIndex.next();
655 if (!m_layoutMap.contains(stringListIndex.value()) && stringListIndex.value().contains(
"MEG"))
656 stringListIndex.remove();
660 m_selectionGroupsMap.insert(i.key(), channelList);
666void ChannelSelectionView::updateSelectionGroupsList(QListWidgetItem* current, QListWidgetItem* previous)
673 if (current->text().contains(
"EEG"))
679 m_pUi->m_listWidget_visibleChannels->clear();
680 auto items = m_selectionGroupsMap.find(current->text());
681 m_pUi->m_listWidget_visibleChannels->addItems(*items);
694void ChannelSelectionView::updateSceneItems()
696 QStringList visibleItems;
698 for (
int i = 0; i < m_pUi->m_listWidget_visibleChannels->count(); i++)
699 visibleItems << m_pUi->m_listWidget_visibleChannels->item(i)->text();
701 m_pSelectionScene->hideItems(visibleItems);
706void ChannelSelectionView::updateUserDefinedChannelsList()
708 QList<QGraphicsItem*> itemList = m_pSelectionScene->selectedItems();
709 QStringList userDefinedChannels;
711 for (
int i = 0; i < itemList.size(); i++) {
712 SelectionSceneItem* item =
static_cast<SelectionSceneItem*
>(itemList.at(i));
716 m_pUi->m_listWidget_userDefined->clear();
717 m_pUi->m_listWidget_userDefined->addItems(userDefinedChannels);
724void ChannelSelectionView::onBtnLoadUserSelection()
726 QString path = QFileDialog::getOpenFileName(
this,
727 QString(
"Open selection file"),
728 QString(
"../resources/general/selectionGroups/"),
729 tr(
"Selection files (*.sel *.mon)"));
734 loadSelectionGroups(path);
735 m_pUi->m_lineEdit_loadedFile->setText(QFileInfo(path).fileName());
740void ChannelSelectionView::onBtnSaveUserSelection()
743 QString path = QFileDialog::getSaveFileName(
this,
744 "Save user channel selection",
745 QString(
"../resources/general/selectionGroups/%1_%2_%3_UserSelection").arg(date.currentDate().year()).arg(date.currentDate().month()).arg(date.currentDate().day()),
746 tr(
"MNE selection file(*.sel);; Brainstorm montage file(*.mon)"));
748 QMultiMap<QString, QStringList> tempMap = m_selectionGroupsMap;
749 tempMap.remove(
"All");
750 tempMap.remove(
"All EEG");
752 if (!path.isEmpty()) {
753 if (path.contains(
".sel"))
755 if (path.contains(
".mon"))
762void ChannelSelectionView::onBtnAddToSelectionGroups()
765 for (
int i = 0; i < m_pUi->m_listWidget_userDefined->count(); i++)
766 temp << m_pUi->m_listWidget_userDefined->item(i)->text();
768 m_selectionGroupsMap.insert(m_pUi->m_lineEdit_selectionGroupName->text(), temp);
769 m_pUi->m_listWidget_selectionGroups->insertItem(m_pUi->m_listWidget_selectionGroups->count(), m_pUi->m_lineEdit_selectionGroupName->text());
774void ChannelSelectionView::onComboBoxLayoutChanged()
776 QString selectionName(m_pUi->m_comboBox_layoutFile->currentText());
777 loadLayout(resolveLayoutPath(selectionName));
783void ChannelSelectionView::resizeEvent(QResizeEvent* event)
793bool ChannelSelectionView::eventFilter(QObject* obj, QEvent* event)
796 if (obj == m_pUi->m_listWidget_userDefined && event->type() == QEvent::KeyRelease) {
797 QKeyEvent* keyEvent =
static_cast<QKeyEvent*
>(event);
799 if (keyEvent->key() == Qt::Key_Delete) {
800 qDeleteAll(m_pUi->m_listWidget_userDefined->selectedItems());
807 if (obj == m_pUi->m_listWidget_selectionGroups && event->type() == QEvent::KeyRelease) {
808 QKeyEvent* keyEvent =
static_cast<QKeyEvent*
>(event);
810 if (keyEvent->key() == Qt::Key_Delete) {
811 QList<QListWidgetItem*> tempSelectedList;
813 for (
int i = 0; i < m_pUi->m_listWidget_selectionGroups->selectedItems().size(); i++) {
814 if (m_pUi->m_listWidget_selectionGroups->selectedItems().at(i)->text() !=
"All" &&
815 m_pUi->m_listWidget_selectionGroups->selectedItems().at(i)->text() !=
"All EEG") {
816 tempSelectedList.append(m_pUi->m_listWidget_selectionGroups->selectedItems().at(i));
817 m_selectionGroupsMap.remove(m_pUi->m_listWidget_selectionGroups->selectedItems().at(i)->text());
821 qDeleteAll(tempSelectedList);
830 return QWidget::eventFilter(obj, event);
837 return m_pUi->viewWidget;
844 return m_pUi->controlWidget;
851 return ((m_pUi->m_listWidget_selectionGroups->currentItem()->text() ==
"All") && (m_pUi->m_listWidget_userDefined->count() == 0));
858 m_pSelectionScene->clear();
Static MATLAB-style FIFF facade: thin wrapper functions kept for parity with the historical mne-matla...
Generator that projects 3-D electrode positions onto a 2-D .lout topographic layout via least-squares...
Reader / writer for MNE .sel channel-selection files and Brainstorm .mon montage files.
Interactive 2-D sensor-layout picker for building and saving channel groups.
QAbstractTableModel exposing per-channel FIFF metadata (name, type, unit, position,...
QGraphicsScene of the sensor-layout dots used by DISPLIB::ChannelSelectionView for interactive channe...
Channel-selection group descriptor (DISPLIB::SelectionItem) and the matching QGraphicsItem (DISPLIB::...
2-D plotter layout read from an MNE-C .lout file: viewports, channel matching and zoom.
FIFF file I/O, in-memory data structures and high-level readers/writers.
2-D display widgets and visualisation helpers (charts, topography, colour maps).
Shared utilities (I/O helpers, spectral analysis, layout management, warp algorithms).
AbstractView(QWidget *parent=0, Qt::WindowFlags f=Qt::Widget)
void selectionChanged(const QList< QGraphicsItem * > &selectedChannelItems)
QListWidgetItem * getItemForChName(QListWidget *listWidget, const QString &channelName)
QString getCurrentLayoutFile()
const QMap< QString, QPointF > & getLayoutMap()
void showSelectedChannelsOnly(QStringList selectedChannels)
QStringList getSelectedChannels()
QWidget * getViewWidget()
void updateProcessingMode(ProcessingMode mode)
ChannelSelectionView(const QString &sSettingsPath="", QWidget *parent=0, QSharedPointer< ChannelInfoModel > pChannelInfoModel=QSharedPointer< ChannelInfoModel >(0), Qt::WindowType f=Qt::Widget)
void highlightChannels(QModelIndexList channelIndexList)
void newFiffFileLoaded(QSharedPointer< FIFFLIB::FiffInfo > &pFiffInfo)
void selectChannels(QStringList channelList)
void setCurrentlyMappedFiffChannels(const QStringList &mappedLayoutChNames)
void loadedLayoutMap(const QMap< QString, QPointF > &layoutMap)
QString getCurrentGroupFile()
void setCurrentLayoutFile(QString currentLayoutFile)
void updateGuiMode(GuiMode mode)
QWidget * getControlWidget()
QSharedPointer< ChannelInfoModel > SPtr
QGraphicsScene of sensor-layout dots used by ChannelSelectionView for interactive channel picking.
Graphics item representing a selectable electrode or channel in a 2-D layout scene.
static std::optional< MNELayout > read(const QString &path)
static bool makeLayout(const QList< QVector< float > > &inputPoints, QList< QVector< float > > &outputPoints, const QStringList &names, QFile &outFile, bool do_fit, float prad, float w, float h, bool writeFile=false, bool mirrorXAxis=false, bool mirrorYAxis=false)
static bool readBrainstormMonFile(QString path, QMultiMap< QString, QStringList > &selectionMap)
static bool writeBrainstormMonFiles(QString path, const QMultiMap< QString, QStringList > &selectionMap)
static bool readMNESelFile(QString path, QMultiMap< QString, QStringList > &selectionMap)
static bool writeMNESelFile(QString path, const QMultiMap< QString, QStringList > &selectionMap)