Saving histograms into a pdf / png format directly from ROOT

hmm what is the output of:

for key in root_keys:
    print(key,key.ClassName())

?

One example output of:

for key in root_keys:
    print("key: ", key, "ClassName: ", key.ClassName())
key:  Name: NUM_LooseID_DEN_genTracks_abseta_1_pt_2_Canv Title: c ClassName:  TKey
key:  Name: NUM_LooseID_DEN_genTracks_abseta_1_pt_2_resP Title: Result of fit of p.d.f. pdfPass to dataset hPass ClassName:  TKey
key:  Name: ProcessID0 Title: 8555bfbe-cc6e-11ec-a3de-513b8e80beef ClassName:  TKey
key:  Name: NUM_LooseID_DEN_genTracks_abseta_1_pt_2_resF Title: Result of fit of p.d.f. pdfFail to dataset hFail ClassName:  TKey
key:  Name: NUM_LooseID_DEN_genTracks_abseta_1_pt_2_statTests Title: statTests ClassName:  TKey
key:  Name: NUM_LooseID_DEN_genTracks_abseta_1_pt_2_GenPass Title:  ClassName:  TKey
key:  Name: NUM_LooseID_DEN_genTracks_abseta_1_pt_2_GenFail Title:  ClassName:  TKey
key:  Name: NUM_LooseID_DEN_genTracks_abseta_1_pt_2_Pass Title:  ClassName:  TKey
key:  Name: NUM_LooseID_DEN_genTracks_abseta_1_pt_2_Fail Title:  ClassName:  TKey
key:  Name: NUM_LooseID_DEN_genTracks_abseta_2_pt_1_Canv Title: c ClassName:  TKey
key:  Name: NUM_LooseID_DEN_genTracks_abseta_2_pt_1_resP Title: Result of fit of p.d.f. pdfPass to dataset hPass ClassName:  TKey
key:  Name: ProcessID0 Title: c5340b0e-cc6e-11ec-bcef-8ca0b8bcbeef ClassName:  TKey
key:  Name: NUM_LooseID_DEN_genTracks_abseta_2_pt_1_resF Title: Result of fit of p.d.f. pdfFail to dataset hFail ClassName:  TKey

Try instead with:

for key in root_keys:
    if key.InheritsFrom('TCanvas'):
        print(key)
        c = key.ReadObj()
        c.SaveAs("test.png")

Here I get the error:

SysError in <TFile::ReadBuffer>: error reading from file ./UL_2018/fits_data/muon/generalTracks/Z/Run2018_UL/massRangeDown/NUM_TightID_DEN_genTracks/NUM_TightID_DEN_genTracks_abseta_3_pt_7.root (Input/output error)
Error in <TFile::Init>: ./UL_2018/fits_data/muon/generalTracks/Z/Run2018_UL/massRangeDown/NUM_TightID_DEN_genTracks/NUM_TightID_DEN_genTracks_abseta_3_pt_7.root failed to read the file type data.

Does it happen with all files, or only with one?

If only with one, it seems that this particular ROOT file is corrupt. See: Corrupted ROOT files without reason ?! - #15 by linev

Also, please check if you have read permission on this file/folder.

Ah, just with this one! When I go to the actual file and look around, I get:

SysError in <TFile::ReadBuffer>: error reading from file ./UL_2018/fits_data/muon/generalTracks/Z/Run2018_UL/massRangeDown/NUM_TightID_DEN_genTracks/NUM_TightID_DEN_genTracks_abseta_3_pt_7.root (Remote I/O error)
Error in <TFile::Init>: ./UL_2018/fits_data/muon/generalTracks/Z/Run2018_UL/massRangeDown/NUM_TightID_DEN_genTracks/NUM_TightID_DEN_genTracks_abseta_3_pt_7.root failed to read the file type data.
(TFile *) nullptr

@ferhue Thank you so much for that! Is there a way I can go around those null pointers (not include them when trying to get TCanvases from ~200 other files that are good)?

Maybe the following:

try:
    myfile = ROOT.TFile.Open(file_name, "READ")
    root_keys = myfile.GetListOfKeys()
    for key in root_keys:
        ...HERE YOUR CODE
except:
    print('Skipping file',file_name)

Hmm…@ferhue, it’s still giving me a similar error:

SysError in <TFile::ReadBuffer>: error reading from file ./UL_2018/fits_data/muon/generalTracks/Z/Run2018_UL/massRangeDown/NUM_TightID_DEN_genTracks/NUM_TightID_DEN_genTracks_abseta_3_pt_7.root (Remote I/O error)
Error in <TFile::Init>: ./UL_2018/fits_data/muon/generalTracks/Z/Run2018_UL/massRangeDown/NUM_TightID_DEN_genTracks/NUM_TightID_DEN_genTracks_abseta_3_pt_7.root failed to read the file type data.

Can you just ignore the error? Or is the script crashing?

The script is crashing :frowning_face:

hmm maybe try this after TFile.Open:

if myfile.IsZombie():
    continue

Otherwise, check beforehand what the size of your file is, and skip it if it is very low.
See How do I check file size in Python? - Stack Overflow

So I have:

if nSigFail < 1.0:
        c = ROOT.TCanvas('','',200,10,700,500)
        #c = inFile.Get("TCanvas")                                                                                                                               
        dir1 = '/eos/user/t/tcarnaha/spark_tnp/'
        file_name = (dir1 +inFile.strip(".")[1:])
        #print('Loading file: ', file_name)                                                                                                                      
        myfile = ROOT.TFile.Open(file_name, "READ")

        if myfile.IsZombie():
            continue

        root_dir = myfile.GetDirectory(file_name+"_Canv") #may cause problems                                                                                    
        c = root_dir
        c.cd()
	c.SaveAs("test.png")

The scripts doesn’t like this very much; the file size is only 49KB though, so small but of similar size as the others.

If this doesn’t work, then I have no other ideas.

if nSigFail < 1.0:
    dir1 = '/eos/user/t/tcarnaha/spark_tnp/'
    file_name = (dir1 +inFile.strip(".")[1:])
    #print('Loading file: ', file_name)
    try:
        myfile = ROOT.TFile.Open(file_name, "READ")
    except:
        print('error')

No worries, @ferhue; thanks so much for all of your time invested. I’m sure I’ll beat my head against something fundamental eventually. Something is going wrong when it attempts to retrieve the TFiles I think.


Maybe just to anyone as a more general question: is there a general, fundamental way to retrieve a Canvas from an already-existent root file, and save it as a .pdf or .png? (See drawing–from directory spark_tnp/UL_2018/…/<file.root>, retrieving the Canvas, saving it in a picture.png file–the whole procedure should be saved in the scripts/ directory)? Because from what I’m doing, it is not coming to fruition.

What about

root /some/dir/with/file/test.root -e 'c->Draw(); c->SaveAs("out.png")' -q

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