MNE-CPP  beta 1.0
mainwindow.cpp
1 //=============================================================================================================
36 //*************************************************************************************************************
37 //=============================================================================================================
38 // INCLUDES
39 //=============================================================================================================
40 
41 #include <iostream>
42 #include <vector>
43 #include <math.h>
44 #include <fiff/fiff.h>
45 #include <mne/mne.h>
46 
47 #include "math.h"
48 #include "mainwindow.h"
49 #include "ui_mainwindow.h"
50 
51 //*************************************************************************************************************
52 //=============================================================================================================
53 // QT INCLUDES
54 //=============================================================================================================
55 
56 #include <QTableWidgetItem>
57 #include <QFileDialog>
58 #include <QHeaderView>
59 #include <QMessageBox>
60 #include <QMap>
61 #include <QtConcurrent>
62 #include <qtconcurrentrun.h>
63 
64 #include "QtGui"
65 
66 //*************************************************************************************************************
67 //=============================================================================================================
68 // USED NAMESPACES
69 //=============================================================================================================
70 
71 using namespace MNELIB;
72 using namespace UTILSLIB;
73 
74 //*************************************************************************************************************
75 //=============================================================================================================
76 // FORWARD DECLARATIONS
77 //=============================================================================================================
78 
79 bool _new_paint;
80 bool _has_file;
81 
82 fiff_int_t _from;
83 fiff_int_t _to;
84 
85 fiff_int_t _first_sample;
86 fiff_int_t _last_sample;
87 fiff_int_t _press_pos;
88 
89 qreal _offset_time;
90 qint32 _samplecount;
91 qreal _max_pos;
92 qreal _max_neg;
93 qreal _sample_rate;
94 qreal _signal_maximum;
95 qreal _signal_negative_scale;
96 qreal _border_margin_height;
97 qint32 _x_axis_height;
98 
99 QList<QColor> _colors;
100 QStringList _matlab_channels;
101 MatrixXd _signal_matrix;
102 MatrixXd _atom_sum_matrix;
103 MatrixXd _residuum_matrix;
104 FiffEvoked _pick_evoked;
105 
106 QTimer *_counter_timer;
107 QThread* mp_Thread;
108 AdaptiveMp *adaptive_Mp;
109 FixDictMp *fixDict_Mp ;
110 Formulaeditor *_formula_editor;
111 EditorWindow *_editor_window;
112 Enhancededitorwindow *_enhanced_editor_window;
113 settingwindow *_setting_window;
114 TreebasedDictWindow *_treebased_dict_window;
115 
116 //*************************************************************************************************************
117 //=============================================================================================================
118 // MAIN
119 //=============================================================================================================
120 MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
121 {
122  ui->setupUi(this);
123 
124  this->setMinimumSize(1280, 640);
125  callGraphWindow = new GraphWindow();
126  callGraphWindow->setMouseTracking(true);
127  callGraphWindow->setMinimumHeight(140);
128  callGraphWindow->setMinimumWidth(500);
129  ui->l_Graph->addWidget(callGraphWindow);
130 
131  connect(callGraphWindow, SIGNAL(read_new()), this, SLOT(on_mouse_button_release()));
132 
133  callAtomSumWindow = new AtomSumWindow();
134  callAtomSumWindow->setMouseTracking(true);
135  callAtomSumWindow->setMinimumHeight(140);
136  callAtomSumWindow->setMinimumWidth(500);
137  ui->l_atoms->addWidget(callAtomSumWindow);
138 
139  callResidumWindow = new ResiduumWindow();
140  callResidumWindow->setMouseTracking(true);
141  callResidumWindow->setMinimumHeight(140);
142  callResidumWindow->setMinimumWidth(500);
143  ui->l_res->addWidget(callResidumWindow);
144 
145  callXAxisWindow = new XAxisWindow();
146  callXAxisWindow->setMaximumHeight(0);
147  callXAxisWindow->setToolTip("timeline");
148  ui->l_XAxis->addWidget(callXAxisWindow);
149  // set progressbar
150  ui->progressBarCalc->setHidden(true);
151  ui->progress_bar_save->setHidden(true);
152 
153  ui->splitter->setStretchFactor(1,4);
154 
155  ui->lb_from->setHidden(true);
156  ui->dsb_from->setHidden(true);
157  ui->lb_to->setHidden(true);
158  ui->dsb_to->setHidden(true);
159  ui->lb_samples->setHidden(true);
160  ui->sb_sample_count->setHidden(true);
161  ui->cb_all_select->setHidden(true);
162  ui->lb_timer->setHidden(true);
163 
164  // set result tableview
165  ui->tbv_Results->setColumnCount(5);
166  ui->tbv_Results->setHorizontalHeaderLabels(QString("energy\n[%];scale\n[sec];trans\n[sec];modu\n[Hz];phase\n[rad]").split(";"));
167  ui->tbv_Results->setColumnWidth(0,55);
168  ui->tbv_Results->setColumnWidth(1,45);
169  ui->tbv_Results->setColumnWidth(2,40);
170  ui->tbv_Results->setColumnWidth(3,40);
171  ui->tbv_Results->setColumnWidth(4,40);
172 
173  is_saved = true;
174  is_calulating = false;
175  _new_paint = true;
176  _sample_rate = 1;
177  _counter_timer = new QTimer();
178 
179  this->cb_model = new QStandardItemModel;
180  connect(this->cb_model, SIGNAL(dataChanged ( const QModelIndex&, const QModelIndex&)), this, SLOT(cb_selection_changed(const QModelIndex&, const QModelIndex&)));
181  connect(ui->tbv_Results->model(), SIGNAL(dataChanged ( const QModelIndex&, const QModelIndex&)), this, SLOT(tbv_selection_changed(const QModelIndex&, const QModelIndex&)));
182  connect(_counter_timer, SIGNAL(timeout()), this, SLOT(on_time_out()));
183 
184  qRegisterMetaType<source_file_type>("source_file_type");
185  qRegisterMetaType<Eigen::MatrixXd>("MatrixXd");
186  qRegisterMetaType<Eigen::VectorXd>("VectorXd");
187  qRegisterMetaType<Eigen::RowVectorXi>("RowVectorXi");
188  qRegisterMetaType<adaptive_atom_list>("adaptive_atom_list");
189  qRegisterMetaType<fix_dict_atom_list>("fix_dict_atom_list");
190  qRegisterMetaType<FIFFLIB::fiff_int_t>("fiff_int_t");
191  qRegisterMetaType<select_map>("select_map");
192 
193  QDir dir(QDir::homePath() + "/" + "Matching-Pursuit-Toolbox");
194  if(!dir.exists())dir.mkdir(".");
195  fill_dict_combobox();
196 
197  QSettings settings;
198  move(settings.value("pos", QPoint(200, 200)).toPoint());
199  resize(settings.value("size", QSize(1050, 700)).toSize());
200  this->restoreState(settings.value("window_state").toByteArray());
201  ui->splitter->restoreState(settings.value("splitter_sizes").toByteArray());
202  last_open_path = settings.value("last_open_path", QDir::homePath()+ "/" + "Matching-Pursuit-Toolbox").toString();
203  last_save_path = settings.value("last_save_path", QDir::homePath()+ "/" + "Matching-Pursuit-Toolbox").toString();
204 
205  //infolabel is invisible
206  if(!settings.value("show_infos", true).toBool())
207  {
208  ui->lb_info_content->setHidden(true);
209  ui->lb_info->setHidden(true);
210  ui->lb_figure_of_merit->setHidden(true);
211  }
212 }
213 
214 //*************************************************************************************************************************************
215 
216 MainWindow::~MainWindow()
217 {
218  if(_editor_window != NULL)
219  delete _editor_window;
220  if(_enhanced_editor_window != NULL)
221  delete _enhanced_editor_window;
222  if(_setting_window != NULL)
223  delete _setting_window;
224  if(_formula_editor != NULL)
225  delete _formula_editor;
226  if(_treebased_dict_window != NULL)
227  delete _treebased_dict_window;
228 
229  delete callAtomSumWindow;
230  delete callGraphWindow;
231  delete callResidumWindow;
232  delete callXAxisWindow;
233 
234  delete this->cb_model;
235  delete ui;
236 }
237 
238 //*************************************************************************************************************************************
239 
240 SaveFifFile::SaveFifFile(){}
241 
242 //*************************************************************************************************************************************
243 
244 SaveFifFile::~SaveFifFile(){}
245 
246 //*************************************************************************************************************************************
247 
248 void MainWindow::closeEvent(QCloseEvent * event)
249 {
250 
251  if(ui->progress_bar_save->isVisible())
252  {
253  if(QMessageBox::question(this, "warning", "Saving fif-file is still in progress. Are you sure you want to quit?") == QMessageBox::Yes)
254  event->accept();
255  else
256  {
257  event->ignore();
258  return;
259  }
260  }
261 
262  if(is_calulating)
263  {
264  if(QMessageBox::question(this, "warning", "Calculation is still in progress. Are you sure you want to quit?") == QMessageBox::Yes)
265  event->accept();
266  else
267  {
268  event->ignore();
269  return;
270  }
271  }
272 
273  QSettings settings;
274  if(settings.value("show_warnings",true).toBool() && !is_saved)
275  {
276  QString text = "Warning, your changes have not been saved.\nTo close this window and discard your changes\nclick OK otherwise click Cancel and save the current changes.";
277  DeleteMessageBox *msg_box = new DeleteMessageBox(text, "Warning...", "OK", "Cancel");
278  msg_box->setModal(true);
279  qint32 result = msg_box->exec();
280 
281  if(result == 0)
282  {
283  msg_box->close();
284  event->ignore();
285  return;
286  }
287  msg_box->close();
288  }
289 
290  /* ToDo: call threadinterrupt
291  if(mp_Thread != NULL)
292  if(mp_Thread->isRunning())
293  emit mp_Thread->requestInterruption();
294  */
295 
296  if(!this->isMaximized())
297  {
298  settings.setValue("pos", pos());
299  settings.setValue("size", size());
300  }
301  settings.setValue("splitter_sizes", ui->splitter->saveState());
302  settings.setValue("window_state", this->saveState());
303  settings.setValue("maximized", this->isMaximized());
304  settings.setValue("last_open_path", last_open_path);
305  settings.setValue("last_save_path", last_save_path);
306  event->accept();
307 }
308 
309 //*************************************************************************************************************************************
310 
311 void MainWindow::open_file()
312 {
313  QString temp_file_name = QFileDialog::getOpenFileName(this, "Please select signal file.", last_open_path,"(*.fif *.txt)");
314  if(temp_file_name.isNull()) return;
315 
316  QStringList string_list = temp_file_name.split('/');
317  last_open_path = "";
318  for(qint32 i = 0; i < string_list.length() - 1; i++)
319  last_open_path += string_list.at(i) + '/';
320  file_name = temp_file_name;
321  this->cb_model->clear();
322  this->cb_items.clear();
323 
324  this->setWindowTitle(string_list.last().append(" - Matching-Pursuit-Toolbox"));//show current file in header of mainwindow
325 
326  ui->dsb_sample_rate->setEnabled(true);
327 
328  QFile file(file_name);
329  if (!file.open(QIODevice::ReadOnly))
330  {
331  QMessageBox::warning(this, tr("Error"),
332  tr("error: unable to open signal file."));
333  this->setWindowTitle("Matching-Pursuit-Toolbox");
334  return;
335  }
336  file.close();
337 
338  _colors.clear();
339  _colors.append(QColor(0, 0, 0));
340  _pick_evoked.clear();
341  _offset_time = 0;
342  _from = -1;
343  if(file_name.endsWith(".fif", Qt::CaseInsensitive))
344  {
345  _has_file = true;
346 
347  if(!read_fiff_ave(file_name))
348  if(!read_fiff_file(file_name))
349  {
350  this->setWindowTitle("Matching-Pursuit-Toolbox");
351  _has_file = false;
352  return;
353  }
354 
355  ui->dsb_sample_rate->setEnabled(false);
356  }
357  else
358  {
359  _has_file = true;
360 
361  if(!read_matlab_file(file_name))
362  {
363  this->setWindowTitle("Matching-Pursuit-Toolbox");
364  _has_file = false;
365  return;
366  }
367 
368  ui->dsb_sample_rate->setEnabled(true);
369  }
370 
371  //initial
372  original_signal_matrix = _signal_matrix;
373  fill_channel_combobox();
374  read_fiff_changed = true;
375 
376  last_from = _from;
377  last_to = _to;
378  last_sample_count = _to - _from + 1;
379 
380  ui->dsb_from->setMaximum((_last_sample - 63) / _sample_rate);
381  ui->dsb_to->setMinimum((_first_sample + 63) / _sample_rate);
382  ui->lb_from->setToolTip(QString("minimum: %1 seconds").arg(_first_sample / _sample_rate));
383  ui->lb_to->setToolTip(QString("maximum: %1 seconds").arg(_last_sample / _sample_rate));
384  ui->dsb_from->setToolTip(QString("sample: %1").arg(_from));
385  ui->dsb_to->setToolTip(QString("sample: %1").arg(_to));
386  ui->sb_sample_count->setToolTip(QString("epoch: %1 sec").arg((_to - _from + 1) / _sample_rate));
387  ui->lb_samples->setToolTip(QString("min: 64 (%1 sec)\nmax: 4096 (%2 sec)").arg(64 / _sample_rate).arg(4096 / _sample_rate));
388 
389  ui->dsb_from->setValue((_from / _sample_rate) + _offset_time);
390  ui->dsb_to->setValue(_to / _sample_rate + _offset_time);
391  _samplecount = _to - _from + 1;
392  ui->sb_sample_count->setValue(_to - _from + 1);
393 
394  read_fiff_changed = false;
395 
396  ui->lb_from->setHidden(false);
397  ui->dsb_from->setHidden(false);
398  ui->lb_to->setHidden(false);
399  ui->dsb_to->setHidden(false);
400  ui->lb_samples->setHidden(false);
401  ui->sb_sample_count->setHidden(false);
402  ui->tbv_Results->setRowCount(0);
403  ui->lb_figure_of_merit->setHidden(true);
404  callXAxisWindow->setMinimumHeight(22);
405  callXAxisWindow->setMaximumHeight(22);
406 
407 
408  _atom_sum_matrix = MatrixXd::Zero(_signal_matrix.rows(), _signal_matrix.cols()); //resize
409  _residuum_matrix = MatrixXd::Zero(_signal_matrix.rows(), _signal_matrix.cols()); //resize
410 
411  ui->progressBarCalc->reset();
412  ui->progressBarCalc->setVisible(false);
413  ui->lb_signal_energy->clear();
414  ui->lb_approx_energy->clear();
415  ui->lb_residual_energy->clear();
416  ui->lb_signal_energy_text->clear();
417  ui->lb_approx_energy_text->clear();
418  ui->lb_residual_energy_text->clear();
419  ui->lb_info_content->clear();
420  ui->cb_all_select->setHidden(true);
421  ui->lb_timer->setHidden(true);
422  ui->actionSpeicher->setEnabled(false);
423  ui->actionSpeicher_unter->setEnabled(false);
424  ui->actionExport->setEnabled(false);
425  if(_signal_matrix.cols() == 0) ui->btt_Calc->setEnabled(false);
426  else ui->btt_Calc->setEnabled(true);
427  has_warning = false;
428 
429  _new_paint = true;
430 
431  update();
432 }
433 
434 //*************************************************************************************************************************************
435 
436 bool MainWindow::read_fiff_ave(QString file_name)
437 {
438  QFile t_fileEvoked(file_name);
439 
440  fiff_int_t setno = 0;
441  QPair<QVariant, QVariant> baseline(QVariant(), 0);
442  FiffEvoked evoked(t_fileEvoked, setno, baseline);
443  if(evoked.isEmpty())
444  return false;
445 
446  QSettings settings;
447  QMap<QString, QVariant> chn_name_map;
448  for(qint32 m = 0; m < 4; m++)
449  chn_name_map.insert(QString("MEG;EEG;STI;EOG").split(';').at(m), true);
450  chn_name_map = settings.value("channel_names", chn_name_map).toMap();
451 
452  QStringList pick_list;
453 
454  QMap<QString, QVariant>::const_iterator i;
455  for (i = chn_name_map.constBegin(); i != chn_name_map.constEnd(); ++i)
456  if(i.value().toBool())
457  pick_list.append(i.key());
458 
459  // Set up pick list: MEG + STI 014 - bad channels
460  QStringList include;
461  include << "STI 014";
462  bool want_meg = chn_name_map["MEG"].toBool();
463  bool want_eeg = chn_name_map["EEG"].toBool();
464  bool want_stim = chn_name_map["STI"].toBool();
465 
466 
467  QStringList filter_list;
468  for(qint32 i = 0; i < evoked.info.ch_names.length(); i++)
469  {
470  for(qint32 k = 0; k < pick_list.length(); k++)
471  if(evoked.info.ch_names.at(i).contains(pick_list.at(k)))
472  filter_list.append(evoked.info.ch_names.at(i));
473  }
474 
475  _pick_evoked = evoked.pick_channels(filter_list);
476  picks = _pick_evoked.info.pick_types(want_meg, want_eeg, want_stim);
477  pick_info = _pick_evoked.info.pick_info();
478 
479  if(_pick_evoked.isEmpty())
480  return false;
481 
482  ui->dsb_sample_rate->setValue(_pick_evoked.info.sfreq);
483  _sample_rate = _pick_evoked.info.sfreq;
484 
485 
486  _signal_matrix = MatrixXd::Zero(_pick_evoked.data.cols(), _pick_evoked.data.rows());
487 
488  for(qint32 channels = 0; channels < _pick_evoked.data.rows(); channels++)
489  _signal_matrix.col(channels) = _pick_evoked.data.row(channels);
490 
491 
492  _offset_time = _pick_evoked.times[0];
493  _from = 0;
494  _first_sample = _pick_evoked.first;
495  _to = _signal_matrix.rows() - 1;
496  _last_sample = _pick_evoked.last;
497 
498  reference_matrix = _signal_matrix;
499 
500  file_type = AVE;
501  return true;
502 }
503 
504 //*************************************************************************************************************************************
505 
506 void MainWindow::read_fiff_ave_new()
507 {
508  qint32 row_number = 0;
509  qint32 selected_chn = 0;
510 
511  qint32 size = 0;
512  for(qint32 i = 0; i < reference_matrix.cols(); i++)
513  if(select_channel_map[i] == true)
514  size++;
515 
516  _signal_matrix = MatrixXd::Zero(_to - _from, size);
517 
518  _colors.clear();
519  for(qint32 channels = 0; channels < reference_matrix.cols(); channels++)
520  if(select_channel_map[channels] == true)
521  {
522  row_number = 0;
523  _colors.append(original_colors.at(channels));
524  for(qint32 i = _from; i < _to; i++)
525  {
526  _signal_matrix(row_number, selected_chn) = reference_matrix(i, channels);
527  row_number++;
528  }
529  selected_chn++;
530  }
531 
532  //resize original signal matrix so that all channels are still in memory and only time is changed
533  original_signal_matrix = MatrixXd::Zero(_signal_matrix.rows(), reference_matrix.cols());
534  for(qint32 channels = 0; channels < reference_matrix.cols(); channels++)
535  {
536  row_number = 0;
537  for(qint32 i = _from; i < _to; i++ )
538  {
539  original_signal_matrix(row_number, channels) = reference_matrix(i, channels);
540  row_number++;
541  }
542  }
543 
544  _atom_sum_matrix = MatrixXd::Zero(_signal_matrix.rows(), _signal_matrix.cols()); //resize
545  _residuum_matrix = MatrixXd::Zero(_signal_matrix.rows(), _signal_matrix.cols()); //resize
546 
547  ui->tbv_Results->clearContents();
548  ui->tbv_Results->setRowCount(0);
549  ui->actionSpeicher->setEnabled(false);
550  ui->actionSpeicher_unter->setEnabled(false);
551  ui->lb_info_content->clear();
552  ui->cb_all_select->setHidden(true);
553  ui->lb_timer->setHidden(true);
554  ui->progressBarCalc->setHidden(true);
555  ui->actionExport->setEnabled(false);
556  ui->lb_figure_of_merit->setHidden(true);
557  ui->lb_signal_energy->clear();
558  ui->lb_approx_energy->clear();
559  ui->lb_residual_energy->clear();
560  ui->lb_signal_energy_text->clear();
561  ui->lb_approx_energy_text->clear();
562  ui->lb_residual_energy_text->clear();
563 
564  has_warning = false;
565  _new_paint = true;
566  update();
567 }
568 
569 //*************************************************************************************************************************************
570 
571 bool MainWindow::read_fiff_file(QString fileName)
572 {
573  // Setup for reading the raw data
574  QFile t_fileRaw(fileName);
575  FiffRawData raw(t_fileRaw);
576 
577  //save channel names to settings
578  QSettings settings;
579  QMap<QString, QVariant> chn_name_map;
580  for(qint32 m = 0; m < 4; m++)
581  chn_name_map.insert(QString("MEG;EEG;STI;EOG").split(';').at(m), true);
582 
583  chn_name_map = settings.value("channel_names", chn_name_map).toMap();
584  QString next_name;
585 
586  for(qint32 k = 0; k < raw.info.ch_names.length(); k++)
587  {
588  bool found_no_new_name = false;
589  next_name = raw.info.ch_names.at(k).split(" ").first();
590  if(chn_name_map.contains(next_name))
591  {
592  found_no_new_name = true;
593  break;
594  }
595  if(!found_no_new_name)
596  chn_name_map.insert(next_name, true);
597  }
598 
599  settings.setValue("channel_names", chn_name_map);
600 
601  // Set up pick list: MEG + STI 014 - bad channels
602  QStringList include;
603  include << "STI 014";
604  bool want_meg = chn_name_map["MEG"].toBool();
605  bool want_eeg = chn_name_map["EEG"].toBool();
606  bool want_stim = chn_name_map["STI"].toBool();
607 
608  picks = raw.info.pick_types(want_meg, want_eeg, want_stim/*, include /*, raw.info.bads*/);
609 
610  //save fiff data borders global
611  _first_sample = raw.first_samp;
612  _last_sample = raw.last_samp;
613 
614  if(_from == -1)
615  {
616  _from = _first_sample;
617  if(_from + 511 <= _last_sample) _to = _from + 511;
618  else _to = _last_sample;
619  }
620 
621  ui->dsb_sample_rate->setValue(raw.info.sfreq);
622  _sample_rate = raw.info.sfreq;
623 
624  pick_info = raw.info.pick_info(picks);
625  // Read a data segment
626  // times output argument is optional
627  if (!raw.read_raw_segment(datas, times, _from, _to, picks))
628  {
629  QMessageBox::critical(this, "Error", "error reading fif-file. Could not read raw segment.");
630  printf("Could not read raw segment.\n");
631  return false;
632  }
633  printf("Read %d samples.\n",(qint32)datas.cols());
634 
635  //signal must be filled with datas like this, because data.col == signal.row and vice versa
636  _signal_matrix = MatrixXd::Zero(datas.cols(),datas.rows());
637 
638  for(qint32 channels = 0; channels < datas.rows(); channels++)
639  _signal_matrix.col(channels) = datas.row(channels);
640 
641  file_type = RAW;
642  return true;
643 }
644 
645 //*************************************************************************************************************************************
646 
647 void MainWindow::read_fiff_file_new(QString file_name)
648 {
649  qint32 selected_chn = 0;
650  read_fiff_file(file_name);
651  original_signal_matrix = _signal_matrix;
652 
653  qint32 size = 0;
654  for(qint32 i = 0; i < original_signal_matrix.cols(); i++)
655  if(select_channel_map[i] == true)
656  size++;
657 
658  _colors.clear();
659  _signal_matrix = MatrixXd::Zero(original_signal_matrix.rows(), size);
660 
661  for(qint32 channels = 0; channels < original_signal_matrix.cols(); channels++)
662  if(select_channel_map[channels] == true)
663  {
664  _colors.append(original_colors.at(channels));
665  _signal_matrix.col(selected_chn) = original_signal_matrix.col(channels);
666  selected_chn++;
667  }
668 
669  _atom_sum_matrix = MatrixXd::Zero(_signal_matrix.rows(), _signal_matrix.cols()); //resize
670  _residuum_matrix = MatrixXd::Zero(_signal_matrix.rows(), _signal_matrix.cols()); //resize
671 
672  ui->tbv_Results->clearContents();
673  ui->tbv_Results->setRowCount(0);
674  ui->actionSpeicher->setEnabled(false);
675  ui->actionSpeicher_unter->setEnabled(false);
676  ui->lb_info_content->clear();
677  ui->cb_all_select->setHidden(true);
678  ui->lb_timer->setHidden(true);
679  ui->progressBarCalc->setHidden(true);
680  ui->actionExport->setEnabled(false);
681  ui->lb_figure_of_merit->setHidden(true);
682  ui->lb_signal_energy->clear();
683  ui->lb_approx_energy->clear();
684  ui->lb_residual_energy->clear();
685  ui->lb_signal_energy_text->clear();
686  ui->lb_approx_energy_text->clear();
687  ui->lb_residual_energy_text->clear();
688 
689  has_warning = false;
690  _new_paint = true;
691  update();
692 }
693 
694 //*************************************************************************************************************************************
695 
696 bool MainWindow::read_matlab_file(QString fileName)
697 {
698  QFile file(fileName);
699  file.open(QIODevice::ReadOnly);
700 
701  QTextStream stream(&file);
702  bool isFloat;
703 
704  _matlab_channels = stream.readAll().split('\n', QString::SkipEmptyParts);
705 
706  for(qint32 k = 0; k < _matlab_channels.length(); k++)
707  {
708  qint32 row_number = 0;
709  QStringList signal_samples = _matlab_channels.at(k).split(',', QString::SkipEmptyParts);
710 
711  if(k==0)
712  {
713  _first_sample = 0;
714  _last_sample = signal_samples.length() - 1;
715  _from = _first_sample;
716 
717  if(_from + 511 <= _last_sample)
718  _to = _from + 511;
719  else
720  _to = _last_sample;
721 
722  _signal_matrix = MatrixXd::Zero(_to - _from + 1, _matlab_channels.length());
723  }
724 
725  for(qint32 i = _from; i <= _to; i++)
726  {
727  qreal value = signal_samples.at(i).toFloat(&isFloat);
728  if(!isFloat)
729  {
730  _signal_matrix = MatrixXd::Zero(0, 0);
731  QMessageBox::critical(this, "error", QString("error reading matlab file. Could not read line %1 from file %2.").arg(i).arg(fileName));
732  //reset ui
733  ui->tbv_Results->clear();
734  ui->tbv_Results->clearContents();
735  ui->tbv_Results->setRowCount(0);
736  ui->tbv_Results->setColumnCount(0);
737  ui->btt_Calc->setDisabled(true);
738  //reset progressbar text color to black
739  pal.setColor(QPalette::Text, Qt::black);
740  ui->progressBarCalc->setPalette(pal);
741  ui->progressBarCalc->setFormat("residual energy: 100% iterations: 0");
742  //reset infolabels
743  ui->lb_signal_energy->setHidden(true);
744  ui->lb_signal_energy_text->setHidden(true);
745  ui->lb_approx_energy->setHidden(true);
746  ui->lb_approx_energy_text->setHidden(true);
747  ui->lb_residual_energy->setHidden(true);
748  ui->lb_residual_energy_text->setHidden(true);
749 
750  is_white = false;
751 
752  is_saved = false;
753  has_warning = false;
754  return false;
755  }
756  _signal_matrix(row_number, k) = value;
757  row_number++;
758  }
759  }
760  file.close();
761 
762  _sample_rate = 1;
763  ui->dsb_sample_rate->setValue(_sample_rate);
764 
765  file_type = TXT;
766 
767  return true;
768 }
769 
770 //*************************************************************************************************************************************
771 
772 void MainWindow::read_matlab_file_new()
773 {
774  bool isFloat;
775  qint32 selected_chn = 0;
776 
777  _signal_matrix = MatrixXd::Zero(_to - _from + 1, _matlab_channels.length());
778 
779  for(qint32 k = 0;k < _matlab_channels.length(); k++)
780  {
781  qint32 row_number = 0;
782  QStringList signal_samples = _matlab_channels.at(k).split(',', QString::SkipEmptyParts);
783 
784  for(qint32 i = _from; i <= _to; i++)
785  {
786  qreal value = signal_samples.at(i).toFloat(&isFloat);
787  if(!isFloat)
788  _signal_matrix = MatrixXd::Zero(0, 0);
789 
790  _signal_matrix(row_number, k) = value;
791  row_number++;
792  }
793  }
794 
795  original_signal_matrix = _signal_matrix;
796 
797  qint32 size = 0;
798  for(qint32 i = 0; i < original_signal_matrix.cols(); i++)
799  if(select_channel_map[i] == true)
800  size++;
801 
802  _colors.clear();
803  _signal_matrix = MatrixXd::Zero(original_signal_matrix.rows(), size);
804 
805  for(qint32 channels = 0; channels < original_signal_matrix.cols(); channels++)
806  if(select_channel_map[channels] == true)
807  {
808  _colors.append(original_colors.at(channels));
809  _signal_matrix.col(selected_chn) = original_signal_matrix.col(channels);
810  selected_chn++;
811  }
812 
813 
814  _atom_sum_matrix = MatrixXd::Zero(_signal_matrix.rows(), _signal_matrix.cols()); //resize
815  _residuum_matrix = MatrixXd::Zero(_signal_matrix.rows(), _signal_matrix.cols()); //resize
816 
817  ui->tbv_Results->clearContents();
818  ui->tbv_Results->setRowCount(0);
819  ui->actionSpeicher->setEnabled(false);
820  ui->actionSpeicher_unter->setEnabled(false);
821  ui->lb_info_content->clear();
822  ui->cb_all_select->setHidden(true);
823  ui->lb_timer->setHidden(true);
824  ui->progressBarCalc->setHidden(true);
825  ui->actionExport->setEnabled(false);
826  ui->lb_figure_of_merit->setHidden(true);
827  ui->lb_signal_energy->clear();
828  ui->lb_approx_energy->clear();
829  ui->lb_residual_energy->clear();
830  ui->lb_signal_energy_text->clear();
831  ui->lb_approx_energy_text->clear();
832  ui->lb_residual_energy_text->clear();
833 
834  has_warning = false;
835  _new_paint = true;
836  update();
837 }
838 //*************************************************************************************************************************************
839 
841 {
842  QDir dir(QDir::homePath() + "/" + "Matching-Pursuit-Toolbox");
843  QStringList filterList;
844  filterList.append("*.dict");
845  QFileInfoList fileList = dir.entryInfoList(filterList);
846 
847  ui->cb_Dicts->clear();
848  for(int i = 0; i < fileList.length(); i++)
849  ui->cb_Dicts->addItem(QIcon(":/images/icons/DictIcon.png"), fileList.at(i).baseName());
850 
851  //dis-/enable button calc, if dicts are existing
852  if(ui->cb_Dicts->itemText(0) == "" && ui->rb_OwnDictionary->isChecked())
853  ui->btt_Calc->setEnabled(false);
854  else if(_has_file && ui->rb_OwnDictionary->isChecked())
855  ui->btt_Calc->setEnabled(true);
856 
857 }
858 
859 //*************************************************************************************************************************************
860 
861 void MainWindow::fill_channel_combobox()
862 {
863  //select all channels item
864  this->cb_item = new QStandardItem;
865  this->cb_item->setText("de/select all channels");
866  this->cb_item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
867  this->cb_item->setData(Qt::Checked, Qt::CheckStateRole);
868  this->cb_model->appendRow(this->cb_item);
869  this->cb_items.push_back(this->cb_item);
870 
871  QSettings settings;
872 
873  QStringList chn_names;
874  chn_names.clear();
875  if(!pick_info.isEmpty())
876  chn_names = pick_info.ch_names;
877  else
878  for(qint32 i = 0; i < _signal_matrix.cols(); i++)
879  chn_names.append(QString::number(i));
880 
881 
882 
883  //cout << "chn_name_lenght: " << chn_names.length() << "\n";
884  //cout << "channelcount: " << _signal_matrix.cols() << "\n";
885  for(qint32 channels = 1; channels <= _signal_matrix.cols(); channels++)
886  {
887  if(settings.value("pastell_colors", false).toBool())
888  _colors.append(QColor::fromHsv(qrand() % 256, 255, 190));
889  else
890  _colors.append(QColor::fromRgb(qrand() / ((qreal)RAND_MAX + 300) * 255, qrand() / ((qreal)RAND_MAX + 300) * 255, qrand() / ((qreal)RAND_MAX + 300) * 255));
891  //channel item
892  this->cb_item = new QStandardItem;
893  this->cb_item->setText(chn_names.at(channels - 1));
894  this->cb_item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
895  this->cb_item->setData(Qt::Checked, Qt::CheckStateRole);
896  select_channel_map.insert(channels - 1, true);
897  if(!pick_info.isEmpty())
898  {
899  for(qint32 k = 0; k < pick_info.bads.length(); k++)
900  if(pick_info.bads.at(k) == this->cb_item->text())
901  {
902  select_channel_map[channels - 1] = false;
903  this->cb_item->setData(Qt::Unchecked, Qt::CheckStateRole);
904  this->cb_item->setBackground(QColor::fromRgb(0x0F0, 0x080, 0x080, 0x00FF));
905  break;
906  }
907  }
908  this->cb_items.push_back(this->cb_item);
909  this->cb_model->insertRow(channels, this->cb_item);
910  }
911 
912  original_colors = _colors;
913 
914  qint32 size = 0;
915  for(qint32 i = 0; i < original_signal_matrix.cols(); i++)
916  if(select_channel_map[i] == true)
917  size++;
918 
919 
920  _signal_matrix = MatrixXd::Zero(original_signal_matrix.rows(), size);
921  _atom_sum_matrix = MatrixXd::Zero(original_signal_matrix.rows(), size);
922  _residuum_matrix = MatrixXd::Zero(original_signal_matrix.rows(), size);
923 
924  _colors.clear();
925  qint32 selected_chn = 0;
926 
927  for(qint32 channels = 0; channels < original_signal_matrix.cols(); channels++)
928  if(select_channel_map[channels] == true)
929  {
930  _colors.append(original_colors.at(channels));
931  _signal_matrix.col(selected_chn) = original_signal_matrix.col(channels);
932  selected_chn++;
933  }
934  ui->cb_channels->setModel(this->cb_model);
935 }
936 
937 //*************************************************************************************************************************************
938 
939 void MainWindow::cb_selection_changed(const QModelIndex& topLeft, const QModelIndex& bottomRight)
940 {
941  Q_UNUSED(bottomRight);
942 
943  QStandardItem* cb_item = this->cb_items[topLeft.row()];
944  if(topLeft.row() == 0)
945  {
946  if(cb_item->checkState() == Qt::Checked)
947  {
948  for(qint32 i = 1; i < ui->cb_channels->count(); i++)
949  if(this->cb_items[i]->checkState() == Qt::Unchecked)
950  this->cb_items[i]->setData(Qt::Checked, Qt::CheckStateRole);
951  }
952  else
953  {
954  for(qint32 i = 1; i < ui->cb_channels->count(); i++)
955  if(this->cb_items[i]->checkState() == Qt::Checked)
956  this->cb_items[i]->setData(Qt::Unchecked, Qt::CheckStateRole);
957  }
958  return;
959  }
960 
961  ui->tbv_Results->clearContents();
962  ui->tbv_Results->setRowCount(0);
963  ui->actionSpeicher->setEnabled(false);
964  ui->actionSpeicher_unter->setEnabled(false);
965  ui->actionExport->setEnabled(false);
966 
967  if(cb_item->checkState() == Qt::Unchecked)
968  select_channel_map[topLeft.row() - 1] = false;
969  else if(cb_item->checkState() == Qt::Checked)
970  select_channel_map[topLeft.row() - 1] = true;
971 
972  qint32 size = 0;
973  for(qint32 i = 0; i < original_signal_matrix.cols(); i++)
974  if(select_channel_map[i] == true)
975  size++;
976 
977 
978  _signal_matrix = MatrixXd::Zero(original_signal_matrix.rows(), size);
979  _atom_sum_matrix = MatrixXd::Zero(original_signal_matrix.rows(), size);
980  _residuum_matrix = MatrixXd::Zero(original_signal_matrix.rows(), size);
981 
982  _colors.clear();
983  qint32 selected_chn = 0;
984  for(qint32 channels = 0; channels < original_signal_matrix.cols(); channels++)
985  if(select_channel_map[channels] == true)
986  {
987  _colors.append(original_colors.at(channels));
988  _signal_matrix.col(selected_chn) = original_signal_matrix.col(channels);
989  selected_chn++;
990  }
991 
992  if(_signal_matrix.cols() == 0) ui->btt_Calc->setEnabled(false);
993  else ui->btt_Calc->setEnabled(true);
994 
995  _new_paint = true;
996  update();
997 }
998 
999 //*************************************************************************************************************************************
1000 
1001 void GraphWindow::paintEvent(QPaintEvent* event)
1002 {
1003  Q_UNUSED(event);
1004  paint_signal(_signal_matrix, this->size());
1005 }
1006 
1007 //*************************************************************************************************************************************
1008 
1009 void GraphWindow::paint_signal(MatrixXd signalMatrix, QSize windowSize)
1010 {
1011 
1012  QPainter painter(this);
1013  painter.setRenderHint(QPainter::Antialiasing, true);
1014  painter.fillRect(0,0,windowSize.width(),windowSize.height(),QBrush(Qt::white)); // paint window white
1015  painter.drawRect(0,0, windowSize.width(), windowSize.height());
1016 
1017  if(signalMatrix.rows() > 0 && signalMatrix.cols() > 0)
1018  {
1019  const qint32 maxStrLenght = 55; // max lenght in pixel of x-axis string
1020  qint32 borderMarginWidth = 15; // reduce paintspace in GraphWindow of borderMargin pixels
1021  qreal maxPos = 0.0; // highest signalvalue
1022  qreal maxNeg = 0.0; // smalest signalvalue
1023  qreal maxmax = 0.0; // absolute difference maxpos - maxneg
1024  qreal scaleYText = 0.0;
1025  qint32 negScale = 0;
1026 
1027  _border_margin_height = 5 + windowSize.height() / 10; // adapt bordermargin to avoid painting out of range
1028 
1029  if(_new_paint)
1030  {
1031  maxPos = signalMatrix.maxCoeff();
1032  maxNeg = signalMatrix.minCoeff();
1033 
1034  // absolute signalheight
1035  if(maxNeg <= 0) maxmax = maxPos - maxNeg;
1036  else maxmax = maxPos + maxNeg;
1037 
1038  _max_pos = maxPos; // to globe max_pos
1039  _max_neg = maxNeg; // to globe min_pos
1040  _signal_maximum = maxmax; // to globe abs_max
1041  _new_paint = false;
1042  }
1043 
1044  // scale axis text
1045  scaleYText = _signal_maximum / 10.0;
1046 
1047  if(_max_neg < 0) negScale = floor((_max_neg * 10 / _signal_maximum) + 0.5);
1048  if(_max_pos <= 0) negScale = -10;
1049  _signal_negative_scale = negScale; // to globe _signal_negative_scale
1050 
1051  // scale signal
1052  qreal scaleX = (windowSize.width() - maxStrLenght - borderMarginWidth) / qreal(signalMatrix.rows() - 1);
1053  qreal scaleY = (windowSize.height() - _border_margin_height) / _signal_maximum;
1054 
1055  //scale axis
1056  qreal scaleXAchse = (windowSize.width() - maxStrLenght - borderMarginWidth) / 20.0;
1057  qreal scaleYAchse = (windowSize.height() - _border_margin_height) / 10.0;
1058 
1059  for(qint32 i = 0; i < 11; i++)
1060  {
1061  if(negScale == 0) // x-Axis reached (y-value = 0)
1062  {
1063  _x_axis_height = i * scaleYAchse - windowSize.height() + _border_margin_height / 2; // position of x axis in height
1064 
1065  // append scaled signalpoints and paint signal
1066  for(qint32 channel = 0; channel < signalMatrix.cols(); channel++) // over all Channels
1067  {
1068  QPolygonF poly;
1069  for(qint32 h = 0; h < signalMatrix.rows(); h++)
1070  poly.append(QPointF((h * scaleX) + maxStrLenght, -(signalMatrix(h, channel) * scaleY + _x_axis_height)));
1071  QPen pen(_colors.at(channel), 0.5, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin);
1072  painter.setPen(pen);
1073  painter.drawPolyline(poly);
1074  }
1075 
1076  // paint x-axis
1077  for(qint32 j = 1; j < 21; j++)
1078  {
1079  if(fmod(j, 4.0) == 0) //draw light grey sectors
1080  {
1081  QPen pen(Qt::darkGray, 0.5, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin);
1082  painter.setPen(pen);
1083  painter.drawLine(j * scaleXAchse + maxStrLenght, -(_x_axis_height - windowSize.height()),
1084  j * scaleXAchse + maxStrLenght , -(_x_axis_height + windowSize.height())); // scalelines x-axis
1085  }
1086  QPen pen(Qt::black, 1, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin);
1087  painter.setPen(pen);
1088  painter.drawLine(j * scaleXAchse + maxStrLenght, -(_x_axis_height - 2),
1089  j * scaleXAchse + maxStrLenght , -(_x_axis_height + 2)); // scalelines x-axis
1090  }
1091  painter.drawLine(maxStrLenght - 40, -_x_axis_height, windowSize.width()-5, -_x_axis_height); // paint x-axis
1092  }
1093  painter.drawText(3, -(i * scaleYAchse - windowSize.height()) - _border_margin_height / 2 + 4, QString::number(negScale * scaleYText, 'g', 3)); // paint scalevalue y-axis
1094 
1095  painter.drawLine(maxStrLenght - 2, -((i * scaleYAchse)-(windowSize.height()) + _border_margin_height / 2),
1096  maxStrLenght + 2, -((i * scaleYAchse)-(windowSize.height()) + _border_margin_height / 2)); // scalelines y-axis
1097 
1098  negScale++;
1099  }
1100  painter.drawLine(maxStrLenght, 2, maxStrLenght, windowSize.height() - 2); // paint y-axis
1101  }
1102  painter.end();
1103 }
1104 
1105 //*************************************************************************************************************************************
1106 
1107 void AtomSumWindow::paintEvent(QPaintEvent* event)
1108 {
1109  Q_UNUSED(event);
1110  paint_atom_sum(_atom_sum_matrix, this->size(), _signal_maximum, _signal_negative_scale);
1111 }
1112 
1113 //*************************************************************************************************************************************
1114 
1115 void AtomSumWindow::paint_atom_sum(MatrixXd atom_matrix, QSize windowSize, qreal signalMaximum, qreal signalNegativeMaximum)
1116 {
1117  // paint window white
1118  QPainter painter(this);
1119  painter.setRenderHint(QPainter::Antialiasing, true);
1120  painter.fillRect(0,0,windowSize.width(),windowSize.height(),QBrush(Qt::white));
1121  painter.drawRect(0,0, windowSize.width(), windowSize.height());
1122 
1123  // can also checked of zerovector, then you paint no empty axis
1124  if(atom_matrix.rows() > 0 && atom_matrix.cols() > 0 && _signal_matrix.rows() > 0 && _signal_matrix.cols() > 0)
1125  {
1126  const qint32 maxStrLenght = 55;
1127  qint32 borderMarginWidth = 15; // reduce paintspace in GraphWindow of borderMargin pixels
1128 
1129  // scale axis title
1130  qreal scaleYText = signalMaximum / 10.0;
1131 
1132  // scale signal
1133  qreal scaleX = (windowSize.width() - maxStrLenght - borderMarginWidth) / qreal(atom_matrix.rows() - 1);
1134  qreal scaleY = (windowSize.height() - _border_margin_height) / signalMaximum;
1135 
1136  //scale axis
1137  qreal scaleXAchse = (windowSize.width() - maxStrLenght - borderMarginWidth) / 20.0;
1138  qreal scaleYAchse = (windowSize.height() - _border_margin_height) / 10.0;
1139 
1140  for(qint32 i = 0; i < 11; i++)
1141  {
1142  if(signalNegativeMaximum == 0) // x-Axis reached (y-value = 0)
1143  {
1144  // append scaled signalpoints and paint signal
1145  for(qint32 channel = 0; channel < atom_matrix.cols(); channel++) // over all Channels
1146  {
1147  QPolygonF poly;
1148  for(qint32 h = 0; h < atom_matrix.rows(); h++)
1149  poly.append(QPointF((h * scaleX) + maxStrLenght, -(atom_matrix(h, channel) * scaleY + _x_axis_height)));
1150  QPen pen(_colors.at(channel), 0.5, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin);
1151  painter.setPen(pen);
1152  painter.drawPolyline(poly);
1153  }
1154  // paint x-axis
1155  for(qint32 j = 1; j < 21; j++)
1156  {
1157  if(fmod(j, 4.0) == 0) //draw light grey sectors
1158  {
1159  QPen pen(Qt::darkGray, 0.5, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin);
1160  painter.setPen(pen);
1161  painter.drawLine(j * scaleXAchse + maxStrLenght, -(_x_axis_height - windowSize.height()),
1162  j * scaleXAchse + maxStrLenght, -(_x_axis_height + windowSize.height())); // scalelines x-axis
1163  }
1164  QPen pen(Qt::black, 1, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin);
1165  painter.setPen(pen);
1166  painter.drawLine(j * scaleXAchse + maxStrLenght, -(_x_axis_height - 2),
1167  j * scaleXAchse + maxStrLenght, -(_x_axis_height + 2)); // scalelines x-axis
1168  }
1169  painter.drawLine(maxStrLenght - 40, -_x_axis_height, windowSize.width()-5, -_x_axis_height); // paint x-axis
1170  }
1171 
1172  painter.drawText(3, -(i * scaleYAchse - windowSize.height()) - _border_margin_height / 2 + 4, QString::number(signalNegativeMaximum * scaleYText, 'g', 3)); // paint scalvalue Y-axis
1173  painter.drawLine(maxStrLenght - 2, -((i * scaleYAchse)-(windowSize.height()) + _border_margin_height / 2),
1174  maxStrLenght + 2, -((i * scaleYAchse)-(windowSize.height()) + _border_margin_height / 2)); // scalelines y-axis
1175 
1176  signalNegativeMaximum++;
1177  }
1178  painter.drawLine(maxStrLenght, 2, maxStrLenght, windowSize.height() - 2); // paint y-axis
1179  }
1180  painter.end();
1181 }
1182 
1183 //*************************************************************************************************************************************
1184 
1185 void ResiduumWindow::paintEvent(QPaintEvent* event)
1186 {
1187  Q_UNUSED(event);
1188  paint_residuum(_residuum_matrix, this->size(), _signal_maximum, _signal_negative_scale);
1189 }
1190 
1191 //*************************************************************************************************************************************
1192 
1193 void ResiduumWindow::paint_residuum(MatrixXd residuum_matrix, QSize windowSize, qreal signalMaximum, qreal signalNegativeMaximum)
1194 {
1195  // paint window white
1196  QPainter painter(this);
1197  painter.setRenderHint(QPainter::Antialiasing, true);
1198  painter.fillRect(0,0,windowSize.width(),windowSize.height(),QBrush(Qt::white));
1199  painter.drawRect(0,0, windowSize.width(), windowSize.height());
1200 
1201  if(residuum_matrix.rows() > 0 && residuum_matrix.cols() > 0 && _signal_matrix.rows() > 0 && _signal_matrix.cols() > 0)
1202  {
1203  const qint32 maxStrLenght = 55;
1204  qint32 borderMarginWidth = 15; // reduce paintspace in GraphWindow of borderMargin pixels
1205 
1206  // scale axis title
1207  qreal scaleYText = signalMaximum / 10.0;
1208 
1209  // scale signal
1210  qreal scaleX = (windowSize.width() - maxStrLenght - borderMarginWidth) / qreal(residuum_matrix.rows() - 1);
1211  qreal scaleY = (windowSize.height() - _border_margin_height) / signalMaximum;
1212 
1213  //scale axis
1214  qreal scaleXAchse = (windowSize.width() - maxStrLenght - borderMarginWidth) / 20.0;
1215  qreal scaleYAchse = (windowSize.height() - _border_margin_height) / 10.0;
1216 
1217  for(qint32 i = 0; i < 11; i++)
1218  {
1219  if(signalNegativeMaximum == 0) // x-axis reached (y-value = 0)
1220  {
1221  // append scaled signalpoints and paint signal
1222  for(qint32 channel = 0; channel < residuum_matrix.cols(); channel++) // over all Channels
1223  {
1224  QPolygonF poly;
1225  for(qint32 h = 0; h < residuum_matrix.rows(); h++)
1226  poly.append(QPointF(h * scaleX + maxStrLenght, - (residuum_matrix(h, channel) * scaleY + _x_axis_height)));
1227  QPen pen(_colors.at(channel), 0.5, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin);
1228  painter.setPen(pen);
1229  painter.drawPolyline(poly);
1230  }
1231  // paint x-axis
1232  for(qint32 j = 1; j < 21; j++)
1233  {
1234  if(fmod(j, 4.0) == 0) //draw light grey sectors
1235  {
1236  QPen pen(Qt::darkGray, 0.5, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin);
1237  painter.setPen(pen);
1238  painter.drawLine(j * scaleXAchse + maxStrLenght, -(_x_axis_height - windowSize.height()),
1239  j * scaleXAchse + maxStrLenght, -(_x_axis_height + windowSize.height())); // scalelines x-axis
1240  }
1241  QPen pen(Qt::black, 1, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin);
1242  painter.setPen(pen);
1243  painter.drawLine(j * scaleXAchse + maxStrLenght, -(_x_axis_height - 2),
1244  j * scaleXAchse + maxStrLenght, -(_x_axis_height + 2)); // scalelines x-axis
1245  }
1246  painter.drawLine(maxStrLenght - 40, -_x_axis_height, windowSize.width()-5, -_x_axis_height); // paint x-axis
1247  }
1248 
1249  painter.drawText(3, -(i * scaleYAchse - windowSize.height()) - _border_margin_height/2 + 4, QString::number(signalNegativeMaximum * scaleYText, 'g', 3)); // paint scalevalue y-axis
1250  painter.drawLine(maxStrLenght - 2, -((i * scaleYAchse)-(windowSize.height()) + _border_margin_height / 2),
1251  maxStrLenght + 2, -((i * scaleYAchse)-(windowSize.height()) + _border_margin_height / 2)); // scalelines y-axis
1252 
1253  signalNegativeMaximum++;
1254  }
1255 
1256  painter.drawLine(maxStrLenght, 2, maxStrLenght, windowSize.height() - 2); // paint y-axis
1257  }
1258  painter.end();
1259 }
1260 
1261 //*************************************************************************************************************************************
1262 
1263 void XAxisWindow::paintEvent(QPaintEvent* event)
1264 {
1265  Q_UNUSED(event);
1266  paint_axis(_signal_matrix, this->size());
1267 }
1268 
1269 //*************************************************************************************************************************************
1270 
1271 void XAxisWindow::paint_axis(MatrixXd signalMatrix, QSize windowSize)
1272 {
1273  QPainter painter(this);
1274  painter.setRenderHint(QPainter::Antialiasing, true);
1275 
1276  if(signalMatrix.rows() > 0 && signalMatrix.cols() > 0)
1277  {
1278  const qint32 maxStrLenght = 55;
1279  qint32 borderMarginWidth = 15;
1280  qreal scaleXText = (signalMatrix.rows() - 1) / _sample_rate / 20.0; // divide signallength
1281  qreal scaleXAchse = (windowSize.width() - maxStrLenght - borderMarginWidth) / 20.0;
1282 
1283  for(qint32 j = 0; j < 21; j++)
1284  {
1285  if(j == 20)
1286  {
1287  painter.drawText(j * scaleXAchse + 37, 20, QString::number(j * scaleXText + _from / _sample_rate + _offset_time, 'f', 2)); // scalevalue as string
1288  painter.drawLine(j * scaleXAchse + maxStrLenght, 5 + 2,
1289  j * scaleXAchse + maxStrLenght, 5 - 2); // scalelines
1290  }
1291  else
1292  {
1293  painter.drawText(j * scaleXAchse + 45, 20, QString::number(j * scaleXText + _from / _sample_rate + _offset_time, 'f', 2)); // scalevalue as string
1294  painter.drawLine(j * scaleXAchse + maxStrLenght, 5 + 2,
1295  j * scaleXAchse + maxStrLenght, 5 - 2); // scalelines
1296  }
1297  }
1298  painter.drawText(5 , 20, "[sec]"); // unit
1299  painter.drawLine(5, 5, windowSize.width()-5, 5); // paint y-line
1300  }
1301 }
1302 
1303 //*************************************************************************************************************************************
1304 
1305 // starts MP-algorithm
1306 void MainWindow::on_btt_Calc_clicked()
1307 {
1308  truncation_criterion criterion;
1309 
1310  if(ui->chb_Iterations->isChecked() && !ui->chb_ResEnergy->isChecked())
1311  criterion = Iterations;
1312  if(ui->chb_Iterations->isChecked() && ui->chb_ResEnergy->isChecked())
1313  criterion = Both;
1314  if(ui->chb_ResEnergy->isChecked() && !ui->chb_Iterations->isChecked())
1315  criterion = SignalEnergy;
1316 
1317  if(ui->btt_Calc->text()== "calculate")
1318  {
1319  ui->progressBarCalc->setValue(0);
1320  ui->progressBarCalc->setHidden(false);
1321 
1322  if(ui->chb_Iterations->checkState() == Qt::Unchecked && ui->chb_ResEnergy->checkState() == Qt::Unchecked)
1323  {
1324  QMessageBox msgBox(QMessageBox::Warning, "Error", "No truncation criterion choosen.", QMessageBox::Ok, this);
1325  msgBox.exec();
1326  return;
1327  }
1328 
1329  if(((ui->dsb_energy->value() <= 1 && ui->dsb_energy->isEnabled()) && (ui->sb_Iterations->value() >= 500 && ui->sb_Iterations->isEnabled()))
1330  || (ui->dsb_energy->value() <= 1 && ui->dsb_energy->isEnabled() && !ui->sb_Iterations->isEnabled())
1331  || (ui->sb_Iterations->value() >= 500 && ui->sb_Iterations->isEnabled() && !ui->dsb_energy->isEnabled()) )
1332  {
1333  QSettings settings;
1334  if(settings.value("show_warnings", true).toBool())
1335  {
1337  msgBox->setModal(true);
1338  msgBox->exec();
1339  msgBox->close();
1340  }
1341  }
1342 
1343  ui->gb_trunc->setEnabled(false);
1344  ui->btt_OpenSignal->setEnabled(false);
1345  ui->btt_Calc->setText("cancel");
1346  ui->cb_channels->setEnabled(false);
1347  ui->cb_all_select->setEnabled(false);
1348  ui->dsb_from->setEnabled(false);
1349  ui->dsb_to->setEnabled(false);
1350  ui->sb_sample_count ->setEnabled(false);
1351  ui->tbv_Results->clearContents();
1352  ui->tbv_Results->setRowCount(0);
1353  ui->cb_all_select->setHidden(false);
1354  ui->lb_timer->setHidden(false);
1355  ui->actionExport->setEnabled(false);
1356  ui->lb_figure_of_merit->setHidden(true);
1357  ui->lb_info_content->clear();
1358 
1359  _adaptive_atom_list.clear();
1360  _fix_dict_atom_list.clear();
1361 
1362  //reset progressbar text color to black, reset infos
1363  pal.setColor(QPalette::Text, Qt::black);
1364  ui->progressBarCalc->setPalette(pal);
1365  ui->progressBarCalc->setFormat("residual energy: 100% iterations: 0");
1366 
1367  ui->lb_signal_energy->setHidden(true);
1368  ui->lb_signal_energy_text->setHidden(true);
1369  ui->lb_approx_energy->setHidden(true);
1370  ui->lb_approx_energy_text->setHidden(true);
1371  ui->lb_residual_energy->setHidden(true);
1372  ui->lb_residual_energy_text->setHidden(true);
1373 
1374  is_white = false;
1375 
1376  is_saved = false;
1377  has_warning = false;
1378 
1379  _residuum_matrix = _signal_matrix;
1380  _atom_sum_matrix = MatrixXd::Zero(_signal_matrix.rows(), _signal_matrix.cols());
1381  callAtomSumWindow->update();
1382  callResidumWindow->update();
1383 
1384  recieved_result_counter = 0;
1385  counter_time.start();
1386  _counter_timer->setInterval(100);
1387  _counter_timer->start();
1388 
1389  if(ui->rb_OwnDictionary->isChecked())
1390  {
1391  ui->tbv_Results->setColumnCount(2);
1392  ui->tbv_Results->setHorizontalHeaderLabels(QString("energy\n[%];atom").split(";"));
1393  ui->tbv_Results->setColumnWidth(0,55);
1394  ui->tbv_Results->setColumnWidth(1,280);
1395  max_tbv_header_width = 0;
1396  calc_fix_mp(QString(QDir::homePath() + "/" + "Matching-Pursuit-Toolbox/%1.dict").arg(ui->cb_Dicts->currentText()), _signal_matrix, criterion);
1397  }
1398  else if(ui->rb_adativMp->isChecked())
1399  {
1400  QList<qint32> sizes = ui->splitter->sizes();
1401  sizes.insert(0, 240);
1402  ui->splitter->setSizes(sizes);
1403  max_tbv_header_width = 150;
1404 
1405  ui->tbv_Results->setColumnCount(5);
1406  ui->tbv_Results->setHorizontalHeaderLabels(QString("energy\n[%];scale\n[sec];trans\n[sec];modu\n[Hz];phase\n[rad]").split(";"));
1407  ui->tbv_Results->setColumnWidth(0,55);
1408  ui->tbv_Results->setColumnWidth(1,45);
1409  ui->tbv_Results->setColumnWidth(2,40);
1410  ui->tbv_Results->setColumnWidth(3,40);
1411  ui->tbv_Results->setColumnWidth(4,50);
1412 
1413  calc_adaptiv_mp(_signal_matrix, criterion);
1414  }
1415  is_calulating = true;
1416  }
1417  //cancel calculation thread
1418  else if(ui->btt_Calc->text() == "cancel")
1419  {
1420  emit mp_Thread->requestInterruption();
1421  ui->btt_Calc->setText("wait...");
1422  }
1423 }
1424 
1425 //*************************************************************************************************************
1426 
1427 void MainWindow::on_time_out()
1428 {
1429  QTime diff_time(0,0);
1430  diff_time = diff_time.addMSecs(counter_time.elapsed());
1431  ui->lb_timer->setText(diff_time.toString("hh:mm:ss.zzz"));
1432  _counter_timer->start();
1433 }
1434 
1435 //*************************************************************************************************************
1436 void MainWindow::recieve_result(qint32 current_iteration, qint32 max_iterations, qreal current_energy, qreal max_energy, MatrixXd residuum,
1437  adaptive_atom_list adaptive_atom_res_list, fix_dict_atom_list fix_dict_atom_res_list)
1438 {
1439  tbv_is_loading = true;
1440 
1441  QSettings settings;
1442  qreal percent = ui->dsb_energy->value();
1443  residuum_energy = 100 * (max_energy - current_energy) / max_energy;
1444  signal_energy = max_energy;
1445 
1446  //current atoms list update
1447  if(fix_dict_atom_res_list.isEmpty())
1448  {
1449  GaborAtom temp_atom = adaptive_atom_res_list.last().last();
1450  QList<GaborAtom> temp_channel_list= adaptive_atom_res_list.last();
1451  qreal atom_energy = 0;
1452 
1453  for(qint32 i = 0; i < adaptive_atom_res_list.last().length(); i++)
1454  {
1455  atom_energy += adaptive_atom_res_list.last().at(i).energy;
1456  }
1457 
1458 
1459  qreal phase = temp_atom.phase;
1460  if(temp_atom.phase > 2*PI) phase -= 2*PI;
1461 
1462  QTableWidgetItem* atomEnergieItem = new QTableWidgetItem(QString::number(100 * atom_energy / max_energy, 'f', 2));
1463  QTableWidgetItem* atomScaleItem = new QTableWidgetItem(QString::number(temp_atom.scale / _sample_rate, 'g', 3));
1464  QTableWidgetItem* atomTranslationItem = new QTableWidgetItem(QString::number(temp_atom.translation / qreal(_sample_rate) + _from / _sample_rate + _offset_time, 'g', 4));
1465  QTableWidgetItem* atomModulationItem = new QTableWidgetItem(QString::number(temp_atom.modulation * _sample_rate / temp_atom.sample_count, 'g', 3));
1466  QTableWidgetItem* atomPhaseItem = new QTableWidgetItem(QString::number(phase, 'g', 3));
1467 
1468  atomEnergieItem->setFlags(Qt::ItemIsUserCheckable);
1469  atomScaleItem->setFlags(Qt::NoItemFlags);
1470  atomTranslationItem->setFlags(Qt::NoItemFlags);
1471  atomModulationItem->setFlags(Qt::NoItemFlags);
1472  atomPhaseItem->setFlags(Qt::NoItemFlags);
1473  atomEnergieItem->setCheckState(Qt::Checked);
1474 
1475  atomEnergieItem->setTextAlignment(0x0082);
1476  atomScaleItem->setTextAlignment(0x0082);
1477  atomTranslationItem->setTextAlignment(0x0082);
1478  atomModulationItem->setTextAlignment(0x0082);
1479  atomPhaseItem->setTextAlignment(0x0082);
1480 
1481  //_adaptive_atom_list.append(temp_atom); //old
1482  _adaptive_atom_list.append(adaptive_atom_res_list.last());
1483 
1484  //ToDo: sort_results for trial_separation
1485  if(settings.value("sort_results", true).toBool())// && !settings.value("trial_separation", false).toBool())
1486  {
1487  qSort(adaptive_atom_res_list.begin(), adaptive_atom_res_list.end(), sort_energy_adaptive);
1488  qSort(_adaptive_atom_list.begin(), _adaptive_atom_list.end(), sort_energy_adaptive);
1489  }
1490 
1491  // ToDo: qint32 index = adaptive_atom_res_list.indexOf(temp_atom);
1492  qint32 index = 0;
1493  while(index < _adaptive_atom_list.length())
1494  {
1495  if(temp_atom.scale == _adaptive_atom_list.at(index).last().scale
1496  && temp_atom.modulation == _adaptive_atom_list.at(index).last().modulation
1497  && temp_atom.translation == _adaptive_atom_list.at(index).last().translation
1498  && temp_atom.energy == _adaptive_atom_list.at(index).last().energy)
1499  break;
1500  index++;
1501  }
1502 
1503  ui->tbv_Results->insertRow(index);
1504  ui->tbv_Results->setItem(index, 0, atomEnergieItem);
1505  ui->tbv_Results->setItem(index, 1, atomScaleItem);
1506  ui->tbv_Results->setItem(index, 2, atomTranslationItem);
1507  ui->tbv_Results->setItem(index, 3, atomModulationItem);
1508  ui->tbv_Results->setItem(index, 4, atomPhaseItem);
1509 
1510  //update residuum and atom sum for painting and later save to hdd
1511  for(qint32 i = 0; i < _signal_matrix.cols(); i++)
1512  {
1513  if(settings.value("trial_separation", false).toBool())
1514  {
1515  VectorXd atom_vec = temp_channel_list.at(i).max_scalar_product * temp_atom.create_real(temp_channel_list.at(i).sample_count,
1516  temp_channel_list.at(i).scale,
1517  temp_channel_list.at(i).translation,
1518  temp_channel_list.at(i).modulation,
1519  temp_channel_list.at(i).phase);
1520  _residuum_matrix.col(i) -= atom_vec;
1521  _atom_sum_matrix.col(i) += atom_vec;
1522  //_residuum_matrix = residuum;
1523  }
1524  else
1525  {
1526  VectorXd atom_vec = temp_atom.max_scalar_list.at(i) * temp_atom.create_real(temp_atom.sample_count, temp_atom.scale, temp_atom.translation, temp_atom.modulation, temp_atom.phase_list.at(i));
1527  _residuum_matrix.col(i) -= atom_vec;
1528  _atom_sum_matrix.col(i) += atom_vec;
1529  }
1530  }
1531  }
1532  else if(adaptive_atom_res_list.isEmpty())
1533  {
1534  FixDictAtom temp_atom = fix_dict_atom_res_list.last();
1535  fix_dict_atom_res_list.last().display_text = create_display_text(fix_dict_atom_res_list.last());
1536  temp_atom.display_text = create_display_text(fix_dict_atom_res_list.last());
1537 
1538  QFont font;
1539  QFontMetrics fm(font);
1540  qint32 header_width = fm.width(fix_dict_atom_res_list.last().display_text) + 35;
1541  if(header_width > max_tbv_header_width)
1542  {
1543  ui->tbv_Results->setColumnWidth(1, header_width);
1544  max_tbv_header_width = header_width;
1545  }
1546 
1547  QTableWidgetItem* atom_energie_item = new QTableWidgetItem(QString::number(100 * temp_atom.energy / max_energy, 'f', 2));
1548  QTableWidgetItem* atom_name_item = new QTableWidgetItem(temp_atom.display_text);
1549 
1550  atom_energie_item->setFlags(Qt::ItemIsUserCheckable);
1551  atom_name_item->setFlags(Qt::NoItemFlags);
1552  atom_energie_item->setCheckState(Qt::Checked);
1553 
1554  atom_energie_item->setTextAlignment(0x0082);
1555  atom_name_item->setTextAlignment(0x0081);
1556 
1557  _fix_dict_atom_list.append(temp_atom);
1558  if(settings.value("sort_results", true).toBool())
1559  {
1560  qSort(fix_dict_atom_res_list.begin(),fix_dict_atom_res_list.end(), sort_energy_fix);
1561  qSort(_fix_dict_atom_list.begin(),_fix_dict_atom_list.end(), sort_energy_fix);
1562  }
1563  // ToDo: index = _adaptive_atom_list.indexOf(temp_atom);
1564  qint32 index = 0;
1565  while(index < fix_dict_atom_res_list.length())
1566  {
1567  if(temp_atom.display_text == fix_dict_atom_res_list.at(index).display_text)
1568  break;
1569  index++;
1570  }
1571  ui->tbv_Results->insertRow(index);
1572  ui->tbv_Results->setItem(index, 0, atom_energie_item);
1573  ui->tbv_Results->setItem(index, 1, atom_name_item);
1574 
1575  //update residuum and atom sum for painting and later save to hdd
1576 
1577  for(qint32 i = 0; i < _signal_matrix.cols(); i++)
1578  {
1579  _residuum_matrix.col(i) -= temp_atom.max_scalar_list.at(i) * temp_atom.atom_samples;
1580  _atom_sum_matrix.col(i) += temp_atom.max_scalar_list.at(i) * temp_atom.atom_samples;
1581  }/*
1582  _residuum_matrix = residuum;
1583  _atom_sum_matrix = _signal_matrix - residuum;
1584  */}
1585 
1586  //progressbar update remaining energy and iterations update
1587 
1588  QString text = QString("residual energy: %0% iterations: %1").arg(QString::number(residuum_energy, 'f', 2)).arg(current_iteration);
1589  ui->progressBarCalc->setFormat(text);
1590  qint32 prgrsbar_adapt = 99;
1591  if(max_iterations > 1999 && current_iteration < 100)
1592  ui->progressBarCalc->setMaximum(100);
1593  if(ui->chb_ResEnergy->isChecked() && (current_iteration >= (prgrsbar_adapt)) && (max_energy - current_energy) > (0.01 * percent * max_energy))
1594  ui->progressBarCalc->setMaximum(current_iteration + 5);
1595  if(max_iterations < 1999) ui->progressBarCalc->setMaximum(max_iterations);
1596  ui->progressBarCalc->setValue(current_iteration);
1597 
1598  if(((current_iteration == max_iterations) || (max_energy - current_energy) < (0.01 * percent * max_energy))&&ui->chb_ResEnergy->isChecked())
1599  ui->progressBarCalc->setValue(ui->progressBarCalc->maximum());
1600 
1601  if(ui->progressBarCalc->value() > ui->progressBarCalc->maximum() / 2 && !is_white)
1602  {
1603  pal.setColor(QPalette::Text, Qt::white);
1604  ui->progressBarCalc->setPalette(pal);
1605  is_white = true;
1606  }
1607 
1608  // update ui
1609  if(max_iterations > 10 && percent < 1 && _signal_matrix.cols() > 40 && recieved_result_counter % 10 == 0)
1610  {
1611  callAtomSumWindow->update();
1612  callResidumWindow->update();
1613  }
1614  else if(max_iterations > 5 && percent < 5 && _signal_matrix.cols() > 20 && recieved_result_counter % 5 == 0)
1615  {
1616  callAtomSumWindow->update();
1617  callResidumWindow->update();
1618  }
1619  else if(_signal_matrix.cols() < 20)
1620  {
1621  callAtomSumWindow->update();
1622  callResidumWindow->update();
1623  }
1624 
1625  tbv_is_loading = false;
1626  recieved_result_counter++;
1627 }
1628 
1629 //*************************************************************************************************************
1630 
1631 void MainWindow::recieve_warnings(qint32 warning_number)
1632 {
1633  QSettings settings;
1634 
1635  if(settings.value("show_infos", true).toBool())
1636  {
1637  ui->lb_info_content->setHidden(false);
1638  ui->lb_info->setHidden(false);
1639 
1640  QString text;
1641  if(warning_number == 1 && !has_warning)
1642  {
1643  text = "The dictionary does not have the appropriate atoms to approximate the signal more closely. Calculation terminated before reaching truncation criterion. ";
1644  ui->lb_info_content->setText(text);
1645  has_warning = true;
1646  }
1647  else if(warning_number == 2 && !has_warning)
1648  {
1649  text = "No matching sample count between atoms and signal. This may lead to discontinuities. ";
1650  ui->lb_info_content->setText(text);
1651  has_warning = true;
1652  }
1653  else if(has_warning && warning_number != 10)
1654  {
1655  text = "This dictionary does not fit the signals sample count (leads to discontinuities) and excludes atoms to reduce further residual energy. Calculation terminated before reaching truncation criterion. ";
1656  ui->lb_info_content->setText(text);
1657  }
1658  if(warning_number == 10)
1659  {
1660  text = ui->lb_info_content->text();
1661  text.append("Algorithm canceled by user interaction.");
1662  ui->lb_info_content->setText(text);
1663  }
1664  if(warning_number == 11)
1665  {
1666  text = QString("Simplex Iteration limit of %1 achieved, result may not be optimal. ").arg(settings.value("adaptive_iterations").toInt());
1667  ui->lb_info_content->setText(text);
1668  }
1669 
1670  }
1671 }
1672 
1673 //*************************************************************************************************************
1674 
1675 void MainWindow::tbv_selection_changed(const QModelIndex& topLeft, const QModelIndex& bottomRight)
1676 {
1677  Q_UNUSED(bottomRight);
1678  bool all_selected = true;
1679  bool all_deselected = true;
1680  QSettings settings;
1681 
1682  if(tbv_is_loading) return;
1683 
1684  for(qint32 i = 0; i < ui->tbv_Results->rowCount() - 1; i++) // last item is residuum
1685  if(ui->tbv_Results->item(i, 0)->checkState()) all_deselected = false;
1686  else all_selected = false;
1687 
1688  if(all_selected) ui->cb_all_select->setCheckState(Qt::Checked);
1689  else if(all_deselected) ui->cb_all_select->setCheckState(Qt::Unchecked);
1690  else ui->cb_all_select->setCheckState(Qt::PartiallyChecked);
1691 
1692  QTableWidgetItem* item = ui->tbv_Results->item(topLeft.row(), 0);
1693  if(topLeft.row() == ui->tbv_Results->rowCount() - 1)
1694  {
1695  if(item->checkState())
1696  {
1697  for(qint32 channels = 0; channels < _signal_matrix.cols(); channels++)
1698  {
1699  _atom_sum_matrix.col(channels) += real_residuum_matrix.col(channels);
1700  _residuum_matrix.col(channels) -= real_residuum_matrix.col(channels);
1701  }
1702  composed_energy += residuum_energy;
1703  }
1704  else
1705  {
1706  for(qint32 channels = 0; channels < _signal_matrix.cols(); channels++)
1707  {
1708  _atom_sum_matrix.col(channels) -= real_residuum_matrix.col(channels);
1709  _residuum_matrix.col(channels) += real_residuum_matrix.col(channels);
1710  }
1711  composed_energy -= residuum_energy;
1712  }
1713  }
1714  else
1715  {
1716  if(ui->tbv_Results->columnCount() > 2)
1717  {
1718  if(!settings.value("trial_separation", false).toBool())//normal adaptive mp with global bestmatching atom
1719  {
1720  GaborAtom atom = _adaptive_atom_list.at(topLeft.row()).last();
1721  if(!auto_change)
1722  select_atoms_map[topLeft.row()] = item->checkState();
1723 
1724  if(item->checkState())
1725  {
1726  for(qint32 channels = 0; channels < _signal_matrix.cols(); channels++)
1727  {
1728  _atom_sum_matrix.col(channels) += atom.max_scalar_list.at(channels) * atom.create_real(atom.sample_count, atom.scale, atom.translation, atom.modulation, atom.phase_list.at(channels));
1729  _residuum_matrix.col(channels) -= atom.max_scalar_list.at(channels) * atom.create_real(atom.sample_count, atom.scale, atom.translation, atom.modulation, atom.phase_list.at(channels));
1730  }
1731  composed_energy += 100 * atom.energy / signal_energy;
1732  }
1733  else
1734  {
1735  for(qint32 channels = 0; channels < _signal_matrix.cols(); channels++)
1736  {
1737  _atom_sum_matrix.col(channels) -= atom.max_scalar_list.at(channels) * atom.create_real(atom.sample_count, atom.scale, atom.translation, atom.modulation, atom.phase_list.at(channels));
1738  _residuum_matrix.col(channels) += atom.max_scalar_list.at(channels) * atom.create_real(atom.sample_count, atom.scale, atom.translation, atom.modulation, atom.phase_list.at(channels));
1739  }
1740  composed_energy -= 100 * atom.energy / signal_energy;
1741  }
1742  }
1743  else //trial separation
1744  {
1745  if(item->checkState())
1746  {
1747  for(qint32 channels = 0; channels < _signal_matrix.cols(); channels++)
1748  {
1749  GaborAtom atom = _adaptive_atom_list.at(topLeft.row()).at(channels);
1750  _atom_sum_matrix.col(channels) += atom.max_scalar_product * atom.create_real(atom.sample_count, atom.scale, atom.translation, atom.modulation, atom.phase);
1751  _residuum_matrix.col(channels) -= atom.max_scalar_product * atom.create_real(atom.sample_count, atom.scale, atom.translation, atom.modulation, atom.phase);
1752  composed_energy += 100 * atom.energy / signal_energy;
1753  }
1754  }
1755  else
1756  {
1757  for(qint32 channels = 0; channels < _signal_matrix.cols(); channels++)
1758  {
1759  GaborAtom atom = _adaptive_atom_list.at(topLeft.row()).at(channels);
1760  _atom_sum_matrix.col(channels) -= atom.max_scalar_product * atom.create_real(atom.sample_count, atom.scale, atom.translation, atom.modulation, atom.phase);
1761  _residuum_matrix.col(channels) += atom.max_scalar_product * atom.create_real(atom.sample_count, atom.scale, atom.translation, atom.modulation, atom.phase);
1762  composed_energy -= 100 * atom.energy / signal_energy;
1763  }
1764  }
1765 
1766  }
1767  }
1768  else
1769  {
1770  FixDictAtom atom = _fix_dict_atom_list.at(topLeft.row());
1771  if(!auto_change)
1772  select_atoms_map[topLeft.row()] = item->checkState();
1773 
1774  if(item->checkState())
1775  {
1776  for(qint32 channels = 0; channels < _signal_matrix.cols(); channels++)
1777  {
1778  _atom_sum_matrix.col(channels) += atom.max_scalar_list.at(channels) * atom.atom_samples;
1779  _residuum_matrix.col(channels) -= atom.max_scalar_list.at(channels) * atom.atom_samples;
1780  composed_energy += 100 * atom.energy / signal_energy;
1781  }
1782  }
1783  else
1784  {
1785  for(qint32 channels = 0; channels < _signal_matrix.cols(); channels++)
1786  {
1787  _atom_sum_matrix.col(channels) -= atom.max_scalar_list.at(channels) * atom.atom_samples;
1788  _residuum_matrix.col(channels) += atom.max_scalar_list.at(channels) * atom.atom_samples;
1789  composed_energy -= 100 * atom.energy / signal_energy;
1790  }
1791  }
1792  }
1793  }
1794 
1795  ui->lb_signal_energy_text->setText("absolute signal energy:");
1796  ui->lb_signal_energy->setText(QString::number(signal_energy, 'g', 2));
1797  ui->lb_approx_energy_text->setText("approximation energy:");
1798  ui->lb_approx_energy->setText(QString::number(abs(composed_energy), 'f', 2) + "%");
1799  ui->lb_residual_energy_text->setText("remaining residual energy:");
1800  ui->lb_residual_energy->setText(QString::number(abs(100 - composed_energy), 'f', 2) + "%");
1801 
1802  callAtomSumWindow->update();
1803  callResidumWindow->update();
1804 }
1805 
1806 //*************************************************************************************************************
1807 
1808 void MainWindow::calc_thread_finished()
1809 {
1810  is_calulating = false;
1811  tbv_is_loading = true;
1812 
1813  if(_fix_dict_atom_list.isEmpty() && !_adaptive_atom_list.isEmpty())
1814  ui->actionExport->setEnabled(true);
1815 
1816  ui->actionSpeicher->setEnabled(true);
1817  ui->actionSpeicher_unter->setEnabled(true);
1818 
1819 
1820  _counter_timer->stop();
1821  ui->gb_trunc->setEnabled(true);
1822  ui->btt_OpenSignal->setEnabled(true);
1823  ui->progressBarCalc->setValue(ui->progressBarCalc->maximum());
1824 
1825  pal.setColor(QPalette::Text, Qt::white);
1826  ui->progressBarCalc->setPalette(pal);
1827  is_white = true;
1828 
1829  ui->btt_Calc->setText("calculate");
1830  ui->cb_channels->setEnabled(true);
1831  ui->cb_all_select->setEnabled(true);
1832  ui->dsb_from->setEnabled(true);
1833  ui->dsb_to->setEnabled(true);
1834  ui->sb_sample_count ->setEnabled(true);
1835 
1836  QList<qint32> sizes = ui->splitter->sizes();
1837  sizes.insert(0, max_tbv_header_width + 100);
1838  ui->splitter->setSizes(sizes);
1839 
1840  for(qint32 col = 0; col < ui->tbv_Results->columnCount(); col++)
1841  for(qint32 row = 0; row < ui->tbv_Results->rowCount(); row++)
1842  {
1843  if(col == 0)
1844  ui->tbv_Results->item(row, col)->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
1845  else
1846  ui->tbv_Results->item(row, col)->setFlags(Qt::ItemIsEnabled);
1847  }
1848 
1849  real_residuum_matrix = _residuum_matrix;
1850 
1851  for(qint32 i = 0; i < ui->tbv_Results->rowCount(); i++)
1852  select_atoms_map.insert(i, true);
1853 
1854  ui->tbv_Results->setRowCount(ui->tbv_Results->rowCount() + 1);
1855 
1856  QTableWidgetItem* energy_item = new QTableWidgetItem(QString::number(residuum_energy, 'f', 2));//ui->lb_RestEnergieResiduumValue->text().remove('%'));
1857  energy_item->setFlags(Qt::ItemIsUserCheckable | Qt::ItemIsEnabled);
1858  energy_item->setCheckState(Qt::Unchecked);
1859  energy_item->setTextAlignment(0x0082);
1860 
1861  QTableWidgetItem* residuum_item = new QTableWidgetItem("residue");
1862  residuum_item->setFlags(Qt::ItemIsEnabled);
1863  residuum_item->setTextAlignment(Qt::AlignCenter);
1864 
1865  ui->tbv_Results->setItem(ui->tbv_Results->rowCount() - 1, 0, energy_item);
1866  ui->tbv_Results->setItem(ui->tbv_Results->rowCount() - 1, 1, residuum_item);
1867  ui->tbv_Results->setSpan(ui->tbv_Results->rowCount() - 1, 1, 1, 4);
1868 
1869  //calc energy infos
1870  composed_energy = 100 - residuum_energy;
1871  ui->lb_signal_energy_text->setText("absolute signal energy:");
1872  ui->lb_signal_energy->setText(QString::number(signal_energy, 'g', 2));
1873  ui->lb_approx_energy_text->setText("approximation energy:");
1874  ui->lb_approx_energy->setText(QString::number(abs(composed_energy), 'f', 2) + "%");
1875  ui->lb_residual_energy_text->setText("remaining residual energy:");
1876  ui->lb_residual_energy->setText(QString::number(abs(100 - composed_energy), 'f', 2) + "%");
1877  //show energy infos
1878  ui->lb_signal_energy->setHidden(false);
1879  ui->lb_signal_energy_text->setHidden(false);
1880  ui->lb_approx_energy->setHidden(false);
1881  ui->lb_approx_energy_text->setHidden(false);
1882  ui->lb_residual_energy->setHidden(false);
1883  ui->lb_residual_energy_text->setHidden(false);
1884 
1885  //figure of merit to evaluate the alogorithm, here we use correlation between signal and atom_sum_matrix
1886  QSettings settings;
1887  if(settings.value("show_infos", true).toBool())
1888  {
1889  qreal correlation = 0;
1890  qreal divisor_sig = 0;
1891  qreal divisor_app = 0;
1892  MatrixXd sig_no_mean = (_signal_matrix.array() - _signal_matrix.mean()).matrix();
1893  MatrixXd app_no_mean = (_atom_sum_matrix.array() - _atom_sum_matrix.mean()).matrix();
1894  for(qint32 channel = 0; channel < _atom_sum_matrix.cols(); channel++)
1895  {
1896  correlation += sig_no_mean.col(channel).dot(app_no_mean.col(channel));
1897  divisor_sig += sig_no_mean.col(channel).dot(sig_no_mean.col(channel));
1898  divisor_app += app_no_mean.col(channel).dot(app_no_mean.col(channel));
1899  }
1900 
1901  qreal divisor = sqrt(divisor_app * divisor_sig);
1902  correlation /= divisor;
1903  correlation *= 1000;
1904  qint32 corr = correlation;
1905  correlation = qreal(corr) / 1000;
1906  cout << "\ncorrelation: "<<correlation;
1907  ui->lb_figure_of_merit->setText(QString("FOM: %1").arg((QString::number(correlation, 'f', 3))));
1908  ui->lb_figure_of_merit->setHidden(false);
1909  }
1910 
1911  tbv_is_loading = false;
1912 
1913  update();
1914 }
1915 
1916 //*************************************************************************************************************
1917 
1918 void MainWindow::calc_adaptiv_mp(MatrixXd signal, truncation_criterion criterion)
1919 {
1920  adaptive_Mp = new AdaptiveMp();
1921  qreal res_energy = ui->dsb_energy->value();
1922 
1923  //threading
1924  mp_Thread = new QThread;
1925  adaptive_Mp->moveToThread(mp_Thread);
1926 
1927  connect(this, SIGNAL(send_input(MatrixXd, qint32, qreal, bool, qint32, qint32, qreal, qreal, qreal, qreal, bool)),
1928  adaptive_Mp, SLOT(recieve_input(MatrixXd, qint32, qreal, bool, qint32, qint32, qreal, qreal, qreal, qreal, bool)));
1929  connect(adaptive_Mp, SIGNAL(current_result(qint32, qint32, qreal, qreal, MatrixXd, adaptive_atom_list, fix_dict_atom_list)),
1930  this, SLOT(recieve_result(qint32, qint32, qreal, qreal, MatrixXd, adaptive_atom_list, fix_dict_atom_list)));
1931  connect(adaptive_Mp, SIGNAL(finished_calc()), mp_Thread, SLOT(quit()));
1932  connect(adaptive_Mp, SIGNAL(finished_calc()), adaptive_Mp, SLOT(deleteLater()));
1933  connect(mp_Thread, SIGNAL(finished()), this, SLOT(calc_thread_finished()));
1934  connect(mp_Thread, SIGNAL(finished()), mp_Thread, SLOT(deleteLater()));
1935 
1936  connect(adaptive_Mp, SIGNAL(send_warning(qint32)), this, SLOT(recieve_warnings(qint32)));
1937 
1938  QSettings settings;
1939  bool fixphase = settings.value("fixPhase", false).toBool();
1940  bool trial_separation = settings.value("trial_separation", false).toBool();
1941  qint32 boost = settings.value("boost", 100).toInt();
1942  qint32 iterations = settings.value("adaptive_iterations", 1E3).toInt();
1943  qreal reflection = settings.value("adaptive_reflection", 1.00).toDouble();
1944  qreal expansion = settings.value("adaptive_expansion", 0.20).toDouble();
1945  qreal contraction = settings.value("adaptive_contraction", 0.5).toDouble();
1946  qreal fullcontraction = settings.value("adaptive_fullcontraction", 0.50).toDouble();
1947  switch(criterion)
1948  {
1949  case Iterations:
1950  emit send_input(signal, ui->sb_Iterations->value(), qreal(MININT32), fixphase, boost, iterations,
1951  reflection, expansion, contraction, fullcontraction, trial_separation);
1952  mp_Thread->start();
1953  break;
1954 
1955  case SignalEnergy:
1956  emit send_input(signal, MAXINT32, res_energy, fixphase, boost, iterations,
1957  reflection, expansion, contraction, fullcontraction, trial_separation);
1958  mp_Thread->start();
1959  break;
1960 
1961  case Both:
1962  emit send_input(signal, ui->sb_Iterations->value(), res_energy, fixphase, boost, iterations,
1963  reflection, expansion, contraction, fullcontraction, trial_separation);
1964  mp_Thread->start();
1965  break;
1966  }
1967 }
1968 
1969 //************************************************************************************************************************************
1970 
1971 void MainWindow::calc_fix_mp(QString path, MatrixXd signal, truncation_criterion criterion)
1972 {
1973  fixDict_Mp = new FixDictMp();
1974  qreal res_energy = ui->dsb_energy->value();
1975 
1976  //threading
1977  mp_Thread = new QThread;
1978  fixDict_Mp->moveToThread(mp_Thread);
1979 
1980  connect(this, SIGNAL(send_input_fix_dict(MatrixXd, qint32, qreal, qint32, QString, qreal)),
1981  fixDict_Mp, SLOT(recieve_input(MatrixXd, qint32, qreal, qint32, QString, qreal)));
1982  connect(fixDict_Mp, SIGNAL(current_result(qint32, qint32, qreal, qreal, MatrixXd, adaptive_atom_list, fix_dict_atom_list)),
1983  this, SLOT(recieve_result(qint32, qint32, qreal, qreal, MatrixXd, adaptive_atom_list, fix_dict_atom_list)));
1984  connect(fixDict_Mp, SIGNAL(finished_calc()), mp_Thread, SLOT(quit()));
1985  connect(fixDict_Mp, SIGNAL(finished_calc()), fixDict_Mp, SLOT(deleteLater()));
1986  connect(mp_Thread, SIGNAL(finished()), this, SLOT(calc_thread_finished()));
1987  connect(mp_Thread, SIGNAL(finished()), mp_Thread, SLOT(deleteLater()));
1988 
1989  connect(fixDict_Mp, SIGNAL(send_warning(qint32)), this, SLOT(recieve_warnings(qint32)));
1990 
1991  QSettings settings;
1992  qint32 boost = settings.value("boost_fixDict", 100).toInt();
1993  qreal delta_energy = settings.value("delta_energy", 0.0005).toDouble();
1994 
1995  switch(criterion)
1996  {
1997  case Iterations:
1998  emit send_input_fix_dict(signal, ui->sb_Iterations->value(), qreal(MININT32), boost, path, delta_energy);
1999  mp_Thread->start();
2000  break;
2001 
2002  case SignalEnergy:
2003  emit send_input_fix_dict(signal, MAXINT32, res_energy, boost, path, delta_energy);
2004  mp_Thread->start();
2005  break;
2006 
2007  case Both:
2008  emit send_input_fix_dict(signal, ui->sb_Iterations->value(), res_energy, boost, path, delta_energy);
2009  mp_Thread->start();
2010  break;
2011  }
2012 }
2013 
2014 //*************************************************************************************************************
2015 
2016 QString MainWindow::create_display_text(FixDictAtom global_best_matching)
2017 {
2018  QSettings settings;
2019  QString display_text;
2020 
2021  if(!settings.value("show_phys_params", false).toBool())
2022  {
2023  if(global_best_matching.type == GABORATOM)
2024  {
2025  display_text = QString("Gaboratom: scale: %0, translation: %1, modulation: %2, phase: %3")
2026  .arg(QString::number(global_best_matching.gabor_atom.scale, 'f', 2))
2027  .arg(QString::number(global_best_matching.translation, 'f', 2))
2028  .arg(QString::number(global_best_matching.gabor_atom.modulation, 'f', 2))
2029  .arg(QString::number(global_best_matching.gabor_atom.phase, 'f', 2));
2030  }
2031  else if(global_best_matching.type == CHIRPATOM)
2032  {
2033  display_text = QString("Chripatom: scale: %0, translation: %1, modulation: %2, phase: %3, chirp: %4")
2034  .arg(QString::number(global_best_matching.chirp_atom.scale, 'f', 2))
2035  .arg(QString::number(global_best_matching.translation, 'f', 2))
2036  .arg(QString::number(global_best_matching.chirp_atom.modulation, 'f', 2))
2037  .arg(QString::number(global_best_matching.chirp_atom.phase, 'f', 2))
2038  .arg(QString::number(global_best_matching.chirp_atom.chirp, 'f', 2));
2039  }
2040  else if(global_best_matching.type == FORMULAATOM)
2041  {
2042  display_text = QString("%0: transl: %1 a: %2, b: %3 c: %4, d: %5, e: %6, f: %7, g: %8, h: %9")
2043  .arg(global_best_matching.atom_formula)
2044  .arg(QString::number(global_best_matching.translation, 'f', 2))
2045  .arg(QString::number(global_best_matching.formula_atom.a, 'f', 2))
2046  .arg(QString::number(global_best_matching.formula_atom.b, 'f', 2))
2047  .arg(QString::number(global_best_matching.formula_atom.c, 'f', 2))
2048  .arg(QString::number(global_best_matching.formula_atom.d, 'f', 2))
2049  .arg(QString::number(global_best_matching.formula_atom.e, 'f', 2))
2050  .arg(QString::number(global_best_matching.formula_atom.f, 'f', 2))
2051  .arg(QString::number(global_best_matching.formula_atom.g, 'f', 2))
2052  .arg(QString::number(global_best_matching.formula_atom.h, 'f', 2));
2053  }
2054  }
2055  else
2056  {
2057  if(global_best_matching.type == GABORATOM)
2058  {
2059  qreal phase = global_best_matching.gabor_atom.phase;
2060  if(global_best_matching.gabor_atom.phase > 2*PI) phase -= 2*PI;
2061 
2062  display_text = QString("Gaboratom: scale: %0 sec, translation: %1 sec, modulation: %2 Hz, phase: %3 rad")
2063  .arg(QString::number(global_best_matching.gabor_atom.scale / _sample_rate, 'f', 2))
2064  .arg(QString::number((global_best_matching.translation + _from) / _sample_rate + _offset_time, 'f', 2))
2065  .arg(QString::number(global_best_matching.gabor_atom.modulation * _sample_rate / global_best_matching.sample_count, 'f', 2))
2066  .arg(QString::number(phase, 'f', 2));
2067  }
2068  else if(global_best_matching.type == CHIRPATOM)
2069  {
2070  qreal phase = global_best_matching.chirp_atom.phase;
2071  if(global_best_matching.chirp_atom.phase > 2*PI) phase -= 2*PI;
2072 
2073  display_text = QString("Chripatom: scale: %0 sec, translation: %1 sec, modulation: %2 Hz, phase: %3 rad, chirp: %4")
2074  .arg(QString::number(global_best_matching.chirp_atom.scale / _sample_rate, 'f', 2))
2075  .arg(QString::number((global_best_matching.translation + _from) / _sample_rate + _offset_time, 'f', 2))
2076  .arg(QString::number(global_best_matching.chirp_atom.modulation * _sample_rate / global_best_matching.sample_count, 'f', 2))
2077  .arg(QString::number(phase, 'f', 2))
2078  .arg(QString::number(global_best_matching.chirp_atom.chirp, 'f', 2));
2079  }
2080  else if(global_best_matching.type == FORMULAATOM)
2081  {
2082  display_text = QString("%0: transl: %1 a: %2, b: %3 c: %4, d: %5, e: %6, f: %7, g: %8, h: %9")
2083  .arg(global_best_matching.atom_formula)
2084  .arg(QString::number((global_best_matching.translation + _from) / _sample_rate + _offset_time, 'f', 2))
2085  .arg(QString::number(global_best_matching.formula_atom.a, 'f', 2))
2086  .arg(QString::number(global_best_matching.formula_atom.b, 'f', 2))
2087  .arg(QString::number(global_best_matching.formula_atom.c, 'f', 2))
2088  .arg(QString::number(global_best_matching.formula_atom.d, 'f', 2))
2089  .arg(QString::number(global_best_matching.formula_atom.e, 'f', 2))
2090  .arg(QString::number(global_best_matching.formula_atom.f, 'f', 2))
2091  .arg(QString::number(global_best_matching.formula_atom.g, 'f', 2))
2092  .arg(QString::number(global_best_matching.formula_atom.h, 'f', 2));
2093  }
2094  }
2095 
2096  return display_text;
2097 }
2098 
2099 //*****************************************************************************************************************
2100 
2101 // Opens Dictionaryeditor
2102 void MainWindow::on_actionW_rterbucheditor_triggered()
2103 {
2104  if(_editor_window == NULL)
2105  {
2106  _editor_window = new EditorWindow();
2107  connect(_editor_window, SIGNAL(dict_saved()), this, SLOT(on_dicts_saved()));
2108  }
2109  if(!_editor_window->isVisible()) _editor_window->show();
2110  else
2111  {
2112  _editor_window->setWindowState(Qt::WindowActive);
2113  _editor_window->raise();
2114  }
2115 
2116 }
2117 
2118 //*****************************************************************************************************************
2119 
2120 // opens advanced Dictionaryeditor
2121 void MainWindow::on_actionErweiterter_W_rterbucheditor_triggered()
2122 {
2123  if(_enhanced_editor_window == NULL)
2124  {
2125  _enhanced_editor_window = new Enhancededitorwindow();
2126  if(_editor_window == NULL) _editor_window = new EditorWindow();
2127  connect(_enhanced_editor_window, SIGNAL(dict_saved()), _editor_window, SLOT(on_save_dicts()));
2128  }
2129  if(!_enhanced_editor_window->isVisible()) _enhanced_editor_window->show();
2130  else
2131  {
2132  _enhanced_editor_window->setWindowState(Qt::WindowActive);
2133  _enhanced_editor_window->raise();
2134  }
2135 }
2136 
2137 //*****************************************************************************************************************
2138 
2139 
2140 // opens formula editor
2141 void MainWindow::on_actionAtomformeleditor_triggered()
2142 {
2143  if(_formula_editor == NULL)
2144  {
2145  _formula_editor = new Formulaeditor();
2146  if(_enhanced_editor_window == NULL) _enhanced_editor_window = new Enhancededitorwindow();
2147  connect(_formula_editor, SIGNAL(formula_saved()), _enhanced_editor_window, SLOT(on_formula_saved()));
2148  }
2149  if(!_formula_editor->isVisible()) _formula_editor->show();
2150  else
2151  {
2152  _formula_editor->setWindowState(Qt::WindowActive);
2153  _formula_editor->raise();
2154  }
2155 }
2156 
2157 //*****************************************************************************************************************
2158 
2159 // open treebase window
2160 void MainWindow::on_actionCreate_treebased_dictionary_triggered()
2161 {
2162  _treebased_dict_window = new TreebasedDictWindow();
2163  _treebased_dict_window->show();
2164 }
2165 
2166 //*****************************************************************************************************************
2167 
2168 // open settings
2169 void MainWindow::on_actionSettings_triggered()
2170 {
2171  if(_setting_window == NULL) _setting_window = new settingwindow();
2172  if(_setting_window != NULL) _setting_window->set_values();
2173  if(!_setting_window->isVisible()) _setting_window->show();
2174  else
2175  {
2176  _setting_window->setWindowState(Qt::WindowActive);
2177  _setting_window->raise();
2178  }
2179 
2180  connect(_setting_window, SIGNAL(change_info_label()), this, SLOT(activate_info_label()));
2181 }
2182 
2183 //*****************************************************************************************************************
2184 
2185 // opens Filedialog for read signal (contextmenue)
2186 void MainWindow::on_actionNeu_triggered()
2187 {
2188  open_file();
2189 }
2190 
2191 //*****************************************************************************************************************
2192 
2193 // opens Filedialog for read signal (button)
2194 void MainWindow::on_btt_OpenSignal_clicked()
2195 {
2196  open_file();
2197 }
2198 
2199 
2200 //*****************************************************************************************************************
2201 
2202 void MainWindow::on_dsb_sample_rate_editingFinished()
2203 {
2204  _sample_rate = ui->dsb_sample_rate->value();
2205  if(!read_fiff_changed)
2206  {
2207  read_fiff_changed = true;
2208 
2209  ui->dsb_from->setMaximum((_last_sample - 63) / _sample_rate);
2210  ui->dsb_to->setMinimum((_first_sample + 63) / _sample_rate);
2211  ui->lb_from->setToolTip(QString("minimum: %1 seconds").arg(_first_sample / _sample_rate));
2212  ui->lb_to->setToolTip(QString("maximum: %1 seconds").arg(_last_sample / _sample_rate));
2213  ui->sb_sample_count->setToolTip(QString("epoch: %1 sec").arg((_to - _from + 1) / _sample_rate));
2214  ui->lb_samples->setToolTip(QString("min: 64 (%1 sec)\nmax: 4096 (%2 sec)").arg(64 / _sample_rate).arg(4096 / _sample_rate));
2215 
2216  if(_from != 0)
2217  ui->dsb_from->setValue(_from / _sample_rate + _offset_time);
2218  ui->dsb_to->setValue(_to / _sample_rate + _offset_time);
2219  read_fiff_changed = false;
2220  }
2221  callXAxisWindow->update();
2222 }
2223 
2224 //*****************************************************************************************************************
2225 
2226 void MainWindow::on_dsb_from_editingFinished()
2227 {
2228  if(read_fiff_changed || _from == last_from) return;
2229  if(ui->dsb_from->value() * _sample_rate < _first_sample)
2230  ui->dsb_from->setValue(_first_sample / _sample_rate + _offset_time);
2231 
2232  if(file_name.split('.').last() == "fif")
2233  {
2234  if(!_pick_evoked.isEmpty())
2235  read_fiff_ave_new();
2236  else
2237  read_fiff_file_new(file_name);
2238  }
2239  else read_matlab_file_new();
2240  last_from = _from;
2241 }
2242 
2243 //*****************************************************************************************************************
2244 
2245 void MainWindow::on_dsb_to_editingFinished()
2246 {
2247  if(read_fiff_changed || _to == last_to) return;
2248  if(ui->dsb_to->value() * _sample_rate > _last_sample)
2249  ui->dsb_to->setValue(_last_sample / _sample_rate);
2250 
2251  if(file_name.split('.').last() == "fif")
2252  {
2253  if(!_pick_evoked.isEmpty())
2254  read_fiff_ave_new();
2255  else
2256  read_fiff_file_new(file_name);
2257  }
2258  else read_matlab_file_new();
2259  last_to = _to;
2260 }
2261 
2262 //*****************************************************************************************************************
2263 
2264 void MainWindow::on_sb_sample_count_editingFinished()
2265 {
2266  if(read_fiff_changed || ui->sb_sample_count->value() == last_sample_count) return;
2267 
2268  if(file_name.split('.').last() == "fif")
2269  {
2270  if(!_pick_evoked.isEmpty())
2271  read_fiff_ave_new();
2272  else
2273  read_fiff_file_new(file_name);
2274  }
2275  else read_matlab_file_new();
2276 
2277  last_sample_count = ui->sb_sample_count->value();
2278 }
2279 
2280 //*****************************************************************************************************************
2281 
2282 void MainWindow::on_dsb_from_valueChanged(double arg1)
2283 {
2284  if(read_fiff_changed) return;
2285 
2286  read_fiff_changed = true;
2287  _from = floor((arg1 - _offset_time) * _sample_rate);
2288  if(_from < 0)//stay consistent despite negative time values
2289  {
2290  ui->dsb_from->setValue(_offset_time);
2291  _from = 0;
2292  }
2293  _to = _from + ui->sb_sample_count->value() - 1;
2294 
2295  if(_to >= _last_sample - _offset_time * _sample_rate)
2296  {
2297  _to = _last_sample - _offset_time * _sample_rate;
2298  _samplecount = _to - _from + 1;
2299  ui->sb_sample_count->setValue(_samplecount);
2300  }
2301 
2302  ui->dsb_to->setValue(_to / _sample_rate + _offset_time);
2303  read_fiff_changed = false;
2304 
2305  ui->dsb_from->setToolTip(QString("sample: %1").arg(_from));
2306 }
2307 
2308 //*****************************************************************************************************************
2309 
2310 
2311 void MainWindow::on_dsb_to_valueChanged(double arg1)
2312 {
2313  if(read_fiff_changed) return;
2314 
2315  read_fiff_changed = true;
2316  _to = floor((arg1 - _offset_time) * _sample_rate);
2317  if(_to > _last_sample - _offset_time * _sample_rate)
2318  {
2319  ui->dsb_to->setValue(_last_sample / _sample_rate);
2320  _to = _last_sample - _offset_time * _sample_rate;
2321  }
2322  _from = _to - ui->sb_sample_count->value() + 1;
2323 
2324  if(_from + _offset_time * _sample_rate <= _first_sample)
2325  {
2326  _from = _first_sample - _offset_time * _sample_rate;
2327  _samplecount = _to - _from + 1;
2328  ui->sb_sample_count->setValue(_samplecount);
2329  }
2330 
2331  ui->dsb_from->setValue(_from / _sample_rate + _offset_time);
2332  read_fiff_changed = false;
2333 
2334  ui->dsb_to->setToolTip(QString("sample: %1").arg(_to));
2335 }
2336 
2337 //*****************************************************************************************************************
2338 
2339 void MainWindow::on_sb_sample_count_valueChanged(int arg1)
2340 {
2341  ui->sb_sample_count->setToolTip(QString("epoch: %1 sec").arg((arg1) / _sample_rate));
2342 
2343  if(read_fiff_changed) return;
2344 
2345  read_fiff_changed = true;
2346  _to = _from + arg1 - 1;
2347 
2348  if(_to > _last_sample - _offset_time * _sample_rate)
2349  {
2350  _to = _last_sample - _offset_time * _sample_rate;
2351  _samplecount = _to - _from + 1;
2352  ui->sb_sample_count->setValue(_samplecount);
2353  }
2354  _samplecount = arg1;
2355  ui->dsb_to->setValue(_to / _sample_rate + _offset_time);
2356  read_fiff_changed = false;
2357 
2358 }
2359 
2360 //*****************************************************************************************************************
2361 
2362 void MainWindow::on_cb_all_select_clicked()
2363 {
2364  if(tbv_is_loading) return;
2365 
2366  if( ui->cb_all_select->checkState() == Qt::Unchecked && !was_partialchecked)
2367  {
2368  ui->cb_all_select->setCheckState(Qt::PartiallyChecked);
2369  was_partialchecked = true;
2370  }
2371  else if(ui->cb_all_select->checkState() == Qt::Checked && !was_partialchecked)
2372  {
2373  ui->cb_all_select->setCheckState(Qt::Unchecked);
2374  was_partialchecked = false;
2375  }
2376 
2377  auto_change = true;
2378 
2379  if(ui->cb_all_select->checkState() == Qt::Checked)
2380  for(qint32 i = 0; i < ui->tbv_Results->rowCount() - 1; i++) // last item is residuum
2381  ui->tbv_Results->item(i, 0)->setCheckState(Qt::Checked);
2382  else if(ui->cb_all_select->checkState() == Qt::Unchecked)
2383  for(qint32 i = 0; i < ui->tbv_Results->rowCount() - 1; i++) // last item is residuum
2384  ui->tbv_Results->item(i, 0)->setCheckState(Qt::Unchecked);
2385  else
2386  {
2387  for(qint32 i = 0; i < ui->tbv_Results->rowCount() - 1; i++) // last item is residuum
2388  if(select_atoms_map[i] == true)
2389  ui->tbv_Results->item(i, 0)->setCheckState(Qt::Checked);
2390  else
2391  ui->tbv_Results->item(i, 0)->setCheckState(Qt::Unchecked);
2392  }
2393 
2394  bool all_selected = true;
2395  bool all_deselected = true;
2396  for(qint32 i = 0; i < ui->tbv_Results->rowCount() - 1; i++) // last item is residuum
2397  if(ui->tbv_Results->item(i, 0)->checkState())
2398  all_deselected = false;
2399  else
2400  all_selected = false;
2401 
2402  if(all_selected)
2403  ui->cb_all_select->setCheckState(Qt::Checked);
2404  else if(all_deselected)
2405  {
2406  ui->cb_all_select->setCheckState(Qt::Unchecked);
2407  was_partialchecked = true;
2408  }
2409  else ui->cb_all_select->setCheckState(Qt::PartiallyChecked);
2410 
2411  auto_change = false;
2412 }
2413 
2414 //*****************************************************************************************************************
2415 
2416 void MainWindow::on_dicts_saved()
2417 {
2418  fill_dict_combobox();
2419 }
2420 
2421 //*****************************************************************************************************************
2422 
2423 void MainWindow::on_actionSpeicher_triggered()
2424 {
2425  QString save_name = "";
2426  QStringList saveList = file_name.split('/').last().split('.').first().split('_');
2427  for(int i = 0; i < saveList.length(); i++)
2428  {
2429  if(i == saveList.length() - 1)
2430  save_name += "mp_" + saveList.at(i);
2431  else
2432  save_name += saveList.at(i) + "_";
2433  }
2434 
2435  if(file_name.split('.').last() != "fif")
2436  {
2437  if(save_path.isEmpty())
2438  {
2439  save_path = QFileDialog::getSaveFileName(this, "Save file as...", last_save_path + "/" + save_name,"(*.txt)");
2440  if(save_path.isEmpty()) return;
2441  }
2442  save_parameters();
2443  QMessageBox::information(this, tr("information"),
2444  tr("No fif file for save. Only parameter.txt saved."));
2445  return;
2446  }
2447 
2448  if(save_path.isEmpty())
2449  {
2450  save_path = QFileDialog::getSaveFileName(this, "Save file as...", last_save_path + "/" + save_name,"(*.fif)");
2451  if(save_path.isEmpty()) return;
2452  }
2453 
2454  QStringList string_list = save_path.split('/');
2455  last_save_path = "";
2456  for(qint32 i = 0; i < string_list.length() - 1; i++)
2457  last_save_path += string_list.at(i) + '/';
2458 
2459  save_fif_file();
2460 }
2461 
2462 //*****************************************************************************************************************
2463 
2464 void MainWindow::on_actionSpeicher_unter_triggered()
2465 {
2466  QString save_name = "";
2467  QStringList saveList = file_name.split('/').last().split('.').first().split('_');
2468  for(int i = 0; i < saveList.length(); i++)
2469  {
2470  if(i == saveList.length() - 1) save_name += "mp_" + saveList.at(i);
2471  else save_name += saveList.at(i) + "_";
2472  }
2473 
2474  if(file_name.split('.').last() != "fif")
2475  save_path = QFileDialog::getSaveFileName(this, "Save file as...", last_save_path + "/" + save_name,"(*.txt)");
2476  else
2477  save_path = QFileDialog::getSaveFileName(this, "Save file as...", last_save_path + "/" + save_name,"(*.fif)");
2478 
2479  if(save_path.isEmpty()) return;
2480 
2481  // savepath without filename, memorise last savepath
2482  QStringList string_list = save_path.split('/');
2483  last_save_path = "";
2484  for(qint32 i = 0; i < string_list.length() - 1; i++)
2485  last_save_path += string_list.at(i) + '/';
2486 
2487  save_fif_file();
2488 }
2489 
2490 //*****************************************************************************************************************
2491 
2493 {
2494  save_parameters();
2495 
2496  SaveFifFile *save_Fif = new SaveFifFile();
2497  QThread *save_thread = new QThread();
2498 
2499  save_Fif->moveToThread(save_thread);
2500 
2501  connect(this, SIGNAL(to_save(QString, QString, fiff_int_t, fiff_int_t, MatrixXd, MatrixXd, select_map, RowVectorXi, source_file_type )),
2502  save_Fif, SLOT(save_fif_file(QString, QString, fiff_int_t, fiff_int_t, MatrixXd, MatrixXd, select_map, RowVectorXi, source_file_type )));
2503  connect(save_Fif, SIGNAL(save_progress(qint32, qint32)), this, SLOT(recieve_save_progress(qint32, qint32)));
2504  connect(this, SIGNAL(kill_save_thread()), save_thread, SLOT(quit()));
2505  connect(this, SIGNAL(kill_save_thread()), save_Fif, SLOT(deleteLater()));
2506  //connect(save_thread, SIGNAL(finished()), save_Fif, SLOT(deleteLater()));
2507  connect(save_thread, SIGNAL(finished()), save_thread, SLOT(deleteLater()));
2508  connect(save_Fif, SIGNAL(finished()), save_thread, SLOT(deleteLater()));
2509 
2510  is_saved = true;
2511  ui->lb_timer->setHidden(true);
2512  ui->cb_all_select->setHidden(true);
2513  ui->progress_bar_save->setHidden(false);
2514  ui->progress_bar_save->setFormat("save fif file: %p%");
2515  ui->progress_bar_save->setValue(0);
2516  ui->progress_bar_save->setMinimum(0);
2517  ui->progress_bar_save->setMaximum(_last_sample);
2518  //reset progressbar text color to black
2519  pal.setColor(QPalette::Text, Qt::black);
2520  ui->progress_bar_save->setPalette(pal);
2521  //ui->progress_bar_save->repaint();
2522  is_save_white = false;
2523 
2524  ui->actionSpeicher->setEnabled(false);
2525  ui->actionSpeicher_unter->setEnabled(false);
2526 
2527  emit to_save(file_name, save_path, _from, _to, _atom_sum_matrix, reference_matrix, select_channel_map, picks, file_type);
2528  save_thread->start();
2529 }
2530 
2531 //*****************************************************************************************************************
2532 
2533 void MainWindow::recieve_save_progress(qint32 current_progress, qint32 finished)
2534 {
2535  if(finished == 0) //save in progress
2536  {
2537  ui->progress_bar_save->setValue(current_progress);
2538  if(ui->progress_bar_save->value() > ui->progress_bar_save->maximum() / 2 && !is_save_white)
2539  {
2540  pal.setColor(QPalette::Text, Qt::white);
2541  ui->progress_bar_save->setPalette(pal);
2542  is_save_white = true;
2543  }
2544  }
2545  else if(finished == 2) // error on save
2546  {
2547  QMessageBox::warning(this, "Error", "error: no success on save.");
2548  ui->progress_bar_save->setHidden(true);
2549  emit kill_save_thread();
2550  }
2551  else if(finished == 4) // save .txt instead of ave.fif as long as mne-cpp do not serve that function
2552  QMessageBox::warning(this, "Error", "error: unable to save -ave.fif files\nDecomposition data saved to:\n" + save_path + ".txt");
2553 
2554  else //save is successfully finished
2555  {
2556  ui->progress_bar_save->setHidden(true);
2557  ui->actionSpeicher->setEnabled(true);
2558  ui->actionSpeicher_unter->setEnabled(true);
2559 
2560  emit kill_save_thread();
2561  }
2562 }
2563 //*****************************************************************************************************************
2564 
2565 void SaveFifFile::save_fif_file(QString source_path, QString save_path, fiff_int_t start_change, fiff_int_t end_change, MatrixXd changes, MatrixXd original_signal,
2566  select_map select_channel_map, RowVectorXi picks, source_file_type file_type)
2567 {
2568  QFile t_fileIn(source_path);
2569  QFile t_fileOut(save_path);
2570 
2571  switch(file_type)
2572  {
2573  case RAW: // if(QString::compare(source_path.split('.').last(), "fif", Qt::CaseInsensitive) == 0)
2574  {
2575  // Setup for reading the raw data
2576  FiffRawData raw(t_fileIn);
2577 
2578  RowVectorXd cals;
2579  FiffStream::SPtr outfid = Fiff::start_writing_raw(t_fileOut, raw.info, cals, picks);
2580 
2581  // Set up the reading parameters
2582  fiff_int_t from = raw.first_samp;
2583  fiff_int_t to = raw.last_samp;
2584  float quantum_sec = 10.0f;//read and write in 10 sec junks
2585  fiff_int_t quantum = ceil(quantum_sec*raw.info.sfreq); // To read the whole file at once set quantum = to - from + 1;
2586 
2587  // Read and write all the data
2588  //************************************************************************************
2589  bool first_buffer = true;
2590  fiff_int_t first;
2591  fiff_int_t last;
2592  MatrixXd data;
2593  MatrixXd times;
2594 
2595  // from 0 to start of change
2596  for(first = from; first < start_change; first += quantum)
2597  {
2598  last = first + quantum - 1;
2599  if (last > start_change)
2600  {
2601  last = start_change - 1;
2602  }
2603  if (!raw.read_raw_segment(data ,times, first, last, picks))
2604  {
2605  printf("error during read_raw_segment\n");
2606  emit save_progress(first, 2);
2607  return;
2608  }
2609  printf("Writing...");
2610  if (first_buffer)
2611  {
2612  if (first > 0)
2613  outfid->write_int(FIFF_FIRST_SAMPLE, &first);
2614  first_buffer = false;
2615  }
2616  outfid->write_raw_buffer(data, cals);
2617  printf("[done]\n");
2618 
2619  emit save_progress(first, 0);
2620  }
2621 
2622  //************************************************************************************
2623 
2624  // from start of change to end of change
2625  if (!raw.read_raw_segment(data, times, start_change ,end_change,picks))
2626  {
2627  printf("error during read_raw_segment\n");
2628  emit save_progress(first, 2);
2629  return;
2630  }
2631 
2632  qint32 index = 0;
2633  for(qint32 channels = 0; channels < data.rows(); channels++)
2634  {
2635  if(select_channel_map[channels])
2636  {
2637  data.row(channels) = changes.col(index) ;
2638  index++;
2639  }
2640  }
2641  printf("Writing new data...");
2642  if (first_buffer)
2643  {
2644  if (start_change > 0)
2645  outfid->write_int(FIFF_FIRST_SAMPLE, &start_change);
2646  first_buffer = false;
2647  }
2648  outfid->write_raw_buffer(data, cals);
2649  printf("[done]\n");
2650 
2651 
2652  //************************************************************************************
2653 
2654  // from end of change to end
2655  for(first = end_change + 1; first < to; first += quantum)
2656  {
2657  last = first + quantum - 1;
2658  if (last > to)
2659  {
2660  last = to;
2661  }
2662  if (!raw.read_raw_segment(data, times, first, last, picks))
2663  {
2664  printf("error during read_raw_segment\n");
2665  emit save_progress(first, 2);
2666  return;
2667  }
2668  printf("Writing...");
2669  outfid->write_raw_buffer(data, cals);
2670  printf("[done]\n");
2671 
2672  emit save_progress(first, false);
2673  }
2674 
2675  emit save_progress(to, true);
2676 
2677  outfid->finish_writing_raw();
2678  printf("Finished\n");
2679  break;
2680  }
2681 
2682  case AVE: // if(source_path.contains("-ave.", Qt::CaseInsensitive))
2683  {
2684  std::cout << "thread\n";
2685  //temporary ToDo: revert this temp if saving AVE is possible in MNE-CPP
2686  emit save_progress(0, 4);
2687 
2688  t_fileOut.setFileName(save_path.append(".txt"));
2689 
2690  if (t_fileOut.open(QFile::WriteOnly | QFile::Truncate))
2691  {
2692  QTextStream matlab_stream(&t_fileOut);
2693  qint32 channel_index = 0;
2694  for(qint32 channel = 0; channel < original_signal.cols(); channel++)
2695  {
2696  qint32 sample_index = 0;
2697  if(select_channel_map[channel])//changes in this channels
2698  {
2699  for(qint32 sample = 0; sample < original_signal.rows(); sample++)
2700  if(sample >= start_change && sample < end_change)
2701  {
2702  matlab_stream << QString::number(changes(sample_index, channel_index)) << ",";
2703  sample_index++;
2704  }
2705  else matlab_stream << QString::number(original_signal(sample, channel)) << ",";
2706  matlab_stream<< "\n";
2707  channel_index++;
2708  }
2709  else //no changes in this channel, just save original channel
2710  {
2711  for(qint32 sample = 0; sample < original_signal.rows(); sample++)
2712  matlab_stream << QString::number(original_signal(sample, channel)) << ",";
2713  matlab_stream<< "\n";
2714  }
2715  emit save_progress((channel + 1) * (original_signal.rows() /original_signal.cols()), 0);
2716  }
2717  }
2718  emit save_progress(original_signal.rows(), true);
2719  //end temporary
2720 
2721  break;
2722  }
2723 
2724  case TXT: // if(QString::compare(source_path.split('.').last(), "txt", Qt::CaseInsensitive) == 0)
2725  {
2726  if (t_fileOut.open(QFile::WriteOnly | QFile::Truncate))
2727  {
2728  QTextStream matlab_stream(&t_fileOut);
2729 
2730  qint32 index = 0;
2731  for(qint32 channel = 0; channel < _matlab_channels.length(); channel++)
2732  {
2733  if(select_channel_map[channel])//changes in this channels
2734  {
2735  QStringList signal_samples = _matlab_channels.at(channel).split(',', QString::SkipEmptyParts);
2736  for(qint32 sample = start_change; sample <= end_change; sample++)
2737  {
2738  signal_samples.replace(sample, QString::number(changes(sample - start_change, index)));//ToDo: ready
2739  }
2740  for(qint32 sample = 0; sample < signal_samples.length() - 1; sample++)
2741  matlab_stream << signal_samples.at(sample) << ",";
2742  matlab_stream << signal_samples.last();
2743  matlab_stream << "\n"; //next channel
2744  index++;
2745  }
2746  else //no changes in this channel, just save original channel
2747  {
2748  matlab_stream << _matlab_channels.at(channel);
2749  matlab_stream << "\n"; //next channel
2750  }
2751  emit save_progress((channel + 1) * (_matlab_channels.at(0).split(',', QString::SkipEmptyParts).length() /_matlab_channels.length()), 0);
2752  }
2753  }
2754  emit save_progress(_matlab_channels.at(0).split(',', QString::SkipEmptyParts).length(), true);
2755  break;
2756  }
2757 
2758  default:
2759  {
2760  emit save_progress(0, 2);
2761  return;
2762  }
2763  }
2764 }
2765 
2766 //*****************************************************************************************************************
2767 
2768 void MainWindow::save_parameters()
2769 {
2770  QString save_parameter_path = save_path.split(".").first() + "_params.txt";
2771  QString original_file_name = file_name.split("/").last().split(".").first();
2772  QFile xml_file(save_parameter_path);
2773  if(xml_file.open(QIODevice::WriteOnly))
2774  {
2775  QXmlStreamWriter xmlWriter(&xml_file);
2776  xmlWriter.setAutoFormatting(true);
2777  xmlWriter.writeStartDocument();
2778  xmlWriter.writeStartElement("MP_DECOMPOSITION");
2779  xmlWriter.writeAttribute("fiff_file_name", original_file_name);
2780  xmlWriter.writeAttribute("epoch_from", QString::number(ui->dsb_from->value()));
2781  xmlWriter.writeAttribute("epoch_to", QString::number(ui->dsb_to->value()));
2782  xmlWriter.writeAttribute("samples", QString::number(ui->sb_sample_count->value()));
2783  xmlWriter.writeAttribute("sample_rate", QString::number(ui->dsb_sample_rate->value()));
2784 
2785  for(qint32 i = 0; i < ui->tbv_Results->rowCount() - 1; i++)
2786  {
2787  if(ui->tbv_Results->columnCount() == 2 && ui->tbv_Results->item(i, 1)->text() != "residuum")
2788  {
2789  FixDictAtom fix_atom = _fix_dict_atom_list.at(i);
2790 
2791  xmlWriter.writeStartElement("ATOM");
2792  xmlWriter.writeAttribute("formula", fix_atom.atom_formula);
2793  xmlWriter.writeAttribute("sample_count", QString::number(fix_atom.sample_count));
2794  xmlWriter.writeAttribute("%energy_from_signal", ui->tbv_Results->item(i, 0)->text());
2795  xmlWriter.writeAttribute("dict_source", fix_atom.dict_source);
2796  xmlWriter.writeStartElement("PARAMETER");
2797 
2798  if(fix_atom.type == GABORATOM)
2799  {
2800  xmlWriter.writeAttribute("scale", QString::number(fix_atom.gabor_atom.scale));
2801  xmlWriter.writeAttribute("translation", QString::number(fix_atom.translation));
2802  xmlWriter.writeAttribute("modulation", QString::number(fix_atom.gabor_atom.modulation));
2803  xmlWriter.writeAttribute("phase", QString::number(fix_atom.gabor_atom.phase));
2804  }
2805  else if(fix_atom.type == CHIRPATOM)
2806  {
2807  xmlWriter.writeAttribute("scale", QString::number(fix_atom.chirp_atom.scale));
2808  xmlWriter.writeAttribute("translation", QString::number(fix_atom.translation));
2809  xmlWriter.writeAttribute("modulation", QString::number(fix_atom.chirp_atom.modulation));
2810  xmlWriter.writeAttribute("phase", QString::number(fix_atom.chirp_atom.phase));
2811  xmlWriter.writeAttribute("chirp", QString::number(fix_atom.chirp_atom.chirp));
2812  }
2813  else if(fix_atom.type == FORMULAATOM)
2814  {
2815  xmlWriter.writeAttribute("translation", QString::number(fix_atom.translation));
2816  xmlWriter.writeAttribute("a", QString::number(fix_atom.formula_atom.a));
2817  xmlWriter.writeAttribute("b", QString::number(fix_atom.formula_atom.b));
2818  xmlWriter.writeAttribute("c", QString::number(fix_atom.formula_atom.c));
2819  xmlWriter.writeAttribute("d", QString::number(fix_atom.formula_atom.d));
2820  xmlWriter.writeAttribute("e", QString::number(fix_atom.formula_atom.e));
2821  xmlWriter.writeAttribute("f", QString::number(fix_atom.formula_atom.f));
2822  xmlWriter.writeAttribute("g", QString::number(fix_atom.formula_atom.g));
2823  xmlWriter.writeAttribute("h", QString::number(fix_atom.formula_atom.h));
2824  }
2825  xmlWriter.writeEndElement(); //PARAMETER
2826  xmlWriter.writeEndElement(); //ATOM
2827  }
2828  else //ToDo: does not work for trial separation like this
2829  {
2830  GaborAtom gabor_atom = _adaptive_atom_list.at(i).last();
2831  xmlWriter.writeStartElement("ATOM");
2832  xmlWriter.writeAttribute("formula", "GABORATOM");
2833  xmlWriter.writeAttribute("sample_count", QString::number(gabor_atom.sample_count));
2834  xmlWriter.writeAttribute("%energy_from_signal", ui->tbv_Results->item(i, 0)->text());
2835 
2836  xmlWriter.writeStartElement("MATHEMATICAL_PARAMETERS");
2837  xmlWriter.writeAttribute("scale", QString::number(gabor_atom.scale));
2838  xmlWriter.writeAttribute("translation", QString::number(gabor_atom.translation));
2839  xmlWriter.writeAttribute("modulation", QString::number(gabor_atom.modulation));
2840  xmlWriter.writeAttribute("phase", QString::number(gabor_atom.phase));
2841  xmlWriter.writeEndElement(); //PARAMETER
2842 
2843  xmlWriter.writeStartElement("PHYSICAL_PARAMETERS");
2844  xmlWriter.writeAttribute("scale", QString::number(gabor_atom.scale / _sample_rate, 'g', 3));
2845  xmlWriter.writeAttribute("translation", QString::number(gabor_atom.translation / qreal(_sample_rate) + _from / _sample_rate, 'g', 4));
2846  xmlWriter.writeAttribute("modulation", QString::number(gabor_atom.modulation * _sample_rate / gabor_atom.sample_count, 'g', 3));
2847 
2848  qreal phase = gabor_atom.phase;
2849  if(phase > 2*PI) phase -= 2*PI;
2850  xmlWriter.writeAttribute("phase", QString::number(phase, 'g', 3));
2851  xmlWriter.writeEndElement(); //PARAMETER
2852  xmlWriter.writeEndElement(); //ATOM
2853  }
2854  }
2855  xmlWriter.writeEndElement(); //MP_DECOMPOSITION
2856  xmlWriter.writeEndDocument();
2857  }
2858  xml_file.close();
2859 }
2860 
2861 //*****************************************************************************************************************
2862 
2863 void MainWindow::on_actionExport_triggered()
2864 {
2865  if(_adaptive_atom_list.length() == 0)
2866  {
2867  QMessageBox::warning(this, tr("Error"),
2868  tr("error: No adaptive MP results for save."));
2869  return;
2870  }
2871 
2872  QString save_path = QFileDialog::getSaveFileName(this, "Export results as dict file...", QDir::homePath() + "/" + "Matching-Pursuit-Toolbox" + "/" + "resultdict","(*.dict)");
2873  if(save_path.isEmpty()) return;
2874 
2875  QStringList string_list = save_path.split('/');
2876  last_save_path = "";
2877  for(qint32 i = 0; i < string_list.length() - 1; i++)
2878  last_save_path += string_list.at(i) + '/';
2879 
2880  QSettings settings;
2881  qint32 pdict_count = settings.value("pdict_count", 8).toInt();
2882 
2883  QFile xml_file(save_path);
2884  if(xml_file.open(QIODevice::WriteOnly))
2885  {
2886  QXmlStreamWriter xmlWriter(&xml_file);
2887  xmlWriter.setAutoFormatting(true);
2888  xmlWriter.writeStartDocument();
2889 
2890  xmlWriter.writeStartElement("COUNT");
2891  xmlWriter.writeAttribute("of_atoms", QString::number(_adaptive_atom_list.length() * _adaptive_atom_list.first().length()));
2892 
2893  qint16 built_count = 0;
2894  qint32 div = floor(_adaptive_atom_list.length() / (qreal)pdict_count);
2895  qint32 mod = _adaptive_atom_list.length() % pdict_count;
2896  if(div != 0)
2897  {
2898  for(qint32 j = 0; j < pdict_count; j++)
2899  {
2900  xmlWriter.writeStartElement("built_Atoms");
2901  xmlWriter.writeAttribute("formula", "Gaboratom");
2902  xmlWriter.writeAttribute("sample_count", QString::number(_adaptive_atom_list.first().first().sample_count));
2903  xmlWriter.writeAttribute("atom_count", QString::number(div * _adaptive_atom_list.first().length()));
2904  xmlWriter.writeAttribute("source_dict", save_path.split('/').last().split('.').first() + "_" + QString::number(j));
2905 
2906  for(qint32 i = 0; i < div; i++)
2907  {
2908  for(qint32 chn = 0; chn < _adaptive_atom_list.first().length(); chn++)
2909  {
2910  GaborAtom gabor_atom = _adaptive_atom_list.at(i + j * div).at(chn);
2911  QStringList result_list = gabor_atom.create_string_values(gabor_atom.sample_count, gabor_atom.scale, gabor_atom.sample_count / 2, gabor_atom.modulation, gabor_atom.phase);
2912 
2913  xmlWriter.writeStartElement("ATOM");
2914  xmlWriter.writeAttribute("ID", QString::number(i * _adaptive_atom_list.first().length() + chn));
2915  xmlWriter.writeAttribute("scale", QString::number(gabor_atom.scale));
2916  xmlWriter.writeAttribute("modu", QString::number(gabor_atom.modulation));
2917  xmlWriter.writeAttribute("phase", QString::number(gabor_atom.phase));
2918 
2919  xmlWriter.writeStartElement("samples");
2920  QString samples_to_xml;
2921  for (qint32 it = 0; it < result_list.length(); it++)
2922  {
2923  samples_to_xml.append(result_list.at(it));
2924  samples_to_xml.append(":");
2925  }
2926  xmlWriter.writeAttribute("samples", samples_to_xml);
2927  xmlWriter.writeEndElement(); //samples
2928 
2929  xmlWriter.writeEndElement(); //ATOM
2930  }
2931  built_count++;
2932  }
2933  xmlWriter.writeEndElement(); //built_atoms
2934  } //builds
2935  }
2936 
2937  if(mod != 0)
2938  {
2939  xmlWriter.writeStartElement("built_Atoms");
2940  xmlWriter.writeAttribute("formula", "Gaboratom");
2941  xmlWriter.writeAttribute("sample_count", QString::number(_adaptive_atom_list.first().first().sample_count));
2942  xmlWriter.writeAttribute("atom_count", QString::number(mod * _adaptive_atom_list.first().length()));
2943  xmlWriter.writeAttribute("source_dict", save_path.split('/').last().split('.').first() + "_" + QString::number(built_count));
2944 
2945  for(qint32 i = 0; i < mod; i++)
2946  {
2947  for(qint32 chn = 0; chn < _adaptive_atom_list.first().length(); chn++)
2948  {
2949  GaborAtom gabor_atom = _adaptive_atom_list.at(i + pdict_count * div).at(chn);
2950  QStringList result_list = gabor_atom.create_string_values(gabor_atom.sample_count, gabor_atom.scale, gabor_atom.sample_count / 2, gabor_atom.modulation, gabor_atom.phase);
2951 
2952  xmlWriter.writeStartElement("ATOM");
2953  xmlWriter.writeAttribute("ID", QString::number(i * _adaptive_atom_list.first().length() + chn));
2954  xmlWriter.writeAttribute("scale", QString::number(gabor_atom.scale));
2955  xmlWriter.writeAttribute("modu", QString::number(gabor_atom.modulation));
2956  xmlWriter.writeAttribute("phase", QString::number(gabor_atom.phase));
2957 
2958  xmlWriter.writeStartElement("samples");
2959  QString samples_to_xml;
2960  for (qint32 it = 0; it < result_list.length(); it++)
2961  {
2962  samples_to_xml.append(result_list.at(it));
2963  samples_to_xml.append(":");
2964  }
2965  xmlWriter.writeAttribute("samples", samples_to_xml);
2966  xmlWriter.writeEndElement(); //samples
2967 
2968  xmlWriter.writeEndElement(); //ATOM
2969  }
2970  }
2971  xmlWriter.writeEndElement(); //built_atoms
2972  }
2973  xmlWriter.writeEndElement(); //COUNT
2974  xmlWriter.writeEndDocument();
2975  }
2976  xml_file.close();
2977  fill_dict_combobox();
2978 }
2979 
2980 //*****************************************************************************************************************
2981 
2982 bool MainWindow::sort_energy_adaptive(const QList<GaborAtom> atom_1, const QList<GaborAtom> atom_2)
2983 {
2984  qreal energy_1 = 0;
2985  qreal energy_2 = 0;
2986 
2987  for(qint32 i = 0; i < atom_1.length(); i++)
2988  {
2989  energy_1 += atom_1.at(i).energy;
2990  energy_2 += atom_2.at(i).energy;
2991  }
2992  return (energy_1 > energy_2);
2993 }
2994 
2995 //*****************************************************************************************************************
2996 
2997 bool MainWindow::sort_energy_fix(const FixDictAtom atom_1, const FixDictAtom atom_2)
2998 {
2999  return (atom_1.energy > atom_2.energy);
3000 }
3001 
3002 //*****************************************************************************************************************
3003 
3004 void MainWindow::on_cb_Dicts_currentIndexChanged(const QString &arg1)
3005 {
3006  Q_UNUSED(arg1);
3007  ui->lb_info_content->clear();
3008  //ui->lb_info_content->repaint();
3009  has_warning = false;
3010 }
3011 
3012 //*****************************************************************************************************************
3013 
3014 void MainWindow::on_rb_adativMp_clicked()
3015 {
3016  ui->cb_Dicts->setEnabled(false);
3017  ui->lb_info_content->clear();
3018  if(_has_file)
3019  ui->btt_Calc->setEnabled(true);
3020  //ui->lb_info_content->repaint();
3021  has_warning = false;
3022 }
3023 
3024 //*****************************************************************************************************************
3025 
3026 void MainWindow::activate_info_label()
3027 {
3028  QSettings settings;
3029  if(!settings.value("show_infos", true).toBool())
3030  {
3031  ui->lb_info_content->setHidden(true);
3032  ui->lb_info->setHidden(true);
3033  }
3034  else
3035  {
3036  ui->lb_info_content->setHidden(false);
3037  ui->lb_info->setHidden(false);
3038  }
3039 }
3040 
3041 //*****************************************************************************************************************
3042 
3043 void MainWindow::on_dsb_energy_valueChanged(double arg1)
3044 {
3045  if(arg1 > 99.9)
3046  ui->dsb_energy->setValue(99.9);
3047 }
3048 
3049 //*****************************************************************************************************************
3050 
3051 void MainWindow::on_actionBeenden_triggered()
3052 {
3053  close();
3054 }
3055 
3056 //*****************************************************************************************************************
3057 
3058 void GraphWindow::mouseMoveEvent(QMouseEvent *event)
3059 {
3060  if(_to - _from != 0)
3061  {
3062  qint32 temp_pos_x = mapFromGlobal(QCursor::pos()).x() - 55;
3063  qint32 temp_pos_y = this->height() - mapFromGlobal(QCursor::pos()).y();
3064 
3065  qreal stretch_factor_x = (this->width() - 55/*left_margin*/ - 15/*right_margin*/) / qreal(_samplecount - 1);
3066  qreal stretch_factor_y = (this->height() - _border_margin_height) / _signal_maximum;
3067 
3068  qreal time = _from / _sample_rate + _offset_time + temp_pos_x / stretch_factor_x / _sample_rate;
3069  qreal amplitude = temp_pos_y / stretch_factor_y - (this->height() + _x_axis_height) / stretch_factor_y;
3070 
3071  if(mapFromGlobal(QCursor::pos()).x() >= 55 && mapFromGlobal(QCursor::pos()).x() <= (this->width() - 15))
3072  this->setToolTip(QString("time: %1 sec\namplitude: %2").arg(time).arg(QString::number(amplitude, 'g', 3)));
3073  else this->setToolTip(QString("amplitude: %1").arg(QString::number(amplitude, 'g', 3)));
3074 
3075  if(event->buttons() == Qt::LeftButton)
3076  setCursor(Qt::ClosedHandCursor);
3077  else
3078  setCursor(Qt::CrossCursor);
3079  }
3080 }
3081 
3082 //*****************************************************************************************************************
3083 
3084 void AtomSumWindow::mouseMoveEvent(QMouseEvent *event)
3085 {
3086  Q_UNUSED(event);
3087  if(_to - _from != 0)
3088  {
3089  qint32 temp_pos_x = mapFromGlobal(QCursor::pos()).x() - 55;
3090  qint32 temp_pos_y = this->height() - mapFromGlobal(QCursor::pos()).y();
3091 
3092  qreal stretch_factor_x = (this->width() - 55/*left_margin*/ - 15/*right_margin*/) / qreal(_samplecount - 1);
3093  qreal stretch_factor_y = (this->height() - _border_margin_height) / _signal_maximum;
3094 
3095  qreal time = _from / _sample_rate + _offset_time + temp_pos_x / stretch_factor_x / _sample_rate;
3096  qreal amplitude = temp_pos_y / stretch_factor_y - (this->height() + _x_axis_height) / stretch_factor_y;
3097 
3098  if(mapFromGlobal(QCursor::pos()).x() >= 55 && mapFromGlobal(QCursor::pos()).x() <= (this->width() - 15))
3099  this->setToolTip(QString("time: %1 sec\namplitude: %2").arg(time).arg(QString::number(amplitude, 'g', 3)));
3100  else this->setToolTip(QString("amplitude: %1").arg(QString::number(amplitude, 'g', 3)));
3101 
3102  setCursor(Qt::CrossCursor);
3103  }
3104 }
3105 
3106 //*****************************************************************************************************************
3107 
3108 void ResiduumWindow::mouseMoveEvent(QMouseEvent *event)
3109 {
3110  Q_UNUSED(event);
3111  if(_to - _from != 0)
3112  {
3113  qint32 temp_pos_x = mapFromGlobal(QCursor::pos()).x() - 55;
3114  qint32 temp_pos_y = this->height() - mapFromGlobal(QCursor::pos()).y();
3115 
3116  qreal stretch_factor_x = (this->width() - 55/*left_margin*/ - 15/*right_margin*/) / qreal(_samplecount - 1);
3117  qreal stretch_factor_y = (this->height() - _border_margin_height) / _signal_maximum;
3118 
3119  qreal time = _from / _sample_rate + _offset_time + temp_pos_x / stretch_factor_x / _sample_rate;
3120  qreal amplitude = temp_pos_y / stretch_factor_y - (this->height() + _x_axis_height) / stretch_factor_y;
3121 
3122  if(mapFromGlobal(QCursor::pos()).x() >= 55 && mapFromGlobal(QCursor::pos()).x() <= (this->width() - 15))
3123  this->setToolTip(QString("time: %1 sec\namplitude: %2").arg(time).arg(QString::number(amplitude, 'g', 3)));
3124  else this->setToolTip(QString("amplitude: %1").arg(QString::number(amplitude, 'g', 3)));
3125 
3126  setCursor(Qt::CrossCursor);
3127  }
3128 }
3129 
3130 //*****************************************************************************************************************
3131 
3132 void GraphWindow::mousePressEvent(QMouseEvent *event)
3133 {
3134  Q_UNUSED(event);
3135  if(_to - _from != 0)
3136  {
3137  _press_pos = mapFromGlobal(QCursor::pos()).x();
3138  setCursor(Qt::ClosedHandCursor);
3139  }
3140 }
3141 
3142 //*****************************************************************************************************************
3143 
3144 void GraphWindow::mouseReleaseEvent(QMouseEvent *event)
3145 {
3146  Q_UNUSED(event);
3147 
3148  if(_to - _from != 0)
3149  {
3150  fiff_int_t release_pos = mapFromGlobal(QCursor::pos()).x();
3151  qreal stretch_factor = qreal(this->width() - 55 - 15) / (qreal)(_samplecount);
3152  qint32 old_from = _from;
3153  qint32 old_to = _to;
3154  _from += floor((_press_pos - release_pos) / stretch_factor);
3155  _to = _from + _samplecount - 1;
3156  if(_from < _first_sample - _offset_time * _sample_rate)
3157  {
3158  _from = _first_sample - _offset_time * _sample_rate;
3159  _to = _from + _samplecount - 1;
3160  }
3161 
3162  if(_to > _last_sample - _offset_time * _sample_rate)
3163  {
3164  _to = _last_sample - _offset_time * _sample_rate;
3165  _from = _to - _samplecount + 1;
3166  }
3167 
3168  setCursor(Qt::CrossCursor);
3169 
3170  // +/- 5 pixel dont read new if clicked by mistake
3171  if(abs(_press_pos - release_pos) < 5 || old_from == _from || old_to == _to)
3172  return;
3173 
3174  emit read_new();
3175  }
3176 
3177 }
3178 
3179 //*****************************************************************************************************************
3180 
3181 void GraphWindow::wheelEvent(QWheelEvent *event)
3182 {
3183 
3184  if(_to - _from != 0)
3185  {
3186  _samplecount -= event->angleDelta().y() / 1.875 * _samplecount / 2048;
3187 
3188  if(_samplecount > 4096)
3189  _samplecount = 4096;
3190 
3191  if(_samplecount < 64)
3192  _samplecount = 64;
3193  if(_samplecount == _to - _from + 1)
3194  return;
3195 
3196  qreal stretch_factor = qreal(this->width() - 55/*left_margin*/ - 15/*right_margin*/) / (qreal)(_to - _from);
3197  qint32 temp_pos = mapFromGlobal(QCursor::pos()).x() - 55;
3198  qint32 actual_sample = _from + floor((qreal)temp_pos / stretch_factor);
3199  qint32 delta_from = (qreal)_samplecount * ((qreal)temp_pos / (qreal)(this->width() - 70));
3200 
3201  _from = actual_sample - delta_from;
3202 
3203  _to = _from + _samplecount - 1;
3204 
3205  if(_from < _first_sample - _offset_time * _sample_rate)
3206  {
3207  _from = _first_sample - _offset_time * _sample_rate;
3208  _samplecount = _to - _from + 1;
3209  }
3210 
3211  if(_to > _last_sample - _offset_time * _sample_rate)
3212  {
3213  _to = _last_sample - _offset_time * _sample_rate;
3214  _samplecount = _to - _from + 1;
3215  }
3216  emit read_new();
3217  }
3218 }
3219 
3220 //*****************************************************************************************************************
3221 
3222 void MainWindow::on_mouse_button_release()
3223 {
3224  if(QString::compare(ui->btt_Calc->text(), "cancel", Qt::CaseInsensitive) == 0 || QString::compare(ui->btt_Calc->text(), "wait...", Qt::CaseInsensitive) == 0)
3225  return;
3226  read_fiff_changed = true;
3227 
3228  ui->dsb_from->setValue(_from / _sample_rate + _offset_time);
3229  ui->dsb_to->setValue(_to / _sample_rate + _offset_time);
3230  ui->sb_sample_count->setValue(_samplecount);
3231 
3232  read_fiff_changed = false;
3233 
3234  if(file_name.split('.').last() == "fif")
3235  {
3236  if(!_pick_evoked.isEmpty())
3237  read_fiff_ave_new();
3238  else
3239  read_fiff_file_new(file_name);
3240  }
3241  else
3242  read_matlab_file_new();
3243 }
3244 
3245 void MainWindow::on_rb_OwnDictionary_clicked()
3246 {
3247  ui->cb_Dicts->setEnabled(true);
3248  if(ui->cb_Dicts->itemText(0) == "")
3249  ui->btt_Calc->setEnabled(false);
3250  else if(_has_file)
3251  ui->btt_Calc->setEnabled(true);
3252 }
void save_fif_file()
GaborAtom used in adaptive MP Algorithm.
Definition: atom.h:192
Definition: aboutwindow.h:52
void paint_axis(MatrixXd signalMatrix, QSize windowSize)
FiffInfo pick_info(const RowVectorXi &sel=defaultVectorXi) const
Definition: fiff_info.cpp:300
void paint_signal(MatrixXd signalMatrix, QSize windowSize)
FixDictAtom used in fix dict MP Algorithm.
Definition: atom.h:123
evoked data
Definition: fiff_evoked.h:91
RowVectorXf times
Definition: fiff_evoked.h:216
VectorXd create_real(qint32 sample_count, qreal scale, quint32 translation, qreal modulation, qreal phase)
Definition: atom.cpp:185
QSharedPointer< FiffStream > SPtr
Definition: fiff_stream.h:132
FIFF raw measurement data.
Definition: fiff_raw_data.h:94
The fixdictMP class provides functions several calculating functions to run the Matching Pursuit Algo...
Definition: fixdictmp.h:149
void paint_residuum(MatrixXd residuum_matrix, QSize windowSize, qreal maxPos, qreal maxNeg)
void paint_atom_sum(MatrixXd atom_matrix, QSize windowSize, qreal signalMaximum, qreal signalNegativeMaximum)
QStringList create_string_values(qint32 sample_count, qreal scale, qint32 translation, qreal modulation, qreal phase)
Definition: atom.cpp:124
RowVectorXi pick_types(const QString meg, bool eeg=false, bool stim=false, const QStringList &include=defaultQStringList, const QStringList &exclude=defaultQStringList) const
FiffEvoked pick_channels(const QStringList &include=defaultQStringList, const QStringList &exclude=defaultQStringList) const
The adaptiveMP class provides functions several calculating functions to run the Matching Pursuit Alg...
Definition: adaptivemp.h:105
void fill_dict_combobox()
Definition: mainwindow.cpp:840
FIFF class declaration, which provides static wrapper functions to stay consistent with mne matlab to...