Handle traces created from CSV files in trace edit dialog

This commit is contained in:
Jan Käberich 2021-07-13 19:57:01 +02:00
parent fa4e954f73
commit 3038dc0f75
7 changed files with 462 additions and 37 deletions

View File

@ -0,0 +1,145 @@
#include "csvimport.h"
#include "ui_csvimport.h"
#include <QFileDialog>
#include "Traces/trace.h"
#include <QDebug>
CSVImport::CSVImport(QWidget *parent) :
QWidget(parent),
ui(new Ui::csvimport),
status(false)
{
ui->setupUi(this);
ui->from->setPrecision(5);
ui->to->setPrecision(5);
ui->traces->setPrecision(0);
ui->points->setPrecision(0);
connect(ui->file, &QLineEdit::textChanged, this, &CSVImport::setFile);
}
CSVImport::~CSVImport()
{
delete ui;
}
bool CSVImport::getStatus()
{
return status;
}
CSV CSVImport::getCSV()
{
return csv;
}
QString CSVImport::getFilename()
{
return ui->file->text();
}
bool CSVImport::fillTrace(Trace &t)
{
try {
t.fillFromCSV(csv, ui->traceSelector->currentIndex());
return true;
} catch (const std::exception &e) {
qWarning() << QString("CSV import failed to fill trace: ") + e.what();
return false;
}
}
void CSVImport::setFile(QString filename)
{
ui->file->setText(filename);
evaluateFile();
emit filenameChanged(filename);
}
void CSVImport::selectTrace(unsigned int index)
{
ui->traceSelector->setCurrentIndex(index);
}
void CSVImport::on_browse_clicked()
{
auto filename = QFileDialog::getOpenFileName(nullptr, "Open measurement file", "", "CSV files (*.csv)", nullptr, QFileDialog::DontUseNativeDialog);
if (filename.length() > 0) {
ui->file->setText(filename);
evaluateFile();
}
}
void CSVImport::evaluateFile()
{
// store currently selected trace
auto selectedTrace = ui->traceSelector->currentText();
bool new_status = false;
ui->traces->setText("");
ui->points->setText("");
ui->from->setText("");
ui->to->setText("");
ui->status->clear();
ui->traceSelector->clear();
try {
csv = CSV::fromFile(ui->file->text());
auto domain = Trace::dataTypeFromString(csv.getHeader(0));
if (domain == Trace::DataType::Invalid) {
// just assume frequency domain
domain = Trace::DataType::Frequency;
}
ui->domain->setCurrentText(Trace::dataTypeToString(domain));
switch(domain) {
case Trace::DataType::Frequency:
ui->from->setUnit("Hz");
ui->to->setUnit("Hz");
break;
case Trace::DataType::Time:
ui->from->setUnit("s");
ui->to->setUnit("s");
break;
case Trace::DataType::Power:
ui->from->setUnit("dBm");
ui->to->setUnit("dBm");
break;
default:
break;
}
auto xvalues = csv.getColumn(0);
ui->from->setValue(xvalues.front());
ui->to->setValue(xvalues.back());
ui->points->setValue(xvalues.size());
bool okay = true;
int numTraces = 0;
while(okay) {
try {
Trace t;
auto name = t.fillFromCSV(csv, numTraces);
ui->traceSelector->addItem(name);
numTraces++;
} catch (const std::exception &e) {
// no more traces
okay = false;
}
}
ui->traces->setValue(numTraces);
// check if previously selected trace is still available
if(ui->traceSelector->findText(selectedTrace) >= 0) {
ui->traceSelector->setCurrentText(selectedTrace);
} else {
ui->traceSelector->setCurrentIndex(0);
}
new_status = true;
} catch (const std::exception &e) {
ui->status->setText(e.what());
}
if (new_status != status) {
status = new_status;
emit statusChanged(status);
}
emit filenameChanged(ui->file->text());
}

View File

@ -0,0 +1,45 @@
#ifndef CSVIMPORT_H
#define CSVIMPORT_H
#include <QWidget>
#include "csv.h"
#include "Traces/trace.h"
namespace Ui {
class csvimport;
}
class CSVImport : public QWidget
{
Q_OBJECT
public:
explicit CSVImport(QWidget *parent = nullptr);
~CSVImport();
bool getStatus();
CSV getCSV();
QString getFilename();
bool fillTrace(Trace &t);
signals:
void statusChanged(bool status);
void filenameChanged(QString name);
public slots:
void setFile(QString filename);
void selectTrace(unsigned int index);
private slots:
void on_browse_clicked();
private:
void evaluateFile();
Ui::csvimport *ui;
int required_ports;
CSV csv;
bool status;
};
#endif // CSVIMPORT_H

View File

@ -0,0 +1,192 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>csvimport</class>
<widget class="QWidget" name="csvimport">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>232</width>
<height>256</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLineEdit" name="file">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="browse">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>20</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>...</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QLabel" name="status">
<property name="palette">
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>239</red>
<green>41</green>
<blue>41</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>239</red>
<green>41</green>
<blue>41</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>190</red>
<green>190</green>
<blue>190</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="text">
<string/>
</property>
</widget>
</item>
<item>
<layout class="QFormLayout" name="formLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Domain:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QComboBox" name="domain">
<property name="enabled">
<bool>false</bool>
</property>
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Traces:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="SIUnitEdit" name="traces">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_17">
<property name="text">
<string>Points:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="SIUnitEdit" name="points">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_24">
<property name="text">
<string>From:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="SIUnitEdit" name="from">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_25">
<property name="text">
<string>To:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="SIUnitEdit" name="to">
<property name="enabled">
<bool>false</bool>
</property>
</widget>
</item>
<item row="5" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Trace:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QComboBox" name="traceSelector"/>
</item>
</layout>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>SIUnitEdit</class>
<extends>QLineEdit</extends>
<header>CustomWidgets/siunitedit.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -33,6 +33,7 @@ TouchstoneImport::TouchstoneImport(QWidget *parent, int ports) :
connect(ui->port2Group, qOverload<int>(&QButtonGroup::buttonClicked), [=](int id) {
preventCollisionWithGroup(ui->port1Group, id);
});
connect(ui->file, &QLineEdit::textChanged, this, &TouchstoneImport::setFile);
setPorts(ports);
}
@ -103,6 +104,7 @@ void TouchstoneImport::setFile(QString filename)
{
ui->file->setText(filename);
evaluateFile();
emit filenameChanged(filename);
}
void TouchstoneImport::on_browse_clicked()
@ -110,7 +112,6 @@ void TouchstoneImport::on_browse_clicked()
auto filename = QFileDialog::getOpenFileName(nullptr, "Open measurement file", "", "Touchstone files (*.s1p *.s2p *.s3p *.s4p)", nullptr, QFileDialog::DontUseNativeDialog);
if (filename.length() > 0) {
ui->file->setText(filename);
evaluateFile();
}
}

View File

@ -11,6 +11,7 @@ HEADERS += \
Calibration/receivercaldialog.h \
Calibration/sourcecaldialog.h \
CustomWidgets/colorpickerbutton.h \
CustomWidgets/csvimport.h \
CustomWidgets/informationbox.h \
CustomWidgets/jsonpickerdialog.h \
CustomWidgets/siunitedit.h \
@ -138,6 +139,7 @@ SOURCES += \
Calibration/receivercaldialog.cpp \
Calibration/sourcecaldialog.cpp \
CustomWidgets/colorpickerbutton.cpp \
CustomWidgets/csvimport.cpp \
CustomWidgets/informationbox.cpp \
CustomWidgets/jsonpickerdialog.cpp \
CustomWidgets/siunitedit.cpp \
@ -253,6 +255,7 @@ FORMS += \
Calibration/calkitdialog.ui \
Calibration/frequencycaldialog.ui \
Calibration/manualcalibrationdialog.ui \
CustomWidgets/csvimport.ui \
CustomWidgets/jsonpickerdialog.ui \
CustomWidgets/tilewidget.ui \
CustomWidgets/touchstoneimport.ui \

View File

@ -19,6 +19,27 @@ TraceEditDialog::TraceEditDialog(Trace &t, QWidget *parent) :
ui->name->setText(t.name());
ui->color->setColor(trace.color());
ui->vFactor->setValue(t.velocityFactor());
connect(ui->bLive, &QPushButton::clicked, [=](bool live) {
if(live) {
ui->stack->setCurrentIndex(0);
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
}
});
connect(ui->bFile, &QPushButton::clicked, [&](bool file) {
if(file) {
if(t.getFilename().endsWith(".csv")) {
ui->stack->setCurrentIndex(2);
ui->csvImport->setFile(t.getFilename());
ui->csvImport->selectTrace(t.getFileParameter());
} else {
// attempt to parse as touchstone
ui->stack->setCurrentIndex(1);
ui->touchstoneImport->setFile(t.getFilename());
}
}
});
connect(ui->color, &ColorPickerButton::colorChanged, [=](const QColor& color){
trace.setColor(color);
});
@ -26,7 +47,7 @@ TraceEditDialog::TraceEditDialog(Trace &t, QWidget *parent) :
ui->GSource->setId(ui->bLive, 0);
ui->GSource->setId(ui->bFile, 1);
if(t.isCalibration() || (t.isFromFile() && t.getFilename().endsWith(".csv"))) {
if(t.isCalibration()) {
// prevent editing imported calibration traces (and csv files for now)
ui->bLive->setEnabled(false);
ui->bFile->setEnabled(false);
@ -34,12 +55,7 @@ TraceEditDialog::TraceEditDialog(Trace &t, QWidget *parent) :
ui->CLiveParam->setEnabled(false);
}
if(t.isFromFile() && !t.getFilename().endsWith(".csv")) {
ui->bFile->click();
ui->touchstoneImport->setFile(t.getFilename());
}
auto updateFileStatus = [this]() {
auto updateTouchstoneFileStatus = [this]() {
// remove all options from paramater combo box
while(ui->CParameter->count() > 0) {
ui->CParameter->removeItem(0);
@ -61,6 +77,25 @@ TraceEditDialog::TraceEditDialog(Trace &t, QWidget *parent) :
ui->CParameter->setCurrentIndex(0);
}
}
if(ui->touchstoneImport->getFilename().endsWith(".csv")) {
// switch to csv import dialog
ui->stack->setCurrentIndex(2);
ui->csvImport->setFile(ui->touchstoneImport->getFilename());
}
};
auto updateCSVFileStatus = [this]() {
if (ui->bFile->isChecked() && !ui->csvImport->getStatus()) {
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
} else {
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
auto touchstone = ui->touchstoneImport->getTouchstone();
}
if(!(ui->touchstoneImport->getFilename().endsWith(".csv"))) {
// switch to touchstone import dialog
ui->stack->setCurrentIndex(1);
ui->touchstoneImport->setFile(ui->csvImport->getFilename());
}
};
switch(t.liveType()) {
@ -91,11 +126,13 @@ TraceEditDialog::TraceEditDialog(Trace &t, QWidget *parent) :
default: break;
}
connect(ui->GSource, qOverload<int>(&QButtonGroup::buttonClicked), updateFileStatus);
connect(ui->touchstoneImport, &TouchstoneImport::statusChanged, updateFileStatus);
connect(ui->touchstoneImport, &TouchstoneImport::filenameChanged, updateFileStatus);
connect(ui->touchstoneImport, &TouchstoneImport::statusChanged, updateTouchstoneFileStatus);
connect(ui->touchstoneImport, &TouchstoneImport::filenameChanged, updateTouchstoneFileStatus);
connect(ui->csvImport, &CSVImport::filenameChanged, updateCSVFileStatus);
updateFileStatus();
if(t.isFromFile()) {
ui->bFile->click();
}
// setup math part of the GUI
auto model = new MathModel(t);
@ -208,8 +245,14 @@ void TraceEditDialog::on_buttonBox_accepted()
if(!trace.isCalibration()) {
// only apply changes if it is not a calibration trace
if (ui->bFile->isChecked()) {
auto t = ui->touchstoneImport->getTouchstone();
trace.fillFromTouchstone(t, ui->CParameter->currentIndex());
if(ui->stack->currentIndex() == 1) {
// touchstone page active
auto t = ui->touchstoneImport->getTouchstone();
trace.fillFromTouchstone(t, ui->CParameter->currentIndex());
} else {
// CSV page active
ui->csvImport->fillTrace(trace);
}
} else {
Trace::LivedataType type = Trace::LivedataType::Overwrite;
Trace::LiveParameter param = Trace::LiveParameter::S11;

View File

@ -117,7 +117,7 @@
<property name="currentIndex">
<number>0</number>
</property>
<widget class="QWidget" name="page">
<widget class="QWidget" name="LivePage">
<layout class="QFormLayout" name="formLayout_2">
<item row="0" column="0">
<widget class="QLabel" name="label_3">
@ -157,7 +157,7 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="page_2">
<widget class="QWidget" name="TouchstonePage">
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="TouchstoneImport" name="touchstoneImport" native="true"/>
@ -178,6 +178,13 @@
</item>
</layout>
</widget>
<widget class="QWidget" name="CSVPage">
<layout class="QVBoxLayout" name="verticalLayout_6">
<item>
<widget class="CSVImport" name="csvImport" native="true"/>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
@ -335,6 +342,11 @@
</layout>
</widget>
<customwidgets>
<customwidget>
<class>SIUnitEdit</class>
<extends>QLineEdit</extends>
<header>CustomWidgets/siunitedit.h</header>
</customwidget>
<customwidget>
<class>TouchstoneImport</class>
<extends>QWidget</extends>
@ -347,32 +359,16 @@
<header>CustomWidgets/colorpickerbutton.h</header>
</customwidget>
<customwidget>
<class>SIUnitEdit</class>
<extends>QLineEdit</extends>
<header>CustomWidgets/siunitedit.h</header>
<class>CSVImport</class>
<extends>QWidget</extends>
<header>CustomWidgets/csvimport.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../icons.qrc"/>
</resources>
<connections>
<connection>
<sender>GSource</sender>
<signal>buttonClicked(int)</signal>
<receiver>stack</receiver>
<slot>setCurrentIndex(int)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>146</x>
<y>216</y>
</hint>
</hints>
</connection>
</connections>
<connections/>
<buttongroups>
<buttongroup name="GSource"/>
</buttongroups>