TTreeReader TChain notify on change of file

Hi, maybe I overlook something - is there some tutorial/example code how to get a notification when TChain changes a file in the processing via TTreeReader?
Something like MakeClass/TSelector ::Notify?

Thanks,
Zdenek


ROOT Version: 6.30.04
Platform: macOS
Compiler: Not Provided


Dear @zhubacek ,

The feature you are looking for is implemented via TNotifyLink. I am not aware of a specific tutorial for TChain, but in this tutorial there is an example usage at the bottom (the tutorial does many other things). See also the doc of TChain::LoadTree for an explanation on the usage of the notify object by the chain.

Cheers,
Vincenzo

Hi @vpadulan,
Thanks, but to be honest, I don’t understand, how the TNotifyLink should work and some example would be useful - I don’t get what a subscriber should be/if the TNotifyLink should be a template of something?

For the tutorial, yes, I know this one, I could do my own TSelector and there I am able to modify the Notify() method, but I’m looking for a simpler code (if that is possible).
I’d like to have a very simple TTreeReader on a TChain:

TChain *ch = new TChain("myTree");
  ch->Add("file1.root");
  ch->Add("file2.root");

  TTreeReader myReader(ch);
  TTreeReaderValue<int> njet(myReader,      "nJets");
  TTreeReaderArray<double> jetpt(myReader,   "jetPt");

  int counter = 0;
...
  while (myReader.Next())
    {
      if (ch->FileChanged()) SetSomeFileRelatedWeight();
    }

The Notify() seemed to lead to way that I should derive my own class MyReader from the TTreeReader and implement the notification, but in that case it leads to the TSelector which seems to be a unnecessary complicated for a simple reader?

Thanks,
Zdenek

Dear @zhubacek ,

I prepared for you the smallest example that I was able to create, see the attached zipped file. I will paste the instructions to run the contents also here for reference so that the general logic is documented

  1. You need a class that acts as the notifier. The only requirement is that the
    class implements a bool Notify() method. Write this class in a header. In
    my example the method just prints a notification every time it is called.

  2. Create a dictionary for the TNotifyLink<MyNotifier> instantiation.
    See I/O of custom classes - ROOT for detailed instructions, the
    following is just one way to do it.

    $: rootcling -f DictMyNotifier.cxx mynotifier.hxx LinkDef.h
    

    This generates the file DictMyNotifier.cxx

  3. Compile the program including the dictionary in the compilation:

    $: g++ -O3 -o repro.out DictMyNotifier.cxx repro.cpp `root-config --cflags --glibs`
    
  4. Run the program, notice that at each new file in the chain there will be a
    new notification printed.

forum_58244_tnotifylink.zip (7.3 KB)

With TTreeReader it should be trivial to extend by just calling PrependLink(treereader.GetTree()) or something similar.

Cheers,
Vincenzo

Dear @vpadulan ,
Thank you very much!

I slightly extended the notifier to get for example the current filename:

struct MyNotifier{
  MyNotifier() : fChain(0)
  {}
  void Init(TTree* tree)
  {
    fChain=tree;
  }
    bool Notify(){
      
        std::cout << "Notification! reading new file" << "\n";
	std::cout <<"File name: "<<fChain->GetCurrentFile()->GetName()<<std::endl;

	return true;
    }
  TTree *fChain;
};

This works well with the chain, but when I try what you suggest with the TTreeReader:

...
    TTreeReader myReader(&c);
    TTreeReaderValue<int> var1(myReader,"column1");
    
    MyNotifier n;
    n.Init(&c);
    TNotifyLink<MyNotifier> l{&n};
    l.PrependLink(*myReader.GetTree());
    int counter =0;
    while (myReader.Next())
      {
	counter++;
	std::cout <<"Event: "<<counter<<" "<<*var1<<std::endl;
      }

works as well, however I get a warning:
Warning in <TChain::TTree::SetNotify>: The tree or chain already has a fNotify registered and it is a TNotifyLink, while the new object is not a TNotifyLink. Setting fNotify to the new value will lead to an orphan linked list of TNotifyLinks and it is most likely not intended. If this is the intended goal, please call SetNotify(nullptr) first to silence this warning.
it seems that the notification is set up twice?

In that case, I don’t understand which Notify link is already set up? I tried calling c.SetNotify(nullptr); before setting up myReader and MyNotifier but this didn’t help?

Thank you
Zdenek