diff --git a/Software/PC_Application/Application.pro b/Software/PC_Application/Application.pro
index a67569d..2326e5c 100644
--- a/Software/PC_Application/Application.pro
+++ b/Software/PC_Application/Application.pro
@@ -26,6 +26,8 @@ HEADERS += \
Tools/eseries.h \
Tools/impedancematchdialog.h \
Traces/Math/medianfilter.h \
+ Traces/Math/tdrbandpass.h \
+ Traces/Math/tdrlowpass.h \
Traces/Math/tracemath.h \
Traces/Math/tracematheditdialog.h \
Traces/fftcomplex.h \
@@ -81,6 +83,8 @@ SOURCES += \
Tools/eseries.cpp \
Tools/impedancematchdialog.cpp \
Traces/Math/medianfilter.cpp \
+ Traces/Math/tdrbandpass.cpp \
+ Traces/Math/tdrlowpass.cpp \
Traces/Math/tracemath.cpp \
Traces/Math/tracematheditdialog.cpp \
Traces/fftcomplex.cpp \
@@ -127,7 +131,9 @@ FORMS += \
Device/manualcontroldialog.ui \
Generator/signalgenwidget.ui \
Tools/impedancematchdialog.ui \
+ Traces/Math/medianexplanationwidget.ui \
Traces/Math/medianfilterdialog.ui \
+ Traces/Math/newtracemathdialog.ui \
Traces/Math/tracematheditdialog.ui \
Traces/markerwidget.ui \
Traces/smithchartdialog.ui \
diff --git a/Software/PC_Application/Traces/Math/medianexplanationwidget.ui b/Software/PC_Application/Traces/Math/medianexplanationwidget.ui
new file mode 100644
index 0000000..0a6c074
--- /dev/null
+++ b/Software/PC_Application/Traces/Math/medianexplanationwidget.ui
@@ -0,0 +1,44 @@
+
+
+ MedianFilterExplanationWidget
+
+
+
+ 0
+ 0
+ 364
+ 412
+
+
+
+ Form
+
+
+ -
+
+
+ <html><head/><body><p><span style=" font-weight:600;">Median Filter</span></p><p>The median filter looks at a number of input samples, sorts them and uses the one in the middle as the output sample. This filters the data and especially eliminates outliers.</p><p>Parameters: </p><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 1;"><li style=" margin-top:12px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Kernel Size: the amount of input samples used for each output sample. Higher values result in more aggressive filtering</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Sorting method: Since the input data is complex, there are several options for sorting:</li></ul><ul style="margin-top: 0px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; -qt-list-indent: 2;"><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Absolute value</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Phase</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Real</li><li style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Imaginary</li></ul><p><br/></p><p><br/></p></body></html>
+
+
+ true
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
diff --git a/Software/PC_Application/Traces/Math/medianfilter.cpp b/Software/PC_Application/Traces/Math/medianfilter.cpp
index 759ac4e..0b21a7d 100644
--- a/Software/PC_Application/Traces/Math/medianfilter.cpp
+++ b/Software/PC_Application/Traces/Math/medianfilter.cpp
@@ -1,15 +1,12 @@
#include "medianfilter.h"
#include "ui_medianfilterdialog.h"
+#include "ui_medianexplanationwidget.h"
#include
using namespace Math;
using namespace std;
-namespace Ui {
-class MedianFilterDialog;
-}
-
MedianFilter::MedianFilter()
{
kernelSize = 3;
@@ -50,18 +47,26 @@ void MedianFilter::edit()
d->show();
}
+QWidget *MedianFilter::createExplanationWidget()
+{
+ auto w = new QWidget();
+ auto ui = new Ui::MedianFilterExplanationWidget;
+ ui->setupUi(w);
+ return w;
+}
+
void MedianFilter::inputSamplesChanged(unsigned int begin, unsigned int end) {
if(data.size() != input->rData().size()) {
data.resize(input->rData().size());
}
if(data.size() > 0) {
auto kernelOffset = (kernelSize-1)/2;
- int start = (int) begin - kernelOffset;
- unsigned int stop = (int) end + kernelOffset;
+ int start = (int) begin - (int) kernelOffset;
+ unsigned int stop = end + kernelOffset;
if(start < 0) {
start = 0;
}
- if(stop >= input->rData().size()) {
+ if(stop > input->rData().size()) {
stop = input->rData().size();
}
@@ -71,6 +76,7 @@ void MedianFilter::inputSamplesChanged(unsigned int begin, unsigned int end) {
case Order::Phase: return arg(a) < arg(b);
case Order::Real: return real(a) < real(b);
case Order::Imag: return imag(a) < imag(b);
+ default: return false;
}
};
@@ -82,16 +88,13 @@ void MedianFilter::inputSamplesChanged(unsigned int begin, unsigned int end) {
unsigned int inputSample;
if(kernelOffset > in + out) {
inputSample = 0;
- } else if(in + kernelOffset + out >= input->rData().size()) {
+ } else if(in + out >= input->rData().size() + kernelOffset) {
inputSample = input->rData().size() - 1;
} else {
inputSample = in + out - kernelOffset;
}
auto sample = input->rData().at(inputSample).y;
- if(out == (unsigned int) start) {
- // this is the first sample to update, fill initial kernel
- kernel[in] = sample;
- }
+ kernel[in] = sample;
}
// sort initial kernel
sort(kernel.begin(), kernel.end(), comp);
@@ -131,5 +134,6 @@ QString MedianFilter::orderToString(MedianFilter::Order o)
case Order::Phase: return "Phase";
case Order::Real: return "Real";
case Order::Imag: return "Imag";
+ default: return QString();
}
}
diff --git a/Software/PC_Application/Traces/Math/medianfilter.h b/Software/PC_Application/Traces/Math/medianfilter.h
index f28a457..2cbba2f 100644
--- a/Software/PC_Application/Traces/Math/medianfilter.h
+++ b/Software/PC_Application/Traces/Math/medianfilter.h
@@ -15,6 +15,8 @@ public:
virtual void edit() override;
+ static QWidget *createExplanationWidget();
+
public slots:
// a single value of the input data has changed, index determines which sample has changed
virtual void inputSamplesChanged(unsigned int begin, unsigned int end) override;
diff --git a/Software/PC_Application/Traces/Math/medianfilterdialog.ui b/Software/PC_Application/Traces/Math/medianfilterdialog.ui
index a7fa5ec..b387522 100644
--- a/Software/PC_Application/Traces/Math/medianfilterdialog.ui
+++ b/Software/PC_Application/Traces/Math/medianfilterdialog.ui
@@ -17,7 +17,7 @@
Median Filter
- false
+ true
-
diff --git a/Software/PC_Application/Traces/Math/newtracemathdialog.ui b/Software/PC_Application/Traces/Math/newtracemathdialog.ui
new file mode 100644
index 0000000..d7e06b1
--- /dev/null
+++ b/Software/PC_Application/Traces/Math/newtracemathdialog.ui
@@ -0,0 +1,84 @@
+
+
+ NewTraceMathDialog
+
+
+ Qt::ApplicationModal
+
+
+
+ 0
+ 0
+ 840
+ 596
+
+
+
+ Available math operations
+
+
+ true
+
+
+
-
+
+
-
+
+
+ -
+
+
+ -1
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+ QDialogButtonBox::Cancel|QDialogButtonBox::Ok
+
+
+
+
+
+
+
+
+ buttonBox
+ accepted()
+ NewTraceMathDialog
+ accept()
+
+
+ 248
+ 254
+
+
+ 157
+ 274
+
+
+
+
+ buttonBox
+ rejected()
+ NewTraceMathDialog
+ reject()
+
+
+ 316
+ 260
+
+
+ 286
+ 274
+
+
+
+
+
diff --git a/Software/PC_Application/Traces/Math/tdrbandpass.cpp b/Software/PC_Application/Traces/Math/tdrbandpass.cpp
new file mode 100644
index 0000000..afd8f14
--- /dev/null
+++ b/Software/PC_Application/Traces/Math/tdrbandpass.cpp
@@ -0,0 +1,85 @@
+#include "tdrbandpass.h"
+
+#include "Traces/fftcomplex.h"
+
+
+#include
+using namespace Math;
+using namespace std;
+
+TDRBandpass::TDRBandpass()
+{
+
+}
+
+TraceMath::DataType TDRBandpass::outputType(TraceMath::DataType inputType)
+{
+ if(inputType == DataType::Frequency) {
+ return DataType::Time;
+ } else {
+ return DataType::Invalid;
+ }
+}
+
+QString TDRBandpass::description()
+{
+ return "TDR (bandpass mode)";
+}
+
+void TDRBandpass::edit()
+{
+ // nothing to do for now
+}
+
+QWidget *TDRBandpass::createExplanationWidget()
+{
+ return new QLabel("Test");
+}
+
+void TDRBandpass::inputSamplesChanged(unsigned int begin, unsigned int end)
+{
+ Q_UNUSED(begin);
+ const double PI = 3.141592653589793238463;
+ if(input->rData().size() >= 2) {
+ // TDR is computationally expensive, only update at the end of sweep
+ if(end != input->rData().size()) {
+ // not the end, do nothing
+ return;
+ }
+ // create vector for frequency data
+ vector> dft(end);
+ // window data and perform FFTshift ("zero"-bin expected at index 0 but is in the middle of input data)
+ for(unsigned int i=0;irData()[i].y * hamming;
+ // swap upper and lower half
+ if(i < end/2) {
+ dft[i + (end+1)/2] = windowed;
+ } else {
+ dft[i - end/2] = windowed;
+ }
+ }
+ // perform IFT operation on data
+ Fft::transform(dft, true);
+
+ // calculate sample distance
+ auto freqStep = input->rData()[1].x - input->rData()[0].x;
+ auto timeStep = 1.0 / (freqStep * end);
+
+ // copy DFT data to output data
+ data.resize(dft.size());
+ for(unsigned int i=0;i
+using namespace Math;
+using namespace std;
+
+TDRLowpass::TDRLowpass()
+{
+
+}
+
+TraceMath::DataType TDRLowpass::outputType(TraceMath::DataType inputType)
+{
+ if(inputType == DataType::Frequency) {
+ return DataType::Time;
+ } else {
+ return DataType::Invalid;
+ }
+}
+
+QString TDRLowpass::description()
+{
+ return "TDR (bandpass mode)";
+}
+
+void TDRLowpass::edit()
+{
+ // nothing to do for now
+}
+
+QWidget *TDRLowpass::createExplanationWidget()
+{
+ return new QLabel("Test");
+}
+
+void TDRLowpass::inputSamplesChanged(unsigned int begin, unsigned int end)
+{
+ Q_UNUSED(begin);
+ if(input->rData().size() >= 2) {
+ // TDR is computationally expensive, only update at the end of sweep
+ if(end != input->rData().size()) {
+ // not the end, do nothing
+ return;
+ }
+ auto steps = input->rData().size();
+ auto firstStep = input->rData().front().x;
+ if(firstStep == 0) {
+ // zero as first step would result in infinite number of points, skip and start with second
+ firstStep = input->rData()[1].x;
+ steps--;
+ }
+ if(firstStep * steps != input->rData().back().x) {
+ // data is not available with correct frequency spacing, calculate required steps
+ steps = input->rData().back().x / firstStep;
+ }
+ const double PI = 3.141592653589793238463;
+ // reserve vector for negative frequenies and DC as well
+ vector> frequencyDomain(2*steps + 1);
+ // copy frequencies, use the flipped conjugate for negative part
+ for(unsigned int i = 1;i<=steps;i++) {
+ auto S = input->getInterpolatedSample(firstStep * i).y;
+ constexpr double alpha0 = 0.54;
+ auto hamming = alpha0 - (1.0 - alpha0) * -cos(PI * i / steps);
+ S *= hamming;
+ frequencyDomain[2 * steps - i + 1] = conj(S);
+ frequencyDomain[i] = S;
+ }
+ // use simple extrapolation from lowest two points to extract DC value
+ auto abs_DC = 2.0 * abs(frequencyDomain[1]) - abs(frequencyDomain[2]);
+ auto phase_DC = 2.0 * arg(frequencyDomain[1]) - arg(frequencyDomain[2]);
+ frequencyDomain[0] = polar(abs_DC, phase_DC);
+
+ auto fft_bins = frequencyDomain.size();
+ const double fs = 1.0 / (firstStep * fft_bins);
+
+ Fft::transform(frequencyDomain, true);
+
+ data.clear();
+ data.resize(fft_bins);
+
+ for(unsigned int i = 0;i data.back().x) {
+ ret.y = std::numeric_limits>::quiet_NaN();
+ ret.x = std::numeric_limits::quiet_NaN();
+ } else {
+ auto it = lower_bound(data.begin(), data.end(), x, [](const Data &lhs, const double x) -> bool {
+ return lhs.x < x;
+ });
+ if(it->x == x) {
+ ret = *it;
+ } else {
+ // no exact match, needs to interpolate
+ auto high = *it;
+ it--;
+ auto low = *it;
+ double alpha = (x - low.x) / (high.x - low.x);
+ ret.y = low.y * (1 - alpha) + high.y * alpha;
+ ret.x = x;
+ }
+ }
+ return ret;
+}
+
unsigned int TraceMath::numSamples()
{
return data.size();
diff --git a/Software/PC_Application/Traces/Math/tracemath.h b/Software/PC_Application/Traces/Math/tracemath.h
index 2e794e1..2293f41 100644
--- a/Software/PC_Application/Traces/Math/tracemath.h
+++ b/Software/PC_Application/Traces/Math/tracemath.h
@@ -5,6 +5,42 @@
#include
#include
+/*
+ * How to implement a new type of math operation:
+ * 1. Create your new math operation class by deriving from this class. Put the new class in the namespace
+ * "Math" to avoid name collisions.
+ * 2. Implement required virtual functions:
+ * a. outputType(DataType inputType):
+ * Indicates what kind of result your math operation creates, depending on the type of its input.
+ * If the input type is not applicable for your operation (e.g. frequency domain data as input for
+ * a (forward) DFT, you can return DataType::Invalid
+ * b. description():
+ * Return a short, user-readable description how the operation is set up. This will be displayed
+ * in the math edit dialog.
+ * c. edit():
+ * Optional. If your operation has customizable parameters, calling this function should start a
+ * dialog that allows the user to change these parameters.
+ * d. inputSamplesChanged(unsigned int begin, unsigned int end)
+ * This slot gets called whenever the input data has changed. Override it and implement your math
+ * operation in it. Parameters begin and end indicate which input samples have changed: If, for
+ * example, only the 2nd and third input values have changed, they are set like this: begin=1 end=3
+ * CAUTION: the size of the input vector may have changed, check before accessing it.
+ *
+ * Emit the signal outputSamplesChanged(unsigned int begin, unsigned int end) after your operation is
+ * finished. Also call either success(), warning() or error() at the end of this slot, depending on
+ * whether the operation succeeded:
+ * success(): everything went well, output data contains valid values
+ * warning(): something might be wrong (e.g. not enough input samples to create meaningful data, ...).
+ * Provide a hint by passing a short description string
+ * error(): something went wrong (called with wrong type of data, mathematical error, ...).
+ * Provide a hint by passing a short description string
+ * 3. Add a new type to the Type enum for your operation
+ * 4. Extend the createMath(Type type) factory function to create an instance of your operation
+ * 5. Add a static function "createExplanationWidget" which returns a QWidget explaining what your operation does.
+ * This will be displayed when the user chooses to add a new math operation.
+ * 6. Extend the function getInfo(Type type) to set a name and create the explanation widget for your operation
+ */
+
class TraceMath : public QObject {
Q_OBJECT
public:
@@ -28,7 +64,24 @@ public:
Error,
};
+ enum class Type {
+ MedianFilter,
+ TDRlowpass,
+ TDRbandpass,
+ // Add new math operations here, do not explicitly assign values and keep the Last entry at the last position
+ Last,
+ };
+
+ static TraceMath *createMath(Type type);
+ class TypeInfo {
+ public:
+ QString name;
+ QWidget *explanationWidget;
+ };
+ static TypeInfo getInfo(Type type);
+
Data getSample(unsigned int index);
+ Data getInterpolatedSample(double x);
unsigned int numSamples();
// indicate whether this function produces time or frequency domain data
diff --git a/Software/PC_Application/Traces/Math/tracematheditdialog.cpp b/Software/PC_Application/Traces/Math/tracematheditdialog.cpp
index fd4a012..d592f83 100644
--- a/Software/PC_Application/Traces/Math/tracematheditdialog.cpp
+++ b/Software/PC_Application/Traces/Math/tracematheditdialog.cpp
@@ -2,6 +2,11 @@
#include "ui_tracematheditdialog.h"
#include
+#include "ui_newtracemathdialog.h"
+namespace Ui {
+class NewTraceMathDialog;
+}
+
#include "medianfilter.h"
TraceMathEditDialog::TraceMathEditDialog(Trace &t, QWidget *parent) :
@@ -18,6 +23,7 @@ TraceMathEditDialog::TraceMathEditDialog(Trace &t, QWidget *parent) :
headerView->setSectionResizeMode(MathModel::ColIndexDomain, QHeaderView::ResizeToContents);
connect(ui->view->selectionModel(), &QItemSelectionModel::currentRowChanged, [=](const QModelIndex ¤t, const QModelIndex &previous){
+ Q_UNUSED(previous)
if(!current.isValid()) {
ui->bDelete->setEnabled(false);
ui->bMoveUp->setEnabled(false);
@@ -37,7 +43,30 @@ TraceMathEditDialog::TraceMathEditDialog(Trace &t, QWidget *parent) :
});
connect(ui->bAdd, &QPushButton::clicked, [=](){
- model->addOperation(new Math::MedianFilter);
+ auto d = new QDialog();
+ auto ui = new Ui::NewTraceMathDialog();
+ ui->setupUi(d);
+ for(int i = 0; i < (int) TraceMath::Type::Last;i++) {
+ auto info = TraceMath::getInfo(static_cast(i));
+ ui->list->addItem(info.name);
+ if(!info.explanationWidget) {
+ info.explanationWidget = new QWidget();
+ }
+ ui->stack->addWidget(info.explanationWidget);
+ }
+ // always show the widget for the selected function
+ connect(ui->list, &QListWidget::currentRowChanged, ui->stack, &QStackedWidget::setCurrentIndex);
+
+ connect(ui->buttonBox, &QDialogButtonBox::accepted, [=](){
+ auto newMath = TraceMath::createMath(static_cast(ui->list->currentRow()));
+ if(newMath) {
+ model->addOperation(newMath);
+ }
+ });
+ ui->list->setCurrentRow(0);
+ ui->stack->setCurrentIndex(0);
+
+ d->show();
});
connect(ui->bDelete, &QPushButton::clicked, [=](){
model->deleteRow(ui->view->currentIndex().row());
@@ -45,13 +74,11 @@ TraceMathEditDialog::TraceMathEditDialog(Trace &t, QWidget *parent) :
connect(ui->bMoveUp, &QPushButton::clicked, [&](){
auto index = ui->view->currentIndex();
t.swapMathOrder(index.row() - 1);
- model->rowsSwapped(index.row() - 1);
ui->view->setCurrentIndex(index.sibling(index.row() - 1, 0));
});
connect(ui->bMoveDown, &QPushButton::clicked, [&](){
auto index = ui->view->currentIndex();
t.swapMathOrder(index.row());
- model->rowsSwapped(index.row());
ui->view->setCurrentIndex(index.sibling(index.row() + 1, 0));
});
}
@@ -70,11 +97,13 @@ MathModel::MathModel(Trace &t, QObject *parent)
int MathModel::rowCount(const QModelIndex &parent) const
{
+ Q_UNUSED(parent);
return t.getMathOperations().size();
}
int MathModel::columnCount(const QModelIndex &parent) const
{
+ Q_UNUSED(parent);
return ColIndexLast;
}
@@ -168,7 +197,3 @@ void MathModel::deleteRow(unsigned int row)
endRemoveRows();
}
-void MathModel::rowsSwapped(unsigned int top)
-{
-// emit dataChanged(createIndex(top, 0), createIndex(top+1, ColIndexLast - 1));
-}
diff --git a/Software/PC_Application/Traces/Math/tracematheditdialog.h b/Software/PC_Application/Traces/Math/tracematheditdialog.h
index f8bcc37..4f0f54e 100644
--- a/Software/PC_Application/Traces/Math/tracematheditdialog.h
+++ b/Software/PC_Application/Traces/Math/tracematheditdialog.h
@@ -30,7 +30,6 @@ public:
void addOperation(TraceMath *math);
void deleteRow(unsigned int row);
- void rowsSwapped(unsigned int top);
private:
Trace &t;
diff --git a/Software/PC_Application/Traces/Math/tracematheditdialog.ui b/Software/PC_Application/Traces/Math/tracematheditdialog.ui
index 10bd270..44b44d1 100644
--- a/Software/PC_Application/Traces/Math/tracematheditdialog.ui
+++ b/Software/PC_Application/Traces/Math/tracematheditdialog.ui
@@ -17,7 +17,7 @@
Math functions
- false
+ true
-
diff --git a/Software/PC_Application/Traces/trace.cpp b/Software/PC_Application/Traces/trace.cpp
index 22b0157..6bd3a9e 100644
--- a/Software/PC_Application/Traces/trace.cpp
+++ b/Software/PC_Application/Traces/trace.cpp
@@ -263,6 +263,7 @@ void Trace::updateLastMath(vector::reverse_iterator start)
lastMath = newLast;
// relay signals of end of math chain
connect(lastMath, &TraceMath::outputSamplesChanged, this, &Trace::dataChanged);
+ emit outputSamplesChanged(0, data.size());
}
}
diff --git a/Software/PC_Application/Traces/traceeditdialog.ui b/Software/PC_Application/Traces/traceeditdialog.ui
index 4842052..6a3f4bb 100644
--- a/Software/PC_Application/Traces/traceeditdialog.ui
+++ b/Software/PC_Application/Traces/traceeditdialog.ui
@@ -17,7 +17,7 @@
Edit Trace
- false
+ true
-
diff --git a/Software/PC_Application/icons/math_disabled.svg b/Software/PC_Application/icons/math_disabled.svg
index d23978e..721c347 100644
--- a/Software/PC_Application/icons/math_disabled.svg
+++ b/Software/PC_Application/icons/math_disabled.svg
@@ -9,13 +9,13 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="17.410528mm"
- height="9.36625mm"
- viewBox="0 0 17.410529 9.3662499"
+ width="9.5429888mm"
+ height="8.6545076mm"
+ viewBox="0 0 9.5429888 8.6545077"
version="1.1"
id="svg8"
- inkscape:version="0.92.3 (2405546, 2018-03-11)"
- sodipodi:docname="math_disabled.svg">
+ sodipodi:docname="math_disabled.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ transform="translate(-84.809019,-129.3552)">
- f(x)
+ x="85.422623"
+ y="136.7381"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Padauk Book';-inkscape-font-specification:'Padauk Book, ';stroke-width:0.26458332px">M
+ style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#fcffff;stroke-width:1.70000005;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ d="m 85.314335,137.50494 6.93903,-6.21735 0.812743,-0.72822 0.780583,-0.6994"
+ id="path819"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccc" />
+
diff --git a/Software/PC_Application/icons/math_enabled.svg b/Software/PC_Application/icons/math_enabled.svg
index e00ef46..00f3fa4 100644
--- a/Software/PC_Application/icons/math_enabled.svg
+++ b/Software/PC_Application/icons/math_enabled.svg
@@ -9,13 +9,13 @@
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
- width="16.50322mm"
- height="9.36625mm"
- viewBox="0 0 16.50322 9.36625"
+ width="9.5429888mm"
+ height="8.6545076mm"
+ viewBox="0 0 9.5429888 8.6545077"
version="1.1"
id="svg8"
- inkscape:version="0.92.3 (2405546, 2018-03-11)"
- sodipodi:docname="math_enabled.svg">
+ sodipodi:docname="math_enabled.svg"
+ inkscape:version="0.92.3 (2405546, 2018-03-11)">
+ transform="translate(-84.809019,-129.3552)">
- f(x)
+ x="85.422623"
+ y="136.7381"
+ style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Padauk Book';-inkscape-font-specification:'Padauk Book, ';stroke-width:0.26458332px">M
+
+