diff --git a/parameters/config.xml b/parameters/config.xml index 49dc841..b4a01c0 100644 --- a/parameters/config.xml +++ b/parameters/config.xml @@ -1,212 +1,215 @@ + + + diff --git a/src/InputHandler/GENIEInputHandler.cxx b/src/InputHandler/GENIEInputHandler.cxx index a81cd28..a5eb414 100644 --- a/src/InputHandler/GENIEInputHandler.cxx +++ b/src/InputHandler/GENIEInputHandler.cxx @@ -1,504 +1,503 @@ // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret /******************************************************************************* * This file is part of NUISANCE. * * NUISANCE is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * NUISANCE is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with NUISANCE. If not, see . *******************************************************************************/ #ifdef __GENIE_ENABLED__ #include "GENIEInputHandler.h" #include "InputUtils.h" GENIEGeneratorInfo::~GENIEGeneratorInfo() { DeallocateParticleStack(); } void GENIEGeneratorInfo::AddBranchesToTree(TTree* tn) { tn->Branch("GenieParticlePDGs", &fGenieParticlePDGs, "GenieParticlePDGs/I"); } void GENIEGeneratorInfo::SetBranchesFromTree(TTree* tn) { tn->SetBranchAddress("GenieParticlePDGs", &fGenieParticlePDGs); } void GENIEGeneratorInfo::AllocateParticleStack(int stacksize) { fGenieParticlePDGs = new int[stacksize]; } void GENIEGeneratorInfo::DeallocateParticleStack() { delete fGenieParticlePDGs; } void GENIEGeneratorInfo::FillGeneratorInfo(NtpMCEventRecord* ntpl) { Reset(); // Check for GENIE Event if (!ntpl) return; if (!ntpl->event) return; // Cast Event Record GHepRecord* ghep = static_cast(ntpl->event); if (!ghep) return; // Fill Particle Stack GHepParticle* p = 0; TObjArrayIter iter(ghep); // Loop over all particles int i = 0; while ((p = (dynamic_cast((iter).Next())))) { if (!p) continue; // Get PDG fGenieParticlePDGs[i] = p->Pdg(); i++; } } void GENIEGeneratorInfo::Reset() { for (int i = 0; i < kMaxParticles; i++) { fGenieParticlePDGs[i] = 0; } } GENIEInputHandler::GENIEInputHandler(std::string const& handle, std::string const& rawinputs) { LOG(SAM) << "Creating GENIEInputHandler : " << handle << std::endl; // Run a joint input handling fName = handle; // Setup the TChain fGENIETree = new TChain("gtree"); fSaveExtra = FitPar::Config().GetParB("SaveExtraGenie"); fCacheSize = FitPar::Config().GetParI("CacheSize"); fMaxEvents = FitPar::Config().GetParI("MAXEVENTS"); - // Are we running with NOvA weights - bool nova_wgt = true; + fNOvAWeights = FitPar::Config().GetParB("NOvA_Weights"); MAQEw = 1.0; NonResw = 1.0; RPAQEw = 1.0; RPARESw = 1.0; MECw = 1.0; DISw = 1.0; NOVAw = 1.0; // Loop over all inputs and grab flux, eventhist, and nevents std::vector inputs = InputUtils::ParseInputFileList(rawinputs); for (size_t inp_it = 0; inp_it < inputs.size(); ++inp_it) { // Open File for histogram access TFile* inp_file = new TFile( InputUtils::ExpandInputDirectories(inputs[inp_it]).c_str(), "READ"); if (!inp_file or inp_file->IsZombie()) { THROW("GENIE File IsZombie() at : '" << inputs[inp_it] << "'" << std::endl << "Check that your file paths are correct and the file exists!" << std::endl << "$ ls -lh " << inputs[inp_it]); } // Get Flux/Event hist TH1D* fluxhist = (TH1D*)inp_file->Get("nuisance_flux"); TH1D* eventhist = (TH1D*)inp_file->Get("nuisance_events"); if (!fluxhist or !eventhist) { ERROR(FTL, "Input File Contents: " << inputs[inp_it]); inp_file->ls(); THROW("GENIE FILE doesn't contain flux/xsec info." << std::endl << "Try running the app PrepareGENIE first on :" << inputs[inp_it] << std::endl << "$ PrepareGENIE -h"); } // Get N Events TTree* genietree = (TTree*)inp_file->Get("gtree"); if (!genietree) { ERROR(FTL, "gtree not located in GENIE file: " << inputs[inp_it]); THROW("Check your inputs, they may need to be completely regenerated!"); throw; } int nevents = genietree->GetEntries(); if (nevents <= 0) { THROW("Trying to a TTree with " << nevents << " to TChain from : " << inputs[inp_it]); } // Check for precomputed weights TTree *weighttree = (TTree*)inp_file->Get("nova_wgts"); - if (!weighttree) { - LOG(FIT) << "Did not find nova_wgts tree in file " << inputs[inp_it] << std::endl; - nova_wgt = false; - } else { - LOG(FIT) << "Found nova_wgts tree in file " << inputs[inp_it] << std::endl; - nova_wgt = true; + if (fNOvAWeights) { + if (!weighttree) { + THROW("Did not find nova_wgts tree in file " << inputs[inp_it] << " but you specified it" << std::endl); + } else { + LOG(FIT) << "Found nova_wgts tree in file " << inputs[inp_it] << std::endl; + } } // Register input to form flux/event rate hists RegisterJointInput(inputs[inp_it], nevents, fluxhist, eventhist); // Add To TChain fGENIETree->AddFile(inputs[inp_it].c_str()); if (weighttree != NULL) fGENIETree->AddFriend(weighttree); } // Registor all our file inputs SetupJointInputs(); // Assign to tree fEventType = kGENIE; fGenieNtpl = NULL; fGENIETree->SetBranchAddress("gmcrec", &fGenieNtpl); // Set up the custom weights - if (nova_wgt) { + if (fNOvAWeights) { fGENIETree->SetBranchAddress("MAQEwgt", &MAQEw); fGENIETree->SetBranchAddress("nonResNormWgt", &NonResw); fGENIETree->SetBranchAddress("RPAQEWgt", &RPAQEw); fGENIETree->SetBranchAddress("RPARESWgt", &RPARESw); fGENIETree->SetBranchAddress("MECWgt", &MECw); fGENIETree->SetBranchAddress("DISWgt", &DISw); fGENIETree->SetBranchAddress("nova2018CVWgt", &NOVAw); } // Libraries should be seen but not heard... StopTalking(); fGENIETree->GetEntry(0); StartTalking(); // Create Fit Event fNUISANCEEvent = new FitEvent(); fNUISANCEEvent->SetGenieEvent(fGenieNtpl); if (fSaveExtra) { fGenieInfo = new GENIEGeneratorInfo(); fNUISANCEEvent->AddGeneratorInfo(fGenieInfo); } fNUISANCEEvent->HardReset(); }; GENIEInputHandler::~GENIEInputHandler() { // if (fGenieGHep) delete fGenieGHep; // if (fGenieNtpl) delete fGenieNtpl; // if (fGENIETree) delete fGENIETree; // if (fGenieInfo) delete fGenieInfo; } void GENIEInputHandler::CreateCache() { if (fCacheSize > 0) { // fGENIETree->SetCacheEntryRange(0, fNEvents); fGENIETree->AddBranchToCache("*", 1); fGENIETree->SetCacheSize(fCacheSize); } } void GENIEInputHandler::RemoveCache() { // fGENIETree->SetCacheEntryRange(0, fNEvents); fGENIETree->AddBranchToCache("*", 0); fGENIETree->SetCacheSize(0); } FitEvent* GENIEInputHandler::GetNuisanceEvent(const UInt_t entry, const bool lightweight) { if (entry >= (UInt_t)fNEvents) return NULL; // Read Entry from TTree to fill NEUT Vect in BaseFitEvt; fGENIETree->GetEntry(entry); // Run NUISANCE Vector Filler if (!lightweight) { CalcNUISANCEKinematics(); } #ifdef __PROB3PP_ENABLED__ else { // Check for GENIE Event if (!fGenieNtpl) return NULL; if (!fGenieNtpl->event) return NULL; // Cast Event Record fGenieGHep = static_cast(fGenieNtpl->event); if (!fGenieGHep) return NULL; TObjArrayIter iter(fGenieGHep); genie::GHepParticle* p; while ((p = (dynamic_cast((iter).Next())))) { if (!p) { continue; } // Get Status int state = GetGENIEParticleStatus(p, fNUISANCEEvent->Mode); if (state != genie::kIStInitialState) { continue; } fNUISANCEEvent->probe_E = p->E() * 1.E3; fNUISANCEEvent->probe_pdg = p->Pdg(); break; } } #endif // Setup Input scaling for joint inputs fNUISANCEEvent->InputWeight = GetInputWeight(entry); return fNUISANCEEvent; } int GENIEInputHandler::GetGENIEParticleStatus(genie::GHepParticle* p, int mode) { /* kIStUndefined = -1, kIStInitialState = 0, / generator-level initial state / kIStStableFinalState = 1, / generator-level final state: particles to be tracked by detector-level MC / kIStIntermediateState = 2, kIStDecayedState = 3, kIStCorrelatedNucleon = 10, kIStNucleonTarget = 11, kIStDISPreFragmHadronicState = 12, kIStPreDecayResonantState = 13, kIStHadronInTheNucleus = 14, / hadrons inside the nucleus: marked for hadron transport modules to act on / kIStFinalStateNuclearRemnant = 15, / low energy nuclear fragments entering the record collectively as a 'hadronic blob' pseudo-particle / kIStNucleonClusterTarget = 16, // for composite nucleons before phase space decay */ int state = kUndefinedState; switch (p->Status()) { case genie::kIStNucleonTarget: case genie::kIStInitialState: case genie::kIStCorrelatedNucleon: case genie::kIStNucleonClusterTarget: state = kInitialState; break; case genie::kIStStableFinalState: state = kFinalState; break; case genie::kIStHadronInTheNucleus: if (abs(mode) == 2) state = kInitialState; else state = kFSIState; break; case genie::kIStPreDecayResonantState: case genie::kIStDISPreFragmHadronicState: case genie::kIStIntermediateState: state = kFSIState; break; case genie::kIStFinalStateNuclearRemnant: case genie::kIStUndefined: case genie::kIStDecayedState: default: break; } // Flag to remove nuclear part in genie if (p->Pdg() > 1000000) { if (state == kInitialState) state = kNuclearInitial; else if (state == kFinalState) state = kNuclearRemnant; } return state; } #endif #ifdef __GENIE_ENABLED__ int GENIEInputHandler::ConvertGENIEReactionCode(GHepRecord* gheprec) { // Electron Scattering if (gheprec->Summary()->ProcInfo().IsEM()) { if (gheprec->Summary()->InitState().ProbePdg() == 11) { if (gheprec->Summary()->ProcInfo().IsQuasiElastic()) return 1; else if (gheprec->Summary()->ProcInfo().IsMEC()) return 2; else if (gheprec->Summary()->ProcInfo().IsResonant()) return 13; else if (gheprec->Summary()->ProcInfo().IsDeepInelastic()) return 26; else { ERROR(WRN, "Unknown GENIE Electron Scattering Mode!" << std::endl << "ScatteringTypeId = " << gheprec->Summary()->ProcInfo().ScatteringTypeId() << " " << "InteractionTypeId = " << gheprec->Summary()->ProcInfo().InteractionTypeId() << std::endl << genie::ScatteringType::AsString( gheprec->Summary()->ProcInfo().ScatteringTypeId()) << " " << genie::InteractionType::AsString( gheprec->Summary()->ProcInfo().InteractionTypeId()) << " " << gheprec->Summary()->ProcInfo().IsMEC()); return 0; } } // Weak CC } else if (gheprec->Summary()->ProcInfo().IsWeakCC()) { // CC MEC if (gheprec->Summary()->ProcInfo().IsMEC()) { if (pdg::IsNeutrino(gheprec->Summary()->InitState().ProbePdg())) return 2; else if (pdg::IsAntiNeutrino(gheprec->Summary()->InitState().ProbePdg())) return -2; // CC OTHER } else { return utils::ghep::NeutReactionCode(gheprec); } // Weak NC } else if (gheprec->Summary()->ProcInfo().IsWeakNC()) { // NC MEC if (gheprec->Summary()->ProcInfo().IsMEC()) { if (pdg::IsNeutrino(gheprec->Summary()->InitState().ProbePdg())) return 32; else if (pdg::IsAntiNeutrino(gheprec->Summary()->InitState().ProbePdg())) return -32; // NC OTHER } else { return utils::ghep::NeutReactionCode(gheprec); } } return 0; } void GENIEInputHandler::CalcNUISANCEKinematics() { // Reset all variables fNUISANCEEvent->ResetEvent(); // Check for GENIE Event if (!fGenieNtpl) return; if (!fGenieNtpl->event) return; // Cast Event Record fGenieGHep = static_cast(fGenieNtpl->event); if (!fGenieGHep) return; // Convert GENIE Reaction Code fNUISANCEEvent->Mode = ConvertGENIEReactionCode(fGenieGHep); // Set Event Info fNUISANCEEvent->fEventNo = 0.0; fNUISANCEEvent->fTotCrs = fGenieGHep->XSec(); fNUISANCEEvent->fTargetA = 0.0; fNUISANCEEvent->fTargetZ = 0.0; fNUISANCEEvent->fTargetH = 0; fNUISANCEEvent->fBound = 0.0; fNUISANCEEvent->InputWeight = 1.0; //(1E+38 / genie::units::cm2) * fGenieGHep->XSec(); // And the custom weights - fNUISANCEEvent->CustomWeight = NOVAw; - fNUISANCEEvent->CustomWeightArray[0] = MAQEw; - fNUISANCEEvent->CustomWeightArray[1] = NonResw; - fNUISANCEEvent->CustomWeightArray[2] = RPAQEw; - fNUISANCEEvent->CustomWeightArray[3] = RPARESw; - fNUISANCEEvent->CustomWeightArray[4] = MECw; - fNUISANCEEvent->CustomWeightArray[5] = NOVAw; - - /* - fNUISANCEEvent->CustomWeight = 1.0; - fNUISANCEEvent->CustomWeightArray[0] = 1.0; - fNUISANCEEvent->CustomWeightArray[1] = 1.0; - fNUISANCEEvent->CustomWeightArray[2] = 1.0; - fNUISANCEEvent->CustomWeightArray[3] = 1.0; - fNUISANCEEvent->CustomWeightArray[4] = 1.0; - fNUISANCEEvent->CustomWeightArray[5] = 1.0; - */ + if (fNOvAWeights) { + fNUISANCEEvent->CustomWeight = NOVAw; + fNUISANCEEvent->CustomWeightArray[0] = MAQEw; + fNUISANCEEvent->CustomWeightArray[1] = NonResw; + fNUISANCEEvent->CustomWeightArray[2] = RPAQEw; + fNUISANCEEvent->CustomWeightArray[3] = RPARESw; + fNUISANCEEvent->CustomWeightArray[4] = MECw; + fNUISANCEEvent->CustomWeightArray[5] = NOVAw; + } else { + fNUISANCEEvent->CustomWeight = 1.0; + fNUISANCEEvent->CustomWeightArray[0] = 1.0; + fNUISANCEEvent->CustomWeightArray[1] = 1.0; + fNUISANCEEvent->CustomWeightArray[2] = 1.0; + fNUISANCEEvent->CustomWeightArray[3] = 1.0; + fNUISANCEEvent->CustomWeightArray[4] = 1.0; + fNUISANCEEvent->CustomWeightArray[5] = 1.0; + } // Get N Particle Stack unsigned int npart = fGenieGHep->GetEntries(); unsigned int kmax = fNUISANCEEvent->kMaxParticles; if (npart > kmax) { ERR(WRN) << "GENIE has too many particles, expanding stack." << std::endl; fNUISANCEEvent->ExpandParticleStack(npart); } // Fill Particle Stack GHepParticle* p = 0; TObjArrayIter iter(fGenieGHep); fNUISANCEEvent->fNParticles = 0; // Loop over all particles while ((p = (dynamic_cast((iter).Next())))) { if (!p) continue; // Get Status int state = GetGENIEParticleStatus(p, fNUISANCEEvent->Mode); // Remove Undefined if (kRemoveUndefParticles && state == kUndefinedState) continue; // Remove FSI if (kRemoveFSIParticles && state == kFSIState) continue; if (kRemoveNuclearParticles && (state == kNuclearInitial || state == kNuclearRemnant)) continue; // Fill Vectors int curpart = fNUISANCEEvent->fNParticles; fNUISANCEEvent->fParticleState[curpart] = state; // Mom fNUISANCEEvent->fParticleMom[curpart][0] = p->Px() * 1.E3; fNUISANCEEvent->fParticleMom[curpart][1] = p->Py() * 1.E3; fNUISANCEEvent->fParticleMom[curpart][2] = p->Pz() * 1.E3; fNUISANCEEvent->fParticleMom[curpart][3] = p->E() * 1.E3; // PDG fNUISANCEEvent->fParticlePDG[curpart] = p->Pdg(); // Add to N particle count fNUISANCEEvent->fNParticles++; // Extra Check incase GENIE fails. if ((UInt_t)fNUISANCEEvent->fNParticles == kmax) { ERR(WRN) << "Number of GENIE Particles exceeds maximum!" << std::endl; ERR(WRN) << "Extend kMax, or run without including FSI particles!" << std::endl; break; } } // Fill Extra Stack if (fSaveExtra) fGenieInfo->FillGeneratorInfo(fGenieNtpl); // Run Initial, FSI, Final, Other ordering. fNUISANCEEvent->OrderStack(); FitParticle* ISNeutralLepton = fNUISANCEEvent->GetHMISParticle(PhysConst::pdg_neutrinos); if (ISNeutralLepton) { fNUISANCEEvent->probe_E = ISNeutralLepton->E(); fNUISANCEEvent->probe_pdg = ISNeutralLepton->PDG(); } return; } void GENIEInputHandler::Print() {} #endif diff --git a/src/InputHandler/GENIEInputHandler.h b/src/InputHandler/GENIEInputHandler.h index 818fda8..d2a1d18 100644 --- a/src/InputHandler/GENIEInputHandler.h +++ b/src/InputHandler/GENIEInputHandler.h @@ -1,117 +1,119 @@ // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret /******************************************************************************* * This file is part of NUISANCE. * * NUISANCE is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * NUISANCE is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with NUISANCE. If not, see . *******************************************************************************/ #ifndef GENIEINPUTHANDLER_H #define GENIEINPUTHANDLER_H /*! * \addtogroup InputHandler * @{ */ #ifdef __GENIE_ENABLED__ #include "InputHandler.h" #include "InputUtils.h" #include "PlotUtils.h" #include "GHEP/GHepParticle.h" #include "PDG/PDGUtils.h" #include "GHEP/GHepUtils.h" #include "Conventions/Units.h" #include "EVGCore/EventRecord.h" #include "GHEP/GHepRecord.h" #include "Ntuple/NtpMCEventRecord.h" using namespace genie; /// GENIE Generator Container to save extra particle status codes. class GENIEGeneratorInfo : public GeneratorInfoBase { public: GENIEGeneratorInfo() {}; virtual ~GENIEGeneratorInfo(); /// Assigns information to branches void AddBranchesToTree(TTree* tn); /// Setup reading information from branches void SetBranchesFromTree(TTree* tn); /// Allocate any dynamic arrays for a new particle stack size void AllocateParticleStack(int stacksize); /// Clear any dynamic arrays void DeallocateParticleStack(); /// Read extra genie information from the event void FillGeneratorInfo(NtpMCEventRecord* ntpl); /// Reset extra information to default/empty values void Reset(); int kMaxParticles; ///< Number of particles in stack int* fGenieParticlePDGs; ///< GENIE Particle PDGs (example) }; /// Main GENIE InputHandler class GENIEInputHandler : public InputHandlerBase { public: /// Standard constructor given a name and input files GENIEInputHandler(std::string const& handle, std::string const& rawinputs); virtual ~GENIEInputHandler(); /// Create a TTree Cache to speed up file read void CreateCache(); /// Remove TTree Cache to save memory void RemoveCache(); /// Returns a NUISANCE format event from the GENIE TTree. If !lightweight /// then CalcNUISANCEKinematics() is called to convert the GENIE event into /// a standard NUISANCE format. FitEvent* GetNuisanceEvent(const UInt_t entry, const bool lightweight = false); /// Converts GENIE event into standard NUISANCE FitEvent by looping over all /// particles in the event and adding them to stack in fNUISANCEEvent. void CalcNUISANCEKinematics(); /// Placeholder for GENIE related event printing. void Print(); /// Converts GENIE particle status codes into NUISANCE status codes. int GetGENIEParticleStatus(genie::GHepParticle* part, int mode = 0); /// Converts GENIE event reaction codes into NUISANCE reaction codes. int ConvertGENIEReactionCode(GHepRecord* gheprec); GHepRecord* fGenieGHep; ///< Pointer to actual event record NtpMCEventRecord* fGenieNtpl; ///< Ntpl Wrapper Class TChain* fGENIETree; ///< Main GENIE Event TTree bool fSaveExtra; ///< Flag to save Extra GENIE info into Nuisance Event GENIEGeneratorInfo* fGenieInfo; ///< Extra GENIE Generator Info Writer - // Extra weights from Jeremgy + bool fNOvAWeights; ///< Flag to save nova weights or not + + // Extra weights from Jeremy for NOvA weights double MAQEw; double NonResw; double RPAQEw; double RPARESw; double MECw; double DISw; double NOVAw; }; /*! @} */ #endif #endif