#include "AliAODExtension.h" //------------------------------------------------------------------------- // Support class for AOD extensions. This is created by the user analysis // that requires a separate file for some AOD branches. The name of the // AliAODExtension object is the file name where the AOD branches will be // stored. //------------------------------------------------------------------------- #include "AliAODBranchReplicator.h" #include "AliAODEvent.h" #include "AliCodeTimer.h" #include "AliLog.h" #include "Riostream.h" #include "TDirectory.h" #include "TFile.h" #include "TList.h" #include "TMap.h" #include "TMap.h" #include "TObjString.h" #include "TROOT.h" #include "TString.h" #include "TTree.h" ClassImp(AliAODExtension) //______________________________________________________________________________ AliAODExtension::AliAODExtension() : TNamed(), fAODEvent(0), fTreeE(0), fFileE(0), fNtotal(0), fNpassed(0), fSelected(kFALSE), fRepFiMap(0x0), fRepFiList(0x0), fEnableReferences(kTRUE), fObjectList(0x0) { // default ctor } //______________________________________________________________________________ AliAODExtension::AliAODExtension(const char* name, const char* title, Bool_t isfilter) :TNamed(name,title), fAODEvent(0), fTreeE(0), fFileE(0), fNtotal(0), fNpassed(0), fSelected(kFALSE), fRepFiMap(0x0), fRepFiList(0x0), fEnableReferences(kTRUE), fObjectList(0x0) { // Constructor. if (isfilter) { TObject::SetBit(kFilteredAOD); printf("####### Added AOD filter %s\n", name); } else printf("####### Added AOD extension %s\n", name); KeepUnspecifiedBranches(); } //______________________________________________________________________________ AliAODExtension::~AliAODExtension() { // Destructor. if(fFileE){ // is already handled in TerminateIO fFileE->Close(); delete fFileE; fTreeE = 0; fAODEvent = 0; } if (fTreeE) delete fTreeE; if (fRepFiMap) fRepFiMap->DeleteAll(); delete fRepFiMap; // the map is owner delete fRepFiList; // the list is not delete fObjectList; // not owner } //______________________________________________________________________________ void AliAODExtension::AddBranch(const char* cname, void* addobj) { // Add a new branch to the aod if (!fAODEvent) { char type[20]; gROOT->ProcessLine(Form("TString s_tmp; AliAnalysisManager::GetAnalysisManager()->GetAnalysisTypeString(s_tmp); sprintf((char*)%p, \"%%s\", s_tmp.Data());", type)); Init(type); } TDirectory *owd = gDirectory; if (fFileE) { fFileE->cd(); } char** apointer = (char**) addobj; TObject* obj = (TObject*) *apointer; fAODEvent->AddObject(obj); TString bname(obj->GetName()); if (!fTreeE->FindBranch(bname.Data())) { Bool_t acceptAdd(kTRUE); if ( TestBit(kDropUnspecifiedBranches) ) { // check that this branch is in our list of specified ones... // otherwise do not add it ! TIter next(fRepFiMap); TObjString* p; acceptAdd=kFALSE; while ( ( p = static_cast(next()) ) && !acceptAdd ) { if ( p->String() == bname ) acceptAdd=kTRUE; } } if ( acceptAdd ) { // Do the same as if we book via // TTree::Branch(TCollection*) fObjectList->Add(obj); const Int_t kSplitlevel = 99; // default value in TTree::Branch() const Int_t kBufsize = 32000; // default value in TTree::Branch() fTreeE->Bronch(bname.Data(), cname, fAODEvent->GetList()->GetObjectRef(obj), kBufsize, kSplitlevel - 1); } } owd->cd(); } //______________________________________________________________________________ Bool_t AliAODExtension::FinishEvent() { // Fill current event. fNtotal++; if (!IsFilteredAOD()) { fAODEvent->MakeEntriesReferencable(); fTreeE->Fill(); return kTRUE; } // Filtered AOD. Fill only if event is selected. if (!fSelected) return kTRUE; TIter next(fRepFiList); AliAODBranchReplicator* repfi; while ( ( repfi = static_cast(next()) ) ) { repfi->ReplicateAndFilter(*fAODEvent); } fNpassed++; fTreeE->Fill(); fSelected = kFALSE; // so that next event will not be selected unless demanded return kTRUE; } //______________________________________________________________________________ Bool_t AliAODExtension::Init(Option_t *option) { // Initialize IO. AliCodeTimerAuto(GetName(),0); if(!fAODEvent) { fAODEvent = new AliAODEvent(); } TDirectory *owd = gDirectory; TString opt(option); opt.ToLower(); if (opt.Contains("proof")) { // proof // Merging via files. Need to access analysis manager via interpreter. gROOT->ProcessLine(Form("AliAnalysisDataContainer *c_common_out = AliAnalysisManager::GetAnalysisManager()->GetCommonOutputContainer();")); gROOT->ProcessLine(Form("AliAnalysisManager::GetAnalysisManager()->OpenProofFile(c_common_out, \"RECREATE\", \"%s\");", fName.Data())); fFileE = gFile; } else { fFileE = new TFile(GetName(), "RECREATE"); } fTreeE = new TTree("aodTree", "AliAOD tree"); delete fObjectList; fObjectList = new TList; fObjectList->SetOwner(kFALSE); // be explicit we're not the owner... TList* inputList = fAODEvent->GetList(); TIter next(inputList); TObject* o; while ( ( o = next() ) ) { // Loop on the objects that are within the main AOD, and see what to do with them : // - transmit them to our AOD as they are // - filter them (by means of an AliAODBranchReplicator) // - drop them completely Bool_t mustKeep(kFALSE); TString test(o->ClassName()); test.ToUpper(); if (test.Contains("HEADER")) { // do not allow to drop header branch mustKeep=kTRUE; } if ( fRepFiMap && !mustKeep ) { // we have some replicators, so let's see what the relevant one decides about this object TObject* specified = fRepFiMap->FindObject(o->GetName()); // FindObject finds key=o->GetName() in the map if (specified) { AliAODBranchReplicator* repfi = dynamic_cast(fRepFiMap->GetValue(o->GetName())); // GetValue gets the replicator corresponding to key=o->GetName() if ( repfi ) { TList* replicatedList = repfi->GetList(); if (replicatedList) { AliAODEvent::AssignIDtoCollection(replicatedList); TIter nextRep(replicatedList); TObject* objRep; while ( ( objRep = nextRep() ) ) { if ( !fObjectList->FindObject(objRep) ) // insure we're not adding several times the same object { fObjectList->Add(objRep); } } } else { AliError(Form("replicatedList from %s is null !",repfi->GetName())); } } } else { if ( !TestBit(kDropUnspecifiedBranches) ) { // object o will be transmitted to the output AOD, unchanged fObjectList->Add(o); } } } else { // no replicator, so decide based on the policy about dropping unspecified branches if ( mustKeep || !TestBit(kDropUnspecifiedBranches) ) { // object o will be transmitted to the output AOD, unchanged fObjectList->Add(o); } } } if (fEnableReferences) { fTreeE->BranchRef(); } fTreeE->Branch(fObjectList); owd->cd(); return kTRUE; } //______________________________________________________________________________ void AliAODExtension::Print(Option_t* opt) const { // Print info about this extension cout << opt << Form("%s - %s - %s - aod %p",IsFilteredAOD() ? "FilteredAOD" : "Extension", GetName(),GetTitle(),GetAOD()) << endl; if ( !fEnableReferences ) { cout << opt << opt << "References are disabled ! Hope you know what you are doing !" << endl; } if ( TestBit(kDropUnspecifiedBranches) ) { cout << opt << opt << "All branches not explicitely specified will be dropped" << endl; } TIter next(fRepFiMap); TObjString* s; while ( ( s = static_cast(next()) ) ) { AliAODBranchReplicator* br = static_cast(fRepFiMap->GetValue(s->String().Data())); cout << opt << opt << "Branch " << s->String(); if (br) { cout << " will be filtered by class " << br->ClassName(); } else { cout << " will be transmitted as is"; } cout << endl; } } //______________________________________________________________________________ void AliAODExtension::SetEvent(AliAODEvent* event) { // Connects to an external event if (!IsFilteredAOD()) { Error("SetEvent", "Not allowed to set external event for non filtered AOD's"); return; } fAODEvent = event; } //______________________________________________________________________________ void AliAODExtension::AddAODtoTreeUserInfo() { // Add aod event to tree user info if (!fTreeE) return; AliAODEvent* aodEvent(fAODEvent); if ( IsFilteredAOD() ) { // cannot attach fAODEvent (which is shared with our AliAODHandler mother) // so we create a custom (empty) AliAODEvent // Has also the advantage we can specify only the list of objects // that are actually there in this filtered aod // aodEvent = new AliAODEvent; TIter nextObj(fObjectList); TObject* o; while ( ( o = nextObj() ) ) { aodEvent->AddObject(o); } } fTreeE->GetUserInfo()->Add(aodEvent); } //______________________________________________________________________________ Bool_t AliAODExtension::TerminateIO() { // Terminate IO if (TObject::TestBit(kFilteredAOD)) printf("AOD Filter %s: events processed: %d passed: %d\n", GetName(), fNtotal, fNpassed); else printf("AOD extension %s: events processed: %d\n", GetName(), fNtotal); if (fFileE) { fFileE->Write(); fFileE->Close(); delete fFileE; fFileE = 0; fTreeE = 0; fAODEvent = 0; } return kTRUE; } //______________________________________________________________________________ void AliAODExtension::FilterBranch(const char* branchName, AliAODBranchReplicator* repfi) { // Specify a filter/replicator for a given branch // // If repfi=0x0, this will disable the branch (in the output) completely. // // repfi is adopted by this class, i.e. user should not delete it. // // WARNING : branch name must be exact. // // See also the documentation for AliAODBranchReplicator class. // if (!fRepFiMap) { fRepFiMap = new TMap; fRepFiMap->SetOwnerKeyValue(kTRUE,kTRUE); fRepFiList = new TList; fRepFiList->SetOwner(kFALSE); } fRepFiMap->Add(new TObjString(branchName),repfi); if (repfi && !fRepFiList->FindObject(repfi)) { // insure we get unique and non-null replicators in this list fRepFiList->Add(repfi); } }