File indexing completed on 2024-05-05 03:48:26

0001 /*
0002     File                 : HilbertTransformTest.cpp
0003     Project              : LabPlot
0004     Description          : Tests for Hilbert transform
0005     --------------------------------------------------------------------
0006     SPDX-FileCopyrightText: 2021 Stefan Gerlach <stefan.gerlach@uni.kn>
0007 
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 
0011 #include "HilbertTransformTest.h"
0012 #include "backend/core/column/Column.h"
0013 #include "backend/worksheet/plots/cartesian/XYHilbertTransformCurve.h"
0014 
0015 // ##############################################################################
0016 
0017 void HilbertTransformTest::test1() {
0018     // data
0019     QVector<int> xData = {1, 2, 3, 4};
0020     QVector<double> yData = {1., 2., 3., 4.};
0021 
0022     // data source columns
0023     Column xDataColumn(QStringLiteral("x"), AbstractColumn::ColumnMode::Integer);
0024     xDataColumn.replaceInteger(0, xData);
0025 
0026     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0027     yDataColumn.replaceValues(0, yData);
0028 
0029     XYHilbertTransformCurve curve(QStringLiteral("Hilbert Trafo"));
0030     curve.setXDataColumn(&xDataColumn);
0031     curve.setYDataColumn(&yDataColumn);
0032 
0033     // prepare the transform
0034     XYHilbertTransformCurve::TransformData data = curve.transformData();
0035     curve.setTransformData(data);
0036 
0037     // perform the transform
0038     const auto& result = curve.result();
0039 
0040     // check the results
0041     QCOMPARE(result.available, true);
0042     QCOMPARE(result.valid, true);
0043 
0044     const AbstractColumn* resultXDataColumn = curve.xColumn();
0045     const AbstractColumn* resultYDataColumn = curve.yColumn();
0046 
0047     const int np = resultXDataColumn->rowCount();
0048     QCOMPARE(np, 4);
0049 
0050     for (int i = 0; i < np; i++)
0051         QCOMPARE(resultXDataColumn->valueAt(i), (double)i + 1);
0052     for (int i = 0; i < np; i++)
0053         DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(i));
0054 
0055     QCOMPARE(resultYDataColumn->valueAt(0), 1.);
0056     QCOMPARE(resultYDataColumn->valueAt(1), -1.);
0057     QCOMPARE(resultYDataColumn->valueAt(2), -1.);
0058     QCOMPARE(resultYDataColumn->valueAt(3), 1.);
0059 }
0060 
0061 void HilbertTransformTest::test2() {
0062     // data
0063     QVector<int> xData = {1, 2, 3, 4, 5, 6, 7};
0064     QVector<double> yData = {1., 2., 3., 4., 3., 2., 1.};
0065 
0066     // data source columns
0067     Column xDataColumn(QStringLiteral("x"), AbstractColumn::ColumnMode::Integer);
0068     xDataColumn.replaceInteger(0, xData);
0069 
0070     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0071     yDataColumn.replaceValues(0, yData);
0072 
0073     XYHilbertTransformCurve curve(QStringLiteral("Hilbert Trafo"));
0074     curve.setXDataColumn(&xDataColumn);
0075     curve.setYDataColumn(&yDataColumn);
0076 
0077     // prepare the transform
0078     XYHilbertTransformCurve::TransformData data = curve.transformData();
0079     curve.setTransformData(data);
0080 
0081     // perform the transform
0082     const auto& result = curve.result();
0083 
0084     // check the results
0085     QCOMPARE(result.available, true);
0086     QCOMPARE(result.valid, true);
0087 
0088     const AbstractColumn* resultXDataColumn = curve.xColumn();
0089     const AbstractColumn* resultYDataColumn = curve.yColumn();
0090 
0091     const int np = resultXDataColumn->rowCount();
0092     QCOMPARE(np, 7);
0093 
0094     for (int i = 0; i < np; i++)
0095         QCOMPARE(resultXDataColumn->valueAt(i), (double)i + 1);
0096     for (int i = 0; i < np; i++)
0097         DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(i));
0098 
0099     QCOMPARE(resultYDataColumn->valueAt(0), -0.736238855198572);
0100     QCOMPARE(resultYDataColumn->valueAt(1), -1.22454414518711);
0101     QCOMPARE(resultYDataColumn->valueAt(2), -1.29334051930247);
0102     FuzzyCompare(resultYDataColumn->valueAt(3), 0., 1.e-15);
0103     QCOMPARE(resultYDataColumn->valueAt(4), -resultYDataColumn->valueAt(2));
0104     QCOMPARE(resultYDataColumn->valueAt(5), -resultYDataColumn->valueAt(1));
0105     QCOMPARE(resultYDataColumn->valueAt(6), -resultYDataColumn->valueAt(0));
0106 }
0107 
0108 void HilbertTransformTest::test3() {
0109     // data
0110     QVector<int> xData = {1, 2, 3, 4, 5, 6, 7, 8};
0111     QVector<double> yData = {1, 2, 3, 4, 5, 6, 7, 8};
0112 
0113     // data source columns
0114     Column xDataColumn(QStringLiteral("x"), AbstractColumn::ColumnMode::Integer);
0115     xDataColumn.replaceInteger(0, xData);
0116 
0117     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0118     yDataColumn.replaceValues(0, yData);
0119 
0120     XYHilbertTransformCurve curve(QStringLiteral("Hilbert trafo"));
0121     curve.setXDataColumn(&xDataColumn);
0122     curve.setYDataColumn(&yDataColumn);
0123 
0124     // prepare the transform
0125     XYHilbertTransformCurve::TransformData data = curve.transformData();
0126 
0127     // perform the transform
0128     curve.setTransformData(data);
0129 
0130     const auto& result = curve.result();
0131 
0132     // check the results
0133     QCOMPARE(result.available, true);
0134     QCOMPARE(result.valid, true);
0135 
0136     const AbstractColumn* resultXDataColumn = curve.xColumn();
0137     const AbstractColumn* resultYDataColumn = curve.yColumn();
0138 
0139     const int np = resultXDataColumn->rowCount();
0140     QCOMPARE(np, 8);
0141 
0142     for (int i = 0; i < np; i++)
0143         QCOMPARE(resultXDataColumn->valueAt(i), (double)i + 1);
0144     for (int i = 0; i < np; i++)
0145         DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(i));
0146 
0147     QCOMPARE(resultYDataColumn->valueAt(0), 3.82842712474619);
0148     QCOMPARE(resultYDataColumn->valueAt(1), -1.);
0149     QCOMPARE(resultYDataColumn->valueAt(2), -1.);
0150     QCOMPARE(resultYDataColumn->valueAt(3), -1.82842712474619);
0151     QCOMPARE(resultYDataColumn->valueAt(4), -1.82842712474619);
0152     QCOMPARE(resultYDataColumn->valueAt(5), -1.);
0153     QCOMPARE(resultYDataColumn->valueAt(6), -1.);
0154     QCOMPARE(resultYDataColumn->valueAt(7), 3.82842712474619);
0155 }
0156 
0157 void HilbertTransformTest::test4() {
0158     // data
0159     QVector<int> xData = {1, 2, 3, 4, 5, 6, 7, 8, 9};
0160     QVector<double> yData = {1., -1., 2., -2., 3., -3., 4., -4., 5.};
0161 
0162     // data source columns
0163     Column xDataColumn(QStringLiteral("x"), AbstractColumn::ColumnMode::Integer);
0164     xDataColumn.replaceInteger(0, xData);
0165 
0166     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0167     yDataColumn.replaceValues(0, yData);
0168 
0169     XYHilbertTransformCurve curve(QStringLiteral("Hilbert trafo"));
0170     curve.setXDataColumn(&xDataColumn);
0171     curve.setYDataColumn(&yDataColumn);
0172 
0173     // prepare the transform
0174     XYHilbertTransformCurve::TransformData data = curve.transformData();
0175 
0176     // perform the transform
0177     curve.setTransformData(data);
0178 
0179     const auto& result = curve.result();
0180 
0181     // check the results
0182     QCOMPARE(result.available, true);
0183     QCOMPARE(result.valid, true);
0184 
0185     const AbstractColumn* resultXDataColumn = curve.xColumn();
0186     const AbstractColumn* resultYDataColumn = curve.yColumn();
0187 
0188     const int np = resultXDataColumn->rowCount();
0189     QCOMPARE(np, 9);
0190 
0191     for (int i = 0; i < np; i++)
0192         QCOMPARE(resultXDataColumn->valueAt(i), (double)i + 1);
0193     for (int i = 0; i < np; i++)
0194         DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(i));
0195 
0196     QCOMPARE(resultYDataColumn->valueAt(0), 5.73760166175338);
0197     QCOMPARE(resultYDataColumn->valueAt(1), -2.91301405896714);
0198     QCOMPARE(resultYDataColumn->valueAt(2), 2.9964917553466);
0199     QCOMPARE(resultYDataColumn->valueAt(3), -2.12747459905025);
0200     QCOMPARE(resultYDataColumn->valueAt(4), 1.6613081372851);
0201     QCOMPARE(resultYDataColumn->valueAt(5), -1.10190838316691);
0202     QCOMPARE(resultYDataColumn->valueAt(6), -0.146025447565372);
0203     QCOMPARE(resultYDataColumn->valueAt(7), 0.674355652492414);
0204     QCOMPARE(resultYDataColumn->valueAt(8), -4.78133471812782);
0205 }
0206 
0207 void HilbertTransformTest::testPerformance() {
0208     // data
0209     QVector<int> xData;
0210     QVector<double> yData;
0211 #ifdef HAVE_FFTW3
0212     const int N = 1e6;
0213 #else // GSL is much slower
0214     const int N = 2e5;
0215 #endif
0216     for (int i = 0; i < N; i++) {
0217         xData.append(i);
0218         yData.append(i % 100);
0219     }
0220 
0221     // data source columns
0222     Column xDataColumn(QStringLiteral("x"), AbstractColumn::ColumnMode::Integer);
0223     xDataColumn.replaceInteger(0, xData);
0224 
0225     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0226     yDataColumn.replaceValues(0, yData);
0227 
0228     XYHilbertTransformCurve curve(QStringLiteral("Hilbert trafo"));
0229     curve.setXDataColumn(&xDataColumn);
0230     curve.setYDataColumn(&yDataColumn);
0231 
0232     // prepare and perform the convolution
0233     XYHilbertTransformCurve::TransformData data = curve.transformData();
0234     QBENCHMARK {
0235         // triggers recalculate()
0236         curve.setTransformData(data);
0237     }
0238 
0239     // check the results
0240     const auto& result = curve.result();
0241 
0242     QCOMPARE(result.available, true);
0243     QCOMPARE(result.valid, true);
0244 
0245     const AbstractColumn* resultXDataColumn = curve.xColumn();
0246 
0247     const int np = resultXDataColumn->rowCount();
0248     QCOMPARE(np, N);
0249 }
0250 
0251 QTEST_MAIN(HilbertTransformTest)