TColor not saved in canvas' .root output?

Dear ROOT developers,

I use following code to draw a histogram onto a canvas and to save it to a .root file:

from ROOT import TCanvas, TColor, TH1F
import ROOT

def createColor():
	ci = ROOT.TColor.GetFreeColorIndex()
	return ci, TColor(ci, 0/255., 168/255., 196/255.)

c = TCanvas()
c.Draw()

h1 = TH1F("h1", "histo from a gaussian", 100, -3, 3)
h1.FillRandom("gaus", 10000)

#style options
ci, color = createColor()
h1.SetFillColor(ci)

h1.Draw()
c.SaveAs("outputImage.png")
c.SaveAs("outputImage.root")

If I open the outputImage.root in the TBrowser (upper image), I get a different result than when opening the outputImage.png (lower image):

Is it possible that the TColor I define in the function is not saved to the .root file properly? Is there something I can do to improve that? I would like to continue using a function to define my colors, as the code this is actually intended for is quite large and I would like to keep a modular structure.

I have to have .root files, as I am aiming to use jsroot to display the plots I created (I want interactiveness :wink: ).

Cheers,
Ben


ROOT Version: 6.14
Platform: Linux Mint 19 Tara


I just tried to to change histogram color and save the canvas in a .root file. When I read back the ROOT file I get back the colors . Do you have a small reproducer showing the issue ?

Dear Couet,

may I ask some questions to provide you with an accurate answer? Are you changing the colors in the ROOT file produced with the code from above?

I am asking, because if I modify above example to

from ROOT import TCanvas, TColor, TH1F
import ROOT

c = TCanvas()
c.Draw()

h1 = TH1F("h1", "histo from a gaussian", 100, -3, 3)
h1.FillRandom("gaus", 10000)

#style options
h1.SetFillColor(8)

h1.Draw()
c.SaveAs("outputImage.png")
c.SaveAs("outputImage.root")

everything works as expected, your histogram has color in the .root file.

Cheers,
Ben

Yes with:

{
   auto c = new TCanvas();
   int ci = TColor::GetFreeColorIndex();
   auto col = new TColor(ci, 0/255., 168/255., 196/255.);

   auto h1 = new TH1F("h1", "histo from a gaussian", 100, -3, 3);
   h1->FillRandom("gaus", 10000);

   h1->SetFillColor(ci);

   h1->Draw();
   c->SaveAs("outputImage.png");
   c->SaveAs("outputImage.root");
}

The color is not saved in the ROOT file. You will need to redefined this color.

Hi Couet,

thank you for your reply! Is there any chance this will be updated in subsequent versions of ROOT? Is there anything I can do to simplify the reapplication of the color? Can I save the TColor instance in the ROOT file for example, as well?

I think this behaviour should be changed, as this is not beneficial for future applications of e.g. jsroot.

Cheers,
Ben

Colors are not saved because it can ve a huge overhead with big palettes.
You need to define the extra colors you need in you rootlogon.C file.

Hi Couet,
thank you for your reply! If I understand the source code correctly, the colors are saved, if at least 51 new colors were defined. However this only works, if you do not call TColor::DefinedColors() before or save another canvas in advance.

What do you think of following proposal? When saving a canvas loop over the primitives that are not TColors and add the custom defined colors to the list of primitives, if not already there.

Cheers,
Ben

Why not … Can you propose a PR for that ?

Hi,

Current solution for automatic colors list saving in TCanvas is fragile, while depends on global state.

For me much better solution will be to provide special methods to store complete colors list in the ROOT file and read such colors back from the file. In that case one always has under control that happens.

Regards,
Sergey

I can have a look into this, but just to let you know that I am not very experienced with the ROOT source code and it would take me some time to build ROOT, implement and validate this feature. Further I have a lot of things on my to-do list atm… Maybe it would be faster if someone else takes care of this?

The problem might be the size overhead not needed ins 90% of the cases.

Hi Ben,

In my point of view, the old TColor / palette design is preventing us from handing these cases correctly. If you stream all “non-default” TColor objects used by objects on a pad, what do you do with palettes, and how do people change the palette when read from a file?

We are working on a complete new ROOT graphics implementation that addresses this: I’d be curious to hear your comments on RCanvas and how it handles palettes and colors. Hmm, but we don’t have a tutorial for this yet. Maybe @linev could point us to one? (The code is currently undergoing some major changes still - it’s all new! - so we might not have an up-to-date tutorial yet.)

1 Like

Hi Axel,
thank you for your reply! I agree that the palette saving could be problematic in the case you are mentioning. I suppose an implementation would need to check for new palettes and colors and multiple potential special cases.

Thank you for these wonderful news! I’d be very excited to test the new RCanvas. I suppose this goes with ROOT7? It would be very kind if you could provide me with some small example on the usage, in particular how to save things as .root files for usage with JSROOT. I already found this TH1 example and the RCanvas documentation, though I am not sure from there how to save things as .root.

Cheers,
Ben

Hi Ben,

RCanvas code undergoes major changes now, therefore it is early to recommend it as alternative.
Our current approach - palette with associated colors will be always stored with RCanvas. And RColor itself will be just RGB value which can be changed independently for every histogram drawings. Means - you will get functionality exactly as you need. But we need to finalize current implementation, which is in transition state now.

Regards,
Sergey

Hi Sergey,

thank you for your honest opinion. Should you need a guinea pig for feedback, feel free to get back to me.

Cheers,
Ben

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