Retrieving an unnamed TGraph

Stupid question: can I retrieve an unnamed object (TGraph in my case) from a file? How?

THanks

{
  // https://root.cern.ch/root/html534/TFile.html
  TFile *f = TFile::Open("MyFile.root");
  // https://root.cern.ch/root/html534/TDirectoryFile.html
  gDirectory->ls();
  // https://root.cern.ch/root/html534/TList.html
  TList *l = gDirectory->GetListOfKeys();
  for (Int_t i = 0; i < l->GetSize(); i++) ((TKey *)(l->At(i)))->ls();
  TGraph *g = 0;
  for (Int_t i = 0; i < l->GetSize(); i++) {
    // https://root.cern.ch/root/html534/TKey.html
    TKey *k = ((TKey *)(l->At(i)));
    if (TString("TGraph").EqualTo(k->GetClassName())) {
      std::cout << "A TGraph was found." << std::endl;
      g = dynamic_cast<TGraph *>(k->ReadObj());
      break;
    }
  }
  if (g) g->Draw("A*");
}

BTW. If you need to retrieve, e.g., TGraphAsymmErrors objects, replace all occurrences of TGraph in this macro with TGraphAsymmErrors.

A small additional note.
If, in your ROOT file, you have just a single TGraph which was saved without giving it a “distinct name”, then it probably had got the name “Graph” (the default name set by ROOT). In this case you can simply try:

{
  // https://root.cern.ch/root/html534/TFile.html
  TFile *f = TFile::Open("MyFile.root");
  // https://root.cern.ch/root/html534/TDirectoryFile.html
  // f->ls(); // f-> ... or ... gDirectory->
  TGraph *g;
  f->GetObject("Graph", g); // f-> ... or ... gDirectory->
  if (g) g->Draw("A*");
}

Thanks, It’s interesting to know how ROOT handles unnamed objects, I often declare unnamed TGraph objects and then write them on file forgetting to assign a name.

Can I find anywhere (without looking directly into the class implementation) other insights about this topic? e.g. what happens with a number of unnamed objects of the same class greater than one?

Attach your ROOT file (with multiple “nameless” TGraph objects) here.

The file is actually very trivial, just saved few useless TGraphs (created with the constructor with no arguments and then filled with random points) and then tried to figure out how to retrieve them. At this point I was only interested to know, as a matter of curiosity, if ROOT actually gives by itself “standard” names to these nameless objects so that the user can retrieve them. Obviously your first answer I’s an efficient way to achieve the same result.

If you provide me such file I can try to come out with something more simple.

Here you are:

test.root (4.18 KB)

Try:

{
  TFile *f = TFile::Open("test.root");
  // f->ls();
  TGraph *o;
  TMultiGraph *mg = new TMultiGraph();
  TString name = ""; // usually "Graph" or ""
  for (Int_t i = 1; i < 9999 ; i++) { // 9999 = a "memory object"
#if 1 /* 0 or 1 */
    // checks that the object with the given "name" is a TGraph
    f->GetObject(name + ";" + ((Long_t)i), o);
#else /* 0 or 1 */
    // assumes that any object with the given "name" is a TGraph
    o = ((TGraph *)(f->Get(name + ";" + ((Long_t)i))));
#endif /* 0 or 1 */
    // if (o) f->Remove(o); // needed for TH* and similar objects
    if (!o) break; // no more TGraph found
    mg->Add(o);
  }
  if (mg->GetListOfGraphs()) mg->Draw("A");
}

BTW. If you need to retrieve, e.g., TGraphAsymmErrors objects, replace all occurrences of TGraph in this macro with TGraphAsymmErrors.

Great, thank you so much, that’s generally useful also to retrieve different objects saved with same name.

Just note that there will be an additional “action” required if, instead of TGraph objects, you try to retrieve TH* objects (and similar) using “GetObject” or “Get” (i.e., something like: “if (o) f->Remove(o);”) → see: Broken TDirectoryFile::FindObjectAny and TDirectoryFile::FindKeyAny - #11 by pcanal

A complete toy example dealing with some TH1D histograms:

{
  TString f_name = "toy.root";
  TFile *f;
  
  TString o_name = "h"; // usually "SomeName" or ""
  TH1D *o;
  
  // create the "f_name" ROOT file with a bunch of histograms
  for (Int_t i = 1; i <= 10 ; i++) {
    f = TFile::Open(f_name, ((i > 1) ? "UPDATE" : "RECREATE"));
    o = new TH1D(o_name, TString("sub-sample ") + ((Long_t)i), 100, -3, 3);
    o->FillRandom("gaus", 10000);
    o->Write();
    delete f; // automatically deletes "o"
  }
  
  // analyse histograms from the "f_name" ROOT file
  f = TFile::Open(f_name);
  f->ls();
  THStack *hs = new THStack();
  for (Int_t i = 1; i < 9999 ; i++) { // 9999 = a "memory object"
#if 1 /* 0 or 1 */
    // checks that the object with the given "o_name" is a TH1D
    f->GetObject(o_name + ";" + ((Long_t)i), o);
#else /* 0 or 1 */
    // assumes that any object with the given "o_name" is a TH1D
    o = ((TH1D *)(f->Get(o_name + ";" + ((Long_t)i))));
#endif /* 0 or 1 */
    if (o) f->Remove(o); // needed for TH* and similar objects
    if (!o) break; // no more TH1D found
    hs->Add(o);
  }
  if (hs->GetNhists()) hs->Draw();
}

BTW. If you need to deal with, e.g., TH1F histograms, replace all occurrences of TH1D in this macro with TH1F.