As already shown at Qt/LVL/Signal Power Tool page, application contains:
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include < QMainWindow > #include "filterdialog.h" QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: Ui::MainWindow *ui; FilterDialog* myFilter; QVectorti, ch_1; private slots: // 1st TAB:: SDOF void cmdSysClicked(); void cmdClearClicked(); void cmdCLRAClicked(); void yAxisScaler(); void xAxisScaler(); void logAxis(); // 2nd TAB:: RAND void on_cmdRead_clicked(); //| read the psd table into the programm and plot it .... void on_slddB_valueChanged(); //| slider changes dB borders -> solved with secret lblSalic void on_editAxis(); //| editing axis minimum and maxium right side of the plot -> problem if field empty .. void on_clr_table(); //| Clear all data from table void on_addTableRow(); //| Add row to the table * last void on_removeTableRow(); //| Delete row from the table *last void on_insertSignal(); //| provide the file for inserting data ... void on_cmdScaleFs(); //| rescale the X axis from samples to time instances ... void on_WidowMovement(); //| when moving te window through the signal ... void on_cmdScaleN(); //| when scaling back to domain of samples void DSP_process(); //| determines which checkboxes are on// off, copy spectrum ... void clearSignal(); //| clears all vectors and graphs .. void logSignalAxis(); //| logarithmic small window axis manipulator function void on_cmdCSpect(); //| plot spectrum to the profile window }; #endif // MAINWINDOW_H
#include "mainwindow.h" #include "ui_mainwindow.h" #include < QMessageBox > #include < QDebug > #include < QtMath > #include < QSharedPointer > #include < QDialog > #include "sdof_analytic.h" #include "IOSignal.h" #include "filter.h" #include "dialog.h" #include "filterdialog.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); // TAB::: SDOF // // //*********************************************************************| // x and y axis scalers ui->dialYaxis->setMaximum(100); ui->dialYaxis->setMinimum(0); ui->dialXaxis->setMaximum(10); ui->dialXaxis->setMinimum(0); // y radio buttons:: not exclusive ui->radioLogX->setAutoExclusive(false); ui->radioLogY->setAutoExclusive(false); ui->radYlogS->setAutoExclusive(false); ui->radXlogS->setAutoExclusive(false); // connect the radiobuttons connect(ui->cmdSys, SIGNAL(clicked()), SLOT(cmdSysClicked())); connect(ui->cmdClear, SIGNAL(clicked()), SLOT(cmdClearClicked())); connect(ui->cmdCLRA, SIGNAL(clicked()),SLOT(cmdCLRAClicked())); // connect the scaling connect(ui->dialYaxis ,SIGNAL(valueChanged(int)),SLOT(yAxisScaler())); connect(ui->dialXaxis ,SIGNAL(valueChanged(int)),SLOT(xAxisScaler())); // connect radio buttons::: both call the same function logAxis connect(ui->radioLogX,SIGNAL(clicked()), SLOT(logAxis())); connect(ui->radioLogY,SIGNAL(clicked()), SLOT(logAxis())); // TAB::: PSD Analysis // // //*********************************************************************| ui->slddB->setMaximum(0); ui->slddB->setMaximum(10); connect(ui->slddB,SIGNAL(valueChanged(int)),SLOT(on_slddB_valueChanged())); connect(ui->edtmaxY, SIGNAL(editingFinished()),SLOT(on_editAxis())); connect(ui->cmdYRescale, SIGNAL(clicked()),SLOT(on_editAxis())); connect(ui->cmdCLR, SIGNAL(clicked()),SLOT(on_clr_table())); connect(ui->cmdREM, SIGNAL(clicked()),SLOT(on_removeTableRow())); connect(ui->cmdADD, SIGNAL(clicked()),SLOT(on_addTableRow())); connect(ui->toolIOSignal, SIGNAL(clicked()),SLOT(on_insertSignal())); // edit sampling time connect(ui->cmdScaleFs,SIGNAL(clicked()), SLOT(on_cmdScaleFs())); connect(ui->sldTimeLine,SIGNAL(valueChanged(int)),SLOT(on_WidowMovement())); connect(ui->cmdScaleN, SIGNAL(clicked()), SLOT(on_cmdScaleN())); connect(ui->cmdProcess,SIGNAL(clicked()), SLOT(DSP_process())); connect(ui->cmdDel, SIGNAL(clicked()), SLOT(clearSignal())); //| connect radio buttons for scalng Signal/DFT window) connect( ui->radYlogS, SIGNAL(clicked()), SLOT(logSignalAxis())); connect( ui->radXlogS, SIGNAL(clicked()), SLOT(logSignalAxis())); //| connect spec. plotter to the main plot ...spectral plot connect(ui->cmdCSpect, SIGNAL(clicked()),SLOT(on_cmdCSpect())); } MainWindow::~MainWindow() { delete ui; } //| ------------------------------------------------------ TAB 1 //| //| // clear the plot void MainWindow::cmdClearClicked() { ui->Plot1->graph(0)->clearData(); QVectorx,y; ui->Plot1->graph(0)->setData(x,y); ui->Plot1->update(); ui->Plot1->rescaleAxes(); ui->Plot1->replot(); ui->Plot2->graph(0)->setData(x,y); ui->Plot2->update(); ui->Plot2->rescaleAxes(); ui->Plot2->replot(); } // clear table CLR void MainWindow::cmdCLRAClicked() { ui->lstAnalysis->clear(); } // manipulating yAxisScaler void MainWindow::yAxisScaler() { double yScale = ui ->dialYaxis->value(); double Qfact = ui->edtQ->text().toDouble(); double yrange = (1+0.01*yScale)*Qfact; ui -> lblSlider2 -> setText(QString("%1").arg(yrange)); ui->Plot1->yAxis->setRange(0, yrange); ui->Plot1-> replot(); } // manipulationg xAxisSclaer void MainWindow::xAxisScaler() { double i = ui->dialXaxis->value(); double f = ui->edtR->text().toDouble(); double xrange = f*((10-i)/10); ui -> lblSlider -> setText(QString("%1").arg(i)); ui->Plot1->xAxis->setRange(f-xrange, f+xrange); ui->Plot1-> replot(); } // manipulate radio buttons for setting up the log. axis void MainWindow::logAxis() { // Chece when button clicked if( ui->radioLogY->isChecked()){ ui->Plot1->yAxis->setScaleType(QCPAxis::stLogarithmic); ui->Plot1->update(); ui->Plot1->rescaleAxes(); ui->Plot1->replot(); } else if(ui->radioLogY->isChecked()==false) { ui->Plot1->yAxis->setScaleType(QCPAxis::stLinear); ui->Plot1->update(); ui->Plot1->rescaleAxes(); ui->Plot1->replot(); } if(ui->radioLogX->isChecked()==true) { ui->Plot1->xAxis->setScaleType(QCPAxis::stLogarithmic); ui->Plot1->update(); ui->Plot1->rescaleAxes(); ui->Plot1->replot(); } else if(ui->radioLogX->isChecked()==false) { ui->Plot1->xAxis->setScaleType(QCPAxis::stLinear); ui->Plot1->update(); ui->Plot1->rescaleAxes(); ui->Plot1->replot(); } } void MainWindow::cmdSysClicked() { // take the UI inputs double fstart= ui->edtStart->text().toDouble(); double fend = ui->edtEnd->text().toDouble(); double fr = ui->edtR->text().toDouble(); double q = ui->edtQ->text().toDouble(); double N = ui->edtN->text().toDouble(); // create an SDOF - object ... Sdof_analytic sys(fstart, fend, fr, q, N); sys.FRF_THIS(); vector frf = sys.getFRFVector(); QVector y = QVector (frf.begin(), frf.end()); QVector x,xd; double df = (fend-fstart)/N; double f=0; double disp; for(int j = 0; j < y.size(); j++) { x.push_back(f); f +=df; disp = y[j]/pow((2*M_PI*f),2); xd.push_back(disp); } // Add Graphs ui->Plot1->addGraph(); ui->Plot1->graph(0)->setPen(QPen(Qt::black, 1)); ui->Plot1->graph(0)->setData(x,y); ui->Plot1->update(); ui->Plot1->rescaleAxes(); ui->Plot1->replot(); ui->Plot1->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom); ui->Plot2->addGraph(); ui->Plot2->graph(0)->setPen(QPen(Qt::red, 1.5)); ui->Plot2->xAxis->setScaleType(QCPAxis::stLogarithmic); ui->Plot2->yAxis->setScaleType(QCPAxis::stLogarithmic); ui->Plot2->graph(0)->setData(x,xd); ui->Plot2->update(); ui->Plot2->rescaleAxes(); ui->Plot2->replot(); ui->Plot2->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom); // ADAPTER:: reuse cout << str()/ofstream and plug it in Q String; string s = sys.sdof_info(); QString qstr = QString::fromStdString(s); ui->lstAnalysis->addItem(qstr); } //edit axis.. on the right side void MainWindow::on_editAxis() { double min_y, max_y, min_x, max_x; min_y = ui->edtminY->text().toDouble(); max_y = ui->edtmaxY->text().toDouble(); min_x = ui->edtminX->text().toDouble(); max_x = ui->edtmaxX->text().toDouble(); ui->Plot3->xAxis->setRange(0.85*min_x,max_x*1.15); ui->Plot3->update(); ui->Plot3->replot(); ui->Plot3->yAxis->setRange(min_y,max_y); ui->Plot3->update(); ui->Plot3->replot(); } //| ------------------------------------------------------ TAB 2 //| //| void MainWindow::on_cmdCSpect() { //|||||||||||||||||||||||||||| conditions to activate the process is ...same as DFT/PSD // if psd is checked // if i have the window size // and sampling frequency if( ui->chkPSD->isChecked() && !ui->edtWinSize->text().isEmpty() && !ui->edtFs->text().isEmpty() ) { ui->chkDFT->setChecked(true); //| IF PSD chekbox is on //| turn the DFT chekbox also on .. // check whether signal is in frequency domain, samples not accepted if( ui->lblXSignal->text() =="t[sec]") { double N = ui->edtWinSize->text().toDouble(); double x1 = ui->sldTimeLine->value(); double Fs = ui->edtFs->text().toDouble(); vector win; for(int i = 0; i to |-> QVector vector XDFT = SOUT4Q(channel01); // signal out for Q QVector x_dft = QVector (XDFT.begin(), XDFT.end()); //| Make the frequency axis QVector f_vec; double fi=0; double df = channel01.fs/N; for(int i =0; i< x_dft.size(); i++) //| x_dft.size == N/2 ! { fi += df; f_vec.push_back(fi); } QVector x_psd; double psd_i; // dft to psd ... for(int i=0; i < x_dft.size() ; i++) { // ( m/s² )² / Hz psd_i = pow(x_dft[i], 2)/df; x_psd.push_back(psd_i); } /* dakle ako se profil ucita */ if(ui->lblSalic->text()=="" ) { //if time signal is here and no profile has beeen created // plot the spectrum as it is .. ui->Plot3->addGraph(); ui->Plot3->graph(3)->setPen(QPen(Qt::darkGray, 1)); ui->Plot3->graph(3)->setData(f_vec,x_psd); ui->Plot3->update(); ui->Plot3->replot(); } else if( ui->lblSalic->text()=="...") // no profile inside the screen plot3 is empty { ui->Plot3->addGraph(); ui->Plot3->graph(0)->setPen(QPen(Qt::red, 2)); ui->Plot3->graph(0)->setData(f_vec,x_psd); ui->Plot3->rescaleAxes(); ui->Plot3->update(); ui->Plot3->replot(); qInfo() << "text()==..."; qInfo() << f_vec[100] <<", " << x_psd[100]; } else if(ui->lblSalic->text()=="" && ui->slddB->value()!=0) // ocito startni slddB nije 0 { ui->Plot3->addGraph(); ui->Plot3->graph(3)->setPen(QPen(Qt::darkGray, 1)); ui->Plot3->graph(3)->setData(f_vec,x_psd); ui->Plot3->update(); ui->Plot3->replot(); } } } // qInfo()<<"||||||||||||||||||||||||||| end of function ... "; }// end of function void MainWindow::logSignalAxis() { if( ui->radXlogS->isChecked()) { ui->Plot5->xAxis->setScaleType(QCPAxis::stLogarithmic); ui->Plot5->update(); ui->Plot5->rescaleAxes(); ui->Plot5->replot(); } else if( ui->radXlogS->isChecked()==false) { ui->Plot5->xAxis->setScaleType(QCPAxis::stLinear); ui->Plot5->update(); ui->Plot5->rescaleAxes(); ui->Plot5->replot(); } if( ui->radYlogS->isChecked()) { ui->Plot5->yAxis->setScaleType(QCPAxis::stLogarithmic); ui->Plot5->update(); ui->Plot5->rescaleAxes(); ui->Plot5->replot(); }else if (ui->radYlogS->isChecked()==false) { ui->Plot5->yAxis->setScaleType(QCPAxis::stLinear); ui->Plot5->update(); ui->Plot5->rescaleAxes(); ui->Plot5->replot(); } } void MainWindow::on_cmdScaleN() { ui->edtFs->setText(""); ui->lblXSignal->setText("sample [n]"); ui->lblSTime->setText("Samples:"); ui->lblTs->setText(QString::number(ch_1.size())); ui->lblUnitTs->setText(""); ui->lblSecret->setText("[n]"); // return the signal to the ti.clear(); for(int i = 0; i< ch_1.size();i ++){ ti.push_back(i); }; double max = *std::max_element(ch_1.constBegin(),ch_1.constEnd()); ui->Plot4->graph(0)->setPen(QPen(Qt::red, 1)); ui->Plot4->graph(0)->setData(ti,ch_1); ui->Plot4->update(); ui->Plot4->rescaleAxes(); ui->Plot4->yAxis->setRange(-max*1.2, max*1.2); ui->Plot4->replot(); } void MainWindow::on_WidowMovement() { //| if no data about sampling frequency //| if no signal input //| slider set to <1,1000> //| if signal is in the program //| slider goes up to the last sample number //| if window size is also known //| slider goes to range (signal size - window size) //| on slider movement show window // if sampling frequency is NOT known if( ui->edtFs->text().isEmpty()) { ui->sldTimeLine->setMinimum(1); if(ch_1.size()==0) // and vector is empty { ui->sldTimeLine->setMaximum(1000); //| set maximum of slider to 1e3 } else { ui->sldTimeLine->setMaximum(ch_1.size()); //| else set to sinal size if(!ui->edtWinSize->text().isEmpty() && ui->lblXSignal->text()=="sample [n]") //| if window-size edit filed is NOT empty { //| AND we have samples on X axis // Take the window size in samples and proceed with computations... double winSize = ui->edtWinSize->text().toDouble(); ui->sldTimeLine->setMaximum(ch_1.size()-winSize); int win_0 = ui->sldTimeLine->value(); int win_e = win_0 + winSize; QVector BL,xl; //| aux vectors for showing the window double max = *std::max_element(ch_1.constBegin(),ch_1.constEnd()); double cursorScale = 1.15; BL.push_back(-max*cursorScale); BL.push_back(max*cursorScale); BL.push_back(max*cursorScale); BL.push_back(-max*cursorScale); xl.push_back(win_0); xl.push_back(win_0); xl.push_back(win_e); xl.push_back(win_e); ui->lblWinMin->setText(QString::number(win_0)); ui->lblWinMax->setText(QString::number(win_e)); ui->Plot4->addGraph(); ui->Plot4->graph(1)->setData(xl,BL); ui->Plot4->graph(1)->setPen(QPen(Qt::black, 1)); ui->Plot4->update(); ui->Plot4->replot(); BL.clear(); xl.clear(); }// end of case::window size konwn and samples on the x axis .. }// end vector not empty ... }// end if sampling frequency added // if sampling frequency IS GIVEN if( !ui->edtFs->text().isEmpty() && !ui->edtWinSize->text().isEmpty() && ui->lblXSignal->text() =="t[sec]") { //| if sampling frequency is NOT empty, AND you have window size //| and you have the "t[sec]" on X Axis //| set labels reight to X axis double fs = ui->edtFs->text().toDouble(); double ts = 1/fs; //| set slider to signal size ... ui->sldTimeLine->setMaximum(ch_1.size()); //| else set to sinal size double winSize = ui->edtWinSize->text().toDouble(); //| window size in samples ... double winSizeT = winSize*ts; //| window size in seconds ... ui->sldTimeLine->setMaximum(ch_1.size()-winSize); //| slider takes the same windowsize ..in samples double win_0T = ui->sldTimeLine->value()*ts; //| window starting time in sec double win_eT = win_0T + winSizeT; //| window end time in sec QVector BT,xt; double max = *std::max_element(ch_1.constBegin(),ch_1.constEnd()); //| take maximum in signal scale it up 15% + double cursorScale = 1.15; BT.push_back(-max*cursorScale); BT.push_back(max*cursorScale); BT.push_back(max*cursorScale); BT.push_back(-max*cursorScale); xt.push_back(win_0T); xt.push_back(win_0T); xt.push_back(win_eT); xt.push_back(win_eT); double TO_MSEC =1000; // sale values by factor to get secons/mseconds ui->lblWinMin->setText(QString::number(win_0T*TO_MSEC)); ui->lblWinMax->setText(QString::number(win_eT*TO_MSEC)); ui->lblSecret->setText(" =" + QString::number(winSizeT*TO_MSEC) + " [msec]"); ui->Plot4->addGraph(); ui->Plot4->graph(1)->setData(xt,BT); ui->Plot4->graph(1)->setPen(QPen(Qt::darkGreen, 1)); ui->Plot4->update(); ui->Plot4->replot(); BT.clear(); xt.clear(); } else if(!ui->edtFs->text().isEmpty() && ui->edtWinSize->text().isEmpty() && ui->lblXSignal->text() =="t[sec]") { //| if sampling frequency is NOT empty, AND DON'T have window size //| and you have the "t[sec]" on X Axis //| Enter number of samples to get the time window try { QMessageBox popup; popup.setText("Enter 'Window Size' to slide the window through signal.. "); popup.exec(); }catch (exception &e) { } } //| if window ChkBox is on:: zoom what is in the windwo ...in time or samples if( ui->chkWin->isChecked() && !ch_1.isEmpty()) { //if window size is given if(!ui->edtWinSize->text().isEmpty()) { double winSize = ui->edtWinSize->text().toDouble(); double win0 = ui->sldTimeLine->value(); double wine = winSize + win0; QVector x_temp; QVector y_temp; ui->Plot5->addGraph(); ui->Plot5->graph(0)->clearData(); //|||| Time Series:: from Window & but no sampling frequency if(ui->edtFs->text().isEmpty()) { //| sampling frequency field is empty => use samples for(int i = win0; i edtFs->text().isEmpty()) //| sampling frequency file is not empty .. use time vector { // scale the x axis .. double fs = ui->edtFs->text().toDouble(); for(int i = win0; i Plot5->graph(0)->setData(x_temp,y_temp); ui->Plot5->update(); ui->Plot5->rescaleAxes(); ui->Plot5->yAxis->setRange(-maxy*1.5, maxy*1.5); ui->Plot5->replot(); // clear vectors x_temp.clear(); y_temp.clear(); } } // if you want to process frame on slider movements uncomment this conditions if( !ui->edtFs->text().isEmpty() && !ch_1.empty() && !ui->edtWinSize->text().isEmpty() && ui->chkWin->isChecked() ) { //....| if there is a sampling frequency //......| and if channel values are within the //..........| and if edtWinSize if( ui->chkDFT->isChecked() || ui->chkPSD->isChecked()) { //.....| if any of the chkBoxes is on .. activate DSP_process() function ... //..... //DSP_process(); } } if(!ui->chkDFT->isChecked()) { ui->lblWinX2->setText("{-}"); } }// end of whole function on_WindowMovement(); // IF cmdProcess clicked this is called as -> DSP_process(0/1) void MainWindow::DSP_process() { if( ui->chkPSD->isChecked()) { ui->chkDFT->setChecked(true); //| IF PSD chekbox is on } //| turn the DFT chekbox also on .. // INPUT :: take the window from signal, take the inputs from the ui double N = ui->edtWinSize->text().toDouble(); double x1 = ui->sldTimeLine->value(); double Fs = ui->edtFs->text().toDouble(); vector win; for(int i = 0; i chkDFT->isChecked() && ui->chkWin->isChecked() && !ui->edtFs->text().isEmpty()) { // make the dsp channel IOSignal channel00; channel00.fs = Fs; channel00.inputRe(win); DFT(channel00); //| see IOSignal.h for the model reference //| std::vector to |-> QVector vector XDFT = SOUT4Q(channel00); QVector x_dft = QVector (XDFT.begin(), XDFT.end()); //| make the frequency axis QVector f_vec; double fi=0; double df = channel00.fs/N; for(int i =0; i< x_dft.size(); i++) //| x_dft.size == N/2 ! { fi += df; f_vec.push_back(fi); } double max = *std::max_element(x_dft.constBegin(),x_dft.constEnd()); ui->Plot5->graph(0)->setPen(QPen(Qt::darkGreen, 1)); ui->Plot5->yAxis->setRange(-max*0.2, max*1.2); //| if is to be computd ||||||||||||||||||||||||||||||||______PSD checkbox ..| if( ui->chkPSD->isChecked() ) { QVector x_psd; double psd_i; for(int i=0; i < x_dft.size() ; i++) { // ( m/s² )² / Hz psd_i = pow(x_dft[i], 2)/df; x_psd.push_back(psd_i); } for(int i=0; i < x_dft.size() ; i++) { //| vector swap psd_i = x_psd[i]; x_dft[i] = psd_i; } ui->Plot5->graph(0)->setPen(QPen(Qt::black, 1)); } //| converter of the vector -> QVector ui->Plot5->graph(0)->setData(f_vec,x_dft); ui->Plot5->update(); ui->Plot5->rescaleAxes(); ui->Plot5->replot(); ui->Plot5->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom); ui->Plot5->graph(0)->setPen(QPen(Qt::darkRed, 1)); ui->lblWinX2->setText("{Hz}"); } else if(!ui->chkDFT->isChecked()) { ui->lblWinX2->setText("{-}"); } /* |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||____ LPF checkbox | */ //|---- if Low pass filter is on and sampling frequency is given ... if(ui->chkLPF->isChecked() && !ui->edtFs->text().isEmpty() ) { // POP UP DIALOG********************* Filter Cutoff // // pop up filter dialog for setting up the filter on the channel .. //************************************************************************** FilterDialog myFilter; myFilter.setModal(true); myFilter.exec(); //************************************************************************** if(myFilter.submitPressed==true) //| if user accepts the { double fcut = myFilter.getCutoff(); //| Take user entered cutoff frequency DEQ filterSystem; //| Setup teh differential equations ... Coeff lpf = LPF_butter(fcut,Fs); //| LPF filter butterworth ... QVector y_filt; //| filtered signal y_filt; for(int i =0; i < ch_1.size(); i++) { y_filt.push_back(filterSystem.process(lpf, ch_1[i])); } // Plot the filtered signal upon the existing ui->Plot4->addGraph(); ui->Plot4->graph(1)->setPen(QPen(Qt::darkGreen, 0.8)); ui->Plot4->graph(1)->setData(ti,y_filt); ui->Plot4->update(); ui->Plot4->replot(); // POP UP DIALOG********************* Accepting the filtered signal ... // CONFIRM FILTERING // pop up filter dialog for setting up the filter on the channel .. //************************************************************************** Dialog IsThisOk; IsThisOk.setModal(true); IsThisOk.exec(); // if user accepts the results of LPF if(IsThisOk.Accepted == true) { //| take filtered data to global vector //| then clear the graphs ui->Plot4->graph(0)->clearData(); ui->Plot4->graph(1)->clearData(); ui->Plot4->update(); ui->Plot4->replot(); // then set the data again .. ui->Plot4->graph(0)->setData(ti,y_filt); ui->Plot4->update(); ui->Plot4->replot(); double temp; //ch_1.clear(); for(int i=0; i< ch_1.size(); i++) { temp = y_filt[i]; ch_1[i] = temp; } } // turn the filter off ui->chkLPF->setChecked(false); } } }// end of DSP_process(); // CLEAR all vectors and graphs in signal void MainWindow::clearSignal() { // if there is a signal in the program if( !ch_1.empty()) { // clear global vectors ch_1.clear(); ti.clear(); // ckear plots ui->Plot4->graph(0)->setData(ti,ch_1); ui->Plot4->graph(1)->clearData(); ui->Plot4->graph(2)->clearData(); ui->Plot4->update(); ui->Plot4->replot(); ui->Plot5->graph(0)->clearData(); ui->Plot5->update(); ui->Plot5->replot(); } // uncheck all buttons ui->chkLPF->setChecked(false); ui->chkWin->setChecked(false); ui->chkDFT->setChecked(false); ui->chkPSD->setChecked(false); // clear all windows .. ui->edtFs->setText(""); ui->edtWinSize->setText(""); //qInfo() << "clearSiagnal() finished.. "; } // for moving the X axis to time void MainWindow::on_cmdScaleFs() { //| If there is no signal in interface if( ch_1.isEmpty() && ti.isEmpty() ) { QMessageBox msgBox; msgBox.setText("Input Channel before editing time series ... "); msgBox.exec(); } else{ //| if slider not set to zero double sldValue = ui->sldTimeLine->value(); ui->lblSecret->setText(""); if(sldValue > 0) //|if slider already moved, than evertything rescaled { //| there is an old signal window, so clear it ui->Plot4->graph(1)->clearData(); ui->Plot4->update(); ui->Plot4->replot(); } //| clear window size //ui->edtWinSize->setText(""); if(!ui->edtFs->text().isEmpty()) //| if Fs field is active, sampling frequency is given .. therefore { double Fs = ui->edtFs->text().toDouble(); double ts = 1/Fs; double ts_msec = ts*1e3; ti.clear(); ui->lblSTime->setText("Sampling time:"); ui->lblTs->setText(QString::number(ts_msec)); ui->lblUnitTs->setText("[msec]"); ui->lblXSignal->setText("t[sec]"); //qInfo()<< "Fs" << Fs << "ts" << ts <<"\n"; double t = 0; for(int i = 0; i Plot4->graph(0)->setPen(QPen(Qt::darkBlue, 1)); ui->Plot4->graph(0)->setData(ti,ch_1); ui->Plot4->update(); ui->Plot4->rescaleAxes(); ui->Plot4->yAxis->setRange(-max*1.2, max*1.2); ui->Plot4->replot(); }else { QMessageBox msgBox; msgBox.setText("Enter the sampling frequency ... "); msgBox.exec(); } } } // tool button inserting signal into interface void MainWindow::on_insertSignal() { clearSignal(); QString file_name = QFileDialog::getOpenFileName(this,"open file","C://"); // qInfo()<< file_name ; QFile txtFile(file_name); //| create filename // if file is not opened if(txtFile.open(QFile::ReadOnly)) { QTextStream in(&txtFile); while(! in.atEnd()) { QString line = in.readLine(); ch_1.push_back(line.toDouble()); } txtFile.close(); } // time vector for(int i=0; i < ch_1.size(); i++ ) { ti.push_back(i); } ui->sldTimeLine->setMaximum(ch_1.size()); double max = *std::max_element(ch_1.constBegin(),ch_1.constEnd()); // plot inported signal to plot 4 ui->Plot4->addGraph(); ui->Plot4->graph(0)->setPen(QPen(Qt::red, 1)); ui->Plot4->graph(0)->setData(ti,ch_1); ui->Plot4->update(); ui->Plot4->rescaleAxes(); ui->Plot4->yAxis->setRange(-max*1.2, max*1.2); ui->Plot4->replot(); ui->Plot4->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom); } // add the row to the profile table void MainWindow::on_addTableRow() { int N = ui->tableWidget->rowCount(); ui->tableWidget->insertRow(N); } // remove the row from the profile table void MainWindow::on_removeTableRow() { int N = ui->tableWidget->rowCount(); // | vorsicht, der C++ zaehlt ab dem index 0, also der Nte in der Reihe ist der N-1te ui->tableWidget->removeRow(N-1); } // clear table void MainWindow::on_clr_table() { int N = ui->tableWidget->rowCount(); if(N>0){ // Reading profile data for(int i = 0; i < N ; i++) { ui->tableWidget->item(i,0)->setText(""); ui->tableWidget->item(i,1)->setText(""); } QMessageBox msgBox; msgBox.setText("The table has been cleared."); msgBox.exec(); } } // cmd read profile void MainWindow::on_cmdRead_clicked() { // reset the dB borders to 0 ui->slddB->setValue(0); int N = ui->tableWidget->rowCount(); // int M = ui->tableWidget->columnCount(); ui->lblSalic->setText(""); // Reading profile data QVector x_fr,y_psd; x_fr.clear(); y_psd.clear(); for(int i = 0; i < N ; i++) { double x = ui->tableWidget->item(i,0)->text().toDouble(); double y = ui->tableWidget->item(i,1)->text().toDouble(); //qInfo()<Plot3->addGraph(); ui->Plot3->graph(0)->setPen(QPen(Qt::black, 1)); ui->Plot3->graph(0)->setData(x_fr,y_psd); ui->Plot3->xAxis->setScaleType(QCPAxis::stLogarithmic); ui->Plot3->yAxis->setScaleType(QCPAxis::stLogarithmic); //QSharedPointer logTicker(new QCPAxisTickerLog); ui->Plot3->xAxis2->setVisible(true); ui->Plot3->xAxis2->setTickLabels(false); ui->Plot3->yAxis2->setVisible(true); ui->Plot3->yAxis2->setTickLabels(false); connect(ui->Plot3->xAxis, SIGNAL(rangeChanged(QCPRange)), ui->Plot3->xAxis2, SLOT(setRange(QCPRange))); connect(ui->Plot3->yAxis, SIGNAL(rangeChanged(QCPRange)), ui->Plot3->yAxis2, SLOT(setRange(QCPRange))); ui->Plot3->update(); ui->Plot3->rescaleAxes(); ui->Plot3->replot(); double max_f = *std::max_element(x_fr.constBegin(),x_fr.constEnd()); //| max number in freq double min_f = *std::min_element(x_fr.constBegin(),x_fr.constEnd()); //| min number double max_psd = *std::max_element(y_psd.constBegin(),y_psd.constEnd()); //| max number in y_psd ui->Plot3->xAxis->setRange(0.85*min_f, 1.25*max_f); ui->Plot3->yAxis->setRange(0,4*max_psd); ui->Plot3->replot(); ui->Plot3->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom); } // slider dB mover void MainWindow::on_slddB_valueChanged() { // read the user input double w = ui->slddB->value(); ui->lbldB->setText(QString("%1").arg(w)); if(ui->lblSalic->text()=="...") { // do nothing .. } else { // go throught the table and pick up the profile // Reading profile data and fill up the vector xdB, ydB double x,y; QVector xdB,ydB_HIGH,ydB_LOW; int N = ui->tableWidget->rowCount(); for(int i = 0; i < N ; i++) { x = ui->tableWidget->item(i,0)->text().toDouble(); y = ui->tableWidget->item(i,1)->text().toDouble(); ydB_HIGH.push_back( y* pow(10, w/10)); // ydB = y x 10^(dB/10) ydB_LOW.push_back( y/ pow(10, w/10)); // ydB = y x 10^(dB/10) xdB.push_back(x); } // print vectors to the console //for(int i = 0; i < N ; i++) {qInfo()<< xdB[i] << " " << ydB_LOW[i] << "\n"; } ui->Plot3->addGraph(); ui->Plot3->graph(1)->setPen(QPen(Qt::green, 1)); ui->Plot3->graph(1)->setData(xdB,ydB_HIGH); //ui->Plot3->replot(); ui->Plot3->addGraph(); ui->Plot3->graph(2)->setPen(QPen(Qt::blue, 0.5)); ui->Plot3->graph(2)->setData(xdB,ydB_LOW); ui->Plot3->replot(); } }
#ifndef FILTER_H #define FILTER_H #include < cmath > #include < iostream > /* DIGITAL FILTER Example ................................................................| ____ ____ ____ | || || \ | | | | | D ) | | | | | / | | | | | \ | | | | | . \ |____||____||__|\__| BIQUAD FILTER SET ... ****************************************************************** Bypass - pass te signal through .. LPF - Low pass filter .. Butterworth 2nd order .. normalized ****************************************************************** //| Only LPF 2nd order is given here for modelling as //| simple as possible ... //| 21.5.2021 J.Gusic */ #define PI 3.14159265358979323846 struct Coeff { double a0,a1,a2; double b0,b1,b2; }; // (1) This function returns coefficients of a filter // // //..........................................................................................| // Second order butterworth filter Coeff LPF_butter(double fc, double fs) { Coeff LPF; const double ita =1.0/ tan(M_PI*fc/fs); const double q=sqrt(2.0); LPF.b0 = 1.0 / (1.0 + q*ita + ita*ita); LPF.b1 = 2*LPF.b0; LPF.b2 = LPF.b0; LPF.a1 = -2.0 * (ita*ita - 1.0) * LPF.b0; LPF.a2 = (1.0 - q*ita + ita*ita) * LPF.b0; return LPF; } //(2) Difference equation is used for filtering process with calculated coefficients // Biquad filter time series computation ...implementation of digital filtee coeff. // //...........................................................................................| struct DEQ { // set up the x[n-1], x[n-2] ... double x1,x2; double y0,y1, y2; double b0,b1,b2; double a1,a2; double process( const Coeff& fltCoeff, double x0) { // read in the coefficients b0 = fltCoeff.b0; b1 = fltCoeff.b1; b2 = fltCoeff.b2; a1 = fltCoeff.a1; a2 = fltCoeff.a2; y0 = b0*x0 + b1*x1 + b2*x2 - a1*y1 -a2*y2; x2 = x1; x1 = x0; y2 = y1; y1 = y0; return y0; } }; #endif
#ifndef FILTERDIALOG_H #define FILTERDIALOG_H #include < QDialog > namespace Ui { class FilterDialog; } class FilterDialog : public QDialog { Q_OBJECT public: explicit FilterDialog(QWidget *parent = nullptr); ~FilterDialog(); double getCutoff(); double fc; bool submitPressed; private slots: void on_cmdIIRsubmit_clicked(); void on_pushButton_clicked(); private: Ui::FilterDialog *ui; }; #endif // FILTERDIALOG_H
#include "filterdialog.h" #include "ui_filterdialog.h" #include < QDebug > FilterDialog::FilterDialog(QWidget *parent) : QDialog(parent), ui(new Ui::FilterDialog) { ui->setupUi(this); } FilterDialog::~FilterDialog() { delete ui; } // submiting filter parameter void FilterDialog::on_cmdIIRsubmit_clicked() { fc = ui->edtIIRFc->text().toDouble(); //| if submit button clicked .. take fc submitPressed = true; close(); } // canceling filter parameter void FilterDialog::on_pushButton_clicked() { close(); } // getter for exporting the values from the object filterdialog .. double FilterDialog::getCutoff() { return fc; }
#ifndef DIALOG_H #define DIALOG_H #include < QDialog > namespace Ui { class Dialog; } class Dialog : public QDialog { Q_OBJECT public: explicit Dialog(QWidget *parent = nullptr); ~Dialog(); bool Accepted = false; private: Ui::Dialog *ui; private slots: void user_accepts(); }; #endif // DIALOG_H
#include "dialog.h" #include "ui_dialog.h" Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); connect(ui->cmdYes, SIGNAL(clicked()),SLOT(user_accepts())); connect(ui->cmdNo, SIGNAL(clicked()),SLOT(close())); } Dialog::~Dialog() { delete ui; } void Dialog::user_accepts() { Accepted = true; close(); }