ajgilbert/ICHiggsTauTau — pull request #7 by ajgilbert (2014-08-12 15:23:22+00:00)
Title: Updates to Core code

@pjdunne @adewit @rcl11 @amagnan
Hi all, (please ignore if you're on holiday :-) )

I've put together a set of updates to the TreeEvent/ModuleBase/AnalysisBase parts of the Core code - first time it's really changed in quite a while. As some of the interfaces and behaviour are modified I've put a detailed list of the changes below, and will wait a bit before merging into master. My plan is to do this on friday assuming no issues are raised.

The biggest change is the ability to run multiple module sequences in one AnalysisBase instance. The idea is that in the future we can run all analysis channels/systematics variations in one go, massively reducing the number of jobs that have to be submitted and the total processing time. E.g. in H->tau tau one could run all channels and their tau/electron energy scale shifts at the same time, and probably not bother with skimming at all.

And just to warn: big, interface-breaking changes are coming soon to the CMSSW-facing part of the framework (sorry!)

Feedback always welcome.

cheers,
Andrew

Changes (roughly in order of decreasing importance):
- AnalysisBase now supports multiple module sequences. Existing calls
to AddModule(ic::ModuleBase*) will append the given module pointer
to a sequence labelled "default". To add a module to a different
sequence (and automatically create that sequence if necessary) use
AddModule(std::string, ic::ModuleBase*), where the first argument is
the module label. RunAnalysis() will process each sequence of
modules, one after the other, for each event. At the beginning of a
new sequence the TreeEvent is reset, i.e. all products are cleared
and objects loaded from the TTree are reset to their initial state.
- AnalysisBase no longer counts the sum of weighted events passing
each module. This means it's possible to run on ntuples that don't
contain an EventInfo branch. If there is demand for this feature
something similar (but more flexible) can be restored.
- AnalysisBase no longer provides a complete interface to check which
module particular events failed in. The printing of this information
is now triggered by a module's Execute method returning the status
code 3. For convenience, a new module, "CheckEvents" has been added
in the Modules package that can be given a list of event numbers for
which this status code will be injected. So to recap, these are the
status codes in use at the moment:
0 : event passed, continue processing and increase yield counter
1 : event failed, stop processing and don't increase counter
2 : event failed, continue processing and don't increase counter
3 : event passed, switch on failure checking, continue processing
and increase counter
- Bugfix in TreeEvent: if a collection was loaded from a branch into two
different Event products, the second load operation would overwrite any
changes made to objects in the collection since the first load. E.g.

// First load the pfJets branch into PtrVec "jets1"
auto jets1 = event.GetPtrVec("jets1", "pfJets");
// Change the jet pT (e.g. doing JES uncertainty)
jets[0]->set_pt(...);
// Load the same branch as another PtrVec "jets2"
// => jet pt reset to initial values
auto jets2 = event.GetPtrVec("jets2", "pfJets");

With this fix the second load won't reset the pfJets vector. Please
check if any of your code would have been affected by this bug. Note
that with multiple Module sequences the loaded objects will always
be reset when switching from one sequence to the next.
- TreeEvent: it is now possible to explicitly check if a branch
exists in the TTree, using the method ExistsInTree(std::string).
This will work regardless of whether the product you are checking
has been loaded into the event. For the sake of parity, the method
ExistsInEvent(std::string) has been added and will just call
Exists() for the underlying ic::Event storage
- Runtime errors in these classes that previously threw unnamed
expections now throw exceptions with some info about what actually
went wrong.
- Experimental: The TreeEvent should now correctly handle
branches that store fundamental types, e.g. float, char* etc. These
have to be treated differently when doing SetBranchAddress, e.g.

double x;
tree->SetBranchAddress("some_double", &x);

instead of:

double *x = nullptr;
tree->SetBranchAddress("some_double", &x);

which is what we do for all non-fundamental (i.e. class) types. The
actual interface in TreeEvent is the same however, e.g.

double *x = tree_event->GetPtr("some_double");

If you have use for this feature please test and report back.
- Various optimisations to the underlying TreeEvent code, should
result in a small speed-up
- Removed program_options parsing in ModuleBase, was experimental and
not actually used anywhere
- Changed the constructor for AnalysisBase slightly, instead of two
arguments for the folder containing the TTree and the TTree name,
just have one argument for the complete path. Fixed all calls to
this in the framework: e.g. "icEventProducer", "EventTree" -->
"icEventProducer/EventTree" everywhere
- Re-formated some of the AnalysisBase printout