2023-05-31 17:30:46 -04:00
|
|
|
#ifndef CUSTOM_HIST_H
|
|
|
|
#define CUSTOM_HIST_H
|
|
|
|
|
|
|
|
#include "qcustomplot.h"
|
|
|
|
|
|
|
|
//^==============================================
|
|
|
|
//^==============================================
|
|
|
|
class Histogram1D : public QCustomPlot{
|
|
|
|
public:
|
2023-06-01 17:51:00 -04:00
|
|
|
Histogram1D(QString title, QString xLabel, int xbin, double xmin, double xmax, QWidget * parent = nullptr) : QCustomPlot(parent){
|
|
|
|
Rebin(xbin, xmin, xmax);
|
2023-05-31 17:30:46 -04:00
|
|
|
|
|
|
|
xAxis->setLabel(xLabel);
|
|
|
|
|
|
|
|
legend->setVisible(true);
|
2023-06-02 15:41:26 -04:00
|
|
|
QPen borderPen = legend->borderPen();
|
|
|
|
borderPen.setWidth(0);
|
|
|
|
borderPen.setColor(Qt::transparent);
|
|
|
|
legend->setBorderPen(borderPen);
|
2023-05-31 17:30:46 -04:00
|
|
|
legend->setFont(QFont("Helvetica", 9));
|
|
|
|
|
|
|
|
addGraph();
|
|
|
|
graph(0)->setName(title);
|
|
|
|
graph(0)->setPen(QPen(Qt::blue));
|
|
|
|
graph(0)->setBrush(QBrush(QColor(0, 0, 255, 20)));
|
|
|
|
|
|
|
|
xAxis2->setVisible(true);
|
|
|
|
xAxis2->setTickLabels(false);
|
|
|
|
yAxis2->setVisible(true);
|
|
|
|
yAxis2->setTickLabels(false);
|
|
|
|
// make left and bottom axes always transfer their ranges to right and top axes:
|
|
|
|
connect(xAxis, SIGNAL(rangeChanged(QCPRange)), xAxis2, SLOT(setRange(QCPRange)));
|
|
|
|
connect(yAxis, SIGNAL(rangeChanged(QCPRange)), yAxis2, SLOT(setRange(QCPRange)));
|
|
|
|
|
|
|
|
graph(0)->setData(xList, yList);
|
|
|
|
|
|
|
|
//setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
|
2023-06-02 15:41:26 -04:00
|
|
|
//setInteractions( QCP::iRangeDrag | QCP::iRangeZoom );
|
|
|
|
|
|
|
|
//setSelectionRectMode(QCP::SelectionRectMode::srmZoom);
|
2023-05-31 17:30:46 -04:00
|
|
|
|
|
|
|
rescaleAxes();
|
|
|
|
yAxis->setRangeLower(0);
|
|
|
|
yAxis->setRangeUpper(10);
|
|
|
|
|
2023-06-02 15:41:26 -04:00
|
|
|
txtTotEntry = new QCPItemText(this);
|
|
|
|
txtTotEntry->setPositionAlignment(Qt::AlignLeft);
|
|
|
|
txtTotEntry->position->setType(QCPItemPosition::ptAxisRectRatio);
|
|
|
|
txtTotEntry->position->setCoords(0.1, 0.1);;
|
|
|
|
txtTotEntry->setText("Total Entry : 0");
|
|
|
|
txtTotEntry->setFont(QFont("Helvetica", 9));
|
|
|
|
|
|
|
|
txtUnderFlow = new QCPItemText(this);
|
|
|
|
txtUnderFlow->setPositionAlignment(Qt::AlignLeft);
|
|
|
|
txtUnderFlow->position->setType(QCPItemPosition::ptAxisRectRatio);
|
|
|
|
txtUnderFlow->position->setCoords(0.1, 0.15);;
|
|
|
|
txtUnderFlow->setText("Under Flow : 0");
|
|
|
|
txtUnderFlow->setFont(QFont("Helvetica", 9));
|
|
|
|
|
|
|
|
txtOverFlow = new QCPItemText(this);
|
|
|
|
txtOverFlow->setPositionAlignment(Qt::AlignLeft);
|
|
|
|
txtOverFlow->position->setType(QCPItemPosition::ptAxisRectRatio);
|
|
|
|
txtOverFlow->position->setCoords(0.1, 0.2);;
|
|
|
|
txtOverFlow->setText("Over Flow : 0");
|
|
|
|
txtOverFlow->setFont(QFont("Helvetica", 9));
|
|
|
|
|
|
|
|
usingMenu = false;
|
|
|
|
|
2023-05-31 17:30:46 -04:00
|
|
|
connect(this, &QCustomPlot::mouseMove, this, [=](QMouseEvent *event){
|
|
|
|
double x = this->xAxis->pixelToCoord(event->pos().x());
|
2023-06-01 17:51:00 -04:00
|
|
|
double bin = (x - xMin)/dX;
|
2023-05-31 17:30:46 -04:00
|
|
|
double z = yList[2*qFloor(bin) + 1];
|
|
|
|
|
2023-06-01 17:51:00 -04:00
|
|
|
QString coordinates = QString("Bin: %1, Value: %2").arg(qFloor(bin)).arg(z);
|
2023-05-31 17:30:46 -04:00
|
|
|
QToolTip::showText(event->globalPosition().toPoint(), coordinates, this);
|
|
|
|
});
|
|
|
|
|
|
|
|
connect(this, &QCustomPlot::mousePress, this, [=](QMouseEvent * event){
|
2023-06-02 15:41:26 -04:00
|
|
|
if (event->button() == Qt::LeftButton && !usingMenu){
|
|
|
|
setSelectionRectMode(QCP::SelectionRectMode::srmZoom);
|
|
|
|
}
|
2023-05-31 17:30:46 -04:00
|
|
|
if (event->button() == Qt::RightButton) {
|
2023-06-02 15:41:26 -04:00
|
|
|
usingMenu = true;
|
|
|
|
setSelectionRectMode(QCP::SelectionRectMode::srmNone);
|
2023-05-31 17:30:46 -04:00
|
|
|
QMenu *menu = new QMenu(this);
|
|
|
|
menu->setAttribute(Qt::WA_DeleteOnClose);
|
|
|
|
|
|
|
|
QAction * a1 = menu->addAction("UnZoom");
|
2023-06-01 17:51:00 -04:00
|
|
|
//TODO QAction * a2 = menu->addAction("Fit Guass");
|
2023-05-31 17:30:46 -04:00
|
|
|
|
|
|
|
QAction *selectedAction = menu->exec(event->globalPosition().toPoint());
|
|
|
|
if( selectedAction == a1 ){
|
2023-06-01 17:51:00 -04:00
|
|
|
xAxis->setRangeLower(xMin);
|
2023-05-31 17:30:46 -04:00
|
|
|
xAxis->setRangeUpper(xMax);
|
|
|
|
yAxis->setRangeLower(0);
|
2023-06-01 17:51:00 -04:00
|
|
|
yAxis->setRangeUpper(yMax * 1.2 > 10 ? yMax * 1.2 : 10);
|
2023-05-31 17:30:46 -04:00
|
|
|
replot();
|
2023-06-02 15:41:26 -04:00
|
|
|
usingMenu = false;
|
2023-05-31 17:30:46 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
2023-06-01 17:51:00 -04:00
|
|
|
|
2023-05-31 17:30:46 -04:00
|
|
|
}
|
|
|
|
|
2023-06-01 17:51:00 -04:00
|
|
|
int GetNBin() const {return xBin;}
|
|
|
|
double GetXMin() const {return xMin;}
|
|
|
|
double GetXMax() const {return xMax;}
|
|
|
|
|
2023-05-31 17:30:46 -04:00
|
|
|
void UpdatePlot(){
|
|
|
|
graph(0)->setData(xList, yList);
|
2023-06-01 17:51:00 -04:00
|
|
|
xAxis->setRangeLower(xMin);
|
2023-05-31 17:30:46 -04:00
|
|
|
xAxis->setRangeUpper(xMax);
|
|
|
|
yAxis->setRangeLower(0);
|
|
|
|
yAxis->setRangeUpper(yMax * 1.2 > 10 ? yMax * 1.2 : 10);
|
|
|
|
replot();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Clear(){
|
2023-06-01 17:51:00 -04:00
|
|
|
for( int i = 0; i <= yList.count(); i++) yList[i] = 0;
|
|
|
|
yMax = 0;
|
|
|
|
UpdatePlot();
|
2023-05-31 17:30:46 -04:00
|
|
|
}
|
|
|
|
|
2023-06-01 17:51:00 -04:00
|
|
|
void Rebin(int xbin, double xmin, double xmax){
|
|
|
|
xMin = xmin;
|
|
|
|
xMax = xmax;
|
|
|
|
xBin = xbin;
|
2023-05-31 17:30:46 -04:00
|
|
|
|
|
|
|
dX = (xMax - xMin)/(xBin);
|
|
|
|
|
|
|
|
xList.clear();
|
|
|
|
yList.clear();
|
|
|
|
|
|
|
|
for( int i = 0; i <= xBin; i ++ ){
|
2023-06-01 17:51:00 -04:00
|
|
|
xList.append(xMin + i*dX-(dX)*0.000001);
|
|
|
|
xList.append(xMin + i*dX);
|
2023-05-31 17:30:46 -04:00
|
|
|
yList.append(0);
|
|
|
|
yList.append(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
yMax = 0;
|
|
|
|
|
|
|
|
totalEntry = 0;
|
|
|
|
underFlow = 0;
|
|
|
|
overFlow = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void Fill(double value){
|
|
|
|
totalEntry ++;
|
2023-06-02 15:41:26 -04:00
|
|
|
txtTotEntry->setText("Total Entry : "+ QString::number(totalEntry));
|
|
|
|
|
|
|
|
if( value < xMin ) {
|
|
|
|
underFlow ++;
|
|
|
|
txtUnderFlow->setText("Under Flow : "+ QString::number(underFlow));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if( value > xMax ) {
|
|
|
|
overFlow ++;
|
|
|
|
txtOverFlow->setText("Over Flow : "+ QString::number(overFlow));
|
|
|
|
return;
|
|
|
|
}
|
2023-05-31 17:30:46 -04:00
|
|
|
|
|
|
|
double bin = (value - xMin)/dX;
|
|
|
|
int index1 = 2*qFloor(bin) + 1;
|
|
|
|
int index2 = index1 + 1;
|
2023-06-01 17:51:00 -04:00
|
|
|
|
2023-05-31 17:30:46 -04:00
|
|
|
if( 0 <= index1 && index1 <= 2*xBin) yList[index1] += 1;
|
|
|
|
if( 0 <= index1 && index2 <= 2*xBin) yList[index2] += 1;
|
|
|
|
|
|
|
|
if( yList[index1] > yMax ) yMax = yList[index1];
|
|
|
|
}
|
|
|
|
|
|
|
|
void Print(){
|
|
|
|
for( int i = 0; i < xList.count(); i++){
|
|
|
|
printf("%f %f\n", xList[i], yList[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
double xMin, xMax, dX;
|
|
|
|
int xBin;
|
|
|
|
|
|
|
|
double yMax;
|
|
|
|
|
|
|
|
int totalEntry;
|
|
|
|
int underFlow;
|
|
|
|
int overFlow;
|
|
|
|
|
|
|
|
QVector<double> xList, yList;
|
|
|
|
|
2023-06-02 15:41:26 -04:00
|
|
|
QCPItemText * txtTotEntry;
|
|
|
|
QCPItemText * txtUnderFlow;
|
|
|
|
QCPItemText * txtOverFlow;
|
|
|
|
|
|
|
|
bool usingMenu;
|
|
|
|
|
2023-05-31 17:30:46 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
//^==============================================
|
|
|
|
//^==============================================
|
|
|
|
class Histogram2D : public QCustomPlot{
|
|
|
|
public:
|
2023-06-01 17:51:00 -04:00
|
|
|
Histogram2D(QString title, QString xLabel, QString yLabel, int xbin, double xmin, double xmax, int ybin, double ymin, double ymax, QWidget * parent = nullptr) : QCustomPlot(parent){
|
|
|
|
xMin = xmin;
|
|
|
|
xMax = xmax;
|
|
|
|
yMin = ymin;
|
|
|
|
yMax = ymax;
|
|
|
|
xBin = xbin;
|
|
|
|
yBin = ybin;
|
2023-05-31 17:30:46 -04:00
|
|
|
|
|
|
|
axisRect()->setupFullAxesBox(true);
|
|
|
|
xAxis->setLabel(xLabel);
|
|
|
|
yAxis->setLabel(yLabel);
|
|
|
|
|
2023-06-01 17:51:00 -04:00
|
|
|
colorMap = new QCPColorMap(xAxis, yAxis);
|
2023-05-31 17:30:46 -04:00
|
|
|
colorMap->data()->setSize(xBin, yBin);
|
|
|
|
colorMap->data()->setRange(QCPRange(xMin, xMax), QCPRange(yMin, yMax));
|
|
|
|
colorMap->setInterpolate(false);
|
|
|
|
|
|
|
|
QCPTextElement *titleEle = new QCPTextElement(this, title, QFont("sans", 12));
|
|
|
|
plotLayout()->addElement(0, 0, titleEle);
|
|
|
|
|
|
|
|
colorScale = new QCPColorScale(this);
|
|
|
|
plotLayout()->addElement(0, 1, colorScale);
|
|
|
|
colorScale->setType(QCPAxis::atRight);
|
|
|
|
colorMap->setColorScale(colorScale);
|
|
|
|
|
|
|
|
QCPColorGradient color;
|
|
|
|
color.clearColorStops();
|
|
|
|
color.setColorStopAt( 0, QColor("white" ));
|
|
|
|
color.setColorStopAt( 0.5, QColor("blue"));
|
|
|
|
color.setColorStopAt( 1, QColor("yellow"));
|
|
|
|
colorMap->setGradient(color);
|
|
|
|
|
|
|
|
rescaleAxes();
|
|
|
|
|
2023-06-02 15:41:26 -04:00
|
|
|
usingMenu = false;
|
|
|
|
|
2023-05-31 17:30:46 -04:00
|
|
|
connect(this, &QCustomPlot::mouseMove, this, [=](QMouseEvent *event){
|
2023-06-01 17:51:00 -04:00
|
|
|
double x = xAxis->pixelToCoord(event->pos().x());
|
|
|
|
double y = yAxis->pixelToCoord(event->pos().y());
|
2023-05-31 17:30:46 -04:00
|
|
|
int xI, yI;
|
|
|
|
colorMap->data()->coordToCell(x, y, &xI, &yI);
|
|
|
|
double z = colorMap->data()->cell(xI, yI);
|
|
|
|
|
|
|
|
QString coordinates = QString("X: %1, Y: %2, Z: %3").arg(x).arg(y).arg(z);
|
|
|
|
QToolTip::showText(event->globalPosition().toPoint(), coordinates, this);
|
|
|
|
});
|
|
|
|
|
2023-06-01 17:51:00 -04:00
|
|
|
connect(this, &QCustomPlot::mousePress, this, [=](QMouseEvent * event){
|
2023-06-02 15:41:26 -04:00
|
|
|
if (event->button() == Qt::LeftButton && !usingMenu){
|
|
|
|
setSelectionRectMode(QCP::SelectionRectMode::srmZoom);
|
|
|
|
}
|
2023-06-01 17:51:00 -04:00
|
|
|
if (event->button() == Qt::RightButton) {
|
2023-06-02 15:41:26 -04:00
|
|
|
usingMenu = true;
|
|
|
|
setSelectionRectMode(QCP::SelectionRectMode::srmNone);
|
|
|
|
|
2023-06-01 17:51:00 -04:00
|
|
|
QMenu *menu = new QMenu(this);
|
|
|
|
menu->setAttribute(Qt::WA_DeleteOnClose);
|
|
|
|
|
|
|
|
QAction * a1 = menu->addAction("UnZoom");
|
|
|
|
|
|
|
|
QAction *selectedAction = menu->exec(event->globalPosition().toPoint());
|
|
|
|
|
|
|
|
if( selectedAction == a1 ){
|
|
|
|
xAxis->setRangeLower(xMin);
|
|
|
|
xAxis->setRangeUpper(xMax);
|
|
|
|
yAxis->setRangeLower(yMin);
|
|
|
|
yAxis->setRangeUpper(yMax);
|
|
|
|
replot();
|
2023-06-02 15:41:26 -04:00
|
|
|
usingMenu = false;
|
2023-06-01 17:51:00 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2023-05-31 17:30:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void UpdatePlot(){
|
|
|
|
colorMap->rescaleDataRange();
|
|
|
|
rescaleAxes();
|
|
|
|
replot();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Fill(double x, double y){
|
|
|
|
int xIndex, yIndex;
|
|
|
|
colorMap->data()->coordToCell(x, y, &xIndex, &yIndex);
|
|
|
|
//printf("%f, %d %d| %f, %d %d\n", x, xIndex, xBin, y, yIndex, yBin);
|
|
|
|
if( xIndex < 0 || xBin < xIndex || yIndex < 0 || yBin < yIndex ) return;
|
|
|
|
double value = colorMap->data()->cell(xIndex, yIndex);
|
|
|
|
colorMap->data()->setCell(xIndex, yIndex, value + 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
double xMin, xMax, yMin, yMax;
|
|
|
|
int xBin, yBin;
|
|
|
|
|
|
|
|
QCPColorMap * colorMap;
|
|
|
|
QCPColorScale *colorScale;
|
|
|
|
|
2023-06-02 15:41:26 -04:00
|
|
|
bool usingMenu;
|
|
|
|
|
2023-05-31 17:30:46 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|