root
root copied to clipboard
Issue using TColor and saving canvas to ROOT format
Check duplicate issues.
- [X] Checked for duplicates
Description
It seems that when saving a canvas to a ROOT file (SaveAs("c.root")), colors defined with TColor::GetColor are not preserved whereas builtin colors are. This can be seen saving the canvas to both . png .root formats, then load the .root and save it again as a .png, and compare the two pngs created.
Tagging CMS CAT conveners @lenzip @anigamova and DPROC subconveners @oglez @ttedeschi
Reproducer
Define a save.C macro:
{
TRandom3 r;
TH1F h = TH1F("test","Test",100,-1.0,1.0);
for (int i=0;i<=1000;++i) {
h.Fill(r.Rndm());
}
TCanvas c = TCanvas();
c.Draw();
h.SetFillStyle(1001);
h.SetFillColor(TColor::GetColor("#F5BB54"));
//h.SetFillColor(kRed);
h.Draw("HIST");
c.SaveAs("c.root");
c.SaveAs("c.png");
}
and a load.C macro:
{
TFile *f = new TFile("c.root");
TH1F *h1 = (TH1F*)f->Get("c1");
h1->Draw();
h1->SaveAs("loaded_c.png")
}
If h.SetFillColor(TColor::GetColor("#F5BB54")); is uncommented and h.SetFillColor(kRed) is commented, c.png and loaded_c.png differ (the latter lacks the color), whereas if h.SetFillColor(TColor::GetColor("#F5BB54")) is commented and h.SetFillColor(kRed) is uncommented, c.png and loaded_c.png are the same (both properly showing the red fill color).
ROOT version
6.32.04
Installation method
Operating system
Ubuntu 24.04
Additional context
No response
Yes, this is how the colors are implemented. Only the builtins colors are known at saving time in root files. This other formats save the colors (including .C).
One can store all colors in the canvas if call TColor::DefinedColors(1) before.
If read such canvas back - all colors (including custom) will be restored.
@ttedeschi
Did you try to call TColor::DefinedColors(1) before storing canvas in ROOT file?
Hi sorry for the late reply, I tried and it works for ROOT 6.32 (I am finally able to see the right color in the loaded canvas), while with ROOT 6.30 I get
/test/./load_new.C:6:18: error: use 'template' keyword to treat 'Get' as a dependent template name
auto cnv = file->Get<TCanvas>("c1");
^
template
/test/./load_new.C:6:1: error: Syntax error
auto cnv = file->Get<TCanvas>("c1");
^
FunctionDecl 0x5af6325fe230 <input_line_8:1:1, /test/./load_new.C:14:1> input_line_8:1:6 __cling_Un1Qu30 'void (void *)'
|-ParmVarDecl 0x5af6325fe178 <col:22, col:28> col:28 vpClingValue 'void *'
|-CompoundStmt 0x5af6326e1a70 <col:42, /test/./load_new.C:14:1>
| |-DeclStmt 0x5af6326de478 <line:3:1, col:35>
| | `-VarDecl 0x5af63264d6a8 <col:1, col:34> col:8 f 'TFile *' cinit
| | `-CXXNewExpr 0x5af6326de418 <col:12, col:34> 'TFile *' CXXMethod 0x5af6326db188 'operator new' 'void *(size_t)'
| | `-CXXConstructExpr 0x5af6326ddee0 <col:16, col:34> 'TFile':'TFile' 'void (const char *, Option_t *, const char *, Int_t)'
| | |-ImplicitCastExpr 0x5af6326dde68 <col:22> 'const char *' <ArrayToPointerDecay>
| | | `-StringLiteral 0x5af63264d788 <col:22> 'const char[11]' lvalue "c_new.root"
| | |-CXXDefaultArgExpr 0x5af6326dde80 <<invalid sloc>> 'const char *'
| | |-CXXDefaultArgExpr 0x5af6326ddea0 <<invalid sloc>> 'const char *'
| | `-CXXDefaultArgExpr 0x5af6326ddec0 <<invalid sloc>> 'Int_t':'int'
| |-DeclStmt 0x5af6326df820 <line:6:1, col:36>
| | `-VarDecl 0x5af6326de508 <col:1, col:35> col:6 used cnv 'auto' cinit
| | `-CallExpr 0x5af6326df7c8 <col:12, col:35> '<dependent type>'
| | |-CXXDependentScopeMemberExpr 0x5af6326df6b0 <col:12, col:29> '<dependent type>' lvalue ->Get
| | | `-DeclRefExpr 0x5af6326de680 <col:12> '<dependent type>' lvalue Var 0x5af6326de578 'file' '<dependent type>'
| | `-StringLiteral 0x5af6326df7a8 <col:31> 'const char[3]' lvalue "c1"
| |-CallExpr 0x5af6326df8c0 <line:8:1, col:11> '<dependent type>'
| | `-CXXDependentScopeMemberExpr 0x5af6326df878 <col:1, col:6> '<dependent type>' lvalue ->Draw
| | `-DeclRefExpr 0x5af6326df838 <col:1> 'auto' lvalue Var 0x5af6326de508 'cnv' 'auto'
| |-CallExpr 0x5af6326e1a40 <line:10:1, col:31> '<dependent type>'
| | |-CXXDependentScopeMemberExpr 0x5af6326df900 <col:1, col:6> '<dependent type>' lvalue ->SaveAs
| | | `-DeclRefExpr 0x5af6326df8e0 <col:1> 'auto' lvalue Var 0x5af6326de508 'cnv' 'auto'
| | `-StringLiteral 0x5af6326e1a18 <col:13> 'const char[17]' lvalue "loaded_c_new.png"
| `-NullStmt 0x5af6326e1a68 <line:13:1>
|-AnnotateAttr 0x5af6326de5e0 <<invalid sloc>> Implicit R"ATTRDUMP(__ResolveAtRuntime)ATTRDUMP"
`-AnnotateAttr 0x5af6326de730 <<invalid sloc>> Implicit R"ATTRDUMP(__ResolveAtRuntime)ATTRDUMP"
<<<NULL>>>
p.s. just for completeness I made a little mistake in the example above, I load the object in the root file as an histogram, but I would have to load it as a canvas object.. anyway if I substitute TH1F *h1 = (TH1F*)f->Get("c1"); with auto cnv = f->Get<TCanvas>("c1"); the issue is exactly the same
Looks like you need to use latest ROOT version to get desired functionality.
Hi @couet,
It appears this issue is closed, but wasn't yet added to a project. Please add upcoming versions that will include the fix, or 'not applicable' otherwise.
Sincerely, :robot:
Hi @couet,
It appears this issue is closed, but wasn't yet added to a project. Please add upcoming versions that will include the fix, or 'not applicable' otherwise.
Sincerely, :robot: