Set TCanvas size in batch mode

I am trying to run root in batch mode, and save TCanvas in a .root file. What I notice though is that when I save the Canvas in batch mode, it doesn’t preserve the size I created it with, but at some default value. I attach a small running example macro.
Could you please let me know what the workaround is? I am using root version 5.19.04
test.C (1012 Bytes)

I see what you mean. I have no workaround yet. I will investigate.

Hi all,

I have the same problem, quite annoying for me since I have to run a script producing plots quite often and messing up the screen all the time because I need the Canvas in the right size. Is there some fix for this meanwhile?

best,
Daniel

Actually, seems to me, this problem as been fixed.
I executed the macro provided in this thread in batch mode.
Then I restarted ROOT in interactive mode and displayed the saved canvas.
The saved canvas has the same size has the original one when the macro is executed in interactive mode.
I am using trunk version of ROOT.

Hi,

strange…it’s been a while since the topic came up the first time. I am using ROOT 5-27 and it doesn’t seem to work. Perhaps the change has been very recent. I will try again. Thank you again!

Daniel

Hm, unfortunately it still does not work for me. I alternatively try to set the size correctly after getting it from file like:

but this leads to a seg fault…

regards,
Daniel

Are we doing the same thing ? I did that:

$ root -b
  *******************************************
  *                                         *
  *        W E L C O M E  to  R O O T       *
  *                                         *
  *   Version   5.29/01  15 December 2010   *
  *                                         *
  *  You are welcome to visit our Web site  *
  *          [root.cern.ch](http://root.cern.ch)            *
  *                                         *
  *******************************************

ROOT 5.29/01 (trunk@38301, Mar 04 2011, 14:12:16 on macosx64)

CINT/ROOT C/C++ Interpreter version 5.18.00, July 2, 2010
Type ? for help. Commands must be C++ statements.
Enclose multiple statements between { }.
root [0] .x plot.C("plot")
root [1] .q
$ root
  *******************************************
  *                                         *
  *        W E L C O M E  to  R O O T       *
  *                                         *
  *   Version   5.29/01  15 December 2010   *
  *                                         *
  *  You are welcome to visit our Web site  *
  *          [root.cern.ch](http://root.cern.ch)            *
  *                                         *
  *******************************************

ROOT 5.29/01 (trunk@38301, Mar 04 2011, 14:12:16 on macosx64)

CINT/ROOT C/C++ Interpreter version 5.18.00, July 2, 2010
Type ? for help. Commands must be C++ statements.
Enclose multiple statements between { }.
root [0] TFile f("plot.root")
root [1] VarCanvas.Draw()
root [2] 

Sorry that it took me a while to reply.

Well, it looks to me like we are doing the same thing (ROOT 5.27/06)…Did you change the canvas size to some non-standard dimensions before saving it to file? I also could not do:

TFile f("myfile.root"); MyCanvas.Draw();

directly but had to do:

but this cannot be it…right?

regards,
Daniel

I did nothing special. Just ran the macro test.c given in the first post. This macro generates a non standard canvas size (portrait oriented). I ran it in batch to create the file plot.root (see previous posts). Then I ran root again in interactive mode, attached the file plot.root (see again the previous posts), plot the saved canvas (see one more the previous posts) and I get the same portrait oriented canvas size.

Hi again,

I overlooked the test.C file in the first post somehow, I am sorry. I tested it with this file but it still does not work for me :wink: The canvas size changes…so probably this was fixed quite recently and I should upgrade to a more recent version of ROOT.

Cheers,
Daniel

Yes that’s is what I am thinking. I do not thing I can do a mistake saying the size is kept because the portrait layout is not standard therefore it is clearly identifiable.

I am refreshing this old topic because I have exact same issue:
Let’s start with this simple macro:
demo.C (113 Bytes)

{
    auto can = new TCanvas("can", "can", 400, 400);
    can->SetWindowSize(800, 800);
    can->SaveAs(".C");
}

When run: root demo.C the saved canvas is:

//=========Macro generated from canvas: can/can
//=========  (Tue Feb  3 12:30:06 2026) by ROOT version 6.38.00
   TCanvas *can = new TCanvas("can", "can", 3000, 360, 800, 800);

but when called in batch mode root -b demo.C:

//=========Macro generated from canvas: can/can
//=========  (Tue Feb  3 12:30:55 2026) by ROOT version 6.38.00
   TCanvas *can = new TCanvas("can", "can", 0, 0, 400, 400);

Any ideas how to save changes in batch mode?

..:: edit: to be presiely as also written below, the canvas saved in batch mode does not preserve the canvas size as seen in tehse two lines:

   TCanvas *can = new TCanvas("can", "can", 3000, 360, 800, 800); // window mode
   TCanvas *can = new TCanvas("can", "can", 0, 0, 400, 400);      // batch mode

Here one can read:

At creation time, no matter if in interactive or batch mode, the constructor defines the size of the canvas window (including the size of the window manager’s decoration). To define precisely the graphics area size of a canvas in the interactive mode, the following four lines of code should be used:

{
   Double_t w = 600;
   Double_t h = 600;
   auto c = new TCanvas("c", "c", w, h);
   c->SetWindowSize(w + (w - c->GetWw()), h + (h - c->GetWh()));
}

and in the batch mode simply do:

c->SetCanvasSize(w,h);

If the canvas size exceeds the window size, scroll bars will be added to the canvas This allows to display very large canvases (even bigger than the screen size). The Following example shows how to proceed.

@couet The problem is that SaveAs is ignoring the modified Canvas/Window size. If you try this macro (save as demo.C):

{
  auto can = new TCanvas("can", "can", 400, 400);
  can->SetWindowSize(500, 500);
  can->SetCanvasSize(800, 800);
  can->Draw();
  gPad->Modified();
  gPad->Update();
  can->SaveAs(".C");
}

and run it in batch (root -b -q demo.C), the result is:

#ifdef __CLING__
#pragma cling optimize(0)
#endif
void can()
{
//=========Macro generated from canvas: can/can
//=========  (Tue Feb  3 15:20:16 2026) by ROOT version 6.36.06
   TCanvas *can = new TCanvas("can", "can", 0, 0, 400, 400);
   gStyle->SetOptFit(0);
   gStyle->SetOptStat(1111);
   gStyle->SetOptTitle(1);
   TColor::SetPalette(57, nullptr);
   can->Range(0,0,1,1);
   can->SetFillColor(0);
   can->SetBorderMode(0);
   can->SetBorderSize(2);
   can->SetFrameBorderMode(0);
   can->Modified();
   can->SetSelected(can);
}

So ROOT is keeping the size with which it was first created, ignoring modifications. I see that SaveAs accepts options (ROOT: TObject Class Reference), so maybe the window/canvas size can be specified there? (but not sure how)

1 Like

That’s exactly the point.

BTW. This magic statement sequence is expected to set the correct canvas size in both modes (interactive and batch):

c->SetWindowSize(w, h); c->SetWindowSize(w + (w - c->GetWw()), h + (h - c->GetWh()));

1 Like

It sets proper canvas size, but the canvas size is not stored in the saved C file.
This is issue with storing mechanism, because the canvas is created with window size and not canvas, and in batch mode there is no window, so there is nothing to resize…

I tried doing something like this but this is also not satisfying me (look for trick):

{
    Double_t w = 400;
    Double_t h = 400;

    auto can = new TCanvas("can_size", "can_size", w, h);

    printf("1. Ww = %d  Wh = %d    WindowWidth = %d  WindowHeight = %d\n",
           can->GetWw(), can->GetWh(), can->GetWindowWidth(), can->GetWindowHeight());

    Double_t w2 = 800;
    Double_t h2 = 800;

    if (gROOT->IsBatch()) {
        printf("BATCH MODE\n");

        can->SetCanvasSize(w2, h2);

        // TRICK STARTS HERE
        Int_t ww, wh; UInt_t winw, winh;
        can->GetCanvasPar(ww, wh, winw, winh);
        winw = w2;
        winh = h2;

        can->SaveAs("can_size_batch.C");
        can->SaveAs("can_size_batch.png");
    } else {
        printf("GRAPH MODE\n");

        can->SetWindowSize(w2 + (w - can->GetWw()), h2 + (h - can->GetWh()));

        can->SaveAs("can_size_graph.C");
        can->SaveAs("can_size_graph.png");
    }

    printf("2. Ww = %d  Wh = %d    WindowWidth = %d  WindowHeight = %d\n",
           can->GetWw(), can->GetWh(), can->GetWindowWidth(), can->GetWindowHeight());
}

because the saved sizes are:

TCanvas *can_size = new TCanvas("can_size", "can_size", 1, 1, 804, 804);      // BATCH MODE
TCanvas *can_size = new TCanvas("can_size", "can_size", 3000, 331, 802, 829); // WINDOW MODE

But I am working on PR which will fix that. Perhaps today I will put draft into github.

Both “can_size_*.png” files (and other “graphical formats”) should be equal (800 x 800 pixels).
Maybe the problem is in the “.C” (and possibly also “.xml”) output.