Skip to content
Snippets Groups Projects
MainWindow.cpp 9.17 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 <QMessageBox>
    
    #include "reconstruction.h"
    
    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->actionStart, &QAction::triggered, this, &MainWindow::handleStart);
        connect(ui->actionStop, &QAction::triggered, this, &MainWindow::handleStop);
        connect(ui->actionClear, &QAction::triggered, this, &MainWindow::handleClear);
    
        connect(ui->actionAbout, &QAction::triggered, this, &MainWindow::handleAbout);
    
        config = new Setup(Vector3D(SOURCE_X, SOURCE_Y, SOURCE_Z));
        coneQueue = new SPSC(config->capacity);
    
        workerThread = new Worker(this, config, coneQueue);
        connect(workerThread, &Worker::finished, workerThread, &QObject::deleteLater);
        connect(workerThread, &Worker::finished, this, &MainWindow::notifyThreadFinished);
        connect(this, &MainWindow::threadStopped, workerThread, &Worker::stopExecution);
        workerThread->start();
    
        createHist();
        createGridlines();
        createCountsLabel();
        ui->canvas->Canvas()->Modified();
        ui->canvas->Canvas()->Update();
    }
    
    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)
    {
        QMessageBox::StandardButton resBtn = QMessageBox::question( this, "Close",
                                                                    tr("Are you sure you want to quit?\n"),
                                                                    QMessageBox::Cancel | QMessageBox::No | QMessageBox::Yes,
                                                                    QMessageBox::Yes);
        if (resBtn != QMessageBox::Yes) {
            event->ignore();
        } else {
            finished=true;
            if (workerThread) {
    //            qDebug() << "Exiting thread..";
                aborted=true;
                // send stop signal to worker thread
                emit threadStopped();
            }
    //        event->accept();
        }
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
        if (coneQueue)
            delete coneQueue;
        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::run()
    {
        std::vector<Cone> cones(config->chuckSize);
        bool emptyQueue = false;
        while (!finished)
        {
            if (!stop)
            {
                int i(0);
                while (i < config->chuckSize)
                {
                    emptyQueue = !(coneQueue->wait_dequeue_timed(cones[i],
                                                               std::chrono::milliseconds(10)));
                    if (emptyQueue) break;
                    i++;
                }
                // update image
                updateImage(cones.cbegin(), cones.cbegin() + i, true);
                if (emptyQueue && threadExecutionFinished)
                {
                    // stop updating after this final run
                    finished = true;
    //                qDebug() << "Processing finished.";
                    QMessageBox messageBox;
                    messageBox.setText("Image reconstruction finished.");
                    messageBox.setWindowTitle("Finished");
                    messageBox.exec();
                    break;
                }
                // gSystem->Sleep(100);
            }
            QApplication::processEvents();
        }
    }
    
    void MainWindow::updateImage(std::vector<Cone>::const_iterator first,
                                 std::vector<Cone>::const_iterator last,
                                 const bool& normalized)
    {
        if (first == last)
            return;
        // update image
        if (normalized)
            addConesNormalized(config, hist, counts, first, last);
        else
            addCones(config, hist, counts, first, last);
        // redraw
        redraw();
    }
    
    void MainWindow::createHist()
    {
        hist = new TH2D("ROI", " ; Azimuth (degree); Elevation (degree)",
                        config->phiBins, -180, 180,
                        config->thetaBins, -90, 90);
        // init image
        for (int i = 0; i < config->phiBins; i++)
        {
            for (int j = 0; j < config->thetaBins; j++)
            {
                hist->SetBinContent(i+1, j+1, 0);
            }
        }
        gStyle->SetOptStat(0);
        hist->GetZaxis()->SetLabelSize(0.02);
        hist->Draw("z aitoff");
    
    }
    
    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(counts);
        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()
    {
        std::string strtmp = "Total counts: " + std::to_string(counts);
        countsText->SetText(0.7, 0.92, strtmp.c_str());
        ui->canvas->Canvas()->Modified();
        ui->canvas->Canvas()->Update();
    }
    
    void MainWindow::handleOpen()
    {
        qDebug() << "Open file clicked";
    }
    
    void MainWindow::handleSave()
    {
        qDebug() << "Save clicked";
    }
    
    void MainWindow::handleSaveAs()
    {
        qDebug() << "Save as clicked";
    }
    
    void MainWindow::handleClose()
    {
        qDebug() << "Close clicked";
        this->close();
    }
    
    void MainWindow::handleStart()
    {
        stop=false;
    //    qDebug() << "Start clicked";
    }
    
    void MainWindow::handleStop()
    {
        stop=true;
    //    qDebug() << "Stop clicked";
    }
    
    void MainWindow::handleClear()
    {
        counts = 0;
        hist->Reset();
        redraw();
    //    qDebug() << "Clear clicked";
    }
    
    void MainWindow::handleAbout()
    {
        QMessageBox messageBox;
        messageBox.setText("This application is created using Qt 5.13.2. Source code is available at Gitlab.");
        messageBox.setWindowTitle("About");
        messageBox.exec();
    //    qDebug() << "About clicked";
    }
    
    void MainWindow::notifyThreadFinished()
    {
        // pop up a message box indicating processing is finished.
        threadExecutionFinished = true;
    }