diff --git a/src/backend/hypothesis_test/HypothesisTest.cpp b/src/backend/hypothesis_test/HypothesisTest.cpp index 6e85493e4..2dbb51588 100644 --- a/src/backend/hypothesis_test/HypothesisTest.cpp +++ b/src/backend/hypothesis_test/HypothesisTest.cpp @@ -1,321 +1,648 @@ /*************************************************************************** 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 HypothesisTest::HypothesisTest(const QString &name) : AbstractPart(name), d(new HypothesisTestPrivate(this)) { } HypothesisTest::~HypothesisTest() { delete d; } QAbstractItemModel* HypothesisTest::dataModel() { return d->dataModel; } QAbstractItemModel* HypothesisTest::horizontalHeaderModel() { return d->horizontalHeaderModel; } 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; } 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() { - d->performTwoSampleTTest(); + +} + +void HypothesisTest::performTwoSampleIndependetTTest(bool equal_variance) { + d->performTwoSampleIndependetTest("ttest", equal_variance); +} + +void HypothesisTest::performTwoSamplePairedTTest() { + d->performTwoSamplePairedTest("ttest"); +} + +void HypothesisTest::PerformOneSampleTTest() { + d->PerformOneSampleTest("ttest"); +} + +void HypothesisTest::performTwoSampleIndependetZTest() { + d->performTwoSampleIndependetTest("ztest"); +} + +void HypothesisTest::performTwoSamplePairedZTest() { + d->performTwoSamplePairedTest("ztest"); } +void HypothesisTest::PerformOneSampleZTest() { + d->PerformOneSampleTest("ztest"); +} + + + + QString HypothesisTest::testName() { return d->m_currTestName; } /****************************************************************************** * Private Implementations * ****************************************************************************/ HypothesisTestPrivate::HypothesisTestPrivate(HypothesisTest* owner) : q(owner) , dataModel(new QStandardItemModel) , horizontalHeaderModel(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 (col != "") { column = dataSourceSpreadsheet->column(col); // qDebug() << "col is " << col; m_columns.append(column); } } } -void HypothesisTestPrivate::performTwoSampleTTest() { +void HypothesisTestPrivate::performTwoSampleIndependetTest(QString test, bool equal_variance) { dataModel->clear(); horizontalHeaderModel->clear(); - m_currTestName = i18n("Independent Two Sample T Test"); - DEBUG("performing two sample test :DEBUG MACRO"); - qDebug() << "performing two sample test: qDebug()"; + if (test == "ttest") + m_currTestName = i18n("Two Sample Independent T Test"); + if (test == "ztest") + m_currTestName = i18n("Two Sample Independent Z Test"); + + qDebug() << "performing two sample independent T test"; 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; bool allColumnsValid = 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(!allColumnsValid) { msg_box->setText(i18n("one of the selected columns is invalid")); msg_box->exec(); return; } if (!modeOk) { msg_box->setText(i18n("select only columns with numbers")); msg_box->exec(); return; } - dataModel->setRowCount(1); - dataModel->setColumnCount(3); - - horizontalHeaderModel->setColumnCount(3); 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]); - DEBUG( "for " << i); - DEBUG( "n is " << n[i]); - DEBUG( "mean is " << mean[i]); - DEBUG( "std is " << std[i]); if (n[i] < 1) { msg_box->setText(i18n("atleast one of selected column is 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); + if (test == "ttest") { + + dataModel->setRowCount(1); + dataModel->setColumnCount(3); + + horizontalHeaderModel->setColumnCount(3); + + double t; + int df; + 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); + + + t = (mean[0] - mean[1])/(sp*qSqrt(1.0/n[0] + 1.0/n[1])); + } else { + double temp; + temp = qPow( qPow(std[0], 2)/n[0] + qPow(std[1], 2)/n[1], 2); + temp = temp / ( (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); + + t = (mean[0] - mean[1]) / (qSqrt( (qPow(std[0], 2)/n[0]) + (qPow(std[1], 2)/n[1]))); + } + + // now finding p value from t value + double p_value = nsl_stats_tdist_p(t, df); + + // QString text = i18n("T value for test is %1 and\n p value is %2",t, p_value); + // msg_box->setText(text); + // msg_box->exec(); + + //setting dataModel + dataModel->setItem(0, 0, new QStandardItem(QString::number(t))); + dataModel->setItem(0, 1, new QStandardItem(QString::number(df))); + dataModel->setItem(0, 2, new QStandardItem(QString::number(p_value))); + + + //setting horizontal header model + horizontalHeaderModel->setHeaderData(0, Qt::Horizontal, "t value"); + horizontalHeaderModel->setHeaderData(1, Qt::Horizontal, "dof"); + horizontalHeaderModel->setHeaderData(2, Qt::Horizontal, "p value"); + + emit q->changed(); + return; + } else if(test == "ztest") { + dataModel->setRowCount(1); + dataModel->setColumnCount(2); + + horizontalHeaderModel->setColumnCount(2); + + 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); + + double z = (mean[0] - mean[1])/(sp*qSqrt(1.0/n[0] + 1.0/n[1])); + + // now finding p value from t value + double p_value = nsl_stats_tdist_p(z, df); + + // QString text = i18n("T value for test is %1 and\n p value is %2",t, p_value); + // msg_box->setText(text); + // msg_box->exec(); + + //setting dataModel + dataModel->setItem(0, 0, new QStandardItem(QString::number(z))); + dataModel->setItem(0, 1, new QStandardItem(QString::number(p_value))); + + + //setting horizontal header model + horizontalHeaderModel->setHeaderData(0, Qt::Horizontal, "z value"); + horizontalHeaderModel->setHeaderData(1, Qt::Horizontal, "p value"); + + emit q->changed(); + return; + } + +} + +void HypothesisTestPrivate::performTwoSamplePairedTest(QString test) { + dataModel->clear(); + horizontalHeaderModel->clear();\ + if (test == "ttest") + m_currTestName = i18n("Two Sample Paired T Test"); + if (test == "ztest") + m_currTestName = i18n("Two Sample Paired Z Test"); + + qDebug() << "performing two sample paired t test"; + + 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; + bool allColumnsValid = 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(!allColumnsValid) { + msg_box->setText(i18n("one of the selected columns is invalid")); + msg_box->exec(); + return; + } - QDEBUG("sp is " << sp); + if (!modeOk) { + msg_box->setText(i18n("select only columns with numbers")); + msg_box->exec(); + return; + } - double t = (mean[0] - mean[1])/(sp*qSqrt(1.0/n[0] + 1.0/n[1])); + 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(); + return; + } - // now finding p value from t value - double p_value = nsl_stats_tdist_p(t, df); + if (n < 1) { + msg_box->setText(i18n("columns are empty")); + msg_box->exec(); + return; + } -// QString text = i18n("T value for test is %1 and\n p value is %2",t, p_value); -// msg_box->setText(text); -// msg_box->exec(); + if (test == "ttest") { + dataModel->setRowCount(1); + dataModel->setColumnCount(3); - //setting dataModel - dataModel->setItem(0, 0, new QStandardItem(QString::number(t))); - dataModel->setItem(0, 1, new QStandardItem(QString::number(df))); - dataModel->setItem(0, 2, new QStandardItem(QString::number(p_value))); + horizontalHeaderModel->setColumnCount(3); + double t = mean / (std/qSqrt(n)); + int df = n - 1; - //setting horizontal header model - horizontalHeaderModel->setHeaderData(0, Qt::Horizontal, "t value"); - horizontalHeaderModel->setHeaderData(1, Qt::Horizontal, "dof"); - horizontalHeaderModel->setHeaderData(2, Qt::Horizontal, "p value"); + // now finding p value from t value + double p_value = nsl_stats_tdist_p(t, df); - emit q->changed(); + + + // QString text = i18n("T value for test is %1 and\n p value is %2",t, p_value); + // msg_box->setText(text); + // msg_box->exec(); + + //setting dataModel + dataModel->setItem(0, 0, new QStandardItem(QString::number(t))); + dataModel->setItem(0, 1, new QStandardItem(QString::number(df))); + dataModel->setItem(0, 2, new QStandardItem(QString::number(p_value))); + + + //setting horizontal header model + horizontalHeaderModel->setHeaderData(0, Qt::Horizontal, "t value"); + horizontalHeaderModel->setHeaderData(1, Qt::Horizontal, "dof"); + horizontalHeaderModel->setHeaderData(2, Qt::Horizontal, "p value"); + + emit q->changed(); + return; + } else if (test == "ztest") { + dataModel->setRowCount(1); + dataModel->setColumnCount(2); + + horizontalHeaderModel->setColumnCount(2); + + double z = mean / (std/qSqrt(n)); + int df = n - 1; + + // now finding p value from t value + double p_value = nsl_stats_tdist_p(z, df); + + // QString text = i18n("T value for test is %1 and\n p value is %2",t, p_value); + // msg_box->setText(text); + // msg_box->exec(); + + //setting dataModel + dataModel->setItem(0, 0, new QStandardItem(QString::number(z))); + dataModel->setItem(0, 1, new QStandardItem(QString::number(p_value))); + + + //setting horizontal header model + horizontalHeaderModel->setHeaderData(0, Qt::Horizontal, "z value"); + horizontalHeaderModel->setHeaderData(1, Qt::Horizontal, "p value"); + + emit q->changed(); + return; + } +} + +void HypothesisTestPrivate::PerformOneSampleTest(QString test) { + double population_mean = 0; + dataModel->clear(); + horizontalHeaderModel->clear(); + if (test == "ttest") + m_currTestName = i18n("One Sample T Test"); + if (test == "ztest") + m_currTestName = i18n("One Sample Z Test"); + + qDebug() << "performing two sample paired t test"; + + 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(); + 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(); + 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(); + return; + } + + if (test == "ttest") { + dataModel->setRowCount(1); + dataModel->setColumnCount(3); + + horizontalHeaderModel->setColumnCount(3); + + double t = (mean - population_mean) / (std/qSqrt(n)); + int df = n - 1; + + // now finding p value from t value + double p_value = nsl_stats_tdist_p(t, df); + + // QString text = i18n("T value for test is %1 and\n p value is %2",t, p_value); + // msg_box->setText(text); + // msg_box->exec(); + + //setting dataModel + dataModel->setItem(0, 0, new QStandardItem(QString::number(t))); + dataModel->setItem(0, 1, new QStandardItem(QString::number(df))); + dataModel->setItem(0, 2, new QStandardItem(QString::number(p_value))); + + + //setting horizontal header model + horizontalHeaderModel->setHeaderData(0, Qt::Horizontal, "t value"); + horizontalHeaderModel->setHeaderData(1, Qt::Horizontal, "dof"); + horizontalHeaderModel->setHeaderData(2, Qt::Horizontal, "p value"); + + emit q->changed(); + return; + } else if (test == "ztest") { + dataModel->setRowCount(1); + dataModel->setColumnCount(2); + + horizontalHeaderModel->setColumnCount(2); + + double z = (mean - population_mean) / (std/qSqrt(n)); + int df = n - 1; + + // now finding p value from t value + double p_value = nsl_stats_tdist_p(z, df); + + // QString text = i18n("T value for test is %1 and\n p value is %2",t, p_value); + // msg_box->setText(text); + // msg_box->exec(); + + //setting dataModel + dataModel->setItem(0, 0, new QStandardItem(QString::number(z))); + dataModel->setItem(0, 1, new QStandardItem(QString::number(p_value))); + + + //setting horizontal header model + horizontalHeaderModel->setHeaderData(0, Qt::Horizontal, "z value"); + horizontalHeaderModel->setHeaderData(1, Qt::Horizontal, "p value"); + + emit q->changed(); + return; + } +} + +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; + for (int i = 0; i < count; i++) { + row1 = column1->valueAt(i); + row2 = column2->valueAt(i); + + if (std::isnan(row1) || std::isnan(row2)) { + if (std::isnan(row1) && std::isnan(row2)) + count = i; + else { + count = -1; + return; + } + break; + } + + sum += row1 - row2; + } + + 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; + 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; } /********************************************************************************** * 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); return menu; } diff --git a/src/backend/hypothesis_test/HypothesisTest.h b/src/backend/hypothesis_test/HypothesisTest.h index 8cfcbb7f0..209bd7d47 100644 --- a/src/backend/hypothesis_test/HypothesisTest.h +++ b/src/backend/hypothesis_test/HypothesisTest.h @@ -1,91 +1,98 @@ /*************************************************************************** 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 QAbstractItemModel; class QString; class Column; class HypothesisTest : public AbstractPart { Q_OBJECT public: explicit HypothesisTest(const QString& name); ~HypothesisTest() override; enum DataSourceType {DataSourceSpreadsheet, DataSourceDatabase}; QAbstractItemModel* dataModel(); QAbstractItemModel *horizontalHeaderModel(); QString testName(); void setDataSourceSpreadsheet(Spreadsheet* spreadsheet); void setColumns(QVector cols); void setColumns(QStringList cols); void performTwoSampleTTest(); + void performTwoSampleIndependetTTest(bool equal_variance); + void performTwoSamplePairedTTest(); + void PerformOneSampleTTest(); + void performTwoSampleIndependetZTest(); + 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(); 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 426a192ac..f3814d7c6 100644 --- a/src/backend/hypothesis_test/HypothesisTestPrivate.h +++ b/src/backend/hypothesis_test/HypothesisTestPrivate.h @@ -1,68 +1,71 @@ /*************************************************************************** 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(); 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}; bool m_dbCreated{false}; int m_rowCount{0}; int m_columnCount{0}; QString m_currTestName{"Result Table"}; - void performTwoSampleTTest(); + void performTwoSampleIndependetTest(QString test, bool equal_variance = true); + void performTwoSamplePairedTest(QString test); + void PerformOneSampleTest(QString test); 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); // QMap m_members; }; #endif diff --git a/src/kdefrontend/dockwidgets/HypothesisTestDock.cpp b/src/kdefrontend/dockwidgets/HypothesisTestDock.cpp index 2ece9ad7b..7fe423526 100644 --- a/src/kdefrontend/dockwidgets/HypothesisTestDock.cpp +++ b/src/kdefrontend/dockwidgets/HypothesisTestDock.cpp @@ -1,480 +1,605 @@ /*************************************************************************** File : HypothesisTestDock.cpp Project : LabPlot Description : widget for hypothesis test properties -------------------------------------------------------------------- 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 "HypothesisTestDock.h" #include "backend/core/AspectTreeModel.h" #include "backend/core/AbstractAspect.h" #include "backend/core/Project.h" #include "backend/spreadsheet/Spreadsheet.h" #include "commonfrontend/widgets/TreeViewComboBox.h" #include "kdefrontend/datasources/DatabaseManagerDialog.h" #include "kdefrontend/datasources/DatabaseManagerWidget.h" //#include "kdefrontend/pivot/hypothesisTestView.h" #include "kdefrontend/TemplateHandler.h" #include #include #include #include #include #include /*! \class HypothesisTestDock \brief Provides a dock (widget) for hypothesis testing: \ingroup kdefrontend */ HypothesisTestDock::HypothesisTestDock(QWidget* parent) : QWidget(parent) { ui.setupUi(this); ui.cbDataSourceType->addItem(i18n("Spreadsheet")); ui.cbDataSourceType->addItem(i18n("Database")); cbSpreadsheet = new TreeViewComboBox; ui.gridLayout->addWidget(cbSpreadsheet, 5, 3, 1, 4); ui.bDatabaseManager->setIcon(QIcon::fromTheme("network-server-database")); ui.bDatabaseManager->setToolTip(i18n("Manage connections")); m_configPath = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).constFirst() + "sql_connections"; -// readConnections(); + + + + + // making all test blocks invisible at starting. + ui.lIndependentVariable1->setVisible(false); + ui.cbCol1->setVisible(false); + ui.cbVariable2->setVisible(false); + ui.cbCol2->setVisible(false); + ui.chbEqualVariance->setVisible(false); + ui.chbEqualVariance->setChecked(true); + ui.pbPerformTest->setEnabled(false); + ui.rb_h1_one_tail_2->setVisible(false); + ui.rb_h1_one_tail_1->setVisible(false); + ui.rb_h1_two_tail->setVisible(false); + ui.rb_h0_one_tail_1->setVisible(false); + ui.rb_h0_one_tail_2->setVisible(false); + ui.rb_h0_two_tail->setVisible(false); + ui.l_h0->setVisible(false); + ui.l_h1->setVisible(false); + + QString mu = QChar(0x3BC); + QString mu0 = mu+QChar(0x2092); + + // radio button for null and alternate hypothesis + // for alternative hypothesis + // one_tail_1 is mu > mu0; one_tail_2 is mu < mu0; two_tail = mu != mu0; + ui.rb_h1_one_tail_1->setText(mu + " " + QChar(0x3E) + " " + mu0); + ui.rb_h1_one_tail_2->setText(mu + " " + QChar(0x3C) + " " + mu0); + ui.rb_h1_two_tail->setText(mu + " " + QChar(0x2260) + " " + mu0); + + ui.rb_h0_one_tail_1->setText(mu + " " + QChar(0x2264) + " " + mu0); + ui.rb_h0_one_tail_2->setText(mu + " " + QChar(0x2265) + " " + mu0); + ui.rb_h0_two_tail->setText(mu + " " + QChar(0x3D) + " " + mu0); + + ui.rb_h0_two_tail->setEnabled(false); + ui.rb_h0_one_tail_1->setEnabled(false); + ui.rb_h0_one_tail_2->setEnabled(false); + + // readConnections(); // auto* style = ui.bAddRow->style(); // ui.bAddRow->setIcon(style->standardIcon(QStyle::SP_ArrowRight)); // ui.bAddRow->setToolTip(i18n("Add the selected field to rows")); // ui.bRemoveRow->setIcon(style->standardIcon(QStyle::SP_ArrowLeft)); // ui.bRemoveRow->setToolTip(i18n("Remove the selected field from rows")); // ui.bAddColumn->setIcon(style->standardIcon(QStyle::SP_ArrowRight)); // ui.bAddColumn->setToolTip(i18n("Add the selected field to columns")); // ui.bRemoveColumn->setIcon(style->standardIcon(QStyle::SP_ArrowLeft)); // ui.bRemoveColumn->setToolTip(i18n("Remove the selected field from columns")); // //add/remove buttons only enabled if something was selected // ui.bAddRow->setEnabled(false); // ui.bRemoveRow->setEnabled(false); // ui.bAddColumn->setEnabled(false); // ui.bRemoveColumn->setEnabled(false); // connect(ui.leName, &QLineEdit::textChanged, this, &HypothesisTestDock::nameChanged); // connect(ui.leComment, &QLineEdit::textChanged, this, &HypothesisTestDock::commentChanged); connect(ui.cbDataSourceType, static_cast(&QComboBox::currentIndexChanged), this, &HypothesisTestDock::dataSourceTypeChanged); connect(cbSpreadsheet, &TreeViewComboBox::currentModelIndexChanged, this, &HypothesisTestDock::spreadsheetChanged); // connect(ui.cbConnection, static_cast(&QComboBox::currentIndexChanged), // this, &HypothesisTestDock::connectionChanged); // connect(ui.cbTable, static_cast(&QComboBox::currentIndexChanged), // this, &HypothesisTestDock::tableChanged); // connect(ui.bDatabaseManager, &QPushButton::clicked, this, &HypothesisTestDock::showDatabaseManager); // connect(ui.bAddRow, &QPushButton::clicked, this, &HypothesisTestDock::addRow); // connect(ui.bRemoveRow, &QPushButton::clicked, this,&HypothesisTestDock::removeRow); // connect(ui.bAddColumn, &QPushButton::clicked, this, &HypothesisTestDock::addColumn); // connect(ui.bRemoveColumn, &QPushButton::clicked, this,&HypothesisTestDock::removeColumn); // connect(ui.cbCol1, static_cast(&QComboBox::currentIndexChanged), this, &HypothesisTestDock::doTTest); // connect(ui.cbCol2, static_cast(&QComboBox::currentIndexChanged), this, &HypothesisTestDock::doTTest); // connect(ui.lwFields, &QListWidget::itemSelectionChanged, this, [=]() { // bool enabled = !ui.lwFields->selectedItems().isEmpty(); // ui.bAddRow->setEnabled(enabled); // ui.bAddColumn->setEnabled(enabled); // }); // connect(ui.lwRows, &QListWidget::doubleClicked, this,&HypothesisTestDock::removeRow); // connect(ui.lwRows, &QListWidget::itemSelectionChanged, this, [=]() { // ui.bRemoveRow->setEnabled(!ui.lwRows->selectedItems().isEmpty()); // }); // connect(ui.lwColumns, &QListWidget::doubleClicked, this,&HypothesisTestDock::removeColumn); // connect(ui.lwColumns, &QListWidget::itemSelectionChanged, this, [=]() { // ui.bRemoveColumn->setEnabled(!ui.lwColumns->selectedItems().isEmpty()); // }); - connect(ui.pbPerformTest, &QPushButton::clicked, this, &HypothesisTestDock::doTTest); + connect(ui.twTests, &QTreeWidget::itemClicked, this, &HypothesisTestDock::showHypothesisTest); + connect(ui.pbPerformTest, &QPushButton::clicked, this, &HypothesisTestDock::doHypothesisTest); } void HypothesisTestDock::setHypothesisTest(HypothesisTest* HypothesisTest) { // m_initializing = true; m_hypothesisTest = HypothesisTest; //// m_aspectTreeModel = new AspectTreeModel(m_hypothesisTest->project()); // QList list; // list << "Folder" << "Workbook" << "Spreadsheet" << "LiveDataSource"; // cbSpreadsheet->setTopLevelClasses(list); // list.clear(); // list << "Spreadsheet" << "LiveDataSource"; //// m_aspectTreeModel->setSelectableAspects(list); //// cbSpreadsheet->setModel(m_aspectTreeModel); //show the properties ui.leName->setText(m_hypothesisTest->name()); ui.leComment->setText(m_hypothesisTest->comment()); ui.cbDataSourceType->setCurrentIndex(m_hypothesisTest->dataSourceType()); // if (m_hypothesisTest->dataSourceType() == HypothesisTest::DataSourceSpreadsheet) // setModelIndexFromAspect(cbSpreadsheet, m_hypothesisTest->dataSourceSpreadsheet()); // else // ui.cbConnection->setCurrentIndex(ui.cbConnection->findText(m_hypothesisTest->dataSourceConnection())); //clearing all cbCol* ui.cbCol1->clear(); ui.cbCol2->clear(); for (auto* col : m_hypothesisTest->dataSourceSpreadsheet()->children()) { ui.cbCol1->addItem(col->name()); ui.cbCol2->addItem(col->name()); } this->dataSourceTypeChanged(ui.cbDataSourceType->currentIndex()); // setting rows and columns in combo box; // //available dimensions and measures // ui.lwFields->clear(); // for (auto dimension : m_hypothesisTest->dimensions()) // ui.lwFields->addItem(new QListWidgetItem(QIcon::fromTheme("draw-text"), dimension)); // for (auto measure : m_hypothesisTest->measures()) // ui.lwFields->addItem(new QListWidgetItem(measure)); // //undo functions // connect(m_hypothesisTest, SIGNAL(aspectDescriptionChanged(const AbstractAspect*)), this, SLOT(hypothesisTestDescriptionChanged(const AbstractAspect*))); // //TODO: // m_initializing = false; } -void HypothesisTestDock::doTTest() { +void HypothesisTestDock::showHypothesisTest(QTreeWidgetItem* item, int col) { + if(item->parent() != nullptr){ + ttest = item->parent()->text(col) == "Student's T Test"; + ztest = item->parent()->text(col) == "Z Test"; + } + + two_sample_independent = item->text(col) == "Two Sample Independent"; + two_sample_paired = item->text(col) == "Two Sample Paired"; + one_sample = item->text(col) == "One Sample"; + + ui.lIndependentVariable1->setVisible(two_sample_independent || two_sample_paired || one_sample); + ui.cbCol1->setVisible(two_sample_independent || two_sample_paired || one_sample); + ui.cbVariable2->setVisible(two_sample_independent || two_sample_paired); + ui.cbCol2->setVisible(two_sample_independent || two_sample_paired); + ui.chbEqualVariance->setVisible(ttest && two_sample_independent); + ui.chbEqualVariance->setChecked(true); + ui.pbPerformTest->setEnabled(two_sample_independent || two_sample_paired || one_sample); + + ui.rb_h1_one_tail_2->setVisible(two_sample_independent || two_sample_paired || one_sample); + ui.rb_h1_one_tail_1->setVisible(two_sample_independent || two_sample_paired || one_sample); + ui.rb_h1_two_tail->setVisible(two_sample_independent || two_sample_paired || one_sample); + ui.rb_h0_one_tail_1->setVisible(two_sample_independent || two_sample_paired || one_sample); + ui.rb_h0_one_tail_2->setVisible(two_sample_independent || two_sample_paired || one_sample); + ui.rb_h0_two_tail->setVisible(two_sample_independent || two_sample_paired || one_sample); + ui.l_h0->setVisible(two_sample_independent || two_sample_paired || one_sample); + ui.l_h1->setVisible(two_sample_independent || two_sample_paired || one_sample); + + ui.rb_h1_two_tail->setChecked(true); + ui.rb_h0_two_tail->setChecked(true); +} + +void HypothesisTestDock::doHypothesisTest() { QStringList cols; + if(ttest) { + if(two_sample_independent) { + cols << ui.cbCol1->currentText(); + cols << ui.cbCol2->currentText(); + m_hypothesisTest->setColumns(cols); + m_hypothesisTest->performTwoSampleIndependetTTest( ui.chbEqualVariance->isChecked()); + } + else if(two_sample_paired) { + cols << ui.cbCol1->currentText(); + cols << ui.cbCol2->currentText(); + m_hypothesisTest->setColumns(cols); + m_hypothesisTest->performTwoSamplePairedTTest(); + } + else if(one_sample){ + cols << ui.cbCol1->currentText(); + m_hypothesisTest->setColumns(cols); + m_hypothesisTest->PerformOneSampleTTest(); + } + } + else if(ztest) { + if(two_sample_independent) { + cols << ui.cbCol1->currentText(); + cols << ui.cbCol2->currentText(); + m_hypothesisTest->setColumns(cols); + m_hypothesisTest->performTwoSampleIndependetZTest(); + } + else if(two_sample_paired) { + cols << ui.cbCol1->currentText(); + cols << ui.cbCol2->currentText(); + m_hypothesisTest->setColumns(cols); + m_hypothesisTest->performTwoSamplePairedZTest(); + } + else if(one_sample){ + cols << ui.cbCol1->currentText(); + m_hypothesisTest->setColumns(cols); + m_hypothesisTest->PerformOneSampleZTest(); + } + } + + + + cols << ui.cbCol1->currentText(); cols << ui.cbCol2->currentText(); m_hypothesisTest->setColumns(cols); m_hypothesisTest->performTwoSampleTTest(); } //void HypothesisTestDock::setModelIndexFromAspect(TreeViewComboBox* cb, const AbstractAspect* aspect) { // if (aspect) // cb->setCurrentModelIndex(m_aspectTreeModel->modelIndexOfAspect(aspect)); // else // cb->setCurrentModelIndex(QModelIndex()); //} ///*! // shows the database manager where the connections are created and edited. // The selected connection is selected in the connection combo box in this widget. //**/ //void HypothesisTestDock::showDatabaseManager() { // DatabaseManagerDialog* dlg = new DatabaseManagerDialog(this, ui.cbConnection->currentText()); // if (dlg->exec() == QDialog::Accepted) { // //re-read the available connections to be in sync with the changes in DatabaseManager // m_initializing = true; // ui.cbConnection->clear(); // readConnections(); // //select the connection the user has selected in DatabaseManager // const QString& conn = dlg->connection(); // ui.cbConnection->setCurrentIndex(ui.cbConnection->findText(conn)); // m_initializing = false; // connectionChanged(); // } // delete dlg; //} ///*! // loads all available saved connections //*/ //void HypothesisTestDock::readConnections() { // DEBUG("ImportSQLDatabaseWidget: reading available connections"); // KConfig config(m_configPath, KConfig::SimpleConfig); // for (const auto& name : config.groupList()) // ui.cbConnection->addItem(name); //} ///*! // * adds the selected field to the rows // */ //void HypothesisTestDock::addRow() { // QString field = ui.lwFields->currentItem()->text(); // ui.lwRows->addItem(field); // ui.lwFields->takeItem(ui.lwFields->currentRow()); // m_hypothesisTest->addToRows(field); //} ///*! // * removes the selected field from the rows // */ //void HypothesisTestDock::removeRow() { // const QString& field = ui.lwRows->currentItem()->text(); // ui.lwRows->takeItem(ui.lwRows->currentRow()); // m_hypothesisTest->removeFromRows(field); // updateFields(); //} ///*! // * adds the selected field to the columns // */ //void HypothesisTestDock::addColumn() { // QString field = ui.lwFields->currentItem()->text(); // ui.lwColumns->addItem(field); // ui.lwFields->takeItem(ui.lwFields->currentRow()); // m_hypothesisTest->addToColumns(field); //} ///*! // * removes the selected field from the columns // */ //void HypothesisTestDock::removeColumn() { // const QString& field = ui.lwColumns->currentItem()->text(); // ui.lwColumns->takeItem(ui.lwColumns->currentRow()); // m_hypothesisTest->removeFromColumns(field); // updateFields(); //} ///*! // * re-populates the content of the "Fields" list widget by adding the non-selected fields only. // * called when a selected field is removed from rows or columns. // */ //void HypothesisTestDock::updateFields() { // ui.lwFields->clear(); // for (auto dimension : m_hypothesisTest->dimensions()) // if (!fieldSelected(dimension)) // ui.lwFields->addItem(new QListWidgetItem(QIcon::fromTheme("draw-text"), dimension)); // for (auto measure : m_hypothesisTest->measures()) // if (!fieldSelected(measure)) // ui.lwFields->addItem(new QListWidgetItem(measure)); //} ///*! // * return \c true if the field name \c field was selected among rows or columns, // * return \c false otherwise. // * */ //bool HypothesisTestDock::fieldSelected(const QString& field) { // for (int i = 0; icount(); ++i) // if (ui.lwRows->item(i)->text() == field) // return true; // for (int i = 0; icount(); ++i) // if (ui.lwColumns->item(i)->text() == field) // return true; // return false; //} ////************************************************************* ////****** SLOTs for changes triggered in HypothesisTestDock ******* ////************************************************************* //void HypothesisTestDock::nameChanged() { // if (m_initializing) // return; // m_hypothesisTest->setName(ui.leName->text()); //} //void HypothesisTestDock::commentChanged() { // if (m_initializing) // return; // m_hypothesisTest->setComment(ui.leComment->text()); //} void HypothesisTestDock::dataSourceTypeChanged(int index) { HypothesisTest::DataSourceType type = (HypothesisTest::DataSourceType)index; bool showDatabase = (type == HypothesisTest::DataSourceDatabase); ui.lSpreadsheet->setVisible(!showDatabase); cbSpreadsheet->setVisible(!showDatabase); ui.lConnection->setVisible(showDatabase); ui.cbConnection->setVisible(showDatabase); ui.bDatabaseManager->setVisible(showDatabase); ui.lTable->setVisible(showDatabase); ui.cbTable->setVisible(showDatabase); // if (m_initializing) // return; m_hypothesisTest->setComment(ui.leComment->text()); } void HypothesisTestDock::spreadsheetChanged(const QModelIndex& index) { auto* aspect = static_cast(index.internalPointer()); Spreadsheet* spreadsheet = dynamic_cast(aspect); //clear the previous definitions of combo-box columns ui.cbCol1->clear(); ui.cbCol2->clear(); //TODO: //rows, columns, values //show all spreadsheet columns as available dimensions for (const auto* col : spreadsheet->children()) { ui.cbCol1->addItem(col->name()); ui.cbCol2->addItem(col->name()); } m_hypothesisTest->setDataSourceSpreadsheet(spreadsheet); } //void HypothesisTestDock::connectionChanged() { // if (ui.cbConnection->currentIndex() == -1) { // ui.lTable->hide(); // ui.cbTable->hide(); // return; // } // //clear the previously shown tables // ui.cbTable->clear(); // ui.lTable->show(); // ui.cbTable->show(); // const QString& connection = ui.cbConnection->currentText(); // //connection name was changed, determine the current connections settings // KConfig config(m_configPath, KConfig::SimpleConfig); // KConfigGroup group = config.group(connection); // //close and remove the previos connection, if available // if (m_db.isOpen()) { // m_db.close(); // QSqlDatabase::removeDatabase(m_db.driverName()); // } // //open the selected connection // QDEBUG("HypothesisTestDock: connecting to " + connection); // const QString& driver = group.readEntry("Driver"); // m_db = QSqlDatabase::addDatabase(driver); // const QString& dbName = group.readEntry("DatabaseName"); // if (DatabaseManagerWidget::isFileDB(driver)) { // if (!QFile::exists(dbName)) { // KMessageBox::error(this, i18n("Couldn't find the database file '%1'. Please check the connection settings.", dbName), // i18n("Connection Failed")); // return; // } else // m_db.setDatabaseName(dbName); // } else if (DatabaseManagerWidget::isODBC(driver)) { // if (group.readEntry("CustomConnectionEnabled", false)) // m_db.setDatabaseName(group.readEntry("CustomConnectionString")); // else // m_db.setDatabaseName(dbName); // } else { // m_db.setDatabaseName(dbName); // m_db.setHostName( group.readEntry("HostName") ); // m_db.setPort( group.readEntry("Port", 0) ); // m_db.setUserName( group.readEntry("UserName") ); // m_db.setPassword( group.readEntry("Password") ); // } // WAIT_CURSOR; // if (!m_db.open()) { // RESET_CURSOR; // KMessageBox::error(this, i18n("Failed to connect to the database '%1'. Please check the connection settings.", ui.cbConnection->currentText()) + // QLatin1String("\n\n") + m_db.lastError().databaseText(), // i18n("Connection Failed")); // return; // } // //show all available database tables // if (m_db.tables().size()) { // for (auto table : m_db.tables()) // ui.cbTable->addItem(QIcon::fromTheme("view-form-table"), table); // ui.cbTable->setCurrentIndex(0); // } // RESET_CURSOR; // if (m_initializing) // return; //// m_hypothesisTest->setDataSourceConnection(connection); //} //void HypothesisTestDock::tableChanged() { // const QString& table = ui.cbTable->currentText(); // //show all attributes of the selected table //// for (const auto* col : spreadsheet->children()) { //// QListWidgetItem* item = new QListWidgetItem(col->icon(), col->name()); //// ui.lwFields->addItem(item); //// } // if (m_initializing) // return; //// m_hypothesisTest->setDataSourceTable(table); //} ////************************************************************* ////******** SLOTs for changes triggered in Matrix ********* ////************************************************************* //void HypothesisTestDock::hypothesisTestDescriptionChanged(const AbstractAspect* aspect) { // if (m_hypothesisTest != aspect) // return; // m_initializing = true; // if (aspect->name() != ui.leName->text()) // ui.leName->setText(aspect->name()); // else if (aspect->comment() != ui.leComment->text()) // ui.leComment->setText(aspect->comment()); // m_initializing = false; //} ////************************************************************* ////******************** SETTINGS ******************************* ////************************************************************* //void HypothesisTestDock::load() { //} //void HypothesisTestDock::loadConfigFromTemplate(KConfig& config) { // Q_UNUSED(config); //} ///*! // loads saved matrix properties from \c config. // */ //void HypothesisTestDock::loadConfig(KConfig& config) { // Q_UNUSED(config); //} ///*! // saves matrix properties to \c config. // */ //void HypothesisTestDock::saveConfigAsTemplate(KConfig& config) { // Q_UNUSED(config); //} + +void HypothesisTestDock::on_rb_h1_one_tail_1_clicked() { + ui.rb_h0_one_tail_1->setChecked(true); +} + +void HypothesisTestDock::on_rb_h1_one_tail_2_clicked() { + ui.rb_h0_one_tail_2->setChecked(true); +} + +void HypothesisTestDock::on_rb_h1_two_tail_clicked() { + ui.rb_h0_two_tail->setChecked(true); +} diff --git a/src/kdefrontend/dockwidgets/HypothesisTestDock.h b/src/kdefrontend/dockwidgets/HypothesisTestDock.h index 7f25699ac..cfde8ed6e 100644 --- a/src/kdefrontend/dockwidgets/HypothesisTestDock.h +++ b/src/kdefrontend/dockwidgets/HypothesisTestDock.h @@ -1,94 +1,106 @@ /*************************************************************************** File : HypothesisTestDock.h Project : LabPlot Description : widget for hypothesis testing properties -------------------------------------------------------------------- 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 HYPOTHESISTESTDOCK_H #define HYPOTHESISTESTDOCK_H #include "backend/hypothesis_test/HypothesisTest.h" #include "ui_hypothesistestdock.h" #include class AbstractAspect; class AspectTreeModel; class HypothesisTest; class TreeViewComboBox; class KConfig; class HypothesisTestDock : public QWidget { Q_OBJECT public: explicit HypothesisTestDock(QWidget*); void setHypothesisTest(HypothesisTest*); +private slots: + void on_rb_h1_one_tail_1_clicked(); + void on_rb_h1_one_tail_2_clicked(); + void on_rb_h1_two_tail_clicked(); + private slots: private: Ui::HypothesisTestDock ui; // bool m_initializing{false}; TreeViewComboBox* cbSpreadsheet{nullptr}; HypothesisTest* m_hypothesisTest{nullptr}; //// AspectTreeModel* m_aspectTreeModel{nullptr}; QSqlDatabase m_db; QString m_configPath; - + QWidget* wid; // void load(); // void loadConfig(KConfig&); // void setModelIndexFromAspect(TreeViewComboBox*, const AbstractAspect*); // 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}; + private slots: //SLOTs for changes triggered in PivotTableDock // void nameChanged(); // void commentChanged(); void dataSourceTypeChanged(int); - void doTTest(); + void doHypothesisTest(); + void showHypothesisTest(QTreeWidgetItem* item, int col); void spreadsheetChanged(const QModelIndex&); // void connectionChanged(); // void tableChanged(); // void showDatabaseManager(); // //SLOTs for changes triggered in PivotTable // void pivotTableDescriptionChanged(const AbstractAspect*); // void addRow(); // void removeRow(); // void addColumn(); // void removeColumn(); // //save/load template // void loadConfigFromTemplate(KConfig&); // void saveConfigAsTemplate(KConfig&); signals: // void info(const QString&); }; #endif // PIVOTTABLEDOCK_H diff --git a/src/kdefrontend/ui/dockwidgets/hypothesistestdock.ui b/src/kdefrontend/ui/dockwidgets/hypothesistestdock.ui index 0d1a98ac7..d0b17e058 100644 --- a/src/kdefrontend/ui/dockwidgets/hypothesistestdock.ui +++ b/src/kdefrontend/ui/dockwidgets/hypothesistestdock.ui @@ -1,295 +1,409 @@ HypothesisTestDock 0 0 588 996 Form - - - - + + + + 9 + 40 + 71 + 17 + + + + Comment: + + + + + + 9 + 90 + 34 + 17 + + + + + 75 + true + + + + Data + + + + + + 9 + 255 + 73 + 17 + + + + + 75 + true + + + + Structure: + + + + + + 9 + 9 + 44 + 17 + + + + + 0 + 0 + + + + Name: + + + + + + 490 + 620 + 77 + 23 + + + + Do Test + + + + + + 147 + 9 + 411 + 58 + + + + + + + + + + + + + + + 10 + 117 + 561 + 120 + + + + + - Tests + Source: - - + + + + + + + 0 + 0 + + + + + + + + Spreadsheet: + + + + + + + + 0 + 0 + + + + + + + + + - T Test + Connection: + + + + + + + + 0 + 0 + + + + + + + Table: + + + + + + + + + + + + 10 + 279 + 338 + 289 + + + + + + + + Tests + + - Independent Sample T-Test + Student's T Test + + + Two Sample Independent + + + + + Two Sample Paired + + + + + One Sample + + + + + Z Test + + + + Two Sample Independent + + + + + Two Sample Paired + + + + + One Sample + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + Independent Variable + + + Qt::AlignCenter + + + + + + + + + + + + + + + Independent Variable + + + + + Dependent Variable + + + + + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Equal Variance + + + + + + + + + 10 + 600 + 341 + 106 + + + + Qt::Horizontal + + + + + + + Alternate Hypothesis + + + + + + + mu > muo + + + + + + + mu < muo + + + + + + + mu != muo + + + + + + + + + + + Null Hypothesis + + + + + + + RadioButton + + + + + + + RadioButton + + + + + + + RadioButton + + - - - - - - - - - - 0 - 0 - - - - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 13 - - - - - - - - Source: - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 13 - 23 - - - - - - - - Table: - - - - - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - Comment: - - - - - - - Connection: - - - - - - - Spreadsheet: - - - - - - - - 75 - true - - - - Data - - - - - - - - 75 - true - - - - Structure: - - - - - - - - - - - 0 - 0 - - - - Name: - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - Column 1 - - - Qt::AlignCenter - - - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - true - - - Column 2 - - - Qt::AlignCenter - - - - - - - OK - - - - + + +