File indexing completed on 2024-04-28 03:48:01

0001 /*
0002     File                 : CorrelationTest.cpp
0003     Project              : LabPlot
0004     Description          : Tests for data correlation
0005     --------------------------------------------------------------------
0006     SPDX-FileCopyrightText: 2018 Stefan Gerlach <stefan.gerlach@uni.kn>
0007 
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 
0011 #include "CorrelationTest.h"
0012 #include "backend/core/column/Column.h"
0013 #include "backend/worksheet/plots/cartesian/XYCorrelationCurve.h"
0014 
0015 // ##############################################################################
0016 
0017 void CorrelationTest::testLinear() {
0018     // data
0019     QVector<int> xData = {1, 2, 3, 4};
0020     QVector<double> yData = {1., 2., 3., 4.};
0021     QVector<double> y2Data = {0, 1., .5};
0022 
0023     // data source columns
0024     Column xDataColumn(QStringLiteral("x"), AbstractColumn::ColumnMode::Integer);
0025     xDataColumn.replaceInteger(0, xData);
0026 
0027     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0028     yDataColumn.replaceValues(0, yData);
0029 
0030     Column y2DataColumn(QStringLiteral("y2"), AbstractColumn::ColumnMode::Double);
0031     y2DataColumn.replaceValues(0, y2Data);
0032 
0033     XYCorrelationCurve correlationCurve(QStringLiteral("correlation"));
0034     correlationCurve.setXDataColumn(&xDataColumn);
0035     correlationCurve.setYDataColumn(&yDataColumn);
0036     correlationCurve.setY2DataColumn(&y2DataColumn);
0037 
0038     // prepare the correlation
0039     XYCorrelationCurve::CorrelationData correlationData = correlationCurve.correlationData();
0040     correlationCurve.setCorrelationData(correlationData);
0041 
0042     // perform the correlation
0043     correlationCurve.recalculate();
0044     const XYCorrelationCurve::CorrelationResult& correlationResult = correlationCurve.correlationResult();
0045 
0046     // check the results
0047     QCOMPARE(correlationResult.available, true);
0048     QCOMPARE(correlationResult.valid, true);
0049 
0050     const AbstractColumn* resultXDataColumn = correlationCurve.xColumn();
0051     const AbstractColumn* resultYDataColumn = correlationCurve.yColumn();
0052 
0053     const int np = resultXDataColumn->rowCount();
0054     QCOMPARE(np, 7);
0055 
0056     for (int i = 0; i < np; i++)
0057         QCOMPARE(resultXDataColumn->valueAt(i), (double)i + 1);
0058 
0059     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(0));
0060     FuzzyCompare(resultYDataColumn->valueAt(0), 0., 1.e-15);
0061     QCOMPARE(resultYDataColumn->valueAt(1), 0.5);
0062     QCOMPARE(resultYDataColumn->valueAt(2), 2.);
0063     QCOMPARE(resultYDataColumn->valueAt(3), 3.5);
0064     QCOMPARE(resultYDataColumn->valueAt(4), 5.);
0065     QCOMPARE(resultYDataColumn->valueAt(5), 4.);
0066     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(6));
0067     FuzzyCompare(resultYDataColumn->valueAt(6), 0., 2.e-15);
0068 }
0069 
0070 void CorrelationTest::testLinear2() {
0071     // data
0072     QVector<int> xData = {1, 2, 3};
0073     QVector<double> yData = {1., 2., 3.};
0074     QVector<double> y2Data = {0, 1., .5};
0075 
0076     // data source columns
0077     Column xDataColumn(QStringLiteral("x"), AbstractColumn::ColumnMode::Integer);
0078     xDataColumn.replaceInteger(0, xData);
0079 
0080     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0081     yDataColumn.replaceValues(0, yData);
0082 
0083     Column y2DataColumn(QStringLiteral("y2"), AbstractColumn::ColumnMode::Double);
0084     y2DataColumn.replaceValues(0, y2Data);
0085 
0086     XYCorrelationCurve correlationCurve(QStringLiteral("correlation"));
0087     correlationCurve.setXDataColumn(&xDataColumn);
0088     correlationCurve.setYDataColumn(&yDataColumn);
0089     correlationCurve.setY2DataColumn(&y2DataColumn);
0090 
0091     // prepare the correlation
0092     XYCorrelationCurve::CorrelationData correlationData = correlationCurve.correlationData();
0093     correlationCurve.setCorrelationData(correlationData);
0094 
0095     // perform the correlation
0096     correlationCurve.recalculate();
0097     const XYCorrelationCurve::CorrelationResult& correlationResult = correlationCurve.correlationResult();
0098 
0099     // check the results
0100     QCOMPARE(correlationResult.available, true);
0101     QCOMPARE(correlationResult.valid, true);
0102 
0103     const AbstractColumn* resultXDataColumn = correlationCurve.xColumn();
0104     const AbstractColumn* resultYDataColumn = correlationCurve.yColumn();
0105 
0106     const int np = resultXDataColumn->rowCount();
0107     QCOMPARE(np, 5);
0108 
0109     for (int i = 0; i < np; i++)
0110         QCOMPARE(resultXDataColumn->valueAt(i), (double)i + 1);
0111 
0112     QCOMPARE(resultYDataColumn->valueAt(0), 0.5);
0113     QCOMPARE(resultYDataColumn->valueAt(1), 2.);
0114     QCOMPARE(resultYDataColumn->valueAt(2), 3.5);
0115     QCOMPARE(resultYDataColumn->valueAt(3), 3.);
0116     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(4));
0117     FuzzyCompare(resultYDataColumn->valueAt(4), 0., 1.e-15);
0118 }
0119 
0120 void CorrelationTest::testLinear_noX() {
0121     // data
0122     QVector<double> yData = {1., 2., 3., 4.};
0123     QVector<double> y2Data = {0, 1., .5};
0124 
0125     // data source columns
0126     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0127     yDataColumn.replaceValues(0, yData);
0128 
0129     Column y2DataColumn(QStringLiteral("y2"), AbstractColumn::ColumnMode::Double);
0130     y2DataColumn.replaceValues(0, y2Data);
0131 
0132     XYCorrelationCurve correlationCurve(QStringLiteral("correlation"));
0133     correlationCurve.setYDataColumn(&yDataColumn);
0134     correlationCurve.setY2DataColumn(&y2DataColumn);
0135 
0136     // prepare the correlation
0137     XYCorrelationCurve::CorrelationData correlationData = correlationCurve.correlationData();
0138     correlationCurve.setCorrelationData(correlationData);
0139 
0140     // perform the correlation
0141     correlationCurve.recalculate();
0142     const XYCorrelationCurve::CorrelationResult& correlationResult = correlationCurve.correlationResult();
0143 
0144     // check the results
0145     QCOMPARE(correlationResult.available, true);
0146     QCOMPARE(correlationResult.valid, true);
0147 
0148     const AbstractColumn* resultXDataColumn = correlationCurve.xColumn();
0149     const AbstractColumn* resultYDataColumn = correlationCurve.yColumn();
0150 
0151     const int np = resultXDataColumn->rowCount();
0152     QCOMPARE(np, 7);
0153 
0154     for (int i = 0; i < np; i++)
0155         QCOMPARE(resultXDataColumn->valueAt(i), (double)(i - np / 2));
0156 
0157     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(0));
0158     FuzzyCompare(resultYDataColumn->valueAt(0), 0., 1.e-15);
0159     QCOMPARE(resultYDataColumn->valueAt(1), 0.5);
0160     QCOMPARE(resultYDataColumn->valueAt(2), 2.);
0161     QCOMPARE(resultYDataColumn->valueAt(3), 3.5);
0162     QCOMPARE(resultYDataColumn->valueAt(4), 5.);
0163     QCOMPARE(resultYDataColumn->valueAt(5), 4.);
0164     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(6));
0165     FuzzyCompare(resultYDataColumn->valueAt(6), 0., 2.e-15);
0166 }
0167 
0168 void CorrelationTest::testLinear_swapped() {
0169     // data
0170     QVector<int> xData = {1, 2, 3, 4};
0171     QVector<double> yData = {0, 1., .5};
0172     QVector<double> y2Data = {1., 2., 3., 4.};
0173 
0174     // data source columns
0175     Column xDataColumn(QStringLiteral("x"), AbstractColumn::ColumnMode::Integer);
0176     xDataColumn.replaceInteger(0, xData);
0177 
0178     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0179     yDataColumn.replaceValues(0, yData);
0180 
0181     Column y2DataColumn(QStringLiteral("y2"), AbstractColumn::ColumnMode::Double);
0182     y2DataColumn.replaceValues(0, y2Data);
0183 
0184     XYCorrelationCurve correlationCurve(QStringLiteral("correlation"));
0185     correlationCurve.setXDataColumn(&xDataColumn);
0186     correlationCurve.setYDataColumn(&yDataColumn);
0187     correlationCurve.setY2DataColumn(&y2DataColumn);
0188 
0189     // prepare the correlation
0190     XYCorrelationCurve::CorrelationData correlationData = correlationCurve.correlationData();
0191     correlationCurve.setCorrelationData(correlationData);
0192 
0193     // perform the correlation
0194     correlationCurve.recalculate();
0195     const XYCorrelationCurve::CorrelationResult& correlationResult = correlationCurve.correlationResult();
0196 
0197     // check the results
0198     QCOMPARE(correlationResult.available, true);
0199     QCOMPARE(correlationResult.valid, true);
0200 
0201     const AbstractColumn* resultXDataColumn = correlationCurve.xColumn();
0202     const AbstractColumn* resultYDataColumn = correlationCurve.yColumn();
0203 
0204     const int np = resultXDataColumn->rowCount();
0205     QCOMPARE(np, 7);
0206 
0207     for (int i = 0; i < np; i++)
0208         QCOMPARE(resultXDataColumn->valueAt(i), (double)i + 1);
0209 
0210     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(0));
0211     FuzzyCompare(resultYDataColumn->valueAt(0), 0., 2.e-15);
0212     QCOMPARE(resultYDataColumn->valueAt(1), 4.);
0213     QCOMPARE(resultYDataColumn->valueAt(2), 5.);
0214     QCOMPARE(resultYDataColumn->valueAt(3), 3.5);
0215     QCOMPARE(resultYDataColumn->valueAt(4), 2.);
0216     QCOMPARE(resultYDataColumn->valueAt(5), 0.5);
0217     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(6));
0218     FuzzyCompare(resultYDataColumn->valueAt(6), 0., 1.e-15);
0219 }
0220 
0221 /* circular */
0222 
0223 void CorrelationTest::testCircular() {
0224     // data
0225     QVector<int> xData = {1, 2, 3, 4};
0226     QVector<double> yData = {1., 2., 3., 4.};
0227     QVector<double> y2Data = {0, 1., .5};
0228 
0229     // data source columns
0230     Column xDataColumn(QStringLiteral("x"), AbstractColumn::ColumnMode::Integer);
0231     xDataColumn.replaceInteger(0, xData);
0232 
0233     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0234     yDataColumn.replaceValues(0, yData);
0235 
0236     Column y2DataColumn(QStringLiteral("y2"), AbstractColumn::ColumnMode::Double);
0237     y2DataColumn.replaceValues(0, y2Data);
0238 
0239     XYCorrelationCurve correlationCurve(QStringLiteral("correlation"));
0240     correlationCurve.setXDataColumn(&xDataColumn);
0241     correlationCurve.setYDataColumn(&yDataColumn);
0242     correlationCurve.setY2DataColumn(&y2DataColumn);
0243 
0244     // prepare the correlation
0245     XYCorrelationCurve::CorrelationData correlationData = correlationCurve.correlationData();
0246     correlationData.type = nsl_corr_type_circular;
0247     correlationCurve.setCorrelationData(correlationData);
0248 
0249     // perform the correlation
0250     correlationCurve.recalculate();
0251     const XYCorrelationCurve::CorrelationResult& correlationResult = correlationCurve.correlationResult();
0252 
0253     // check the results
0254     QCOMPARE(correlationResult.available, true);
0255     QCOMPARE(correlationResult.valid, true);
0256 
0257     const AbstractColumn* resultXDataColumn = correlationCurve.xColumn();
0258     const AbstractColumn* resultYDataColumn = correlationCurve.yColumn();
0259 
0260     const int np = resultXDataColumn->rowCount();
0261     QCOMPARE(np, 4);
0262 
0263     for (int i = 0; i < np; i++)
0264         QCOMPARE(resultXDataColumn->valueAt(i), (double)i + 1);
0265 
0266     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(0));
0267     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(1));
0268     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(2));
0269     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(3));
0270     QCOMPARE(resultYDataColumn->valueAt(0), 2.);
0271     QCOMPARE(resultYDataColumn->valueAt(1), 4.5);
0272     QCOMPARE(resultYDataColumn->valueAt(2), 5.);
0273     QCOMPARE(resultYDataColumn->valueAt(3), 3.5);
0274 }
0275 
0276 void CorrelationTest::testCircular2() {
0277     // data
0278     QVector<int> xData = {1, 2, 3};
0279     QVector<double> yData = {1., 2., 3.};
0280     QVector<double> y2Data = {0, 1., .5};
0281 
0282     // data source columns
0283     Column xDataColumn(QStringLiteral("x"), AbstractColumn::ColumnMode::Integer);
0284     xDataColumn.replaceInteger(0, xData);
0285 
0286     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0287     yDataColumn.replaceValues(0, yData);
0288 
0289     Column y2DataColumn(QStringLiteral("y2"), AbstractColumn::ColumnMode::Double);
0290     y2DataColumn.replaceValues(0, y2Data);
0291 
0292     XYCorrelationCurve correlationCurve(QStringLiteral("correlation"));
0293     correlationCurve.setXDataColumn(&xDataColumn);
0294     correlationCurve.setYDataColumn(&yDataColumn);
0295     correlationCurve.setY2DataColumn(&y2DataColumn);
0296 
0297     // prepare the correlation
0298     XYCorrelationCurve::CorrelationData correlationData = correlationCurve.correlationData();
0299     correlationData.type = nsl_corr_type_circular;
0300     correlationCurve.setCorrelationData(correlationData);
0301 
0302     // perform the correlation
0303     correlationCurve.recalculate();
0304     const XYCorrelationCurve::CorrelationResult& correlationResult = correlationCurve.correlationResult();
0305 
0306     // check the results
0307     QCOMPARE(correlationResult.available, true);
0308     QCOMPARE(correlationResult.valid, true);
0309 
0310     const AbstractColumn* resultXDataColumn = correlationCurve.xColumn();
0311     const AbstractColumn* resultYDataColumn = correlationCurve.yColumn();
0312 
0313     const int np = resultXDataColumn->rowCount();
0314     QCOMPARE(np, 3);
0315 
0316     for (int i = 0; i < np; i++)
0317         QCOMPARE(resultXDataColumn->valueAt(i), (double)i + 1);
0318 
0319     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(0));
0320     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(1));
0321     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(2));
0322     QCOMPARE(resultYDataColumn->valueAt(0), 2.);
0323     QCOMPARE(resultYDataColumn->valueAt(1), 3.5);
0324     QCOMPARE(resultYDataColumn->valueAt(2), 3.5);
0325 }
0326 
0327 /* norm tests */
0328 
0329 void CorrelationTest::testLinear_biased() {
0330     // data
0331     QVector<double> yData = {1., 2., 3., 4.};
0332     QVector<double> y2Data = {0, 1., .5};
0333 
0334     // data source columns
0335     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0336     yDataColumn.replaceValues(0, yData);
0337 
0338     Column y2DataColumn(QStringLiteral("y2"), AbstractColumn::ColumnMode::Double);
0339     y2DataColumn.replaceValues(0, y2Data);
0340 
0341     XYCorrelationCurve correlationCurve(QStringLiteral("correlation"));
0342     correlationCurve.setYDataColumn(&yDataColumn);
0343     correlationCurve.setY2DataColumn(&y2DataColumn);
0344 
0345     // prepare the correlation
0346     XYCorrelationCurve::CorrelationData correlationData = correlationCurve.correlationData();
0347     correlationData.normalize = nsl_corr_norm_biased;
0348     correlationCurve.setCorrelationData(correlationData);
0349 
0350     // perform the correlation
0351     correlationCurve.recalculate();
0352     const XYCorrelationCurve::CorrelationResult& correlationResult = correlationCurve.correlationResult();
0353 
0354     // check the results
0355     QCOMPARE(correlationResult.available, true);
0356     QCOMPARE(correlationResult.valid, true);
0357 
0358     const AbstractColumn* resultXDataColumn = correlationCurve.xColumn();
0359     const AbstractColumn* resultYDataColumn = correlationCurve.yColumn();
0360 
0361     const int np = resultXDataColumn->rowCount();
0362     QCOMPARE(np, 7);
0363 
0364     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(0));
0365     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(1));
0366     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(2));
0367     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(3));
0368     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(4));
0369     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(5));
0370     FuzzyCompare(resultYDataColumn->valueAt(0), 0., 1.e-15);
0371     QCOMPARE(resultYDataColumn->valueAt(1), 0.125);
0372     QCOMPARE(resultYDataColumn->valueAt(2), .5);
0373     QCOMPARE(resultYDataColumn->valueAt(3), 3.5 / 4.);
0374     QCOMPARE(resultYDataColumn->valueAt(4), 1.25);
0375     QCOMPARE(resultYDataColumn->valueAt(5), 1.);
0376     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(6));
0377     FuzzyCompare(resultYDataColumn->valueAt(6), 0., 2.e-15);
0378 }
0379 
0380 void CorrelationTest::testLinear2_biased() {
0381     // data
0382     QVector<double> yData = {1., 2., 3.};
0383     QVector<double> y2Data = {0, 1., .5};
0384 
0385     // data source columns
0386     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0387     yDataColumn.replaceValues(0, yData);
0388 
0389     Column y2DataColumn(QStringLiteral("y2"), AbstractColumn::ColumnMode::Double);
0390     y2DataColumn.replaceValues(0, y2Data);
0391 
0392     XYCorrelationCurve correlationCurve(QStringLiteral("correlation"));
0393     correlationCurve.setYDataColumn(&yDataColumn);
0394     correlationCurve.setY2DataColumn(&y2DataColumn);
0395 
0396     // prepare the correlation
0397     XYCorrelationCurve::CorrelationData correlationData = correlationCurve.correlationData();
0398     correlationData.normalize = nsl_corr_norm_biased;
0399     correlationCurve.setCorrelationData(correlationData);
0400 
0401     // perform the correlation
0402     correlationCurve.recalculate();
0403     const XYCorrelationCurve::CorrelationResult& correlationResult = correlationCurve.correlationResult();
0404 
0405     // check the results
0406     QCOMPARE(correlationResult.available, true);
0407     QCOMPARE(correlationResult.valid, true);
0408 
0409     const AbstractColumn* resultXDataColumn = correlationCurve.xColumn();
0410     const AbstractColumn* resultYDataColumn = correlationCurve.yColumn();
0411 
0412     const int np = resultXDataColumn->rowCount();
0413     QCOMPARE(np, 5);
0414 
0415     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(0));
0416     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(1));
0417     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(2));
0418     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(3));
0419     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(4));
0420     QCOMPARE(resultYDataColumn->valueAt(0), 1. / 6.);
0421     QCOMPARE(resultYDataColumn->valueAt(1), 2. / 3.);
0422     QCOMPARE(resultYDataColumn->valueAt(2), 7. / 6.);
0423     QCOMPARE(resultYDataColumn->valueAt(3), 1.);
0424     FuzzyCompare(resultYDataColumn->valueAt(4), 0., 1.e-15);
0425 }
0426 
0427 void CorrelationTest::testLinear_unbiased() {
0428     // data
0429     QVector<double> yData = {1., 2., 3., 4.};
0430     QVector<double> y2Data = {0, 1., .5};
0431 
0432     // data source columns
0433     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0434     yDataColumn.replaceValues(0, yData);
0435 
0436     Column y2DataColumn(QStringLiteral("y2"), AbstractColumn::ColumnMode::Double);
0437     y2DataColumn.replaceValues(0, y2Data);
0438 
0439     XYCorrelationCurve correlationCurve(QStringLiteral("correlation"));
0440     correlationCurve.setYDataColumn(&yDataColumn);
0441     correlationCurve.setY2DataColumn(&y2DataColumn);
0442 
0443     // prepare the correlation
0444     XYCorrelationCurve::CorrelationData correlationData = correlationCurve.correlationData();
0445     correlationData.normalize = nsl_corr_norm_unbiased;
0446     correlationCurve.setCorrelationData(correlationData);
0447 
0448     // perform the correlation
0449     correlationCurve.recalculate();
0450     const XYCorrelationCurve::CorrelationResult& correlationResult = correlationCurve.correlationResult();
0451 
0452     // check the results
0453     QCOMPARE(correlationResult.available, true);
0454     QCOMPARE(correlationResult.valid, true);
0455 
0456     const AbstractColumn* resultXDataColumn = correlationCurve.xColumn();
0457     const AbstractColumn* resultYDataColumn = correlationCurve.yColumn();
0458 
0459     const int np = resultXDataColumn->rowCount();
0460     QCOMPARE(np, 7);
0461 
0462     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(0));
0463     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(1));
0464     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(2));
0465     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(3));
0466     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(4));
0467     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(5));
0468     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(6));
0469     FuzzyCompare(resultYDataColumn->valueAt(0), 0., 1.e-15);
0470     QCOMPARE(resultYDataColumn->valueAt(1), 0.25);
0471     QCOMPARE(resultYDataColumn->valueAt(2), 2. / 3.);
0472     QCOMPARE(resultYDataColumn->valueAt(3), 3.5 / 4.);
0473     QCOMPARE(resultYDataColumn->valueAt(4), 5. / 3.);
0474     QCOMPARE(resultYDataColumn->valueAt(5), 2.);
0475     FuzzyCompare(resultYDataColumn->valueAt(6), 0., 2.e-15);
0476 }
0477 
0478 void CorrelationTest::testLinear2_unbiased() {
0479     // data
0480     QVector<double> yData = {1., 2., 3.};
0481     QVector<double> y2Data = {0, 1., .5};
0482 
0483     // data source columns
0484     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0485     yDataColumn.replaceValues(0, yData);
0486 
0487     Column y2DataColumn(QStringLiteral("y2"), AbstractColumn::ColumnMode::Double);
0488     y2DataColumn.replaceValues(0, y2Data);
0489 
0490     XYCorrelationCurve correlationCurve(QStringLiteral("correlation"));
0491     correlationCurve.setYDataColumn(&yDataColumn);
0492     correlationCurve.setY2DataColumn(&y2DataColumn);
0493 
0494     // prepare the correlation
0495     XYCorrelationCurve::CorrelationData correlationData = correlationCurve.correlationData();
0496     correlationData.normalize = nsl_corr_norm_unbiased;
0497     correlationCurve.setCorrelationData(correlationData);
0498 
0499     // perform the correlation
0500     correlationCurve.recalculate();
0501     const XYCorrelationCurve::CorrelationResult& correlationResult = correlationCurve.correlationResult();
0502 
0503     // check the results
0504     QCOMPARE(correlationResult.available, true);
0505     QCOMPARE(correlationResult.valid, true);
0506 
0507     const AbstractColumn* resultXDataColumn = correlationCurve.xColumn();
0508     const AbstractColumn* resultYDataColumn = correlationCurve.yColumn();
0509 
0510     const int np = resultXDataColumn->rowCount();
0511     QCOMPARE(np, 5);
0512 
0513     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(0));
0514     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(1));
0515     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(2));
0516     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(3));
0517     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(4));
0518     QCOMPARE(resultYDataColumn->valueAt(0), 0.5);
0519     QCOMPARE(resultYDataColumn->valueAt(1), 1.);
0520     QCOMPARE(resultYDataColumn->valueAt(2), 7. / 6.);
0521     QCOMPARE(resultYDataColumn->valueAt(3), 1.5);
0522     FuzzyCompare(resultYDataColumn->valueAt(4), 0., 1.e-15);
0523 }
0524 
0525 void CorrelationTest::testLinear_coeff() {
0526     // data
0527     QVector<double> yData = {1., 2., 3., 4.};
0528     QVector<double> y2Data = {0, 1., .5};
0529 
0530     // data source columns
0531     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0532     yDataColumn.replaceValues(0, yData);
0533 
0534     Column y2DataColumn(QStringLiteral("y2"), AbstractColumn::ColumnMode::Double);
0535     y2DataColumn.replaceValues(0, y2Data);
0536 
0537     XYCorrelationCurve correlationCurve(QStringLiteral("correlation"));
0538     correlationCurve.setYDataColumn(&yDataColumn);
0539     correlationCurve.setY2DataColumn(&y2DataColumn);
0540 
0541     // prepare the correlation
0542     XYCorrelationCurve::CorrelationData correlationData = correlationCurve.correlationData();
0543     correlationData.normalize = nsl_corr_norm_coeff;
0544     correlationCurve.setCorrelationData(correlationData);
0545 
0546     // perform the correlation
0547     correlationCurve.recalculate();
0548     const XYCorrelationCurve::CorrelationResult& correlationResult = correlationCurve.correlationResult();
0549 
0550     // check the results
0551     QCOMPARE(correlationResult.available, true);
0552     QCOMPARE(correlationResult.valid, true);
0553 
0554     const AbstractColumn* resultXDataColumn = correlationCurve.xColumn();
0555     const AbstractColumn* resultYDataColumn = correlationCurve.yColumn();
0556 
0557     const int np = resultXDataColumn->rowCount();
0558     QCOMPARE(np, 7);
0559 
0560     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(0));
0561     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(1));
0562     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(2));
0563     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(3));
0564     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(4));
0565     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(5));
0566     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(6));
0567     FuzzyCompare(resultYDataColumn->valueAt(0), 0., 1.e-15);
0568     double norm = sqrt(30) * sqrt(1.25);
0569     QCOMPARE(resultYDataColumn->valueAt(1), 0.5 / norm);
0570     QCOMPARE(resultYDataColumn->valueAt(2), 2. / norm);
0571     QCOMPARE(resultYDataColumn->valueAt(3), 3.5 / norm);
0572     QCOMPARE(resultYDataColumn->valueAt(4), 5. / norm);
0573     QCOMPARE(resultYDataColumn->valueAt(5), 4. / norm);
0574     FuzzyCompare(resultYDataColumn->valueAt(6), 0., 2.e-15);
0575 }
0576 
0577 void CorrelationTest::testLinear2_coeff() {
0578     // data
0579     QVector<double> yData = {1., 2., 3.};
0580     QVector<double> y2Data = {0, 1., .5};
0581 
0582     // data source columns
0583     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0584     yDataColumn.replaceValues(0, yData);
0585 
0586     Column y2DataColumn(QStringLiteral("y2"), AbstractColumn::ColumnMode::Double);
0587     y2DataColumn.replaceValues(0, y2Data);
0588 
0589     XYCorrelationCurve correlationCurve(QStringLiteral("correlation"));
0590     correlationCurve.setYDataColumn(&yDataColumn);
0591     correlationCurve.setY2DataColumn(&y2DataColumn);
0592 
0593     // prepare the correlation
0594     XYCorrelationCurve::CorrelationData correlationData = correlationCurve.correlationData();
0595     correlationData.normalize = nsl_corr_norm_coeff;
0596     correlationCurve.setCorrelationData(correlationData);
0597 
0598     // perform the correlation
0599     correlationCurve.recalculate();
0600     const XYCorrelationCurve::CorrelationResult& correlationResult = correlationCurve.correlationResult();
0601 
0602     // check the results
0603     QCOMPARE(correlationResult.available, true);
0604     QCOMPARE(correlationResult.valid, true);
0605 
0606     const AbstractColumn* resultXDataColumn = correlationCurve.xColumn();
0607     const AbstractColumn* resultYDataColumn = correlationCurve.yColumn();
0608 
0609     const int np = resultXDataColumn->rowCount();
0610     QCOMPARE(np, 5);
0611 
0612     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(0));
0613     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(1));
0614     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(2));
0615     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(3));
0616     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(4));
0617     double norm = sqrt(14.) * sqrt(1.25);
0618     QCOMPARE(resultYDataColumn->valueAt(0), .5 / norm);
0619     QCOMPARE(resultYDataColumn->valueAt(1), 2. / norm);
0620     QCOMPARE(resultYDataColumn->valueAt(2), 3.5 / norm);
0621     QCOMPARE(resultYDataColumn->valueAt(3), 3. / norm);
0622     FuzzyCompare(resultYDataColumn->valueAt(4), 0., 1.e-15);
0623 }
0624 
0625 void CorrelationTest::testCircular_coeff() {
0626     // data
0627     QVector<double> yData = {1., 2., 3., 4.};
0628     QVector<double> y2Data = {0, 1., .5};
0629 
0630     // data source columns
0631     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0632     yDataColumn.replaceValues(0, yData);
0633 
0634     Column y2DataColumn(QStringLiteral("y2"), AbstractColumn::ColumnMode::Double);
0635     y2DataColumn.replaceValues(0, y2Data);
0636 
0637     XYCorrelationCurve correlationCurve(QStringLiteral("correlation"));
0638     correlationCurve.setYDataColumn(&yDataColumn);
0639     correlationCurve.setY2DataColumn(&y2DataColumn);
0640 
0641     // prepare the correlation
0642     XYCorrelationCurve::CorrelationData correlationData = correlationCurve.correlationData();
0643     correlationData.type = nsl_corr_type_circular;
0644     correlationData.normalize = nsl_corr_norm_coeff;
0645     correlationCurve.setCorrelationData(correlationData);
0646 
0647     // perform the correlation
0648     correlationCurve.recalculate();
0649     const XYCorrelationCurve::CorrelationResult& correlationResult = correlationCurve.correlationResult();
0650 
0651     // check the results
0652     QCOMPARE(correlationResult.available, true);
0653     QCOMPARE(correlationResult.valid, true);
0654 
0655     const AbstractColumn* resultXDataColumn = correlationCurve.xColumn();
0656     const AbstractColumn* resultYDataColumn = correlationCurve.yColumn();
0657 
0658     const int np = resultXDataColumn->rowCount();
0659     QCOMPARE(np, 4);
0660 
0661     for (int i = 0; i < np; i++)
0662         QCOMPARE(resultXDataColumn->valueAt(i), (double)i);
0663 
0664     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(0));
0665     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(1));
0666     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(2));
0667     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(3));
0668     QCOMPARE(resultYDataColumn->valueAt(0), 0.32659863237109);
0669     QCOMPARE(resultYDataColumn->valueAt(1), 0.734846922834953);
0670     QCOMPARE(resultYDataColumn->valueAt(2), 0.816496580927726);
0671     QCOMPARE(resultYDataColumn->valueAt(3), 0.571547606649408);
0672 }
0673 
0674 void CorrelationTest::testCircular2_coeff() {
0675     // data
0676     QVector<double> yData = {1., 2., 3.};
0677     QVector<double> y2Data = {0, 1., .5};
0678 
0679     // data source columns
0680     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0681     yDataColumn.replaceValues(0, yData);
0682 
0683     Column y2DataColumn(QStringLiteral("y2"), AbstractColumn::ColumnMode::Double);
0684     y2DataColumn.replaceValues(0, y2Data);
0685 
0686     XYCorrelationCurve correlationCurve(QStringLiteral("correlation"));
0687     correlationCurve.setYDataColumn(&yDataColumn);
0688     correlationCurve.setY2DataColumn(&y2DataColumn);
0689 
0690     // prepare the correlation
0691     XYCorrelationCurve::CorrelationData correlationData = correlationCurve.correlationData();
0692     correlationData.type = nsl_corr_type_circular;
0693     correlationData.normalize = nsl_corr_norm_coeff;
0694     correlationCurve.setCorrelationData(correlationData);
0695 
0696     // perform the correlation
0697     correlationCurve.recalculate();
0698     const XYCorrelationCurve::CorrelationResult& correlationResult = correlationCurve.correlationResult();
0699 
0700     // check the results
0701     QCOMPARE(correlationResult.available, true);
0702     QCOMPARE(correlationResult.valid, true);
0703 
0704     const AbstractColumn* resultXDataColumn = correlationCurve.xColumn();
0705     const AbstractColumn* resultYDataColumn = correlationCurve.yColumn();
0706 
0707     const int np = resultXDataColumn->rowCount();
0708     QCOMPARE(np, 3);
0709 
0710     for (int i = 0; i < np; i++)
0711         QCOMPARE(resultXDataColumn->valueAt(i), (double)i);
0712 
0713     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(0));
0714     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(1));
0715     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(2));
0716     QCOMPARE(resultYDataColumn->valueAt(0), 0.478091443733757);
0717     QCOMPARE(resultYDataColumn->valueAt(1), 0.836660026534076);
0718     QCOMPARE(resultYDataColumn->valueAt(2), 0.836660026534076);
0719 }
0720 
0721 /* samplingInterval */
0722 
0723 void CorrelationTest::testLinear_samplingInterval() {
0724     // data
0725     QVector<double> yData = {1., 2., 3., 4.};
0726     QVector<double> y2Data = {0, 1., .5};
0727 
0728     // data source columns
0729     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0730     yDataColumn.replaceValues(0, yData);
0731 
0732     Column y2DataColumn(QStringLiteral("y2"), AbstractColumn::ColumnMode::Double);
0733     y2DataColumn.replaceValues(0, y2Data);
0734 
0735     XYCorrelationCurve correlationCurve(QStringLiteral("correlation"));
0736     correlationCurve.setYDataColumn(&yDataColumn);
0737     correlationCurve.setY2DataColumn(&y2DataColumn);
0738 
0739     // prepare the correlation
0740     XYCorrelationCurve::CorrelationData correlationData = correlationCurve.correlationData();
0741     correlationData.samplingInterval = 0.1;
0742     correlationCurve.setCorrelationData(correlationData);
0743 
0744     // perform the correlation
0745     correlationCurve.recalculate();
0746     const XYCorrelationCurve::CorrelationResult& correlationResult = correlationCurve.correlationResult();
0747 
0748     // check the results
0749     QCOMPARE(correlationResult.available, true);
0750     QCOMPARE(correlationResult.valid, true);
0751 
0752     const AbstractColumn* resultXDataColumn = correlationCurve.xColumn();
0753     const AbstractColumn* resultYDataColumn = correlationCurve.yColumn();
0754 
0755     const int np = resultXDataColumn->rowCount();
0756     QCOMPARE(np, 7);
0757 
0758     for (int i = 0; i < np; i++) {
0759         DEBUG(std::setprecision(15) << resultXDataColumn->valueAt(i));
0760         QCOMPARE(resultXDataColumn->valueAt(i), (double)(i - np / 2) * correlationData.samplingInterval);
0761     }
0762 
0763     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(0));
0764     FuzzyCompare(resultYDataColumn->valueAt(0), 0., 1.e-15);
0765     QCOMPARE(resultYDataColumn->valueAt(1), 0.5);
0766     QCOMPARE(resultYDataColumn->valueAt(2), 2.);
0767     QCOMPARE(resultYDataColumn->valueAt(3), 3.5);
0768     QCOMPARE(resultYDataColumn->valueAt(4), 5.);
0769     QCOMPARE(resultYDataColumn->valueAt(5), 4.);
0770     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(6));
0771     FuzzyCompare(resultYDataColumn->valueAt(6), 0., 2.e-15);
0772 }
0773 
0774 void CorrelationTest::testLinear2_samplingInterval() {
0775     // data
0776     QVector<double> yData = {1., 2., 3.};
0777     QVector<double> y2Data = {0, 1., .5};
0778 
0779     // data source columns
0780     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0781     yDataColumn.replaceValues(0, yData);
0782 
0783     Column y2DataColumn(QStringLiteral("y2"), AbstractColumn::ColumnMode::Double);
0784     y2DataColumn.replaceValues(0, y2Data);
0785 
0786     XYCorrelationCurve correlationCurve(QStringLiteral("correlation"));
0787     correlationCurve.setYDataColumn(&yDataColumn);
0788     correlationCurve.setY2DataColumn(&y2DataColumn);
0789 
0790     // prepare the correlation
0791     XYCorrelationCurve::CorrelationData correlationData = correlationCurve.correlationData();
0792     correlationData.samplingInterval = 0.1;
0793     correlationCurve.setCorrelationData(correlationData);
0794 
0795     // perform the correlation
0796     correlationCurve.recalculate();
0797     const XYCorrelationCurve::CorrelationResult& correlationResult = correlationCurve.correlationResult();
0798 
0799     // check the results
0800     QCOMPARE(correlationResult.available, true);
0801     QCOMPARE(correlationResult.valid, true);
0802 
0803     const AbstractColumn* resultXDataColumn = correlationCurve.xColumn();
0804     const AbstractColumn* resultYDataColumn = correlationCurve.yColumn();
0805 
0806     const int np = resultXDataColumn->rowCount();
0807     QCOMPARE(np, 5);
0808 
0809     for (int i = 0; i < np; i++) {
0810         DEBUG(std::setprecision(15) << resultXDataColumn->valueAt(i));
0811         QCOMPARE(resultXDataColumn->valueAt(i), (double)(i - np / 2) * correlationData.samplingInterval);
0812     }
0813 
0814     QCOMPARE(resultYDataColumn->valueAt(0), 0.5);
0815     QCOMPARE(resultYDataColumn->valueAt(1), 2.);
0816     QCOMPARE(resultYDataColumn->valueAt(2), 3.5);
0817     QCOMPARE(resultYDataColumn->valueAt(3), 3.);
0818     DEBUG(std::setprecision(15) << resultYDataColumn->valueAt(4));
0819     FuzzyCompare(resultYDataColumn->valueAt(4), 0., 1.e-15);
0820 }
0821 
0822 void CorrelationTest::testCircular_samplingInterval() {
0823     // data
0824     QVector<double> yData = {1., 2., 3., 4.};
0825     QVector<double> y2Data = {0, 1., .5};
0826 
0827     // data source columns
0828     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0829     yDataColumn.replaceValues(0, yData);
0830 
0831     Column y2DataColumn(QStringLiteral("y2"), AbstractColumn::ColumnMode::Double);
0832     y2DataColumn.replaceValues(0, y2Data);
0833 
0834     XYCorrelationCurve correlationCurve(QStringLiteral("correlation"));
0835     correlationCurve.setYDataColumn(&yDataColumn);
0836     correlationCurve.setY2DataColumn(&y2DataColumn);
0837 
0838     // prepare the correlation
0839     XYCorrelationCurve::CorrelationData correlationData = correlationCurve.correlationData();
0840     correlationData.type = nsl_corr_type_circular;
0841     correlationData.samplingInterval = 0.1;
0842     correlationCurve.setCorrelationData(correlationData);
0843 
0844     // perform the correlation
0845     correlationCurve.recalculate();
0846     const XYCorrelationCurve::CorrelationResult& correlationResult = correlationCurve.correlationResult();
0847 
0848     // check the results
0849     QCOMPARE(correlationResult.available, true);
0850     QCOMPARE(correlationResult.valid, true);
0851 
0852     const AbstractColumn* resultXDataColumn = correlationCurve.xColumn();
0853     const AbstractColumn* resultYDataColumn = correlationCurve.yColumn();
0854 
0855     const int np = resultXDataColumn->rowCount();
0856     QCOMPARE(np, 4);
0857 
0858     for (int i = 0; i < np; i++) {
0859         DEBUG(std::setprecision(15) << resultXDataColumn->valueAt(i));
0860         QCOMPARE(resultXDataColumn->valueAt(i), (double)i * correlationData.samplingInterval);
0861     }
0862 
0863     QCOMPARE(resultYDataColumn->valueAt(0), 2.);
0864     QCOMPARE(resultYDataColumn->valueAt(1), 4.5);
0865     QCOMPARE(resultYDataColumn->valueAt(2), 5.);
0866     QCOMPARE(resultYDataColumn->valueAt(3), 3.5);
0867 }
0868 
0869 void CorrelationTest::testCircular2_samplingInterval() {
0870     // data
0871     QVector<double> yData = {1., 2., 3.};
0872     QVector<double> y2Data = {0, 1., .5};
0873 
0874     // data source columns
0875     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0876     yDataColumn.replaceValues(0, yData);
0877 
0878     Column y2DataColumn(QStringLiteral("y2"), AbstractColumn::ColumnMode::Double);
0879     y2DataColumn.replaceValues(0, y2Data);
0880 
0881     XYCorrelationCurve correlationCurve(QStringLiteral("correlation"));
0882     correlationCurve.setYDataColumn(&yDataColumn);
0883     correlationCurve.setY2DataColumn(&y2DataColumn);
0884 
0885     // prepare the correlation
0886     XYCorrelationCurve::CorrelationData correlationData = correlationCurve.correlationData();
0887     correlationData.type = nsl_corr_type_circular;
0888     correlationData.samplingInterval = 0.1;
0889     correlationCurve.setCorrelationData(correlationData);
0890 
0891     // perform the correlation
0892     correlationCurve.recalculate();
0893     const XYCorrelationCurve::CorrelationResult& correlationResult = correlationCurve.correlationResult();
0894 
0895     // check the results
0896     QCOMPARE(correlationResult.available, true);
0897     QCOMPARE(correlationResult.valid, true);
0898 
0899     const AbstractColumn* resultXDataColumn = correlationCurve.xColumn();
0900     const AbstractColumn* resultYDataColumn = correlationCurve.yColumn();
0901 
0902     const int np = resultXDataColumn->rowCount();
0903     QCOMPARE(np, 3);
0904 
0905     for (int i = 0; i < np; i++) {
0906         DEBUG(std::setprecision(15) << resultXDataColumn->valueAt(i));
0907         QCOMPARE(resultXDataColumn->valueAt(i), (double)i * correlationData.samplingInterval);
0908     }
0909 
0910     QCOMPARE(resultYDataColumn->valueAt(0), 2.);
0911     QCOMPARE(resultYDataColumn->valueAt(1), 3.5);
0912     QCOMPARE(resultYDataColumn->valueAt(2), 3.5);
0913 }
0914 
0915 void CorrelationTest::testPerformance() {
0916     // data
0917     QVector<double> yData, y2Data;
0918 #ifdef HAVE_FFTW3
0919     const int N = 1e6;
0920 #else // GSL is much slower
0921     const int N = 5e4;
0922 #endif
0923     for (int i = 0; i < N; i++) {
0924         yData.append(i % 100);
0925         y2Data.append(i % 10);
0926     }
0927 
0928     // data source columns
0929     Column yDataColumn(QStringLiteral("y"), AbstractColumn::ColumnMode::Double);
0930     yDataColumn.replaceValues(0, yData);
0931 
0932     Column y2DataColumn(QStringLiteral("y2"), AbstractColumn::ColumnMode::Double);
0933     y2DataColumn.replaceValues(0, y2Data);
0934 
0935     XYCorrelationCurve correlationCurve(QStringLiteral("correlation"));
0936     correlationCurve.setYDataColumn(&yDataColumn);
0937     correlationCurve.setY2DataColumn(&y2DataColumn);
0938 
0939     // prepare and perform the correlation
0940     XYCorrelationCurve::CorrelationData correlationData = correlationCurve.correlationData();
0941     QBENCHMARK {
0942         // triggers recalculate()
0943         correlationCurve.setCorrelationData(correlationData);
0944     }
0945 
0946     // check the results
0947     const XYCorrelationCurve::CorrelationResult& correlationResult = correlationCurve.correlationResult();
0948 
0949     QCOMPARE(correlationResult.available, true);
0950     QCOMPARE(correlationResult.valid, true);
0951 
0952     const AbstractColumn* resultXDataColumn = correlationCurve.xColumn();
0953 
0954     const int np = resultXDataColumn->rowCount();
0955     QCOMPARE(np, 2 * N - 1);
0956 }
0957 
0958 QTEST_MAIN(CorrelationTest)