/// \file /// \ingroup tutorial_ProofStdVec /// /// Selector for generic processing with stdlib collections /// /// \macro_code /// /// \author Gerardo Ganis (gerardo.ganis@cern.ch) #define ProofStdVect_cxx #include "ProofStdVect.h" #include #include #include #include #include #include #include #include #include #include //_____________________________________________________________________________ ProofStdVect::ProofStdVect() { // Constructor fCreate = kFALSE; fTree = nullptr; fFile = nullptr; fProofFile = nullptr; fRandom = nullptr; fHgood = nullptr; fHbad = nullptr; } //_____________________________________________________________________________ ProofStdVect::~ProofStdVect() { // Destructor SafeDelete(fTree); SafeDelete(fFile); SafeDelete(fRandom); } //_____________________________________________________________________________ void ProofStdVect::Begin(TTree * /*tree*/) { // The Begin() function is called at the start of the query. // When running with PROOF Begin() is only called on the client. // The tree argument is deprecated (on PROOF 0 is passed). TString option = GetOption(); // Dataset creation run? if (fInput && fInput->FindObject("ProofStdVect_Create")) { fCreate = kTRUE; } else if (option.Contains("create")) { fCreate = kTRUE; } } //_____________________________________________________________________________ void ProofStdVect::SlaveBegin(TTree * /*tree*/) { // The SlaveBegin() function is called after the Begin() function. // When running with PROOF SlaveBegin() is called on each slave server. // The tree argument is deprecated (on PROOF 0 is passed). TString option = GetOption(); // Dataset creation run? if (fInput && fInput->FindObject("ProofStdVect_Create")) { fCreate = kTRUE; } else if (option.Contains("create")) { fCreate = kTRUE; } // If yes, create the output file ... if (fCreate) { // Just create the object UInt_t opt = TProofOutputFile::kRegister | TProofOutputFile::kOverwrite | TProofOutputFile::kVerify; fProofFile = new TProofOutputFile("ProofStdVect.root", TProofOutputFile::kDataset, opt, "TestStdVect"); // Open the file fFile = fProofFile->OpenFile("RECREATE"); if (fFile && fFile->IsZombie()) SafeDelete(fFile); // Cannot continue if (!fFile) { Info("SlaveBegin", "could not create '%s': instance is invalid!", fProofFile->GetName()); return; } // Create a TTree fTree = new TTree("stdvec", "Tree with std vector"); fTree->Branch("Vb",&fVb); fTree->Branch("Vfx",&fVfx); fTree->Branch("Vfy",&fVfy); // File resident fTree->SetDirectory(fFile); fTree->AutoSave(); // Init the random generator fRandom = new TRandom3(0); } else { // Create two histograms fHgood = new TH1F("Hgood", "Good hits", 100., -2.5, 2.5); fHbad = new TH1F("Hbad", "Bad hits", 100., -6., 6.); fOutput->Add(fHgood); fOutput->Add(fHbad); } } //_____________________________________________________________________________ Bool_t ProofStdVect::Process(Long64_t entry) { // The Process() function is called for each entry in the tree (or possibly // keyed object in the case of PROOF) to be processed. The entry argument // specifies which entry in the currently loaded tree is to be processed. // It can be passed to either ProofStdVect::GetEntry() or TBranch::GetEntry() // to read either all or the required parts of the data. When processing // keyed objects with PROOF, the object is already loaded and is available // via the fObject pointer. // // This function should contain the "body" of the analysis. It can contain // simple or elaborate selection criteria, run algorithms on the data // of the event and typically fill histograms. // // The processing can be stopped by calling Abort(). // // Use fStatus to set the return value of TTree::Process(). // // The return value is currently not used. if (fCreate) { if (!fTree) return kTRUE; // Number of vectors Int_t nv = (Int_t) (entry % 10); if (nv < 1) nv = 1; // Create vectors for (Int_t i = 0; i < nv; i++) { std::vector vb; std::vector vfx, vfy; Int_t np = (Int_t) (entry % 100); if (np < 1) np = 1; for (Int_t j = 0; j < np; j++) { float x = (float)j; float y = 5.*x; Double_t sy = (Double_t) (0.1*y); Double_t ym = fRandom->Gaus((Double_t)y, sy); Double_t c2 = TMath::Abs((ym - y) / sy); bool xb = (1. - TMath::Erfc(c2/TMath::Sqrt(2.)) > .95) ? false : true; vb.push_back(xb); vfx.push_back(x); vfy.push_back(float(ym)); } fVb.push_back(vb); fVfx.push_back(vfx); fVfy.push_back(vfy); } // Fill the tree fTree->Fill(); // Clear the vectors std::vector >::iterator ivb; for (ivb = fVb.begin(); ivb != fVb.end(); ivb++) { (*ivb).clear(); } fVb.clear(); std::vector >::iterator ivf; for (ivf = fVfx.begin(); ivf != fVfx.end(); ivf++) { (*ivf).clear(); } fVfx.clear(); for (ivf = fVfy.begin(); ivf != fVfy.end(); ivf++) { (*ivf).clear(); } fVfy.clear(); } else { // Read the entry GetEntry(entry); // Plot normalized values for bad and good hits for (UInt_t i = 0; i < fVfyr->size(); i++) { std::vector &vb = fVbr->at(i); std::vector &vfx = fVfxr->at(i); std::vector &vfy = fVfyr->at(i); for (UInt_t j = 0; j < vfy.size(); j++) { Double_t ny = (vfy.at(j) - 5*vfx.at(j)) / (0.1 * 5 * vfx.at(j)); if (vb.at(j) < 0.5) fHbad->Fill(ny); else fHgood->Fill(ny); } } } return kTRUE; } //_____________________________________________________________________________ void ProofStdVect::SlaveTerminate() { // The SlaveTerminate() function is called after all entries or objects // have been processed. When running with PROOF SlaveTerminate() is called // on each slave server. // Nothing to do in read mode if (!fCreate) return; // Write the ntuple to the file if (fFile) { if (!fTree) { Error("SlaveTerminate", "'tree' is undefined!"); return; } Bool_t cleanup = kFALSE; TDirectory::TContext ctxt; if (fTree->GetEntries() > 0) { fFile->cd(); fTree->Write(); fProofFile->Print(); fOutput->Add(fProofFile); } else { cleanup = kTRUE; } fTree->SetDirectory(nullptr); fFile->Close(); // Cleanup, if needed if (cleanup) { TUrl uf(*(fFile->GetEndpointUrl())); SafeDelete(fFile); gSystem->Unlink(uf.GetFile()); SafeDelete(fProofFile); } } } //_____________________________________________________________________________ void ProofStdVect::Terminate() { // The Terminate() function is the last function to be called during // a query. It always runs on the client, it can be used to present // the results graphically or save the results to file. // Nothing to do in create mode if (fCreate) return; // Create a canvas, with 2 pads TCanvas *c1 = new TCanvas("cvstdvec", "Test StdVec", 800,10,700,780); c1->Divide(1,2); TPad *pad1 = (TPad *) c1->GetPad(1); TPad *pad2 = (TPad *) c1->GetPad(2); pad2->cd(); if (fHbad) fHbad->Draw(); pad1->cd(); if (fHgood) fHgood->Draw(); c1->cd(); c1->Update(); } //_____________________________________________________________________________ void ProofStdVect::Init(TTree *tree) { // The Init() function is called when the selector needs to initialize // a new tree or chain. Typically here the branch addresses and branch // pointers of the tree will be set. // It is normally not necessary to make changes to the generated // code, but the routine can be extended by the user if needed. // Init() will be called many times when running on PROOF // (once per file to be processed). // Nothing to do in create mode if (fCreate) return; // Set object pointer fVbr = nullptr; fVfxr = nullptr; fVfyr = nullptr; // Set branch addresses and branch pointers if (!tree) return; fChain = tree; fChain->SetMakeClass(1); fChain->SetBranchAddress("Vb", &fVbr, &b_Vb); fChain->SetBranchAddress("Vfx", &fVfxr, &b_Vfx); fChain->SetBranchAddress("Vfy", &fVfyr, &b_Vfy); } //_____________________________________________________________________________ Bool_t ProofStdVect::Notify() { // The Notify() function is called when a new file is opened. This // can be either for a new TTree in a TChain or when when a new TTree // is started when using PROOF. It is normally not necessary to make changes // to the generated code, but the routine can be extended by the // user if needed. The return value is currently not used. // Nothing to do in create mode if (fCreate) return kTRUE; Info("Notify","processing file: %s",fChain->GetCurrentFile()->GetName()); return kTRUE; }