remove the old Histogram using QChart, move HistogramXD to a new file
This commit is contained in:
parent
c342f7c8e6
commit
69d25facb8
|
@ -58,30 +58,25 @@ Canvas::Canvas(Digitizer ** digi, unsigned int nDigi, QMainWindow * parent) : QM
|
||||||
double nBin = 100;
|
double nBin = 100;
|
||||||
|
|
||||||
for( unsigned int i = 0; i < MaxNDigitizer; i++){
|
for( unsigned int i = 0; i < MaxNDigitizer; i++){
|
||||||
for( int j = 0; j < MaxNChannels; j++){
|
for( int j = 0; j < digi[i]->GetNChannels(); j++){
|
||||||
if( i < nDigi ) {
|
if( i < nDigi ) {
|
||||||
hist[i][j] = new Histogram("Digi-" + QString::number(digi[i]->GetSerialNumber()) +", Ch-" + QString::number(j), xMin, xMax, nBin);
|
hist[i][j] = new Histogram1D("Digi-" + QString::number(digi[i]->GetSerialNumber()) +", Ch-" + QString::number(j), "Raw Energy [ch]", nBin, xMin, xMax);
|
||||||
histView[i][j] = new RChartView(hist[i][j]->GetChart());
|
|
||||||
histView[i][j]->SetVRange(0, 10);
|
|
||||||
}else{
|
}else{
|
||||||
hist[i][j] = nullptr;
|
hist[i][j] = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
histLayout->addWidget(histView[0][0], 0, 0);
|
histLayout->addWidget(hist[0][0], 0, 0);
|
||||||
oldBd = -1;
|
oldBd = -1;
|
||||||
oldCh = -1;
|
oldCh = -1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Canvas::~Canvas(){
|
Canvas::~Canvas(){
|
||||||
for( int i = 0; i < MaxNDigitizer; i++){
|
for( unsigned int i = 0; i < nDigi; i++ ){
|
||||||
for( int j = 0; j < MaxNChannels; j++){
|
for( int ch = 0; ch < digi[i]->GetNChannels(); ch++){
|
||||||
if( hist[i][j] ) {
|
delete hist[i][ch];
|
||||||
delete hist[i][j];
|
|
||||||
delete histView[i][j];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,13 +84,13 @@ Canvas::~Canvas(){
|
||||||
void Canvas::ChangeHistView(){
|
void Canvas::ChangeHistView(){
|
||||||
|
|
||||||
if( oldCh >= 0 ) {
|
if( oldCh >= 0 ) {
|
||||||
histLayout->removeWidget(histView[oldBd][oldCh]);
|
histLayout->removeWidget(hist[oldBd][oldCh]);
|
||||||
histView[oldBd][oldCh]->setParent(nullptr);
|
hist[oldBd][oldCh]->setParent(nullptr);
|
||||||
}
|
}
|
||||||
int bd = cbDigi->currentIndex();
|
int bd = cbDigi->currentIndex();
|
||||||
int ch = cbCh->currentIndex();
|
int ch = cbCh->currentIndex();
|
||||||
|
|
||||||
histLayout->addWidget(histView[bd][ch], 0, 0);
|
histLayout->addWidget(hist[bd][ch], 0, 0);
|
||||||
|
|
||||||
oldBd = bd;
|
oldBd = bd;
|
||||||
oldCh = ch;
|
oldCh = ch;
|
||||||
|
@ -110,9 +105,14 @@ void Canvas::UpdateCanvas(){
|
||||||
int lastIndex = digi[i]->GetData()->DataIndex[ch];
|
int lastIndex = digi[i]->GetData()->DataIndex[ch];
|
||||||
int nDecoded = digi[i]->GetData()->NumEventsDecoded[ch];
|
int nDecoded = digi[i]->GetData()->NumEventsDecoded[ch];
|
||||||
|
|
||||||
|
if( nDecoded == 0 ) continue;
|
||||||
|
|
||||||
for( int j = lastIndex - nDecoded + 1; j <= lastIndex; j ++){
|
for( int j = lastIndex - nDecoded + 1; j <= lastIndex; j ++){
|
||||||
hist[i][ch]->Fill( digi[i]->GetData()->Energy[ch][j]);
|
hist[i][ch]->Fill( digi[i]->GetData()->Energy[ch][j]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hist[i][ch]->UpdatePlot();
|
||||||
|
|
||||||
}
|
}
|
||||||
digiMTX[i].unlock();
|
digiMTX[i].unlock();
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "ClassDigitizer.h"
|
#include "ClassDigitizer.h"
|
||||||
#include "CustomThreads.h"
|
#include "CustomThreads.h"
|
||||||
#include "CustomWidgets.h"
|
#include "CustomWidgets.h"
|
||||||
|
#include "CustomHistogram.h"
|
||||||
|
|
||||||
|
|
||||||
//^====================================================
|
//^====================================================
|
||||||
|
@ -35,8 +36,7 @@ private:
|
||||||
Digitizer ** digi;
|
Digitizer ** digi;
|
||||||
unsigned short nDigi;
|
unsigned short nDigi;
|
||||||
|
|
||||||
Histogram * hist[MaxNDigitizer][MaxNChannels];
|
Histogram1D * hist[MaxNDigitizer][MaxNChannels];
|
||||||
RChartView * histView[MaxNDigitizer][MaxNChannels];
|
|
||||||
|
|
||||||
RComboBox * cbDivision;
|
RComboBox * cbDivision;
|
||||||
|
|
||||||
|
|
|
@ -347,8 +347,7 @@ int Digitizer::ProgramPSDBoard(){
|
||||||
//ret = CAEN_DGTZ_Reset(handle);
|
//ret = CAEN_DGTZ_Reset(handle);
|
||||||
Reset();
|
Reset();
|
||||||
|
|
||||||
ret = CAEN_DGTZ_WriteRegister(handle, DPP::RecordLength_G + 0x7000, 62);
|
ret = CAEN_DGTZ_WriteRegister(handle, DPP::BoardConfiguration, 0x0F0115); /// has Extra2, dual trace, input and CFD
|
||||||
ret = CAEN_DGTZ_WriteRegister(handle, DPP::BoardConfiguration, 0x0F3911); /// has Extra2, dual trace, input and CFD
|
|
||||||
|
|
||||||
ret = CAEN_DGTZ_SetAcquisitionMode(handle, CAEN_DGTZ_SW_CONTROLLED); /// software command
|
ret = CAEN_DGTZ_SetAcquisitionMode(handle, CAEN_DGTZ_SW_CONTROLLED); /// software command
|
||||||
ret |= CAEN_DGTZ_SetIOLevel(handle, CAEN_DGTZ_IOLevel_NIM);
|
ret |= CAEN_DGTZ_SetIOLevel(handle, CAEN_DGTZ_IOLevel_NIM);
|
||||||
|
@ -358,12 +357,12 @@ int Digitizer::ProgramPSDBoard(){
|
||||||
|
|
||||||
ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::ChannelDCOffset) + 0x7000 , 0xEEEE );
|
ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::ChannelDCOffset) + 0x7000 , 0xEEEE );
|
||||||
|
|
||||||
ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::PreTrigger) + 0x7000 , 32 );
|
ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::PreTrigger) + 0x7000 , 20 );
|
||||||
ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::RecordLength_G) + 0x7000 , 128 );
|
ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::RecordLength_G) + 0x7000 , 80 );
|
||||||
|
|
||||||
ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::PSD::ShortGateWidth) + 0x7000 , 10 );
|
ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::PSD::ShortGateWidth) + 0x7000 , 32 );
|
||||||
ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::PSD::LongGateWidth) + 0x7000 , 30 );
|
ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::PSD::LongGateWidth) + 0x7000 , 64 );
|
||||||
ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::PSD::GateOffset) + 0x7000 , 3 );
|
ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::PSD::GateOffset) + 0x7000 , 19 );
|
||||||
|
|
||||||
if( ret != 0 ) { printf("==== set channels error.\n"); return 0;}
|
if( ret != 0 ) { printf("==== set channels error.\n"); return 0;}
|
||||||
|
|
||||||
|
|
228
CustomHistogram.h
Normal file
228
CustomHistogram.h
Normal file
|
@ -0,0 +1,228 @@
|
||||||
|
#ifndef CUSTOM_HIST_H
|
||||||
|
#define CUSTOM_HIST_H
|
||||||
|
|
||||||
|
#include "qcustomplot.h"
|
||||||
|
|
||||||
|
//^==============================================
|
||||||
|
//^==============================================
|
||||||
|
class Histogram1D : public QCustomPlot{
|
||||||
|
public:
|
||||||
|
Histogram1D(QString title, QString xLabel, int xBin, double xMin, double xMax, QWidget * parent = nullptr) : QCustomPlot(parent){
|
||||||
|
Rebin(xBin, xMin, xMax);
|
||||||
|
|
||||||
|
xAxis->setLabel(xLabel);
|
||||||
|
|
||||||
|
legend->setVisible(true);
|
||||||
|
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);
|
||||||
|
setInteractions( QCP::iRangeZoom );
|
||||||
|
|
||||||
|
rescaleAxes();
|
||||||
|
yAxis->setRangeLower(0);
|
||||||
|
yAxis->setRangeUpper(10);
|
||||||
|
|
||||||
|
connect(this, &QCustomPlot::mouseMove, this, [=](QMouseEvent *event){
|
||||||
|
double x = this->xAxis->pixelToCoord(event->pos().x());
|
||||||
|
int bin = (x - xMin)/dX;
|
||||||
|
double z = yList[2*qFloor(bin) + 1];
|
||||||
|
|
||||||
|
QString coordinates = QString("Bin: %1, Value: %2").arg(bin).arg(z);
|
||||||
|
QToolTip::showText(event->globalPosition().toPoint(), coordinates, this);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(this, &QCustomPlot::mousePress, this, [=](QMouseEvent * event){
|
||||||
|
if (event->button() == Qt::RightButton) {
|
||||||
|
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(0);
|
||||||
|
xAxis->setRangeUpper(xMax);
|
||||||
|
yAxis->setRangeLower(0);
|
||||||
|
yAxis->setRangeUpper(yMax * 1.2);
|
||||||
|
replot();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdatePlot(){
|
||||||
|
graph(0)->setData(xList, yList);
|
||||||
|
xAxis->setRangeLower(0);
|
||||||
|
xAxis->setRangeUpper(xMax);
|
||||||
|
yAxis->setRangeLower(0);
|
||||||
|
yAxis->setRangeUpper(yMax * 1.2 > 10 ? yMax * 1.2 : 10);
|
||||||
|
replot();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear(){
|
||||||
|
for( int i = 0; i <= xBin; i++) yList[i] = 0;
|
||||||
|
graph(0)->setData(xList, yList);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Rebin(int xBin, double xMin, double xMax){
|
||||||
|
this->xMin = xMin;
|
||||||
|
this->xMax = xMax;
|
||||||
|
this->xBin = xBin;
|
||||||
|
|
||||||
|
dX = (xMax - xMin)/(xBin);
|
||||||
|
|
||||||
|
xList.clear();
|
||||||
|
yList.clear();
|
||||||
|
|
||||||
|
for( int i = 0; i <= xBin; i ++ ){
|
||||||
|
xList.append(i*dX-(dX)*0.000001);
|
||||||
|
xList.append(i*dX);
|
||||||
|
yList.append(0);
|
||||||
|
yList.append(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
yMax = 0;
|
||||||
|
|
||||||
|
totalEntry = 0;
|
||||||
|
underFlow = 0;
|
||||||
|
overFlow = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Fill(double value){
|
||||||
|
|
||||||
|
totalEntry ++;
|
||||||
|
if( value < xMin ) underFlow ++;
|
||||||
|
if( value > xMax ) overFlow ++;
|
||||||
|
|
||||||
|
double bin = (value - xMin)/dX;
|
||||||
|
int index1 = 2*qFloor(bin) + 1;
|
||||||
|
int index2 = index1 + 1;
|
||||||
|
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;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//^==============================================
|
||||||
|
//^==============================================
|
||||||
|
class Histogram2D : public QCustomPlot{
|
||||||
|
public:
|
||||||
|
Histogram2D(QString title, QString xLabel, QString yLabel, int xBin, double xMin, double xMax, int yBin, double yMin, double yMax, QWidget * parent = nullptr) : QCustomPlot(parent){
|
||||||
|
this->xMin = xMin;
|
||||||
|
this->xMax = xMax;
|
||||||
|
this->yMin = yMin;
|
||||||
|
this->yMax = yMax;
|
||||||
|
this->xBin = xBin;
|
||||||
|
this->yBin = yBin;
|
||||||
|
|
||||||
|
axisRect()->setupFullAxesBox(true);
|
||||||
|
xAxis->setLabel(xLabel);
|
||||||
|
yAxis->setLabel(yLabel);
|
||||||
|
|
||||||
|
colorMap = new QCPColorMap(this->xAxis, this->yAxis);
|
||||||
|
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();
|
||||||
|
|
||||||
|
connect(this, &QCustomPlot::mouseMove, this, [=](QMouseEvent *event){
|
||||||
|
double x = this->xAxis->pixelToCoord(event->pos().x());
|
||||||
|
double y = this->yAxis->pixelToCoord(event->pos().y());
|
||||||
|
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);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdatePlot(){
|
||||||
|
// rescale the data dimension (color) such that all data points lie in the span visualized by the color gradient:
|
||||||
|
colorMap->rescaleDataRange();
|
||||||
|
|
||||||
|
// make sure the axis rect and color scale synchronize their bottom and top margins (so they line up):
|
||||||
|
// QCPMarginGroup *marginGroup = new QCPMarginGroup(this);
|
||||||
|
// this->axisRect()->setMarginGroup(QCP::msBottom|QCP::msTop, marginGroup);
|
||||||
|
// colorScale->setMarginGroup(QCP::msBottom|QCP::msTop, marginGroup);
|
||||||
|
|
||||||
|
// rescale the key (x) and value (y) axes so the whole color map is visible:
|
||||||
|
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;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
105
CustomWidgets.h
105
CustomWidgets.h
|
@ -179,109 +179,4 @@ private:
|
||||||
QLabel * m_coordinateLabel;
|
QLabel * m_coordinateLabel;
|
||||||
};
|
};
|
||||||
|
|
||||||
//^====================================================
|
|
||||||
class Histogram {
|
|
||||||
public:
|
|
||||||
Histogram(QString title, double xMin, double xMax, int nBin){
|
|
||||||
|
|
||||||
plot = new RChart();
|
|
||||||
dataSeries = new QLineSeries();
|
|
||||||
|
|
||||||
Rebin(xMin, xMax, nBin);
|
|
||||||
|
|
||||||
maxBin = -1;
|
|
||||||
maxBinValue = 0;
|
|
||||||
|
|
||||||
//dataSeries->setPen(QPen(Qt::blue, 1));
|
|
||||||
areaSeries = new QAreaSeries(dataSeries);
|
|
||||||
areaSeries->setName(title);
|
|
||||||
areaSeries->setBrush(Qt::blue);
|
|
||||||
|
|
||||||
plot->addSeries(areaSeries);
|
|
||||||
|
|
||||||
plot->setAnimationDuration(1); // msec
|
|
||||||
plot->setAnimationOptions(QChart::NoAnimation);
|
|
||||||
plot->createDefaultAxes();
|
|
||||||
|
|
||||||
QValueAxis * xaxis = qobject_cast<QValueAxis*> (plot->axes(Qt::Horizontal).first());
|
|
||||||
xaxis->setRange(xMin, xMax);
|
|
||||||
xaxis->setTickCount( nBin + 1 > 11 ? 11 : nBin + 1);
|
|
||||||
//xaxis->setLabelFormat("%.1f");
|
|
||||||
//xaxis->setTitleText("Time [ns]");
|
|
||||||
|
|
||||||
QValueAxis * yaxis = qobject_cast<QValueAxis*> (plot->axes(Qt::Vertical).first());
|
|
||||||
yaxis->setRange(0, 10);
|
|
||||||
|
|
||||||
}
|
|
||||||
~Histogram(){
|
|
||||||
delete areaSeries;
|
|
||||||
delete dataSeries;
|
|
||||||
delete plot;
|
|
||||||
}
|
|
||||||
|
|
||||||
RChart * GetChart() { return plot;}
|
|
||||||
|
|
||||||
void Clear(){
|
|
||||||
for( int i = 0; i <= nBin; i++) {
|
|
||||||
dataSeries->replace(2*i, xMin + i * dX, 0);
|
|
||||||
dataSeries->replace(2*i+1, xMin + i * dX, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetColor(Qt::GlobalColor color){ areaSeries->setBrush(color);}
|
|
||||||
|
|
||||||
void Rebin(double xMin, double xMax, int nBin){
|
|
||||||
dataSeries->clear();
|
|
||||||
this->xMin = xMin;
|
|
||||||
this->xMax = xMax;
|
|
||||||
this->nBin = nBin;
|
|
||||||
dX = (xMax-xMin)/nBin;
|
|
||||||
for( int i = 0; i <= nBin; i++) {
|
|
||||||
dataSeries->append(xMin + i * dX, 0 );
|
|
||||||
dataSeries->append(xMin + i * dX, 0 );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fill(double value){
|
|
||||||
|
|
||||||
double bin = (value - xMin)/dX;
|
|
||||||
if( bin < 0 || bin >= nBin ) return;
|
|
||||||
|
|
||||||
int index1 = 2*qFloor(bin) + 1;
|
|
||||||
int index2 = index1 + 1;
|
|
||||||
|
|
||||||
QPointF point1 = dataSeries->at(index1);
|
|
||||||
dataSeries->replace(index1, point1.x(), point1.y() + 1);
|
|
||||||
|
|
||||||
QPointF point2 = dataSeries->at(index2);
|
|
||||||
dataSeries->replace(index2, point2.x(), point2.y() + 1);
|
|
||||||
|
|
||||||
if( point2.y() + 1 > maxBinValue ){
|
|
||||||
maxBinValue = point2.y() + 1;
|
|
||||||
maxBin = index2/2;
|
|
||||||
}
|
|
||||||
|
|
||||||
QValueAxis * yaxis = qobject_cast<QValueAxis*> (plot->axes(Qt::Vertical).first());
|
|
||||||
yaxis->setRange(0, maxBinValue < 10 ? 10 : ((double)maxBinValue) * 1.2 );
|
|
||||||
//yaxis->setTickInterval(1);
|
|
||||||
//yaxis->setTickCount(10);
|
|
||||||
//yaxis->setLabelFormat("%.0f");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
RChart * plot;
|
|
||||||
QLineSeries * dataSeries;
|
|
||||||
QAreaSeries * areaSeries;
|
|
||||||
|
|
||||||
double dX, xMin, xMax;
|
|
||||||
int nBin;
|
|
||||||
|
|
||||||
int maxBin;
|
|
||||||
int maxBinValue;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
//^====================================================
|
|
||||||
|
|
||||||
#endif
|
#endif
|
|
@ -26,6 +26,7 @@ HEADERS += ClassData.h \
|
||||||
ClassDigitizer.h \
|
ClassDigitizer.h \
|
||||||
CustomThreads.h \
|
CustomThreads.h \
|
||||||
CustomWidgets.h \
|
CustomWidgets.h \
|
||||||
|
CustomHistogram.h \
|
||||||
DigiSettingsPanel.h \
|
DigiSettingsPanel.h \
|
||||||
FSUDAQ.h \
|
FSUDAQ.h \
|
||||||
macro.h \
|
macro.h \
|
||||||
|
|
|
@ -51,33 +51,37 @@ void OnlineAnalyzer::StopThread(){
|
||||||
|
|
||||||
void OnlineAnalyzer::SetUpCanvas(){
|
void OnlineAnalyzer::SetUpCanvas(){
|
||||||
|
|
||||||
h2 = new Histogram2D("testing", "x", "y", 100, 0, 4000, 100, 0, 4000, this);
|
h2 = new Histogram2D("testing", "x", "y", 400, 0, 4000, 400, 0, 4000, this);
|
||||||
layout->addWidget(h2);
|
layout->addWidget(h2);
|
||||||
|
|
||||||
|
h1 = new Histogram1D("testing", "x", 400, 0, 4000, this);
|
||||||
|
layout->addWidget(h1);
|
||||||
|
|
||||||
|
|
||||||
//Histogram * h1 = new Histogram("h1", 0, 5000, 200);
|
//Histogram * h1 = new Histogram("h1", 0, 5000, 200);
|
||||||
|
|
||||||
|
|
||||||
std::random_device rd;
|
std::random_device rd;
|
||||||
std::mt19937 gen(rd());
|
std::mt19937 gen(rd());
|
||||||
std::normal_distribution<double> distribution(2000.0, 500);
|
std::normal_distribution<double> distribution(2000.0, 1000);
|
||||||
for( int i = 0; i < 1000 ; i++ ){
|
for( int i = 0; i < 1000 ; i++ ){
|
||||||
h2->Fill(distribution(gen), distribution(gen));
|
//h2->Fill(distribution(gen), distribution(gen));
|
||||||
|
h1->Fill(distribution(gen));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h1->UpdatePlot();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnlineAnalyzer::UpdateHistograms(){
|
void OnlineAnalyzer::UpdateHistograms(){
|
||||||
|
|
||||||
//Set with digitizer to be event build
|
//Set with digitizer to be event build
|
||||||
digiMTX[0].lock();
|
digiMTX[0].lock();
|
||||||
//digi[0]->GetData()->PrintAllData();
|
|
||||||
oeb[0]->BuildEvents(100, false);
|
oeb[0]->BuildEvents(100, false);
|
||||||
digiMTX[0].unlock();
|
digiMTX[0].unlock();
|
||||||
|
|
||||||
//============ Get events, and do analysis
|
//============ Get events, and do analysis
|
||||||
long eventBuilt = oeb[0]->eventbuilt;
|
long eventBuilt = oeb[0]->eventbuilt;
|
||||||
printf("------------- eventBuilt %ld \n", eventBuilt);
|
|
||||||
if( eventBuilt == 0 ) return;
|
if( eventBuilt == 0 ) return;
|
||||||
|
|
||||||
long eventIndex = oeb[0]->eventIndex;
|
long eventIndex = oeb[0]->eventIndex;
|
||||||
|
@ -87,7 +91,6 @@ void OnlineAnalyzer::UpdateHistograms(){
|
||||||
|
|
||||||
unsigned short e1 = 0, e2 = 0;
|
unsigned short e1 = 0, e2 = 0;
|
||||||
|
|
||||||
int count = 0;
|
|
||||||
for( long i = eventStart ; i <= eventIndex; i ++ ){
|
for( long i = eventStart ; i <= eventIndex; i ++ ){
|
||||||
std::vector<dataPoint> event = oeb[0]->events[i];
|
std::vector<dataPoint> event = oeb[0]->events[i];
|
||||||
|
|
||||||
|
@ -97,8 +100,10 @@ void OnlineAnalyzer::UpdateHistograms(){
|
||||||
}
|
}
|
||||||
|
|
||||||
h2->Fill(e1, e2);
|
h2->Fill(e1, e2);
|
||||||
count ++;
|
|
||||||
if( count > 500 ) break;
|
//h1->Fill(e1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h2->UpdatePlot();
|
||||||
|
|
||||||
}
|
}
|
106
OnlineAnalyser.h
106
OnlineAnalyser.h
|
@ -28,110 +28,7 @@ This is the mother of all other derivative analysis class.
|
||||||
derivative class should define the SetUpCanvas() and UpdateHistogram();
|
derivative class should define the SetUpCanvas() and UpdateHistogram();
|
||||||
|
|
||||||
***************************************/
|
***************************************/
|
||||||
|
#include "CustomHistogram.h"
|
||||||
#include "qcustomplot.h"
|
|
||||||
|
|
||||||
//^==============================================
|
|
||||||
//^==============================================
|
|
||||||
class Histogram1D : public QCustomPlot{
|
|
||||||
public:
|
|
||||||
Histogram1D(QString title, QString xLabel, int xBin, double xMin, double xMax, QWidget * parent = nullptr) : QCustomPlot(parent){
|
|
||||||
this->xMin = xMin;
|
|
||||||
this->xMax = xMax;
|
|
||||||
this->xBin = xBin;
|
|
||||||
|
|
||||||
this->xAxis->setLabel(xLabel);
|
|
||||||
|
|
||||||
bars = new QCPBars(this->xAxis, this->yAxis);
|
|
||||||
bars->setWidth((xMax- xMin)/xBin);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
double xMin, xMax, xBin;
|
|
||||||
|
|
||||||
QCPBars *bars;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
//^==============================================
|
|
||||||
//^==============================================
|
|
||||||
class Histogram2D : public QCustomPlot{
|
|
||||||
public:
|
|
||||||
Histogram2D(QString title, QString xLabel, QString yLabel, int xBin, double xMin, double xMax, int yBin, double yMin, double yMax, QWidget * parent = nullptr) : QCustomPlot(parent){
|
|
||||||
this->xMin = xMin;
|
|
||||||
this->xMax = xMax;
|
|
||||||
this->yMin = yMin;
|
|
||||||
this->yMax = yMax;
|
|
||||||
this->xBin = xBin;
|
|
||||||
this->yBin = yBin;
|
|
||||||
|
|
||||||
axisRect()->setupFullAxesBox(true);
|
|
||||||
this->xAxis->setLabel(xLabel);
|
|
||||||
this->yAxis->setLabel(yLabel);
|
|
||||||
|
|
||||||
colorMap = new QCPColorMap(this->xAxis, this->yAxis);
|
|
||||||
colorMap->data()->setSize(xBin, yBin);
|
|
||||||
colorMap->data()->setRange(QCPRange(xMin, xMax), QCPRange(yMin, yMax));
|
|
||||||
colorMap->setInterpolate(false);
|
|
||||||
|
|
||||||
colorScale = new QCPColorScale(this);
|
|
||||||
this->plotLayout()->addElement(0, 1, colorScale);
|
|
||||||
colorScale->setType(QCPAxis::atRight);
|
|
||||||
colorMap->setColorScale(colorScale);
|
|
||||||
|
|
||||||
QCPColorGradient color;
|
|
||||||
color.clearColorStops();
|
|
||||||
color.setColorStopAt( 0, QColor("white" ));
|
|
||||||
color.setColorStopAt( 1, QColor("blue"));
|
|
||||||
colorMap->setGradient(color);
|
|
||||||
|
|
||||||
this->rescaleAxes();
|
|
||||||
|
|
||||||
connect(this, &QCustomPlot::mouseMove, this, [=](QMouseEvent *event){
|
|
||||||
double x = this->xAxis->pixelToCoord(event->pos().x());
|
|
||||||
double y = this->yAxis->pixelToCoord(event->pos().y());
|
|
||||||
int xI, yI;
|
|
||||||
colorMap->data()->coordToCell(x, y, &xI, &yI);
|
|
||||||
double z = colorMap->data()->cell(xI, yI);
|
|
||||||
|
|
||||||
// Format the coordinates as desired
|
|
||||||
QString coordinates = QString("X: %1, Y: %2, Z: %3").arg(x).arg(y).arg(z);
|
|
||||||
|
|
||||||
// Show the coordinates as a tooltip
|
|
||||||
QToolTip::showText(event->globalPosition().toPoint(), coordinates, this);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void Fill(double x, double y){
|
|
||||||
int xIndex, yIndex;
|
|
||||||
colorMap->data()->coordToCell(x, y, &xIndex, &yIndex);
|
|
||||||
//printf("%d %d\n", xIndex, yIndex);
|
|
||||||
if( xIndex < 0 || xBin < xIndex || yIndex < 0 || yBin < yIndex ) return;
|
|
||||||
double value = colorMap->data()->cell(xIndex, yIndex);
|
|
||||||
colorMap->data()->setCell(xIndex, yIndex, value + 1);
|
|
||||||
|
|
||||||
// rescale the data dimension (color) such that all data points lie in the span visualized by the color gradient:
|
|
||||||
colorMap->rescaleDataRange();
|
|
||||||
|
|
||||||
// make sure the axis rect and color scale synchronize their bottom and top margins (so they line up):
|
|
||||||
// QCPMarginGroup *marginGroup = new QCPMarginGroup(this);
|
|
||||||
// this->axisRect()->setMarginGroup(QCP::msBottom|QCP::msTop, marginGroup);
|
|
||||||
// colorScale->setMarginGroup(QCP::msBottom|QCP::msTop, marginGroup);
|
|
||||||
|
|
||||||
// rescale the key (x) and value (y) axes so the whole color map is visible:
|
|
||||||
this->rescaleAxes();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
double xMin, xMax, yMin, yMax;
|
|
||||||
int xBin, yBin;
|
|
||||||
|
|
||||||
QCPColorMap * colorMap;
|
|
||||||
QCPColorScale *colorScale;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
//^==============================================
|
//^==============================================
|
||||||
//^==============================================
|
//^==============================================
|
||||||
|
@ -164,6 +61,7 @@ private:
|
||||||
|
|
||||||
//======================== custom histograms
|
//======================== custom histograms
|
||||||
Histogram2D * h2;
|
Histogram2D * h2;
|
||||||
|
Histogram1D * h1;
|
||||||
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
|
@ -57,7 +57,6 @@ void OnlineEventBuilder::FindEarlistTimeAndCh(){
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnlineEventBuilder::FindLatestTime(){
|
void OnlineEventBuilder::FindLatestTime(){
|
||||||
|
|
||||||
latestTime = 0;
|
latestTime = 0;
|
||||||
for( unsigned ch = 0; ch < nCh; ch++ ){
|
for( unsigned ch = 0; ch < nCh; ch++ ){
|
||||||
int index = data->DataIndex[ch];
|
int index = data->DataIndex[ch];
|
||||||
|
@ -66,8 +65,7 @@ void OnlineEventBuilder::FindLatestTime(){
|
||||||
latestTime = data->Timestamp[ch][index];
|
latestTime = data->Timestamp[ch][index];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//printf("--- latest time %lld \n", latestTime);
|
||||||
printf("--- latest time %lld \n", latestTime);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnlineEventBuilder::BuildEvents(unsigned short timeWindow, bool verbose){
|
void OnlineEventBuilder::BuildEvents(unsigned short timeWindow, bool verbose){
|
||||||
|
|
49
README.md
49
README.md
|
@ -2,23 +2,36 @@
|
||||||
|
|
||||||
This is a DAQ for 1st gen CAEN digitizer for V1725, V17255S, V1230 with PHA and PSD firmware.
|
This is a DAQ for 1st gen CAEN digitizer for V1725, V17255S, V1230 with PHA and PSD firmware.
|
||||||
|
|
||||||
It has scope (updated every half-sec), allow full control of the digitizer (except LVDS), and allow saving waevform.
|
It has scope (updated every half-sec), allow full control of the digitizer (except LVDS), and allow saving waveform.
|
||||||
|
|
||||||
It can be connected to InfluxDB v1.8 and Elog.
|
It can be connected to InfluxDB v1.8 and Elog.
|
||||||
|
|
||||||
|
# Undergoing
|
||||||
|
|
||||||
|
the following additional functions are planned and I am working on them
|
||||||
|
|
||||||
|
- 1-D and 2-D histogram
|
||||||
|
- Online Analyzer
|
||||||
|
- support V1740 DPP-QDC
|
||||||
|
- synchronization helper
|
||||||
|
|
||||||
# Required / Development enviroment
|
# Required / Development enviroment
|
||||||
|
|
||||||
Ubuntu 22.04
|
Ubuntu 22.04
|
||||||
|
|
||||||
CAENVMELib_v3.3
|
- CAENVMELib_v3.3
|
||||||
|
- CAENCOmm_v1.5.3
|
||||||
|
- CAENDigitizer_v2.17.1
|
||||||
|
- CAEN A3818 Driver
|
||||||
|
|
||||||
CAENCOmm_v1.5.3
|
- qt6-base-dev
|
||||||
|
- libqt6charts6-dec
|
||||||
|
- libcurl4-openssl-dev
|
||||||
|
- elog
|
||||||
|
|
||||||
CAENDigitizer_v2.17.1
|
The CAEN Libraries need to download and install manually. The other libraries can be installed using the following command:
|
||||||
|
|
||||||
CAEN A3818 Driver
|
`sudo apt install qt6-base-dev libqt6charts6-dev libcurl4-openssl-dev elog`
|
||||||
|
|
||||||
`sudo apt install qt6-base-dev libcurl4-openssl-dev libqt6charts6-dev qt6-webengine-dev elog`
|
|
||||||
|
|
||||||
The elog installed using apt is 3.1.3. If a higher version is needed. Please go to https://elog.psi.ch/elog/
|
The elog installed using apt is 3.1.3. If a higher version is needed. Please go to https://elog.psi.ch/elog/
|
||||||
|
|
||||||
|
@ -32,10 +45,28 @@ use `qmake6 -project ` to generate the *.pro
|
||||||
|
|
||||||
in the *.pro, add
|
in the *.pro, add
|
||||||
|
|
||||||
` QT += core widgets charts`
|
` QT += core widgets charts printsupport`
|
||||||
|
|
||||||
` LIBS += -lCAENDigitizer -lcurl`
|
` LIBS += -lCAENDigitizer -lcurl`
|
||||||
|
|
||||||
then run ` qmake6 *.pro` it will generate Makefile
|
then run ` qmake6 *.pro` it will generate Makefile
|
||||||
|
|
||||||
then ` make`
|
then ` make`
|
||||||
|
|
||||||
|
if you want to use GDB debugger, in the *.pro file add
|
||||||
|
|
||||||
|
` QMAKE_CXXFLAGS += -g`
|
||||||
|
|
||||||
|
## exclude some files from the auto-gen *.pro
|
||||||
|
|
||||||
|
The following files must be excluded from the *.pro, as they are not related to the GUI
|
||||||
|
|
||||||
|
- DataGenerator.cpp
|
||||||
|
- DataReaderScript.cpp
|
||||||
|
- EventBuilder.cpp
|
||||||
|
- test.cpp
|
||||||
|
- test_indep.cpp
|
||||||
|
|
||||||
|
Those file can be compiled using
|
||||||
|
|
||||||
|
`make -f Makefile_test`
|
Loading…
Reference in New Issue
Block a user