diff --git a/CMakeLists.txt.user.4.8-pre1 b/CMakeLists.txt.user.4.8-pre1 new file mode 100644 index 000000000..1d263cec5 --- /dev/null +++ b/CMakeLists.txt.user.4.8-pre1 @@ -0,0 +1,1756 @@ + + + + + + EnvironmentId + {8aab856c-4268-430e-935d-1fc6c3939b19} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + {a4fe69e5-b48a-40e0-b2f6-ff46a3365815} + 0 + 0 + 0 + + + /home/deva/build-labplot-Desktop-Default + + + + + all + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Build + + ProjectExplorer.BuildSteps.Build + + + + + + clean + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Default + Default + CMakeProjectManager.CMakeBuildConfiguration + + + + CMAKE_BUILD_TYPE:STRING=Debug + + /home/deva/build-labplot-Desktop-Debug + + + + + all + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Build + + ProjectExplorer.BuildSteps.Build + + + + + + clean + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + Debug + CMakeProjectManager.CMakeBuildConfiguration + + + + CMAKE_BUILD_TYPE:STRING=Release + + /home/deva/build-labplot-Desktop-Release + + + + + all + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Build + + ProjectExplorer.BuildSteps.Build + + + + + + clean + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + Release + CMakeProjectManager.CMakeBuildConfiguration + + + + CMAKE_BUILD_TYPE:STRING=RelWithDebInfo + + /home/deva/build-labplot-Desktop-Release with Debug Information + + + + + all + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Build + + ProjectExplorer.BuildSteps.Build + + + + + + clean + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release with Debug Information + Release with Debug Information + CMakeProjectManager.CMakeBuildConfiguration + + + + CMAKE_BUILD_TYPE:STRING=MinSizeRel + + /home/deva/build-labplot-Desktop-Minimum Size Release + + + + + all + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Build + + ProjectExplorer.BuildSteps.Build + + + + + + clean + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Minimum Size Release + Minimum Size Release + CMakeProjectManager.CMakeBuildConfiguration + + 5 + + + 0 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + Deploy locally + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + labplot2 + + + /tmp/QtCreator-zKyLSD/qtc-cmake-XXH4cuqI/src + 2 + + labplot2 + + CMakeProjectManager.CMakeRunConfiguration.labplot2 + 3768 + false + true + false + false + true + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + differentiationtest + + + /tmp/QtCreator-zKyLSD/qtc-cmake-XXH4cuqI/tests/analysis/differentiation + -1 + + differentiationtest + + CMakeProjectManager.CMakeRunConfiguration.differentiationtest + 3768 + false + true + false + false + true + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + nsldifftest + + + /tmp/QtCreator-zKyLSD/qtc-cmake-XXH4cuqI/tests/nsl/diff + -1 + + nsldifftest + + CMakeProjectManager.CMakeRunConfiguration.nsldifftest + 3768 + false + true + false + false + true + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + nslinttest + + + /tmp/QtCreator-zKyLSD/qtc-cmake-XXH4cuqI/tests/nsl/int + -1 + + nslinttest + + CMakeProjectManager.CMakeRunConfiguration.nslinttest + 3768 + false + true + false + false + true + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + nslsfwindowtest + + + /tmp/QtCreator-zKyLSD/qtc-cmake-XXH4cuqI/tests/nsl/sf + -1 + + nslsfwindowtest + + CMakeProjectManager.CMakeRunConfiguration.nslsfwindowtest + 3768 + false + true + false + false + true + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + nslsfbasictest + + + /tmp/QtCreator-zKyLSD/qtc-cmake-XXH4cuqI/tests/nsl/sf + -1 + + nslsfbasictest + + CMakeProjectManager.CMakeRunConfiguration.nslsfbasictest + 3768 + false + true + false + false + true + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + nslsmoothtest + + + /tmp/QtCreator-zKyLSD/qtc-cmake-XXH4cuqI/tests/nsl/smooth + -1 + + nslsmoothtest + + CMakeProjectManager.CMakeRunConfiguration.nslsmoothtest + 3768 + false + true + false + false + true + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + integrationtest + + + /tmp/QtCreator-zKyLSD/qtc-cmake-XXH4cuqI/tests/analysis/integration + -1 + + integrationtest + + CMakeProjectManager.CMakeRunConfiguration.integrationtest + 3768 + false + true + false + false + true + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + fittest + + + /tmp/QtCreator-zKyLSD/qtc-cmake-XXH4cuqI/tests/analysis/fit + -1 + + fittest + + CMakeProjectManager.CMakeRunConfiguration.fittest + 3768 + false + true + false + false + true + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + convolutiontest + + + /tmp/QtCreator-zKyLSD/qtc-cmake-XXH4cuqI/tests/analysis/convolution + -1 + + convolutiontest + + CMakeProjectManager.CMakeRunConfiguration.convolutiontest + 3768 + false + true + false + false + true + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + correlationtest + + + /tmp/QtCreator-zKyLSD/qtc-cmake-XXH4cuqI/tests/analysis/correlation + -1 + + correlationtest + + CMakeProjectManager.CMakeRunConfiguration.correlationtest + 3768 + false + true + false + false + true + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + asciifiltertest + + + /tmp/QtCreator-zKyLSD/qtc-cmake-XXH4cuqI/tests/import_export/ASCII + -1 + + asciifiltertest + + CMakeProjectManager.CMakeRunConfiguration.asciifiltertest + 3768 + false + true + false + false + true + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + jsonfiltertest + + + /tmp/QtCreator-zKyLSD/qtc-cmake-XXH4cuqI/tests/import_export/JSON + -1 + + jsonfiltertest + + CMakeProjectManager.CMakeRunConfiguration.jsonfiltertest + 3768 + false + true + false + false + true + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + projectimporttest + + + /tmp/QtCreator-zKyLSD/qtc-cmake-XXH4cuqI/tests/import_export/project + -1 + + projectimporttest + + CMakeProjectManager.CMakeRunConfiguration.projectimporttest + 3768 + false + true + false + false + true + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + nsldfttest + + + /tmp/QtCreator-zKyLSD/qtc-cmake-XXH4cuqI/tests/nsl/dft + -1 + + nsldfttest + + CMakeProjectManager.CMakeRunConfiguration.nsldfttest + 3768 + false + true + false + false + true + + 15 + + + + ProjectExplorer.Project.Target.1 + + Imported Kit + Imported Kit + {5dc9fd71-2911-42ea-ae59-b3f509566709} + 0 + 0 + 0 + + + /home/deva/build-labplot-Imported_Kit_5dc9fd-Default + + + + + all + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Build + + ProjectExplorer.BuildSteps.Build + + + + + + clean + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Default + Default + CMakeProjectManager.CMakeBuildConfiguration + + + + CMAKE_BUILD_TYPE:STRING=Debug + + /home/deva/build-labplot-Imported_Kit_5dc9fd-Debug + + + + + all + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Build + + ProjectExplorer.BuildSteps.Build + + + + + + clean + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + Debug + CMakeProjectManager.CMakeBuildConfiguration + + + + CMAKE_BUILD_TYPE:STRING=Release + + /home/deva/build-labplot-Imported_Kit_5dc9fd-Release + + + + + all + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Build + + ProjectExplorer.BuildSteps.Build + + + + + + clean + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + Release + CMakeProjectManager.CMakeBuildConfiguration + + + + CMAKE_BUILD_TYPE:STRING=RelWithDebInfo + + /home/deva/build-labplot-Imported_Kit_5dc9fd-Release with Debug Information + + + + + all + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Build + + ProjectExplorer.BuildSteps.Build + + + + + + clean + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release with Debug Information + Release with Debug Information + CMakeProjectManager.CMakeBuildConfiguration + + + + CMAKE_BUILD_TYPE:STRING=MinSizeRel + + /home/deva/build-labplot-Imported_Kit_5dc9fd-Minimum Size Release + + + + + all + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Build + + ProjectExplorer.BuildSteps.Build + + + + + + clean + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Minimum Size Release + Minimum Size Release + CMakeProjectManager.CMakeBuildConfiguration + + 5 + + + 0 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + Deploy locally + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + -1 + + + + %{buildDir} + Custom Executable + + ProjectExplorer.CustomExecutableRunConfiguration + 3768 + false + true + false + false + true + + 1 + + + + ProjectExplorer.Project.Target.2 + + Imported Kit + Imported Kit + {8e99deae-104f-42a6-b97e-de9375803f55} + 0 + 0 + 0 + + + /home/deva/build-labplot-Imported_Kit_8e99de-Default + + + + + all + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Build + + ProjectExplorer.BuildSteps.Build + + + + + + clean + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Default + Default + CMakeProjectManager.CMakeBuildConfiguration + + + + CMAKE_BUILD_TYPE:STRING=Debug + + /home/deva/build-labplot-Imported_Kit_8e99de-Debug + + + + + all + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Build + + ProjectExplorer.BuildSteps.Build + + + + + + clean + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + Debug + CMakeProjectManager.CMakeBuildConfiguration + + + + CMAKE_BUILD_TYPE:STRING=Release + + /home/deva/build-labplot-Imported_Kit_8e99de-Release + + + + + all + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Build + + ProjectExplorer.BuildSteps.Build + + + + + + clean + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + Release + CMakeProjectManager.CMakeBuildConfiguration + + + + CMAKE_BUILD_TYPE:STRING=RelWithDebInfo + + /home/deva/build-labplot-Imported_Kit_8e99de-Release with Debug Information + + + + + all + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Build + + ProjectExplorer.BuildSteps.Build + + + + + + clean + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release with Debug Information + Release with Debug Information + CMakeProjectManager.CMakeBuildConfiguration + + + + CMAKE_BUILD_TYPE:STRING=MinSizeRel + + /home/deva/build-labplot-Imported_Kit_8e99de-Minimum Size Release + + + + + all + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Build + + ProjectExplorer.BuildSteps.Build + + + + + + clean + + true + CMake Build + + CMakeProjectManager.MakeStep + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Minimum Size Release + Minimum Size Release + CMakeProjectManager.CMakeBuildConfiguration + + 5 + + + 0 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + Deploy locally + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + -1 + + + + %{buildDir} + Custom Executable + + ProjectExplorer.CustomExecutableRunConfiguration + 3768 + false + true + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 3 + + + ProjectExplorer.Project.Updater.FileVersion + 18 + + + Version + 18 + + diff --git a/src/backend/hypothesis_test/HypothesisTest.cpp b/src/backend/hypothesis_test/HypothesisTest.cpp index 506464c4f..1dcdd74da 100644 --- a/src/backend/hypothesis_test/HypothesisTest.cpp +++ b/src/backend/hypothesis_test/HypothesisTest.cpp @@ -1,929 +1,766 @@ /*************************************************************************** File : HypothesisTest.cpp Project : LabPlot Description : Doing Hypothesis-Test on data provided -------------------------------------------------------------------- Copyright : (C) 2019 Devanshu Agarwal(agarwaldevanshu8@gmail.com) ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "HypothesisTest.h" #include "HypothesisTestPrivate.h" #include "kdefrontend/hypothesis_test/HypothesisTestView.h" #include "backend/spreadsheet/Spreadsheet.h" #include "backend/core/column/Column.h" #include "backend/lib/macros.h" #include "QDebug" extern "C" { #include "backend/nsl/nsl_stats.h" } #include #include #include #include #include #include #include #include HypothesisTest::HypothesisTest(const QString &name) : AbstractPart(name), -d(new HypothesisTestPrivate(this)) { + d(new HypothesisTestPrivate(this)) { } HypothesisTest::~HypothesisTest() { delete d; } void HypothesisTest::setDataSourceType(DataSourceType type) { if (type != d->dataSourceType) { d->dataSourceType = type; } } void HypothesisTest::setDataSourceSpreadsheet(Spreadsheet *spreadsheet) { if (spreadsheet != d->dataSourceSpreadsheet) d->setDataSourceSpreadsheet(spreadsheet); } QStringList HypothesisTest::allColumns() { return d->all_columns; } HypothesisTest::TailType HypothesisTest::tailType() { return d->tail_type; } void HypothesisTest::setPopulationMean(QVariant populationMean) { d->m_population_mean = populationMean.toDouble(); } void HypothesisTest::setSignificanceLevel(QVariant alpha) { d->m_significance_level = alpha.toDouble(); } void HypothesisTest::setTailType(HypothesisTest::TailType tailType) { d->tail_type = tailType; } void HypothesisTest::setColumns(QVector cols) { d->m_columns = cols; } void HypothesisTest::setColumns(QStringList cols) { return d->setColumns(cols); } HypothesisTest::DataSourceType HypothesisTest::dataSourceType() const { return d->dataSourceType; } void HypothesisTest::performTwoSampleTTest() { } void HypothesisTest::performTwoSampleIndependentTTest(bool equal_variance) { d->performTwoSampleIndependentTest(HypothesisTestPrivate::TestT, equal_variance); + d->m_currTestName = "

Two Sample Independent T Test

"; } void HypothesisTest::performTwoSamplePairedTTest() { d->performTwoSamplePairedTest(HypothesisTestPrivate::TestT); + d->m_currTestName = "

Two Sample Paried T Test

"; } void HypothesisTest::PerformOneSampleTTest() { d->PerformOneSampleTest(HypothesisTestPrivate::TestT); + d->m_currTestName = "

One Sample T Test

"; } void HypothesisTest::performTwoSampleIndependentZTest() { d->performTwoSampleIndependentTest(HypothesisTestPrivate::TestZ); + d->m_currTestName = "

Two Sample Independent Z Test

"; } void HypothesisTest::performTwoSamplePairedZTest() { d->performTwoSamplePairedTest(HypothesisTestPrivate::TestZ); + d->m_currTestName = "

Two Sample Paired Z Test

"; } void HypothesisTest::PerformOneSampleZTest() { d->PerformOneSampleTest(HypothesisTestPrivate::TestZ); + d->m_currTestName = "

One Sample Z Test

"; } - QString HypothesisTest::testName() { return d->m_currTestName; } QString HypothesisTest::statsTable() { return d->m_stats_table; } -QString HypothesisTest::summaryResultText() { - return d->m_summary_results; -} /****************************************************************************** * Private Implementations * ****************************************************************************/ HypothesisTestPrivate::HypothesisTestPrivate(HypothesisTest* owner) : q(owner) , dataModel(new QStandardItemModel) , horizontalHeaderModel(new QStandardItemModel) , verticalHeaderModel(new QStandardItemModel) , resultModel(new QStandardItemModel()){ } HypothesisTestPrivate::~HypothesisTestPrivate() { } void HypothesisTestPrivate::setDataSourceSpreadsheet(Spreadsheet *spreadsheet) { dataSourceSpreadsheet = spreadsheet; //setting rows and columns count; m_rowCount = dataSourceSpreadsheet->rowCount(); m_columnCount = dataSourceSpreadsheet->columnCount(); for (auto* col : dataSourceSpreadsheet->children()) { all_columns << col->name(); } } void HypothesisTestPrivate::setColumns(QStringList cols) { m_columns.clear(); Column* column = new Column("column"); for (QString col : cols) { if (!cols.isEmpty()) { column = dataSourceSpreadsheet->column(col); m_columns.append(column); } } } /**************************Two Sample Independent *************************************/ void HypothesisTestPrivate::performTwoSampleIndependentTest(TestType test, bool equal_variance) { - dataModel->clear(); - horizontalHeaderModel->clear(); - verticalHeaderModel->clear(); - resultModel->clear(); + QString test_name; + + double value; + int df; + double p_value = 0; + clearGlobalVariables(); - QMessageBox* msg_box = new QMessageBox(); - // checking for cols; if (m_columns.size() != 2) { - msg_box->setText(i18n("Inappropriate number of columns selected")); - msg_box->exec(); + printError("Inappropriate number of columns selected"); + emit q->changed(); return; } int n[2]; double sum[2], mean[2], std[2]; QString col1_name = m_columns[0]->name(); QString col2_name = m_columns[1]->name(); if (m_columns[0]->columnMode() == AbstractColumn::Integer || m_columns[0]->columnMode() == AbstractColumn::Numeric) { for (int i = 0; i < 2; i++) { findStats(m_columns[i], n[i], sum[i], mean[i], std[i]); if (n[i] < 1) { - msg_box->setText(i18n("At least one of selected column is empty")); - msg_box->exec(); + printError("At least one of selected column is empty"); + emit q->changed(); return; } } - } - else { + } else { findStatsCategorical(n, sum, mean, std, col1_name, col2_name); if (n[0] == -1) { - msg_box->setText(i18n("Unequal size between %1 and %2", m_columns[0]->name(), m_columns[1]->name())); - msg_box->exec(); + printError( i18n("Unequal size between %1 and %2", m_columns[0]->name(), m_columns[1]->name())); + emit q->changed(); return; } else if(n[0] == -2) { - msg_box->setText(i18n("There are more than two categorical variables in %1", m_columns[0]->name())); - msg_box->exec(); + printError( i18n("There are more than two categorical variables in %1", m_columns[0]->name())); + emit q->changed(); return; } else if (n[0] == 0) { - msg_box->setText(i18n("atleast one of selected column is empty")); - msg_box->exec(); + printError("atleast one of selected column is empty"); + emit q->changed(); return; } } QVariant row_major[] = {"", "N", "Sum", "Mean", "Std", col1_name, n[0], sum[0], mean[0], std[0], col2_name, n[1], sum[1], mean[1], std[1]}; m_stats_table = getHtmlTable(3, 5, row_major); switch (test) { - case TestT: { - m_currTestName = i18n("Two Sample Independent T Test for %1 vs %2", col1_name, col2_name); - double t_value; - int df; - QString temp_msg = ""; - double p_value = 0; - m_summary_results = ""; - - if (equal_variance) { - df = n[0] + n[1] - 2; - double sp = qSqrt( ((n[0]-1)*qPow(std[0],2) + (n[1]-1)*qPow(std[1],2))/df); - t_value = (mean[0] - mean[1])/(sp*qSqrt(1.0/n[0] + 1.0/n[1])); - } else { - double temp_val; - temp_val = qPow( qPow(std[0], 2)/n[0] + qPow(std[1], 2)/n[1], 2); - temp_val = temp_val / ( (qPow( (qPow(std[0], 2)/n[0]), 2)/(n[0]-1)) + (qPow( (qPow(std[1], 2)/n[1]), 2)/(n[1]-1))); - df = qRound(temp_val); - - t_value = (mean[0] - mean[1]) / (qSqrt( (qPow(std[0], 2)/n[0]) + (qPow(std[1], 2)/n[1]))); - } - switch (tail_type) { - case HypothesisTest::TailNegative: - p_value = nsl_stats_tdist_p(t_value, df); - m_summary_results += i18n("

Null Hypothesis: Population mean of %1 %2 Population mean of %3
", col1_name, UTF8_QSTRING("≥"), col2_name); - m_summary_results += i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3
", col1_name, UTF8_QSTRING("â‹–"), col2_name); - break; - case HypothesisTest::TailPositive: - t_value *= -1; - p_value = nsl_stats_tdist_p(t_value, df); - m_summary_results += i18n("

Null Hypothesis: Population mean of %1 %2 Population mean of %3
", col1_name, UTF8_QSTRING("≤"), col2_name); - m_summary_results += i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3
", col1_name, UTF8_QSTRING(">"), col2_name); - break; - case HypothesisTest::TailTwo: - p_value = nsl_stats_tdist_p(t_value, df) + nsl_stats_tdist_p(-1*t_value, df); - - m_summary_results += i18n("

Null Hypothesis: Population mean of %1 %2 Population mean of %3
", col1_name, UTF8_QSTRING("="), col2_name); - m_summary_results += i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3
", col1_name, UTF8_QSTRING("≠"), col2_name); - break; - } - - m_summary_results += i18n("Significance level is %1

", m_significance_level); - m_summary_results += i18n("

T Value is %1
", t_value); - - if (p_value <= m_significance_level) - temp_msg = i18n("We can safely reject Null Hypothesis for significance level %1", m_significance_level); - else - temp_msg = i18n("There is a plausibility for Null Hypothesis to be true"); - - m_summary_results += i18n("" - " Hover over me %1" - "", temp_msg); - -// m_summary_results += i18n("

P Value is %1" -// " %2" -// "
", p_value, temp_msg); - - m_summary_results += i18n("Degree of Freedom is %1setRowCount(8); - resultModel->setColumnCount(1); + case TestT: { + test_name = "T"; + if (equal_variance) { df = n[0] + n[1] - 2; - - //Assuming equal variance double sp = qSqrt( ((n[0]-1)*qPow(std[0],2) + (n[1]-1)*qPow(std[1],2))/df); - z_value = (mean[0] - mean[1])/(sp*qSqrt(1.0/n[0] + 1.0/n[1])); - - switch (tail_type) { - case HypothesisTest::TailNegative: - p_value = nsl_stats_tdist_p(z_value, df); - m_summary_results += i18n("

Null Hypothesis: Population mean of %1 %2 Population mean of %3
", col1_name, UTF8_QSTRING("≥"), col2_name); - m_summary_results += i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3
", col1_name, UTF8_QSTRING("â‹–"), col2_name); - break; - case HypothesisTest::TailPositive: - z_value *= -1; - p_value = nsl_stats_tdist_p(z_value, df); - m_summary_results += i18n("

Null Hypothesis: Population mean of %1 %2 Population mean of %3
", col1_name, UTF8_QSTRING("≤"), col2_name); - m_summary_results += i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3
", col1_name, UTF8_QSTRING(">"), col2_name); - break; - case HypothesisTest::TailTwo: - p_value = nsl_stats_tdist_p(z_value, df) + nsl_stats_tdist_p(-1*z_value, df); - m_summary_results += i18n("

Null Hypothesis: Population mean of %1 %2 Population mean of %3
", col1_name, UTF8_QSTRING("="), col2_name); - m_summary_results += i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3
", col1_name, UTF8_QSTRING("≠"), col2_name); - break; - } + value = (mean[0] - mean[1])/(sp*qSqrt(1.0/n[0] + 1.0/n[1])); + } else { + double temp_val; + temp_val = qPow( qPow(std[0], 2)/n[0] + qPow(std[1], 2)/n[1], 2); + temp_val = temp_val / ( (qPow( (qPow(std[0], 2)/n[0]), 2)/(n[0]-1)) + (qPow( (qPow(std[1], 2)/n[1]), 2)/(n[1]-1))); + df = qRound(temp_val); + value = (mean[0] - mean[1]) / (qSqrt( (qPow(std[0], 2)/n[0]) + (qPow(std[1], 2)/n[1]))); + } + break; + } case TestZ: { + test_name = "Z"; + df = n[0] + n[1] - 2; - resultModel->setData(resultModel->index(3, 0), i18n("Z value is %1", z_value), Qt::DisplayRole); - resultModel->setData(resultModel->index(4, 0), i18n("P value is %1", p_value), Qt::DisplayRole); - resultModel->setData(resultModel->index(5, 0), i18n("Significance level is %1", m_significance_level), Qt::DisplayRole); + double sp = qSqrt( ((n[0]-1)*qPow(std[0],2) + (n[1]-1)*qPow(std[1],2))/df); + value = (mean[0] - mean[1])/(sp*qSqrt(1.0/n[0] + 1.0/n[1])); + } + } - resultModel->setData(resultModel->index(7, 0), i18n("Assumption: Central Limit Theorem is Valid"), Qt::DisplayRole); + m_currTestName = i18n("

Two Sample Independent %1 Test for %2 vs %3

", test_name, col1_name, col2_name); + p_value = getPValue(test, value, col1_name, col2_name, df); - if (p_value <= m_significance_level) - temp_msg = i18n("We can safely reject Null Hypothesis for significance level %1", m_significance_level); - else - temp_msg = i18n("There is a plausibility for Null Hypothesis to be true"); + printLine(2, i18n("Significance level is %1", m_significance_level), "blue"); + printLine(4, i18n("%1 Value is %2 ", test_name, value), "green"); + printLine(5, i18n("P Value is %1 ", p_value), "green"); + printLine(6, i18n("Degree of Freedom is %1", df), "green"); + + if (p_value <= m_significance_level) + q->m_view->setResultLine(5, i18n("We can safely reject Null Hypothesis for significance level %1", m_significance_level), Qt::ToolTipRole); + else + q->m_view->setResultLine(5, i18n("There is a plausibility for Null Hypothesis to be true"), Qt::ToolTipRole); - // tool tips - resultModel->setData(resultModel->index(4, 0), temp_msg, Qt::ToolTipRole); - // resultModel->setData(resultModel->index(0, 0), QIcon("open.xpm"), Qt::DecorationRole); - break; - } - } emit q->changed(); return; - } /********************************Two Sample Paired ***************************************/ void HypothesisTestPrivate::performTwoSamplePairedTest(TestType test) { - dataModel->clear(); - horizontalHeaderModel->clear(); - verticalHeaderModel->clear(); - resultModel->clear(); - + QString test_name; + int n; + double sum, mean, std; + double value; + int df; + double p_value = 0; + clearGlobalVariables(); - QMessageBox* msg_box = new QMessageBox(); - // checking for cols; if (m_columns.size() != 2) { - msg_box->setText(i18n("Inappropriate number of columns selected")); - msg_box->exec(); + printError("Inappropriate number of columns selected"); + emit q->changed(); return; } - bool modeOk = true; for (int i = 0; i < 2; i++) { - if(m_columns[i]->columnMode() == AbstractColumn::Numeric || m_columns[i]->columnMode() == AbstractColumn::Integer) - continue; - modeOk = false; - } - - - if (!modeOk) { - msg_box->setText(i18n("select only columns with numbers")); - msg_box->exec(); - return; + if (!(m_columns[i]->columnMode() == AbstractColumn::Numeric || m_columns[i]->columnMode() == AbstractColumn::Integer)) { + printError("select only columns with numbers"); + emit q->changed(); + return; + } } - int n; - double sum, mean, std; findStatsPaired(m_columns[0], m_columns[1], n, sum, mean, std); if (n == -1) { - msg_box->setText(i18n("both columns are having different sizes")); - msg_box->exec(); + printError("both columns are having different sizes"); + emit q->changed(); return; } if (n < 1) { - msg_box->setText(i18n("columns are empty")); - msg_box->exec(); + printError("columns are empty"); + emit q->changed(); return; } QVariant row_major[] = {"", "N", "Sum", "Mean", "Std", "difference", n, sum, mean, std}; m_stats_table = getHtmlTable(2, 5, row_major); - if (test == TestT) { - m_currTestName = i18n("Two Sample Paired T Test for %1 vs %2", m_columns[0]->name(), m_columns[1]->name()); - double t_value; - int df; - QString temp_msg = ""; - double p_value = 0; - m_summary_results = ""; - - resultModel->setRowCount(7); - resultModel->setColumnCount(1); - - t_value = mean / (std/qSqrt(n)); - df = n - 1; - switch (tail_type) { - case HypothesisTest::TailNegative: - p_value = nsl_stats_tdist_p(t_value, df); - m_summary_results += i18n("

Null Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING("≥"), m_columns[1]->name()); - m_summary_results += i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING("â‹–"), m_columns[1]->name()); - break; - case HypothesisTest::TailPositive: - t_value *= -1; - p_value = nsl_stats_tdist_p(t_value, df); - m_summary_results += i18n("

Null Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING("≤"), m_columns[1]->name()); - m_summary_results += i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING(">"), m_columns[1]->name()); - break; - case HypothesisTest::TailTwo: - p_value = nsl_stats_tdist_p(t_value, df) + nsl_stats_tdist_p(-1*t_value, df); - m_summary_results += i18n("

Null Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING("="), m_columns[1]->name()); - m_summary_results += i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING("≠"), m_columns[1]->name()); - break; - } - - - resultModel->setData(resultModel->index(3, 0), i18n("T value is %1", t_value), Qt::DisplayRole); - resultModel->setData(resultModel->index(4, 0), i18n("P value is %1", p_value), Qt::DisplayRole); - resultModel->setData(resultModel->index(5, 0), i18n("DoF is %1", df), Qt::DisplayRole); - resultModel->setData(resultModel->index(6, 0), i18n("Significance level is %1", m_significance_level), Qt::DisplayRole); - - if (p_value <= m_significance_level) - temp_msg = i18n("We can safely reject Null Hypothesis for significance level %1", m_significance_level); - else - temp_msg = i18n("There is a plausibility for Null Hypothesis to be true"); - - // tool tips - resultModel->setData(resultModel->index(4, 0), temp_msg, Qt::ToolTipRole); -// resultModel->setData(resultModel->index(0, 0), QIcon("open.xpm"), Qt::DecorationRole); - - emit q->changed(); - return; - } - else if (test == TestZ) { - m_currTestName = i18n("Two Sample Paired Z Test for %1 vs %2", m_columns[0]->name(), m_columns[1]->name()); - double z_value; - int df; - QString temp_msg = ""; - double p_value = 0; - m_summary_results = ""; - - resultModel->setRowCount(8); - resultModel->setColumnCount(1); - - z_value = mean / (std/qSqrt(n)); + switch (test) { + case TestT: { + value = mean / (std/qSqrt(n)); df = n - 1; + test_name = "T"; + printLine(6, i18n("Degree of Freedom is %1Null Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING("≥"), m_columns[1]->name()); - m_summary_results += i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING("â‹–"), m_columns[1]->name()); - break; - case HypothesisTest::TailPositive: - z_value *= -1; - m_summary_results += i18n("

Null Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING("≤"), m_columns[1]->name()); - m_summary_results += i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING(">"), m_columns[1]->name()); - break; - case HypothesisTest::TailTwo: - p_value = nsl_stats_tdist_p(z_value, df) + nsl_stats_tdist_p(-1*z_value, df); - m_summary_results += i18n("

Null Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING("="), m_columns[1]->name()); - m_summary_results += i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING("≠"), m_columns[1]->name()); - break; - } - - resultModel->setData(resultModel->index(3, 0), i18n("Z value is %1", z_value), Qt::DisplayRole); - resultModel->setData(resultModel->index(4, 0), i18n("P value is %1", p_value), Qt::DisplayRole); - resultModel->setData(resultModel->index(5, 0), i18n("Significance level is %1", m_significance_level), Qt::DisplayRole); - - resultModel->setData(resultModel->index(7, 0), i18n("Assumption: Central Limit Theorem is Valid"), Qt::DisplayRole); - - if (p_value <= m_significance_level) - temp_msg = i18n("We can safely reject Null Hypothesis for significance level %1", m_significance_level); - else - temp_msg = i18n("There is a plausibility for Null Hypothesis to be true"); - - // tool tips - resultModel->setData(resultModel->index(4, 0), temp_msg, Qt::ToolTipRole); - // resultModel->setData(resultModel->index(0, 0), QIcon("open.xpm"), Qt::DecorationRole); + p_value = getPValue(test, value, m_columns[0]->name(), i18n("%1",m_population_mean), df); + m_currTestName = i18n("

One Sample %1 Test for %2 vs %3

", test_name, m_columns[0]->name(), m_columns[1]->name()); + printLine(2, i18n("Significance level is %1

", m_significance_level), "blue"); + printLine(4, i18n("%1 Value is %2

", test_name, value), "green"); + printLine(5, i18n("P Value is %1

", p_value), "green"); + if (p_value <= m_significance_level) + q->m_view->setResultLine(5, i18n("We can safely reject Null Hypothesis for significance level %1", m_significance_level), Qt::ToolTipRole); + else + q->m_view->setResultLine(5, i18n("There is a plausibility for Null Hypothesis to be true"), Qt::ToolTipRole); + emit q->changed(); + return; - emit q->changed(); - return; - } } /******************************** One Sample ***************************************/ void HypothesisTestPrivate::PerformOneSampleTest(TestType test) { - dataModel->clear(); - horizontalHeaderModel->clear(); - verticalHeaderModel->clear(); - resultModel->clear(); + QString test_name; + double value; + int df; + double p_value = 0; + clearGlobalVariables(); - QMessageBox* msg_box = new QMessageBox(); - // checking for cols; if (m_columns.size() != 1) { - msg_box->setText(i18n("Inappropriate number of columns selected")); - msg_box->exec(); + printError("Inappropriate number of columns selected"); + emit q->changed(); return; } if ( !(m_columns[0]->columnMode() == AbstractColumn::Numeric || m_columns[0]->columnMode() == AbstractColumn::Integer)) { - msg_box->setText(i18n("select only columns with numbers")); - msg_box->exec(); + printError("select only columns with numbers"); + emit q->changed(); return; } int n; double sum, mean, std; findStats(m_columns[0], n, sum, mean, std); if (n < 1) { - msg_box->setText(i18n("column is empty")); - msg_box->exec(); + printError("column is empty"); + emit q->changed(); return; } - QVariant row_major[] = {"", "N", "Sum", "Mean", "Std", m_columns[0]->name(), n, sum, mean, std}; m_stats_table = getHtmlTable(2, 5, row_major); - if (test == TestT) { - m_currTestName = i18n("One Sample T Test for %1", m_columns[0]->name()); - double t_value; - int df; - QString temp_msg = ""; - double p_value = 0; - m_summary_results = ""; - - resultModel->setRowCount(7); - resultModel->setColumnCount(1); - - t_value = (mean - m_population_mean) / (std/qSqrt(n)); - df = n - 1; - - switch (tail_type) { - case HypothesisTest::TailNegative: - p_value = nsl_stats_tdist_p(t_value, df); - m_summary_results += i18n("

Null Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING("≥"), m_population_mean); - m_summary_results += i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING("â‹–"), m_population_mean); - break; - case HypothesisTest::TailPositive: - t_value *= -1; - p_value = nsl_stats_tdist_p(t_value, df); - m_summary_results += i18n("

Null Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING("≤"), m_population_mean); - m_summary_results += i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING(">"), m_population_mean); - break; - case HypothesisTest::TailTwo: - p_value = nsl_stats_tdist_p(t_value, df) + nsl_stats_tdist_p(-1*t_value, df); - m_summary_results += i18n("

Null Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING("="), m_population_mean); - m_summary_results += i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING("≠"), m_population_mean); - break; - } - - - resultModel->setData(resultModel->index(3, 0), i18n("T value is %1", t_value), Qt::DisplayRole); - resultModel->setData(resultModel->index(4, 0), i18n("P value is %1", p_value), Qt::DisplayRole); - resultModel->setData(resultModel->index(5, 0), i18n("DoF is %1", df), Qt::DisplayRole); - resultModel->setData(resultModel->index(6, 0), i18n("Significance level is %1", m_significance_level), Qt::DisplayRole); - - if (p_value <= m_significance_level) - temp_msg = i18n("We can safely reject Null Hypothesis for significance level %1", m_significance_level); - else - temp_msg = i18n("There is a plausibility for Null Hypothesis to be true"); - - // tool tips - resultModel->setData(resultModel->index(4, 0), temp_msg, Qt::ToolTipRole); -// resultModel->setData(resultModel->index(0, 0), QIcon("open.xpm"), Qt::DecorationRole); - - - emit q->changed(); - return; - } - else if (test == TestZ) { - m_currTestName = i18n("One Sample Z Test for %1", m_columns[0]->name()); - double z_value; - int df; - QString temp_msg = ""; - double p_value = 0; - m_summary_results = ""; - - resultModel->setRowCount(8); - resultModel->setColumnCount(1); - - z_value = (mean - m_population_mean) / (std/qSqrt(n)); + switch (test) { + case TestT: { + test_name = "T"; + value = (mean - m_population_mean) / (std/qSqrt(n)); df = n - 1; + printLine(6, i18n("Degree of Freedom is %1", df), "blue"); + break; + } case TestZ: { + test_name = "Z"; + df = 0; + value = (mean - m_population_mean) / (std/qSqrt(n)); + }} - switch (tail_type) { - case HypothesisTest::TailNegative: - p_value = nsl_stats_tdist_p(z_value, df); - m_summary_results += i18n("

Null Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING("≥"), m_population_mean); - m_summary_results += i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING("â‹–"), m_population_mean); - break; - case HypothesisTest::TailPositive: - z_value *= -1; - m_summary_results += i18n("

Null Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING("≤"), m_population_mean); - m_summary_results += i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING(">"), m_population_mean); - break; - case HypothesisTest::TailTwo: - p_value = nsl_stats_tdist_p(z_value, df) + nsl_stats_tdist_p(-1*z_value, df); - m_summary_results += i18n("

Null Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING("="), m_population_mean); - m_summary_results += i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3
", m_columns[0]->name(), UTF8_QSTRING("≠"), m_population_mean); - break; - } - - - resultModel->setData(resultModel->index(3, 0), i18n("Z value is %1", z_value), Qt::DisplayRole); - resultModel->setData(resultModel->index(4, 0), i18n("P value is %1", p_value), Qt::DisplayRole); - resultModel->setData(resultModel->index(5, 0), i18n("Significance level is %1", m_significance_level), Qt::DisplayRole); - resultModel->setData(resultModel->index(7, 0), i18n("Assumption: Central Limit Theorem is Valid"), Qt::DisplayRole); + p_value = getPValue(test, value, m_columns[0]->name(), i18n("%1",m_population_mean), df); + m_currTestName = i18n("

One Sample %1 Test for %2

", test_name, m_columns[0]->name()); + printLine(2, i18n("Significance level is %1", m_significance_level), "blue"); + printLine(4, i18n("%1 Value is %2", test_name, value), "green"); + printLine(5, i18n("P Value is %1", p_value), "green"); - if (p_value <= m_significance_level) - temp_msg = i18n("We can safely reject Null Hypothesis for significance level %1", m_significance_level); - else - temp_msg = i18n("There is a plausibility for Null Hypothesis to be true"); - - // tool tips - resultModel->setData(resultModel->index(4, 0), temp_msg, Qt::ToolTipRole); -// resultModel->setData(resultModel->index(0, 0), QIcon("open.xpm"), Qt::DecorationRole); + if (p_value <= m_significance_level) + q->m_view->setResultLine(5, i18n("We can safely reject Null Hypothesis for significance level %1", m_significance_level), Qt::ToolTipRole); + else + q->m_view->setResultLine(5, i18n("There is a plausibility for Null Hypothesis to be true"), Qt::ToolTipRole); + emit q->changed(); + return; - emit q->changed(); - return; - } } +/***************************************Helper Functions*************************************/ + void HypothesisTestPrivate::findStatsPaired(Column* column1, Column* column2, int &count, double &sum, double &mean, double &std) { sum = 0; mean = 0; std = 0; int count1 = column1->rowCount(); int count2 = column2->rowCount(); count = qMin(count1, count2); - double row1, row2; + double cell1, cell2; for (int i = 0; i < count; i++) { - row1 = column1->valueAt(i); - row2 = column2->valueAt(i); + cell1 = column1->valueAt(i); + cell2 = column2->valueAt(i); - if (std::isnan(row1) || std::isnan(row2)) { - if (std::isnan(row1) && std::isnan(row2)) + if (std::isnan(cell1) || std::isnan(cell2)) { + if (std::isnan(cell1) && std::isnan(cell2)) count = i; else { count = -1; return; } break; } - sum += row1 - row2; + sum += cell1 - cell2; } if (count < 1) return; mean = sum/count; double row; for (int i = 0; i < count; i++) { - row1 = column1->valueAt(i); - row2 = column2->valueAt(i); - row = row1 - row2; + cell1 = column1->valueAt(i); + cell2 = column2->valueAt(i); + row = cell1 - cell2; std += qPow( (row - mean), 2); } if (count > 1) std = std / (count-1); std = qSqrt(std); return; } void HypothesisTestPrivate::findStats(Column* column, int &count, double &sum, double &mean, double &std) { sum = 0; mean = 0; std = 0; count = column->rowCount(); for (int i = 0; i < count; i++) { double row = column->valueAt(i); if ( std::isnan(row)) { count = i; break; } sum += row; } if (count < 1) return; mean = sum/count; for (int i = 0; i < count; i++) { double row = column->valueAt(i); std += qPow( (row - mean), 2); } if (count > 1) std = std / (count-1); std = qSqrt(std); return; } void HypothesisTestPrivate::findStatsCategorical(int n[], double sum[], double mean[], double std[], QString &col1_name, QString &col2_name) { /* Error codes; n[0] = -1 : unequal rows n[0] = -2 : #categorical variables != 2; */ // clearing the variables; for (int i = 0; i < 2; i++) { sum[i] = 0; mean[i] = 0; std[i] = 0; n[i] = 0; } int count_temp = m_columns[0]->rowCount(); col1_name = ""; col2_name = ""; for (int i = 0; i < count_temp; i++) { QString name = m_columns[0]->textAt(i); double value = m_columns[1]->valueAt(i); if (name == "" || std::isnan(value)) { - if (name == "" && std::isnan(value)) { + if (name == "" && std::isnan(value)) break; - } else { + else { n[0] = -1; return; } } if (name == col1_name) { n[0]++; sum[0] += value; } else if (name == col2_name) { n[1]++; sum[1] += value; } else if (col1_name == "") { n[0]++; sum[0] += value; col1_name = name; } else if (col2_name == "") { n[1]++; sum[1] += value; col2_name = name; } else { // this case occurs when there are more than two categorical variables in column 1 // sending error code of -1; n[0] = -2; return; } } if (col1_name == "" || col2_name == "") { n[0] = -2; return; } mean[0] = sum[0]/n[0]; mean[1] = sum[1]/n[1]; for (int i = 0; i < n[0]+n[1]; i++) { QString name = m_columns[0]->textAt(i); double value = m_columns[1]->valueAt(i); - if (name == col1_name) { + if (name == col1_name) std[0] += qPow( (value - mean[0]), 2); - } else { + else { std[1] += qPow( (value - mean[1]), 2); } } for (int i = 0; i < 2; i++) { if (n[i] > 1) std[i] = std[i] / (n[i] - 1); std[i] = qSqrt(std[i]); } return; } + +double HypothesisTestPrivate::getPValue(const HypothesisTestPrivate::TestType &test, double &value, const QString &col1_name, const QString &col2_name, const int df) { + double p_value = 0; + switch (test) { + case TestT: { + switch (tail_type) { + case HypothesisTest::TailNegative: + p_value = nsl_stats_tdist_p(value, df); + q->m_view->setResultLine(0, i18n("

Null Hypothesis: Population mean of %1 %2 Population mean of %3

", col1_name, UTF8_QSTRING("≥"), col2_name)); + q->m_view->setResultLine(1, i18n("

Alternate Hypothesis: Population mean of %1 %2 Population mean of %3

", col1_name, UTF8_QSTRING("â‹–"), col2_name)); + break; + case HypothesisTest::TailPositive: + value *= -1; + p_value = nsl_stats_tdist_p(value, df); + q->m_view->setResultLine(0, i18n("

Null Hypothesis: Population mean of %1 %2 Population mean of %3

", col1_name, UTF8_QSTRING("≤"), col2_name)); + q->m_view->setResultLine(1, i18n("

Alternate Hypothesis: Population mean of %1 %2 Population mean of %3

", col1_name, UTF8_QSTRING(">"), col2_name)); + break; + case HypothesisTest::TailTwo: + p_value = nsl_stats_tdist_p(value, df) + nsl_stats_tdist_p(-1*value, df); + + q->m_view->setResultLine(0, i18n("

Null Hypothesis: Population mean of %1 %2 Population mean of %3

", col1_name, UTF8_QSTRING("="), col2_name)); + q->m_view->setResultLine(1, i18n("

Alternate Hypothesis: Population mean of %1 %2 Population mean of %3

", col1_name, UTF8_QSTRING("≠"), col2_name)); + break; + } + break; + } case TestZ: { + switch (tail_type) { + case HypothesisTest::TailNegative: + p_value = nsl_stats_tdist_p(value, df); + q->m_view->setResultLine(0, i18n("

Null Hypothesis: Population mean of %1 %2 Population mean of %3

", col1_name, UTF8_QSTRING("≥"), col2_name)); + q->m_view->setResultLine(1, i18n("

Alternate Hypothesis: Population mean of %1 %2 Population mean of %3

", col1_name, UTF8_QSTRING("â‹–"), col2_name)); + break; + case HypothesisTest::TailPositive: + value *= -1; + p_value = nsl_stats_tdist_p(value, df); + q->m_view->setResultLine(0, i18n("

Null Hypothesis: Population mean of %1 %2 Population mean of %3

", col1_name, UTF8_QSTRING("≤"), col2_name)); + q->m_view->setResultLine(1, i18n("

Alternate Hypothesis: Population mean of %1 %2 Population mean of %3

", col1_name, UTF8_QSTRING(">"), col2_name)); + break; + case HypothesisTest::TailTwo: + p_value = nsl_stats_tdist_p(value, df) + nsl_stats_tdist_p(-1*value, df); + + q->m_view->setResultLine(0, i18n("

Null Hypothesis: Population mean of %1 %2 Population mean of %3

", col1_name, UTF8_QSTRING("="), col2_name)); + q->m_view->setResultLine(1, i18n("

Alternate Hypothesis: Population mean of %1 %2 Population mean of %3

", col1_name, UTF8_QSTRING("≠"), col2_name)); + break; + } + break; + } + } + if (p_value > 1) + return 1; + return p_value; +} + QString HypothesisTestPrivate::getHtmlTable(int row, int column, QVariant *row_major) { if (row < 1 || column < 1) return QString(); QString table = ""; table = "" "" " "; QString bg = "tg-0pky"; bool pky = true; QString element; table += " "; for (int j = 0; j < column; j++) { element = row_major[j].toString(); table += i18n(" ", bg, element); } table += " "; if (pky) bg = "tg-0pky"; else bg = "tg-btxf"; pky = !pky; for (int i = 1; i < row; i++) { table += " "; QString element = row_major[i*column].toString(); table += i18n(" ", bg, element); for (int j = 1; j < column; j++) { QString element = row_major[i*column+j].toString(); table += i18n(" ", bg, element); } table += " "; if (pky) bg = "tg-0pky"; else bg = "tg-btxf"; pky = !pky; } table += "
%2
%2%2
"; return table; } + +void HypothesisTestPrivate::printLine(const int &index, const QString &msg, const QString &color) { + q->m_view->setResultLine(index, i18n("

%2

", color, msg)); + return; +} + +void HypothesisTestPrivate::printError(const QString &error_msg) { + printLine(0, error_msg, "red"); + emit q->changed(); +} + + +void HypothesisTestPrivate::clearGlobalVariables() { + m_stats_table = ""; + q->m_view->clearResult(); +} + /********************************************************************************** * virtual functions implementations * ********************************************************************************/ /*! Saves as XML. */ void HypothesisTest::save(QXmlStreamWriter* writer) const { writer->writeStartElement("hypothesisTest"); writeBasicAttributes(writer); writeCommentElement(writer); //TODO: writer->writeEndElement(); } /*! Loads from XML. */ bool HypothesisTest::load(XmlStreamReader* reader, bool preview) { Q_UNUSED(preview); if (!readBasicAttributes(reader)) return false; //TODO: return !reader->hasError(); } Spreadsheet *HypothesisTest::dataSourceSpreadsheet() const { return d->dataSourceSpreadsheet; } bool HypothesisTest::exportView() const { return true; } bool HypothesisTest::printView() { return true; } bool HypothesisTest::printPreview() const { return true; } /*! Constructs a primary view on me. This method may be called multiple times during the life time of an Aspect, or it might not get called at all. Aspects must not depend on the existence of a view for their operation. */ QWidget* HypothesisTest::view() const { if (!m_partView) { m_view = new HypothesisTestView(const_cast(this)); m_partView = m_view; } return m_partView; } /*! Returns a new context menu. The caller takes ownership of the menu. */ QMenu* HypothesisTest::createContextMenu() { QMenu* menu = AbstractPart::createContextMenu(); -// Q_ASSERT(menu); -// emit requestProjectContextMenu(menu); + // Q_ASSERT(menu); + // emit requestProjectContextMenu(menu); return menu; } diff --git a/src/backend/hypothesis_test/HypothesisTest.h b/src/backend/hypothesis_test/HypothesisTest.h index 4a5cbb48a..7fc11fb19 100644 --- a/src/backend/hypothesis_test/HypothesisTest.h +++ b/src/backend/hypothesis_test/HypothesisTest.h @@ -1,103 +1,104 @@ /*************************************************************************** File : HypothesisTest.h Project : LabPlot Description : Doing Hypothesis-Test on data provided -------------------------------------------------------------------- Copyright : (C) 2019 Devanshu Agarwal(agarwaldevanshu8@gmail.com) ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #ifndef HYPOTHESISTEST_H #define HYPOTHESISTEST_H #include #include "backend/core/AbstractPart.h" #include "backend/lib/macros.h" class HypothesisTestPrivate; class HypothesisTestView; class Spreadsheet; class QString; class Column; class QLayout; class HypothesisTest : public AbstractPart { Q_OBJECT public: explicit HypothesisTest(const QString& name); ~HypothesisTest() override; enum DataSourceType {DataSourceSpreadsheet, DataSourceDatabase}; enum TailType {TailPositive, TailNegative, TailTwo}; QString testName(); QString statsTable(); - QString summaryResultText(); void setDataSourceSpreadsheet(Spreadsheet* spreadsheet); void setColumns(QVector cols); void setColumns(QStringList cols); void performTwoSampleTTest(); void performTwoSampleIndependentTTest(bool equal_variance); void performTwoSamplePairedTTest(); void PerformOneSampleTTest(); void performTwoSampleIndependentZTest(); void performTwoSamplePairedZTest(); void PerformOneSampleZTest(); DataSourceType dataSourceType() const; //virtual methods // QIcon icon() const override; QMenu* createContextMenu() override; QWidget* view() const override; bool exportView() const override; bool printView() override; bool printPreview() const override; void save(QXmlStreamWriter*) const override; bool load(XmlStreamReader*, bool preview) override; Spreadsheet* dataSourceSpreadsheet() const; void setDataSourceType(DataSourceType type); QStringList allColumns(); void setTailType(TailType tailType); TailType tailType(); void setPopulationMean(QVariant populationMean); void setSignificanceLevel(QVariant alpha); +// void setResultLine(int index, QVariant data, Qt::ItemDataRole role = Qt::DisplayRole); +// void clearResult(); private: HypothesisTestPrivate* const d; mutable HypothesisTestView* m_view{nullptr}; friend class HypothesisTestPrivate; signals: void changed(); void requestProjectContextMenu(QMenu*); void dataSourceTypeChanged(HypothesisTest::DataSourceType); void dataSourceSpreadsheetChanged(Spreadsheet*); }; #endif // HypothesisTest_H diff --git a/src/backend/hypothesis_test/HypothesisTestPrivate.h b/src/backend/hypothesis_test/HypothesisTestPrivate.h index 9ff3ed6ad..024df28d8 100644 --- a/src/backend/hypothesis_test/HypothesisTestPrivate.h +++ b/src/backend/hypothesis_test/HypothesisTestPrivate.h @@ -1,88 +1,90 @@ /*************************************************************************** File : HypothesisTestPrivate.h Project : LabPlot Description : Private members of Hypothesis Test -------------------------------------------------------------------- Copyright : (C) 2019 Devanshu Agarwal(agarwaldevanshu8@gmail.com) ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #ifndef HYPOTHESISTESTPRIVATE_H #define HYPOTHESISTESTPRIVATE_H #include class QStandardItemModel; class HypothesisTestPrivate { public: explicit HypothesisTestPrivate(HypothesisTest*); virtual ~HypothesisTestPrivate(); enum TestType {TestT, TestZ}; QString name() const; HypothesisTest* const q; HypothesisTest::DataSourceType dataSourceType{HypothesisTest::DataSourceSpreadsheet}; Spreadsheet* dataSourceSpreadsheet{nullptr}; void setDataSourceSpreadsheet(Spreadsheet* spreadsheet); void setColumns(QStringList cols); QVector m_columns; QStringList all_columns; QStandardItemModel* dataModel{nullptr}; QStandardItemModel* horizontalHeaderModel{nullptr}; QStandardItemModel* verticalHeaderModel{nullptr}; bool m_dbCreated{false}; int m_rowCount{0}; int m_columnCount{0}; QString m_currTestName{"Result Table"}; double m_population_mean; double m_significance_level; QString m_stats_table; - QString m_summary_results; - void performTwoSampleIndependentTest(TestType test, bool equal_variance = true); void performTwoSamplePairedTest(TestType test); void PerformOneSampleTest(TestType test); HypothesisTest::TailType tail_type; QStandardItemModel* resultModel{nullptr}; private: void findStats(Column* column, int &count, double &sum, double &mean, double &std); void findStatsPaired(Column *column1, Column *column2, int &count, double &sum, double &mean, double &std); - void findStatsCategorical(int n[2], double sum[2], double mean[2], double std[2], QString &col1_name, QString &col2_name); - + double getPValue(const TestType &test, double &value, const QString &col1_name, const QString &col2_name, const int df = 0); QString getHtmlTable(int row, int column, QVariant *row_major); -// QMap m_members; + void printError(const QString &error_msg); + void clearGlobalVariables(); + + + // QMap m_members; + void printLine(const int &index, const QString &msg, const QString &color = "blue"); }; #endif diff --git a/src/kdefrontend/hypothesis_test/HypothesisTestView.cpp b/src/kdefrontend/hypothesis_test/HypothesisTestView.cpp index 29f630180..71a3b7342 100644 --- a/src/kdefrontend/hypothesis_test/HypothesisTestView.cpp +++ b/src/kdefrontend/hypothesis_test/HypothesisTestView.cpp @@ -1,178 +1,198 @@ /*************************************************************************** File : HypothesisTestView.cpp Project : LabPlot Description : View class for Hypothesis Tests' Table -------------------------------------------------------------------- Copyright : (C) 2019 Devanshu Agarwal(agarwaldevanshu8@gmail.com) ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #include "HypothesisTestView.h" #include "backend/hypothesis_test/HypothesisTest.h" #include "backend/lib/macros.h" #include "backend/lib/trace.h" #include #include #include #include #include #include #include #include #include -#include +#include #include #include #include #include #include /*! \class HypothesisTestView \brief View class for Hypothesis Test \ingroup kdefrontend */ HypothesisTestView::HypothesisTestView(HypothesisTest* hypothesisTest) : QWidget(), m_hypothesisTest(hypothesisTest), m_testName(new QLabel()), m_statsTable(new QLabel()), - m_summaryResults(new QLabel()){ + m_summaryResults(new QWidget()){ - //setting alignments and fonts of testname label; - m_testName->setText(m_hypothesisTest->testName()); -// QFont font = m_testName->font(); -// font.setPointSize(15); -// m_testName->setFont(font); + m_summaryResults->setMouseTracking(true); auto* layout = new QVBoxLayout(this); layout->addWidget(m_testName); layout->addWidget(m_statsTable); layout->addWidget(m_summaryResults); - + layout->addWidget(m_summaryResults); init(); } HypothesisTestView::~HypothesisTestView() = default; void HypothesisTestView::init() { initActions(); initMenus(); + +// m_summaryResults->setStyleSheet("background-color:white; border: 0px; margin: 0px; padding 0px;qproperty-frame: false;"); + QVBoxLayout* summary_layout = new QVBoxLayout(m_summaryResults); + + for (int i = 0; i < 10; i++) { + m_resultLine[i] = new QLabel(); + summary_layout->addWidget(m_resultLine[i]); + } + connect(m_hypothesisTest, &HypothesisTest::changed, this, &HypothesisTestView::changed); } + + void HypothesisTestView::initActions() { } void HypothesisTestView::initMenus() { } +void HypothesisTestView::setResultLine(int index, QVariant data, Qt::ItemDataRole role) { + if (index < 0 || index >= 10) return; + + if (role == Qt::DisplayRole) + m_resultLine[index]->setText(data.toString()); + else if (role == Qt::ToolTipRole) + m_resultLine[index]->setToolTip(data.toString()); +} + +void HypothesisTestView::clearResult() { + for (int i = 0; i < 10; i++) + m_resultLine[i]->clear(); +} + void HypothesisTestView::connectActions() { } void HypothesisTestView::fillToolBar(QToolBar* toolBar) { Q_UNUSED(toolBar); } /*! * Populates the menu \c menu with the pivot table and pivot table view relevant actions. * The menu is used * - as the context menu in PivotTableView * - as the "pivot table menu" in the main menu-bar (called form MainWin) * - as a part of the pivot table context menu in project explorer */ void HypothesisTestView::createContextMenu(QMenu* menu) { Q_ASSERT(menu); } bool HypothesisTestView::exportView() { return true; } bool HypothesisTestView::printView() { QPrinter printer; auto* dlg = new QPrintDialog(&printer, this); dlg->setWindowTitle(i18nc("@title:window", "Print Spreadsheet")); bool ret; if ((ret = dlg->exec()) == QDialog::Accepted) { print(&printer); } delete dlg; return ret; } bool HypothesisTestView::printPreview() { QPrintPreviewDialog* dlg = new QPrintPreviewDialog(this); connect(dlg, &QPrintPreviewDialog::paintRequested, this, &HypothesisTestView::print); return dlg->exec(); } /*! prints the complete spreadsheet to \c printer. */ void HypothesisTestView::print(QPrinter* printer) const { WAIT_CURSOR; QPainter painter (printer); RESET_CURSOR; } void HypothesisTestView::changed() { m_testName->setText(m_hypothesisTest->testName()); m_statsTable->setText(m_hypothesisTest->statsTable()); - m_summaryResults->setText(m_hypothesisTest->summaryResultText()); } void HypothesisTestView::exportToFile(const QString& path, const bool exportHeader, const QString& separator, QLocale::Language language) const { Q_UNUSED(exportHeader); Q_UNUSED(separator); Q_UNUSED(language); QFile file(path); if (!file.open(QFile::WriteOnly | QFile::Truncate)) return; PERFTRACE("export pivot table to file"); } void HypothesisTestView::exportToLaTeX(const QString & path, const bool exportHeaders, const bool gridLines, const bool captions, const bool latexHeaders, const bool skipEmptyRows, const bool exportEntire) const { Q_UNUSED(exportHeaders); Q_UNUSED(gridLines); Q_UNUSED(captions); Q_UNUSED(latexHeaders); Q_UNUSED(skipEmptyRows); Q_UNUSED(exportEntire); QFile file(path); if (!file.open(QFile::WriteOnly | QFile::Truncate)) return; - PERFTRACE("export pivot table to latex"); + PERFTRACE("export pivot table to latex"); } diff --git a/src/kdefrontend/hypothesis_test/HypothesisTestView.h b/src/kdefrontend/hypothesis_test/HypothesisTestView.h index 1f6ff7ae6..9e54af4ab 100644 --- a/src/kdefrontend/hypothesis_test/HypothesisTestView.h +++ b/src/kdefrontend/hypothesis_test/HypothesisTestView.h @@ -1,88 +1,93 @@ /*************************************************************************** File : PivotTableView.h Project : LabPlot Description : View class for Hypothesis Tests' -------------------------------------------------------------------- Copyright : (C) 2019 Devanshu Agarwal(agarwaldevanshu8@gmail.com) ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, * * Boston, MA 02110-1301 USA * * * ***************************************************************************/ #ifndef HYPOTHESISTESTVIEW_H #define HYPOTHESISTESTVIEW_H #include #include "backend/core/AbstractColumn.h" #include "backend/lib/IntervalAttribute.h" class Column; class HypothesisTest; class HypothesisTestModel; class AbstractAspect; class QTableView; class QHeaderView; class QListView; class QPrinter; class QMenu; class QToolBar; class QModelIndex; class QItemSelection; class QLabel; +class QTextEdit; +class QLineEdit; class HypothesisTestView : public QWidget { Q_OBJECT public: explicit HypothesisTestView(HypothesisTest*); ~HypothesisTestView() override; bool exportView(); bool printView(); bool printPreview(); private: void init(); void initActions(); void initMenus(); void connectActions(); void exportToFile(const QString&, const bool, const QString&, QLocale::Language) const; void exportToLaTeX(const QString&, const bool exportHeaders, const bool gridLines, const bool captions, const bool latexHeaders, const bool skipEmptyRows,const bool exportEntire) const; HypothesisTest* m_hypothesisTest; QLabel* m_testName; QLabel* m_statsTable; - QLabel* m_summaryResults; + QWidget* m_summaryResults; + QLabel* m_resultLine[10]; public slots: void createContextMenu(QMenu*); void fillToolBar(QToolBar*); void print(QPrinter*) const; void changed(); + void setResultLine(int index, QVariant data, Qt::ItemDataRole role = Qt::DisplayRole); + void clearResult(); private slots: }; #endif diff --git a/src/kdefrontend/ui/dockwidgets/hypothesistestdock.ui b/src/kdefrontend/ui/dockwidgets/hypothesistestdock.ui index 4d47b9f5e..40dad1b60 100644 --- a/src/kdefrontend/ui/dockwidgets/hypothesistestdock.ui +++ b/src/kdefrontend/ui/dockwidgets/hypothesistestdock.ui @@ -1,397 +1,397 @@ HypothesisTestDock 0 0 588 996 Form 9 255 73 17 75 true Structure: - 280 - 630 + 220 + 440 77 23 Do Test 10 480 341 106 Qt::Horizontal Alternate Hypothesis mu > muo mu < muo mu != muo Null Hypothesis mu <= muo mu >= muo mu == muo 10 610 217 81 muo alpha 15 12 90 25 0 0 Name: 15 43 90 25 Comment: 130 43 401 25 130 12 401 25 15 93 42 17 75 true Data 15 116 561 112 Source: 0 0 Spreadsheet: Connection: 0 0 0 0 Table: 12 433 125 23 Equal Variance 13 288 341 50 Test Test type 16 373 394 50 Independent Variable Qt::AlignCenter Independent Variable Variable diff --git a/ttest.diff b/ttest.diff new file mode 100644 index 000000000..1e2e92624 --- /dev/null +++ b/ttest.diff @@ -0,0 +1,260 @@ +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 1c39d438f..0d00a555b 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -236,6 +236,7 @@ set(BACKEND_SOURCES + ${BACKEND_DIR}/matrix/matrixcommands.cpp + ${BACKEND_DIR}/matrix/MatrixModel.cpp + ${BACKEND_DIR}/pivot/PivotTable.cpp ++ ${BACKEND_DIR}/t_test/TTest.cpp + ${BACKEND_DIR}/spreadsheet/Spreadsheet.cpp + ${BACKEND_DIR}/spreadsheet/SpreadsheetModel.cpp + ${BACKEND_DIR}/lib/XmlStreamReader.cpp +diff --git a/src/backend/t_test/TTest.cpp b/src/backend/t_test/TTest.cpp +new file mode 100644 +index 000000000..9bfb0cf25 +--- /dev/null ++++ b/src/backend/t_test/TTest.cpp +@@ -0,0 +1,120 @@ ++#include "TTest.h" ++#include "backend/spreadsheet/Spreadsheet.h" ++#include "backend/core/column/Column.h" ++//#include "commonfrontend/spreadsheet/SpreadsheetView.h" ++ ++#include ++#include ++#include ++#include ++ ++ ++TTest::TTest(const QString &name){ ++ Q_UNUSED(name); ++} ++ ++void TTest::setDataSourceSpreadsheet(Spreadsheet *spreadsheet){ ++ dataSourceSpreadsheet = spreadsheet; ++ ++ m_rowCount = dataSourceSpreadsheet->rowCount(); ++ m_columnCount = dataSourceSpreadsheet->columnCount(); ++ QDEBUG("in ttest::setDataSourceSpreadsheet"); ++ ++ // now finding the number of columns and rows; ++ QDEBUG("row count is " << m_rowCount); ++ QDEBUG("row count is " << m_columnCount); ++ QDEBUG("exiting ttest::setDataSourceSpreadsheet"); ++} ++ ++void TTest::setColumns(QVector cols){ ++ m_columns = cols; ++ return; ++} ++ ++void TTest::performTwoSampleTest(){ ++ QMessageBox* msg_box = new QMessageBox(); ++ // checking for cols; ++ if(m_columns.size() != 2){ ++ msg_box->setText(i18n("Inappropriate number of columns selected")); ++ msg_box->exec(); ++ return; ++ } ++ ++ bool modeOk = true; ++ for (int i = 0; i < 2; i++){ ++ if(m_columns[0]->columnMode() == AbstractColumn::Numeric || m_columns[i]->columnMode() == AbstractColumn::Integer) ++ continue; ++ modeOk = false; ++ } ++ ++ if(!modeOk){ ++ msg_box->setText(i18n("select only columns with numbers")); ++ msg_box->exec(); ++ return; ++ } ++ ++ // use of three than two for human readiblity of code; ++ int n[2]; ++ double sum[2], mean[2], std[2]; ++ ++ for (int i = 0; i < 2; i++) { ++ findStats(m_columns[i], n[i], sum[i], mean[i], std[i]); ++ QDEBUG("for " << i); ++ QDEBUG("n is "<setText(i18n("atleast one of selected column empty")); ++ msg_box->exec(); ++ return; ++ } ++ } ++ int df = n[0] + n[1] - 2; ++ ++ //Assuming equal variance ++ double sp = qSqrt( ((n[0]-1)*qPow(std[0],2) + (n[1]-1)*qPow(std[1],2))/df); ++ ++ QDEBUG("sp is " << sp); ++ ++ double t = (mean[0] - mean[1])/(sp*qSqrt(1.0/n[0] + 1.0/n[1])); ++ QString text = i18n("T value for test is %1",t); ++ msg_box->setText(text); ++ msg_box->exec(); ++ return; ++ ++// double t_value = ++ ++} ++ ++void TTest::findStats(Column* column, int &count, double &sum, double &mean, double &std) { ++ sum = 0; ++ mean = 0; ++ std = 0; ++ ++ count = column->rowCount(); ++ for (int i = 0; i < count; i++) { ++ double row = column->valueAt(i); ++ if ( std::isnan(row)) { ++ count = i; ++ break; ++ } ++ sum += row; ++ } ++ ++ if (count < 1) return; ++ mean = sum/count; ++ ++ for (int i = 0; i < count; i++) { ++ double row = column->valueAt(i); ++ std += qPow((row - mean),2); ++ } ++ ++ if (count > 1) ++ std = std / (count-1); ++ std = qSqrt(std); ++ return; ++} ++ ++ ++ +diff --git a/src/backend/t_test/TTest.h b/src/backend/t_test/TTest.h +new file mode 100644 +index 000000000..7e888a27b +--- /dev/null ++++ b/src/backend/t_test/TTest.h +@@ -0,0 +1,27 @@ ++#ifndef TTEST_H ++#define TTEST_H ++#include ++ ++ ++class Spreadsheet; ++class QString; ++class Column; ++ ++class TTest{ ++public: ++ explicit TTest(const QString& name); ++ void setDataSourceSpreadsheet(Spreadsheet* spreadsheet); ++ void setColumns(QVector cols); ++ void performTwoSampleTest(); ++private: ++// double findMean(Column* col); ++// double findStandardDeviation(Column* col, double mean); ++ void findStats(Column* column, int &count, double &sum, double &mean, double &std); ++ ++ Spreadsheet* dataSourceSpreadsheet{nullptr}; ++ int m_rowCount{0}; ++ int m_columnCount{0}; ++ QVector m_columns; ++}; ++ ++#endif // TTEST_H +diff --git a/src/commonfrontend/spreadsheet/SpreadsheetView.cpp b/src/commonfrontend/spreadsheet/SpreadsheetView.cpp +index ef0717c15..7a658653b 100644 +--- a/src/commonfrontend/spreadsheet/SpreadsheetView.cpp ++++ b/src/commonfrontend/spreadsheet/SpreadsheetView.cpp +@@ -43,6 +43,8 @@ + #include "backend/core/datatypes/DateTime2StringFilter.h" + #include "backend/core/datatypes/String2DateTimeFilter.h" + #include "backend/pivot/PivotTable.h" ++#include "backend/t_test/TTest.h" ++ + + #include + #include +@@ -220,6 +222,7 @@ void SpreadsheetView::initActions() { + action_go_to_cell = new QAction(QIcon::fromTheme("go-jump"), i18n("&Go to Cell"), this); + action_statistics_all_columns = new QAction(QIcon::fromTheme("view-statistics"), i18n("Statisti&cs"), this ); + action_pivot_table = new QAction(QIcon::fromTheme("table"), i18n("Pivot Table"), this); ++ action_do_ttest = new QAction(i18n("T Test"), this); + + // column related actions + action_insert_column_left = new QAction(QIcon::fromTheme("edit-table-insert-column-left"), i18n("Insert Column Left"), this); +@@ -471,6 +474,12 @@ void SpreadsheetView::initMenus() { + m_columnMenu->addMenu(m_columnManipulateDataMenu); + m_columnMenu->addSeparator(); + ++ //for ttest statistics; ++ m_columnHypothesisTestingMenu = new QMenu("Hypothesis Testing",this); ++ m_columnHypothesisTestingMenu->addAction(action_do_ttest); ++ m_columnMenu->addMenu(m_columnHypothesisTestingMenu); ++ m_columnMenu->addSeparator(); ++ + m_columnSortMenu = new QMenu(i18n("Sort"), this); + m_columnSortMenu->setIcon(QIcon::fromTheme("view-sort-ascending")); + m_columnSortMenu->addAction(action_sort_asc_column); +@@ -558,6 +567,7 @@ void SpreadsheetView::connectActions() { + connect(action_go_to_cell, &QAction::triggered, this, + static_cast(&SpreadsheetView::goToCell)); + connect(action_pivot_table, &QAction::triggered, this, &SpreadsheetView::createPivotTable); ++ connect(action_do_ttest, &QAction::triggered, this, &SpreadsheetView::doTTest); + + connect(action_insert_column_left, &QAction::triggered, this, &SpreadsheetView::insertColumnLeft); + connect(action_insert_column_right, &QAction::triggered, this, &SpreadsheetView::insertColumnRight); +@@ -764,9 +774,17 @@ void SpreadsheetView::createPivotTable() { + PivotTable* pivot = new PivotTable(i18n("Pivot Table for %1", m_spreadsheet->name())); + pivot->setDataSourceType(PivotTable::DataSourceSpreadsheet); + pivot->setDataSourceSpreadsheet(m_spreadsheet); +- m_spreadsheet->parentAspect()->addChild(pivot); ++ m_spreadsheet->parentAspect()->addChild(pivot); + } + ++void SpreadsheetView::doTTest() ++{ ++ TTest* ttest = new TTest(i18n("doing T Test for %1", m_spreadsheet->name())); ++ ttest->setColumns(this->selectedColumns()); ++ ttest->performTwoSampleTest(); ++} ++ ++ + void SpreadsheetView::handleHorizontalSectionMoved(int index, int from, int to) { + Q_UNUSED(index); + +diff --git a/src/commonfrontend/spreadsheet/SpreadsheetView.h b/src/commonfrontend/spreadsheet/SpreadsheetView.h +index b67df1252..eceb1c556 100644 +--- a/src/commonfrontend/spreadsheet/SpreadsheetView.h ++++ b/src/commonfrontend/spreadsheet/SpreadsheetView.h +@@ -130,6 +130,7 @@ private: + QAction* action_go_to_cell; + QAction* action_statistics_all_columns; + QAction* action_pivot_table; ++ QAction* action_do_ttest; + + //column related actions + QAction* action_insert_column_left; +@@ -192,6 +193,7 @@ private: + QMenu* m_spreadsheetMenu; + QMenu* m_plotDataMenu; + QMenu* m_analyzePlotMenu; ++ QMenu* m_columnHypothesisTestingMenu{nullptr}; + + public slots: + void createContextMenu(QMenu*); +@@ -206,6 +208,7 @@ private slots: + void goToPreviousColumn(); + void goToCell(); + void createPivotTable(); ++ void doTTest(); + void sortSpreadsheet(); + void sortDialog(QVector); + diff --git a/verticalHeaderCompleted.diff b/verticalHeaderCompleted.diff new file mode 100644 index 000000000..f48cee771 --- /dev/null +++ b/verticalHeaderCompleted.diff @@ -0,0 +1,693 @@ +diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt +index 1c39d438f..0d00a555b 100644 +--- a/src/CMakeLists.txt ++++ b/src/CMakeLists.txt +@@ -236,6 +236,7 @@ set(BACKEND_SOURCES + ${BACKEND_DIR}/matrix/matrixcommands.cpp + ${BACKEND_DIR}/matrix/MatrixModel.cpp + ${BACKEND_DIR}/pivot/PivotTable.cpp ++ ${BACKEND_DIR}/t_test/TTest.cpp + ${BACKEND_DIR}/spreadsheet/Spreadsheet.cpp + ${BACKEND_DIR}/spreadsheet/SpreadsheetModel.cpp + ${BACKEND_DIR}/lib/XmlStreamReader.cpp +diff --git a/src/backend/pivot/PivotTable.cpp b/src/backend/pivot/PivotTable.cpp +index b9c66d8dd..c166da97a 100644 +--- a/src/backend/pivot/PivotTable.cpp ++++ b/src/backend/pivot/PivotTable.cpp +@@ -45,6 +45,8 @@ + #include + #include + ++#include ++ + /*! + \class PivotTable + \brief Aspect providing a pivot table. +@@ -257,7 +259,7 @@ void PivotTablePrivate::recalculate() { + + if (rows.isEmpty() && columns.isEmpty() && !showTotals) { + //notify about the new result +- emit q->changed(); ++ emit q->changed(); + return; + } + +@@ -309,7 +311,9 @@ void PivotTablePrivate::recalculate() { + + } + +- QDEBUG(query); ++ //QDEBUG(query); ++ ++ qDebug()<<"query is " << query; + + //execute the query + QSqlQuery sqlQuery; +@@ -326,10 +330,15 @@ void PivotTablePrivate::recalculate() { + int firstValueIndex = rows.size() + columns.size(); + int valuesCount = columnsCount - firstValueIndex; + +- DEBUG("nubmer of columns " << columnsCount); +- DEBUG("number rows: " << rowsCount); +- DEBUG("number values: " << valuesCount); +- DEBUG("index of the first value column: " << firstValueIndex); ++// DEBUG("nubmer of columns " << columnsCount); ++// DEBUG("number rows: " << rowsCount); ++// DEBUG("number values: " << valuesCount); ++// DEBUG("index of the first value column: " << firstValueIndex); ++ ++ qDebug() << "number of columns " << columnsCount; ++ qDebug() << "number of rows" << rowsCount; ++ qDebug() << "number of values" << valuesCount; ++ qDebug() << "index of first value column " << firstValueIndex; + + qDebug()<<"model in recalculate " << horizontalHeaderModel; + if (!horizontalHeaderModel) { +@@ -360,7 +369,7 @@ void PivotTablePrivate::recalculate() { + verticalHeaderModel->setColumnCount(rows.count()); + + //horizontal header +- horizontalHeaderModel->setColumnCount(valuesCount); ++ horizontalHeaderModel->setColumnCount(valuesCount); + horizontalHeaderModel->setRowCount(1); + + //TODO: only "Totals" value at the moment, needs to be extended later when we allow to add other values +@@ -396,16 +405,52 @@ void PivotTablePrivate::recalculate() { + + } else if (columns.isEmpty()) { + qDebug()<<"everything on rows"; ++ int* start_span = new int[firstValueIndex]; ++ int* end_span = new int[firstValueIndex]; ++ QString* last_value= new QString[firstValueIndex]; ++ ++ verticalHeaderModel->setRowCount(row+1); ++ for (int i = 0; i < firstValueIndex; ++i) { ++ start_span[i] = 1; ++ end_span[i] = 1; ++ last_value[i] = ""; ++ verticalHeaderModel->setData(verticalHeaderModel->index(row, i), rows.at(i), Qt::DisplayRole); ++ } ++ row++; ++ ++ + while (sqlQuery.next()) { + qDebug()<<"row: " << row; +- horizontalHeaderModel->setRowCount(row+1); +- for (int i = 0; i < firstValueIndex; ++i) { +- qDebug()<<"adding to the horizontal header " << sqlQuery.value(i); +- horizontalHeaderModel->setData(horizontalHeaderModel->index(row, i), sqlQuery.value(i), Qt::DisplayRole); ++ verticalHeaderModel->setRowCount(row+1); ++ ++// if(sqlQuery.value(0).toString() != last_value) ++// { ++// if(end_span > start_span) ++// verticalHeaderModel->setSpan(start_span,0,end_span-start_span,0); ++// start_span = end_span; ++// last_value = sqlQuery.value(0).toString(); ++// } ++// end_span = end_span + 1; ++ bool parent_header_changed = false; ++ for (int i = 0; i < firstValueIndex; ++i) { ++ QString queryVal = sqlQuery.value(i).toString(); ++ qDebug()<<"adding to the horizontal header " << query; ++ ++ if(queryVal != last_value[i] || parent_header_changed) ++ { ++ verticalHeaderModel->setData(verticalHeaderModel->index(row, i), queryVal, Qt::DisplayRole); ++ ++ if(end_span[i] > start_span[i]+1) ++ verticalHeaderModel->setSpan(start_span[i],i,end_span[i]-start_span[i],0); ++ start_span[i] = end_span[i]; ++ parent_header_changed = true; ++ } ++ last_value[i] = queryVal; ++ end_span[i] = end_span[i] + 1; + } + + //values +- for (int i = firstValueIndex; i < columnsCount; ++i) { ++ for (int i = firstValueIndex; i < columnsCount; ++i) { + QString value = sqlQuery.value(i).toString(); + qDebug()<<"adding value " << value; + if (rowsCount == -1) +@@ -415,6 +460,13 @@ void PivotTablePrivate::recalculate() { + + ++row; + } ++ for(int i = 0; i < firstValueIndex; ++i){ ++ if(end_span[i] > start_span[i]){ ++ verticalHeaderModel->setSpan(start_span[i],i,end_span[i]-start_span[i],0); ++ } ++ } ++ verticalHeaderModel->setSpan(1,0,0,rows.count()); ++ + } else if (rows.isEmpty()) { + qDebug()<<"everything on columns"; + // for (int i = firstValueIndex; i < columnsCount; ++i) { +diff --git a/src/backend/t_test/TTest.cpp b/src/backend/t_test/TTest.cpp +new file mode 100644 +index 000000000..9bfb0cf25 +--- /dev/null ++++ b/src/backend/t_test/TTest.cpp +@@ -0,0 +1,120 @@ ++#include "TTest.h" ++#include "backend/spreadsheet/Spreadsheet.h" ++#include "backend/core/column/Column.h" ++//#include "commonfrontend/spreadsheet/SpreadsheetView.h" ++ ++#include ++#include ++#include ++#include ++ ++ ++TTest::TTest(const QString &name){ ++ Q_UNUSED(name); ++} ++ ++void TTest::setDataSourceSpreadsheet(Spreadsheet *spreadsheet){ ++ dataSourceSpreadsheet = spreadsheet; ++ ++ m_rowCount = dataSourceSpreadsheet->rowCount(); ++ m_columnCount = dataSourceSpreadsheet->columnCount(); ++ QDEBUG("in ttest::setDataSourceSpreadsheet"); ++ ++ // now finding the number of columns and rows; ++ QDEBUG("row count is " << m_rowCount); ++ QDEBUG("row count is " << m_columnCount); ++ QDEBUG("exiting ttest::setDataSourceSpreadsheet"); ++} ++ ++void TTest::setColumns(QVector cols){ ++ m_columns = cols; ++ return; ++} ++ ++void TTest::performTwoSampleTest(){ ++ QMessageBox* msg_box = new QMessageBox(); ++ // checking for cols; ++ if(m_columns.size() != 2){ ++ msg_box->setText(i18n("Inappropriate number of columns selected")); ++ msg_box->exec(); ++ return; ++ } ++ ++ bool modeOk = true; ++ for (int i = 0; i < 2; i++){ ++ if(m_columns[0]->columnMode() == AbstractColumn::Numeric || m_columns[i]->columnMode() == AbstractColumn::Integer) ++ continue; ++ modeOk = false; ++ } ++ ++ if(!modeOk){ ++ msg_box->setText(i18n("select only columns with numbers")); ++ msg_box->exec(); ++ return; ++ } ++ ++ // use of three than two for human readiblity of code; ++ int n[2]; ++ double sum[2], mean[2], std[2]; ++ ++ for (int i = 0; i < 2; i++) { ++ findStats(m_columns[i], n[i], sum[i], mean[i], std[i]); ++ QDEBUG("for " << i); ++ QDEBUG("n is "<setText(i18n("atleast one of selected column empty")); ++ msg_box->exec(); ++ return; ++ } ++ } ++ int df = n[0] + n[1] - 2; ++ ++ //Assuming equal variance ++ double sp = qSqrt( ((n[0]-1)*qPow(std[0],2) + (n[1]-1)*qPow(std[1],2))/df); ++ ++ QDEBUG("sp is " << sp); ++ ++ double t = (mean[0] - mean[1])/(sp*qSqrt(1.0/n[0] + 1.0/n[1])); ++ QString text = i18n("T value for test is %1",t); ++ msg_box->setText(text); ++ msg_box->exec(); ++ return; ++ ++// double t_value = ++ ++} ++ ++void TTest::findStats(Column* column, int &count, double &sum, double &mean, double &std) { ++ sum = 0; ++ mean = 0; ++ std = 0; ++ ++ count = column->rowCount(); ++ for (int i = 0; i < count; i++) { ++ double row = column->valueAt(i); ++ if ( std::isnan(row)) { ++ count = i; ++ break; ++ } ++ sum += row; ++ } ++ ++ if (count < 1) return; ++ mean = sum/count; ++ ++ for (int i = 0; i < count; i++) { ++ double row = column->valueAt(i); ++ std += qPow((row - mean),2); ++ } ++ ++ if (count > 1) ++ std = std / (count-1); ++ std = qSqrt(std); ++ return; ++} ++ ++ ++ +diff --git a/src/backend/t_test/TTest.h b/src/backend/t_test/TTest.h +new file mode 100644 +index 000000000..7e888a27b +--- /dev/null ++++ b/src/backend/t_test/TTest.h +@@ -0,0 +1,27 @@ ++#ifndef TTEST_H ++#define TTEST_H ++#include ++ ++ ++class Spreadsheet; ++class QString; ++class Column; ++ ++class TTest{ ++public: ++ explicit TTest(const QString& name); ++ void setDataSourceSpreadsheet(Spreadsheet* spreadsheet); ++ void setColumns(QVector cols); ++ void performTwoSampleTest(); ++private: ++// double findMean(Column* col); ++// double findStandardDeviation(Column* col, double mean); ++ void findStats(Column* column, int &count, double &sum, double &mean, double &std); ++ ++ Spreadsheet* dataSourceSpreadsheet{nullptr}; ++ int m_rowCount{0}; ++ int m_columnCount{0}; ++ QVector m_columns; ++}; ++ ++#endif // TTEST_H +diff --git a/src/commonfrontend/spreadsheet/SpreadsheetView.cpp b/src/commonfrontend/spreadsheet/SpreadsheetView.cpp +index ef0717c15..7a658653b 100644 +--- a/src/commonfrontend/spreadsheet/SpreadsheetView.cpp ++++ b/src/commonfrontend/spreadsheet/SpreadsheetView.cpp +@@ -43,6 +43,8 @@ + #include "backend/core/datatypes/DateTime2StringFilter.h" + #include "backend/core/datatypes/String2DateTimeFilter.h" + #include "backend/pivot/PivotTable.h" ++#include "backend/t_test/TTest.h" ++ + + #include + #include +@@ -220,6 +222,7 @@ void SpreadsheetView::initActions() { + action_go_to_cell = new QAction(QIcon::fromTheme("go-jump"), i18n("&Go to Cell"), this); + action_statistics_all_columns = new QAction(QIcon::fromTheme("view-statistics"), i18n("Statisti&cs"), this ); + action_pivot_table = new QAction(QIcon::fromTheme("table"), i18n("Pivot Table"), this); ++ action_do_ttest = new QAction(i18n("T Test"), this); + + // column related actions + action_insert_column_left = new QAction(QIcon::fromTheme("edit-table-insert-column-left"), i18n("Insert Column Left"), this); +@@ -471,6 +474,12 @@ void SpreadsheetView::initMenus() { + m_columnMenu->addMenu(m_columnManipulateDataMenu); + m_columnMenu->addSeparator(); + ++ //for ttest statistics; ++ m_columnHypothesisTestingMenu = new QMenu("Hypothesis Testing",this); ++ m_columnHypothesisTestingMenu->addAction(action_do_ttest); ++ m_columnMenu->addMenu(m_columnHypothesisTestingMenu); ++ m_columnMenu->addSeparator(); ++ + m_columnSortMenu = new QMenu(i18n("Sort"), this); + m_columnSortMenu->setIcon(QIcon::fromTheme("view-sort-ascending")); + m_columnSortMenu->addAction(action_sort_asc_column); +@@ -558,6 +567,7 @@ void SpreadsheetView::connectActions() { + connect(action_go_to_cell, &QAction::triggered, this, + static_cast(&SpreadsheetView::goToCell)); + connect(action_pivot_table, &QAction::triggered, this, &SpreadsheetView::createPivotTable); ++ connect(action_do_ttest, &QAction::triggered, this, &SpreadsheetView::doTTest); + + connect(action_insert_column_left, &QAction::triggered, this, &SpreadsheetView::insertColumnLeft); + connect(action_insert_column_right, &QAction::triggered, this, &SpreadsheetView::insertColumnRight); +@@ -764,9 +774,17 @@ void SpreadsheetView::createPivotTable() { + PivotTable* pivot = new PivotTable(i18n("Pivot Table for %1", m_spreadsheet->name())); + pivot->setDataSourceType(PivotTable::DataSourceSpreadsheet); + pivot->setDataSourceSpreadsheet(m_spreadsheet); +- m_spreadsheet->parentAspect()->addChild(pivot); ++ m_spreadsheet->parentAspect()->addChild(pivot); + } + ++void SpreadsheetView::doTTest() ++{ ++ TTest* ttest = new TTest(i18n("doing T Test for %1", m_spreadsheet->name())); ++ ttest->setColumns(this->selectedColumns()); ++ ttest->performTwoSampleTest(); ++} ++ ++ + void SpreadsheetView::handleHorizontalSectionMoved(int index, int from, int to) { + Q_UNUSED(index); + +diff --git a/src/commonfrontend/spreadsheet/SpreadsheetView.h b/src/commonfrontend/spreadsheet/SpreadsheetView.h +index b67df1252..eceb1c556 100644 +--- a/src/commonfrontend/spreadsheet/SpreadsheetView.h ++++ b/src/commonfrontend/spreadsheet/SpreadsheetView.h +@@ -130,6 +130,7 @@ private: + QAction* action_go_to_cell; + QAction* action_statistics_all_columns; + QAction* action_pivot_table; ++ QAction* action_do_ttest; + + //column related actions + QAction* action_insert_column_left; +@@ -192,6 +193,7 @@ private: + QMenu* m_spreadsheetMenu; + QMenu* m_plotDataMenu; + QMenu* m_analyzePlotMenu; ++ QMenu* m_columnHypothesisTestingMenu{nullptr}; + + public slots: + void createContextMenu(QMenu*); +@@ -206,6 +208,7 @@ private slots: + void goToPreviousColumn(); + void goToCell(); + void createPivotTable(); ++ void doTTest(); + void sortSpreadsheet(); + void sortDialog(QVector); + +diff --git a/src/kdefrontend/pivot/HierarchicalHeaderView.cpp b/src/kdefrontend/pivot/HierarchicalHeaderView.cpp +index 09236b144..bc05ffcb1 100755 +--- a/src/kdefrontend/pivot/HierarchicalHeaderView.cpp ++++ b/src/kdefrontend/pivot/HierarchicalHeaderView.cpp +@@ -29,6 +29,8 @@ + #include + #include + ++#include ++ + HierarchicalHeaderItem::HierarchicalHeaderItem(HierarchicalHeaderItem* parent): + row_prop(0),column_prop(0),parent_item(parent) { + } +@@ -48,13 +50,13 @@ HierarchicalHeaderItem* HierarchicalHeaderItem::insertChild(int row, int col) { + const HierarchicalHeaderItem* HierarchicalHeaderItem::child(int row,int col) const { + QHash,HierarchicalHeaderItem*>::const_iterator itr = child_items.find(QPair(row,col)); + if (itr != child_items.end()) return itr.value(); +- return 0; ++ return nullptr; + } + + HierarchicalHeaderItem* HierarchicalHeaderItem::child(int row,int col) { + QHash,HierarchicalHeaderItem*>::iterator itr = child_items.find(QPair(row,col)); + if (itr != child_items.end()) return itr.value(); +- return 0; ++ return nullptr; + } + + void HierarchicalHeaderItem::setText(const QString& text) { +@@ -86,22 +88,58 @@ HierarchicalHeaderItem* HierarchicalHeaderItem::parent() { + void HierarchicalHeaderItem::clear() { + QList items = child_items.values(); + foreach (HierarchicalHeaderItem* item, child_items) { +- if (item) delete item; ++ if (item) { ++ delete item; ++ } + } + child_items.clear(); + } + +-//########### ++/********************************************************************************************** ++ * MODEL IMPLEMENTATION ++ * ++ * ********************************************************************************************/ + HierarchicalHeaderModel::HierarchicalHeaderModel(QObject* parent) : QAbstractTableModel(parent), + m_rootItem(new HierarchicalHeaderItem()) { + } + HierarchicalHeaderModel::HierarchicalHeaderModel(int rows, int cols, QObject* parent) : + QAbstractTableModel(parent),m_rowCount(rows),m_columnCount(cols),m_rootItem(new HierarchicalHeaderItem()) { ++ maxWidthArr = new int[m_columnCount]; ++ for(int col=0; colclear(); + delete m_rootItem; ++ delete maxWidthArr; ++} ++ ++void HierarchicalHeaderModel::setBaseSectionSize(QSize size) ++{ ++ ++ baseSectionSize = size; ++ ++ if(orientation == Qt::Vertical){ ++ for (int row=0;rowsetData(this->index(row,col),baseSectionSize,Qt::SizeHintRole); ++ } ++ return; ++ } ++ ++ for (int row=0;rowsetData(this->index(row,col),baseSectionSize,Qt::SizeHintRole); ++ } ++} ++ ++void HierarchicalHeaderModel::setOrientation(Qt::Orientation orient) ++{ ++ orientation = orient; + } + + QModelIndex HierarchicalHeaderModel::index(int row, int column, const QModelIndex & parent) const { +@@ -115,7 +153,6 @@ QModelIndex HierarchicalHeaderModel::index(int row, int column, const QModelInde + if (!childItem) childItem = parentItem->insertChild(row,column); + return createIndex(row,column,childItem); + +- return QModelIndex(); + } + + void HierarchicalHeaderModel::setRowCount(int count) { +@@ -129,6 +166,11 @@ void HierarchicalHeaderModel::setRowCount(int count) { + + void HierarchicalHeaderModel::setColumnCount(int count) { + m_columnCount = count; ++ ++ if(m_columnCount == 0) return; ++ maxWidthArr = new int[m_columnCount]; ++ for(int col=0; colsetData(span,ROW_SPAN_ROLE); + } +- } else ++ } ++ else if (role == Qt::DisplayRole || role == Qt::EditRole){ ++ item->setData(value, role); ++ if(orientation == Qt::Vertical) ++ { ++ int width = value.toString().length()*10; ++ int col = index.column(); ++ if(width > maxWidthArr[col]) ++ maxWidthArr[col] = width; ++ } ++ } ++ else + item->setData(value,role); + + return true; +@@ -195,9 +248,15 @@ Qt::ItemFlags HierarchicalHeaderModel::flags(const QModelIndex &index) const { + } + + void HierarchicalHeaderModel::clear() { ++// setRowCount(0); ++// setColumnCount(0); ++// m_rootItem->clear(); + } + +-//######################### ++/********************************************************************************************** ++ * VIEW IMPLEMENTATION ++ * ++ * ********************************************************************************************/ + HierarchicalHeaderView::HierarchicalHeaderView(Qt::Orientation orientation, int rows, int columns, QWidget* parent): + QHeaderView(orientation,parent) { + QSize baseSectionSize; +@@ -224,7 +283,6 @@ HierarchicalHeaderView::HierarchicalHeaderView(Qt::Orientation orientation, int + + HierarchicalHeaderView::HierarchicalHeaderView(Qt::Orientation orientation, QWidget* parent): + QHeaderView(orientation,parent) { +- QSize baseSectionSize; + if (orientation == Qt::Horizontal) { + baseSectionSize.setWidth(defaultSectionSize()); + baseSectionSize.setHeight(20); +@@ -241,10 +299,24 @@ HierarchicalHeaderView::HierarchicalHeaderView(Qt::Orientation orientation, QWid + + HierarchicalHeaderView::~HierarchicalHeaderView() = default; + ++ ++QSize HierarchicalHeaderView::getBaseSectionSize() const ++{ ++ return baseSectionSize; ++} ++ ++void HierarchicalHeaderView::setNewModel(HierarchicalHeaderModel* model) ++{ ++ m_model = model; ++ setModel(m_model); ++} ++ + HierarchicalHeaderModel* HierarchicalHeaderView::hierarchicalModel() const { + return m_model; + } + ++ ++ + void HierarchicalHeaderView::setRowHeight(int row, int rowHeight) { + const int cols = m_model->columnCount(); + for (int col = 0; col < cols; ++col) { +@@ -584,7 +656,9 @@ int HierarchicalHeaderView::getSectionRange(QModelIndex& index, int* beginSectio + } + + void HierarchicalHeaderView::onSectionResized(int logicalIndex,int oldSize,int newSize) { +- if (!m_model) ++ Q_UNUSED(oldSize); ++ ++ if (!m_model) + return; + + const int OTN = orientation(); +diff --git a/src/kdefrontend/pivot/HierarchicalHeaderView.h b/src/kdefrontend/pivot/HierarchicalHeaderView.h +index 398c80805..abd18e06b 100755 +--- a/src/kdefrontend/pivot/HierarchicalHeaderView.h ++++ b/src/kdefrontend/pivot/HierarchicalHeaderView.h +@@ -32,10 +32,10 @@ + #include + + enum eRbHeaderRole { +- COLUMN_SPAN_ROLE = Qt::UserRole+1, +- ROW_SPAN_ROLE, +- COLUMN_SIZE_ROLE, +- ROW_SIZE_ROLE, ++ COLUMN_SPAN_ROLE = Qt::UserRole+1, ++ ROW_SPAN_ROLE, ++ COLUMN_SIZE_ROLE, ++ ROW_SIZE_ROLE, + }; + + class HierarchicalHeaderItem { +@@ -65,6 +65,10 @@ private: + QHash role_datas; + }; + ++/**************************************************************************************************** ++ * ++ * MODEL DECLARATIONS ++ * *************************************************************************************************/ + + class HierarchicalHeaderModel: public QAbstractTableModel { + Q_OBJECT +@@ -85,12 +89,23 @@ public: + Qt::ItemFlags flags(const QModelIndex &index) const override; + void clear(); + ++ void setBaseSectionSize(QSize size); ++ void setOrientation(Qt::Orientation orient); + private: + int m_rowCount{0}; + int m_columnCount{0}; + HierarchicalHeaderItem* m_rootItem{nullptr}; ++ ++ int *maxWidthArr; ++ QSize baseSectionSize; ++ Qt::Orientation orientation; + }; + ++/**************************************************************************************************** ++ * ++ * VIEW DECLARATIONS ++ * *************************************************************************************************/ ++ + class HierarchicalHeaderView : public QHeaderView { + Q_OBJECT + public: +@@ -104,6 +119,9 @@ public: + void setCellBackgroundColor(const QModelIndex&, const QColor&); + void setCellForegroundColor(const QModelIndex&, const QColor&); + ++ QSize getBaseSectionSize() const; ++ void setNewModel(HierarchicalHeaderModel* model); ++ + protected: + void mousePressEvent(QMouseEvent*) override; + QModelIndex indexAt(const QPoint&) const override; +@@ -124,6 +142,7 @@ signals: + + private: + HierarchicalHeaderModel* m_model{nullptr}; ++ QSize baseSectionSize; + }; + + #endif +diff --git a/src/kdefrontend/pivot/PivotTableView.cpp b/src/kdefrontend/pivot/PivotTableView.cpp +index 38cb37ce1..c6493c8ce 100644 +--- a/src/kdefrontend/pivot/PivotTableView.cpp ++++ b/src/kdefrontend/pivot/PivotTableView.cpp +@@ -46,6 +46,8 @@ + #include + #include + ++#include ++ + /*! + \class PivotTableView + \brief View class for PivotTable +@@ -177,7 +179,21 @@ void PivotTableView::print(QPrinter* printer) const { + + void PivotTableView::changed() { + +-} ++ qDebug() << "in PivotTableView::changed()"; ++ HierarchicalHeaderModel* horizontalHeaderModel = static_cast(m_horizontalHeaderView->hierarchicalModel()); ++ HierarchicalHeaderModel* verticalHeaderModel = static_cast(m_verticalHeaderView->hierarchicalModel()); ++ ++ horizontalHeaderModel->setOrientation(Qt::Horizontal); ++ verticalHeaderModel->setOrientation(Qt::Vertical); ++ ++// qDebug() << " setting size for horizontal header"; ++// qDebug() << " rows, cols = " << horizontalHeaderModel->rowCount() << ", " << horizontalHeaderModel->columnCount(); ++ horizontalHeaderModel->setBaseSectionSize(m_horizontalHeaderView->getBaseSectionSize()); ++ ++// qDebug() << "settign size for vertical header"; ++// qDebug() << " rows, cols = " << verticalHeaderModel->rowCount() << ", " << verticalHeaderModel->columnCount(); ++ verticalHeaderModel->setBaseSectionSize(m_verticalHeaderView->getBaseSectionSize()); ++ } + + void PivotTableView::exportToFile(const QString& path, const bool exportHeader, const QString& separator, QLocale::Language language) const { + Q_UNUSED(exportHeader);