diff --git a/src/backend/hypothesis_test/HypothesisTest.cpp b/src/backend/hypothesis_test/HypothesisTest.cpp --- a/src/backend/hypothesis_test/HypothesisTest.cpp +++ b/src/backend/hypothesis_test/HypothesisTest.cpp @@ -154,6 +154,8 @@ * ****************************************************************************/ //TODO: round off numbers while printing +//TODO: backend of z test; + HypothesisTestPrivate::HypothesisTestPrivate(HypothesisTest* owner) : q(owner) { } @@ -195,7 +197,7 @@ int df = 0; double p_value = 0; double sp = 0; - clearGlobalVariables(); + clearTestView(); if (m_columns.size() != 2) { printError("Inappropriate number of columns selected"); @@ -319,7 +321,7 @@ double value; int df = 0; double p_value = 0; - clearGlobalVariables(); + clearTestView(); if (m_columns.size() != 2) { printError("Inappropriate number of columns selected"); @@ -338,16 +340,16 @@ ErrorType error_code = findStatsPaired(m_columns[0], m_columns[1], n, sum, mean, std); switch (error_code) { - case ErrorUnqualSize: { - printError("both columns are having different sizes"); - emit q->changed(); - return; - } case ErrorEmptyColumn: { - printError("columns are empty"); - emit q->changed(); - return; - } case NoError: - break; + case ErrorUnqualSize: { + printError("both columns are having different sizes"); + emit q->changed(); + return; + } case ErrorEmptyColumn: { + printError("columns are empty"); + emit q->changed(); + return; + } case NoError: + break; } if (n == -1) { @@ -405,7 +407,7 @@ double value; int df = 0; double p_value = 0; - clearGlobalVariables(); + clearTestView(); if (m_columns.size() != 1) { printError("Inappropriate number of columns selected"); @@ -477,7 +479,7 @@ // b stands for b/w groups // w stands for within groups void HypothesisTestPrivate::performOneWayAnova() { - clearGlobalVariables(); + clearTestView(); int np, total_rows; // np is number of partition i.e., number of classes countPartitions(m_columns[0], np, total_rows); @@ -585,6 +587,7 @@ } /**************************************Levene Test****************************************/ +// TODO: Fix: Program crashes when n = np; void HypothesisTestPrivate::performLeveneTest(bool categorical_variable) { QString test_name; double f_value; @@ -593,7 +596,7 @@ int np = 0; // number of partitions int n = 0; int total_rows = 0; - clearGlobalVariables(); + clearTestView(); if (m_columns.size() != 2) { printError("Inappropriate number of columns selected"); @@ -987,6 +990,9 @@ printLine(1, i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3", col1_name, UTF8_QSTRING(">"), col2_name), "blue"); break; case HypothesisTest::TailTwo: + // TODO: check for correctness between: + // p_value = 2*gsl_cdf_tdist_P(value, df) v/s + // p_value = gsl_cdf_tdis_P(value, df) + gsl_cdf_tdis_P(-value, df); p_value = 2.*gsl_cdf_tdist_P(value, df); printLine(0, i18n("Null Hypothesis: Population mean of %1 %2 Population mean of %3", col1_name, UTF8_QSTRING("="), col2_name), "blue"); @@ -1092,7 +1098,7 @@ } -void HypothesisTestPrivate::clearGlobalVariables() { +void HypothesisTestPrivate::clearTestView() { m_stats_table = ""; q->m_view->clearResult(); } diff --git a/src/backend/hypothesis_test/HypothesisTestPrivate.h b/src/backend/hypothesis_test/HypothesisTestPrivate.h --- a/src/backend/hypothesis_test/HypothesisTestPrivate.h +++ b/src/backend/hypothesis_test/HypothesisTestPrivate.h @@ -79,7 +79,7 @@ QString getLine(const QString &msg, const QString &color = "black"); void printLine(const int &index, const QString &msg, const QString &color = "black"); void printError(const QString &error_msg); - void clearGlobalVariables(); + void clearTestView(); }; diff --git a/src/kdefrontend/dockwidgets/HypothesisTestDock.h b/src/kdefrontend/dockwidgets/HypothesisTestDock.h --- a/src/kdefrontend/dockwidgets/HypothesisTestDock.h +++ b/src/kdefrontend/dockwidgets/HypothesisTestDock.h @@ -46,6 +46,25 @@ Q_OBJECT public: + struct Test { + enum Type { + NoneType = 0, + TTest = 1 << 0, + ZTest = 1 << 1, + Anova = 1 << 2 + }; + enum SubType { + NoneSubType = 0, + TwoSampleIndependent = 1 << 0, + TwoSamplePaired = 1 << 1, + OneSample = 1 << 2, + OneWay = 1 << 3, + TwoWay = 1 << 4 + }; + Type type = NoneType; + SubType subtype = NoneSubType; + }; + explicit HypothesisTestDock(QWidget*); void setHypothesisTest(HypothesisTest*); @@ -72,14 +91,7 @@ // void readConnections(); // void updateFields(); // bool fieldSelected(const QString&); - bool ttest{false}; - bool ztest{false}; - bool two_sample_independent{false}; - bool two_sample_paired{false}; - bool one_sample{false}; - bool anova{false}; - bool one_way{false}; - bool two_way{false}; + Test m_test; QScrollArea* scroll_dock; void countPartitions(Column *column, int &np, int &total_rows); @@ -87,9 +99,6 @@ void setColumnsComboBoxView(); bool nonEmptySelectedColumns(); - QStringList test_type_t_z; - QStringList test_type_anova; - QStringList only_values_cols; QStringList two_categorical_cols; QStringList more_than_two_categorical_cols; diff --git a/src/kdefrontend/dockwidgets/HypothesisTestDock.cpp b/src/kdefrontend/dockwidgets/HypothesisTestDock.cpp --- a/src/kdefrontend/dockwidgets/HypothesisTestDock.cpp +++ b/src/kdefrontend/dockwidgets/HypothesisTestDock.cpp @@ -70,16 +70,10 @@ m_configPath = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).constFirst() + "sql_connections"; // adding item to tests and testtype combo box; - ui.cbTest->addItem(i18n("T Test")); - ui.cbTest->addItem(i18n("Z Test")); - ui.cbTest->addItem(i18n("Anova")); - test_type_t_z.append( i18n( "Two Sample Independent")); - test_type_t_z.append( i18n("Two Sample Paired")); - test_type_t_z.append( i18n("One Sample")); - - test_type_anova.append( i18n("One Way")); - test_type_anova.append( i18n("Two Way")); + ui.cbTest->addItem( i18n("T Test"), Test::Type::TTest); + ui.cbTest->addItem( i18n("Z Test"), Test::Type::ZTest); + ui.cbTest->addItem( i18n("ANOVA"), Test::Type::Anova); // making all test blocks invisible at starting. ui.pbLeveneTest->hide(); @@ -135,6 +129,9 @@ ui.pbPerformTest->setIcon(QIcon::fromTheme("run-build")); + ui.leMuo->setText( i18n("%1", population_mean)); + ui.leAlpha->setText( i18n("%1", significance_level)); + // readConnections(); @@ -247,114 +244,144 @@ } void HypothesisTestDock::showTestType() { - ttest = ui.cbTest->currentText() == "T Test"; - ztest = ui.cbTest->currentText() == "Z Test"; - anova = ui.cbTest->currentText() == "Anova"; + m_test.type = Test::Type(ui.cbTest->currentData().toInt()); ui.cbTestType->clear(); + if (m_test.type & (Test::Type::TTest | Test::Type::ZTest)) { + ui.cbTestType->addItem( i18n("Two Sample Independent"), Test::SubType::TwoSampleIndependent); + ui.cbTestType->addItem( i18n("Two Sample Paired"), Test::SubType::TwoSamplePaired); + ui.cbTestType->addItem( i18n("One Sample"), Test::SubType::OneSample); + } + else if (m_test.type & Test::Type::Anova) { + ui.cbTestType->addItem( i18n("One Way"), Test::SubType::OneWay); + ui.cbTestType->addItem( i18n("Two Way"), Test::SubType::TwoWay); + } - if (ttest || ztest) - ui.cbTestType->addItems(test_type_t_z); - if (anova) - ui.cbTestType->addItems(test_type_anova); showHypothesisTest(); } void HypothesisTestDock::showHypothesisTest() { - one_way = ui.cbTestType->currentText() == "One Way"; - two_way = ui.cbTestType->currentText() == "Two Way"; - - two_sample_independent = ui.cbTestType->currentText() == "Two Sample Independent"; - two_sample_paired = ui.cbTestType->currentText() == "Two Sample Paired"; - one_sample = ui.cbTestType->currentText() == "One Sample"; - - ui.lCol1->setVisible(anova || two_sample_independent || two_sample_paired); - ui.cbCol1->setVisible(anova || two_sample_independent || two_sample_paired); - ui.lCol2->setVisible(anova || two_sample_independent || two_sample_paired || one_sample); - ui.cbCol2->setVisible(anova || two_sample_independent || two_sample_paired || one_sample); - ui.lEqualVariance->setVisible(ttest && two_sample_independent); - ui.chbEqualVariance->setVisible(ttest && two_sample_independent); - ui.lCategorical->setVisible(ttest && two_sample_independent); - ui.chbCategorical->setVisible(ttest && two_sample_independent); - ui.pbLeveneTest->setVisible(anova || (ttest && two_sample_independent)); + m_test.subtype = Test::SubType(ui.cbTestType->currentData().toInt()); + + ui.lCol1->show(); + ui.cbCol1->show(); + + ui.lCol2->setVisible(m_test.subtype & (~Test::SubType::OneSample)); + ui.cbCol2->setVisible(m_test.subtype & (~Test::SubType::OneSample)); + + ui.lEqualVariance->setVisible( (m_test.type & Test::Type::TTest) & + (m_test.subtype & Test::SubType::TwoSampleIndependent)); + ui.chbEqualVariance->setVisible( (m_test.type & Test::Type::TTest) & + (m_test.subtype & Test::SubType::TwoSampleIndependent)); + + ui.lCategorical->setVisible( (m_test.type & Test::Type::TTest) & + (m_test.subtype & Test::SubType::TwoSampleIndependent)); + ui.chbCategorical->setVisible( (m_test.type & Test::Type::TTest) & + (m_test.subtype & Test::SubType::TwoSampleIndependent)); + + ui.pbLeveneTest->setVisible( (m_test.type & Test::Type::Anova) | + ( (m_test.type & Test::Type::TTest) & + (m_test.subtype & Test::SubType::TwoSampleIndependent))); + ui.chbEqualVariance->setChecked(true); - ui.rbH1OneTail2->setVisible(two_sample_independent || two_sample_paired || one_sample); - ui.rbH1OneTail1->setVisible(two_sample_independent || two_sample_paired || one_sample); - ui.rbH1TwoTail->setVisible(two_sample_independent || two_sample_paired || one_sample); - ui.rbH0OneTail1->setVisible(two_sample_independent || two_sample_paired || one_sample); - ui.rbH0OneTail2->setVisible(two_sample_independent || two_sample_paired || one_sample); - ui.rbH0TwoTail->setVisible(two_sample_independent || two_sample_paired || one_sample); - ui.lH0->setVisible(two_sample_independent || two_sample_paired || one_sample); - ui.lH1->setVisible(two_sample_independent || two_sample_paired || one_sample); + ui.lH1->setVisible( (m_test.type & ~Test::Type::Anova)); + ui.rbH1OneTail1->setVisible( (m_test.type & ~Test::Type::Anova)); + ui.rbH1OneTail2->setVisible( (m_test.type & ~Test::Type::Anova)); + ui.rbH1TwoTail->setVisible( (m_test.type & ~Test::Type::Anova)); + + ui.lH0->setVisible( (m_test.type & ~Test::Type::Anova)); + ui.rbH0OneTail1->setVisible( (m_test.type & ~Test::Type::Anova)); + ui.rbH0OneTail2->setVisible( (m_test.type & ~Test::Type::Anova)); + ui.rbH0TwoTail->setVisible( (m_test.type & ~Test::Type::Anova)); ui.rbH1TwoTail->setChecked(true); - ui.lMuo->setVisible(one_sample); - ui.leMuo->setVisible(one_sample); - ui.lAlpha->setVisible(anova || two_sample_independent || two_sample_paired || one_sample); - ui.leAlpha->setVisible(anova || two_sample_independent || two_sample_paired || one_sample); + ui.lMuo->setVisible( (m_test.subtype & Test::SubType::OneSample)); + ui.leMuo->setVisible( (m_test.subtype & Test::SubType::OneSample)); - ui.leMuo->setText( i18n("%1", population_mean)); - ui.leAlpha->setText( i18n("%1", significance_level)); + ui.lAlpha->show(); + ui.leAlpha->show(); setColumnsComboBoxView(); - ui.pbPerformTest->setEnabled(nonEmptySelectedColumns() && - (anova || - two_sample_independent || two_sample_paired || one_sample)); + ui.pbPerformTest->setEnabled(nonEmptySelectedColumns()); + ui.pbLeveneTest->setEnabled(nonEmptySelectedColumns()); } void HypothesisTestDock::doHypothesisTest() { - m_hypothesisTest->setPopulationMean(ui.leMuo->text()); m_hypothesisTest->setSignificanceLevel(ui.leAlpha->text()); QStringList cols; - if(ttest) { - if(two_sample_independent) { - cols << ui.cbCol1->currentText() << ui.cbCol2->currentText(); - m_hypothesisTest->setColumns(cols); + switch (m_test.type) { + case Test::Type::TTest: { + cols << ui.cbCol1->currentText() << ui.cbCol2->currentText(); + m_hypothesisTest->setColumns(cols); + + switch (m_test.subtype) { + case Test::SubType::TwoSampleIndependent: m_hypothesisTest->performTwoSampleIndependentTTest(ui.chbCategorical->isChecked(), ui.chbEqualVariance->isChecked()); - } - else if(two_sample_paired) { - cols << ui.cbCol1->currentText(); - cols << ui.cbCol2->currentText(); - m_hypothesisTest->setColumns(cols); + break; + case Test::SubType::TwoSamplePaired: m_hypothesisTest->performTwoSamplePairedTTest(); - } - else if(one_sample){ + break; + case Test::SubType::OneSample: { cols << ui.cbCol1->currentText(); m_hypothesisTest->setColumns(cols); m_hypothesisTest->performOneSampleTTest(); + break; } + case Test::SubType::OneWay: + break; + case Test::SubType::TwoWay: + break; + } + break; } - else if(ztest) { - if(two_sample_independent) { - cols << ui.cbCol1->currentText(); - cols << ui.cbCol2->currentText(); - m_hypothesisTest->setColumns(cols); + case Test::Type::ZTest: { + cols << ui.cbCol1->currentText() << ui.cbCol2->currentText(); + m_hypothesisTest->setColumns(cols); + + switch (m_test.subtype) { + case Test::SubType::TwoSampleIndependent: m_hypothesisTest->performTwoSampleIndependentZTest(); - } - else if(two_sample_paired) { - cols << ui.cbCol1->currentText(); - cols << ui.cbCol2->currentText(); - m_hypothesisTest->setColumns(cols); + break; + case Test::SubType::TwoSamplePaired: m_hypothesisTest->performTwoSamplePairedZTest(); - } - else if(one_sample){ + break; + case Test::SubType::OneSample: { cols << ui.cbCol1->currentText(); m_hypothesisTest->setColumns(cols); m_hypothesisTest->performOneSampleZTest(); + break; + } + case Test::SubType::OneWay: + break; + case Test::SubType::TwoWay: + break; + case Test::SubType::NoneSubType: + break; } + + break; } - else if(anova) { - QStringList cols; - if(one_way) { - cols << ui.cbCol1->currentText() << ui.cbCol2->currentText(); - m_hypothesisTest->setColumns(cols); + case Test::Type::Anova: { + cols << ui.cbCol1->currentText() << ui.cbCol2->currentText(); + m_hypothesisTest->setColumns(cols); + + switch (m_test.subtype) { + case Test::SubType::OneWay: m_hypothesisTest->performOneWayAnova(); + break; + case Test::SubType::TwoWay: + break; } + + break; + } + case Test::Type::NoneType: + break; } } @@ -521,7 +548,7 @@ } void HypothesisTestDock::changeCbCol2Label() { - if (two_sample_paired) { + if ( (m_test.type & ~Test::Type::Anova) & (m_test.subtype & ~Test::SubType::TwoSampleIndependent)) { ui.lCol2->setText( i18n("Independent Var. 2")); return; } @@ -733,7 +760,7 @@ void HypothesisTestDock::setColumnsComboBoxModel(Spreadsheet* spreadsheet) { only_values_cols.clear(); two_categorical_cols.clear(); - more_than_two_categorical_cols.clear(); + more_than_two_categorical_cols.clear(); for (auto* col : spreadsheet->children()) { if (col->columnMode() == AbstractColumn::Integer || col->columnMode() == AbstractColumn::Numeric) @@ -757,17 +784,17 @@ ui.cbCol1->clear(); ui.cbCol2->clear(); - if (two_sample_independent) { + if (m_test.subtype & Test::SubType::TwoSampleIndependent) { ui.cbCol1->addItems(only_values_cols); ui.cbCol1->addItems(two_categorical_cols); ui.cbCol2->addItems(only_values_cols); - } else if (two_sample_paired) { + } else if (m_test.subtype & Test::SubType::TwoSamplePaired) { ui.cbCol1->addItems(only_values_cols); ui.cbCol2->addItems(only_values_cols); - } else if (one_sample) + } else if (m_test.subtype & Test::SubType::OneSample) ui.cbCol1->addItems(only_values_cols); - else if (anova) { + else if (m_test.type & Test::Type::Anova) { ui.cbCol1->addItems(two_categorical_cols); ui.cbCol1->addItems(more_than_two_categorical_cols); ui.cbCol2->addItems(only_values_cols);