Skip to content
Snippets Groups Projects
MainWindow.cpp 8.78 KiB
Newer Older
  • Learn to ignore specific revisions
  • mingf2's avatar
    mingf2 committed
    #include "MainWindow.h"
    #include "ui_MainWindow.h"
    #include "TMath.h"
    #include "TString.h"
    //#include <iostream>
    //#include "TList.h"
    #include "TStyle.h"
    #include "TFile.h"
    #include "TTree.h"
    #include "TGraph.h"
    #include "TAxis.h"
    
    #include "qrootcanvas.h"
    #include <QVBoxLayout>
    #include <TSystem.h>
    #include <QTimer>
    #include <QDebug>
    #include <QWindow>
    
    #include <QFileDialog>
    #include <QDateTime>
    
    mingf2's avatar
    mingf2 committed
    #include <QMessageBox>
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        connect(ui->actionOpen, &QAction::triggered, this, &MainWindow::handleOpen);
        connect(ui->actionExit, &QAction::triggered, this, &MainWindow::handleClose);
        connect(ui->actionSave, &QAction::triggered, this, &MainWindow::handleSave);
        connect(ui->actionSave_As, &QAction::triggered, this, &MainWindow::handleSaveAs);
    
        connect(ui->actionScreenshot, &QAction::triggered, this, &MainWindow::handleScreenshot);
    
    mingf2's avatar
    mingf2 committed
        connect(ui->actionAbout, &QAction::triggered, this, &MainWindow::handleAbout);
    
        config = new Setup(Vector3D(SOURCE_X, SOURCE_Y, SOURCE_Z));
    
        image = new RecoImage(config);
        createGridlines();
        createCountsLabel();
    
    mingf2's avatar
    mingf2 committed
    
    
        // update image on worker thread
        workerThread = new Worker(this, config, image);
    
    mingf2's avatar
    mingf2 committed
        connect(workerThread, &Worker::finished, workerThread, &QObject::deleteLater);
        connect(workerThread, &Worker::finished, this, &MainWindow::notifyThreadFinished);
    
        connect(ui->actionStart, &QAction::triggered, workerThread, &Worker::handleStart);
        connect(ui->actionStop, &QAction::triggered, workerThread, &Worker::handleStop);
        connect(ui->actionClear, &QAction::triggered, workerThread, &Worker::handleClear);
    
    mingf2's avatar
    mingf2 committed
        connect(this, &MainWindow::threadStopped, workerThread, &Worker::stopExecution);
        workerThread->start();
    
    
        // update every 0.1 second
        QTimer *timer = new QTimer(this);
        connect(timer, &QTimer::timeout, this, QOverload<>::of(&MainWindow::redraw));
    
    mingf2's avatar
    mingf2 committed
        timer->start(1000);
    
    
        setWindowTitle(tr("Back projection"));
    
    mingf2's avatar
    mingf2 committed
        ui->canvas->Canvas()->Modified();
        ui->canvas->Canvas()->Update();
    
        ui->statusBar->showMessage("Ready.");
    
    mingf2's avatar
    mingf2 committed
    }
    
    void MainWindow::changeEvent(QEvent *e)
    {
        if(e->type() == QEvent::WindowStateChange){
            QWindowStateChangeEvent *event = static_cast<QWindowStateChangeEvent *>(e);
            if((event->oldState() & Qt::WindowMaximized)||
                    (event->oldState() & Qt::WindowMinimized)||
                    (event->oldState() & Qt::WindowNoState &&
                     this->windowState() == Qt::WindowMaximized)){
                if(ui->canvas->Canvas()){
                    ui->canvas->Canvas()->Resize();
                    ui->canvas->Canvas()->Update();
                }
            }
        }
    }
    
    void MainWindow::closeEvent (QCloseEvent *event)
    {
    
    mingf2's avatar
    mingf2 committed
        QMessageBox::StandardButton resBtn = QMessageBox::question(this, "Close",
                                                                   tr("Are you sure you want to quit?\n"),
                                                                   QMessageBox::Cancel | QMessageBox::No | QMessageBox::Yes,
                                                                   QMessageBox::Yes);
    
    mingf2's avatar
    mingf2 committed
        if (resBtn != QMessageBox::Yes) {
            event->ignore();
        } else {
            if (workerThread) {
    //            qDebug() << "Exiting thread..";
                // send stop signal to worker thread
    
                aborted=true;
    
    mingf2's avatar
    mingf2 committed
                emit threadStopped();
    
    mingf2's avatar
    mingf2 committed
                gSystem->Sleep(500);
    
    mingf2's avatar
    mingf2 committed
            }
    
            event->accept();
    
    mingf2's avatar
    mingf2 committed
        }
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    
        if (image)
            delete image;
    
    mingf2's avatar
    mingf2 committed
        if (countsText)
            delete countsText;
    
    mingf2's avatar
    mingf2 committed
        if (config)
            delete config;
        for (int i = 0; i < longitudes.size(); ++i) {
           if(longitudes[i]) {
               delete longitudes[i];
           }
        }
        for (int i = 0; i < latitudes.size(); ++i) {
           if (latitudes[i]) {
               delete latitudes[i];
           }
        }
    }
    
    
    void MainWindow::createGridlines()
    {
        const int Nl = 19; // Number of drawn latitudes
        const int NL = 19; // Number of drawn longitudes
        const int M = 30;
        float conv=M_PI/180;
        float la, lo, x, y, z;
        for (int j=0;j<Nl;++j) {
            // latitudes[j]=new TGraph();
            latitudes.push_back(new TGraph());
            la = -90+180/(Nl-1)*j;
            for (int i=0;i<M+1;++i) {
                lo = -180+360/M*i;
                z  = sqrt(1+cos(la*conv)*cos(lo*conv/2));
                x  = 180*cos(la*conv)*sin(lo*conv/2)/z;
                y  = 90*sin(la*conv)/z;
                latitudes[j]->SetPoint(i,x,y);
            }
        }
    
        for (int j=0;j<NL;++j) {
            // longitudes[j]=new TGraph();
            longitudes.push_back(new TGraph());
            lo = -180+360/(NL-1)*j;
            for (int i=0;i<M+1;++i) {
                la = -90+180/M*i;
                z  = sqrt(1+cos(la*conv)*cos(lo*conv/2));
                x  = 180*cos(la*conv)*sin(lo*conv/2)/z;
                y  = 90*sin(la*conv)/z;
                longitudes[j]->SetPoint(i,x,y);
            }
        }
        // Draw the grid
        TPad *pad2 = new TPad("pad2","",0,0,1,1);
        pad2->SetFillStyle(4000);
        pad2->SetFillColor(0);
        pad2->SetBorderSize(0);
        pad2->SetFrameBorderMode(0);
        pad2->SetFrameLineColor(0);
        pad2->SetFrameBorderMode(0);
        pad2->Draw();
        pad2->cd();
        Double_t ymin = -89.5;
        Double_t ymax = 89.5;
        Double_t dy = (ymax-ymin)/0.8; //10 per cent margins top and bottom
        Double_t xmin = -180;
        Double_t xmax = 180;
        Double_t dx = (xmax-xmin)/0.8; //10 per cent margins left and right
    
        pad2->Range(xmin-0.1*dx,ymin-0.1*dy,xmax+0.1*dx,ymax+0.1*dy);
    
        for (int j=0;j<Nl;++j) latitudes[j]->Draw("l");
        for (int j=0;j<NL;++j) longitudes[j]->Draw("l");
    }
    
    void MainWindow::createCountsLabel()
    {
    
        std::string strtmp = "Total counts: " + std::to_string(image->counts);
    
    mingf2's avatar
    mingf2 committed
        countsText = new TText(0.7, 0.92, strtmp.c_str());
        countsText->SetTextSizePixels(5);
        countsText->SetNDC(kTRUE);
        countsText->Draw("SAME");
    }
    
    void MainWindow::aitoff2xy(const double& l, const double& b, double &Al, double &Ab)
    {
        Double_t x, y;
        Double_t alpha2 = (l/2)*TMath::DegToRad();
        Double_t delta  = b*TMath::DegToRad();
        Double_t r2     = TMath::Sqrt(2.);
        Double_t f      = 2*r2/TMath::Pi();
        Double_t cdec   = TMath::Cos(delta);
        Double_t denom  = TMath::Sqrt(1. + cdec*TMath::Cos(alpha2));
        x      = cdec*TMath::Sin(alpha2)*2.*r2/denom;
        y      = TMath::Sin(delta)*r2/denom;
        x     *= TMath::RadToDeg()/f;
        y     *= TMath::RadToDeg()/f;
        //  x *= -1.; // for a skymap swap left<->right
        Al = x;
        Ab = y;
    }
    
    void MainWindow::redraw()
    {
    
        image->mMutex.lock();
        std::string strtmp = "Total counts: " + std::to_string(image->counts);
    
    mingf2's avatar
    mingf2 committed
        countsText->SetText(0.7, 0.92, strtmp.c_str());
        ui->canvas->Canvas()->Modified();
        ui->canvas->Canvas()->Update();
    
        image->mMutex.unlock();
    
    mingf2's avatar
    mingf2 committed
    }
    
    void MainWindow::handleOpen()
    {
        qDebug() << "Open file clicked";
    }
    
    
    bool MainWindow::handleSave()
    
    mingf2's avatar
    mingf2 committed
    {
    
    //    qDebug() << "Save clicked";
        if (curFile.isEmpty()) {
            return handleSaveAs();
        } else {
            return saveCanvas(curFile);
        }
    
    mingf2's avatar
    mingf2 committed
    }
    
    
    bool MainWindow::handleSaveAs()
    
    mingf2's avatar
    mingf2 committed
    {
    
        QString fileName = QFileDialog::getSaveFileName(this,
                tr("Save Image"), "",
                tr("PNG file (*.png);;ROOT file (*.root);;C file (*.C);;text file (*.txt)"));
    
    mingf2's avatar
    mingf2 committed
        if (!fileName.isEmpty() && saveCanvas(fileName)){
            curFile = fileName;
            return true;
    
    mingf2's avatar
    mingf2 committed
        return false;
    
    mingf2's avatar
    mingf2 committed
    }
    
    
    bool MainWindow::saveCanvas(const QString& fileName)
    {
        QFileInfo fileInfo(fileName);
        QString ext=fileInfo.completeSuffix();
        bool saved=false;
        if (ext == "root" || ext == "png" || ext == "C") {
    
    mingf2's avatar
    mingf2 committed
            qDebug() << "Save as " << ext << " file.";
    
            image->mMutex.lock();
            ui->canvas->Canvas()->SaveAs(fileName.toLocal8Bit().constData());
            image->mMutex.unlock();
            saved = true;
        }
        else if (ext == "txt") {
    
    mingf2's avatar
    mingf2 committed
            saved = image->saveImage(fileName.toStdString());
    
        }
        if (saved)
        {
            ui->statusBar->showMessage(QString("Image saved to: %1").arg(fileName));
        }
        return saved;
    }
    
    mingf2's avatar
    mingf2 committed
    void MainWindow::handleClose()
    {
    
    mingf2's avatar
    mingf2 committed
    //    qDebug() << "Close clicked";
    
    mingf2's avatar
    mingf2 committed
        this->close();
    }
    
    
    void MainWindow::handleScreenshot()
    
    mingf2's avatar
    mingf2 committed
    {
    
        QDateTime dateTime = QDateTime::currentDateTime();
        QString currentDateTime = dateTime.toString("yyyy-MM-dd-HH-mm-ss");
        QString fileName = QString("Screenshot-%1.png").arg(currentDateTime);
        saveCanvas(fileName);
    
    mingf2's avatar
    mingf2 committed
    }
    void MainWindow::handleAbout()
    {
    
        QMessageBox::about(this, tr("About Application"),
                 tr("This application is created using Qt 5.13.2. Source code is available at Gitlab."));
    
    mingf2's avatar
    mingf2 committed
    //    qDebug() << "About clicked";
    }
    
    void MainWindow::notifyThreadFinished()
    {
        // pop up a message box indicating processing is finished.
    
        if (!aborted)
        {
            QMessageBox messageBox;
            messageBox.setText("Image reconstruction finished.");
            messageBox.setWindowTitle("Finished");
            messageBox.exec();
        }
    
    mingf2's avatar
    mingf2 committed
    }