Histogram2D.h add save/load graphic cuts into/from txt file

This commit is contained in:
Ryan Tang 2024-06-27 16:51:31 -04:00
parent 839b3d2a58
commit c8e032390a

View File

@ -19,7 +19,82 @@ const QList<QPair<QColor, QString>> colorCycle = { {QColor(Qt::red), "Red"},
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){
Histogram2D(QString title, QString xLabel, QString yLabel, int xbin, double xmin, double xmax, int ybin, double ymin, double ymax, QWidget * parent = nullptr);
void SetXTitle(QString xTitle) { xAxis->setLabel(xTitle);}
void SetYTitle(QString yTitle) { yAxis->setLabel(yTitle);}
void Rebin(int xbin, double xmin, double xmax, int ybin, double ymin, double ymax);
void RebinY(int ybin, double ymin, double ymax);
void SetChannelMap(bool onOff, int tickStep = 1) { isChannelMap = onOff; this->tickStep = tickStep;}
void UpdatePlot(){ colorMap->rescaleDataRange(); replot(); }
void Clear(); // Clear Data and histrogram
void Fill(double x, double y);
void DrawCut();
void ClearAllCuts();
QList<QPolygonF> GetCutList() const{return cutList;} // this list may contain empty element
QList<int> GetCutEntryList() const{ return cutEntryList;}
QList<QString> GetCutNameList() const { return cutNameList;}
void PrintCutEntry() const;
double GetXNBin() const {return xBin;}
double GetXMin() const {return xMin;}
double GetXMax() const {return xMax;}
double GetYNBin() const {return yBin;}
double GetYMin() const {return yMin;}
double GetYMax() const {return yMax;}
void SaveCuts(QString cutFileName);
void LoadCuts(QString cutFileName);
private:
double xMin, xMax, yMin, yMax;
int xBin, yBin;
bool isChannelMap;
int tickStep;
bool isLogZ;
QCPColorMap * colorMap;
QCPColorScale *colorScale;
bool usingMenu;
int entry[3][3]; // overflow counter, entrt[1][1] is entry in the plot;
QCPItemRect * box[3][3];
QCPItemText * txt[3][3];
QPolygonF tempCut;
int tempCutID; // only incresing;
int numCut;
QList<QPolygonF> cutList;
QList<QString> cutNameList; // name of the cut
QList<int> cutEntryList; // number of entry inside the cut.
QList<int> cutIDList; // ID of the cut
QList<int> cutTextIDList; //
QList<int> plottableIDList;
bool isDrawCut;
int lastPlottableID;
QCPItemLine * line;
double oldMouseX = 0.0, oldMouseY = 0.0;
bool isBusy;
void rightMouseClickMenu(QMouseEvent * event);
void rightMouseClickRebin();
};
//^###############################################
//^###############################################
inline Histogram2D::Histogram2D(QString title, QString xLabel, QString yLabel, int xbin, double xmin, double xmax, int ybin, double ymin, double ymax, QWidget * parent) : QCustomPlot(parent){
// DebugPrint("%s", "Histogram2D");
for( int i = 0; i < 3; i ++ ){
for( int j = 0; j < 3; j ++ ){
@ -183,97 +258,9 @@ public:
connect(this, &QCustomPlot::mouseRelease, this, [=](){
});
}
}
//^===================================
void SetXTitle(QString xTitle) { xAxis->setLabel(xTitle);}
void SetYTitle(QString yTitle) { yAxis->setLabel(yTitle);}
void Rebin(int xbin, double xmin, double xmax, int ybin, double ymin, double ymax);
void RebinY(int ybin, double ymin, double ymax);
void SetChannelMap(bool onOff, int tickStep = 1) { isChannelMap = onOff; this->tickStep = tickStep;}
void UpdatePlot(){
// QCPColorGradient color;
// color.clearColorStops();
// color.setNanColor(QColor("white"));
// // color.setColorStopAt( 0.0, QColor("white" ));
// // color.setColorStopAt( 1.0/entry[1][1], QColor("purple" ));
// color.setColorStopAt( 0.0, QColor("purple" ));
// color.setColorStopAt( 0.2, QColor("blue"));
// color.setColorStopAt( 0.4, QColor("cyan"));
// color.setColorStopAt( 0.6, QColor("green"));
// color.setColorStopAt( 0.8, QColor("yellow"));
// color.setColorStopAt( 1.0, QColor("red"));
// colorMap->setGradient(color);
colorMap->rescaleDataRange();
replot();
}
void Clear(); // Clear Data and histrogram
void Fill(double x, double y);
void DrawCut();
void ClearAllCuts();
QList<QPolygonF> GetCutList() const{return cutList;} // this list may contain empty element
QList<int> GetCutEntryList() const{ return cutEntryList;}
QList<QString> GetCutNameList() const { return cutNameList;}
void PrintCutEntry() const;
double GetXNBin() const {return xBin;}
double GetXMin() const {return xMin;}
double GetXMax() const {return xMax;}
double GetYNBin() const {return yBin;}
double GetYMin() const {return yMin;}
double GetYMax() const {return yMax;}
private:
double xMin, xMax, yMin, yMax;
int xBin, yBin;
bool isChannelMap;
int tickStep;
bool isLogZ;
QCPColorMap * colorMap;
QCPColorScale *colorScale;
bool usingMenu;
int entry[3][3]; // overflow counter, entrt[1][1] is entry in the plot;
QCPItemRect * box[3][3];
QCPItemText * txt[3][3];
QPolygonF tempCut;
int tempCutID; // only incresing;
QList<QPolygonF> cutList;
QList<int> cutIDList;
int numCut;
bool isDrawCut;
int lastPlottableID;
QList<int> cutTextIDList;
QList<int> plottableIDList;
QList<QString> cutNameList;
QList<int> cutEntryList;
QCPItemLine * line;
double oldMouseX = 0.0, oldMouseY = 0.0;
bool isBusy;
void rightMouseClickMenu(QMouseEvent * event);
void rightMouseClickRebin();
};
//^###############################################
//^###############################################
inline void Histogram2D::Fill(double x, double y){
// DebugPrint("%s", "Histogram2D");
@ -391,7 +378,7 @@ inline void Histogram2D::ClearAllCuts(){
inline void Histogram2D::PrintCutEntry() const{
DebugPrint("%s", "Histogram2D");
if( numCut == 0 ) return;
printf("=============== There are %d cuts.\n", numCut);
printf("=============== There are %d cuts. (%lld, %lld)\n", numCut, cutList.count(), cutEntryList.count());
for( int i = 0; i < cutList.count(); i++){
if( cutList[i].isEmpty() ) continue;
printf("%10s | %d \n", cutNameList[i].toStdString().c_str(), cutEntryList[i]);
@ -423,7 +410,7 @@ inline void Histogram2D::DrawCut(){
}
replot();
//qDebug() << "Plottable count : " << plottableCount() << ", cutList.count :" << cutList.count() << ", cutID :" << lastPlottableID;
// qDebug() << "Plottable count : " << plottableCount() << ", cutList.count :" << cutList.count() << ", cutID :" << lastPlottableID;
}
inline void Histogram2D::rightMouseClickMenu(QMouseEvent * event){
@ -439,8 +426,11 @@ inline void Histogram2D::rightMouseClickMenu(QMouseEvent * event){
QAction * a2 = menu->addAction("Clear hist.");
QAction * a3 = menu->addAction("Toggle Stat.");
QAction * a4 = menu->addAction("Rebin (clear histogram)");
QAction * a8 = menu->addAction("Load Cut(s)");
QAction * a5 = menu->addAction("Create a Cut");
QAction * a7 = nullptr;
if( numCut > 0 ) {
a7 = menu->addAction("Save Cut(s)");
menu->addSeparator();
menu->addAction("Add/Edit names to Cuts");
menu->addAction("Clear all Cuts");
@ -575,6 +565,27 @@ inline void Histogram2D::rightMouseClickMenu(QMouseEvent * event){
return;
}
if( selectedAction == a8 ){ // load Cuts
QString filePath = QFileDialog::getOpenFileName(this,
"Load Cuts from File",
QDir::homePath(),
"Text file (*.txt)");
if (!filePath.isEmpty()) LoadCuts(filePath);
}
if( selectedAction == a7 ){ // Save Cuts
QString filePath = QFileDialog::getSaveFileName(this,
"Save Cuts to File",
QDir::homePath(),
"Text file (*.txt)");
if (!filePath.isEmpty()) SaveCuts(filePath);
}
}
@ -674,5 +685,113 @@ inline void Histogram2D::rightMouseClickRebin(){
}
inline void Histogram2D::SaveCuts(QString cutFileName){
QFile file(cutFileName);
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream out(&file);
// Define the text to write
QStringList lines;
for( int i = 0; i < cutList.size(); i++){
lines << "====== "+ cutNameList[i];
for( int pt = 0 ; pt < cutList[i].size(); pt ++){
lines << QString::number(cutList[i][pt].rx(), 'g', 5) + "," + QString::number(cutList[i][pt].ry(), 'g', 5);
}
}
lines << "#===== End of File";
// Write each line to the file
for (const QString &line : lines) out << line << "\n";
// Close the file
file.close();
qDebug() << "File written successfully to" << cutFileName;
}else{
qWarning() << "Unable to open file" << cutFileName;
}
}
inline void Histogram2D::LoadCuts(QString cutFileName){
QFile file(cutFileName);
QString cutNameTemp;
// Open the file in read mode
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream in(&file);
ClearAllCuts();
tempCut.clear();
// Read each line and append to the QStringList
while (!in.atEnd()) {
QString line = in.readLine();
if( line.contains("======") ){
if( !tempCut.isEmpty() ) {
DrawCut();
plottableIDList.push_back(plottableCount() -1 );
cutNameList.push_back(cutNameTemp);
cutEntryList.push_back(0);
QCPItemText * text = new QCPItemText(this);
text->setText(cutNameList.last());
text->position->setCoords(tempCut[0].rx(), tempCut[0].ry());
int colorID = tempCutID% colorCycle.count();
text->setColor(colorCycle[colorID].first);
cutTextIDList.push_back(itemCount() - 1);
// cutList.push_back(tempCut);
cutIDList.push_back(tempCutID);
}
tempCut.clear();
tempCutID ++;
numCut ++;
int spacePos = line.indexOf(' ');
cutNameTemp = line.mid(spacePos + 1);
continue;
}
if( line.contains("#==") ) {
DrawCut();
plottableIDList.push_back(plottableCount() -1 );
cutNameList.push_back(cutNameTemp);
cutEntryList.push_back(0);
QCPItemText * text = new QCPItemText(this);
text->setText(cutNameList.last());
text->position->setCoords(tempCut[0].rx(), tempCut[0].ry());
int colorID = tempCutID% colorCycle.count();
text->setColor(colorCycle[colorID].first);
cutTextIDList.push_back(itemCount() - 1);
cutList.push_back(tempCut);
cutIDList.push_back(tempCutID);
break;
}else{
QStringList haha = line.split(",");
// qDebug() << haha;
tempCut.push_back(QPointF(haha[0].toFloat(), haha[1].toFloat()));
DrawCut();
}
}
// Close the file
file.close();
qDebug() << "File read successfully from" << cutFileName;
// PrintCutEntry();
// DrawCut();
replot();
} else {
qWarning() << "Unable to open file" << cutFileName;
}
}
#endif