BioSignalPi  v2
hrvwidget.cpp
Go to the documentation of this file.
1 #include "hrvwidget.h"
2 #include "sliderwidget.h"
3 #include "convertecgtoibi.h"
4 #include <plot.h>
5 #include <QtWidgets>
6 #include "hrvanalysis.h"
7 
8 #include <QDebug>
9 
10 #include <cmath>
11 #include <math.h>
12 #include <stddef.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include "HRV/timeDomainHRV_emxAPI.h"
16 #include "HRV/timeDomainHRV_terminate.h"
17 #include "HRV/timeDomainHRV_initialize.h"
18 #include "HRV/freqDomainHRV_types.h"
19 
20 
21 
22 HrvWidget::HrvWidget(QWidget *parent):
23 QWidget( parent )
24 {
25 
26 
27  setupComponents();
28  setupActions();
29  setupLayout();
30 }
31 
32 /*
33  * Load the supported ECG formats from the application directory.
34  *
35  * Supported formats: .txt, .edf, .bdf
36  */
37 void HrvWidget::getEcgFileList()
38 {
39  ecgFilesWidget->clear();
40 
41  QStringList nameFilter;
42  nameFilter << "*.txt";
43  nameFilter << "*.edf";
44  nameFilter << "*.bdf";
45  QDir directory(qApp->applicationDirPath());
46  QStringList ecgFiles = directory.entryList(nameFilter);
47 
48  ecgFilesWidget->addItems(ecgFiles);
49 }
50 
51 /*
52  * If a file is double-clicked, load it in a different thread to prevent locking the GUI
53  */
54 void HrvWidget::fileSelected(QListWidgetItem *item)
55 {
56  tlbl->setText("Loading "+item->text());
57  progBar->setVisible(true);
58  progBar->setRange(0,0);
59  progBar->setValue(0);
60 
61  ConvertEcgToIbi *loadFile = new ConvertEcgToIbi(item->text());
62 
63  connect(loadFile, SIGNAL(sendFileData(QVector<double>, QVector<double>)), this, SLOT(performHRV(QVector<double>, QVector<double>)));
64  connect(loadFile,SIGNAL(finished()),SLOT(fileFinished()));
65  loadFile->start();
66  headerTextArea->setText("Performing HRV-Calculations");
67  //Read header file and display information about the recording
68  QFileInfo fInfo(item->text());
69  QFile headerFile(fInfo.baseName()+"_header.txt");
70  if (headerFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
71  QTextStream headerTextStream(&headerFile);
72  QString headerText;
73 
74  while (!headerTextStream.atEnd()) {
75  headerText += headerTextStream.readLine() + "\n";
76  }
77 
78  headerTextArea->setText(headerText);
79  headerTextStream.flush();
80  headerFile.close();
81  }
82  performHRV(fInfo.baseName());
83 
84 
85 
86 }
87 
88 void HrvWidget::saveFreqHrv(const structFreq_T *tobeSaved){
89  QFile outFile("outputFreqHRV.txt");
90  if (!outFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
91  qDebug() << "Failed to open data file for write" << endl;
92  } else {
93  QTextStream out(&outFile);
94  for (int i=0; i<512; i++){
95  out << QString::number(tobeSaved->lomb.f[i], 'f', 3) << "\t"
96  << QString::number(tobeSaved->lomb.psd[i], 'f', 3) << "\n";
97  }
98  outFile.close();
99  }
100 }
101 
102 void HrvWidget::performHRV(QString fileInfo) {
103  QFile ibiFile(fileInfo+".txt_RR.txt");
104  if (ibiFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
105  QTextStream ibiTextStream(&ibiFile);
106 
107  int i=0;
108  QString strVals = ibiTextStream.readLine();
109  QStringList strPieces = strVals.split(QRegularExpression("\\s+"));
110  QVector <double> ibiData;
111  QVector <double> timeData;
112  while (!ibiTextStream.atEnd()) {
113  strVals = ibiTextStream.readLine();
114  strPieces = strVals.split(QRegularExpression("\\s+"));
115 
116  if (strPieces.length()==3) {
117  ibiData.append(strPieces[2].toDouble());
118  timeData.append(strPieces[1].toDouble());
119  }
120  else if (strPieces.length()==2) {
121  ibiData.append(strPieces[1].toDouble());
122  timeData.append(strPieces[0].toDouble());
123  }
124  }
125  struct0_T outputTime;
126  performTimeDomainHrv(&ibiData, &outputTime);
127  structFreq_T outputFreq;
128  performFreqDomainHrv(&ibiData, &timeData, &outputFreq);
129  psdPlot(&outputFreq);
130  printHRV(&outputTime);
131  printHRV(&outputFreq);
132  saveFreqHrv(&outputFreq);
133 
134 
135  ibiTextStream.flush();
136  ibiFile.close();
137  }
138 
139 
140 }
141 
142 void HrvWidget::performHRV(QVector<double> ibiData, QVector<double> timeData){
143  struct0_T outputTime;
144  performTimeDomainHrv(&ibiData, &outputTime);
145  structFreq_T outputFreq;
146  performFreqDomainHrv(&ibiData, &timeData, &outputFreq);
147  psdPlot(&outputFreq);
148  printHRV(&outputTime);
149  printHRV(&outputFreq);
150  saveFreqHrv(&outputFreq);
151 
152 }
153 
154 void HrvWidget::printHRV(const struct0_T *outputHrv){
155  qDebug() << "Max: " << outputHrv->max << endl
156  << "Mean HR: " << outputHrv->meanHR << endl
157  << "SDNN: " << outputHrv->SDNN << endl
158  << "SDANN: " << outputHrv->SDANN << endl
159  << "Mean: " << outputHrv->mean << endl
160  << "Min: " << outputHrv->min << endl
161  << "Median: " << outputHrv->median << endl;
162  QString headerText;
163  headerTextArea->setText("<b>Time Domain Statistics: </b>");
164  headerText=+ "Max: " + QString::number(outputHrv->max, 'f', 3);
165  headerTextArea->append(headerText);headerText=+ "Mean HR: " + QString::number(outputHrv->meanHR, 'f', 3);
166  headerTextArea->append(headerText);headerText=+ "SDNN: " + QString::number(outputHrv->SDNN, 'f', 3);
167  headerTextArea->append(headerText);headerText=+ "SDANN: " + QString::number(outputHrv->SDANN, 'f', 3);
168  headerTextArea->append(headerText);headerText=+ "Mean: " + QString::number(outputHrv->mean, 'f', 3);
169  headerTextArea->append(headerText);headerText=+ "Min: " + QString::number(outputHrv->min, 'f', 3);
170  headerTextArea->append(headerText);headerText=+ "Median: " + QString::number(outputHrv->median, 'f', 3);
171  headerTextArea->append(headerText);
172 
173 }
174 
175 void HrvWidget::printHRV(const structFreq_T *outputHrv){
176  qDebug() << outputHrv->lomb.hrv.aHF << endl
177  << outputHrv->lomb.hrv.aHF << endl
178  << outputHrv->lomb.hrv.nLF << endl
179  << outputHrv->lomb.hrv.nHF << endl
180  << outputHrv->lomb.hrv.aTotal << endl
181  << outputHrv->lomb.hrv.aLF << endl
182  << outputHrv->lomb.hrv.LFHF << endl
183  << outputHrv->lomb.hrv.pVLF << endl;
184  mainTextArea->append("<b> Frequency Domain Statistics </b>");
185  mainTextArea->append("LF / HF: " + QString::number(outputHrv->lomb.hrv.LFHF, 'f', 3));
186  mainTextArea->append("Power HF: " + QString::number(outputHrv->lomb.hrv.pHF, 'f', 3) + "%");
187  mainTextArea->append("Power LF: " + QString::number(outputHrv->lomb.hrv.pLF, 'f', 3)+ "%");
188  mainTextArea->append("Power VLF: " + QString::number(outputHrv->lomb.hrv.pVLF, 'f', 3) + "%");
189  // myCurve->setRenderHint( QwtPlotItem::RenderAntialiased );
190  myCurve->setPen( Qt::blue );
191  // myCurve->setLegendAttribute( QwtPlotCurve::LegendShowLine );
192  // myCurve->setYAxis( QwtPlot::yLeft );
193 
194  myCurve->setSamples(outputHrv->lomb.f,outputHrv->lomb.psd,100);
195  //myCurve->setSamples(freq,psd,100);
196  myCurve->attach(lombPlot);
197  lombPlot->replot();
198 }
199 
200 
205 void HrvWidget::psdPlot(const structFreq_T *tobePloted) {
206  double mean_Freq=0,mean_psd=0;
207  int index=5;
208  for (int i=0; i<102; i++) {
209  for (int j=0; j<10;j++) {
210  mean_Freq+=tobePloted->lomb.f[index+j-5];
211  mean_psd+=tobePloted->lomb.psd[index+j-5];
212 
213  }
214  index++;
215  freq[i]=mean_Freq/10;
216  psd[i]=mean_psd/10;
217  mean_Freq=0;
218  mean_psd=0;
219  }
220 
221 }
225 void HrvWidget::clearPlot()
226 {
227 
228  lombPlot->repaint();
229 
230 }
231 
232 
233 
234 
235 void HrvWidget::fileFinished(){
236  tlbl->setText("Done!");
237  progBar->setMaximum(10);
238  progBar->setValue(10);
239 }
240 
241 
242 
243 
244 
248 void HrvWidget::setupComponents()
249 {
250 
251 
252  //Buttons
253  getFilesButton = new QPushButton("Get ECG files");
254  resetPlotButton = new QPushButton("Reset plot");
255 
256  //Header text area
257  headerTextArea = new QTextBrowser();
258  headerTextArea->setMinimumWidth(250);
259 
260  //Main text Area
261  mainTextArea = new QTextBrowser();
262 
263  //Progressbar label
264  tlbl = new QLabel("No file selected");
265 
266  //List of ecg files
267  ecgFilesWidget = new QListWidget;
268  ecgFilesWidget->setFixedSize(QSize(QWIDGETSIZE_MAX,100));
269 
270  //Lomb Plot
271  lombPlot=new QwtPlot(this);
272  lombPlot->setTitle("Lomb");
273  lombPlot->setFixedSize(QSize(QWIDGETSIZE_MAX,300));
274  myCurve = new QwtPlotCurve( "Lomb" );
275 
276 
277  //Progress bar
278  progBar = new QProgressBar();
279  progBar->setRange(0,0);
280  progBar->setVisible(false);
281  progBar->setTextVisible(false);
282 
283 
284 
285 }
286 
290 void HrvWidget::setupActions()
291 {
292 
293  //Signals-slots
294  connect(resetPlotButton, SIGNAL(clicked()), this, SLOT(clearPlot()));
295  connect(ecgFilesWidget, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(fileSelected(QListWidgetItem*)));
296  connect(getFilesButton, SIGNAL(clicked()), this, SLOT(getEcgFileList()));
297 
298 }
299 
303 void HrvWidget::setupLayout()
304 {
305 
306 
307 
308 
309  //Progressbar area
310  QHBoxLayout *progressBarLayout = new QHBoxLayout;
311  progressBarLayout->addWidget(tlbl, 2);
312  progressBarLayout->addWidget(progBar, 8);
313 
314 
315 
316  //Area with navigation control components
317  QHBoxLayout *playbackLayout = new QHBoxLayout;
318 
319 
320 
321  //Sidebar layout
322  QVBoxLayout *sidebarLayout = new QVBoxLayout;
323  sidebarLayout->addWidget(getFilesButton);
324  sidebarLayout->addWidget(ecgFilesWidget);
325  sidebarLayout->addLayout(progressBarLayout);
326  sidebarLayout->addWidget(headerTextArea);
327  sidebarLayout->addStretch();
328  sidebarLayout->addWidget(resetPlotButton);
329 
330  //Plot layout
331  QVBoxLayout *plotLayout = new QVBoxLayout;
332  plotLayout->addWidget(lombPlot);
333  plotLayout->addWidget(mainTextArea);
334 
335 
336 
337  //Main layout
338  QHBoxLayout *mainLayout = new QHBoxLayout;
339 
340  mainLayout->addLayout(sidebarLayout, 1);
341  mainLayout->addLayout(plotLayout, 9);
342 
343  setLayout(mainLayout);
344 
345 
346 }
Collection of functions used to interact with the Matlab Coder generated HRV-functions.
void performTimeDomainHrv(const QVector< double > *ibiData, struct0_T *output)
Performs the Statistical Time Domain calculations for HRV Analysis.
Definition: hrvanalysis.cpp:34
Converts textfile with ECG-data into IBI file.
HrvWidget(QWidget *=NULL)
Definition: hrvwidget.cpp:22
void performFreqDomainHrv(const QVector< double > *ibiData, const QVector< double > *timeData, structFreq_T *output)
Performs calculations for Frequency Domain HRV Analysis.
Definition: hrvanalysis.cpp:62