ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvsroot/UserCode/MitAna/TreeMod/src/OutputMod.cc
Revision: 1.12
Committed: Tue Mar 24 16:12:26 2009 UTC (16 years, 1 month ago) by loizides
Content type: text/plain
Branch: MAIN
CVS Tags: Mit_009a, Mit_009, Mit_008
Changes since 1.11: +171 -42 lines
Log Message:
Added BranchDep test and HltTrigger merging capas.

File Contents

# Content
1 // $Id: OutputMod.cc,v 1.11 2009/03/23 22:15:15 loizides Exp $
2
3 #include "MitAna/TreeMod/interface/OutputMod.h"
4 #include "MitAna/TreeMod/interface/HLTFwkMod.h"
5 #include "MitAna/DataUtil/interface/Debug.h"
6 #include "MitAna/DataTree/interface/BranchTable.h"
7 #include "MitAna/DataTree/interface/Names.h"
8 #include "MitAna/DataUtil/interface/TreeWriter.h"
9 #include "MitAna/TreeMod/interface/TreeBranchLoader.h"
10
11 using namespace mithep;
12 using namespace std;
13
14 ClassImp(mithep::OutputMod)
15
16 //--------------------------------------------------------------------------------------------------
17 OutputMod::OutputMod(const char *name, const char *title) :
18 BaseMod(name,title),
19 fTreeName(Names::gkEvtTreeName),
20 fPrefix("skimtest"),
21 fPathName("."),
22 fMaxSize(1024),
23 fCompLevel(9),
24 fSplitLevel(99),
25 fBranchSize(16*1024),
26 fDoReset(kFALSE),
27 fUseBrDep(kTRUE),
28 fCheckTamBr(kTRUE),
29 fKeepTamBr(kFALSE),
30 fTreeWriter(0),
31 fEventHeader(0),
32 fAllEventHeader(0),
33 fRunInfo(0),
34 fLaHeader(0),
35 fBranchTable(0),
36 fBranches(0),
37 fNBranchesMax(1024),
38 fRunTree(0),
39 fLATree(0),
40 fAllTree(0),
41 fSkimmedIn(0),
42 fL1Tree(0),
43 fHltTree(0),
44 fHLTTab(new vector<string>),
45 fHLTLab(new vector<string>),
46 fRunEntries(0),
47 fL1Entries(0),
48 fHltEntries(0),
49 fFileNum(-1),
50 fLastWrittenEvt(-1),
51 fLastSeenEvt(-1),
52 fCounter(0)
53 {
54 // Constructor.
55 }
56
57 //--------------------------------------------------------------------------------------------------
58 void OutputMod::BeginRun()
59 {
60 // Create HLT tree if HLTFwkMod is being run.
61
62 if (!HasHLTInfo())
63 return;
64
65 if (!fHltTree) {
66 HLTFwkMod *hm = const_cast<HLTFwkMod*>(GetHltFwkMod());
67 fTreeWriter->AddBranchToTree(hm->HLTTreeName(), hm->HLTTabName(),
68 TClass::GetClass(typeid(*fHLTTab))->GetName(),
69 &fHLTTab, 32000, 0);
70 fTreeWriter->AddBranchToTree(hm->HLTTreeName(), hm->HLTLabName(),
71 TClass::GetClass(typeid(*fHLTLab))->GetName(),
72 &fHLTLab, 32000, 0);
73 fTreeWriter->SetAutoFill(hm->HLTTreeName(), 0);
74 fHltTree = fTreeWriter->GetTree(hm->HLTTreeName());
75 }
76 }
77
78 //--------------------------------------------------------------------------------------------------
79 void OutputMod::CheckAndAddBranch(const char *bname, const char *cname)
80 {
81 // Check if the given branch should be kept or dropped.
82
83 if (IsAcceptedBranch(bname))
84 return;
85
86 // populate regular expression list if this was not yet done
87 if (fCmdReList.size() != fCmdList.size()) {
88 for (UInt_t i=0; i<fCmdList.size(); ++i) {
89 const char *ptr = fCmdList.at(i).c_str();
90 fCmdReList.push_back(TRegexp(ptr+5,kTRUE));
91 if (ptr[0]=='k')
92 fCmdDeList.push_back(kTRUE);
93 else
94 fCmdDeList.push_back(kFALSE);
95 }
96 }
97
98 // decide whether given branch name should be kept or dropped
99 TString brname(bname);
100 Bool_t decision = kFALSE;
101 Bool_t decision_found = kFALSE;
102
103 for (UInt_t i=0; i<fCmdList.size(); ++i) {
104 TRegexp &re(fCmdReList.at(i));
105 if (brname.Index(re) == kNPOS)
106 continue;
107 decision = fCmdDeList.at(i);
108 decision_found = kTRUE;
109 }
110
111 if (!decision_found) { // no decision found: still drop branch
112 Warning("CheckAndAddBranch",
113 "No decision found for branch '%s' and class '%s'. Branch therefore dropped!",
114 bname, cname);
115 return;
116 }
117
118 if (!decision) { // drop branch according to request
119 Info("CheckAndAddBranch",
120 "Dropped branch '%s' and class '%s'", bname, cname);
121 return;
122 }
123
124 // add branch to accepted branch list
125 Info("CheckAndAddBranch",
126 "Kept branch '%s' and class '%s'", bname, cname);
127
128 fBrNameList.push_back(string(bname));
129 fBrClassList.push_back(string(cname));
130 }
131
132 //--------------------------------------------------------------------------------------------------
133 Bool_t OutputMod::CheckAndResolveBranchDep()
134 {
135 // Checks dependency in BranchTable. Resolve dependency automatically if fUserBrDep is kTRUE.
136
137 TFile *cfile = const_cast<TFile*>(GetSel()->GetCurrentFile());
138 if (!cfile)
139 return kFALSE;
140
141 BranchTable *br = dynamic_cast<BranchTable*>(cfile->Get(Names::gkBranchTable));
142 if (!br)
143 return kFALSE;
144
145 TList *blist = br->GetBranches();
146 if (!blist)
147 return kFALSE;
148
149 fBranchTable = new BranchTable;
150 fBranchTable->SetName(Names::gkBranchTable);
151 fBranchTable->SetOwner();
152
153 TList sht;
154 sht.SetOwner(kTRUE);
155 for (UInt_t i=0; i<fBrNameList.size(); ++i) {
156 sht.Add(new TObjString(fBrNameList.at(i).c_str()));
157 }
158
159 for (UInt_t i=0; i<fBrNameList.size(); ++i) {
160 TString brname(fBrNameList.at(i).c_str());
161 if (!blist->FindObject(brname))
162 continue;
163 TList *bdeps = br->GetDepBranches(brname);
164 if (!bdeps)
165 continue;
166
167 // check dependency
168 TIter iter(bdeps->MakeIterator());
169 const TObjString *n = dynamic_cast<const TObjString*>(iter.Next());
170 while (n) {
171 if (sht.FindObject(n->GetName())) {
172 // dependent branch is already accepted
173 fBranchTable->Add(new BranchName(brname,n->GetName()));
174 } else {
175 if (fUseBrDep) {
176 const TObjArray *arr = GetSel()->GetTree()->GetTree()->GetListOfBranches();
177 TBranch *br = dynamic_cast<TBranch*>(arr->FindObject(n->GetName()));
178 if (!br) {
179 Error("CheckAndResolveBranchDep",
180 "Could not get branch '%s' to resolve dependency for branch '%s'",
181 n->GetName(), brname.Data());
182 } else {
183 Info("CheckAndResolveBranchDep",
184 "Adding branch '%s' to resolve dependency for branch '%s'",
185 n->GetName(), brname.Data());
186 fBrNameList.push_back(string(n->GetName()));
187 fBrClassList.push_back(br->GetClassName());
188 sht.Add(new TObjString(n->GetName()));
189 fBranchTable->Add(new BranchName(brname,n->GetName()));
190 }
191 } else {
192 Warning("CheckAndResolveBranchDep",
193 "Unresolved dependency of branch '%s' and '%s' ",
194 n->GetName(), brname.Data());
195 }
196 }
197 n = dynamic_cast<const TObjString*>(iter.Next());
198 }
199 delete bdeps;
200 }
201 delete blist;
202 return kTRUE;
203 }
204
205 //--------------------------------------------------------------------------------------------------
206 void OutputMod::CheckAndResolveTAMDep(Bool_t solve)
207 {
208 // Check if TAM has loaded additional branches. If requested try to solve the the dependency
209 // by adding the branch to the list of branches.
210
211 const THashTable &ht = GetSel()->GetBranchTable();
212
213 TIter iter(ht.MakeIterator());
214 const TAMBranchInfo *next = dynamic_cast<const TAMBranchInfo*>(iter.Next());
215
216 while (next) {
217 const TAMBranchInfo *cur = next;
218 next = dynamic_cast<const TAMBranchInfo*>(iter.Next());
219 Bool_t isloaded = cur->IsLoaded();
220 if (!isloaded)
221 continue;
222
223 const char *bname = cur->GetName();
224 if (IsAcceptedBranch(bname))
225 continue;
226
227 TreeBranchLoader *loader = dynamic_cast<TreeBranchLoader*>(cur->GetLoader());
228 if (!loader)
229 continue;
230
231 TBranch *br = loader->GetBranch();
232 if (!br)
233 continue;
234
235 const char *cname = br->GetClassName();
236
237 if (solve) {
238 Info("CheckAndResolveTAMDep",
239 "Resolving dependency for loaded branch '%s' and class '%s'", bname,cname);
240
241 fBrNameList.push_back(string(bname));
242 fBrClassList.push_back(string(cname));
243 fBranches[GetNBranches()-1] = reinterpret_cast<TObject*>(loader->GetAddress());
244
245 } else {
246 Warning("CheckAndResolveTAMDep",
247 "Unresolved dependency for loaded branch '%s' and class '%s'",
248 bname,cname);
249 }
250 }
251 }
252
253 //--------------------------------------------------------------------------------------------------
254 void OutputMod::EndRun()
255 {
256 // Nothing to be done at this point.
257 }
258
259 //--------------------------------------------------------------------------------------------------
260 void OutputMod::FillAllEventHeader(Bool_t isremoved)
261 {
262 // Fill event header into the all-event-header tree.
263
264 if (!fTreeWriter->BeginEvent(kFALSE)) {
265 SendError(kAbortAnalysis, "FillAllEventHeader", "Begin event failed!");
266 return;
267 }
268
269 if (fSkimmedIn) { // copy alread skimmed headers if any there
270 for(UInt_t i=0; i<fSkimmedIn->Entries(); ++i) {
271 const EventHeader *eh = fSkimmedIn->At(i);
272 fAllEventHeader->SetEvtNum(eh->EvtNum());
273 fAllEventHeader->SetLumiSec(eh->LumiSec());
274 fAllEventHeader->SetRunNum(eh->RunNum());
275 fAllEventHeader->SetRunEntry(eh->RunEntry());
276 fAllEventHeader->SetSkimmed(eh->Skimmed()+1);
277 fAllTree->Fill();
278 }
279 }
280
281 const EventHeader *eh = GetEventHeader();
282 fAllEventHeader->SetEvtNum(eh->EvtNum());
283 fAllEventHeader->SetLumiSec(eh->LumiSec());
284 fAllEventHeader->SetRunNum(eh->RunNum());
285 if (isremoved) {
286 fAllEventHeader->SetRunEntry(-1);
287 fAllEventHeader->SetSkimmed(eh->Skimmed()+1);
288 } else {
289 fAllEventHeader->SetRunEntry(eh->RunEntry());
290 fAllEventHeader->SetSkimmed(eh->Skimmed());
291 }
292
293 fAllTree->Fill();
294 }
295
296 //--------------------------------------------------------------------------------------------------
297 void OutputMod::FillL1Info()
298 {
299 // Not doing anything here until the production writes out L1 information.
300
301 if (!fL1Tree)
302 return;
303 }
304
305 //--------------------------------------------------------------------------------------------------
306 void OutputMod::FillHltInfo()
307 {
308 // Write HLT trigger table if needed.
309
310 if (!fHltTree)
311 return;
312
313 HLTFwkMod *hm = const_cast<HLTFwkMod*>(GetHltFwkMod());
314 vector<string> *trigtable = hm->fHLTTab;
315 vector<string> *labels = hm->fHLTLab;
316
317 Bool_t doCopy = kFALSE;
318 if (fHLTTab->size()==0) {
319 doCopy = kTRUE;
320 } else {
321 // check if existing table contains all necessary paths:
322 // if so keep it, otherwise store the new one
323
324 if ((fHLTTab->size() != trigtable->size()) ||
325 (fHLTLab->size() != labels->size())) {
326 doCopy = kTRUE;
327 } else {
328 // need to check more thoroughly
329
330 for (UInt_t i=0; i<trigtable->size(); ++i) {
331 if (trigtable->at(i) != fHLTTab->at(i)) {
332 doCopy = kTRUE;
333 break;
334 }
335 }
336 if (!doCopy) {
337 for (UInt_t i=0; i<labels->size(); ++i) {
338 if (labels->at(i) != fHLTLab->at(i)) {
339 doCopy = kTRUE;
340 break;
341 }
342 }
343 }
344 }
345 }
346
347 if (!doCopy)
348 return;
349
350 fHLTTab->resize(trigtable->size());
351 copy(trigtable->begin(),trigtable->end(), fHLTTab->begin());
352 fHLTLab->resize(labels->size());
353 copy(labels->begin(),labels->end(), fHLTLab->begin());
354
355 ++fHltEntries;
356 fHltTree->Fill();
357 }
358
359 //--------------------------------------------------------------------------------------------------
360 Bool_t OutputMod::IsAcceptedBranch(const char *bname)
361 {
362 // Return true if given branch is already in branch list. Also return true if a special
363 // branch like the "EventHeader" branch is reqested.
364
365 // search in branch list
366 for (UInt_t i=0; i<GetNBranches(); ++i) {
367 if (fBrNameList.at(i).compare(bname) == 0)
368 return kTRUE;
369 }
370
371 // check if special branch that we take care of ourselves
372 string name(bname);
373 if (name.compare("EventHeader") == 0) {
374 return kTRUE;
375 }
376
377 return kFALSE;
378 }
379
380 //--------------------------------------------------------------------------------------------------
381 Bool_t OutputMod::Notify()
382 {
383 // On first notify, loop over list of branches to determine the list of kept branches.
384
385 if (GetNEventsProcessed() != 0)
386 return kTRUE;
387
388 const TTree *tree=GetSel()->GetTree();
389 if (!tree)
390 return kFALSE;
391
392 const TObjArray *arr = tree->GetTree()->GetListOfBranches();
393 if (!arr)
394 return kFALSE;
395
396 for (Int_t i=0; i<arr->GetEntries(); ++i) {
397 TBranch *br = dynamic_cast<TBranch*>(arr->At(i));
398 if (!br && !br->GetMother())
399 continue;
400 br = br->GetMother();
401 TClass *cls = TClass::GetClass(br->GetClassName());
402 if (!cls)
403 continue;
404
405 if (!cls->InheritsFrom("TObject")) {
406 Warning("Notify", "Found branch '%s' where class '%s' does not derive from TObject",
407 br->GetName(), br->GetClassName());
408 continue;
409 }
410
411 CheckAndAddBranch(br->GetName(), br->GetClassName());
412 }
413
414 if (!CheckAndResolveBranchDep())
415 return kFALSE;
416
417 RequestBranches();
418 return kTRUE;
419 }
420
421 //--------------------------------------------------------------------------------------------------
422 void OutputMod::LoadBranches()
423 {
424 // Loop over requested branches and load them.
425
426 for (UInt_t i=0; i<GetNBranches(); ++i) {
427 LoadBranch(fBrNameList.at(i).c_str());
428 }
429 }
430
431 //--------------------------------------------------------------------------------------------------
432 void OutputMod::Process()
433 {
434 // Write out the kept branches of the current event. Make sure the meta information is
435 // correctly updated.
436
437 if (GetSel()->GetCurEvt() == fLastSeenEvt) {
438 Warning("Process", "Event with %ul already seen", fLastSeenEvt);
439 return;
440 }
441 fLastSeenEvt = GetSel()->GetCurEvt();
442
443 if (GetSel()->GetCurEvt() == fLastWrittenEvt) {
444 Warning("Process", "Event with %ul already written", fLastWrittenEvt);
445 return;
446 }
447 fLastWrittenEvt = GetSel()->GetCurEvt();
448 ++fCounter;
449
450 // prepare for tree filling
451 if (!fTreeWriter->BeginEvent(fDoReset)) {
452 SendError(kAbortAnalysis, "Process", "Begin event failed!");
453 return;
454 }
455
456 if (GetNEventsProcessed() == 0 && fCheckTamBr) {
457 CheckAndResolveTAMDep(fKeepTamBr);
458 }
459
460 // load all our branches
461 LoadBranches();
462
463 // pass our branches to tree writer if on first event
464 if (GetNEventsProcessed() == 0) {
465 SetupBranches();
466 }
467
468 // reset per file quantities if a new file was opened
469 if (fTreeWriter->GetFileNumber()!=fFileNum) {
470 fRunmap.clear();
471 fRunEntries = 0;
472 fL1Entries = 0;
473 fHltEntries = 0;
474 fFileNum = fTreeWriter->GetFileNumber();
475 fTreeWriter->StoreObject(fBranchTable);
476 }
477
478 UInt_t runnum = GetEventHeader()->RunNum();
479
480 // store look ahead information
481 if (fRunEntries>0) {
482 fLaHeader->SetRunNum(runnum);
483 fLATree->Fill();
484 }
485
486 // fill event header
487 fEventHeader->SetEvtNum(GetEventHeader()->EvtNum());
488 fEventHeader->SetLumiSec(GetEventHeader()->LumiSec());
489 fEventHeader->SetRunNum(runnum);
490
491 // fill all event header
492 FillAllEventHeader(kFALSE);
493
494 // look-up if entry is in map
495 map<UInt_t,Int_t>::iterator riter = fRunmap.find(runnum);
496 if (riter != fRunmap.end()) { // found existing run info
497 Int_t runentry = riter->second;
498 fEventHeader->SetRunEntry(runentry);
499
500 IncNEventsProcessed();
501 fTreeWriter->EndEvent(fDoReset);
502 return;
503 }
504
505 // fill new run info
506 Int_t runentry = fRunEntries;
507 ++fRunEntries;
508 fEventHeader->SetRunEntry(runentry);
509 fRunmap.insert(pair<UInt_t,Int_t>(runnum,runentry));
510 fRunInfo->SetRunNum(runnum);
511
512 Int_t l1entry = fL1Entries;
513 FillL1Info();
514 fRunInfo->SetL1Entry(l1entry);
515
516 Int_t hltentry = fHltEntries;
517 FillHltInfo();
518 if (hltentry < fHltEntries)
519 fRunInfo->SetHltEntry(hltentry);
520 else
521 fRunInfo->SetHltEntry(hltentry-1);
522
523 fRunTree->Fill();
524
525 IncNEventsProcessed();
526
527 if (!fTreeWriter->EndEvent(fDoReset)) {
528 SendError(kAbortAnalysis, "Process", "End event failed!");
529 return;
530 }
531 }
532
533 //--------------------------------------------------------------------------------------------------
534 void OutputMod::ProcessAll()
535 {
536 // Called by the Selector class for events that were skipped.
537
538 if (GetSel()->GetCurEvt() == fLastSeenEvt)
539 return;
540
541 fLastSeenEvt = GetSel()->GetCurEvt();
542 ++fCounter;
543
544 // prepare for tree filling
545 FillAllEventHeader(kTRUE);
546 }
547
548 //--------------------------------------------------------------------------------------------------
549 void OutputMod::RequestBranches()
550 {
551 // Loop over requested branches and request them.
552
553 for (UInt_t i=0; i<GetNBranches(); ++i) {
554 if (i>=fNBranchesMax) {
555 SendError(kAbortAnalysis, "RequestBranch", "Cannot request branch '%s' "
556 "since maximum number of branches [%d] is reached",
557 fBrNameList.at(i).c_str(), fNBranchesMax);
558 return;
559 }
560 fBranches[i] = 0;
561 TAModule::ReqBranch(fBrNameList.at(i).c_str(), fBranches[i]);
562 }
563 }
564
565 //--------------------------------------------------------------------------------------------------
566 void OutputMod::SetupBranches()
567 {
568 // Setup branches in tree writer.
569
570 for (UInt_t i=0; i<GetNBranches(); ++i) {
571 const char *bname = fBrNameList.at(i).c_str();
572 const char *cname = fBrClassList.at(i).c_str();
573 if (!fBranches[i]) {
574 SendError(kWarning, "SetupBranches",
575 "Pointer for branch '%s' and class '%s' is NULL", bname, cname);
576 continue;
577 }
578 Int_t bsize = fBranchSize;
579 TString cnamestr(cname);
580 if ((bsize<128*1024) && (cnamestr.Contains("mithep::MCParticle"))) {
581 bsize=128*1024;
582 } else if ((bsize<32*1024) && (cnamestr.Contains("mithep::CaloTower"))) {
583 bsize=32*1024;
584 }
585
586 fTreeWriter->AddBranch(bname, cname, &fBranches[i], bsize);
587 }
588 }
589
590 //--------------------------------------------------------------------------------------------------
591 void OutputMod::SlaveBegin()
592 {
593 // Setup the tree writer and create branches that can already be created at this point.
594
595 // setup tree writer
596 fTreeWriter = new TreeWriter(fTreeName, kFALSE);
597 fTreeWriter->SetBaseURL(fPathName);
598 fTreeWriter->SetPrefix(fPrefix);
599 fTreeWriter->SetMaxSize(fMaxSize*1024*1024);
600 fTreeWriter->SetCompressLevel(fCompLevel);
601 fTreeWriter->SetDefaultSL(fSplitLevel);
602 fTreeWriter->SetDefaultBrSize(fBranchSize);
603 fTreeWriter->AddTree(fTreeName);
604 fTreeWriter->DoBranchRef(fTreeName);
605
606 // deal with my own tree objects
607 fEventHeader = new EventHeader;
608 fTreeWriter->AddBranch(GetSel()->GetEvtHdrName(), &fEventHeader);
609
610 // deal with other trees
611 const char *tname = 0;
612 fRunInfo = new RunInfo;
613 tname = GetSel()->GetRunTreeName();
614 fTreeWriter->AddBranchToTree(tname, GetSel()->GetRunInfoName(), &fRunInfo);
615 fTreeWriter->SetAutoFill(tname, 0);
616 fRunTree = fTreeWriter->GetTree(tname);
617 fLaHeader = new LAHeader;
618 tname = GetSel()->GetLATreeName();
619 fTreeWriter->AddBranchToTree(tname, GetSel()->GetLAHdrName(), &fLaHeader);
620 fTreeWriter->SetAutoFill(tname, 0);
621 fLATree = fTreeWriter->GetTree(tname);
622 fAllEventHeader = new EventHeader;
623 tname = GetSel()->GetAllEvtTreeName();
624 fTreeWriter->AddBranchToTree(tname, GetSel()->GetAllEvtHdrBrn(), &fAllEventHeader);
625 fAllTree = fTreeWriter->GetTree(tname);
626 fTreeWriter->SetAutoFill(tname, 0);
627
628 // get pointer to all event headers
629 fSkimmedIn = GetPublicObj<EventHeaderCol>(Names::gkSkimmedHeaders);
630
631 // deal here with published objects (not yet implemented)
632
633 // create TObject space for TAM
634 fBranches = new TObject*[fNBranchesMax];
635
636 // adjust checks for TAM branches
637 if (fKeepTamBr)
638 fCheckTamBr = kTRUE;
639 }
640
641 //--------------------------------------------------------------------------------------------------
642 void OutputMod::SlaveTerminate()
643 {
644 // Terminate tree writing and do cleanup.
645
646 RetractObj(Names::gkSkimmedHeaders);
647
648 delete fTreeWriter;
649 fTreeWriter = 0;
650
651 delete fEventHeader;
652 delete fRunInfo;
653 delete fLaHeader;
654 delete fAllEventHeader;
655
656 delete[] fBranches;
657
658 Double_t frac = 100.*GetNEventsProcessed()/fCounter;
659 Info("SlaveTerminate", "Stored %.2f%% events (%ld out of %ld)",
660 frac, GetNEventsProcessed(), fCounter);
661 }