Plotting several graphs on divided canvas using compiled macro


_ROOT Version: v6-18-00
_Platform: Ubuntu 18.04
_Compiler: g++

Hi everyone,

I am trying to plot four graphs on a divided TCanvas in a compiled macro.

The first case is a simple example showing what I would like to plot, while the plot from the second case shows my problem. I attached two figures showing the output.
For some reason the histograms in mainPad(1) and resPad(1) are plotted on top of eachother, while the histogram in resPad(2) is in the space of resPad(1).

Could you please help me find out what the problem is?

Cheers,
Andreas

case2.pdf (15.8 KB)
case1.pdf (16.2 KB)

#include <iostream>
#include <fstream>
#include <string>
#include <TMath.h>
#include <TH1.h>
#include <TCanvas.h>
#include <mutex>
#include <memory>
#include <TGraph.h>
#include <TApplication.h>
#include <TSystem.h>
#include <TROOT.h>
#include <thread>
#include <unistd.h>
#include <iostream>
#include <readline/readline.h>
#include <readline/history.h>
#include <functional>


using namespace std;
using namespace ROOT;


class RootWrapper {

public:
    RootWrapper() : app("-", &_dummy, nullptr), shouldRun(false)
    {
        canvas.Divide(1,2);
        mainPanel = canvas.cd(1);
        mainPanel->SetLogy(true);
        residualPanel = canvas.cd(2);
    }

    void run() {
        shouldRun = true;
        while (shouldRun) {
            auto l = lock();

            usleep(100);

            gSystem->ProcessEvents();
        }
    }

    void requestStop() {
        shouldRun = false;
    }

    void update() {
        canvas.Update();
    }


    std::unique_lock<std::recursive_mutex> lock() {
        return std::unique_lock<std::recursive_mutex>{mutex};
    }


    void switchToMainPad(int n = 0) {
        auto _ = lock();
        mainPanel->cd(n);
    }

    void switchToResPad(int n = 0) {
        auto _ = lock();
        residualPanel->cd(n);
    }

    void split(int n) {
        auto _ = lock();
        residualPanel->Divide(n, 1);
        mainPanel->Divide(n, 1);
        for (int i = 1; i <= n; i++) mainPanel->cd(i)->SetLogy(true);
    }

    void manipulateGui(std::function<void()> f) {
        auto _ = lock();
        f();
        update();
    }


private:
    atomic_bool shouldRun;

    int _dummy = 0;
    std::recursive_mutex mutex;
    TApplication app;
    TCanvas canvas;
    TVirtualPad *mainPanel, *residualPanel;
};





int main(int argc, char *argv[]) {
    int n = 2;
    auto hist1 = new TH1F("h1", "h1", 10, 0, 100);
    hist1->Fill(5);
    auto hist2 = new TH1F("h2", "h2", 10, 0, 10);
    hist2->Fill(5);




    if(stoi(argv[1]) == 1) {


        // Test 1 - Working.

        int _dummy = 0;
        auto app = new TApplication("-", &_dummy, nullptr);
        auto canvas = new TCanvas("test1", "test1");
        canvas->Divide(1, 2);

        auto mainPad = canvas->cd(1);
        auto resPad = canvas->cd(2);

        mainPad->Divide(n, 1);
        resPad->Divide(n, 1);

        for (int i = 1; i <= n; ++i) {
            hist1->SetLineColor(i);
            hist2->SetLineColor(i);
            mainPad->cd(i);
            hist1->DrawClone();

            resPad->cd(i);
            hist2->DrawClone();
        }

        canvas->Modified();
        canvas->Update();
        app->Run();



    } else {



        // Test 2 - Is not working.
        RootWrapper gui;

        thread rootTread([&]() {
            gui.run();
        });

        gui.split(n);
        for (int i = 1; i <= n; ++i) {
            hist1->SetLineColor(i);
            hist2->SetLineColor(i);

            gui.manipulateGui([&]() {
                gui.switchToMainPad(i);
                hist1->DrawClone();
            });

            gui.manipulateGui([&]() {
                gui.switchToResPad(i);
                hist2->DrawClone();
            });
        }

        while (true) {

            string cmd;
            cin >> cmd;
            if (cmd == "x") break;
            else cout << "Unknown command " << cmd << endl;
        }
        gui.requestStop();
        rootTread.join();
    }

    return 0;
 }


could it be there is a cd missing ?
Can you manipulate interactively the plot to see where the missing plot went ?

The plots on mainPad(1) and resPad(1) are on top of eachother in the pdf i attached, but when I move it around they move together.

Also, I just found out that it works fine using root v6-08-00

Ok. I will check on my machine.

for info i get two warnings when compiling your code:

angad.cxx:28:21: warning: field 'app' will be initialized after field 'shouldRun' [-Wreorder]
    RootWrapper() : app("-", &_dummy, nullptr), shouldRun(false)
                    ^
angad.cxx:99:14: warning: unused parameter 'argc' [-Wunused-parameter]
int main(int argc, char *argv[]) {
             ^
2 warnings generated.

Fixed the warnings:
The first case can be run by giving the input 1, otherwise the second case will run.

EDIT : Fixed a bug.

#include <iostream>
#include <fstream>
#include <string>
#include <TMath.h>
#include <TH1.h>
#include <TCanvas.h>
#include <mutex>
#include <memory>
#include <TGraph.h>
#include <TApplication.h>
#include <TSystem.h>
#include <TROOT.h>
#include <thread>
#include <unistd.h>
#include <iostream>
#include <readline/readline.h>
#include <readline/history.h>
#include <functional>

Int_t *num;

using namespace std;
using namespace ROOT;


class RootWrapper {

public:
    RootWrapper() : app("-",num,nullptr)
    {
        canvas.Divide(1,2);
        mainPanel = canvas.cd(1);
        mainPanel->SetLogy(true);
        residualPanel = canvas.cd(2);
    }

    void run() {
        shouldRun = true;
        while (shouldRun) {
            auto l = lock();

            usleep(100);

            gSystem->ProcessEvents();
        }
    }

    void requestStop() {
        shouldRun = false;
    }

    void update() {
        canvas.Update();
    }


    std::unique_lock<std::recursive_mutex> lock() {
        return std::unique_lock<std::recursive_mutex>{mutex};
    }


    void switchToMainPad(int n = 0) {
        auto _ = lock();
        mainPanel->cd(n);
    }

    void switchToResPad(int n = 0) {
        auto _ = lock();
        residualPanel->cd(n);
    }

    void split(int n) {
        auto _ = lock();
        residualPanel->Divide(n, 1);
        mainPanel->Divide(n, 1);
        for (int i = 1; i <= n; i++) mainPanel->cd(i)->SetLogy(true);
    }

    void manipulateGui(std::function<void()> f) {
        auto _ = lock();
        f();
        update();
    }


private:
    TApplication app;
    atomic_bool shouldRun;

    std::recursive_mutex mutex;
    TCanvas canvas;
    TVirtualPad *mainPanel, *residualPanel;
};





int main(int argc, char *argv[]) {
    //(void) argc;
    int n = 2;
    auto hist1 = new TH1F("h1", "h1", 10, 0, 100);
    hist1->Fill(5);
    auto hist2 = new TH1F("h2", "h2", 10, 0, 10);
    hist2->Fill(5);




    if(argc>1) {
        if(stoi(argv[1])==1) {


            // Test 1 - Working.
            auto app = new TApplication("-",num,nullptr);
            auto canvas = new TCanvas("test1", "test1");
            canvas->Divide(1, 2);

            auto mainPad = canvas->cd(1);
            auto resPad = canvas->cd(2);

            mainPad->Divide(n, 1);
            resPad->Divide(n, 1);

            for (int i = 1; i <= n; ++i) {
                hist1->SetLineColor(i);
                hist2->SetLineColor(i);
                mainPad->cd(i);
                hist1->DrawClone();

                resPad->cd(i);
                hist2->DrawClone();
            }

            canvas->Modified();
            canvas->Update();
            app->Run();

    	    return 0;
        }
    }


    // Test 2 - Is not working.
    RootWrapper gui;

    thread rootTread([&]() {
        gui.run();
    });

    gui.split(n);
    for (int i = 1; i <= n; ++i) {
        hist1->SetLineColor(i);
        hist2->SetLineColor(i);

        gui.manipulateGui([&]() {
            gui.switchToMainPad(i);
            hist1->DrawClone();
        });

        gui.manipulateGui([&]() {
            gui.switchToResPad(i);
            hist2->DrawClone();
        });
    }
    while (true) {

        string cmd;
        cin >> cmd;
        if (cmd == "x") break;
        else cout << "Unknown command " << cmd << endl;
    }
    gui.requestStop();
    rootTread.join();
    return 0;
 }

When I run your program on Mac without parameter I get:

$ ./angad  

 *** Break *** segmentation violation
[/usr/lib/system/libsystem_platform.dylib] _sigtramp (no debug info)
[<unknown binary>] (no debug info)
[/Users/couet/roottest/./angad] main (no debug info)
[/usr/lib/system/libdyld.dylib] start (no debug info)

When I run it with input parameter 1 I get a white canvas. I can see that it is in fact several pad on top of each other. I guess I will need to try your program on some Linux machine

I’m sorry, there was a bug when giving an empty argument. This is now fixed, and I updated the code snippet above, so it should be working now.

i still get a crash when i run the macro without parameter on mac.
Also a warning (but that’s a detail)

angad.cxx:90:9: warning: private field '_dummy' is not used [-Wunused-private-field]
    int _dummy = 0;
        ^

I’m sorry about the errors. Its runs fine on my pc.
I fixed it again and updated the code above.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.