Commit 874e2bdd authored by LEFEBVREJP email's avatar LEFEBVREJP email
Browse files

radixplot removal

parent affa63e4
...@@ -12,7 +12,6 @@ TRIBITS_PACKAGE_DEFINE_DEPENDENCIES( ...@@ -12,7 +12,6 @@ TRIBITS_PACKAGE_DEFINE_DEPENDENCIES(
glls radixglls SS OPTIONAL glls radixglls SS OPTIONAL
io radixio SS OPTIONAL io radixio SS OPTIONAL
geometry radixgeometry SS OPTIONAL geometry radixgeometry SS OPTIONAL
plot radixplot SS OPTIONAL
sparsegrids radixsparsegrids SS OPTIONAL sparsegrids radixsparsegrids SS OPTIONAL
widgets radixwidgets SS OPTIONAL widgets radixwidgets SS OPTIONAL
ams radixams SS OPTIONAL ams radixams SS OPTIONAL
......
##---------------------------------------------------------------------------##
## radixplot/CMakeLists.txt
## Jordan P. Lefebvre
## Tuesday May 31 12:50:40 2016
##---------------------------------------------------------------------------##
## CMAKE for radixplot
##---------------------------------------------------------------------------##
TRIBITS_SUBPACKAGE(plot)
##---------------------------------------------------------------------------##
## PACKAGE CONFIGURE FILE
##---------------------------------------------------------------------------##
##---------------------------------------------------------------------------##
## HEADER AND SOURCE FILES
##---------------------------------------------------------------------------##
# C/C++ headers
SET(MOC_HEADERS
plot.hh
)
SET(HEADERS
graph2d.hh
${MOC_HEADERS}
)
#
# Moc the header files
#
IF(USE_QT4)
QT4_WRAP_CPP(MOC_FILES
${MOC_HEADERS}
)
#
# Process qt resource files
QT4_ADD_RESOURCES(RESOURCE_RESULT
${RESOURCE_FILES}
)
ELSE()
QT5_WRAP_CPP(MOC_FILES
${MOC_HEADERS}
)
#
# Process qt resource files
QT5_ADD_RESOURCES(RESOURCE_RESULT
${RESOURCE_FILES}
)
ENDIF()
# C/C++ source
SET(SOURCES
plot.cc
graph2d.cc
)
SET(RESOURCE_FILES
plot.qrc
)
##---------------------------------------------------------------------------##
## PACKAGE TARGETS AND INSTALL
##---------------------------------------------------------------------------##
TRIBITS_ADD_LIBRARY(
radixplot
SOURCES ${SOURCES} ${MOC_FILES} ${RESOURCE_RESULT}
)
INSTALL(FILES ${HEADERS}
DESTINATION include/radixplot)
#
# Add test directory for this package
#
#TRIBITS_ADD_TEST_DIRECTORIES(tests)
#
# Add example directory for this package
#
TRIBITS_ADD_EXAMPLE_DIRECTORIES(examples)
TRIBITS_SUBPACKAGE_POSTPROCESS()
##---------------------------------------------------------------------------##
## end of radixplot/CMakeLists.txt
##---------------------------------------------------------------------------##
##---------------------------------------------------------------------------##
## radixplot/cmake/Dependencies.cmake
## Jordan P. Lefebvre
## Tuesday May 31 12:57:18 2016
##---------------------------------------------------------------------------##
IF(NOT USE_QT5)
SET(USE_QT4 ON)
ENDIF()
IF(USE_QT4)
SET(QT_PACKAGES QT)
ELSE()
SET(QT_PACKAGES Qt5Widgets Qt5Core)
ENDIF()
TRIBITS_PACKAGE_DEFINE_DEPENDENCIES(
LIB_REQUIRED_PACKAGES QtSolutions QCustomPlot
LIB_REQUIRED_TPLS ${QT_PACKAGES}
)
##---------------------------------------------------------------------------##
## end of radixplot/cmake/Dependencies.cmake
##---------------------------------------------------------------------------##
# Provide access to QT-generated code
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
IF(USE_QT4)
QT4_WRAP_CPP(QMOC_FILES
mainwindow.hh
)
ELSE()
QT5_WRAP_CPP(QMOC_FILES
mainwindow.hh
)
ENDIF()
SET(SOURCE
mainwindow.cc
)
TRIBITS_ADD_EXECUTABLE(plot2d-examples
NOEXEPREFIX
SOURCES ${SOURCE} ${QMOC_FILES}
)
/*
* @file: mainwindow.cpp
* @author: Jordan P. Lefebvre, lefebvrejp@ornl.gov
*
* Created on May 31, 2016, 10:52 PM
*/
#include "mainwindow.hh"
#include <QApplication>
#include <QDebug>
#include <QDesktopWidget>
#include <QListView>
#include <QMessageBox>
#include <QMetaEnum>
#include <QScreen>
#include <QSplitter>
#include <QStandardItemModel>
#include <QVBoxLayout>
#include <cstdlib>
#include <limits>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setGeometry(400, 250, 542, 390);
QWidget *mainWidget = new QWidget(this);
plotWidget = new QWidget(this);
setCentralWidget(mainWidget);
QVBoxLayout *layout = new QVBoxLayout(mainWidget);
QVBoxLayout *plotLayout = new QVBoxLayout(plotWidget);
plot = new radix::Plot(this);
QListView *demoListView = new QListView(this);
QStandardItemModel *viewModel = new QStandardItemModel();
demoListView->setModel(viewModel);
viewModel->appendRow(new QStandardItem("Quadratic Demo"));
viewModel->appendRow(new QStandardItem("Simple Demo"));
viewModel->appendRow(new QStandardItem("Sinc Demo"));
viewModel->appendRow(new QStandardItem("Scatter Style Demo"));
viewModel->appendRow(new QStandardItem("Line Style Demo"));
viewModel->appendRow(new QStandardItem("Discontinuous Line Demo"));
viewModel->appendRow(new QStandardItem("Date Demo"));
// split between demo list and plot
QSplitter *split = new QSplitter();
// add demo list
split->addWidget(demoListView);
// add the plot widget
plotLayout->addWidget(plot);
split->addWidget(plotWidget);
split->setStretchFactor(0, 0);
split->setStretchFactor(1, 1);
layout->addWidget(split);
//
// Connect signals
//
connect(demoListView->selectionModel(),
SIGNAL(currentRowChanged(QModelIndex, QModelIndex)), this,
SLOT(changeDemo(QModelIndex, QModelIndex)));
demoListView->setCurrentIndex(viewModel->index(0, 0));
}
void MainWindow::changeDemo(const QModelIndex &current,
const QModelIndex &preivous)
{
int demoIndex = current.row();
// stop timer
// clear existing plot data
delete plot;
plot = new radix::Plot(plotWidget);
plotWidget->layout()->addWidget(plot);
if (dataTimer.isActive())
{
disconnect(&dataTimer, SLOT(timeout()));
dataTimer.stop();
}
//
// reset axes
//
plot->rescaleAxes();
plot->replot();
switch (demoIndex)
{
case 0:
setupQuadraticDemo();
break;
case 1:
setupSimpleDemo();
break;
case 2:
setupSincScatterDemo();
break;
case 3:
setupScatterStyleDemo();
break;
case 4:
setupLineStyleDemo();
break;
case 5:
setupDiscontinuousLineDemo();
break;
case 6:
setupDateDemo();
break;
}
setWindowTitle("QCustomPlot: " + demoName);
currentDemoIndex = demoIndex;
plot->replot();
}
void MainWindow::setupQuadraticDemo()
{
demoName = "Quadratic Demo";
// generate some data:
std::vector<double> x(101), y(101); // initialize with entries 0..100
for (size_t i = 0; i < 101; ++i)
{
x[i] = i / 50.0 - 1; // x goes from -1 to 1
y[i] = x[i] * x[i]; // let's plot a quadratic function
}
// create graph and assign data to it:
radix::Graph2D::SP sp_graph = plot->createGraph2D();
// graph will have the default key/value units
sp_graph->setData(x, y);
sp_graph->setKeyUnit("Seconds");
sp_graph->setValueUnit("eV");
plot->xAxis()->setLabel(sp_graph->getKeyUnit());
plot->yAxis()->setLabel(sp_graph->getValueUnit());
plot->rescaleAxes();
//
// Show xaxis subgrid
//
plot->xAxis()->grid()->setSubGridVisible(true);
}
void MainWindow::setupSimpleDemo()
{
demoName = "Simple Demo";
// add two new graphs and set their look:
radix::Graph2D::SP sp_graph0 = plot->createGraph2D();
// line color blue for first graph
sp_graph0->setPen(QPen(Qt::blue));
// first graph will be filled with translucent blue
sp_graph0->setBrush(QBrush(QColor(0, 0, 255, 20)));
radix::Graph2D::SP sp_graph1 = plot->createGraph2D();
sp_graph1->setPen(QPen(Qt::red)); // line color red for second graph
// generate some points of data (y0 for first, y1 for second graph):
std::vector<double> x(250), y0(250), y1(250);
for (int i = 0; i < 250; ++i)
{
x[i] = i;
y0[i] = qExp(-i / 150.0) * qCos(i / 10.0); // exponentially decaying cosine
y1[i] = qExp(-i / 150.0); // exponential envelope
}
// configure right and top axis to show ticks but no labels:
// (see QCPAxisRect::setupFullAxesBox for a quicker method to do this)
plot->xAxis2()->setVisible(true);
plot->xAxis2()->setTickLabels(false);
plot->yAxis2()->setVisible(true);
plot->yAxis2()->setTickLabels(false);
// make left and bottom axes always transfer their ranges to right
// and top axes:
connect(plot->xAxis(), SIGNAL(rangeChanged(QCPRange)), plot->xAxis2(),
SLOT(setRange(QCPRange)));
connect(plot->yAxis(), SIGNAL(rangeChanged(QCPRange)), plot->yAxis2(),
SLOT(setRange(QCPRange)));
// pass data points to graphs:
sp_graph0->setData(x, y0);
sp_graph1->setData(x, y1);
// let the ranges scale themselves so graph 0 fits perfectly
// in the visible area:
sp_graph0->rescaleAxes();
// same thing for graph 1, but only enlarge ranges
// (in case graph 1 is smaller than graph 0):
sp_graph1->rescaleAxes(true);
// Note: we could have also just called qcplot->rescaleAxes(); instead
// Allow user to drag axis ranges with mouse, zoom with mouse wheel
// and select graphs by clicking:
plot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom |
QCP::iSelectPlottables);
}
void MainWindow::setupSincScatterDemo()
{
demoName = "Sinc Scatter Demo";
plot->legend()->setFont(QFont("Helvetica", 9));
// set locale to english, so we get english decimal separator:
plot->setLocale(QLocale(QLocale::English, QLocale::UnitedKingdom));
// add confidence band graphs:
radix::Graph2D::SP sp_graph1 = plot->createGraph2D();
QPen pen;
pen.setStyle(Qt::DotLine);
pen.setWidth(1);
pen.setColor(QColor(180, 180, 180));
sp_graph1->setName("Confidence Band 68%");
sp_graph1->setPen(pen);
sp_graph1->setBrush(QBrush(QColor(255, 50, 30, 20)));
radix::Graph2D::SP sp_graph2 = plot->createGraph2D();
//
// don't show two confidence band graphs in legend, so remove one
//
plot->legend()->removeItem(plot->legend()->itemCount() - 1);
sp_graph2->setPen(pen);
sp_graph1->setChannelFillGraph(*(sp_graph2.get()));
// add theory curve graph:
radix::Graph2D::SP sp_graph3 = plot->createGraph2D();
pen.setStyle(Qt::DashLine);
pen.setWidth(2);
pen.setColor(Qt::red);
sp_graph3->setPen(pen);
sp_graph3->setName("Theory Curve");
// add data point graph:
radix::Graph2D::SP sp_graph4 = plot->createGraph2D();
sp_graph4->setPen(QPen(Qt::blue));
sp_graph4->setLineStyle(QCPGraph::lsNone);
sp_graph4->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCross, 4));
sp_graph4->setErrorType(QCPGraph::etValue);
sp_graph4->setErrorPen(QPen(QColor(180, 180, 180)));
sp_graph4->setName("Measurement");
//
// generate ideal sinc curve data and some randomly perturbed data
// for scatter plot:
//
std::vector<double> x0(250), y0(250);
std::vector<double> yConfUpper(250), yConfLower(250);
for (size_t i = 0; i < 250; ++i)
{
//
// by adding a small offset(0.01) we make sure not do divide by zero
//
x0[i] = (i / 249.0 - 0.5) * 30 + 0.01;
y0[i] = qSin(x0[i]) / x0[i]; // sinc function
yConfUpper[i] = y0[i] + 0.15;
yConfLower[i] = y0[i] - 0.15;
x0[i] *= 1000;
}
std::vector<double> x1(50), y1(50), y1err(50);
for (size_t i = 0; i < 50; ++i)
{
// generate a gaussian distributed random number:
double tmp1 = rand() / (double)RAND_MAX;
double tmp2 = rand() / (double)RAND_MAX;
//
// box-muller transform for gaussian distribution
double r = qSqrt(-2 * qLn(tmp1)) * qCos(2 * M_PI * tmp2);
//
// set y1 to value of y0 plus a random gaussian pertubation:
//
x1[i] = ((std::rand() % 50) / 50.0 - 0.5) * 30 + 0.25;
y1[i] = qSin(x1[i]) / x1[i] + r * 0.15;
x1[i] *= 1000;
y1err[i] = 0.15;
}
std::sort(x1.begin(), x1.end());
//
// pass data to graphs and let QCustomPlot
// determine the axes ranges so the whole thing is visible:
//
sp_graph1->setData(x0, yConfUpper);
sp_graph2->setData(x0, yConfLower);
sp_graph3->setData(x0, y0);
sp_graph4->setDataValueError(x1, y1, y1err);
sp_graph3->rescaleAxes();
sp_graph4->rescaleAxes(true);
// setup look of bottom tick labels:
plot->xAxis()->setTickLabelRotation(30);
plot->xAxis()->setAutoTickCount(9);
plot->xAxis()->setNumberFormat("ebc");
plot->xAxis()->setNumberPrecision(1);
plot->xAxis()->moveRange(-10);
// make top right axes clones of bottom left axes. Looks prettier:
plot->axisRect()->setupFullAxesBox();
}
void MainWindow::setupScatterStyleDemo()
{
demoName = "Scatter Style Demo";
plot->legend()->setVisible(true);
plot->legend()->setFont(QFont("Helvetica", 9));
plot->legend()->setRowSpacing(-3);
//
// Create list of all possible scatter styles and one custom option
//
QVector<QCPScatterStyle::ScatterShape> shapes;
shapes << QCPScatterStyle::ssCross;
shapes << QCPScatterStyle::ssPlus;
shapes << QCPScatterStyle::ssCircle;
shapes << QCPScatterStyle::ssDisc;
shapes << QCPScatterStyle::ssSquare;
shapes << QCPScatterStyle::ssDiamond;
shapes << QCPScatterStyle::ssStar;
shapes << QCPScatterStyle::ssTriangle;
shapes << QCPScatterStyle::ssTriangleInverted;
shapes << QCPScatterStyle::ssCrossSquare;
shapes << QCPScatterStyle::ssPlusSquare;
shapes << QCPScatterStyle::ssCrossCircle;
shapes << QCPScatterStyle::ssPlusCircle;
shapes << QCPScatterStyle::ssPeace;
shapes << QCPScatterStyle::ssCustom;
QPen pen;
//
// add graphs with different scatter styles:
//
for (int i = 0; i < shapes.size(); ++i)
{
radix::Graph2D::SP graph = plot->createGraph2D();
pen.setColor(QColor(qSin(i * 0.3) * 100 + 100,
qSin(i * 0.6 + 0.7) * 100 + 100,
qSin(i * 0.4 + 0.6) * 100 + 100));
//
// generate data:
//
std::vector<double> x(10), y(10);
for (size_t k = 0; k < 10; ++k)
{
x[k] = k / 10.0 * 4 * 3.14 + 0.01;
y[k] = 7 * qSin(x[k]) / x[k] + (shapes.size() - i) * 5;
}
graph->setData(x, y);
graph->rescaleAxes(true);
graph->setPen(pen);
// use static meta object data from scatter style to get its name
graph->setName(
QCPScatterStyle::staticMetaObject
.enumerator(QCPScatterStyle::staticMetaObject.indexOfEnumerator(
"ScatterShape"))
.valueToKey(shapes.at(i)));
graph->setLineStyle(QCPGraph::lsLine);
//
// set scatter style:
//
if (shapes.at(i) != QCPScatterStyle::ssCustom)
{
graph->setScatterStyle(QCPScatterStyle(shapes.at(i), 10));
}
else
{
//
// Make custom scatter style
//
QPainterPath customScatterPath;
for (int i = 0; i < 3; ++i)
customScatterPath.cubicTo(qCos(2 * M_PI * i / 3.0) * 9,
qSin(2 * M_PI * i / 3.0) * 9,
qCos(2 * M_PI * (i + 0.9) / 3.0) * 9,
qSin(2 * M_PI * (i + 0.9) / 3.0) * 9, 0, 0);
graph->setScatterStyle(QCPScatterStyle(
customScatterPath, QPen(Qt::black, 0), QColor(40, 70, 255, 50), 10));
}
}
//
// set blank axis lines:
//
plot->rescaleAxes();
plot->xAxis()->setTicks(false);
plot->yAxis()->setTicks(false);
plot->xAxis()->setTickLabels(false);
plot->yAxis()->setTickLabels(false);
//
// make top right axes clones of bottom left axes:
//
plot->axisRect()->setupFullAxesBox();
}
void MainWindow::setupLineStyleDemo()
{
demoName = "Line Style Demo";
plot->legend()->setVisible(true);
plot->legend()->setFont(QFont("Helvetica", 9));
QPen pen;
QStringList lineNames;
lineNames << "lsNone"
<< "lsLine"
<< "lsStepLeft"
<< "lsStepRight"
<< "lsStepCenter"
<< "lsImpulse";
//
// add graphs with different line styles:
//
for (int i = QCPGraph::lsNone; i <= QCPGraph::lsImpulse; ++i)
{
radix::Graph2D::SP graph = plot->createGraph2D();
pen.setColor(QColor(qSin(i * 1 + 1.2) * 80 + 80,
qSin(i * 0.3 + 0) * 80 + 80,
qSin(i * 0.3 + 1.5) * 80 + 80));
graph->setPen(pen);
graph->setName(lineNames.at(i - QCPGraph::lsNone).toStdString());
graph->setLineStyle((QCPGraph::LineStyle)i);
graph->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, 5));
//
// generate data:
//
std::vector<double> x(15), y(15);
for (int j = 0; j < 15; ++j)
{
x[j] = j / 15.0 * 5 * 3.14 + 0.01;
// use QCP line style enums to ensure graphs to not overlap
y[j] = 7 * qSin(x[j]) / x[j] - (i - QCPGraph::lsNone) * 5 +
(QCPGraph::lsImpulse)*5 + 2;
}
graph->setData(x, y);
graph->rescaleAxes(true);
}
//
// zoom out a bit:
//
plot->yAxis()->scaleRange(1.1, plot->yAxis()->range().center());
plot->xAxis()->scaleRange(1.1, plot->xAxis()->range().center());
//
// set blank axis lines:
//
plot->xAxis()->setTicks(false);
plot->yAxis()->setTicks(true);
plot->xAxis()->setTickLabels(false);
plot->yAxis()->setTickLabels(true);
//
// make top right axes clones of bottom left axes:
//
plot->axisRect()->setupFullAxesBox();
}
void MainWindow::setupDiscontinuousLineDemo()
{
demoName = "Discontinuous Line Demo";
plot->legend()->setVisible(true);
plot->legend()->setFont(QFont("Helvetica", 9));
QPen pen;
QStringList lineNames;
lineNames << "lsNone"
<< "lsLine"
<< "lsStepLeft"
<< "lsStepRight"
<< "lsStepCenter"
<< "lsImpulse";
//
// add graphs with different line styles:
//
for (int i = QCPGraph::lsNone; i <= QCPGraph::lsStepCenter; ++i)
{
radix::Graph2D::SP graph = plot->createGraph2D();
pen.setColor(QColor(qSin(i * 1 + 1.2) * 80 + 80,
qSin(i * 0.3 + 0) * 80 + 80,
qSin(i * 0.3 + 1.5) * 80 + 80));
graph->setPen(pen);
graph->setName(lineNames.at(i - QCPGraph::lsNone).toStdString());
graph->setLineStyle((QCPGraph::LineStyle)i);
graph->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, 5));
//
// generate data:
//
std::vector<double> x(15), y(15);
for (int j = 0; j < 7; ++j)
{
x[j] = j / 15.0 * 5 * 3.14 + 0.01;
// use QCP line style enums to ensure graphs to not overlap
y[j] = 7 * qSin(x[j]) / x[j] - (i - QCPGraph::lsNone) * 5 +
(QCPGraph::lsImpulse)*5 + 2;