22#include "ui_channelselectionview.h"
47#include <QListWidgetItem>
49#include <QApplication>
51#include <QSignalBlocker>
74, m_pUi(new Ui::ChannelSelectionViewWidget)
75, m_pChannelInfoModel(pChannelInfoModel)
78 m_sSettingsPath = sSettingsPath;
83 initSelectionSceneView();
106void ChannelSelectionView::initListWidgets()
109 m_pUi->m_listWidget_userDefined->installEventFilter(
this);
110 m_pUi->m_listWidget_selectionGroups->installEventFilter(
this);
113 connect(m_pUi->m_listWidget_selectionGroups, &QListWidget::currentItemChanged,
114 this, &ChannelSelectionView::updateSelectionGroupsList);
118 connect(m_pUi->m_listWidget_userDefined->model(), &QAbstractTableModel::dataChanged,
124void ChannelSelectionView::initSelectionSceneView()
127 m_pSelectionScene =
new SelectionScene(m_pUi->m_graphicsView_layoutPlot);
128 m_pUi->m_graphicsView_layoutPlot->setScene(m_pSelectionScene);
130 connect(m_pSelectionScene, &QGraphicsScene::selectionChanged,
131 this, &ChannelSelectionView::updateUserDefinedChannelsList);
136void ChannelSelectionView::initComboBoxes()
138 m_pUi->m_comboBox_layoutFile->clear();
139 m_pUi->m_comboBox_layoutFile->insertItems(0, QStringList() <<
"babymeg-mag-inner-layer.lout"
140 <<
"babymeg-mag-outer-layer.lout"
142 <<
"Vectorview-grad.lout"
143 <<
"Vectorview-all.lout"
144 <<
"Vectorview-mag.lout"
145 <<
"standard_waveguard64_duke.lout"
150 connect(m_pUi->m_comboBox_layoutFile, &QComboBox::currentTextChanged,
151 this, &ChannelSelectionView::onComboBoxLayoutChanged);
154 QString selectionName(
"Vectorview-all.lout");
159 selectionName = QString(
"mne_browse_raw_vv.sel");
160 loadSelectionGroups(QCoreApplication::applicationDirPath() + selectionName.prepend(
"/../resources/general/selectionGroups/"));
165void ChannelSelectionView::initButtons()
167 connect(m_pUi->m_pushButton_saveSelection, &QPushButton::clicked,
168 this, &ChannelSelectionView::onBtnSaveUserSelection);
170 connect(m_pUi->m_pushButton_loadSelection, &QPushButton::clicked,
171 this, &ChannelSelectionView::onBtnLoadUserSelection);
173 connect(m_pUi->m_pushButton_addToSelectionGroups, &QPushButton::clicked,
174 this, &ChannelSelectionView::onBtnAddToSelectionGroups);
179void ChannelSelectionView::initCheckBoxes()
181 connect(m_pUi->m_checkBox_showBadChannelsAsRed, &QCheckBox::clicked,
189 m_currentlyLoadedFiffChannels = mappedLayoutChNames;
192 m_pUi->m_listWidget_visibleChannels->clear();
195 m_pUi->m_listWidget_selectionGroups->clear();
198 auto it = m_selectionGroupsMap.find(
"All");
199 if (it != m_selectionGroupsMap.end()) {
200 m_selectionGroupsMap.erase(it);
202 m_selectionGroupsMap.insert(
"All", m_currentlyLoadedFiffChannels);
205 for (
auto i = m_selectionGroupsMap.constBegin(); i != m_selectionGroupsMap.constEnd(); i++) {
206 m_pUi->m_listWidget_selectionGroups->insertItem(m_pUi->m_listWidget_selectionGroups->count(), i.key());
210 m_pUi->m_listWidget_selectionGroups->setCurrentItem(
getItemForChName(m_pUi->m_listWidget_selectionGroups,
"All"), QItemSelectionModel::Select);
213 updateSelectionGroupsList(
getItemForChName(m_pUi->m_listWidget_selectionGroups,
"All"),
new QListWidgetItem());
220 QStringList channelList;
221 for (
int i = 0; i < channelIndexList.size(); i++) {
222 QModelIndex nameIndex = m_pChannelInfoModel->index(channelIndexList.at(i).row(), 3);
226 QList<QGraphicsItem*> allSceneItems = m_pSelectionScene->items();
228 for (
int i = 0; i < allSceneItems.size(); i++) {
236 m_pSelectionScene->update();
243 QList<QGraphicsItem*> allSceneItems = m_pSelectionScene->items();
245 for (
int i = 0; i < allSceneItems.size(); i++) {
248 item->setSelected(
true);
250 item->setSelected(
false);
253 m_pSelectionScene->update();
261 QListWidget* targetListWidget;
262 if (m_pUi->m_listWidget_userDefined->count() > 0)
263 targetListWidget = m_pUi->m_listWidget_userDefined;
265 targetListWidget = m_pUi->m_listWidget_visibleChannels;
268 QStringList selectedChannels;
270 for (
int i = 0; i < targetListWidget->count(); i++) {
271 QListWidgetItem* item = targetListWidget->item(i);
272 selectedChannels << item->text();
275 return selectedChannels;
281 const QString& channelName)
283 for (
int i = 0; i < listWidget->count(); i++)
284 if (listWidget->item(i)->text() == channelName)
285 return listWidget->item(i);
287 return new QListWidgetItem();
303 loadLayout(resolveLayoutPath(m_pUi->m_comboBox_layoutFile->currentText()));
310 return m_pUi->m_comboBox_layoutFile->currentText();
317 return m_pUi->m_lineEdit_loadedFile->text();
324 qDebug() <<
"setCurrentLayoutFile:" << currentLayoutFile;
325 const QSignalBlocker blocker(m_pUi->m_comboBox_layoutFile);
326 m_pUi->m_comboBox_layoutFile->setCurrentText(currentLayoutFile);
328 loadLayout(resolveLayoutPath(currentLayoutFile));
336 QStringList badChannelMappedNames;
337 QStringList badChannelList = m_pChannelInfoModel->getBadChannelList();
339 if (m_pUi->m_checkBox_showBadChannelsAsRed->isChecked()) {
340 for (
int i = 0; i < m_pChannelInfoModel->rowCount(); i++) {
341 QModelIndex digIndex = m_pChannelInfoModel->index(i, 3);
344 digIndex = m_pChannelInfoModel->index(i, 1);
347 if (badChannelList.contains(origChName)) {
348 badChannelMappedNames << mappedChName;
353 m_pSelectionScene->repaintItems(m_layoutMap, badChannelMappedNames);
354 m_pSelectionScene->update();
365 QListWidget* targetListWidget;
366 if (m_pUi->m_listWidget_userDefined->count() > 0)
367 targetListWidget = m_pUi->m_listWidget_userDefined;
369 targetListWidget = m_pUi->m_listWidget_visibleChannels;
372 QStringList selectedChannels;
374 for (
int i = 0; i < targetListWidget->count(); i++) {
375 QListWidgetItem* item = targetListWidget->item(i);
376 int indexTemp = m_pChannelInfoModel->getIndexFromMappedChName(item->text());
378 if (indexTemp != -1) {
379 QModelIndex mappedNameIndex = m_pChannelInfoModel->index(indexTemp, 1);
382 selectedChannels << origChName;
384 selectedChannels << item->text();
390 if (!m_pSelectionScene->selectedItems().empty()) {
394 QList<QGraphicsItem*> visibleItemList = m_pSelectionScene->items();
395 QMutableListIterator<QGraphicsItem*> i(visibleItemList);
396 while (i.hasNext()) {
397 if (!i.next()->isVisible()) {
409 if (m_sSettingsPath.isEmpty()) {
413 QSettings settings(
"MNECPP");
417 settings.setValue(m_sSettingsPath + QString(
"/ChannelSelectionView/selectedLayoutFile"),
getCurrentLayoutFile());
418 settings.setValue(m_sSettingsPath + QString(
"/ChannelSelectionView/channelSelectionViewPos"), this->pos());
419 settings.setValue(m_sSettingsPath + QString(
"/ChannelSelectionView/selectedGroupFile"),
getCurrentGroupFile());
426 if (m_sSettingsPath.isEmpty()) {
430 QSettings settings(
"MNECPP");
432 setCurrentLayoutFile(settings.value(m_sSettingsPath + QString(
"/ChannelSelectionView/selectedLayoutFile"),
"Vectorview-all.lout").toString());
433 loadSelectionGroups(QCoreApplication::applicationDirPath() + settings.value(m_sSettingsPath + QString(
"/ChannelSelectionView/selectedGroupFile"),
"mne_browse_raw_vv.sel").toString().prepend(
"/../resources/general/selectionGroups/"));
437 QPoint pos = settings.value(m_sSettingsPath + QString(
"/ChannelSelectionView/channelSelectionViewPos"), QPoint(100, 100)).toPoint();
439 QList<QScreen*> screensList = QGuiApplication::screens();
440 if (screensList.isEmpty()) {
441 move(QPoint(100, 100));
473bool ChannelSelectionView::loadLayout(QString path)
475 qDebug() <<
"loadLayout:" << path;
477 const bool state = layout.has_value();
478 m_layoutMap = state ? layout->channelPositions() : QMap<QString, QPointF>();
481 QList<QVector<float>> inputPoints;
482 QList<QVector<float>> outputPoints;
484 QFile out(
"manualLayout.lout");
486 for (
int i = 0; i < m_pChannelInfoModel->rowCount(); i++) {
487 QModelIndex digIndex = m_pChannelInfoModel->index(i, 1);
490 digIndex = m_pChannelInfoModel->index(i, 8);
493 digIndex = m_pChannelInfoModel->index(i, 4);
498 temp.append(channelDig.x());
499 temp.append(channelDig.y());
500 temp.append(channelDig.z());
501 inputPoints.append(temp);
512 if (inputPoints.size() > 0) {
513 while (numberTries < 10) {
533 for (
int i = 0; i < outputPoints.size(); i++) {
534 if (!m_layoutMap.contains(names.at(i))) {
535 m_layoutMap[names.at(i)] = QPointF(outputPoints.at(i)[0], outputPoints.at(i)[1]);
540 m_pSelectionScene->repaintItems(m_layoutMap, bad);
541 m_pSelectionScene->update();
545 m_pUi->m_graphicsView_layoutPlot->fitInView(m_pSelectionScene->itemsBoundingRect(), Qt::KeepAspectRatio);
559QString ChannelSelectionView::resolveLayoutPath(
const QString& layoutFile)
const
561 if (layoutFile.isEmpty()) {
565 if (QFileInfo(layoutFile).isAbsolute()) {
569 return QCoreApplication::applicationDirPath() + QStringLiteral(
"/../resources/general/2DLayouts/") + layoutFile;
574bool ChannelSelectionView::loadSelectionGroups(QString path)
577 m_pUi->m_listWidget_visibleChannels->clear();
580 m_pUi->m_listWidget_selectionGroups->clear();
583 QString newPath = path;
585 m_selectionGroupsMap.clear();
590 if (!path.isEmpty()) {
591 if (path.contains(
".sel"))
593 if (path.contains(
".mon"))
598 auto it = m_selectionGroupsMap.find(
"All");
599 if (it != m_selectionGroupsMap.end()) {
600 m_selectionGroupsMap.erase(it);
602 m_selectionGroupsMap.insert(
"All", m_currentlyLoadedFiffChannels);
605 for (
int i = 0; i < m_pChannelInfoModel->rowCount(); i++) {
606 QModelIndex digIndex = m_pChannelInfoModel->index(i, 1);
609 digIndex = m_pChannelInfoModel->index(i, 4);
617 it = m_selectionGroupsMap.find(
"All EEG");
618 if (it != m_selectionGroupsMap.end()) {
619 m_selectionGroupsMap.erase(it);
621 m_selectionGroupsMap.insert(
"All EEG", names);
625 for (
auto i = m_selectionGroupsMap.constBegin(); i != m_selectionGroupsMap.constEnd(); i++) {
626 m_pUi->m_listWidget_selectionGroups->insertItem(m_pUi->m_listWidget_selectionGroups->count(), i.key());
630 updateSelectionGroupsList(
getItemForChName(m_pUi->m_listWidget_selectionGroups,
"All"),
new QListWidgetItem());
633 m_pUi->m_listWidget_selectionGroups->setCurrentItem(
getItemForChName(m_pUi->m_listWidget_selectionGroups,
"All"), QItemSelectionModel::Select);
635 m_pUi->m_lineEdit_loadedFile->setText(QFileInfo(path).fileName());
646void ChannelSelectionView::cleanUpMEGChannels()
649 for (
auto i = m_selectionGroupsMap.constBegin(); i != m_selectionGroupsMap.constEnd(); i++) {
650 QStringList channelList = i.value();
653 QMutableStringListIterator stringListIndex(channelList);
654 while (stringListIndex.hasNext()) {
655 stringListIndex.next();
657 if (!m_layoutMap.contains(stringListIndex.value()) && stringListIndex.value().contains(
"MEG"))
658 stringListIndex.remove();
662 m_selectionGroupsMap.insert(i.key(), channelList);
668void ChannelSelectionView::updateSelectionGroupsList(QListWidgetItem* current, QListWidgetItem* previous)
675 if (current->text().contains(
"EEG"))
681 m_pUi->m_listWidget_visibleChannels->clear();
682 auto items = m_selectionGroupsMap.find(current->text());
683 m_pUi->m_listWidget_visibleChannels->addItems(*items);
696void ChannelSelectionView::updateSceneItems()
698 QStringList visibleItems;
700 for (
int i = 0; i < m_pUi->m_listWidget_visibleChannels->count(); i++)
701 visibleItems << m_pUi->m_listWidget_visibleChannels->item(i)->text();
703 m_pSelectionScene->hideItems(visibleItems);
708void ChannelSelectionView::updateUserDefinedChannelsList()
710 QList<QGraphicsItem*> itemList = m_pSelectionScene->selectedItems();
711 QStringList userDefinedChannels;
713 for (
int i = 0; i < itemList.size(); i++) {
714 SelectionSceneItem* item =
static_cast<SelectionSceneItem*
>(itemList.at(i));
718 m_pUi->m_listWidget_userDefined->clear();
719 m_pUi->m_listWidget_userDefined->addItems(userDefinedChannels);
726void ChannelSelectionView::onBtnLoadUserSelection()
728 QString path = QFileDialog::getOpenFileName(
this,
729 QString(
"Open selection file"),
730 QString(
"../resources/general/selectionGroups/"),
731 tr(
"Selection files (*.sel *.mon)"));
736 loadSelectionGroups(path);
737 m_pUi->m_lineEdit_loadedFile->setText(QFileInfo(path).fileName());
742void ChannelSelectionView::onBtnSaveUserSelection()
745 QString path = QFileDialog::getSaveFileName(
this,
746 "Save user channel selection",
747 QString(
"../resources/general/selectionGroups/%1_%2_%3_UserSelection").arg(date.currentDate().year()).arg(date.currentDate().month()).arg(date.currentDate().day()),
748 tr(
"MNE selection file(*.sel);; Brainstorm montage file(*.mon)"));
750 QMultiMap<QString, QStringList> tempMap = m_selectionGroupsMap;
751 tempMap.remove(
"All");
752 tempMap.remove(
"All EEG");
754 if (!path.isEmpty()) {
755 if (path.contains(
".sel"))
757 if (path.contains(
".mon"))
764void ChannelSelectionView::onBtnAddToSelectionGroups()
767 for (
int i = 0; i < m_pUi->m_listWidget_userDefined->count(); i++)
768 temp << m_pUi->m_listWidget_userDefined->item(i)->text();
770 m_selectionGroupsMap.insert(m_pUi->m_lineEdit_selectionGroupName->text(), temp);
771 m_pUi->m_listWidget_selectionGroups->insertItem(m_pUi->m_listWidget_selectionGroups->count(), m_pUi->m_lineEdit_selectionGroupName->text());
776void ChannelSelectionView::onComboBoxLayoutChanged()
778 QString selectionName(m_pUi->m_comboBox_layoutFile->currentText());
779 loadLayout(resolveLayoutPath(selectionName));
785void ChannelSelectionView::resizeEvent(QResizeEvent* event)
795bool ChannelSelectionView::eventFilter(QObject* obj, QEvent* event)
798 if (obj == m_pUi->m_listWidget_userDefined && event->type() == QEvent::KeyRelease) {
799 QKeyEvent* keyEvent =
static_cast<QKeyEvent*
>(event);
801 if (keyEvent->key() == Qt::Key_Delete) {
802 qDeleteAll(m_pUi->m_listWidget_userDefined->selectedItems());
809 if (obj == m_pUi->m_listWidget_selectionGroups && event->type() == QEvent::KeyRelease) {
810 QKeyEvent* keyEvent =
static_cast<QKeyEvent*
>(event);
812 if (keyEvent->key() == Qt::Key_Delete) {
813 QList<QListWidgetItem*> tempSelectedList;
815 for (
int i = 0; i < m_pUi->m_listWidget_selectionGroups->selectedItems().size(); i++) {
816 if (m_pUi->m_listWidget_selectionGroups->selectedItems().at(i)->text() !=
"All" &&
817 m_pUi->m_listWidget_selectionGroups->selectedItems().at(i)->text() !=
"All EEG") {
818 tempSelectedList.append(m_pUi->m_listWidget_selectionGroups->selectedItems().at(i));
819 m_selectionGroupsMap.remove(m_pUi->m_listWidget_selectionGroups->selectedItems().at(i)->text());
823 qDeleteAll(tempSelectedList);
832 return QWidget::eventFilter(obj, event);
839 return m_pUi->viewWidget;
846 return m_pUi->controlWidget;
853 return ((m_pUi->m_listWidget_selectionGroups->currentItem()->text() ==
"All") && (m_pUi->m_listWidget_userDefined->count() == 0));
860 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)