Errors in TTreeReader example

Hello,
I tried to use the second “more complete” example of usage of TTreeReader, that can be found here. I list the problems I encountered in decreasing order of importance:

[ul][li]The CheckValue method to validate a TTreeReaderValue always returns false, because TTreeReaderValues that have been just created have a setup status of -7[/li]
[li]CheckValue takes a pointer but a TTreeReaderValue is passed by value instead (and ChekValue should take a reference to TTreeReaderValueBase instead of a pointer to avoid passing null pointers to it)[/li]
[li]TTreeReaderValueBase is now in namespace ROOT::Internal, not just ROOT[/li]
[li]I had to remove from the code all mentions of #include "TriggerInfo.h" #include "Muon.h" #include "Tau.h" and things depending on them[/li]
[li]an unnamed TH1F is declared: TH1F("hist", "TTreeReader example histogram", 10, 0., 100.); and later used as variable “hist”[/li][/ul]

Cheers,
E.G.

Hi Enrico,

thanks for the remarks: a JIRA item was opened about your post to improve asap the documentation - sft.its.cern.ch/jira/browse/ROOT-7687
For what concerns these lines

#include "TriggerInfo.h"
#include "Muon.h"
#include "Tau.h"

(and the whole example) I think the spirit of this piece of code is to show how to plug TTreeReader in a real Physics analysis with names and entities widely known within the analysisers’ community.

Cheers,
Danilo

Hi Enrico,

It looks like you may have a corrected version of this example ?
If yes you can send it to me and I will put it in place.

Olivier

Hello,
sorry I just saw the message (looking forward to mail notifications for post replies :smiley:).

I report below the code I ended up with, but the issue remains that the CheckValue function always returns false, because TTreeReaderValues’ status after their creation is invalid (-7). It might be a different bug, or simply a behaviour that should be better documented and differently handled in CheckValue here.

EDIT: corrected a typo, corrected the lack of case keyword in switch statements, qualified EntryStatuses with “TTreeReader::”

#include "TFile.h"
#include "TH1.h"
#include "TTreeReader.h"
#include "TTreeReaderValue.h"
#include "TTreeReaderArray.h"
#include <vector>
#include <iostream>

bool CheckValue(ROOT::Internal::TTreeReaderValueBase* value) {
   if (value->GetSetupStatus() < 0) {
      std::cerr << "Error " << value->GetSetupStatus()
                << "setting up reader for " << value->GetBranchName() << '\n';
      return false;
   }
   return true;
}

// Analyze the tree "MyTree" in the file passed into the function.
// Returns false in case of errors.
bool analyze(TFile* file) {
   // Create a TTreeReader named "MyTree" from the given TDirectory.
   // The TTreeReader gives access to the TTree to the TTreeReaderValue and
   // TTreeReaderArray objects. It knows the current entry number and knows
   // how to iterate through the TTree.
   TTreeReader reader("MyTree", file);
   // Read a single float value in each tree entries:
   TTreeReaderValue<Float_t> px(reader, "px");
   if (!CheckValue(&px)) return false;
   TH1F hist("hist", "TTreeReader example histogram", 10, -3, 3);
   while (reader.Next()) {
      if (reader.GetEntryStatus() == TTreeReader::kEntryValid) {
         std::cout << "Loaded entry " << reader.GetCurrentEntry() << '\n';
      } else {
         switch (reader.GetEntryStatus()) {
         case TTreeReader::kEntryValid:
            // Handled above.
            break;
         case TTreeReader::kEntryNotLoaded:
            std::cerr << "Error: TTreeReader has not loaded any data yet!\n";
            break;
         case TTreeReader::kEntryNoTree:
            std::cerr << "Error: TTreeReader cannot find a tree names \"MyTree\"!\n";
            break;
         case TTreeReader::kEntryNotFound:
            // Can't really happen as TTreeReader::Next() knows when to stop.
            std::cerr << "Error: The entry number does not exist\n";
            break;
         case TTreeReader::kEntryChainSetupError:
            std::cerr << "Error: TTreeReader cannot access a chain element, e.g. file without the tree\n";
            break;
         case TTreeReader::kEntryChainFileError:
            std::cerr << "Error: TTreeReader cannot open a chain element, e.g. missing file\n";
            break;
         case TTreeReader::kEntryDictionaryError:
            std::cerr << "Error: TTreeReader cannot find the dictionary for some data\n";
            break;
         case TTreeReader::kEntryLast:
            std::cerr << "Warning: TTreeReader reached fLastEntry\n";
            break;
         }
         return false;
      }
      hist.Fill(*px);
   } // TTree entry / event loop

   hist.Print();
   return true;
}

I see you have removed a large part of the example … is it intended ?

I removed the parts I could not compile because I don’t have TriggerInfo.h, Muon.h, Tau.h and have not access to the related objects.

For my part I believe code examples in the documentation should be “plug-and-play” for the users, so they can test and experiment right away, but anyway that is the code that works for me (except for the TTreeReaderValue::GetSetupStatus problem).

Cheers!

Ok I’ll tell the person responsible of the part of code to look at this.

Hi Enrico,

[quote=“eguiraud”]Hello,
I tried to use the second “more complete” example of usage of TTreeReader, that can be found here. I list the problems I encountered in decreasing order of importance:

[ul][li]The CheckValue method to validate a TTreeReaderValue always returns false, because TTreeReaderValues that have been just created have a setup status of -7[/li][/ul]
[/quote]
Thanks, moved after TTreeReader::Next()

Absolutely, thanks, fixed!

Fixed! But I think that’s wrong; I will move TTreeReaderValueBase into ROOT::Details::.

Right - this is a mockup. I wanted to show that it can read actual objects, as that’s often what people have.

Thanks, fixed!

Cheers, Axel.