diff --git a/chart_direct_britton.cpp b/chart_direct_britton.cpp index bf8cef5..cc056e6 100644 --- a/chart_direct_britton.cpp +++ b/chart_direct_britton.cpp @@ -11,7 +11,7 @@ ChartDirectBritton::ChartDirectBritton(params_direct_britton_t *p, QWidget *pare /* populate noise arrays using seed */ std::default_random_engine generator(params->seed); - int length = (int)(params->d/params->h); + int length = ceil(params->d/params->h); params->cn_q1 = (double *)malloc(length * sizeof(*(params->cn_q1))); params->cn_q2 = (double *)malloc(length * sizeof(*(params->cn_q2))); @@ -68,9 +68,8 @@ ChartDirectBritton::ChartDirectBritton(params_direct_britton_t *p, QWidget *pare /* create chart */ QtCharts::QChart *chart = new QtCharts::QChart(); - //chart->legend()->hide(); chart->legend()->setVisible(true); - chart->setTitle("Simplified Direct Britton Model"); + //chart->setTitle("Simplified Direct Britton Model"); /* this will animate the series as it is displayed */ chart->setAnimationOptions(QtCharts::QChart::SeriesAnimations); @@ -80,11 +79,13 @@ ChartDirectBritton::ChartDirectBritton(params_direct_britton_t *p, QWidget *pare /* time axis */ QtCharts::QValueAxis *axisX = new QtCharts::QValueAxis; axisX->setTitleText("Time"); + axisX->setGridLineVisible(false); /* activation axis */ QtCharts::QValueAxis *axisY = new QtCharts::QValueAxis; axisY->setRange(-1.0,params->population); axisY->setTitleText("Population"); + axisY->setGridLineVisible(false); /* add axes to chart */ chart->addAxis(axisX, Qt::AlignBottom); @@ -104,19 +105,21 @@ ChartDirectBritton::ChartDirectBritton(params_direct_britton_t *p, QWidget *pare source_population->attachAxis(axisY); /* chart view goes on top */ - QtCharts::QChartView *chartView = new QtCharts::QChartView(chart); - chartView->setRenderHint(QPainter::Antialiasing); + chart_view = new QtCharts::QChartView(chart); + chart_view->setRenderHint(QPainter::Antialiasing); /* button box comes next */ button_box = new QGroupBox; QHBoxLayout *button_layout = new QHBoxLayout; + m_button_print = new QPushButton("print", this); m_button_close = new QPushButton("close", this); + button_layout->addWidget(m_button_print); button_layout->addWidget(m_button_close); button_box->setLayout(button_layout); /* assemble window: main layout */ QVBoxLayout *main_layout = new QVBoxLayout; - main_layout->addWidget(chartView); + main_layout->addWidget(chart_view); main_layout->addWidget(button_box); setLayout(main_layout); @@ -124,6 +127,7 @@ ChartDirectBritton::ChartDirectBritton(params_direct_britton_t *p, QWidget *pare show(); /* wire the signals */ + connect(m_button_print, SIGNAL (clicked()), this, SLOT(slot_print())); connect(m_button_close, SIGNAL (clicked()), this, SLOT(slot_close())); } @@ -141,3 +145,22 @@ void ChartDirectBritton::slot_close() { this->close(); } +void ChartDirectBritton::slot_print() { + /* create a printer */ + QPrinter *printer = new QPrinter(QPrinter::HighResolution); + //printer->setOrientation(QPrinter::Landscape); + QPrintDialog *dialog = new QPrintDialog(printer); + dialog->setWindowTitle("Print Chart"); + if (dialog->exec() != QDialog::Accepted) + return; + + /* make a painter to paint onto the pages of the printer */ + QPainter *painter = new QPainter(); + painter->begin(printer); + painter->setRenderHint(QPainter::Antialiasing); + chart_view->render(painter, printer->pageRect()); + painter->end(); + delete(dialog); + delete(painter); + delete(printer); +} diff --git a/chart_direct_britton.h b/chart_direct_britton.h index 06f940d..f1b0b5f 100644 --- a/chart_direct_britton.h +++ b/chart_direct_britton.h @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include #include @@ -28,8 +30,12 @@ class ChartDirectBritton : public QWidget double * results_y1; double * results_y2; + /* window component: the chart */ + QtCharts::QChartView *chart_view; + /* window component: button box */ QGroupBox *button_box; + QPushButton *m_button_print; QPushButton *m_button_close; signals: @@ -38,6 +44,7 @@ public slots: private slots: void slot_close(); + void slot_print(); }; #endif // CHART_DIRECT_BRITTON_H diff --git a/chart_gaze.cpp b/chart_gaze.cpp new file mode 100644 index 0000000..f19523b --- /dev/null +++ b/chart_gaze.cpp @@ -0,0 +1,185 @@ +#include "chart_gaze.h" + +/* for debugging */ +#include + +ChartGaze::ChartGaze(params_gaze_t *p, QWidget *parent) + : QWidget(parent), params(p) +{ + /* make the window sort of large */ + setFixedSize(1000,600); + + /* populate noise arrays using seed */ + // if we wanted a seed from time: unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); + std::default_random_engine generator(params->seed); + int length = ceil(params->d/params->h); + params->n_I1 = (double *)malloc(length * sizeof(*(params->n_I1))); + params->n_I2 = (double *)malloc(length * sizeof(*(params->n_I2))); + params->n_w1 = (double *)malloc(length * sizeof(*(params->n_w1))); + params->n_w2 = (double *)malloc(length * sizeof(*(params->n_w2))); + params->n_g1 = (double *)malloc(length * sizeof(*(params->n_g1))); + params->n_g2 = (double *)malloc(length * sizeof(*(params->n_g2))); + params->n_l1 = (double *)malloc(length * sizeof(*(params->n_l1))); + params->n_l2 = (double *)malloc(length * sizeof(*(params->n_l2))); + + gaze_set_noise(&generator, + 0.0, + params->n_std_dev, + length, + params->n_I1, + params->n_I2, + params->n_w1, + params->n_w2, + params->n_g1, + params->n_g2, + params->n_l1, + params->n_l2); + + /* get results of approximation */ + results_y1 = (double *)malloc(length * sizeof(*results_y1)); + results_y2 = (double *)malloc(length * sizeof(*results_y2)); + + // note: function call sets initial conditions + gaze_rk4(&generator, params, results_y1, results_y2); + + /* create series to chart */ + double t; + QtCharts::QLineSeries *series1 = new QtCharts::QLineSeries(); + QtCharts::QLineSeries *series2 = new QtCharts::QLineSeries(); + QtCharts::QLineSeries *series_diff = new QtCharts::QLineSeries(); + QtCharts::QLineSeries *series_gaze = new QtCharts::QLineSeries(); + t = 0.; + for(int i=0;iappend(t,results_y1[i]-results_y2[i]); + series1->append(t,results_y1[i]); + series2->append(t,results_y2[i]); + if(params->gaze_start >= params->gaze_end) { + series_gaze->append(t,-1.5); + } else if (t >= params->gaze_start && t <= params->gaze_end) { + series_gaze->append(t,-1.0); + } else series_gaze->append(t,-1.5); + t += params->h; + } + + /* set series options */ + series1->setName("y1 activation"); + series2->setName("y2 activation"); + series_diff->setName("y1-y2"); + series_gaze->setName("gaze active"); + + QPen diff_pen(QRgb(0xff9933)); + diff_pen.setWidth(2); + diff_pen.setStyle(Qt::DashLine); + series_diff->setPen(diff_pen); + + /* create main chart */ + QtCharts::QChart *chart = new QtCharts::QChart(); + chart->legend()->setVisible(true); + //chart->setTitle("Gaze Model"); + + /* this will animate the series as it is displayed */ + chart->setAnimationOptions(QtCharts::QChart::SeriesAnimations); + chart->setAnimationDuration(3000); // duration in milliseconds + + /* create axes */ + /* time axis */ + QtCharts::QValueAxis *axisX = new QtCharts::QValueAxis; + axisX->setTitleText("Time"); + axisX->setGridLineVisible(false); + + /* activation axis */ + QtCharts::QValueAxis *axisY = new QtCharts::QValueAxis; + axisY->setRange(-2.0,2.0); + axisY->setTitleText("Activation"); + axisY->setGridLineVisible(false); + + /* region axis */ + QtCharts::QCategoryAxis *axisY2 = new QtCharts::QCategoryAxis; + axisY2->append("t2", 2); + axisY2->append("t1", 4); + axisY2->setRange(0,4); + axisY2->setLinePenColor(series_diff->pen().color()); + //axisY3->setGridLinePen((series->pen())); + + /* add axes to chart */ + chart->addAxis(axisX, Qt::AlignBottom); + chart->addAxis(axisY, Qt::AlignLeft); + chart->addAxis(axisY2, Qt::AlignRight); + + /* add data */ + chart->addSeries(series1); + chart->addSeries(series2); + chart->addSeries(series_diff); + chart->addSeries(series_gaze); + + /* attach axes */ + series1->attachAxis(axisX); + series1->attachAxis(axisY); + series2->attachAxis(axisY); + series2->attachAxis(axisX); +// series_diff->attachAxis(axisY2); + series_diff->attachAxis(axisY); + series_diff->attachAxis(axisX); + series_gaze->attachAxis(axisX); + series_gaze->attachAxis(axisY); + + /* main chart view goes on top */ + chart_view = new QtCharts::QChartView(chart); + chart_view->setRenderHint(QPainter::Antialiasing); + + /* button box comes next */ + button_box = new QGroupBox; + QHBoxLayout *button_layout = new QHBoxLayout; + m_button_print = new QPushButton("print", this); + m_button_close = new QPushButton("close", this); + button_layout->addWidget(m_button_print); + button_layout->addWidget(m_button_close); + button_box->setLayout(button_layout); + + /* assemble window: main layout */ + QVBoxLayout *main_layout = new QVBoxLayout; + main_layout->addWidget(chart_view); + main_layout->addWidget(button_box); + + setLayout(main_layout); + setWindowTitle(tr("Gaze Model")); + show(); + + /* wire the signals */ + connect(m_button_close, SIGNAL (clicked()), this, SLOT(slot_close())); + connect(m_button_print, SIGNAL (clicked()), this, SLOT(slot_print())); +} + +void ChartGaze::slot_close() { + free(params->n_I1); + free(params->n_I2); + free(params->n_w1); + free(params->n_w2); + free(params->n_g1); + free(params->n_g2); + free(params->n_l1); + free(params->n_l2); + free(results_y1); + free(results_y2); + this->close(); +} + +void ChartGaze::slot_print() { + /* create a printer */ + QPrinter *printer = new QPrinter(QPrinter::HighResolution); + //printer->setOrientation(QPrinter::Landscape); + QPrintDialog *dialog = new QPrintDialog(printer); + dialog->setWindowTitle("Print Chart"); + if (dialog->exec() != QDialog::Accepted) + return; + + /* make a painter to paint onto the pages of the printer */ + QPainter *painter = new QPainter(); + painter->begin(printer); + painter->setRenderHint(QPainter::Antialiasing); + chart_view->render(painter, printer->pageRect()); + painter->end(); + delete(dialog); + delete(painter); + delete(printer); +} diff --git a/chart_gaze.h b/chart_gaze.h new file mode 100644 index 0000000..421af17 --- /dev/null +++ b/chart_gaze.h @@ -0,0 +1,52 @@ +#ifndef CHART_GAZE_H +#define CHART_GAZE_H + +#include +#include +#include +#include +#include +#include +#include +//#include +//#include +#include +#include +#include +#include +#include +#include +#include "models.h" + +class ChartGaze : public QWidget +{ + Q_OBJECT +public: + explicit ChartGaze(params_gaze_t *p, QWidget *parent = 0); + +private: + /* pointer to parameters */ + params_gaze_t *params; + + /* simulation results */ + double *results_y1; + double *results_y2; + + /* window component: the chart */ + QtCharts::QChartView *chart_view; + + /* window component: button_box */ + QGroupBox *button_box; + QPushButton *m_button_close; + QPushButton *m_button_print; + +signals: + +public slots: + +private slots: + void slot_close(); + void slot_print(); +}; + +#endif // CHART_GAZE_H diff --git a/chart_indirect_britton.cpp b/chart_indirect_britton.cpp index 33fac7f..87af73c 100644 --- a/chart_indirect_britton.cpp +++ b/chart_indirect_britton.cpp @@ -11,7 +11,7 @@ ChartIndirectBritton::ChartIndirectBritton(params_indirect_britton_t *p, QWidget /* populate noise arrays using seed */ std::default_random_engine generator(params->seed); - int length = (int)(params->d/params->h); + int length = ceil(params->d/params->h); params->cn_q1 = (double *)malloc(length * sizeof(*(params->cn_q1))); params->cn_q2 = (double *)malloc(length * sizeof(*(params->cn_q2))); @@ -64,9 +64,8 @@ ChartIndirectBritton::ChartIndirectBritton(params_indirect_britton_t *p, QWidget /* create chart */ QtCharts::QChart *chart = new QtCharts::QChart(); - //chart->legend()->hide(); chart->legend()->setVisible(true); - chart->setTitle("Simplified Indirect Britton Model"); + //chart->setTitle("Simplified Indirect Britton Model"); /* this will animate the series as it is displayed */ chart->setAnimationOptions(QtCharts::QChart::SeriesAnimations); @@ -76,11 +75,13 @@ ChartIndirectBritton::ChartIndirectBritton(params_indirect_britton_t *p, QWidget /* time axis */ QtCharts::QValueAxis *axisX = new QtCharts::QValueAxis; axisX->setTitleText("Time"); + axisX->setGridLineVisible(false); /* activation axis */ QtCharts::QValueAxis *axisY = new QtCharts::QValueAxis; axisY->setRange(-1.0,params->population); axisY->setTitleText("Population"); + axisY->setGridLineVisible(false); /* add axes to chart */ chart->addAxis(axisX, Qt::AlignBottom); @@ -100,19 +101,21 @@ ChartIndirectBritton::ChartIndirectBritton(params_indirect_britton_t *p, QWidget source_population->attachAxis(axisY); /* chart view goes on top */ - QtCharts::QChartView *chartView = new QtCharts::QChartView(chart); - chartView->setRenderHint(QPainter::Antialiasing); + chart_view = new QtCharts::QChartView(chart); + chart_view->setRenderHint(QPainter::Antialiasing); /* button box comes next */ button_box = new QGroupBox; QHBoxLayout *button_layout = new QHBoxLayout; + m_button_print = new QPushButton("print", this); m_button_close = new QPushButton("close", this); + button_layout->addWidget(m_button_print); button_layout->addWidget(m_button_close); button_box->setLayout(button_layout); /* assemble window: main layout */ QVBoxLayout *main_layout = new QVBoxLayout; - main_layout->addWidget(chartView); + main_layout->addWidget(chart_view); main_layout->addWidget(button_box); setLayout(main_layout); @@ -120,6 +123,7 @@ ChartIndirectBritton::ChartIndirectBritton(params_indirect_britton_t *p, QWidget show(); /* wire the signals */ + connect(m_button_print, SIGNAL (clicked()), this, SLOT(slot_print())); connect(m_button_close, SIGNAL (clicked()), this, SLOT(slot_close())); } @@ -135,3 +139,22 @@ void ChartIndirectBritton::slot_close() { this->close(); } +void ChartIndirectBritton::slot_print() { + /* create a printer */ + QPrinter *printer = new QPrinter(QPrinter::HighResolution); + //printer->setOrientation(QPrinter::Landscape); + QPrintDialog *dialog = new QPrintDialog(printer); + dialog->setWindowTitle("Print Chart"); + if (dialog->exec() != QDialog::Accepted) + return; + + /* make a painter to paint onto the pages of the printer */ + QPainter *painter = new QPainter(); + painter->begin(printer); + painter->setRenderHint(QPainter::Antialiasing); + chart_view->render(painter, printer->pageRect()); + painter->end(); + delete(dialog); + delete(painter); + delete(printer); +} diff --git a/chart_indirect_britton.h b/chart_indirect_britton.h index d863557..34622f9 100644 --- a/chart_indirect_britton.h +++ b/chart_indirect_britton.h @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include #include @@ -28,8 +30,12 @@ class ChartIndirectBritton : public QWidget double * results_y1; double * results_y2; + /* window component: the chart */ + QtCharts::QChartView *chart_view; + /* window component: button box */ QGroupBox *button_box; + QPushButton *m_button_print; QPushButton *m_button_close; signals: @@ -38,6 +44,7 @@ public slots: private slots: void slot_close(); + void slot_print(); }; #endif // CHART_INDIRECT_BRITTON_H diff --git a/chart_pratt.cpp b/chart_pratt.cpp index 1bea1bb..6e0579a 100644 --- a/chart_pratt.cpp +++ b/chart_pratt.cpp @@ -11,7 +11,7 @@ ChartPratt::ChartPratt(params_pratt_t *p, QWidget *parent) /* populate noise arrays using seed */ std::default_random_engine generator(params->seed); - int length = (int)(params->d/params->h); + int length = ceil(params->d/params->h); params->cn_q1 = (double *)malloc(length * sizeof(*(params->cn_q1))); params->cn_q2 = (double *)malloc(length * sizeof(*(params->cn_q2))); @@ -68,9 +68,8 @@ ChartPratt::ChartPratt(params_pratt_t *p, QWidget *parent) /* create chart */ QtCharts::QChart *chart = new QtCharts::QChart(); - //chart->legend()->hide(); chart->legend()->setVisible(true); - chart->setTitle("Simplified Pratt (Direct Transfer) Model"); + //chart->setTitle("Simplified Pratt (Direct Transfer) Model"); /* this will animate the series as it is displayed */ chart->setAnimationOptions(QtCharts::QChart::SeriesAnimations); @@ -80,11 +79,13 @@ ChartPratt::ChartPratt(params_pratt_t *p, QWidget *parent) /* time axis */ QtCharts::QValueAxis *axisX = new QtCharts::QValueAxis; axisX->setTitleText("Time"); + axisX->setGridLineVisible(false); /* activation axis */ QtCharts::QValueAxis *axisY = new QtCharts::QValueAxis; axisY->setRange(-1.0,params->population); axisY->setTitleText("Population"); + axisY->setGridLineVisible(false); /* add axes to chart */ chart->addAxis(axisX, Qt::AlignBottom); @@ -104,19 +105,21 @@ ChartPratt::ChartPratt(params_pratt_t *p, QWidget *parent) source_population->attachAxis(axisY); /* chart view goes on top */ - QtCharts::QChartView *chartView = new QtCharts::QChartView(chart); - chartView->setRenderHint(QPainter::Antialiasing); + chart_view = new QtCharts::QChartView(chart); + chart_view->setRenderHint(QPainter::Antialiasing); /* button box comes next */ button_box = new QGroupBox; QHBoxLayout *button_layout = new QHBoxLayout; + m_button_print = new QPushButton("print", this); m_button_close = new QPushButton("close", this); + button_layout->addWidget(m_button_print); button_layout->addWidget(m_button_close); button_box->setLayout(button_layout); /* assemble window: main layout */ QVBoxLayout *main_layout = new QVBoxLayout; - main_layout->addWidget(chartView); + main_layout->addWidget(chart_view); main_layout->addWidget(button_box); setLayout(main_layout); @@ -124,6 +127,7 @@ ChartPratt::ChartPratt(params_pratt_t *p, QWidget *parent) show(); /* wire the signals */ + connect(m_button_print, SIGNAL (clicked()), this, SLOT(slot_print())); connect(m_button_close, SIGNAL (clicked()), this, SLOT(slot_close())); } @@ -141,3 +145,22 @@ void ChartPratt::slot_close() { this->close(); } +void ChartPratt::slot_print() { + /* create a printer */ + QPrinter *printer = new QPrinter(QPrinter::HighResolution); + //printer->setOrientation(QPrinter::Landscape); + QPrintDialog *dialog = new QPrintDialog(printer); + dialog->setWindowTitle("Print Chart"); + if (dialog->exec() != QDialog::Accepted) + return; + + /* make a painter to paint onto the pages of the printer */ + QPainter *painter = new QPainter(); + painter->begin(printer); + painter->setRenderHint(QPainter::Antialiasing); + chart_view->render(painter, printer->pageRect()); + painter->end(); + delete(dialog); + delete(painter); + delete(printer); +} diff --git a/chart_pratt.h b/chart_pratt.h index d932242..7de7ad8 100644 --- a/chart_pratt.h +++ b/chart_pratt.h @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include #include @@ -28,8 +30,12 @@ class ChartPratt : public QWidget double * results_y1; double * results_y2; + /* window component: the chart */ + QtCharts::QChartView *chart_view; + /* window component: button box */ QGroupBox *button_box; + QPushButton *m_button_print; QPushButton *m_button_close; signals: @@ -38,6 +44,7 @@ public slots: private slots: void slot_close(); + void slot_print(); }; #endif // CHART_PRATT_H diff --git a/chart_um.cpp b/chart_um.cpp index f0db2b5..b67fb98 100644 --- a/chart_um.cpp +++ b/chart_um.cpp @@ -12,7 +12,7 @@ ChartUM::ChartUM(params_um_t *p, QWidget *parent) /* populate noise arrays using seed */ // if we wanted a seed from time: unsigned seed = std::chrono::system_clock::now().time_since_epoch().count(); std::default_random_engine generator(params->seed); - int length = (int)(params->d/params->h); + int length = ceil(params->d/params->h); params->cn1 = (double *)malloc(length * sizeof(*(params->cn1))); params->cn2 = (double *)malloc(length * sizeof(*(params->cn2))); um_set_noise(&generator, 0.0, params->std_dev, length, params->cn1, params->cn2); @@ -21,8 +21,9 @@ ChartUM::ChartUM(params_um_t *p, QWidget *parent) results_y1 = (double *)malloc(length * sizeof(*results_y1)); results_y2 = (double *)malloc(length * sizeof(*results_y2)); - // note: function call will set initial conditions + /* note: function call sets initial conditions */ usher_mcclelland_rk4(params, results_y1, results_y2); + //usher_mcclelland_eulers(params, results_y1, results_y2); /* create series to chart */ double t; @@ -38,9 +39,9 @@ ChartUM::ChartUM(params_um_t *p, QWidget *parent) } /* set series options */ - series1->setName("Option A"); - series2->setName("Option B"); - series_diff->setName("A-B"); + series1->setName("y1 activation"); + series2->setName("y2 activation"); + series_diff->setName("y1-y2"); QPen diff_pen(QRgb(0xff9933)); diff_pen.setWidth(2); @@ -49,9 +50,8 @@ ChartUM::ChartUM(params_um_t *p, QWidget *parent) /* create chart */ QtCharts::QChart *chart = new QtCharts::QChart(); - //chart->legend()->hide(); chart->legend()->setVisible(true); - chart->setTitle("Usher-McClelland Model"); + //chart->setTitle("Usher-McClelland Model"); /* this will animate the series as it is displayed */ chart->setAnimationOptions(QtCharts::QChart::SeriesAnimations); @@ -61,16 +61,18 @@ ChartUM::ChartUM(params_um_t *p, QWidget *parent) /* time axis */ QtCharts::QValueAxis *axisX = new QtCharts::QValueAxis; axisX->setTitleText("Time"); + axisX->setGridLineVisible(false); /* activation axis */ QtCharts::QValueAxis *axisY = new QtCharts::QValueAxis; axisY->setRange(-1.0,1.0); axisY->setTitleText("Activation"); + axisY->setGridLineVisible(false); /* region axis */ QtCharts::QCategoryAxis *axisY2 = new QtCharts::QCategoryAxis; - axisY2->append("Option B Wins", 2); - axisY2->append("Option A Wins", 4); + axisY2->append("y2", 2); + axisY2->append("y1", 4); axisY2->setRange(0,4); axisY2->setLinePenColor(series_diff->pen().color()); //axisY3->setGridLinePen((series->pen())); @@ -94,15 +96,16 @@ ChartUM::ChartUM(params_um_t *p, QWidget *parent) series_diff->attachAxis(axisY); series_diff->attachAxis(axisX); - /* chart view goes on top */ - QtCharts::QChartView *chart_view = new QtCharts::QChartView(chart); + chart_view = new QtCharts::QChartView(chart); chart_view->setRenderHint(QPainter::Antialiasing); /* button box comes next */ button_box = new QGroupBox; QHBoxLayout *button_layout = new QHBoxLayout; m_button_close = new QPushButton("close", this); + m_button_print = new QPushButton("print", this); + button_layout->addWidget(m_button_print); button_layout->addWidget(m_button_close); button_box->setLayout(button_layout); @@ -116,6 +119,7 @@ ChartUM::ChartUM(params_um_t *p, QWidget *parent) show(); /* wire the signals */ + connect(m_button_print, SIGNAL (clicked()), this, SLOT(slot_print())); connect(m_button_close, SIGNAL (clicked()), this, SLOT(slot_close())); } @@ -127,3 +131,22 @@ void ChartUM::slot_close() { this->close(); } +void ChartUM::slot_print() { + /* create a printer */ + QPrinter *printer = new QPrinter(QPrinter::HighResolution); + //printer->setOrientation(QPrinter::Landscape); + QPrintDialog *dialog = new QPrintDialog(printer); + dialog->setWindowTitle("Print Chart"); + if (dialog->exec() != QDialog::Accepted) + return; + + /* make a painter to paint onto the pages of the printer */ + QPainter *painter = new QPainter(); + painter->begin(printer); + painter->setRenderHint(QPainter::Antialiasing); + chart_view->render(painter, printer->pageRect()); + painter->end(); + delete(dialog); + delete(painter); + delete(printer); +} diff --git a/chart_um.h b/chart_um.h index abdf903..7b89be7 100644 --- a/chart_um.h +++ b/chart_um.h @@ -8,6 +8,8 @@ #include #include #include +#include +#include #include #include #include @@ -25,12 +27,16 @@ class ChartUM : public QWidget params_um_t *params; /* simulation results */ - double * results_y1; - double * results_y2; + double *results_y1; + double *results_y2; + + /* window component: the chart */ + QtCharts::QChartView *chart_view; /* window component: button_box */ QGroupBox *button_box; - QPushButton * m_button_close; + QPushButton *m_button_close; + QPushButton *m_button_print; signals: @@ -38,6 +44,7 @@ public slots: private slots: void slot_close(); + void slot_print(); }; #endif // CHART_UM_H diff --git a/insect_decision.pdf b/insect_decision.pdf deleted file mode 100644 index db4e41f..0000000 Binary files a/insect_decision.pdf and /dev/null differ diff --git a/insect_decision.pro b/insect_decision.pro index 53d2a58..d000d81 100644 --- a/insect_decision.pro +++ b/insect_decision.pro @@ -1,8 +1,9 @@ TEMPLATE = app -TARGET = usher_mclelland +TARGET = insect_decision QT = core gui QT += charts +QT += printsupport greaterThan(QT_MAJOR_VERSION, 4): QT += widgets @@ -13,7 +14,8 @@ SOURCES += \ chart_um.cpp \ chart_pratt.cpp \ chart_indirect_britton.cpp \ - chart_direct_britton.cpp + chart_direct_britton.cpp \ + chart_gaze.cpp HEADERS += \ mainwindow.h \ @@ -21,4 +23,5 @@ HEADERS += \ chart_um.h \ chart_pratt.h \ chart_indirect_britton.h \ - chart_direct_britton.h + chart_direct_britton.h \ + chart_gaze.h diff --git a/mainwindow.cpp b/mainwindow.cpp index 21fbf6e..3536a18 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -2,6 +2,7 @@ #include "chart_pratt.h" #include "chart_indirect_britton.h" #include "chart_direct_britton.h" +#include "chart_gaze.h" #include "mainwindow.h" #include "models.h" @@ -16,6 +17,7 @@ MainWindow::MainWindow(QWidget *parent) pratt_set_defaults(¶ms_pratt); indirect_britton_set_defaults(¶ms_indirect_britton); direct_britton_set_defaults(¶ms_direct_britton); + gaze_set_defaults(¶ms_gaze); /* set default window size */ setFixedWidth(700); @@ -37,7 +39,7 @@ MainWindow::MainWindow(QWidget *parent) /* stick the layout in this widget (i.e., this window) and make it appear */ setLayout(main_layout); - setWindowTitle(tr("Insert something catchy")); + setWindowTitle(tr("Dynamical Binary Decision Models")); show(); } @@ -67,12 +69,15 @@ void MainWindow::create_combo_menu_box() action_indirect_britton->setText("Simplified indirect Britton model"); action_direct_britton = new QAction(this); action_direct_britton->setText("Simplified direct Britton model"); + action_gaze = new QAction(this); + action_gaze->setText("Gaze model"); combo_menu = new QComboBox(this); combo_menu->addItem(action_um->text(), QVariant::fromValue(action_um)); combo_menu->addItem(action_pratt->text(), QVariant::fromValue(action_pratt)); combo_menu->addItem(action_indirect_britton->text(), QVariant::fromValue(action_indirect_britton)); combo_menu->addItem(action_direct_britton->text(), QVariant::fromValue(action_direct_britton)); + combo_menu->addItem(action_gaze->text(), QVariant::fromValue(action_gaze)); layout->addWidget(combo_menu); combo_menu_box->setLayout(layout); @@ -108,13 +113,21 @@ void MainWindow::create_model_box() create_model_box_pratt(); create_model_box_indirect_britton(); create_model_box_direct_britton(); + create_model_box_gaze(); model_box->addWidget(model_box_um); model_box->addWidget(model_box_pratt); model_box->addWidget(model_box_indirect_britton); model_box->addWidget(model_box_direct_britton); + model_box->addWidget(model_box_gaze); } +/************************************************************** + * + * Usher-McClelland Model GUI Box + * + **************************************************************/ + void MainWindow::create_model_box_um() { model_box_um = new QGroupBox(tr("U-M model parameters:")); @@ -267,7 +280,9 @@ void MainWindow::slot_um_std_dev_changed(double v) { } /************************************************************** + * * Simplified Pratt Model GUI Box + * **************************************************************/ void MainWindow::create_model_box_pratt() { @@ -527,42 +542,42 @@ void MainWindow::create_model_box_indirect_britton() sb_population->setValue(params_indirect_britton.population); QDoubleSpinBox * sb_y1_0 = new QDoubleSpinBox(); - sb_y1_0->setSingleStep(1.0); - sb_y1_0->setDecimals(1); + sb_y1_0->setSingleStep(0.01); + sb_y1_0->setDecimals(3); sb_y1_0->setValue(params_indirect_britton.y1_0); QDoubleSpinBox * sb_y2_0 = new QDoubleSpinBox(); - sb_y2_0->setSingleStep(1.0); - sb_y2_0->setDecimals(1); + sb_y2_0->setSingleStep(0.01); + sb_y2_0->setDecimals(3); sb_y2_0->setValue(params_indirect_britton.y2_0); QDoubleSpinBox * sb_q1 = new QDoubleSpinBox(); - sb_q1->setSingleStep(0.1); + sb_q1->setSingleStep(0.01); sb_q1->setDecimals(3); sb_q1->setValue(params_indirect_britton.q1); QDoubleSpinBox * sb_q2 = new QDoubleSpinBox(); - sb_q2->setSingleStep(0.1); + sb_q2->setSingleStep(0.01); sb_q2->setDecimals(3); sb_q2->setValue(params_indirect_britton.q2); QDoubleSpinBox * sb_l1 = new QDoubleSpinBox(); - sb_l1->setSingleStep(0.1); + sb_l1->setSingleStep(0.01); sb_l1->setDecimals(3); sb_l1->setValue(params_indirect_britton.l1); QDoubleSpinBox * sb_l2 = new QDoubleSpinBox(); - sb_l2->setSingleStep(0.1); + sb_l2->setSingleStep(0.01); sb_l2->setDecimals(3); sb_l2->setValue(params_indirect_britton.l2); QDoubleSpinBox * sb_r1_prime = new QDoubleSpinBox(); - sb_r1_prime->setSingleStep(0.1); + sb_r1_prime->setSingleStep(0.01); sb_r1_prime->setDecimals(3); sb_r1_prime->setValue(params_indirect_britton.r1_prime); QDoubleSpinBox * sb_r2_prime = new QDoubleSpinBox(); - sb_r2_prime->setSingleStep(0.1); + sb_r2_prime->setSingleStep(0.01); sb_r2_prime->setDecimals(3); sb_r2_prime->setValue(params_indirect_britton.r2_prime); @@ -572,7 +587,7 @@ void MainWindow::create_model_box_indirect_britton() sb_seed->setValue(params_indirect_britton.seed); QDoubleSpinBox * sb_std_dev = new QDoubleSpinBox(); - sb_std_dev->setSingleStep(0.1); + sb_std_dev->setSingleStep(0.01); sb_std_dev->setDecimals(3); sb_std_dev->setRange(0,999.00); sb_std_dev->setValue(params_indirect_britton.std_dev); @@ -724,10 +739,12 @@ void MainWindow::create_model_box_direct_britton() QDoubleSpinBox * sb_y1_0 = new QDoubleSpinBox(); sb_y1_0->setSingleStep(0.01); + sb_y1_0->setDecimals(3); sb_y1_0->setValue(params_direct_britton.y1_0); QDoubleSpinBox * sb_y2_0 = new QDoubleSpinBox(); sb_y2_0->setSingleStep(0.01); + sb_y2_0->setDecimals(3); sb_y2_0->setValue(params_direct_britton.y2_0); QDoubleSpinBox * sb_q1 = new QDoubleSpinBox(); @@ -894,6 +911,296 @@ void MainWindow::slot_sdb_std_dev_changed(double v) { params_direct_britton.std_dev = v; } +/************************************************************** + * + * Gaze Model GUI Box + * + **************************************************************/ +void MainWindow::create_model_box_gaze() +{ + model_box_gaze = new QGroupBox(tr("Gaze model parameters:")); + QGridLayout *layout = new QGridLayout; + + QLabel *label_h = new QLabel("Step size:"); + QLabel *label_d = new QLabel("Duration:"); + QLabel *label_y1_0 = new QLabel("y1 initial size:"); + QLabel *label_y2_0 = new QLabel("y2 initial size:"); + QLabel *label_I1 = new QLabel("y1 input:"); + QLabel *label_I2 = new QLabel("y2 input:"); + QLabel *label_g = new QLabel("gaze input:"); + QLabel *label_gaze_start = new QLabel("gaze start:"); + QLabel *label_gaze_end = new QLabel("gaze end:"); + QLabel *label_a = new QLabel("y-intercept:"); + QLabel *label_l1 = new QLabel("y1 leak rate:"); + QLabel *label_l2 = new QLabel("y2 leak rate:"); + QLabel *label_w1 = new QLabel("y1->y2 weight:"); + QLabel *label_w2 = new QLabel("y2->y1 weight:"); + QLabel *label_t1 = new QLabel("target 1 location:"); + QLabel *label_t2 = new QLabel("target 2 location:"); + QLabel *label_tg = new QLabel("gaze location:"); + QLabel *label_seed = new QLabel("Noise seed:"); + QLabel *label_n_std_dev = new QLabel("Noise std deviation:"); + QLabel *label_g_std_dev = new QLabel("Gaze std deviation"); + + /* spinboxes */ + QDoubleSpinBox * sb_h = new QDoubleSpinBox(); + sb_h->setSingleStep(0.01); + sb_h->setDecimals(3); + sb_h->setValue(params_gaze.h); + + QSpinBox * sb_d = new QSpinBox(); + sb_d->setSingleStep(1); + sb_d->setRange(0,999); + sb_d->setValue(params_gaze.d); + + QDoubleSpinBox * sb_y1_0 = new QDoubleSpinBox(); + sb_y1_0->setSingleStep(0.01); + sb_y1_0->setDecimals(3); + sb_y1_0->setValue(params_gaze.y1_0); + + QDoubleSpinBox * sb_y2_0 = new QDoubleSpinBox(); + sb_y2_0->setSingleStep(0.01); + sb_y2_0->setDecimals(3); + sb_y2_0->setValue(params_gaze.y2_0); + + QDoubleSpinBox * sb_I1 = new QDoubleSpinBox(); + sb_I1->setSingleStep(0.01); + sb_I1->setDecimals(3); + sb_I1->setValue(params_gaze.I1); + + QDoubleSpinBox * sb_I2 = new QDoubleSpinBox(); + sb_I2->setSingleStep(0.01); + sb_I2->setDecimals(3); + sb_I2->setValue(params_gaze.I2); + + QDoubleSpinBox * sb_g = new QDoubleSpinBox(); + sb_g->setSingleStep(0.01); + sb_g->setDecimals(3); + sb_g->setValue(params_gaze.g); + + /* bounds testing is currently taken care of during graphing */ + QDoubleSpinBox * sb_gaze_start = new QDoubleSpinBox(); + sb_gaze_start->setSingleStep(0.01); + sb_gaze_start->setDecimals(3); + sb_gaze_start->setRange(0.0,params_gaze.d); + sb_gaze_start->setValue(params_gaze.gaze_start); + + QDoubleSpinBox * sb_gaze_end = new QDoubleSpinBox(); + sb_gaze_end->setSingleStep(0.01); + sb_gaze_end->setDecimals(3); + sb_gaze_end->setRange(0.0, params_gaze.d); + sb_gaze_end->setValue(params_gaze.gaze_end); + + QDoubleSpinBox * sb_a = new QDoubleSpinBox(); + sb_a->setSingleStep(0.01); + sb_a->setDecimals(3); + sb_a->setValue(params_gaze.a); + + QDoubleSpinBox * sb_l1 = new QDoubleSpinBox(); + sb_l1->setSingleStep(0.01); + sb_l1->setDecimals(3); + sb_l1->setValue(params_gaze.l1); + + QDoubleSpinBox * sb_l2 = new QDoubleSpinBox(); + sb_l2->setSingleStep(0.01); + sb_l2->setDecimals(3); + sb_l2->setValue(params_gaze.l2); + + QDoubleSpinBox * sb_w1 = new QDoubleSpinBox(); + sb_w1->setSingleStep(0.01); + sb_w1->setDecimals(3); + sb_w1->setValue(params_gaze.w1); + + QDoubleSpinBox * sb_w2 = new QDoubleSpinBox(); + sb_w2->setSingleStep(0.01); + sb_w2->setDecimals(3); + sb_w2->setValue(params_gaze.w2); + + QDoubleSpinBox * sb_t1 = new QDoubleSpinBox(); + sb_t1->setSingleStep(1.0); + sb_t1->setDecimals(3); + sb_t1->setRange(0.0,90.0); + sb_t1->setValue(params_gaze.t1); + + QDoubleSpinBox * sb_t2 = new QDoubleSpinBox(); + sb_t2->setSingleStep(1.0); + sb_t2->setDecimals(3); + sb_t2->setRange(90.0,180.0); + sb_t2->setValue(params_gaze.t2); + + QDoubleSpinBox * sb_tg = new QDoubleSpinBox(); + sb_tg->setSingleStep(1.0); + sb_tg->setDecimals(3); + sb_tg->setRange(0.0,180.0); + sb_tg->setValue(params_gaze.tg); + + QSpinBox * sb_seed = new QSpinBox(); + sb_seed->setSingleStep(1); + sb_seed->setRange(0,10000); + sb_seed->setValue(params_gaze.seed); + + QDoubleSpinBox * sb_n_std_dev = new QDoubleSpinBox(); + sb_n_std_dev->setSingleStep(0.01); + sb_n_std_dev->setDecimals(3); + sb_n_std_dev->setRange(0,999.00); + sb_n_std_dev->setValue(params_gaze.n_std_dev); + + QDoubleSpinBox * sb_g_std_dev = new QDoubleSpinBox(); + sb_g_std_dev->setSingleStep(0.01); + sb_g_std_dev->setDecimals(3); + sb_g_std_dev->setRange(0,999.00); + sb_g_std_dev->setValue(params_gaze.g_std_dev); + + /* put the labels and spinboxes in the rows, cols */ + /* cols 1 & 2 */ + layout->addWidget(label_h, 0, 0); + layout->addWidget(sb_h, 0, 1); + layout->addWidget(label_d, 1, 0); + layout->addWidget(sb_d, 1, 1); + layout->addWidget(label_y1_0, 2, 0); + layout->addWidget(sb_y1_0, 2, 1); + layout->addWidget(label_y2_0, 3, 0); + layout->addWidget(sb_y2_0, 3, 1); + layout->addWidget(label_I1, 4, 0); + layout->addWidget(sb_I1, 4, 1); + layout->addWidget(label_I2, 5, 0); + layout->addWidget(sb_I2, 5, 1); + layout->addWidget(label_g, 6, 0); + layout->addWidget(sb_g, 6, 1); + layout->addWidget(label_gaze_start, 7, 0); + layout->addWidget(sb_gaze_start, 7, 1); + layout->addWidget(label_gaze_end, 8, 0); + layout->addWidget(sb_gaze_end, 8, 1); + layout->addWidget(label_a, 9, 0); + layout->addWidget(sb_a, 9, 1); + /* cols 3 & 4 */ + layout->addWidget(label_l1, 0, 2); + layout->addWidget(sb_l1, 0, 3); + layout->addWidget(label_l2, 1, 2); + layout->addWidget(sb_l2, 1, 3); + layout->addWidget(label_w1, 2, 2); + layout->addWidget(sb_w1, 2, 3); + layout->addWidget(label_w2, 3, 2); + layout->addWidget(sb_w2, 3, 3); + layout->addWidget(label_t1, 4, 2); + layout->addWidget(sb_t1, 4, 3); + layout->addWidget(label_t2, 5, 2); + layout->addWidget(sb_t2, 5, 3); + layout->addWidget(label_tg, 6, 2); + layout->addWidget(sb_tg, 6, 3); + layout->addWidget(label_seed, 7, 2); + layout->addWidget(sb_seed, 7, 3); + layout->addWidget(label_n_std_dev, 8, 2); + layout->addWidget(sb_n_std_dev, 8, 3); + layout->addWidget(label_g_std_dev, 9, 2); + layout->addWidget(sb_g_std_dev, 9, 3); + + layout->setColumnStretch(1, 10); + layout->setColumnStretch(3, 20); + model_box_gaze->setLayout(layout); + + connect(sb_h, SIGNAL(valueChanged(double)), this, SLOT(slot_g_h_changed(double))); + connect(sb_d, SIGNAL(valueChanged(int)), this, SLOT(slot_g_d_changed(int))); + connect(sb_y1_0, SIGNAL(valueChanged(double)), this, SLOT(slot_g_y1_0_changed(double))); + connect(sb_y2_0, SIGNAL(valueChanged(double)), this, SLOT(slot_g_y2_0_changed(double))); + connect(sb_I1, SIGNAL(valueChanged(double)), this, SLOT(slot_g_I1_changed(double))); + connect(sb_I2, SIGNAL(valueChanged(double)), this, SLOT(slot_g_I2_changed(double))); + connect(sb_g, SIGNAL(valueChanged(double)), this, SLOT(slot_g_g_changed(double))); + connect(sb_gaze_start, SIGNAL(valueChanged(double)), this, SLOT(slot_g_gaze_start_changed(double))); + connect(sb_gaze_end, SIGNAL(valueChanged(double)), this, SLOT(slot_g_gaze_end_changed(double))); + connect(sb_a, SIGNAL(valueChanged(double)), this, SLOT(slot_g_a_changed(double))); + connect(sb_l1, SIGNAL(valueChanged(double)), this, SLOT(slot_g_l1_changed(double))); + connect(sb_l2, SIGNAL(valueChanged(double)), this, SLOT(slot_g_l2_changed(double))); + connect(sb_w1, SIGNAL(valueChanged(double)), this, SLOT(slot_g_w1_changed(double))); + connect(sb_w2, SIGNAL(valueChanged(double)), this, SLOT(slot_g_w2_changed(double))); + connect(sb_t1, SIGNAL(valueChanged(double)), this, SLOT(slot_g_t1_changed(double))); + connect(sb_t2, SIGNAL(valueChanged(double)), this, SLOT(slot_g_t2_changed(double))); + connect(sb_tg, SIGNAL(valueChanged(double)), this, SLOT(slot_g_tg_changed(double))); + connect(sb_seed, SIGNAL(valueChanged(int)), this, SLOT(slot_g_seed_changed(int))); + connect(sb_n_std_dev, SIGNAL(valueChanged(double)), this, SLOT(slot_g_n_std_dev_changed(double))); + connect(sb_g_std_dev, SIGNAL(valueChanged(double)), this, SLOT(slot_g_g_std_dev_changed(double))); +} + +void MainWindow::slot_g_h_changed(double v) { + params_gaze.h = v; +} + +void MainWindow::slot_g_d_changed(int v) { + params_gaze.d = v; +} + +void MainWindow::slot_g_y1_0_changed(double v) { + params_gaze.y1_0 = v; +} + +void MainWindow::slot_g_y2_0_changed(double v) { + params_gaze.y2_0 = v; +} + +void MainWindow::slot_g_I1_changed(double v) { + params_gaze.I1 = v; +} + +void MainWindow::slot_g_I2_changed(double v) { + params_gaze.I2 = v; +} + +void MainWindow::slot_g_g_changed(double v) { + params_gaze.g = v; +} + +void MainWindow::slot_g_gaze_start_changed(double v) { + params_gaze.gaze_start = v; +} + +void MainWindow::slot_g_gaze_end_changed(double v) { + params_gaze.gaze_end = v; +} + +void MainWindow::slot_g_a_changed(double v) { + params_gaze.a = v; +} + +void MainWindow::slot_g_l1_changed(double v) { + params_gaze.l1 = v; +} + +void MainWindow::slot_g_l2_changed(double v) { + params_gaze.l2 = v; +} + +void MainWindow::slot_g_w1_changed(double v) { + params_gaze.w1 = v; +} + +void MainWindow::slot_g_w2_changed(double v) { + params_gaze.w2 = v; +} + +void MainWindow::slot_g_t1_changed(double v) { + params_gaze.t1 = v; +} + +void MainWindow::slot_g_t2_changed(double v) { + params_gaze.t2 = v; +} + +void MainWindow::slot_g_tg_changed(double v) { + params_gaze.tg = v; +} + +void MainWindow::slot_g_seed_changed(int v) { + params_gaze.seed = v; +} + +void MainWindow::slot_g_n_std_dev_changed(double v) { + params_gaze.n_std_dev = v; +} + +void MainWindow::slot_g_g_std_dev_changed(double v) { + params_gaze.g_std_dev = v; +} + /************************************************************** * * Other Slots @@ -920,6 +1227,11 @@ void MainWindow::slot_go_direct_britton() { chart->show(); } +void MainWindow::slot_go_gaze() { + ChartGaze *chart = new ChartGaze(¶ms_gaze); + chart->show(); +} + void MainWindow::slot_model_changed(int index) { switch (index) { @@ -943,6 +1255,11 @@ void MainWindow::slot_model_changed(int index) disconnect(m_button_go, SIGNAL(clicked(bool)), 0, 0); connect(m_button_go, SIGNAL(clicked(bool)), this, SLOT(slot_go_direct_britton())); break; + case MODEL_GAZE: + model_box->setCurrentWidget(model_box_gaze); + disconnect(m_button_go, SIGNAL(clicked(bool)), 0, 0); + connect(m_button_go, SIGNAL(clicked(bool)), this, SLOT(slot_go_gaze())); + break; default: // TODO: Handle this in GUI std::cout << "Unknown model" << std::endl; diff --git a/mainwindow.h b/mainwindow.h index 95b1061..cc989c4 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -29,6 +29,7 @@ class MainWindow : public QWidget void create_model_box_pratt(); void create_model_box_indirect_britton(); void create_model_box_direct_britton(); + void create_model_box_gaze(); /* window component: menu bar */ QMenuBar *menuBar; /* note: apparently on mac/osx the quit action always defaults to the name of the program */ @@ -36,13 +37,14 @@ class MainWindow : public QWidget QAction *exitAction; /* window component: combo menu box for selecting model */ - enum {MODEL_UM = 0, MODEL_PRATT, MODEL_INDIRECT_BRITTON, MODEL_DIRECT_BRITTON}; + enum {MODEL_UM = 0, MODEL_PRATT, MODEL_INDIRECT_BRITTON, MODEL_DIRECT_BRITTON, MODEL_GAZE}; QGroupBox *combo_menu_box; QComboBox *combo_menu; QAction *action_um; QAction *action_pratt; QAction *action_indirect_britton; QAction *action_direct_britton; + QAction *action_gaze; /* window component: button box for actions such as graph or quit */ QGroupBox *action_box; @@ -54,12 +56,14 @@ class MainWindow : public QWidget QGroupBox *model_box_pratt; /* the simplified pratt model box */ QGroupBox *model_box_indirect_britton; /* the simplified indirect britton box */ QGroupBox *model_box_direct_britton; + QGroupBox *model_box_gaze; /* model parameters */ params_um_t params_um; /* usher-mclelland binary decision */ params_pratt_t params_pratt; /* simplified pratt model: social insect, direct switching */ params_indirect_britton_t params_indirect_britton; params_direct_britton_t params_direct_britton; + params_gaze_t params_gaze; /* buttons */ /* Q: should these be defined here or in the action box? @@ -133,11 +137,34 @@ private slots: void slot_sdb_seed_changed(int v); void slot_sdb_std_dev_changed(double v); + /* gaze model changes to spinboxes */ + void slot_g_h_changed(double v); + void slot_g_d_changed(int v); + void slot_g_y1_0_changed(double v); + void slot_g_y2_0_changed(double v); + void slot_g_I1_changed(double v); + void slot_g_I2_changed(double v); + void slot_g_g_changed(double v); + void slot_g_gaze_start_changed(double v); + void slot_g_gaze_end_changed(double v); + void slot_g_a_changed(double v); + void slot_g_l1_changed(double v); + void slot_g_l2_changed(double v); + void slot_g_w1_changed(double v); + void slot_g_w2_changed(double v); + void slot_g_t1_changed(double v); + void slot_g_t2_changed(double v); + void slot_g_tg_changed(double v); + void slot_g_n_std_dev_changed(double v); + void slot_g_g_std_dev_changed(double v); + void slot_g_seed_changed(int v); + /* slots for handling the charting of the different models */ void slot_go_um(); void slot_go_pratt(); void slot_go_indirect_britton(); void slot_go_direct_britton(); + void slot_go_gaze(); void slot_model_changed(int); }; diff --git a/models.cpp b/models.cpp index afce42b..8080b04 100644 --- a/models.cpp +++ b/models.cpp @@ -29,14 +29,35 @@ void um_set_noise(std::default_random_engine *g, double mean, double std_dev, in std::normal_distribution distribution(mean,std_dev); for (int i=0; id/params->h); + + /* set initial conditions */ + results_y1[0] = params->y1_0; + results_y2[0] = params->y2_0; + + int i; + for (i=0;iI1 + + params->cn1[i] + - (params->l1 * results_y1[i]) + - (params->w2 * results_y2[i]); + double y2_k1 = params->I2 + + params->cn2[i] + - (params->l2 * results_y2[i]) + - (params->w1 * results_y1[i]); + results_y1[i+1] = results_y1[i] + (y1_k1 * params->h); + results_y2[i+1] = results_y2[i] + (y2_k1 * params->h); + } +} + void usher_mcclelland_rk4(params_um_t *params, double * results_y1, double * results_y2) { - int length = (int)(params->d/params->h); + + int length = ceil(params->d/params->h); /* set initial conditions */ results_y1[0] = params->y1_0; @@ -133,26 +154,12 @@ void pratt_set_noise(std::default_random_engine *g, for (int i=0; id/params->h); + int length = ceil(params->d/params->h); /* set initial conditions */ results_y1[0] = params->y1_0; @@ -253,9 +260,6 @@ void pratt_rk4(params_pratt_t *params, double * results_y1, double * results_y2) + ((results_y1[i] + (y1_k3 * params->h)) * (params->r1 + params->cn_r1[i])) - ((results_y2[i] + (y2_k3 * params->h)) * (params->r2 + params->cn_r2[i])) - ((results_y2[i] + (y2_k3 * params->h)) * (params->l2 + params->cn_l2[i]))); - /* Euler's method */ -// results_y1[i+1] = results_y1[i] + (y1_k1 * params->h); -// results_y2[i+1] = results_y2[i] + (y2_k1 * params->h); /* RK4 method */ results_y1[i+1] = results_y1[i] + (((y1_k1 + 2*y1_k2 + 2*y1_k3 + y1_k4)/6)*params->h); results_y2[i+1] = results_y2[i] + (((y2_k1 + 2*y2_k2 + 2*y2_k3 + y2_k4)/6)*params->h); @@ -308,20 +312,10 @@ void indirect_britton_set_noise(std::default_random_engine *g, for (int i=0; id/params->h); + int length = ceil(params->d/params->h); /* set initial conditions */ results_y1[0] = params->y1_0; @@ -436,26 +430,12 @@ void direct_britton_set_noise(std::default_random_engine *g, for (int i=0; id/params->h); + int length = ceil(params->d/params->h); /* set initial conditions */ results_y1[0] = params->y1_0; @@ -525,3 +505,137 @@ void direct_britton_rk4(params_direct_britton_t *params, double * results_y1, do results_y2[i+1] = results_y2[i] + (((y2_k1 + 2*y2_k2 + 2*y2_k3 + y2_k4)/6)*params->h); } } + +/***************************************************************************** + * + * Gaze Model + * + * Currently calculates gaze input as a linear function of the distince + * of the gaze from each target. + * + *****************************************************************************/ +void gaze_set_defaults(params_gaze_t *p) { + p->h = 0.2; + p->d = 30; + p->y1_0 = 0.0; + p->y2_0 = 0.0; + p->I1 = 0.05; + p->I2 = 0.05; + p->g = 0.0; + p->gaze_start = 0.0; + p->gaze_end = 0.0; + p->l1 = 0.2; + p->l2 = p->l1; + p->w1 = 0.3; + p->w2 = p->w1; + p->t1 = 45.0; + p->t2 = 135.0; + p->tg = p->t1; + p->a = 5; + p->n_std_dev = 0.1; + p->g_std_dev = 0.1; + p->seed = 32; +} + +/* Fill the noise arrays for the UM model */ +void gaze_set_noise(std::default_random_engine *g, + double mean, + double n_std_dev, + int length, + double *n_I1, + double *n_I2, + double *n_w1, + double *n_w2, + double *n_g1, + double *n_g2, + double *n_l1, + double *n_l2) +{ + std::normal_distribution distribution(mean,n_std_dev); + for (int i=0; id/params->h); + + /* for generating gaze location */ + std::normal_distribution distribution(0.0,params->g_std_dev); + int gs = floor(params->gaze_start/params->h); + int ge = floor(params->gaze_end/params->h); + double g1 = 0.; + double g2 = 0.; + + /* set initial conditions */ + results_y1[0] = params->y1_0; + results_y2[0] = params->y2_0; + + /* outside of gaze interval, the gaze is directed at nothing */ + int i; + for (i=0;i= gs && i <= ge) { + /* gaze is activated */ + double gaze_offset = distribution(*g); + if(params->tg >= params->t1) { + g1 = (params->g) * (((-1)/params->a * (params->tg - params->t1 + gaze_offset) + 1)); + } else { + g1 = (params->g) * (((-1)/params->a * (params->t1 - params->tg - gaze_offset) + 1)); + } + if(params->tg >= params->t2) { + g2 = (params->g) * (((-1)/params->a * (params->tg - params->t2 + gaze_offset) + 1)); + } else { + g2 = (params->g) * (((-1)/params->a * (params->t2 - params->tg - gaze_offset) + 1)); + } + if (g1 < 0.0) g1 = 0.0; + if (g2 < 0.0) g2 = 0.0; + } else { + /* gaze is not active */ + g1 = 0.; + g2 = 0.; + } + + double y1_k1 = (params->I1 + params->n_I1[i]) + + (g1 + params->n_g1[i]) + - (params->l1 * results_y1[i]) + - (params->w2 * results_y2[i]); + double y2_k1 = (params->I2 + params->n_I2[i]) + + (g2 + params->n_g2[i]) + - (params->l2 * results_y2[i]) + - (params->w1 * results_y1[i]); + double y1_k2 = (params->I1 + params->n_I1[i]) + + (g1 + params->n_g1[i]) + - (params->l1 * (results_y1[i] + (y1_k1 * params->h/2))) + - (params->w2 * (results_y2[i] + (y2_k1 * params->h/2))); + double y2_k2 = (params->I2 + params->n_I2[i]) + + (g2 + params->n_g2[i]) + - (params->l2 * (results_y2[i] + (y2_k1 * params->h/2))) + - (params->w1 * (results_y1[i] + (y1_k1 * params->h/2))); + double y1_k3 = (params->I1 + params->n_I1[i]) + + (g1 + params->n_g1[i]) + - (params->l1 * (results_y1[i] + (y1_k2 * params->h/2))) + - (params->w2 * (results_y2[i] + (y2_k2 * params->h/2))); + double y2_k3 = (params->I2 + params->n_I2[i]) + + (g2 + params->n_g2[i]) + - (params->l2 * (results_y2[i] + (y2_k2 * params->h/2))) + - (params->w1 * (results_y1[i] + (y1_k2 * params->h/2))); + double y1_k4 = (params->I1 + params->n_I1[i]) + + (g1 + params->n_g1[i]) + - (params->l1 * (results_y1[i] + (y1_k3 * params->h))) + - (params->w2 * (results_y2[i] + (y2_k3 * params->h))); + double y2_k4 = (params->I2 + params->n_I2[i]) + + (g2 + params->n_g2[i]) + - (params->l2 * (results_y2[i] + (y2_k3 * params->h))) + - (params->w1 * (results_y1[i] + (y1_k3 * params->h))); + results_y1[i+1] = results_y1[i] + (((y1_k1 + 2*y1_k2 + 2*y1_k3 + y1_k4)/6)*params->h); + results_y2[i+1] = results_y2[i] + (((y2_k1 + 2*y2_k2 + 2*y2_k3 + y2_k4)/6)*params->h); + } +} + diff --git a/models.h b/models.h index 5ba3cc4..9883a75 100644 --- a/models.h +++ b/models.h @@ -110,11 +110,47 @@ typedef struct params_direct_britton_s { double *cn_l2; /* noise applied to leakage from nest 2 to source */ } params_direct_britton_t; +/* parameters for gaze model */ +typedef struct params_gaze_s { + double h; /* step size */ + int d; /* duration */ + double y1_0; /* y1 initial condition (priming)*/ + double y2_0; /* y2 initial condition (priming)*/ + double I1; /* input to y1 */ + double I2; /* input to y2 */ + double g; /* maximum gaze input */ + double gaze_start; /* start time for gaze */ + double gaze_end; /* end time for gaze */ + double a; /* y-intercept for linear gaze activation */ + double l1; /* decay (leak) for y1 */ + double l2; /* decay (leak) for y2 */ + double w1; /* inhibition weight from y1 to y2 */ + double w2; /* inhibition weight from y2 to y1 */ + double t1; /* location of target location 1 */ + double t2; /* location of target location 2 */ + double tg; /* location of gaze */ + + double n_std_dev; /* standard deviation for noise */ + double g_std_dev; /* standard deviation for gaze */ + int seed; /* noise seed */ + + /* noise arrays */ + double *n_I1; /* input I1 noise */ + double *n_I2; /* input I2 noise */ + double *n_w1; /* weight w1 noise */ + double *n_w2; /* weight w2 noise */ + double *n_g1; /* noise on gaze input to y1 */ + double *n_g2; /* noise on gaze input to y2 */ + double *n_l1; /* noise on decay from y1 */ + double *n_l2; /* noise on decay from y2 */ +} params_gaze_t; + /* set default parameters */ void um_set_defaults(params_um_t *p); void pratt_set_defaults(params_pratt_t *p); void indirect_britton_set_defaults(params_indirect_britton_t *p); void direct_britton_set_defaults(params_direct_britton_t *p); +void gaze_set_defaults(params_gaze_t *p); /* given a seeded random engine, fill arrays with random noise */ void um_set_noise(std::default_random_engine *g, double mean, double std_dev, int length, double *cn1, double *cn2); @@ -156,7 +192,21 @@ void direct_britton_set_noise(std::default_random_engine *g, double *cn_l1, double *cn_l2); +void gaze_set_noise(std::default_random_engine *g, + double mean, + double n_std_dev, + int length, + double *n_I1, + double *n_I2, + double *n_w1, + double *n_w2, + double *n_g1, + double *n_g2, + double *n_l1, + double *n_l2); + /* the numerical approximations */ +void usher_mcclelland_eulers(params_um_t *params, double *results_y1, double *results_y2); void usher_mcclelland_rk4(params_um_t *params, double * results_y1, double * results_y2); void pratt_rk4(params_pratt_t *params, double * results_y1, double * results_y2); @@ -169,4 +219,6 @@ double indirect_britton_s(double s, double y1, double y2); void direct_britton_rk4(params_direct_britton_t *params, double * results_y1, double * results_y2); double direct_britton_s(double s, double y1, double y2); +void gaze_rk4(std::default_random_engine *g, params_gaze_t * params, double *results_y1, double *results_y2); + #endif // MODELS_H