diff --git a/src/Utils/SignalDef.cxx b/src/Utils/SignalDef.cxx index 03456ad..13f4204 100644 --- a/src/Utils/SignalDef.cxx +++ b/src/Utils/SignalDef.cxx @@ -1,289 +1,291 @@ // Copyright 2016-2021 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 . *******************************************************************************/ #include "FitUtils.h" #include "SignalDef.h" bool SignalDef::isCCINC(FitEvent *event, int nuPDG, double EnuMin, double EnuMax) { // Check for the desired PDG code if (!event->HasISParticle(nuPDG)) return false; // Check that it's within the allowed range if set if (EnuMin != EnuMax) { if (!SignalDef::IsEnuInRange(event, EnuMin*1000, EnuMax*1000)) { return false; } } // Check that the charged lepton we expect has been produced if (!event->HasFSParticle(nuPDG > 0 ? nuPDG-1 : nuPDG+1)) return false; return true; } bool SignalDef::isNCINC(FitEvent *event, int nuPDG, double EnuMin, double EnuMax) { // Check for the desired PDG code before and after the interaction if (!event->HasISParticle(nuPDG) || !event->HasFSParticle(nuPDG)) return false; // Check that it's within the allowed range if set if (EnuMin != EnuMax) if (!SignalDef::IsEnuInRange(event, EnuMin*1000, EnuMax*1000)) return false; return true; } bool SignalDef::isCC0pi(FitEvent *event, int nuPDG, double EnuMin, double EnuMax){ // Check it's CCINC if (!SignalDef::isCCINC(event, nuPDG, EnuMin, EnuMax)) return false; // Veto event with mesons if (event->NumFSMesons() != 0) return false; // Veto events which don't have exactly 1 outgoing charged lepton if (event->NumFSLeptons() != 1) return false; return true; } bool SignalDef::isNC0pi(FitEvent *event, int nuPDG, double EnuMin, double EnuMax){ // Check it's NCINC if (!SignalDef::isNCINC(event, nuPDG, EnuMin, EnuMax)) return false; // Veto event with mesons if (event->NumFSMesons() != 0) return false; // Veto events with a charged lepton if (event->NumFSLeptons() != 0) return false; return true; } bool SignalDef::isCCQE(FitEvent *event, int nuPDG, double EnuMin, double EnuMax){ // Check if it's CCINC if (!SignalDef::isCCINC(event, nuPDG, EnuMin, EnuMax)) return false; // Require modes 1 (CCQE) if (abs(event->Mode) != 1) return false; return true; } bool SignalDef::isNCEL(FitEvent *event, int nuPDG, double EnuMin, double EnuMax){ // Check if it's NCINC if (!SignalDef::isNCINC(event, nuPDG, EnuMin, EnuMax)) return false; // Require modes 51/52 (NCEL) if (abs(event->Mode) != 51 && abs(event->Mode) != 52) return false; return true; } bool SignalDef::isCCQELike(FitEvent *event, int nuPDG, double EnuMin, double EnuMax){ // Check if it's CCINC if (!SignalDef::isCCINC(event, nuPDG, EnuMin, EnuMax)) return false; // Require modes 1/2 (CCQE and MEC) if (abs(event->Mode) != 1 && abs(event->Mode) != 2) return false; return true; } // Require one meson, one charged lepton. types specified in the arguments bool SignalDef::isCC1pi(FitEvent *event, int nuPDG, int piPDG, double EnuMin, double EnuMax){ // First, make sure it's CCINC if (!SignalDef::isCCINC(event, nuPDG, EnuMin, EnuMax)) return false; int nMesons = event->NumFSMesons(); int nLeptons = event->NumFSLeptons(); int nPion = event->NumFSParticle(piPDG); // Check that the desired pion exists and is the only meson if (nPion != 1 || nMesons != 1) return false; // Check that there is only one final state lepton if (nLeptons != 1) return false; return true; } // Require one meson, one neutrino. Types specified as arguments bool SignalDef::isNC1pi(FitEvent *event, int nuPDG, int piPDG, double EnuMin, double EnuMax){ // First, make sure it's NCINC if (!SignalDef::isNCINC(event, nuPDG, EnuMin, EnuMax)) return false; int nMesons = event->NumFSMesons(); int nLeptons = event->NumFSLeptons(); int nPion = event->NumFSParticle(piPDG); // Check that the desired pion exists and is the only meson if (nPion != 1 || nMesons != 1) return false; // Check that there are no charged leptons if (nLeptons != 0) return false; return true; } // A slightly ugly function to replace the BC 2pi channels. // All particles which are allowed in the final state are specified bool SignalDef::isCCWithFS(FitEvent *event, int nuPDG, std::vector pdgs, double EnuMin, double EnuMax){ // Check it's CCINC if (!SignalDef::isCCINC(event, nuPDG, EnuMin, EnuMax)) return false; // Remove events where the number of final state particles // do not match the number specified in the signal definition if ((int)pdgs.size() != event->NumFSParticle()) return false; // For every particle in the list, check the number in the FS for (std::vector::iterator it = pdgs.begin(); it != pdgs.end(); ++it){ // Check how many times this pdg is in the vector int nEntries = std::count (pdgs.begin(), pdgs.end(), *it); if (event->NumFSParticle(*it) != nEntries) return false; } return true; } // Require one meson, one charged lepton, AND specify the only other final state particle // This is only suitable for bubble chambers. Types specified in the arguments bool SignalDef::isCC1pi3Prong(FitEvent *event, int nuPDG, int piPDG, int thirdPDG, double EnuMin, double EnuMax){ // First, make sure it's CC1pi if (!SignalDef::isCC1pi(event, nuPDG, piPDG, EnuMin, EnuMax)) return false; // Check we have the third prong if (event->NumFSParticle(thirdPDG) == 0) return false; // Check that there are only three FS particles if (event->NumFSParticle() != 3) return false; return true; } // Require one meson, one neutrino, AND specify the only other final state particle // This is only suitable for bubble chambers. Types specified in the arguments bool SignalDef::isNC1pi3Prong(FitEvent *event, int nuPDG, int piPDG, int thirdPDG, double EnuMin, double EnuMax){ // First, make sure it's NC1pi if (!SignalDef::isNC1pi(event, nuPDG, piPDG, EnuMin, EnuMax)) return false; // Check we have the third prong if (event->NumFSParticle(thirdPDG) == 0) return false; // Check that there are only three FS particles if (event->NumFSParticle() != 3) return false; return true; } bool SignalDef::isCCCOH(FitEvent *event, int nuPDG, int piPDG, double EnuMin, double EnuMax){ // Check this is a CCINC event if (!SignalDef::isCCINC(event, nuPDG, EnuMin, EnuMax)) return false; int nLepton = event->NumFSParticle(nuPDG > 0 ? nuPDG-1 : nuPDG+1); int nPion = event->NumFSParticle(piPDG); int nFS = event->NumFSParticle(); if (nLepton != 1 || nPion != 1) return false; - if (nFS != 2) return false; + // if (nFS != 2) return false; + // GENIE v3 includes the nucleus in the final state, so modify the definition for now... + if (abs(event->Mode) != 16) return false; return true; } bool SignalDef::isNCCOH(FitEvent *event, int nuPDG, int piPDG, double EnuMin, double EnuMax){ // Check this is an NCINC event if (!SignalDef::isNCINC(event, nuPDG, EnuMin, EnuMax)) return false; int nLepton = event->NumFSParticle(nuPDG); int nPion = event->NumFSParticle(piPDG); int nFS = event->NumFSParticle(); if (nLepton != 1 || nPion != 1) return false; if (nFS != 2) return false; return true; } bool SignalDef::HasProtonKEAboveThreshold(FitEvent* event, double threshold){ for (uint i = 0; i < event->Npart(); i++){ FitParticle* p = event->PartInfo(i); if (!p->IsFinalState()) continue; if (p->fPID != 2212) continue; if (FitUtils::T(p->fP) > threshold / 1000.0) return true; } return false; } bool SignalDef::HasProtonMomAboveThreshold(FitEvent* event, double threshold){ for (uint i = 0; i < event->Npart(); i++){ FitParticle* p = event->PartInfo(i); if (!p->IsFinalState()) continue; if (p->fPID != 2212) continue; if (p->fP.Vect().Mag() > threshold) return true; } return false; } // Calculate the angle between the neutrino and an outgoing particle, apply a cut bool SignalDef::IsRestrictedAngle(FitEvent* event, int nuPDG, int otherPDG, double angle){ // If the particles don't exist, return false if (!event->HasISParticle(nuPDG) || !event->HasFSParticle(otherPDG)) return false; // Get Mom TVector3 pnu = event->GetHMISParticle(nuPDG)->fP.Vect(); TVector3 p2 = event->GetHMFSParticle(otherPDG)->fP.Vect(); double theta = pnu.Angle(p2) * 180. / TMath::Pi(); return (theta < angle); } bool SignalDef::IsEnuInRange(FitEvent* event, double emin, double emax){ return (event->GetNeutrinoIn()->fP.E() > emin && event->GetNeutrinoIn()->fP.E() < emax); }