diff --git a/app/nuwro_NUISANCE.cxx b/app/nuwro_NUISANCE.cxx index fe8053c..a95b1ab 100644 --- a/app/nuwro_NUISANCE.cxx +++ b/app/nuwro_NUISANCE.cxx @@ -1,486 +1,512 @@ #ifdef __NUWRO_ENABLED__ #include "ComparisonRoutines.h" #include "ParserUtils.h" +#include "TargetUtils.h" // All possible inputs std::string gOptEnergyDef; std::vector gOptEnergyRange; int gOptNumberEvents = -1; int gOptNumberTestEvents = 5E6; std::string gOptGeneratorList = "Default"; -std::string gOptCrossSections = "Default"; // If default this will look in $NUISANCE/data/nuwro/default_params.txt +std::string gOptCrossSections = + "Default"; // If default this will look in + // $NUISANCE/data/nuwro/default_params.txt int gOptSeed = time(NULL); std::string gOptTargetDef = ""; std::string gOptFluxDef = ""; std::string gOptOutputFile = ""; int gOptRunNumber = -1; -void GetCommandLineArgs (int argc, char ** argv); -void PrintSyntax (void); - -std::string GetDynamicModes(std::string list){ +void GetCommandLineArgs(int argc, char** argv); +void PrintSyntax(void); +std::string GetDynamicModes(std::string list) { LOG(FIT) << "Using " << list << " to define interaction modes." << std::endl; std::map modes; - if (!list.compare("Default")){ + if (!list.compare("Default")) { modes["dyn_qel_cc"] = 1; // Quasi elastic charged current modes["dyn_qel_nc"] = 1; // Quasi elastic neutral current modes["dyn_res_cc"] = 1; // Resonant charged current modes["dyn_res_nc"] = 1; // Resonant neutral current modes["dyn_dis_cc"] = 1; // Deep inelastic charged current modes["dyn_dis_nc"] = 1; // Deep inelastic neutral current modes["dyn_coh_cc"] = 1; // Coherent charged current modes["dyn_coh_nc"] = 1; // Coherent neutral current modes["dyn_mec_cc"] = 0; // Meson exchange charged current modes["dyn_mec_nc"] = 0; // Meson exchange neutral current - } else if (!list.compare("DefaultFree")){ - modes["dyn_qel_cc"] = 1; // Quasi elastic charged current - modes["dyn_qel_nc"] = 1; // Quasi elastic neutral current - modes["dyn_res_cc"] = 1; // Resonant charged current - modes["dyn_res_nc"] = 1; // Resonant neutral current - modes["dyn_dis_cc"] = 1; // Deep inelastic charged current - modes["dyn_dis_nc"] = 1; // Deep inelastic neutral current - modes["dyn_coh_cc"] = 0; // Coherent charged current - modes["dyn_coh_nc"] = 0; // Coherent neutral current - modes["dyn_mec_cc"] = 0; // Meson exchange charged current - modes["dyn_mec_nc"] = 0; // Meson exchange neutral current - - } else if (!list.compare("Default+MEC")){ + } else if (!list.compare("DefaultFree")) { + modes["dyn_qel_cc"] = 1; // Quasi elastic charged current + modes["dyn_qel_nc"] = 1; // Quasi elastic neutral current + modes["dyn_res_cc"] = 1; // Resonant charged current + modes["dyn_res_nc"] = 1; // Resonant neutral current + modes["dyn_dis_cc"] = 1; // Deep inelastic charged current + modes["dyn_dis_nc"] = 1; // Deep inelastic neutral current + modes["dyn_coh_cc"] = 0; // Coherent charged current + modes["dyn_coh_nc"] = 0; // Coherent neutral current + modes["dyn_mec_cc"] = 0; // Meson exchange charged current + modes["dyn_mec_nc"] = 0; // Meson exchange neutral current + + } else if (!list.compare("Default+MEC")) { modes["dyn_qel_cc"] = 1; // Quasi elastic charged current modes["dyn_qel_nc"] = 1; // Quasi elastic neutral current modes["dyn_res_cc"] = 1; // Resonant charged current modes["dyn_res_nc"] = 1; // Resonant neutral current modes["dyn_dis_cc"] = 1; // Deep inelastic charged current modes["dyn_dis_nc"] = 1; // Deep inelastic neutral current modes["dyn_coh_cc"] = 1; // Coherent charged current modes["dyn_coh_nc"] = 1; // Coherent neutral current modes["dyn_mec_cc"] = 1; // Meson exchange charged current modes["dyn_mec_nc"] = 1; // Meson exchange neutral current } else { THROW("Event generator list " << list << " not found!"); } std::string modestring = ""; - for(std::map::iterator iter = modes.begin(); - iter != modes.end(); iter++){ + for (std::map::iterator iter = modes.begin(); + iter != modes.end(); iter++) { std::cout << " -> " << iter->first << " : " << iter->second << std::endl; - modestring += " -p \"" + iter->first + "=" + GeneralUtils::IntToStr(iter->second) + "\""; + modestring += " -p \"" + iter->first + "=" + + GeneralUtils::IntToStr(iter->second) + "\""; } return modestring; } -std::string GetFluxDefinition(std::string flux, std::string out){ +std::string GetFluxDefinition(std::string flux, std::string out) { LOG(FIT) << "Using " << flux << " to define NuWro beam." << std::endl; // By default the flux is type 6 with a root file - std::vector fluxargs = GeneralUtils::ParseToStr(flux,","); - if (fluxargs.size() < 2){ - THROW("Expected flux in the format: file.root,hist_name1[pdg1],... : reveived : " << flux); + std::vector fluxargs = GeneralUtils::ParseToStr(flux, ","); + if (fluxargs.size() < 2) { + THROW( + "Expected flux in the format: file.root,hist_name1[pdg1],... : " + "reveived : " + << flux); } // Build Map std::map fluxmap; fluxmap["beam_type"] = "6"; fluxmap["beam_inputroot"] = fluxargs[0]; - fluxmap["beam_inputroot_nue"] = ""; - fluxmap["beam_inputroot_nueb"] = ""; - fluxmap["beam_inputroot_numu"] = ""; - fluxmap["beam_inputroot_numub"] = ""; - fluxmap["beam_inputroot_nutau"] = ""; + fluxmap["beam_inputroot_nue"] = ""; + fluxmap["beam_inputroot_nueb"] = ""; + fluxmap["beam_inputroot_numu"] = ""; + fluxmap["beam_inputroot_numub"] = ""; + fluxmap["beam_inputroot_nutau"] = ""; fluxmap["beam_inputroot_nutaub"] = ""; // Split by beam bdgs - for (int i = 1; i < fluxargs.size(); i++){ + for (int i = 1; i < fluxargs.size(); i++) { std::string histdef = fluxargs[i]; - string::size_type open_bracket = histdef.find("["); + string::size_type open_bracket = histdef.find("["); string::size_type close_bracket = histdef.find("]"); string::size_type ibeg = 0; string::size_type iend = open_bracket; - string::size_type jbeg = open_bracket+1; - string::size_type jend = close_bracket-1; - std::string name = std::string(histdef.substr(ibeg,iend).c_str()); - int pdg = atoi(histdef.substr(jbeg,jend).c_str()); - - if (pdg == 12) fluxmap["beam_inputroot_nue"] = name; - else if (pdg ==-12) fluxmap["beam_inputroot_nueb"] = name; - else if (pdg == 14) fluxmap["beam_inputroot_numu"] = name; - else if (pdg ==-14) fluxmap["beam_inputroot_numub"] = name; - else if (pdg == 16) fluxmap["beam_inputroot_nutau"] = name; - else if (pdg ==-16) fluxmap["beam_inputroot_nutaub"] = name; + string::size_type jbeg = open_bracket + 1; + string::size_type jend = close_bracket - 1; + std::string name = std::string(histdef.substr(ibeg, iend).c_str()); + int pdg = atoi(histdef.substr(jbeg, jend).c_str()); + + if (pdg == 12) + fluxmap["beam_inputroot_nue"] = name; + else if (pdg == -12) + fluxmap["beam_inputroot_nueb"] = name; + else if (pdg == 14) + fluxmap["beam_inputroot_numu"] = name; + else if (pdg == -14) + fluxmap["beam_inputroot_numub"] = name; + else if (pdg == 16) + fluxmap["beam_inputroot_nutau"] = name; + else if (pdg == -16) + fluxmap["beam_inputroot_nutaub"] = name; } - - // Now create a new flux file matching the output file - std::cout << " -> Moving flux from '" + fluxmap["beam_inputroot"] + "' to current directory to keep everything organised." << std::endl; - TFile* fluxread = new TFile(fluxmap["beam_inputroot"].c_str(),"READ"); - TFile* fluxwrite = new TFile((out + ".flux.root").c_str(),"RECREATE"); - for(std::map::iterator iter = fluxmap.begin(); - iter != fluxmap.end(); iter++){ + // Now create a new flux file matching the output file + std::cout << " -> Moving flux from '" + fluxmap["beam_inputroot"] + + "' to current directory to keep everything organised." + << std::endl; + TFile* fluxread = new TFile(fluxmap["beam_inputroot"].c_str(), "READ"); + TFile* fluxwrite = new TFile((out + ".flux.root").c_str(), "RECREATE"); + + for (std::map::iterator iter = fluxmap.begin(); + iter != fluxmap.end(); iter++) { TH1* temp = (TH1*)fluxread->Get(iter->second.c_str()); if (!temp) continue; TH1D* cuthist = (TH1D*)temp->Clone(); // Restrict energy range if required - if (gOptEnergyRange.size() == 2){ - for (int i = 0; i < cuthist->GetNbinsX(); i++){ - if (cuthist->GetXaxis()->GetBinCenter(i+1) < gOptEnergyRange[0] or - cuthist->GetXaxis()->GetBinCenter(i+1) > gOptEnergyRange[1]){ - cuthist->SetBinContent(i+1, 0.0); - } + if (gOptEnergyRange.size() == 2) { + for (int i = 0; i < cuthist->GetNbinsX(); i++) { + if (cuthist->GetXaxis()->GetBinCenter(i + 1) < gOptEnergyRange[0] or + cuthist->GetXaxis()->GetBinCenter(i + 1) > gOptEnergyRange[1]) { + cuthist->SetBinContent(i + 1, 0.0); + } } } // Check Flux - if (cuthist->Integral() <= 0.0){ + if (cuthist->Integral() <= 0.0) { THROW("Flux histogram " << iter->second << " has integral <= 0.0"); } // Save fluxwrite->cd(); cuthist->Write(); } std::cout << " ->-> Saved to : " << (out + ".flux.root") << std::endl; fluxmap["beam_inputroot"] = (out + ".flux.root"); fluxwrite->Close(); // Return a parameters string std::string fluxstring = ""; - for(std::map::iterator iter = fluxmap.begin(); - iter != fluxmap.end(); iter++){ + for (std::map::iterator iter = fluxmap.begin(); + iter != fluxmap.end(); iter++) { std::cout << " -> " << iter->first << " : " << iter->second << std::endl; fluxstring += " -p \"" + iter->first + "=" + iter->second + "\""; } return fluxstring; } -std::string GetTargetDefinition(std::string target){ - +std::string GetTargetDefinition(std::string target) { LOG(FIT) << "Defining NuWro Target from : " << target << std::endl; - // Target is given as either a single PDG, or a combo with the total number of nucleons - std::vector trgts = GeneralUtils::ParseToStr(target,","); + // Target is given as either a single PDG, or a combo with the total number of + // nucleons + std::vector trgts = GeneralUtils::ParseToStr(target, ","); std::string targetstring = ""; // Single Target - if (trgts.size() == 1){ - + if (trgts.size() == 1) { int PDG = GeneralUtils::StrToInt(trgts[0]); int Z = TargetUtils::GetTargetZFromPDG(PDG); int N = TargetUtils::GetTargetAFromPDG(PDG) - Z; int TOTAL = 1; - targetstring += (" -p \"target_content=" - + GeneralUtils::IntToStr(Z) + " " - + GeneralUtils::IntToStr(N) + " " - + GeneralUtils::IntToStr(TOTAL) + "x" - + "\""); - - // Combined target - } else if (trgts.size() > 1){ - + targetstring += (" -p \"target_content=" + GeneralUtils::IntToStr(Z) + " " + + GeneralUtils::IntToStr(N) + " " + + GeneralUtils::IntToStr(TOTAL) + "x" + "\""); + + // Combined target + } else if (trgts.size() > 1) { int NUCLEONS = GeneralUtils::StrToInt(trgts[0]); // Loop over all targets - for (size_t i = 1; i < trgts.size(); i++){ - + for (size_t i = 1; i < trgts.size(); i++) { // Extra PDG and W std::string tgtdef = trgts[i]; - string::size_type open_bracket = tgtdef.find("["); + string::size_type open_bracket = tgtdef.find("["); string::size_type close_bracket = tgtdef.find("]"); string::size_type ibeg = 0; string::size_type iend = open_bracket; - string::size_type jbeg = open_bracket+1; - string::size_type jend = close_bracket-1; - int PDG = atoi(tgtdef.substr(ibeg,iend).c_str()); - double W = atof(tgtdef.substr(jbeg,jend).c_str()); + string::size_type jbeg = open_bracket + 1; + string::size_type jend = close_bracket - 1; + int PDG = atoi(tgtdef.substr(ibeg, iend).c_str()); + double W = atof(tgtdef.substr(jbeg, jend).c_str()); // extract Z N int Z = TargetUtils::GetTargetZFromPDG(PDG); - int A = TargetUtils::GetTargetAFromPDG(PDG); + int A = TargetUtils::GetTargetAFromPDG(PDG); int N = TargetUtils::GetTargetAFromPDG(PDG) - Z; std::cout << "Target " << PDG << " Z" << Z << " N" << N << std::endl; // extract weight - int TOTAL = round(double(NUCLEONS)*W / A); - - if (i == 1){ - targetstring += (" -p \"target_content=" - + GeneralUtils::IntToStr(Z) + " " - + GeneralUtils::IntToStr(N) + " " - + GeneralUtils::IntToStr(TOTAL) + "x" - + "\""); + int TOTAL = round(double(NUCLEONS) * W / A); + + if (i == 1) { + targetstring += (" -p \"target_content=" + GeneralUtils::IntToStr(Z) + + " " + GeneralUtils::IntToStr(N) + " " + + GeneralUtils::IntToStr(TOTAL) + "x" + "\""); } else { - targetstring += (" -p \"target_content+=" - + GeneralUtils::IntToStr(Z) + " " - + GeneralUtils::IntToStr(N) + " " - + GeneralUtils::IntToStr(TOTAL) + "x" - + "\""); - } + targetstring += (" -p \"target_content+=" + GeneralUtils::IntToStr(Z) + + " " + GeneralUtils::IntToStr(N) + " " + + GeneralUtils::IntToStr(TOTAL) + "x" + "\""); + } } - // No target given! + // No target given! } else { THROW("No target given : " << target); } std::cout << " -> " << targetstring << std::endl; return targetstring; } -std::string GetEventAndSeedDefinition(int nevents, int ntestevents, int seed){ - +std::string GetEventAndSeedDefinition(int nevents, int ntestevents, int seed) { std::string eventdef = ""; - eventdef += " -p \"number_of_events=" + GeneralUtils::IntToStr(nevents) + "\""; - eventdef += " -p \"number_of_test_events=" + GeneralUtils::IntToStr(ntestevents) + "\""; + eventdef += + " -p \"number_of_events=" + GeneralUtils::IntToStr(nevents) + "\""; + eventdef += " -p \"number_of_test_events=" + + GeneralUtils::IntToStr(ntestevents) + "\""; eventdef += " -p \"random_seed=" + GeneralUtils::IntToStr(seed) + "\""; LOG(FIT) << "Event Definition: " << std::endl; std::cout << " -> number_of_events : " << nevents << std::endl; std::cout << " -> number_of_test_events : " << ntestevents << std::endl; std::cout << " -> seed : " << seed << std::endl; return eventdef; } - - - //____________________________________________________________________________ -int main(int argc, char ** argv) -{ +int main(int argc, char** argv) { LOG(FIT) << "==== RUNNING nuwro_nuisance Event Generator =====" << std::endl; - GetCommandLineArgs(argc,argv); - + GetCommandLineArgs(argc, argv); + // Calculate the dynamic modes definition std::string dynparamsdef = GetDynamicModes(gOptGeneratorList); // Get Flux and Target definition std::string fluxparamsdef = GetFluxDefinition(gOptFluxDef, gOptOutputFile); std::string targetparamsdef = GetTargetDefinition(gOptTargetDef); // Get Run Definition - std::string eventparamsdef = GetEventAndSeedDefinition(gOptNumberEvents, - gOptNumberTestEvents, - gOptSeed); + std::string eventparamsdef = GetEventAndSeedDefinition( + gOptNumberEvents, gOptNumberTestEvents, gOptSeed); // Run NuWro Externally! LOG(FIT) << "==== Actually running nuwro! ===" << std::endl; std::string nuwrocommand = "nuwro"; nuwrocommand += " -i " + gOptCrossSections; nuwrocommand += " -o " + gOptOutputFile; nuwrocommand += " " + fluxparamsdef; nuwrocommand += " " + dynparamsdef; nuwrocommand += " " + eventparamsdef; nuwrocommand += " " + targetparamsdef; std::cout << nuwrocommand << std::endl; sleep(10); system((nuwrocommand).c_str()); return 0; } //____________________________________________________________________________ -void GetCommandLineArgs(int argc, char ** argv) -{ - +void GetCommandLineArgs(int argc, char** argv) { // Check for -h flag. - for (int i = 0; i < argc; i++){ + for (int i = 0; i < argc; i++) { if (!std::string(argv[i]).compare("-h")) PrintSyntax(); } - // Format is nuwro -r run_number -n n events + // Format is nuwro -r run_number -n n events std::vector args = GeneralUtils::LoadCharToVectStr(argc, argv); ParserUtils::ParseArgument(args, "-n", gOptNumberEvents, false); - if (gOptNumberEvents == -1){ - THROW( "No event count passed to nuwro_NUISANCE!"); + if (gOptNumberEvents == -1) { + THROW("No event count passed to nuwro_NUISANCE!"); } // Flux/Energy Specs ParserUtils::ParseArgument(args, "-e", gOptEnergyDef, false); - gOptEnergyRange = GeneralUtils::ParseToDbl(gOptEnergyDef,","); + gOptEnergyRange = GeneralUtils::ParseToDbl(gOptEnergyDef, ","); ParserUtils::ParseArgument(args, "-f", gOptFluxDef, false); - if (gOptFluxDef.empty() and gOptEnergyRange.size() < 1){ + if (gOptFluxDef.empty() and gOptEnergyRange.size() < 1) { THROW("No flux or energy range given to nuwro_nuisance!"); - } else if (gOptFluxDef.empty() and gOptEnergyRange.size() == 1){ + } else if (gOptFluxDef.empty() and gOptEnergyRange.size() == 1) { // Fixed energy, make sure -p is given THROW("nuwro_NUISANCE cannot yet do fixed energy!"); - - } else if (gOptFluxDef.empty() and gOptEnergyRange.size() == 2){ + + } else if (gOptFluxDef.empty() and gOptEnergyRange.size() == 2) { // Uniform energy range THROW("nuwro_NUISANCE cannot yet do a uniform energy range!"); - } else if (!gOptFluxDef.empty()){ + } else if (!gOptFluxDef.empty()) { // Try to convert the flux definition if possible. std::string convflux = BeamUtils::ConvertFluxIDs(gOptFluxDef); if (!convflux.empty()) gOptFluxDef = convflux; } else { THROW("Unknown flux energy range combination!"); } ParserUtils::ParseArgument(args, "-t", gOptTargetDef, false); - if (gOptTargetDef.empty()){ + if (gOptTargetDef.empty()) { THROW("No Target passed to nuwro_nuisance! use the '-t' argument."); } else { std::string convtarget = TargetUtils::ConvertTargetIDs(gOptTargetDef); if (!convtarget.empty()) gOptTargetDef = convtarget; } ParserUtils::ParseArgument(args, "-r", gOptRunNumber, false); ParserUtils::ParseArgument(args, "-o", gOptOutputFile, false); - if (gOptOutputFile.empty()){ + if (gOptOutputFile.empty()) { if (gOptRunNumber == -1) gOptRunNumber = 1; - LOG(FIT) << "No output file given! Saving file to : nuwrogen." << gOptRunNumber << ".event.root" << std::endl; - gOptOutputFile = "nuwrogen." + GeneralUtils::IntToStr(gOptRunNumber) + ".event.root"; + LOG(FIT) << "No output file given! Saving file to : nuwrogen." + << gOptRunNumber << ".event.root" << std::endl; + gOptOutputFile = + "nuwrogen." + GeneralUtils::IntToStr(gOptRunNumber) + ".event.root"; } else { // if no run number given leave as is, else add run number. - if (gOptRunNumber != -1){ + if (gOptRunNumber != -1) { gOptOutputFile += "." + GeneralUtils::IntToStr(gOptRunNumber) + ".root"; } else { gOptRunNumber = 0; } } ParserUtils::ParseArgument(args, "--cross-section", gOptCrossSections, false); - if (!gOptCrossSections.compare("Default")){ - LOG(FIT) << "No Parameters File passed. Using default NuWro one." << std::endl; - char * const var = getenv("NUISANCE"); + if (!gOptCrossSections.compare("Default")) { + LOG(FIT) << "No Parameters File passed. Using default NuWro one." + << std::endl; + char* const var = getenv("NUISANCE"); if (!var) { - std::cout << "Cannot find top level directory! Set the NUISANCE environmental variable" << std::endl; + std::cout << "Cannot find top level directory! Set the NUISANCE " + "environmental variable" + << std::endl; exit(-1); - } + } std::string topnuisancedir = string(var); gOptCrossSections = topnuisancedir + "/nuwro/Default_params.txt"; } - - ParserUtils::ParseArgument(args, "--event-generator-list", gOptGeneratorList, false); + + ParserUtils::ParseArgument(args, "--event-generator-list", gOptGeneratorList, + false); ParserUtils::ParseArgument(args, "--seed", gOptSeed, false); - ParserUtils::ParseArgument(args, "--test-events", gOptNumberTestEvents, false); + ParserUtils::ParseArgument(args, "--test-events", gOptNumberTestEvents, + false); // Final Check and output - if (args.size() > 0){ + if (args.size() > 0) { PrintSyntax(); ParserUtils::CheckBadArguments(args); } - LOG(FIT) << "Generating NuWro Events with the following properties:" << std::endl - << " -> Energy : " << gOptEnergyDef << " (" << gOptEnergyRange.size() << ")" << std::endl - << " -> NEvents : " << gOptNumberEvents << std::endl - << " -> NTestEvents : " << gOptNumberTestEvents << std::endl - << " -> Generators : " << gOptGeneratorList << std::endl - << " -> XSecPars : " << gOptCrossSections << std::endl - << " -> Seed : " << gOptSeed << std::endl - << " -> Target : " << gOptTargetDef << std::endl - << " -> Flux : " << gOptFluxDef << std::endl - << " -> Output : " << gOptOutputFile << std::endl - << " -> Run : " << gOptRunNumber << std::endl; + LOG(FIT) << "Generating NuWro Events with the following properties:" + << std::endl + << " -> Energy : " << gOptEnergyDef << " (" + << gOptEnergyRange.size() << ")" << std::endl + << " -> NEvents : " << gOptNumberEvents << std::endl + << " -> NTestEvents : " << gOptNumberTestEvents << std::endl + << " -> Generators : " << gOptGeneratorList << std::endl + << " -> XSecPars : " << gOptCrossSections << std::endl + << " -> Seed : " << gOptSeed << std::endl + << " -> Target : " << gOptTargetDef << std::endl + << " -> Flux : " << gOptFluxDef << std::endl + << " -> Output : " << gOptOutputFile << std::endl + << " -> Run : " << gOptRunNumber << std::endl; return; } //____________________________________________________________________________ -void PrintSyntax(void) -{ - LOG(FIT) - << "\n\n" << "Syntax:" << "\n" - << "\n nuwro_nuisance [-h]" - << "\n -n nev" - << "\n -f flux_description" - << "\n -t target_description" - << "\n [ -r run_number ]" - << "\n [ -o output_file ]" - << "\n [ --cross-section /path/to/params.txt ]" - << "\n [ --event-generator-list mode_definition ]" - << "\n [ --seed seed_value ]" - << "\n [ --test-events ntest ]" - << "\n \n"; +void PrintSyntax(void) { + LOG(FIT) << "\n\n" + << "Syntax:" + << "\n" + << "\n nuwro_nuisance [-h]" + << "\n -n nev" + << "\n -f flux_description" + << "\n -t target_description" + << "\n [ -r run_number ]" + << "\n [ -o output_file ]" + << "\n [ --cross-section /path/to/params.txt ]" + << "\n [ --event-generator-list mode_definition ]" + << "\n [ --seed seed_value ]" + << "\n [ --test-events ntest ]" + << "\n \n"; LOG(FIT) - << "\n\n Arguments:" << "\n" - << "\n -n nev" - << "\n -> Total number of events to generate (e.g. 2500000)" - << "\n" - << "\n -f flux_description" - << "\n Definition of the flux to be read in from a ROOT file." - << "\n" - << "\n Multiple histograms can be read in from the same file using" - << "\n the format '-f file.root,hist1[pdg1],hist2[pdg2]" - << "\n e.g. \'-f ./flux/myfluxfile.root,numu_flux[14],numubar_flux[-14]\'" - << "\n" - << "\n When passing in multiple histograms, the nuwro_nuisance will" - << "\n generate a single file containing both sets of events with the" - << "\n correct ratios for each set." - << "\n" - << "\n A flux can also be given according to any of the flux IDs shown" - << "\n at the end of this help message." - << "\n e.g. \' -f MINERvA_fhc_numu\' " - << "\n" - << "\n -t target_description" - << "\n Definition of the target to be used. Multiple targets can be given." - << "\n" - << "\n To pass a single target just provide the target PDG" - << "\n e.g. \' -t 1000060120 \'" - << "\n" - << "\n To pass a combined target provide a list containing the following" - << "\n \' -t TotalNucleons,Target1[Weight1],Target2[Weight2],.. where the " - << "\n TotalNucleons is the total nucleons combined, Target1 is the PDG " - << "\n of the first target, and Weight1 is the fractional weight of the " - << "\n first target." - << "\n e.g. \' -t 13,1000060120[0.9231],1000010010[0.0769] \'" - << "\n" - << "\n Target can also be specified by the target IDs given at the end of" - << "\n this help message." - << "\n e.g. \' -t CH2 \'" - << "\n" - << "\n -r run_number" - << "\n run number ID that can be used when generating large samples in small " - << "\n jobs. Must be an integer. When given nuwro_nuisance will update the " - << "\n output file from 'output.root' to 'output.root.run_number.root'" - << "\n" - << "\n -o output_file" - << "\n Path to the output_file you want to save events to." - << "\n" - << "\n If this is not given but '-r' is then events will be saved to " - << "\n the file 'nuwrogen.run_number.events.root'" - << "\n" - << "\n If a run number is given alongside '-o' then events will be saved " - << "\n to 'output.root.run_number.root'" - << "\n" - << "\n --cross-section /path/to/params.txt" - << "\n Path to the nuwro model definition. If this is not given, then this " - << "\n will default to $NUISANCE/data/nuwro/Default_params.txt" - << "\n" - << "\n Look in $NUISANCE/data/nuwro/Default_params.txt for examples when " - << "\n writing your own card files." - << "\n" - << "\n --event-generator-list mode_definition" - << "\n Name of modes to run. This sets the dynamic mode settings in nuwro." - << "\n e.g. --event-generator-list Default+MEC" - << "\n" - << "\n Allowed mode_definitions are given at the end of this help message." - << "\n" - << "\n --seed seed_value " - << "\n Value to use as the seed. If seed isn't given, time(NULL) is used." - << "\n" - << "\n --test-events ntest " - << "\n Sets the number of test events for Nuwro to use. If this option " - << "\n isn't given then we assume 5E6 test events by default." - << "\n\n"; - - std::cout << "-----------------"< Total number of events to generate (e.g. 2500000)" + << "\n" + << "\n -f flux_description" + << "\n Definition of the flux to be read in from a ROOT file." + << "\n" + << "\n Multiple histograms can be read in from the same file using" + << "\n the format '-f file.root,hist1[pdg1],hist2[pdg2]" + << "\n e.g. \'-f " + "./flux/myfluxfile.root,numu_flux[14],numubar_flux[-14]\'" + << "\n" + << "\n When passing in multiple histograms, the nuwro_nuisance will" + << "\n generate a single file containing both sets of events with the" + << "\n correct ratios for each set." + << "\n" + << "\n A flux can also be given according to any of the flux IDs shown" + << "\n at the end of this help message." + << "\n e.g. \' -f MINERvA_fhc_numu\' " + << "\n" + << "\n -t target_description" + << "\n Definition of the target to be used. Multiple targets can be " + "given." + << "\n" + << "\n To pass a single target just provide the target PDG" + << "\n e.g. \' -t 1000060120 \'" + << "\n" + << "\n To pass a combined target provide a list containing the " + "following" + << "\n \' -t TotalNucleons,Target1[Weight1],Target2[Weight2],.. where " + "the " + << "\n TotalNucleons is the total nucleons combined, Target1 is the " + "PDG " + << "\n of the first target, and Weight1 is the fractional weight of " + "the " + << "\n first target." + << "\n e.g. \' -t 13,1000060120[0.9231],1000010010[0.0769] \'" + << "\n" + << "\n Target can also be specified by the target IDs given at the " + "end of" + << "\n this help message." + << "\n e.g. \' -t CH2 \'" + << "\n" + << "\n -r run_number" + << "\n run number ID that can be used when generating large samples " + "in small " + << "\n jobs. Must be an integer. When given nuwro_nuisance will " + "update the " + << "\n output file from 'output.root' to 'output.root.run_number.root'" + << "\n" + << "\n -o output_file" + << "\n Path to the output_file you want to save events to." + << "\n" + << "\n If this is not given but '-r' is then events will be saved to " + << "\n the file 'nuwrogen.run_number.events.root'" + << "\n" + << "\n If a run number is given alongside '-o' then events will be " + "saved " + << "\n to 'output.root.run_number.root'" + << "\n" + << "\n --cross-section /path/to/params.txt" + << "\n Path to the nuwro model definition. If this is not given, then " + "this " + << "\n will default to $NUISANCE/data/nuwro/Default_params.txt" + << "\n" + << "\n Look in $NUISANCE/data/nuwro/Default_params.txt for examples " + "when " + << "\n writing your own card files." + << "\n" + << "\n --event-generator-list mode_definition" + << "\n Name of modes to run. This sets the dynamic mode settings in " + "nuwro." + << "\n e.g. --event-generator-list Default+MEC" + << "\n" + << "\n Allowed mode_definitions are given at the end of this help " + "message." + << "\n" + << "\n --seed seed_value " + << "\n Value to use as the seed. If seed isn't given, time(NULL) is " + "used." + << "\n" + << "\n --test-events ntest " + << "\n Sets the number of test events for Nuwro to use. If this " + "option " + << "\n isn't given then we assume 5E6 test events by default." + << "\n\n"; + + std::cout << "-----------------" << std::endl; TargetUtils::ListTargetIDs(); std::cout << "-----------------" << std::endl; BeamUtils::ListFluxIDs(); std::cout << "-----------------" << std::endl; LOG(FIT) << "Allowed Mode Definitions:" << std::endl - << " - Default : Default CC+NC modes, no MEC" << std::endl - << " - Default+MEC : Default CC+NC modes + 2p2h MEC " << std::endl - << " - DefaultFree : Default CC+NC modes, no Coherent or MEC " << std::endl; + << " - Default : Default CC+NC modes, no MEC" << std::endl + << " - Default+MEC : Default CC+NC modes + 2p2h MEC " << std::endl + << " - DefaultFree : Default CC+NC modes, no Coherent or MEC " + << std::endl; std::cout << "----------------" << std::endl; exit(0); } //____________________________________________________________________________ #endif diff --git a/data/MiniBooNE/anti-ccqe/asqq_bkg_ccqe.txt b/data/MiniBooNE/anti-ccqe/asqq_bkg_ccqe.txt index d30ab7d..ce43181 100755 --- a/data/MiniBooNE/anti-ccqe/asqq_bkg_ccqe.txt +++ b/data/MiniBooNE/anti-ccqe/asqq_bkg_ccqe.txt @@ -1,17 +1,18 @@ -0.00 4.400e-39 0.0 -0.05 3.023e-39 0.0 -0.10 1.920e-39 0.0 -0.20 1.297e-39 0.0 -0.25 8.972e-40 0.0 -0.30 6.183e-40 0.0 -0.35 4.397e-40 0.0 -0.40 3.126e-40 0.0 -0.45 2.260e-40 0.0 -0.50 1.661e-40 0.0 -0.60 1.081e-40 0.0 -0.70 6.207e-41 0.0 -0.80 3.882e-41 0.0 -1.00 2.119e-41 0.0 -1.20 9.146e-42 0.0 -1.50 2.368e-42 0.0 -2.00 1.037e-43 0.0 +0.00 4.400e-39 0.0 +0.05 3.023e-39 0.0 +0.10 1.920e-39 0.0 +0.15 1.297e-39 0.0 +0.20 8.972e-40 0.0 +0.25 6.183e-40 0.0 +0.30 4.397e-40 0.0 +0.35 3.126e-40 0.0 +0.40 2.260e-40 0.0 +0.45 1.661e-40 0.0 +0.50 1.081e-40 0.0 +0.60 6.207e-41 0.0 +0.70 3.882e-41 0.0 +0.80 2.119e-41 0.0 +1.00 9.146e-42 0.0 +1.20 2.368e-42 0.0 +1.50 1.037e-43 0.0 +2.00 0.0 0.0 diff --git a/src/FitBase/Measurement1D.h b/src/FitBase/Measurement1D.h index e373dfe..404ba50 100644 --- a/src/FitBase/Measurement1D.h +++ b/src/FitBase/Measurement1D.h @@ -1,655 +1,655 @@ // Copyright 2016 L. Pickering, P towell, 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 MEASUREMENT_1D_H_SEEN #define MEASUREMENT_1D_H_SEEN /*! * \addtogroup FitBase * @{ */ #include #include #include #include #include #include #include #include // ROOT includes #include #include #include #include #include #include #include #include #include #include #include #include // External data fit includes #include "FitEvent.h" #include "FitParameters.h" #include "FitUtils.h" #include "MeasurementBase.h" #include "PlotUtils.h" #include "StatUtils.h" #include "SignalDef.h" #include "MeasurementVariableBox.h" #include "MeasurementVariableBox1D.h" namespace NUISANCE { namespace FitBase { } } //******************************************************************** /// 1D Measurement base class. Histogram handling is done in this base layer. class Measurement1D : public MeasurementBase { //******************************************************************** public: /* Constructor/Deconstuctor */ Measurement1D(void); virtual ~Measurement1D(void); /* Setup Functions */ /// \brief Setup all configs once initialised /// /// Should be called after all configs have been setup inside fSettings container. /// Handles the processing of inputs and setting up of types. /// Replaces the old 'SetupMeasurement' function. void FinaliseSampleSettings(); /// \brief Creates the 1D data distribution given the binning provided. virtual void CreateDataHistogram(int dimx, double* binx); /// \brief Read 1D data inputs from a text file. /// /// Inputfile should have the format: \n /// low_binedge_1 bin_content_1 bin_error_1 \n /// low_binedge_2 bin_content_2 bin_error_2 \n /// .... .... .... \n /// high_bin_edge_N 0.0 0.0 virtual void SetDataFromTextFile(std::string datafile); /// \brief Read 1D data inputs from a root file. /// /// inhistfile specifies the path to the root file /// histname specifies the name of the histogram. /// /// If no histogram name is given the inhistfile value /// is automatically parsed with ';' so that: \n /// 'myhistfile.root;myhistname' \n /// will also work. virtual void SetDataFromRootFile(std::string inhistfile, std::string histname = ""); /// \brief Setup a default empty data histogram /// /// Only used for flattree creators. virtual void SetEmptyData(); /// \brief Set data bin errors to sqrt(entries) /// /// \warning REQUIRES DATA HISTOGRAM TO BE SET FIRST /// /// Sets the data errors as the sqrt of the bin contents /// Should be use for counting experiments virtual void SetPoissonErrors(); /// \brief Make diagonal covariance from data /// /// \warning If no histogram passed, data must be setup first! /// Setup the covariance inputs by taking the data histogram /// errors and setting up a diagonal covariance matrix. /// /// If no data is supplied, fDataHist is used if already set. virtual void SetCovarFromDiagonal(TH1D* data = NULL); /// \brief Read the data covariance from a text file. /// /// Inputfile should have the format: \n /// covariance_11 covariance_12 covariance_13 ... \n /// covariance_21 covariance_22 covariance_23 ... \n /// ... ... ... ... \n /// /// If no dimensions are given, it is assumed from the number /// entries in the first line of covfile. virtual void SetCovarFromTextFile(std::string covfile, int dim = -1); - + virtual void SetCovarFromMultipleTextFiles(std::string covfiles, int dim = -1); /// \brief Read the data covariance from a ROOT file. /// /// - covfile specifies the full path to the file /// - histname specifies the name of the covariance object. Both TMatrixDSym and TH2D are supported. /// /// If no histogram name is given the inhistfile value /// is automatically parsed with ; so that: \n /// mycovfile.root;myhistname \n /// will also work. virtual void SetCovarFromRootFile(std::string covfile, std::string histname=""); /// \brief Read the inverted data covariance from a text file. /// /// Inputfile should have similar format to that shown /// in SetCovarFromTextFile. /// /// If no dimensions are given, it is assumed from the number /// entries in the first line of covfile. virtual void SetCovarInvertFromTextFile(std::string covfile, int dim = -1); /// \brief Read the inverted data covariance from a ROOT file. /// /// Inputfile should have similar format to that shown /// in SetCovarFromRootFile. /// /// If no histogram name is given the inhistfile value /// is automatically parsed with ; so that: \n /// mycovfile.root;myhistname \n /// will also work. virtual void SetCovarInvertFromRootFile(std::string covfile, std::string histname=""); /// \brief Read the data correlations from a text file. /// /// \warning REQUIRES DATA HISTOGRAM TO BE SET FIRST /// /// Inputfile should have similar format to that shown /// in SetCovarFromTextFile. /// /// If no dimensions are given, it is assumed from the number /// entries in the first line of covfile. virtual void SetCorrelationFromTextFile(std::string covfile, int dim = -1); /// \brief Read the data correlations from multiple text files. /// /// \warning REQUIRES DATA HISTOGRAM TO BE SET FIRST /// /// Inputfile should have similar format to that shown - /// in SetCovarFromTextFile. + /// in SetCovarFromTextFile. /// /// If no dimensions are given, it is assumed from the number /// entries in the first line of the first corrfile. virtual void SetCorrelationFromMultipleTextFiles(std::string corrfiles, int dim = -1); /// \brief Read the data correlations from a ROOT file. /// /// \warning REQUIRES DATA TO BE SET FIRST /// /// Inputfile should have similar format to that shown /// in SetCovarFromRootFile. /// /// If no histogram name is given the inhistfile value /// is automatically parsed with ; so that: \n /// mycovfile.root;myhistname \n /// will also work. virtual void SetCorrelationFromRootFile(std::string covfile, std::string histname=""); /// \brief Read the cholesky decomposed covariance from a text file and turn it into a covariance /// /// Inputfile should have similar format to that shown /// in SetCovarFromTextFile. /// /// If no dimensions are given, it is assumed from the number /// entries in the first line of covfile. virtual void SetCholDecompFromTextFile(std::string covfile, int dim = -1); /// \brief Read the cholesky decomposed covariance from a ROOT file and turn it into a covariance /// /// Inputfile should have similar format to that shown /// in SetCovarFromRootFile. /// /// If no histogram name is given the inhistfile value /// is automatically parsed with ; so that: \n /// mycovfile.root;myhistname \n /// will also work. virtual void SetCholDecompFromRootFile(std::string covfile, std::string histname=""); /// \brief Try to extract a shape-only matrix from the existing covariance virtual void SetShapeCovar(); /// \brief Scale the data by some scale factor virtual void ScaleData(double scale); /// \brief Scale the data error bars by some scale factor virtual void ScaleDataErrors(double scale); /// \brief Scale the covariaince and its invert/decomp by some scale factor. virtual void ScaleCovar(double scale); /// \brief Setup a bin masking histogram and apply masking to data /// /// \warning REQUIRES DATA HISTOGRAM TO BE SET FIRST /// /// Reads in a list of bins in a text file to be masked. Format is: \n /// bin_index_1 1 \n /// bin_index_2 1 \n /// bin_index_3 1 \n /// /// If 0 is given then a bin entry will NOT be masked. So for example: \n\n /// 1 1 \n /// 2 1 \n /// 3 0 \n /// 4 1 \n\n /// Will mask only the 1st, 2nd, and 4th bins. /// /// Masking can be turned on by specifiying the MASK option when creating a sample. /// When this is passed NUISANCE will look in the following locations for the mask file: /// - FitPar::Config().GetParS(fName + ".mask") /// - "data/masks/" + fName + ".mask"; virtual void SetBinMask(std::string maskfile); - + /// \brief Set the current fit options from a string. /// /// This is called twice for each sample, once to set the default /// and once to set the current setting (if anything other than default given) /// /// For this to work properly it requires the default and allowed types to be /// set correctly. These should be specified as a string listing options. /// /// To split up options so that NUISANCE can automatically detect ones that /// are conflicting. Any options seperated with the '/' symbol are non conflicting /// and can be given together, whereas any seperated with the ',' symbol cannot /// be specified by the end user at the same time. /// /// Default Type Examples: /// - DIAG/FIX = Default option will be a diagonal covariance, with FIXED norm. /// - MASK/SHAPE = Default option will be a masked hist, with SHAPE always on. /// /// Allowed Type examples: /// - 'FULL/DIAG/NORM/MASK' = Any of these options can be specified. /// - 'FULL,FREE,SHAPE/MASK/NORM' = User can give either FULL, FREE, or SHAPE as on option. /// MASK and NORM can also be included as options. virtual void SetFitOptions(std::string opt); /// \brief Final constructor setup /// \warning Should be called right at the end of the constructor. /// /// Contains a series of checks to ensure the data and inputs have been setup. /// Also creates the MC histograms needed for fitting. void FinaliseMeasurement(); /* Smearing */ /// \brief Read in smearing matrix from file /// /// Set the smearing matrix from a text file given the size of the matrix virtual void SetSmearingMatrix(std::string smearfile, int truedim, int recodim); /// \brief Apply smearing to MC true to get MC reco /// /// Apply smearing matrix to fMCHist using fSmearingMatrix virtual void ApplySmearingMatrix(void); /* Reconfigure Functions */ /// \brief Create a Measurement1D box /// /// Creates a new 1D variable box containing just fXVar. /// /// This box is the bare minimum required by the JointFCN when /// running fast reconfigures during a routine. /// If for some reason a sample needs extra variables to be saved then /// it should override this function creating its own MeasurementVariableBox /// that contains the extra variables. virtual MeasurementVariableBox* CreateBox() {return new MeasurementVariableBox1D();}; /// \brief Reset all MC histograms /// /// Resets all standard histograms and those registered to auto /// process to zero. /// /// If extra histograms are not included in auto processing, then they must be reset /// by overriding this function and doing it manually if required. virtual void ResetAll(void); /// \brief Fill MC Histograms from XVar /// /// Fill standard histograms using fXVar, Weight read from the variable box. /// /// WARNING : Any extra MC histograms need to be filled by overriding this function, /// even if they have been set to auto process. virtual void FillHistograms(void); // \brief Convert event rates to final histogram /// /// Apply standard scaling procedure to standard mc histograms to convert from /// raw events to xsec prediction. /// /// If any distributions have been set to auto process /// that is done during this function call, and a differential xsec is assumed. /// If that is not the case this function must be overriden. virtual void ScaleEvents(void); /// \brief Scale MC by a factor=1/norm /// /// Apply a simple normalisation scaling if the option FREE or a norm_parameter /// has been specified in the NUISANCE routine. virtual void ApplyNormScale(double norm); /* Statistical Functions */ /// \brief Get Number of degrees of freedom /// /// Returns the number bins inside the data histogram accounting for /// any bin masking applied. virtual int GetNDOF(void); /// \brief Return Data/MC Likelihood at current state /// /// Returns the likelihood of the data given the current MC prediction. /// Diferent likelihoods definitions are used depending on the FitOptions. virtual double GetLikelihood(void); /* Fake Data */ /// \brief Set the fake data values from either a file, or MC /// /// - Setting from a file "path": \n /// When reading from a file the full path must be given to a standard /// nuisance output. The standard MC histogram should have a name that matches /// this sample for it to be read in. /// \n\n /// - Setting from "MC": \n /// If the MC option is given the current MC prediction is used as fake data. virtual void SetFakeDataValues(std::string fakeOption); /// \brief Reset fake data back to starting fake data /// /// Reset the fake data back to original fake data (Reset back to before /// ThrowCovariance was first called) virtual void ResetFakeData(void); /// \brief Reset fake data back to original data /// /// Reset the data histogram back to the true original dataset for this sample /// before any fake data was defined. virtual void ResetData(void); /// \brief Generate fake data by throwing the covariance. /// /// Can be used on fake MC data or just the original dataset. /// Call ResetFakeData or ResetData to return to values before the throw. virtual void ThrowCovariance(void); - /// \brief Throw the data by its assigned errors and assign this to MC - /// - /// Used when creating data toys by assign the MC to this thrown data - /// so that the likelihood is calculated between data and thrown data + /// \brief Throw the data by its assigned errors and assign this to MC + /// + /// Used when creating data toys by assign the MC to this thrown data + /// so that the likelihood is calculated between data and thrown data virtual void ThrowDataToy(void); /* Access Functions */ /// \brief Returns nicely formatted MC Histogram /// /// Format options can also be given in the samplesettings: /// - linecolor /// - linestyle /// - linewidth /// - fillcolor /// - fillstyle /// /// So to have a sample line colored differently in the xml cardfile put: \n /// virtual TH1D* GetMCHistogram(void); /// \brief Returns nicely formatted data Histogram /// /// Format options can also be given in the samplesettings: /// - datacolor /// - datastyle /// - datawidth /// /// So to have a sample data colored differently in the xml cardfile put: \n /// virtual TH1D* GetDataHistogram(void); /// \brief Returns a list of all MC histograms. /// /// Override this if you have extra histograms that need to be /// accessed outside of the Measurement1D class. inline virtual std::vector GetMCList(void) { return std::vector(1, GetMCHistogram()); } /// \brief Returns a list of all Data histograms. /// /// Override this if you have extra histograms that need to be /// accessed outside of the Measurement1D class. inline virtual std::vector GetDataList(void) { return std::vector(1, GetDataHistogram()); } /// \brief Returns a list of all Mask histograms. /// /// Override this if you have extra histograms that need to be /// accessed outside of the Measurement1D class. inline virtual std::vector GetMaskList(void) { return std::vector(1, fMaskHist); }; /// \brief Returns a list of all Fine histograms. /// /// Override this if you have extra histograms that need to be /// accessed outside of the Measurement1D class. inline virtual std::vector GetFineList(void) { return std::vector(1, fMCFine); }; /* Write Functions */ /// \brief Save the current state to the current TFile directory \n /// /// Data/MC are both saved by default. /// A range of other histograms can be saved by setting the /// config option 'drawopts'. /// /// Possible options: \n /// - FINE = Write Fine Histogram \n /// - WEIGHTS = Write Weighted MC Histogram (before scaling) \n /// - FLUX = Write Flux Histogram from MC Input \n /// - EVT = Write Event Histogram from MC Input \n /// - XSEC = Write XSec Histogram from MC Input \n /// - MASK = Write Mask Histogram \n /// - COV = Write Covariance Histogram \n /// - INVCOV = Write Inverted Covariance Histogram \n /// - DECMOP = Write Decomp. Covariance Histogram \n /// - RESIDUAL= Write Resudial Histograms \n /// - RATIO = Write Data/MC Ratio Histograms \n /// - SHAPE = Write MC Shape Histograms norm. to Data \n /// - CANVMC = Build MC Canvas Showing Data, MC, Shape \n /// - MODES = Write PDG Stack \n /// - CANVPDG = Build MC Canvas Showing Data, PDGStack \n /// /// So to save a range of these in parameters/config.xml set: \n /// virtual void Write(std::string drawOpt); virtual void WriteRatioPlot(); virtual void WriteShapePlot(); virtual void WriteShapeRatioPlot(); //* // OLD DEFUNCTIONS // /// OLD FUNCTION virtual void SetupMeasurement(std::string input, std::string type, FitWeight* rw, std::string fkdt); /// OLD FUNCTION virtual void SetupDefaultHist(void); /// OLD FUNCTION virtual void SetDataValues(std::string dataFile); /// OLD FUNCTION virtual void SetDataFromFile(std::string inhistfile, std::string histname); /// OLD FUNCTION virtual void SetDataFromDatabase(std::string inhistfile, std::string histname); /// OLD FUNCTION virtual void SetCovarMatrix(std::string covarFile); /// OLD FUNCTION virtual void SetCovarMatrixFromText(std::string covarFile, int dim, double scale = 1.0); /// OLD FUNCTION virtual void SetCovarMatrixFromCorrText(std::string covarFile, int dim); /// OLD FUNCTION virtual void SetCovarFromDataFile(std::string covarFile, std::string covName, bool FullUnits = false); /// OLD FUNCTION // virtual THStack GetModeStack(void); protected: // Data TH1D* fDataHist; ///< default data histogram TH1D* fDataOrig; ///< histogram to store original data before throws. TH1D* fDataTrue; ///< histogram to store true dataset std::string fPlotTitles; ///< Plot title x and y for the histograms // MC TH1D* fMCHist; ///< default MC Histogram used in the chi2 fits TH1D* fMCFine; ///< finely binned MC histogram TH1D* fMCStat; ///< histogram with unweighted events to properly calculate TH1D* fMCWeighted; ///< Weighted histogram before xsec scaling TH1I* fMaskHist; ///< Mask histogram for neglecting specific bins TMatrixD* fSmearMatrix; ///< Smearing matrix (note, this is not symmetric) TrueModeStack* fMCHist_Modes; ///< Optional True Mode Stack // Statistical TMatrixDSym* covar; ///< Inverted Covariance TMatrixDSym* fFullCovar; ///< Full Covariance TMatrixDSym* fDecomp; ///< Decomposed Covariance TMatrixDSym* fCorrel; ///< Correlation Matrix TMatrixDSym* fShapeCovar; ///< Shape-only covariance TMatrixDSym* fShapeDecomp; ///< Decomposed shape-only covariance TMatrixDSym* fCovar; ///< New FullCovar TMatrixDSym* fInvert; ///< New covar double fNormError; ///< Sample norm error double fLikelihood; ///< Likelihood value // Fake Data bool fIsFakeData; ///< Flag: is the current data fake from MC std::string fFakeDataInput; ///< Input fake data file path TFile* fFakeDataFile; ///< Input fake data file // Fit specific flags std::string fFitType; ///< Current fit type std::string fAllowedTypes; ///< Fit Types Possible std::string fDefaultTypes; ///< Starting Default Fit Types bool fIsShape; ///< Flag : Perform Shape-only fit bool fIsFree; ///< Flag : Perform normalisation free fit bool fIsDiag; ///< Flag : only include uncorrelated diagonal errors bool fIsMask; ///< Flag : Apply bin masking bool fIsRawEvents; ///< Flag : Are bin contents just event rates bool fIsEnu1D; ///< Flag : Perform Flux Unfolded Scaling bool fIsChi2SVD; ///< Flag : Use alternative Chi2 SVD Method (Do not use) bool fAddNormPen; ///< Flag : Add a normalisation penalty term to the chi2. bool fIsFix; ///< Flag : keeping norm fixed bool fIsFull; ///< Flag : using full covariaince bool fIsDifXSec; ///< Flag : creating a dif xsec bool fIsChi2; ///< Flag : using Chi2 over LL methods bool fIsSmeared; ///< Flag : Apply smearing? /// OLD STUFF TO REMOVE TH1D* fMCHist_PDG[61]; ///< REMOVE OLD MC PDG Plot // Arrays for data entries Double_t* fXBins; ///< REMOVE xBin edges Double_t* fDataValues; ///< REMOVE data bin contents Double_t* fDataErrors; ///< REMOVE data bin errors Int_t fNDataPointsX; ///< REMOVE number of data points }; /*! @} */ #endif diff --git a/src/FitBase/MeasurementBase.cxx b/src/FitBase/MeasurementBase.cxx index dbfcd0a..facfa13 100644 --- a/src/FitBase/MeasurementBase.cxx +++ b/src/FitBase/MeasurementBase.cxx @@ -1,596 +1,599 @@ // 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 . *******************************************************************************/ #include "MeasurementBase.h" /* Constructor/Destructors */ //******************************************************************** // 2nd Level Constructor (Inherits From MeasurementBase.h) MeasurementBase::MeasurementBase(void) { //******************************************************************** fScaleFactor = 1.0; fMCFilled = false; fNoData = false; fInput = NULL; NSignal = 0; // Set the default values // After-wards this gets set in SetupMeasurement EnuMin = 0.; EnuMax = 1.E5; fMeasurementSpeciesType = kSingleSpeciesMeasurement; fEventVariables = NULL; fIsJoint = false; fNPOT = 0xdeadbeef; fFluxIntegralOverride = 0xdeadbeef; fTargetVolume = 0xdeadbeef; fTargetMaterialDensity = 0xdeadbeef; fEvtRateScaleFactor = 0xdeadbeef; }; void MeasurementBase::FinaliseMeasurement() { // Used to setup default data hists, covars, etc. } //******************************************************************** // 2nd Level Destructor (Inherits From MeasurementBase.h) MeasurementBase::~MeasurementBase(){ //******************************************************************** }; //******************************************************************** double MeasurementBase::TotalIntegratedFlux(std::string intOpt, double low, double high) { //******************************************************************** // Set Energy Limits if (low == -9999.9) low = this->EnuMin; if (high == -9999.9) high = this->EnuMax; return GetInput()->TotalIntegratedFlux(low, high, intOpt); }; //******************************************************************** double MeasurementBase::PredictedEventRate(std::string intOpt, double low, double high) { //******************************************************************** // Set Energy Limits if (low == -9999.9) low = this->EnuMin; if (high == -9999.9) high = this->EnuMax; return GetInput()->PredictedEventRate(low, high, intOpt) * 1E-38; }; //******************************************************************** void MeasurementBase::SetupInputs(std::string inputfile) { //******************************************************************** // Add this infile to the global manager if (FitPar::Config().GetParB("EventManager")) { fInput = FitBase::AddInput(fName, inputfile); } else { std::vector file_descriptor = GeneralUtils::ParseToStr(inputfile, ":"); if (file_descriptor.size() != 2) { ERR(FTL) << "File descriptor had no filetype declaration: \"" << inputfile << "\". expected \"FILETYPE:file.root\"" << std::endl; throw; } InputUtils::InputType inpType = InputUtils::ParseInputType(file_descriptor[0]); fInput = InputUtils::CreateInputHandler(fName, inpType, file_descriptor[1]); } fNEvents = fInput->GetNEvents(); // Expect INPUTTYPE:FileLocation(s) std::vector file_descriptor = GeneralUtils::ParseToStr(inputfile, ":"); if (file_descriptor.size() != 2) { ERR(FTL) << "File descriptor had no filetype declaration: \"" << inputfile << "\". expected \"FILETYPE:file.root\"" << std::endl; throw; } fInputType = InputUtils::ParseInputType(file_descriptor[0]); fInputFileName = file_descriptor[1]; if (EnuMin == 0 && EnuMax == 1.E5) { EnuMin = fInput->GetFluxHistogram()->GetBinLowEdge(1); EnuMax = fInput->GetFluxHistogram()->GetBinLowEdge( fInput->GetFluxHistogram()->GetNbinsX() + 1); } fFluxHist = fInput->GetFluxHistogram(); fEventHist = fInput->GetEventHistogram(); } //*********************************************** int MeasurementBase::GetInputID() { //*********************************************** return FitBase::GetInputID(fInputFileName); } //*********************************************** SampleSettings MeasurementBase::LoadSampleSettings(nuiskey samplekey) { //*********************************************** SampleSettings setting = SampleSettings(samplekey); fName = setting.GetS("name"); // Used as an initial setup function incase we need to do anything here. LOG(SAM) << "Loading Sample : " << setting.GetName() << std::endl; fEvtRateScaleFactor = 0xdeadbeef; if (!fIsJoint) { SetupInputs(setting.GetS("input")); fNPOT = samplekey.Has("NPOT") ? samplekey.GetD("NPOT") : 1; fFluxIntegralOverride = samplekey.Has("FluxIntegralOverride") ? samplekey.GetD("FluxIntegralOverride") : 0xdeadbeef; fTargetVolume = samplekey.Has("TargetVolume") ? samplekey.GetD("TargetVolume") : 0xdeadbeef; fTargetMaterialDensity = samplekey.Has("TargetMaterialDensity") ? samplekey.GetD("TargetMaterialDensity") : 0xdeadbeef; if ((fTargetVolume != 0xdeadbeef) && (fTargetMaterialDensity != 0xdeadbeef)) { double TargetMass_kg = fTargetVolume * fTargetMaterialDensity; double NNucleons = TargetMass_kg / PhysConst::mass_nucleon_kg; double NNeutrinos = ((fFluxIntegralOverride == 0xdeadbeef) ? TotalIntegratedFlux() : fFluxIntegralOverride) * fNPOT; fEvtRateScaleFactor = NNeutrinos * NNucleons; QLOG(SAM, "\tEvent rate prediction : "); QLOG(SAM, "\t\tTarget volume : " << fTargetVolume << " m^3"); QLOG(SAM, "\t\tTarget density : " << fTargetMaterialDensity << " kg/m^3"); QLOG(SAM, "\t\tTarget mass : " << TargetMass_kg << " kg"); QLOG(SAM, "\t\tNTarget Nucleons : " << NNucleons); + if ((fNPOT != 1)) { + QLOG(SAM, "\t\tTotal POT : " << fNPOT); + } QLOG(SAM, "\t\tNNeutrinos : " << NNeutrinos - << ((fNPOT == 1) ? "/cm^2" : "/POT /cm^2")); + << ((fNPOT != 1) ? " /cm^2" : " /POT /cm^2")); QLOG(SAM, "\t\tXSec -> EvtRate scale factor : " << fEvtRateScaleFactor); } } return setting; } //*********************************************** SampleSettings MeasurementBase::LoadSampleSettings(std::string name, std::string input, std::string type) { //*********************************************** nuiskey samplekey = Config::CreateKey("sample"); samplekey.SetS("name", name); samplekey.SetS("input", input); samplekey.SetS("type", type); return LoadSampleSettings(samplekey); } void MeasurementBase::FinaliseSampleSettings() { EnuMin = fSettings.GetD("enu_min"); EnuMax = fSettings.GetD("enu_max"); } //*********************************************** void MeasurementBase::Reconfigure() { //*********************************************** LOG(REC) << " Reconfiguring sample " << fName << std::endl; // Reset Histograms ResetExtraHistograms(); AutoResetExtraTH1(); this->ResetAll(); // FitEvent* cust_event = fInput->GetEventPointer(); int fNEvents = fInput->GetNEvents(); int countwidth = (fNEvents / 5); // MAIN EVENT LOOP FitEvent* cust_event = fInput->FirstNuisanceEvent(); int i = 0; int npassed = 0; while (cust_event) { cust_event->RWWeight = fRW->CalcWeight(cust_event); cust_event->Weight = cust_event->RWWeight * cust_event->InputWeight; Weight = cust_event->Weight; // Initialize fXVar = -999.9; fYVar = -999.9; fZVar = -999.9; Signal = false; Mode = cust_event->Mode; // Extract Measurement Variables this->FillEventVariables(cust_event); Signal = this->isSignal(cust_event); if (Signal) npassed++; GetBox()->SetX(fXVar); GetBox()->SetY(fYVar); GetBox()->SetZ(fZVar); GetBox()->SetMode(Mode); // GetBox()->fSignal = Signal; // Fill Histogram Values GetBox()->FillBoxFromEvent(cust_event); // this->FillExtraHistograms(GetBox(), Weight); this->FillHistogramsFromBox(GetBox(), Weight); // Print Out if (LOG_LEVEL(REC) && countwidth > 0 && !(i % countwidth)) { std::stringstream ss(""); ss.unsetf(std::ios_base::fixed); ss << std::setw(7) << std::right << i << "/" << fNEvents << " events (" << std::setw(2) << double(i) / double(fNEvents) * 100. << std::left << std::setw(5) << "%) " << "[S,X,Y,Z,M,W] = [" << std::fixed << std::setprecision(2) << std::right << Signal << ", " << std::setw(5) << fXVar << ", " << std::setw(5) << fYVar << ", " << std::setw(5) << fYVar << ", " << std::setw(3) << (int)Mode << ", " << std::setw(5) << Weight << "] " << std::endl; LOG(SAM) << ss.str(); } // iterate cust_event = fInput->NextNuisanceEvent(); i++; } LOG(SAM) << npassed << "/" << fNEvents << " passed selection " << std::endl; if (npassed == 0) { LOG(SAM) << "WARNING: NO EVENTS PASSED SELECTION!" << std::endl; } LOG(REC) << std::setw(10) << std::right << NSignal << "/" << fNEvents << " events passed selection + binning after reweight" << std::endl; // Finalise Histograms fMCFilled = true; this->ConvertEventRates(); } void MeasurementBase::FillHistogramsFromBox(MeasurementVariableBox* var, double weight) { fXVar = var->GetX(); fYVar = var->GetY(); fZVar = var->GetZ(); // Signal = var->fSignal; // Mode = var->fMode; Weight = weight; fEventVariables = var; FillHistograms(); FillExtraHistograms(var, weight); } void MeasurementBase::FillHistograms(double weight) { Weight = weight * GetBox()->GetSampleWeight(); FillHistograms(); FillExtraHistograms(GetBox(), Weight); } MeasurementVariableBox* MeasurementBase::FillVariableBox(FitEvent* event) { GetBox()->Reset(); Mode = event->Mode; Weight = 1.0; // event->Weight; this->FillEventVariables(event); Signal = this->isSignal(event); GetBox()->FillBoxFromEvent(event); GetBox()->SetX(fXVar); GetBox()->SetY(fYVar); GetBox()->SetZ(fZVar); GetBox()->SetMode(event->Mode); GetBox()->SetSampleWeight(Weight); // GetBox()->fSignal = Signal; return GetBox(); } MeasurementVariableBox* MeasurementBase::GetBox() { if (!fEventVariables) fEventVariables = CreateBox(); return fEventVariables; } //*********************************************** void MeasurementBase::ReconfigureFast() { //*********************************************** this->Reconfigure(); } //*********************************************** void MeasurementBase::ConvertEventRates() { //*********************************************** AutoScaleExtraTH1(); ScaleExtraHistograms(GetBox()); this->ScaleEvents(); double normval = fRW->GetSampleNorm(this->fName); if (normval < 0.01 or normval > 10.0) { ERR(WRN) << "Norm Value inside MeasurementBase::ConvertEventRates() looks off!" << std::endl; ERR(WRN) << "It could have become out of sync with the minimizer norm list." << std::endl; ERR(WRN) << "Setting it to 1.0" << std::endl; normval = 1.0; } AutoNormExtraTH1(normval); NormExtraHistograms(GetBox(), normval); this->ApplyNormScale(normval); } //*********************************************** InputHandlerBase* MeasurementBase::GetInput() { //*********************************************** if (!fInput) { ERR(FTL) << "MeasurementBase::fInput not set. Please submit your command " "line options and input cardfile with a bug report to: " "nuisance@projects.hepforge.org" << std::endl; throw; } return fInput; }; //*********************************************** void MeasurementBase::Renormalise() { //*********************************************** // Called when the fitter has changed a measurements normalisation but not any // reweight dials // Means we don't have to call the time consuming reconfigure when this // happens. double norm = fRW->GetDialValue(this->fName + "_norm"); if ((this->fCurrentNorm == 0.0 and norm != 0.0) or not fMCFilled) { this->ReconfigureFast(); return; } if (this->fCurrentNorm == norm) return; this->ApplyNormScale(1.0 / this->fCurrentNorm); this->ApplyNormScale(norm); return; }; //*********************************************** void MeasurementBase::SetSignal(bool sig) { //*********************************************** Signal = sig; } //*********************************************** void MeasurementBase::SetSignal(FitEvent* evt) { //*********************************************** Signal = this->isSignal(evt); } //*********************************************** void MeasurementBase::SetWeight(double wght) { //*********************************************** Weight = wght; } //*********************************************** void MeasurementBase::SetMode(int md) { //*********************************************** Mode = md; } //*********************************************** std::vector MeasurementBase::GetFluxList() { //*********************************************** return GetInput()->GetFluxList(); } //*********************************************** std::vector MeasurementBase::GetEventRateList() { //*********************************************** return GetInput()->GetEventList(); } //*********************************************** std::vector MeasurementBase::GetXSecList() { //*********************************************** return GetInput()->GetXSecList(); } void MeasurementBase::ProcessExtraHistograms(int cmd, MeasurementVariableBox* vars, double weight) { // This should be overriden if we have extra histograms!!! // Add a flag to tell user this... return; } void MeasurementBase::FillExtraHistograms(MeasurementVariableBox* vars, double weight) { ProcessExtraHistograms(kCMD_Fill, vars, weight); } void MeasurementBase::ScaleExtraHistograms(MeasurementVariableBox* vars) { ProcessExtraHistograms(kCMD_Scale, vars, 1.0); } void MeasurementBase::ResetExtraHistograms() { ProcessExtraHistograms(kCMD_Reset, NULL, 1.0); } void MeasurementBase::NormExtraHistograms(MeasurementVariableBox* vars, double norm) { ProcessExtraHistograms(kCMD_Norm, vars, norm); } void MeasurementBase::WriteExtraHistograms() { ProcessExtraHistograms(kCMD_Write, NULL, 1.00); } void MeasurementBase::SetAutoProcessTH1(TH1* hist, int c1, int c2, int c3, int c4, int c5) { FakeStack* fake = new FakeStack(hist); SetAutoProcessTH1(fake, c1, c2, c3, c4, c5); // Need to add a destroy command! } void MeasurementBase::SetAutoProcess(TH1* hist, int c1, int c2, int c3, int c4, int c5) { FakeStack* fake = new FakeStack(hist); SetAutoProcessTH1(fake, c1, c2, c3, c4, c5); // Need to add a destroy command! } void MeasurementBase::SetAutoProcess(TGraph* g, int c1, int c2, int c3, int c4, int c5) { FakeStack* fake = new FakeStack(g); SetAutoProcessTH1(fake, c1, c2, c3, c4, c5); // Need to add a destroy command! } void MeasurementBase::SetAutoProcess(TF1* f, int c1, int c2, int c3, int c4, int c5) { FakeStack* fake = new FakeStack(f); SetAutoProcessTH1(fake, c1, c2, c3, c4, c5); // Need to add a destroy command! } void MeasurementBase::SetAutoProcess(StackBase* hist, int c1, int c2, int c3, int c4, int c5) { SetAutoProcessTH1(hist, c1, c2, c3, c4, c5); } void MeasurementBase::SetAutoProcessTH1(StackBase* hist, int c1, int c2, int c3, int c4, int c5) { // Set Defaults // int ncommands = kCMD_extraplotflags; bool autoflags[5]; autoflags[0] = false; autoflags[1] = false; autoflags[2] = false; autoflags[3] = false; autoflags[4] = false; int givenflags[5]; givenflags[0] = c1; givenflags[1] = c2; givenflags[2] = c3; givenflags[3] = c4; givenflags[4] = c5; fExtraTH1s[hist] = std::vector(5, 0); // Setup a default one. if (c1 == -1 && c2 == -1 && c3 == -1 && c4 == -1 && c5 == -1) { fExtraTH1s[hist][kCMD_Reset] = 1; fExtraTH1s[hist][kCMD_Scale] = 1; fExtraTH1s[hist][kCMD_Norm] = 1; fExtraTH1s[hist][kCMD_Write] = 1; } for (int i = 0; i < 5; i++) { switch (givenflags[i]) { // Skip over... case -1: break; case kCMD_Reset: case kCMD_Scale: case kCMD_Norm: case kCMD_Write: fExtraTH1s[hist][givenflags[i]] = 1; break; case kCMD_Fill: ERR(FTL) << "Can't auto fill yet!" << std::endl; autoflags[givenflags[i]] = 1; break; default: break; } } // LOG(SAM) << "AutoProcessing " << hist->GetName() << std::endl; }; void MeasurementBase::AutoFillExtraTH1() { ERR(FTL) << "Can't auto fill yet! it's too inefficent!" << std::endl; return; } void MeasurementBase::AutoResetExtraTH1() { for (std::map >::iterator iter = fExtraTH1s.begin(); iter != fExtraTH1s.end(); iter++) { if (!((*iter).second)[kCMD_Reset]) continue; (*iter).first->Reset(); } }; void MeasurementBase::AutoScaleExtraTH1() { for (std::map >::iterator iter = fExtraTH1s.begin(); iter != fExtraTH1s.end(); iter++) { if (!((*iter).second)[kCMD_Scale]) continue; if (fIsNoWidth) { (*iter).first->Scale(fScaleFactor); } else { (*iter).first->Scale(fScaleFactor, "width"); } } }; void MeasurementBase::AutoNormExtraTH1(double norm) { double sfactor = 0.0; if (norm != 0.0) sfactor = 1.0 / norm; for (std::map >::iterator iter = fExtraTH1s.begin(); iter != fExtraTH1s.end(); iter++) { if (!((*iter).second)[kCMD_Norm]) continue; (*iter).first->Scale(sfactor); } }; void MeasurementBase::AutoWriteExtraTH1() { for (std::map >::iterator iter = fExtraTH1s.begin(); iter != fExtraTH1s.end(); iter++) { if (!(((*iter).second)[kCMD_Write])) continue; (*iter).first->Write(); } }; diff --git a/src/InputHandler/CMakeLists.txt b/src/InputHandler/CMakeLists.txt index c96a4c2..5b2cf1d 100644 --- a/src/InputHandler/CMakeLists.txt +++ b/src/InputHandler/CMakeLists.txt @@ -1,91 +1,93 @@ # 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 . ################################################################################ set(IMPLFILES BaseFitEvt.cxx FitParticle.cxx FitEvent.cxx GeneratorUtils.cxx StdHepEvt.cxx InputUtils.cxx NEUTInputHandler.cxx GENIEInputHandler.cxx NuWroInputHandler.cxx GIBUUInputHandler.cxx NUANCEInputHandler.cxx InputHandler.cxx NuanceEvent.cxx FitEventInputHandler.cxx SplineInputHandler.cxx GeneratorInfoBase.h InputTypes.h HepMCTextInputHandler.cxx InputFactory.cxx SigmaQ0HistogramInputHandler.cxx +HistogramInputHandler.cxx ) set(HEADERFILES NuanceEvent.h BaseFitEvt.h FitEvent.h FitParticle.h GeneratorUtils.h StdHepEvt.h InputUtils.h NEUTInputHandler.h HepMCTextInputHandler.h GENIEInputHandler.h NuWroInputHandler.h InputHandler.h GIBUUInputHandler.h NUANCEInputHandler.h FitEventInputHandler.h SplineInputHandler.h GeneratorInfoBase.h InputFactory.h InteractionModes.h SigmaQ0HistogramInputHandler.h +HistogramInputHandler.h ) set(LIBNAME InputHandler) if(CMAKE_BUILD_TYPE MATCHES DEBUG) add_library(${LIBNAME} STATIC ${IMPLFILES}) else(CMAKE_BUILD_TYPE MATCHES RELEASE) add_library(${LIBNAME} SHARED ${IMPLFILES}) endif() include_directories(${MINIMUM_INCLUDE_DIRECTORIES}) set_target_properties(${LIBNAME} PROPERTIES VERSION "${ExtFit_VERSION_MAJOR}.${ExtFit_VERSION_MINOR}.${ExtFit_VERSION_REVISION}") #set_target_properties(${LIBNAME} PROPERTIES LINK_FLAGS ${ROOT_LD_FLAGS}) if(DEFINED PROJECTWIDE_EXTRA_DEPENDENCIES) add_dependencies(${LIBNAME} ${PROJECTWIDE_EXTRA_DEPENDENCIES}) endif() if(HEPMC_USED_EP) add_dependencies(${LIBNAME} HepMC) endif() install(TARGETS ${LIBNAME} DESTINATION lib) #Can uncomment this to install the headers... but is it really neccessary? install(FILES ${HEADERFILES} DESTINATION include) set(MODULETargets ${MODULETargets} ${LIBNAME} PARENT_SCOPE) diff --git a/src/InputHandler/FitEventInputHandler.cxx b/src/InputHandler/FitEventInputHandler.cxx index 969c245..441f648 100644 --- a/src/InputHandler/FitEventInputHandler.cxx +++ b/src/InputHandler/FitEventInputHandler.cxx @@ -1,130 +1,143 @@ +// 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 . +*******************************************************************************/ #include "FitEventInputHandler.h" +#include "InputUtils.h" + +FitEventInputHandler::FitEventInputHandler(std::string const& handle, + std::string const& rawinputs) { + LOG(SAM) << "Creating FitEventInputHandler : " << handle << std::endl; + + // Run a joint input handling + fName = handle; + fFitEventTree = new TChain("nuisance_events"); + fCacheSize = FitPar::Config().GetParI("CacheSize"); + + 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(inputs[inp_it].c_str(), "READ"); + if (!inp_file or inp_file->IsZombie()) { + ERR(FTL) << "FitEvent File IsZombie() at " << inputs[inp_it] << std::endl; + throw; + } + + // Get Flux/Event hist + TH1D* fluxhist = (TH1D*)inp_file->Get("nuisance_fluxhist"); + TH1D* eventhist = (TH1D*)inp_file->Get("nuisance_eventhist"); + if (!fluxhist or !eventhist) { + ERR(FTL) << "FitEvent FILE doesn't contain flux/xsec info" << std::endl; + throw; + } -FitEventInputHandler::FitEventInputHandler(std::string const& handle, std::string const& rawinputs) { - LOG(SAM) << "Creating FitEventInputHandler : " << handle << std::endl; - - // Run a joint input handling - fName = handle; - fFitEventTree = new TChain("nuisance_events"); - fCacheSize = FitPar::Config().GetParI("CacheSize"); - - 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(inputs[inp_it].c_str(), "READ"); - if (!inp_file or inp_file->IsZombie()) { - ERR(FTL) << "FitEvent File IsZombie() at " << inputs[inp_it] << std::endl; - throw; - } - - // Get Flux/Event hist - TH1D* fluxhist = (TH1D*)inp_file->Get("nuisance_fluxhist"); - TH1D* eventhist = (TH1D*)inp_file->Get("nuisance_eventhist"); - if (!fluxhist or !eventhist) { - ERR(FTL) << "FitEvent FILE doesn't contain flux/xsec info" << std::endl; - throw; - } - - // Get N Events - TTree* eventtree = (TTree*)inp_file->Get("nuisance_events"); - if (!eventtree) { - ERR(FTL) << "nuisance_events not located in GENIE file! " << inputs[inp_it] << std::endl; - throw; - } - int nevents = eventtree->GetEntries(); - - // Register input to form flux/event rate hists - RegisterJointInput(inputs[inp_it], nevents, fluxhist, eventhist); - - // Add to TChain - fFitEventTree->Add( inputs[inp_it].c_str() ); + // Get N Events + TTree* eventtree = (TTree*)inp_file->Get("nuisance_events"); + if (!eventtree) { + ERR(FTL) << "nuisance_events not located in GENIE file! " + << inputs[inp_it] << std::endl; + throw; } + int nevents = eventtree->GetEntries(); - // Registor all our file inputs - SetupJointInputs(); + // Register input to form flux/event rate hists + RegisterJointInput(inputs[inp_it], nevents, fluxhist, eventhist); - // Assign to tree - fEventType = kINPUTFITEVENT; + // Add to TChain + fFitEventTree->Add(inputs[inp_it].c_str()); + } - // Create Fit Event - fNUISANCEEvent = new FitEvent(); - fNUISANCEEvent->HardReset(); - fNUISANCEEvent->SetBranchAddress(fFitEventTree); - - fFitEventTree->SetBranchAddress("NParticles", &fReadNParticles); - fFitEventTree->SetBranchAddress("ParticleState", &fReadParticleState); - fFitEventTree->SetBranchAddress("ParticlePDG", &fReadParticlePDG); - fFitEventTree->SetBranchAddress("ParticleMom", &fReadParticleMom); + // Registor all our file inputs + SetupJointInputs(); + // Assign to tree + fEventType = kINPUTFITEVENT; - fFitEventTree->Show(0); - fNUISANCEEvent = GetNuisanceEvent(0); - std::cout << "NParticles = " << fNUISANCEEvent->Npart() << std::endl; - std::cout << "Event Info " << fNUISANCEEvent->PartInfo(0)->fPID << std::endl; - + // Create Fit Event + fNUISANCEEvent = new FitEvent(); + fNUISANCEEvent->HardReset(); + fNUISANCEEvent->SetBranchAddress(fFitEventTree); + + fFitEventTree->SetBranchAddress("NParticles", &fReadNParticles); + fFitEventTree->SetBranchAddress("ParticleState", &fReadParticleState); + fFitEventTree->SetBranchAddress("ParticlePDG", &fReadParticlePDG); + fFitEventTree->SetBranchAddress("ParticleMom", &fReadParticleMom); + + fFitEventTree->Show(0); + fNUISANCEEvent = GetNuisanceEvent(0); + std::cout << "NParticles = " << fNUISANCEEvent->Npart() << std::endl; + std::cout << "Event Info " << fNUISANCEEvent->PartInfo(0)->fPID << std::endl; } -FitEventInputHandler::~FitEventInputHandler(){ - if (fFitEventTree) delete fFitEventTree; +FitEventInputHandler::~FitEventInputHandler() { + if (fFitEventTree) delete fFitEventTree; } void FitEventInputHandler::CreateCache() { // fFitEventTree->SetCacheEntryRange(0, fNEvents); - // fFitEventTree->AddBranchToCache("*", 1); - // fFitEventTree->SetCacheSize(fCacheSize); + // fFitEventTree->AddBranchToCache("*", 1); + // fFitEventTree->SetCacheSize(fCacheSize); } void FitEventInputHandler::RemoveCache() { - //fFitEventTree->SetCacheEntryRange(0, fNEvents); + // fFitEventTree->SetCacheEntryRange(0, fNEvents); // fFitEventTree->AddBranchToCache("*", 0); // fFitEventTree->SetCacheSize(0); } -FitEvent* FitEventInputHandler::GetNuisanceEvent(const UInt_t entry, const bool lightweight) { +FitEvent* FitEventInputHandler::GetNuisanceEvent(const UInt_t entry, + const bool lightweight) { + // Return NULL if out of bounds + if (entry >= (UInt_t)fNEvents) return NULL; - // Return NULL if out of bounds - if (entry >= (UInt_t)fNEvents) return NULL; + // Reset all variables before tree read + fNUISANCEEvent->ResetEvent(); - // Reset all variables before tree read - fNUISANCEEvent->ResetEvent(); + // Read NUISANCE Tree + fFitEventTree->GetEntry(entry); - // Read NUISANCE Tree - fFitEventTree->GetEntry(entry); + // Fill Stack + fNUISANCEEvent->fNParticles = 0; + for (size_t i = 0; i < fReadNParticles; i++) { + size_t curpart = fNUISANCEEvent->fNParticles; + fNUISANCEEvent->fParticleState[curpart] = fReadParticleState[i]; - // Fill Stack - fNUISANCEEvent->fNParticles = 0; - for (size_t i = 0; i < fReadNParticles; i++){ - size_t curpart = fNUISANCEEvent->fNParticles; - fNUISANCEEvent->fParticleState[curpart] = fReadParticleState[i]; + // Mom + fNUISANCEEvent->fParticleMom[curpart][0] = fReadParticleMom[i][0]; + fNUISANCEEvent->fParticleMom[curpart][1] = fReadParticleMom[i][1]; + fNUISANCEEvent->fParticleMom[curpart][2] = fReadParticleMom[i][2]; + fNUISANCEEvent->fParticleMom[curpart][3] = fReadParticleMom[i][3]; - // Mom - fNUISANCEEvent->fParticleMom[curpart][0] = fReadParticleMom[i][0]; - fNUISANCEEvent->fParticleMom[curpart][1] = fReadParticleMom[i][1]; - fNUISANCEEvent->fParticleMom[curpart][2] = fReadParticleMom[i][2]; - fNUISANCEEvent->fParticleMom[curpart][3] = fReadParticleMom[i][3]; + // PDG + fNUISANCEEvent->fParticlePDG[curpart] = fReadParticlePDG[i]; - // PDG - fNUISANCEEvent->fParticlePDG[curpart] = fReadParticlePDG[i]; + // Add to N particle count + fNUISANCEEvent->fNParticles++; + } - // Add to N particle count - fNUISANCEEvent->fNParticles++; - } + // Setup Input scaling for joint inputs + fNUISANCEEvent->InputWeight = GetInputWeight(entry); - // Setup Input scaling for joint inputs - fNUISANCEEvent->InputWeight = GetInputWeight(entry); - - return fNUISANCEEvent; + return fNUISANCEEvent; } - double FitEventInputHandler::GetInputWeight(int entry) { - double w = InputHandlerBase::GetInputWeight(entry); - return w * fNUISANCEEvent->SavedRWWeight; + double w = InputHandlerBase::GetInputWeight(entry); + return w * fNUISANCEEvent->SavedRWWeight; } -void FitEventInputHandler::Print() { -} - - +void FitEventInputHandler::Print() {} diff --git a/src/InputHandler/FitEventInputHandler.h b/src/InputHandler/FitEventInputHandler.h index 5bdc84c..0f38ce6 100644 --- a/src/InputHandler/FitEventInputHandler.h +++ b/src/InputHandler/FitEventInputHandler.h @@ -1,43 +1,61 @@ +// 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 FITEVENT_INPUTHANDLER_H #define FITEVENT_INPUTHANDLER_H /*! * \addtogroup InputHandler * @{ */ #include "InputHandler.h" #include "FitEvent.h" #include "PlotUtils.h" /// Class to read in NUISANCE FitEvents that have been saved to tree class FitEventInputHandler : public InputHandlerBase { public: /// Standard constructor given name and inputs FitEventInputHandler(std::string const& handle, std::string const& rawinputs); virtual ~FitEventInputHandler(); /// Create a TTree Cache to speed up file read void CreateCache(); /// Remove TTree Cache to save memory void RemoveCache(); /// Returns NUISANCE FitEvent from the TTree. If lightweight does nothing. FitEvent* GetNuisanceEvent(const UInt_t entry, const bool lightweight=false); /// Alongside InputWeight also returns any saved RWWeights double GetInputWeight(int entry); /// Print out event information void Print(); TChain* fFitEventTree; ///< TTree from FitEvent file. int fReadNParticles; double fReadParticleMom[400][4]; UInt_t fReadParticleState[400]; int fReadParticlePDG[400]; }; /*! @} */ #endif diff --git a/src/InputHandler/GENIEInputHandler.cxx b/src/InputHandler/GENIEInputHandler.cxx index aa0e3e8..64d7578 100644 --- a/src/InputHandler/GENIEInputHandler.cxx +++ b/src/InputHandler/GENIEInputHandler.cxx @@ -1,426 +1,446 @@ -#include "GENIEInputHandler.h" +// 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"); // 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]); } // 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()); } // Registor all our file inputs SetupJointInputs(); // Assign to tree fEventType = kGENIE; fGenieNtpl = NULL; fGENIETree->SetBranchAddress("gmcrec", &fGenieNtpl); fGENIETree->GetEntry(0); // 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; + // 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 { GHepRecord* GenieGHep = static_cast(fNUISANCEEvent->fGenieNtpl->event); if (!GenieGHep) return; TObjArrayIter iter(GenieGHep); while ((p = (dynamic_cast((iter).Next())))) { if (!p) { continue; } // Get Status int state = GetGENIEParticleStatus(p, fNUISANCEEvent->fMode); 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->fMode = ConvertGENIEReactionCode(fGenieGHep); // Set Event Info fNUISANCEEvent->Mode = fNUISANCEEvent->fMode; 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(); // 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->fMode); // 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/GIBUUInputHandler.cxx b/src/InputHandler/GIBUUInputHandler.cxx index 1d9f3aa..880a563 100644 --- a/src/InputHandler/GIBUUInputHandler.cxx +++ b/src/InputHandler/GIBUUInputHandler.cxx @@ -1,251 +1,301 @@ #ifdef __GiBUU_ENABLED__ #include "GIBUUInputHandler.h" +#include "InputUtils.h" + GIBUUGeneratorInfo::~GIBUUGeneratorInfo() { DeallocateParticleStack(); } void GIBUUGeneratorInfo::AddBranchesToTree(TTree* tn) { // tn->Branch("NEUTParticleN", fNEUTParticleN, "NEUTParticleN/I"); // tn->Branch("NEUTParticleStatusCode", fNEUTParticleStatusCode, // "NEUTParticleStatusCode[NEUTParticleN]/I"); // tn->Branch("NEUTParticleAliveCode", fNEUTParticleAliveCode, // "NEUTParticleAliveCode[NEUTParticleN]/I"); } void GIBUUGeneratorInfo::SetBranchesFromTree(TTree* tn) { // tn->SetBranchAddress("NEUTParticleN", &fNEUTParticleN ); // tn->SetBranchAddress("NEUTParticleStatusCode", &fNEUTParticleStatusCode ); // tn->SetBranchAddress("NEUTParticleAliveCode", &fNEUTParticleAliveCode ); } void GIBUUGeneratorInfo::AllocateParticleStack(int stacksize) { // fNEUTParticleN = 0; // fNEUTParticleStatusCode = new int[stacksize]; // fNEUTParticleStatusCode = new int[stacksize]; } void GIBUUGeneratorInfo::DeallocateParticleStack() { // delete fNEUTParticleStatusCode; // delete fNEUTParticleAliveCode; } void GIBUUGeneratorInfo::FillGeneratorInfo(GiBUUStdHepReader* nevent) { Reset(); // for (int i = 0; i < nevent->Npart(); i++) { // fNEUTParticleStatusCode[i] = nevent->PartInfo(i)->fStatus; // fNEUTParticleAliveCode[i] = nevent->PartInfo(i)->fIsAlive; // fNEUTParticleN++; // } } void GIBUUGeneratorInfo::Reset() { // for (int i = 0; i < fNEUTParticleN; i++) { // fNEUTParticleStatusCode[i] = -1; // fNEUTParticleAliveCode[i] = 9; // } // fNEUTParticleN = 0; } GIBUUInputHandler::GIBUUInputHandler(std::string const& handle, std::string const& rawinputs) { LOG(SAM) << "Creating GiBUUInputHandler : " << handle << std::endl; // Run a joint input handling fName = handle; fEventType = kGiBUU; fGIBUUTree = new TChain("giRooTracker"); // 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 LOG(SAM) << "Opening event file " << inputs[inp_it] << std::endl; TFile* inp_file = new TFile(inputs[inp_it].c_str(), "READ"); if ((!inp_file) || (!inp_file->IsOpen())) { THROW("GiBUU file !IsOpen() at : '" << inputs[inp_it] << "'" << std::endl << "Check that your file paths are correct and the file exists!"); } int NFluxes = bool(dynamic_cast(inp_file->Get("numu_flux"))) + bool(dynamic_cast(inp_file->Get("numub_flux"))) + bool(dynamic_cast(inp_file->Get("nue_flux"))) + bool(dynamic_cast(inp_file->Get("nueb_flux"))); if (NFluxes != 1) { THROW("Found " << NFluxes << " input fluxes in " << inputs[inp_it] << ". The NUISANCE GiBUU interface expects to be " "passed multiple species vectors as separate " "input files like: " "\"GiBUU:(MINERVA_FHC_numu_evts.root,MINERVA_FHC_" "numubar_evts.root,[...])\""); } // Get Flux/Event hist TH1D* fluxhist = dynamic_cast(inp_file->Get("flux")); TH1D* eventhist = dynamic_cast(inp_file->Get("evt")); if (!fluxhist || !eventhist) { ERROR(FTL, "Input File Contents: " << inputs[inp_it]); inp_file->ls(); THROW( "GiBUU FILE doesn't contain flux/xsec info. You may have to " "regenerate your MC!"); } // Get N Events TTree* giRooTracker = dynamic_cast(inp_file->Get("giRooTracker")); if (!giRooTracker) { ERROR(FTL, "giRooTracker Tree not located in NEUT file: " << inputs[inp_it]); THROW("Check your inputs, they may need to be completely regenerated!"); throw; } int nevents = giRooTracker->GetEntries(); if (nevents <= 0) { THROW("Trying to a TTree with " << nevents << " to TChain from : " << inputs[inp_it]); } // Register input to form flux/event rate hists RegisterJointInput(inputs[inp_it], nevents, fluxhist, eventhist); // Add To TChain fGIBUUTree->AddFile(inputs[inp_it].c_str()); } // Registor all our file inputs SetupJointInputs(); // Create Fit Event fNUISANCEEvent = new FitEvent(); fGiReader = new GiBUUStdHepReader(); fGiReader->SetBranchAddresses(fGIBUUTree); fNUISANCEEvent->HardReset(); }; FitEvent* GIBUUInputHandler::GetNuisanceEvent(const UInt_t entry, const bool lightweight) { // Check out of bounds if (entry >= (UInt_t)fNEvents) return NULL; // Read Entry from TTree to fill NEUT Vect in BaseFitEvt; fGIBUUTree->GetEntry(entry); // Run NUISANCE Vector Filler if (!lightweight) { CalcNUISANCEKinematics(); } #ifdef __PROB3PP_ENABLED__ else { for (int i = 0; i < fGiReader->StdHepN; i++) { - int state = - GetGIBUUParticleStatus(fGiReader->StdHepStatus[i], fGiReader->StdHepPdg[i]); + int state = GetGIBUUParticleStatus(fGiReader->StdHepStatus[i], + fGiReader->StdHepPdg[i]); if (state != kInitialState) { continue; } if (std::count(PhysConst::pdg_neutrinos, PhysConst::pdg_neutrinos + 4, fGiReader->StdHepPdg[i])) { fNUISANCEEvent->probe_E = fGiReader->StdHepP4[i][3] * 1.E3; fNUISANCEEvent->probe_pdg = fGiReader->StdHepPdg[i]; break; } } } #endif + fNUISANCEEvent->InputWeight *= GetInputWeight(entry); + return fNUISANCEEvent; } int GetGIBUUParticleStatus(int status, int pdg) { int state = kUndefinedState; switch (status) { case 0: // Incoming case 11: // Struck nucleon state = kInitialState; break; case 1: // Good Final State state = kFinalState; break; default: // Other break; } // Set Nuclear States Flag if (pdg > 1000000) { if (state == kInitialState) state = kNuclearInitial; else if (state == kFinalState) state = kNuclearRemnant; else state = kUndefinedState; } return state; } void GIBUUInputHandler::CalcNUISANCEKinematics() { // Reset all variables fNUISANCEEvent->ResetEvent(); FitEvent* evt = fNUISANCEEvent; evt->fMode = fGiReader->GiBUU2NeutCode; evt->Mode = evt->fMode; evt->fEventNo = 0.0; evt->fTotCrs = 0; evt->fTargetA = 0.0; // Change to get these from nuclear remnant. evt->fTargetZ = 0.0; evt->fTargetH = 0; evt->fBound = 0.0; // Extra GiBUU Input Weight evt->InputWeight = fGiReader->EvtWght; // Check Stack N int npart = fGiReader->StdHepN; int kmax = evt->kMaxParticles; if ((UInt_t)npart > (UInt_t)kmax) { ERROR(WRN, "GiBUU has too many particles. Expanding Stack."); fNUISANCEEvent->ExpandParticleStack(npart); } // Create Stack evt->fNParticles = 0; for (int i = 0; i < npart; i++) { // State int state = GetGIBUUParticleStatus(fGiReader->StdHepStatus[i], fGiReader->StdHepPdg[i]); int curpart = evt->fNParticles; // Set State evt->fParticleState[evt->fNParticles] = state; // Mom evt->fParticleMom[curpart][0] = fGiReader->StdHepP4[i][0] * 1.E3; evt->fParticleMom[curpart][1] = fGiReader->StdHepP4[i][1] * 1.E3; evt->fParticleMom[curpart][2] = fGiReader->StdHepP4[i][2] * 1.E3; evt->fParticleMom[curpart][3] = fGiReader->StdHepP4[i][3] * 1.E3; // PDG evt->fParticlePDG[curpart] = fGiReader->StdHepPdg[i]; // Add to total particles evt->fNParticles++; } // 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 GIBUUInputHandler::Print() {} + +void GIBUUInputHandler::SetupJointInputs() { + if (jointeventinputs.size() <= 1) { + jointinput = false; + } else if (jointeventinputs.size() > 1) { + jointinput = true; + jointindexswitch = 0; + } + fMaxEvents = FitPar::Config().GetParI("MAXEVENTS"); + if (fMaxEvents != -1 and jointeventinputs.size() > 1) { + THROW("Can only handle joint inputs when config MAXEVENTS = -1!"); + } + + for (size_t i = 0; i < jointeventinputs.size(); i++) { + double scale = double(fNEvents) / fEventHist->Integral("width"); + scale *= jointfluxinputs.at(i)->Integral("width"); + + jointindexscale.push_back(scale); + } + + fEventHist->SetNameTitle((fName + "_EVT").c_str(), (fName + "_EVT").c_str()); + fFluxHist->SetNameTitle((fName + "_FLUX").c_str(), (fName + "_FLUX").c_str()); + + // Setup Max Events + if (fMaxEvents > 1 && fMaxEvents < fNEvents) { + if (LOG_LEVEL(SAM)) { + std::cout << "\t\t|-> Read Max Entries : " << fMaxEvents << std::endl; + } + fNEvents = fMaxEvents; + } + + // Print out Status + if (LOG_LEVEL(SAM)) { + std::cout << "\t\t|-> Total Entries : " << fNEvents << std::endl + << "\t\t|-> Event Integral : " + << fEventHist->Integral("width") * 1.E-38 << " events/nucleon" + << std::endl + << "\t\t|-> Flux Integral : " << fFluxHist->Integral("width") + << " /cm2" << std::endl + << "\t\t|-> Event/Flux : " + << fEventHist->Integral("width") * 1.E-38 / + fFluxHist->Integral("width") + << " cm2/nucleon" << std::endl; + } +} + #endif diff --git a/src/InputHandler/GIBUUInputHandler.h b/src/InputHandler/GIBUUInputHandler.h index 5b67165..6a8027a 100644 --- a/src/InputHandler/GIBUUInputHandler.h +++ b/src/InputHandler/GIBUUInputHandler.h @@ -1,67 +1,70 @@ #ifndef GIBUUINPUTHANDLER_H #define GIBUUINPUTHANDLER_H #ifdef __GiBUU_ENABLED__ /*! * \addtogroup InputHandler * @{ */ #include "InputHandler.h" #include "PlotUtils.h" #include "StdHepEvt.h" /// GIBUU Generator Container to save extra particle status codes. class GIBUUGeneratorInfo : public GeneratorInfoBase { public: GIBUUGeneratorInfo() {}; virtual ~GIBUUGeneratorInfo(); /// 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 GIBUU information from the event void FillGeneratorInfo(GiBUUStdHepReader* nevent); /// Reset extra information to default/empty values void Reset(); // int kMaxParticles; ///< Number of particles in stack // int* fNEUTParticleStatusCode; ///= fHistos.size()) { + THROW("Requested histogram, index " << i << ", but only specified " + << fHistos.size() << " input histos."); + } + return fHistos[i]; +} +std::vector HistoInputHandler::GetHistograms(int i, int j) { + size_t from = (i < 0) ? 0 : i; + size_t to = (j < 0) ? fHistos.size() : j; + if (j <= i) { + THROW( + "Lower bound of GetHistograms range is larger than or equal to the " + "upper bound: [" + << i << ", " << j << "]."); + } + + std::vector rtnv; + for (size_t it = from; it < to; ++it) { + rtnv.push_back(GetHistogram(it)); + } + return rtnv; +} + +HistoInputHandler::HistoInputHandler(std::string const& handle, + std::string const& rawinputs) { + LOG(SAM) << "Creating HistoInputHandler : " << handle << std::endl; + + // Run a joint input handling + fName = handle; + fNEvents = 1; + fEventType = kHISTO; + + fFluxHist = new TH1D("flux", "dummy", 1, 1, 2); + fFluxHist->SetBinContent(1, 1); + fEventHist = new TH1D("event", "dummy", 1, 1, 2); + fEventHist->SetBinContent(1, 1); + + // 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 + LOG(SAM) << "Reading histograms from descriptor " << inputs[inp_it] + << std::endl; + + std::vector histos = PlotUtils::GetTH1sFromRootFile(inputs[inp_it]); + + for (size_t h_it = 0; h_it < histos.size(); ++h_it) { + LOG(SAM) << "Read " << histos[h_it]->GetName() << std::endl; + fHistos.push_back(histos[h_it]); + } + } +}; + +void HistoInputHandler::Print() {} diff --git a/src/InputHandler/HistogramInputHandler.h b/src/InputHandler/HistogramInputHandler.h new file mode 100644 index 0000000..cd7e42f --- /dev/null +++ b/src/InputHandler/HistogramInputHandler.h @@ -0,0 +1,33 @@ +#ifndef HISTOINPUTHANDLER_H +#define HISTOINPUTHANDLER_H +/*! + * \addtogroup InputHandler + * @{ + */ +#include "InputHandler.h" +#include "PlotUtils.h" +#include "StdHepEvt.h" + +/// Histogram input handler to read root histograms +class HistoInputHandler : public InputHandlerBase { + public: + /// Standard constructor given name and inputs + HistoInputHandler(std::string const& handle, std::string const& rawinputs); + ~HistoInputHandler(){}; + + /// Returns NUISANCE Format Event from GiReader + FitEvent* GetNuisanceEvent(const UInt_t entry, + const bool lightweight = false) { + return NULL; + } + + size_t NHistograms() { return fHistos.size(); } + TH1* GetHistogram(int i = -1); + std::vector GetHistograms(int i = -1, int j = -1); + + /// Print event information + void Print(); + + std::vector fHistos; +}; +#endif diff --git a/src/InputHandler/InputFactory.cxx b/src/InputHandler/InputFactory.cxx index 3333916..c3536ad 100644 --- a/src/InputHandler/InputFactory.cxx +++ b/src/InputHandler/InputFactory.cxx @@ -1,111 +1,122 @@ // 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 . *******************************************************************************/ +#include "FitEventInputHandler.h" +#include "GENIEInputHandler.h" +#include "GIBUUInputHandler.h" +#include "HistogramInputHandler.h" +#include "NEUTInputHandler.h" +#include "NUANCEInputHandler.h" +#include "NuWroInputHandler.h" +#include "SigmaQ0HistogramInputHandler.h" +#include "SplineInputHandler.h" + #include "InputFactory.h" +#include "TFile.h" namespace InputUtils { InputHandlerBase* CreateInputHandler(std::string const& handle, InputUtils::InputType inpType, std::string const& inputs) { InputHandlerBase* input = NULL; std::string newinputs = InputUtils::ExpandInputDirectories(inputs); switch (inpType) { - - - case (kNEUT_Input): + case (kNEUT_Input): #ifdef __NEUT_ENABLED__ - input = new NEUTInputHandler(handle, newinputs); + input = new NEUTInputHandler(handle, newinputs); #else - ERROR(FTL, "Tried to create NEUTInputHandler : " - << handle << " " << inpType << " " << inputs); - THROW("NEUT is not enabled!"); + ERROR(FTL, "Tried to create NEUTInputHandler : " + << handle << " " << inpType << " " << inputs); + THROW("NEUT is not enabled!"); #endif - break; + break; - case (kGENIE_Input): + case (kGENIE_Input): #ifdef __GENIE_ENABLED__ - input = new GENIEInputHandler(handle, newinputs); + input = new GENIEInputHandler(handle, newinputs); #else - ERROR(FTL, "Tried to create GENIEInputHandler : " - << handle << " " << inpType << " " << inputs); - THROW("GENIE is not enabled!"); + ERROR(FTL, "Tried to create GENIEInputHandler : " + << handle << " " << inpType << " " << inputs); + THROW("GENIE is not enabled!"); #endif - break; + break; - - case (kNUWRO_Input): + case (kNUWRO_Input): #ifdef __NUWRO_ENABLED__ - input = new NuWroInputHandler(handle, newinputs); + input = new NuWroInputHandler(handle, newinputs); #else - ERROR(FTL, "Tried to create NuWroInputHandler : " - << handle << " " << inpType << " " << inputs); - THROW("NuWro is not enabled!"); + ERROR(FTL, "Tried to create NuWroInputHandler : " + << handle << " " << inpType << " " << inputs); + THROW("NuWro is not enabled!"); #endif - break; + break; - case (kGiBUU_Input): + case (kGiBUU_Input): #ifdef __GiBUU_ENABLED__ - input = new GIBUUInputHandler(handle, newinputs); + input = new GIBUUInputHandler(handle, newinputs); #else - ERROR(FTL, "Tried to create GiBUUInputHandler : " - << handle << " " << inpType << " " << inputs); - THROW("GiBUU is not enabled!"); + ERROR(FTL, "Tried to create GiBUUInputHandler : " + << handle << " " << inpType << " " << inputs); + THROW("GiBUU is not enabled!"); #endif - break; + break; - case (kNUANCE_Input): + case (kNUANCE_Input): #ifdef __NUANCE_ENABLED__ - input = new NUANCEInputHandler(handle, newinputs); + input = new NUANCEInputHandler(handle, newinputs); #else - ERROR(FTL, "Tried to create NUANCEInputHandler : " - << handle << " " << inpType << " " << inputs); - THROW("NUANCE is not enabled!"); + ERROR(FTL, "Tried to create NUANCEInputHandler : " + << handle << " " << inpType << " " << inputs); + THROW("NUANCE is not enabled!"); #endif - break; + break; + + case (kFEVENT_Input): + input = new FitEventInputHandler(handle, newinputs); + break; - case (kFEVENT_Input): - input = new FitEventInputHandler(handle, newinputs); - break; + case (kEVSPLN_Input): + input = new SplineInputHandler(handle, newinputs); + break; - case (kEVSPLN_Input): - input = new SplineInputHandler(handle, newinputs); - break; + case (kSIGMAQ0HIST_Input): + input = new SigmaQ0HistogramInputHandler(handle, newinputs); + break; - case (kSIGMAQ0HIST_Input): - input = new SigmaQ0HistogramInputHandler(handle, newinputs); - break; + case (kHISTO_Input): + input = new HistoInputHandler(handle, newinputs); + break; - default: - break; + default: + break; } /// Input failed if (!input) { ERR(FTL) << "Input handler creation failed!" << std::endl; std::cout << "Generator Type " << inpType << " not enabled!" << std::endl; throw; } - return input; }; } diff --git a/src/InputHandler/InputFactory.h b/src/InputHandler/InputFactory.h index 9e5ef19..b06d5ad 100644 --- a/src/InputHandler/InputFactory.h +++ b/src/InputHandler/InputFactory.h @@ -1,46 +1,37 @@ // 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 INPUT_FACTORY_H #define INPUT_FACTORY_H #include -#include "TFile.h" #include "InputUtils.h" #include "InputHandler.h" -#include "NEUTInputHandler.h" -#include "GENIEInputHandler.h" -#include "NuWroInputHandler.h" -#include "GIBUUInputHandler.h" -#include "NUANCEInputHandler.h" -#include "FitEventInputHandler.h" -#include "SplineInputHandler.h" -#include "SigmaQ0HistogramInputHandler.h" namespace InputUtils { -InputHandlerBase* CreateInputHandler(std::string const& handle, +InputHandlerBase* CreateInputHandler(std::string const& handle, InputUtils::InputType inpType, std::string const& inputs); } #endif diff --git a/src/InputHandler/InputHandler.cxx b/src/InputHandler/InputHandler.cxx index f8fe558..06d27a9 100644 --- a/src/InputHandler/InputHandler.cxx +++ b/src/InputHandler/InputHandler.cxx @@ -1,266 +1,266 @@ // 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 . *******************************************************************************/ #include "InputHandler.h" +#include "InputUtils.h" InputHandlerBase::InputHandlerBase() { fName = ""; fFluxHist = NULL; fEventHist = NULL; fNEvents = 0; fNUISANCEEvent = NULL; fBaseEvent = NULL; kRemoveUndefParticles = FitPar::Config().GetParB("RemoveUndefParticles"); kRemoveFSIParticles = FitPar::Config().GetParB("RemoveFSIParticles"); kRemoveNuclearParticles = FitPar::Config().GetParB("RemoveNuclearParticles"); fMaxEvents = FitPar::Config().GetParI("MAXEVENTS"); fTTreePerformance = NULL; - }; InputHandlerBase::~InputHandlerBase() { - if (fFluxHist) delete fFluxHist; if (fEventHist) delete fEventHist; // if (fXSecHist) delete fXSecHist; // if (fNUISANCEEvent) delete fNUISANCEEvent; jointfluxinputs.clear(); jointeventinputs.clear(); jointindexlow.clear(); jointindexhigh.clear(); jointindexallowed.clear(); jointindexscale.clear(); // if (fTTreePerformance) { - // fTTreePerformance->SaveAs(("ttreeperfstats_" + fName + ".root").c_str()); - // } + // fTTreePerformance->SaveAs(("ttreeperfstats_" + fName + + // ".root").c_str()); + // } } -void InputHandlerBase::Print() { -}; +void InputHandlerBase::Print(){}; TH1D* InputHandlerBase::GetXSecHistogram(void) { fXSecHist = (TH1D*)fFluxHist->Clone(); fXSecHist->Divide(fEventHist); return fXSecHist; }; double InputHandlerBase::PredictedEventRate(double low, double high, - std::string intOpt) { - + std::string intOpt) { int minBin = fFluxHist->GetXaxis()->FindBin(low); int maxBin = fFluxHist->GetXaxis()->FindBin(high); return fEventHist->Integral(minBin, maxBin + 1, intOpt.c_str()); }; double InputHandlerBase::TotalIntegratedFlux(double low, double high, - std::string intOpt) { - + std::string intOpt) { Int_t minBin = fFluxHist->GetXaxis()->FindFixBin(low); Int_t maxBin = fFluxHist->GetXaxis()->FindFixBin(high); if ((fFluxHist->IsBinOverflow(minBin) && (low != -9999.9))) { minBin = 1; } if ((fFluxHist->IsBinOverflow(maxBin) && (high != -9999.9))) { maxBin = fFluxHist->GetXaxis()->GetNbins() + 1; } // If we are within a single bin if (minBin == maxBin) { // Get the contained fraction of the single bin's width return ((high - low) / fFluxHist->GetXaxis()->GetBinWidth(minBin)) * fFluxHist->Integral(minBin, minBin, intOpt.c_str()); } double lowBinUpEdge = fFluxHist->GetXaxis()->GetBinUpEdge(minBin); double highBinLowEdge = fFluxHist->GetXaxis()->GetBinLowEdge(maxBin); double lowBinfracIntegral = - ((lowBinUpEdge - low) / fFluxHist->GetXaxis()->GetBinWidth(minBin)) * - fFluxHist->Integral(minBin, minBin, intOpt.c_str()); + ((lowBinUpEdge - low) / fFluxHist->GetXaxis()->GetBinWidth(minBin)) * + fFluxHist->Integral(minBin, minBin, intOpt.c_str()); double highBinfracIntegral = - ((high - highBinLowEdge) / fFluxHist->GetXaxis()->GetBinWidth(maxBin)) * - fFluxHist->Integral(maxBin, maxBin, intOpt.c_str()); + ((high - highBinLowEdge) / fFluxHist->GetXaxis()->GetBinWidth(maxBin)) * + fFluxHist->Integral(maxBin, maxBin, intOpt.c_str()); // If they are neighbouring bins if ((minBin + 1) == maxBin) { std::cout << "Get lowfrac + highfrac" << std::endl; // Get the contained fraction of the two bin's width return lowBinfracIntegral + highBinfracIntegral; } // If there are filled bins between them return lowBinfracIntegral + highBinfracIntegral + fFluxHist->Integral(minBin + 1, maxBin - 1, intOpt.c_str()); // return fFluxHist->Integral(minBin + 1, maxBin - 1, intOpt.c_str()); } - std::vector InputHandlerBase::GetFluxList(void) { return std::vector(1, fFluxHist); }; std::vector InputHandlerBase::GetEventList(void) { return std::vector(1, fEventHist); }; std::vector InputHandlerBase::GetXSecList(void) { return std::vector(1, GetXSecHistogram()); }; FitEvent* InputHandlerBase::FirstNuisanceEvent() { fCurrentIndex = 0; return GetNuisanceEvent(fCurrentIndex); }; - - FitEvent* InputHandlerBase::NextNuisanceEvent() { fCurrentIndex++; - if((fMaxEvents != -1) && (fCurrentIndex > fMaxEvents)){ + if ((fMaxEvents != -1) && (fCurrentIndex > fMaxEvents)) { return NULL; } return GetNuisanceEvent(fCurrentIndex); }; - BaseFitEvt* InputHandlerBase::FirstBaseEvent() { fCurrentIndex = 0; return GetBaseEvent(fCurrentIndex); }; BaseFitEvt* InputHandlerBase::NextBaseEvent() { fCurrentIndex++; if (jointinput and fMaxEvents != -1) { - while ( fCurrentIndex < jointindexlow[jointindexswitch] || - fCurrentIndex >= jointindexhigh[jointindexswitch] ) { + while (fCurrentIndex < jointindexlow[jointindexswitch] || + fCurrentIndex >= jointindexhigh[jointindexswitch]) { jointindexswitch++; // Loop Around if (jointindexswitch == jointindexlow.size()) { jointindexswitch = 0; } } - - if (fCurrentIndex > jointindexlow[jointindexswitch] + jointindexallowed[jointindexswitch]) { + if (fCurrentIndex > + jointindexlow[jointindexswitch] + jointindexallowed[jointindexswitch]) { fCurrentIndex = jointindexlow[jointindexswitch]; } } return GetBaseEvent(fCurrentIndex); }; - -void InputHandlerBase::RegisterJointInput(std::string input, int n, TH1D* f, TH1D* e) { - +void InputHandlerBase::RegisterJointInput(std::string input, int n, TH1D* f, + TH1D* e) { if (jointfluxinputs.size() == 0) { jointindexswitch = 0; fNEvents = 0; } // Push into individual input vectors - jointfluxinputs.push_back( (TH1D*) f->Clone() ); - jointeventinputs.push_back( (TH1D*) e->Clone() ); + jointfluxinputs.push_back((TH1D*)f->Clone()); + jointeventinputs.push_back((TH1D*)e->Clone()); jointindexlow.push_back(fNEvents); jointindexhigh.push_back(fNEvents + n); fNEvents += n; // Add to the total flux/event hist - if (!fFluxHist) fFluxHist = (TH1D*) f->Clone(); - else fFluxHist->Add(f); - - if (!fEventHist) fEventHist = (TH1D*) e->Clone(); - else fEventHist->Add(e); - + if (!fFluxHist) + fFluxHist = (TH1D*)f->Clone(); + else + fFluxHist->Add(f); + + if (!fEventHist) + fEventHist = (TH1D*)e->Clone(); + else + fEventHist->Add(e); } - void InputHandlerBase::SetupJointInputs() { - if (jointeventinputs.size() <= 1) { jointinput = false; } else if (jointeventinputs.size() > 1) { jointinput = true; jointindexswitch = 0; } fMaxEvents = FitPar::Config().GetParI("MAXEVENTS"); - if (fMaxEvents != -1 and jointeventinputs.size() > 1){ + if (fMaxEvents != -1 and jointeventinputs.size() > 1) { THROW("Can only handle joint inputs when config MAXEVENTS = -1!"); } - for (size_t i = 0; i < jointeventinputs.size(); i++) { - TH1D* eventhist = (TH1D*) jointeventinputs.at(i)->Clone(); + if (jointeventinputs.size() > 1) { + ERROR(WRN, + "GiBUU sample contains multiple inputs. This will only work for " + "samples that expect multi-species inputs. If this sample does, you " + "can ignore this warning."); + } + for (size_t i = 0; i < jointeventinputs.size(); i++) { double scale = double(fNEvents) / fEventHist->Integral("width"); - scale *= eventhist->Integral("width"); + scale *= jointeventinputs.at(i)->Integral("width"); scale /= double(jointindexhigh[i] - jointindexlow[i]); - jointindexscale .push_back(scale); + jointindexscale.push_back(scale); } fEventHist->SetNameTitle((fName + "_EVT").c_str(), (fName + "_EVT").c_str()); fFluxHist->SetNameTitle((fName + "_FLUX").c_str(), (fName + "_FLUX").c_str()); // Setup Max Events if (fMaxEvents > 1 && fMaxEvents < fNEvents) { if (LOG_LEVEL(SAM)) { std::cout << "\t\t|-> Read Max Entries : " << fMaxEvents << std::endl; } fNEvents = fMaxEvents; } // Print out Status if (LOG_LEVEL(SAM)) { std::cout << "\t\t|-> Total Entries : " << fNEvents << std::endl - << "\t\t|-> Event Integral : " << fEventHist->Integral("width") * 1.E-38 << " events/nucleon" << std::endl - << "\t\t|-> Flux Integral : " << fFluxHist->Integral("width") << " /cm2" << std::endl + << "\t\t|-> Event Integral : " + << fEventHist->Integral("width") * 1.E-38 << " events/nucleon" + << std::endl + << "\t\t|-> Flux Integral : " << fFluxHist->Integral("width") + << " /cm2" << std::endl << "\t\t|-> Event/Flux : " - << fEventHist->Integral("width") * 1.E-38 / fFluxHist->Integral("width") << " cm2/nucleon" << std::endl; + << fEventHist->Integral("width") * 1.E-38 / + fFluxHist->Integral("width") + << " cm2/nucleon" << std::endl; } - } BaseFitEvt* InputHandlerBase::GetBaseEvent(const UInt_t entry) { return static_cast(GetNuisanceEvent(entry, true)); } double InputHandlerBase::GetInputWeight(int entry) { - if (!jointinput) return 1.0; // Find Switch Scale - while ( entry < jointindexlow[jointindexswitch] || - entry >= jointindexhigh[jointindexswitch] ) { + while (entry < jointindexlow[jointindexswitch] || + entry >= jointindexhigh[jointindexswitch]) { jointindexswitch++; // Loop Around if (jointindexswitch >= jointindexlow.size()) { jointindexswitch = 0; } } return jointindexscale[jointindexswitch]; }; - diff --git a/src/InputHandler/InputHandler.h b/src/InputHandler/InputHandler.h index a04cbf2..3377403 100644 --- a/src/InputHandler/InputHandler.h +++ b/src/InputHandler/InputHandler.h @@ -1,146 +1,145 @@ // 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 INPUTHANDLER2_H #define INPUTHANDLER2_H /*! * \addtogroup InputHandler * @{ */ #include "TH1D.h" #include "FitEvent.h" #include "BaseFitEvt.h" #include "TTreePerfStats.h" -#include "InputUtils.h" /// Base InputHandler class defining how events are requested and setup. class InputHandlerBase { public: /// Base constructor resets everything to default InputHandlerBase(); /// Removes flux/event rate histograms virtual ~InputHandlerBase(); /// Return NUISANCE FitEvent Class from given event entry. /// Must be overriden by GeneratorInputHandler. Lightweight allows a faster option /// to be given where only RW information is needed. virtual FitEvent* GetNuisanceEvent(const UInt_t entry, const bool lightweight=false) = 0; /// Calls GetNuisanceEvent(entry, TRUE); virtual BaseFitEvt* GetBaseEvent(const UInt_t entry); /// Print current event information virtual void Print(); /// Return handler ID inline std::string GetName (void) {return fName; }; /// Return Handler Event Type Index inline int GetType (void) {return fEventType;}; /// Get Total Number of Events being Handled inline virtual int GetNEvents (void) {return fNEvents; }; /// Get the Total Flux Histogram these events were generated with inline virtual TH1D* GetFluxHistogram (void) {return fFluxHist; }; /// Get the Total Event Histogram these events were generated with inline virtual TH1D* GetEventHistogram (void) {return fEventHist;}; /// Get the Total Cross-section Histogram (EventHist/FluxHist) virtual TH1D* GetXSecHistogram(void); /// Return all Flux Histograms for all InputFiles. virtual std::vector GetFluxList(void); /// Return all Event Histograms for all InputFiles virtual std::vector GetEventList(void); /// Return all Xsec Histograms for all InputFiles virtual std::vector GetXSecList(void); /// Placeholder to create a cache to speed up reads in GeneratorInputHandler inline virtual void CreateCache(){}; /// Placeholder to remove optional cache to free up memory inline virtual void RemoveCache(){}; /// Return starting NUISANCE event pointer (entry=0) FitEvent* FirstNuisanceEvent(); /// Iterate to next NUISANCE event. Returns NULL when entry > fNEvents. FitEvent* NextNuisanceEvent(); /// Returns starting Base Event Pointer (entry=0) BaseFitEvt* FirstBaseEvent(); /// Iterate to next NUISANCE Base Event. Returns NULL when entry > fNEvents. BaseFitEvt* NextBaseEvent(); /// Register an input file and update event/flux information virtual void RegisterJointInput(std::string input, int n, TH1D* f, TH1D* e); /// Finalise setup of Input event/flux information and calculate /// joint input weights if joint input is provided. virtual void SetupJointInputs(); /// Calculate a weight for the event given the joint input information. /// Used to scale the relative proportion of multiple inputs correctly /// with respect to one another. virtual double GetInputWeight(int entry); /// Returns the total predicted event rate for this input given the /// low and high energy ranges. intOpt specifies the option the ROOT /// TH1D integral should use. e.g. "" or "width" double PredictedEventRate(double low, double high, std::string intOpt); /// Returns the total generated flux for this input given the /// low and high energy ranges. intOpt specifies the option the ROOT /// TH1D integral should use. e.g. "" or "width" double TotalIntegratedFlux(double low = -9999.9, double high = -9999.9, std::string intOpt = ""); /// Actual data members. std::vector jointfluxinputs; std::vector jointeventinputs; std::vector jointindexlow; std::vector jointindexhigh; std::vector jointindexallowed; size_t jointindexswitch; bool jointinput; std::vector jointindexscale; std::string fName; TH1D* fFluxHist; TH1D* fEventHist; TH1D* fXSecHist; int fNEvents; int fMaxEvents; FitEvent* fNUISANCEEvent; BaseFitEvt* fBaseEvent; int fEventType; int fCurrentIndex; int fCacheSize; bool kRemoveUndefParticles; bool kRemoveFSIParticles; bool kRemoveNuclearParticles; TTreePerfStats* fTTreePerformance; }; /*! @} */ #endif diff --git a/src/InputHandler/InputTypes.h b/src/InputHandler/InputTypes.h index eacac10..89215cd 100644 --- a/src/InputHandler/InputTypes.h +++ b/src/InputHandler/InputTypes.h @@ -1,159 +1,164 @@ // 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 INPUTTYPES_SEEN_H #define INPUTTYPES_SEEN_H /// Global Enum to define generator type being read with FitEvent /// Have to define kNORM as if its a generator for the time being. enum generator_event_type { kUNKNOWN = 999, kNEUT = 0, kNIWG = 1, kNUWRO = 2, kT2K = 3, kCUSTOM = 4, kGENIE = 5, kEVTSPLINE = 6, kNUANCE = 7, kGiBUU = 8, kNORM = 9, kMODENORM = 10, kEMPTY = 11, kINPUTFITEVENT = 12, kNEWSPLINE = 13, kLIKEWEIGHT = 14, kSPLINEPARAMETER = 15, kHEPMC = 16, - kHISTEVENT = 17, + kHISTO = 17, kSIGMAQ0HIST = 18, kLast_generator_event_type }; namespace InputUtils { enum InputType { kNEUT_Input = 0, kNUWRO_Input = 1, kGENIE_Input = 2, kGiBUU_Input, kNUANCE_Input, kEVSPLN_Input, kEMPTY_Input, kFEVENT_Input, kJOINT_Input, kSIGMAQ0HIST_Input, + kHISTO_Input, kInvalid_Input, - kHIST_Input, // Not sure if this are currently used. kBNSPLN_Input, // Not sure if this are currently used. }; } inline std::ostream& operator<<(std::ostream& os, generator_event_type const& gs) { switch (gs) { case kUNKNOWN: { return os << "kUNKNOWN"; } case kNEUT: { return os << "kNEUT"; } case kNIWG: { return os << "kNIWG"; } case kNUWRO: { return os << "kNUWRO"; } case kT2K: { return os << "kT2K"; } case kCUSTOM: { return os << "kCUSTOM"; } case kGENIE: { return os << "kGENIE"; } case kEVTSPLINE: { return os << "kEVTSPLINE"; } case kNUANCE: { return os << "kNUANCE"; } case kGiBUU: { return os << "kGiBUU"; } case kNORM: { return os << "kNORM"; } case kMODENORM: { return os << "kMODENORM"; } case kHEPMC: { return os << "kHEPMC"; } case kSIGMAQ0HIST: { return os << "kSIGMAQ0HIST"; } + case kHISTO: { + return os << "kHISTO"; + } default: { return os << "kUNKNOWN"; } } } inline std::ostream &operator<<(std::ostream &os, InputUtils::InputType it) { switch (it) { case InputUtils::kNEUT_Input: { return os << "kNEUT_Input"; } case InputUtils::kNUWRO_Input: { return os << "kNUWRO_Input"; } case InputUtils::kGENIE_Input: { return os << "kGENIE_Input"; } case InputUtils::kGiBUU_Input: { return os << "kGiBUU_Input"; } case InputUtils::kNUANCE_Input: { return os << "kNUANCE_Input"; } case InputUtils::kEVSPLN_Input: { return os << "kEVSPLN_Input"; } case InputUtils::kEMPTY_Input: { return os << "kEMPTY_Input"; } case InputUtils::kFEVENT_Input: { return os << "kFEVENT_Input"; } case InputUtils::kJOINT_Input: { return os << "kJOINT_Input"; } case InputUtils::kSIGMAQ0HIST_Input: { return os << "kSIGMAQ0HIST_Input"; } + case InputUtils::kHISTO_Input: { + return os << "kHISTO_Input"; + } case InputUtils::kInvalid_Input: - case InputUtils::kHIST_Input: case InputUtils::kBNSPLN_Input: default: { return os << "kInvalid_Input"; } } } #endif diff --git a/src/InputHandler/InputUtils.cxx b/src/InputHandler/InputUtils.cxx index 4bed1bb..8f7acdf 100644 --- a/src/InputHandler/InputUtils.cxx +++ b/src/InputHandler/InputUtils.cxx @@ -1,173 +1,173 @@ // 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 . *******************************************************************************/ #include "FitParameters.h" #include "GeneralUtils.h" #include "InputHandler.h" #include "InputUtils.h" namespace InputUtils { std::vector ParseInputFileList(std::string const &inpFile) { std::vector inputs = GeneralUtils::ParseToStr(inpFile, ","); if (inputs.front()[0] == '(') { inputs.front() = inputs.front().substr(1); } if (inputs.back()[inputs.back().size() - 1] == ')') { inputs.back() = inputs.back().substr(0, inputs.back().size() - 1); } return inputs; } InputType ParseInputType(std::string const &inp) { // The hard-coded list of supported input generators const static std::string filetypes[] = { "NEUT", "NUWRO", "GENIE", "GiBUU", "NUANCE", - "EVSPLN", "EMPTY", "FEVENT", "JOINT", "SIGMAQ0HIST"}; + "EVSPLN", "EMPTY", "FEVENT", "JOINT", "SIGMAQ0HIST", "HISTO"}; size_t nInputTypes = GeneralUtils::GetArraySize(filetypes); for (size_t i = 0; i < nInputTypes; i++) { if (inp == filetypes[i]) { return InputType(i); } } return kInvalid_Input; } bool IsJointInput(std::string const &inputs) { bool isJoint = (inputs[0] == '('); if (isJoint && (inputs[inputs.length() - 1] != ')')) { ERR(FTL) << "Inputs specifier: \"" << inputs << "\" looks like a composite input specifier -- " "(filea.root,fileb.root), however, it did not end in a \')\', " "it ended in a \'" << inputs[inputs.length() - 1] << "\'" << std::endl; throw; } return isJoint; } std::string ExpandInputDirectories(std::string const &inputs) { // Parse the "environement" flags in the fitter config // Can specify NEUT_DIR = "" and others in parameters/fitter.config.dat const static std::string filedir[] = {"NEUT_DIR", "NUWRO_DIR", "GENIE_DIR", "NUANCE_DIR", "EVSPLN_DIR", "GIBUU_DIR"}; size_t nfiledir = GeneralUtils::GetArraySize(filedir); std::string expandedInputs = inputs; for (size_t i = 0; i < nfiledir; i++) { std::string tempdir = "@" + filedir[i]; bool didRpl; do { size_t torpl = expandedInputs.find(tempdir); if (torpl != std::string::npos) { std::string event_folder = FitPar::Config().GetParS(filedir[i]); expandedInputs.replace(torpl, tempdir.size(), event_folder); didRpl = true; } else { didRpl = false; } } while (didRpl); } bool didRpl; do { size_t torpl = expandedInputs.find("//"); if (torpl != std::string::npos) { expandedInputs.replace(torpl, 2, "/"); didRpl = true; } else { didRpl = false; } } while (didRpl); return expandedInputs; } InputType GuessInputTypeFromFile(TFile *inpF) { const std::string NEUT_TreeName = "neuttree"; const std::string NuWro_TreeName = "treeout"; const std::string GENIE_TreeName = "gtree"; const std::string GiBUU_TreeName = "giRooTracker"; if (!inpF) { return kInvalid_Input; } TTree *NEUT_Input = dynamic_cast(inpF->Get(NEUT_TreeName.c_str())); if (NEUT_Input) { return kNEUT_Input; } TTree *NUWRO_Input = dynamic_cast(inpF->Get(NuWro_TreeName.c_str())); if (NUWRO_Input) { return kNUWRO_Input; } TTree *GENIE_Input = dynamic_cast(inpF->Get(GENIE_TreeName.c_str())); if (GENIE_Input) { return kGENIE_Input; } TTree *GiBUU_Input = dynamic_cast(inpF->Get(GiBUU_TreeName.c_str())); if (GiBUU_Input) { return kGiBUU_Input; } return kInvalid_Input; } std::string PrependGuessedInputTypeToName(std::string const &inpFName) { //If it already has a name. if(inpFName.find(":") != std::string::npos){ return inpFName; } TFile *inpF = TFile::Open(inpFName.c_str(), "READ"); if (!inpF || !inpF->IsOpen()) { THROW("Couldn't open \"" << inpFName << "\" for reading."); } InputType iType = GuessInputTypeFromFile(inpF); if (iType == kInvalid_Input) { THROW("Couldn't determine input type from file: " << inpFName << "."); } inpF->Close(); delete inpF; switch (iType) { case kNEUT_Input: { return "NEUT:" + inpFName; } case kNUWRO_Input: { return "NUWRO:" + inpFName; } case kGENIE_Input: { return "GENIE:" + inpFName; } case kGiBUU_Input: { return "GiBUU:" + inpFName; } default: { ERR(FTL) << "Input type from file: " << inpFName << " was invalid." << std::endl; throw; } } } } diff --git a/src/InputHandler/NEUTInputHandler.cxx b/src/InputHandler/NEUTInputHandler.cxx index 49bbf87..3bf9746 100644 --- a/src/InputHandler/NEUTInputHandler.cxx +++ b/src/InputHandler/NEUTInputHandler.cxx @@ -1,457 +1,459 @@ #ifdef __NEUT_ENABLED__ #include "NEUTInputHandler.h" +#include "InputUtils.h" + NEUTGeneratorInfo::~NEUTGeneratorInfo() { DeallocateParticleStack(); } void NEUTGeneratorInfo::AddBranchesToTree(TTree* tn) { tn->Branch("NEUTParticleN", fNEUTParticleN, "NEUTParticleN/I"); tn->Branch("NEUTParticleStatusCode", fNEUTParticleStatusCode, "NEUTParticleStatusCode[NEUTParticleN]/I"); tn->Branch("NEUTParticleAliveCode", fNEUTParticleAliveCode, "NEUTParticleAliveCode[NEUTParticleN]/I"); } void NEUTGeneratorInfo::SetBranchesFromTree(TTree* tn) { tn->SetBranchAddress("NEUTParticleN", &fNEUTParticleN); tn->SetBranchAddress("NEUTParticleStatusCode", &fNEUTParticleStatusCode); tn->SetBranchAddress("NEUTParticleAliveCode", &fNEUTParticleAliveCode); } void NEUTGeneratorInfo::AllocateParticleStack(int stacksize) { fNEUTParticleN = 0; fNEUTParticleStatusCode = new int[stacksize]; fNEUTParticleStatusCode = new int[stacksize]; } void NEUTGeneratorInfo::DeallocateParticleStack() { delete fNEUTParticleStatusCode; delete fNEUTParticleAliveCode; } void NEUTGeneratorInfo::FillGeneratorInfo(NeutVect* nevent) { Reset(); for (int i = 0; i < nevent->Npart(); i++) { fNEUTParticleStatusCode[i] = nevent->PartInfo(i)->fStatus; fNEUTParticleAliveCode[i] = nevent->PartInfo(i)->fIsAlive; fNEUTParticleN++; } } void NEUTGeneratorInfo::Reset() { for (int i = 0; i < fNEUTParticleN; i++) { fNEUTParticleStatusCode[i] = -1; fNEUTParticleAliveCode[i] = 9; } fNEUTParticleN = 0; } NEUTInputHandler::NEUTInputHandler(std::string const& handle, std::string const& rawinputs) { LOG(SAM) << "Creating NEUTInputHandler : " << handle << std::endl; // Run a joint input handling fName = handle; // Setup the TChain fNEUTTree = new TChain("neuttree"); fSaveExtra = FitPar::Config().GetParB("SaveExtraNEUT"); fCacheSize = FitPar::Config().GetParI("CacheSize"); fMaxEvents = FitPar::Config().GetParI("MAXEVENTS"); // 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(inputs[inp_it].c_str(), "READ"); if (!inp_file or inp_file->IsZombie()) { THROW("NEUT 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( (PlotUtils::GetObjectWithName(inp_file, "flux")).c_str()); TH1D* eventhist = (TH1D*)inp_file->Get( (PlotUtils::GetObjectWithName(inp_file, "evt")).c_str()); if (!fluxhist or !eventhist) { ERROR(FTL, "Input File Contents: " << inputs[inp_it]); inp_file->ls(); THROW( "NEUT FILE doesn't contain flux/xsec info. You may have to " "regenerate your MC!"); } // Get N Events TTree* neuttree = (TTree*)inp_file->Get("neuttree"); if (!neuttree) { ERROR(FTL, "neuttree not located in NEUT file: " << inputs[inp_it]); THROW("Check your inputs, they may need to be completely regenerated!"); throw; } int nevents = neuttree->GetEntries(); if (nevents <= 0) { THROW("Trying to a TTree with " << nevents << " to TChain from : " << inputs[inp_it]); } // Register input to form flux/event rate hists RegisterJointInput(inputs[inp_it], nevents, fluxhist, eventhist); // Add To TChain fNEUTTree->AddFile(inputs[inp_it].c_str()); } // Registor all our file inputs SetupJointInputs(); // Assign to tree fEventType = kNEUT; fNeutVect = NULL; fNEUTTree->SetBranchAddress("vectorbranch", &fNeutVect); fNEUTTree->GetEntry(0); // Create Fit Event fNUISANCEEvent = new FitEvent(); fNUISANCEEvent->SetNeutVect(fNeutVect); if (fSaveExtra) { fNeutInfo = new NEUTGeneratorInfo(); fNUISANCEEvent->AddGeneratorInfo(fNeutInfo); } fNUISANCEEvent->HardReset(); }; NEUTInputHandler::~NEUTInputHandler(){ // if (fNEUTTree) delete fNEUTTree; // if (fNeutVect) delete fNeutVect; // if (fNeutInfo) delete fNeutInfo; }; void NEUTInputHandler::CreateCache() { if (fCacheSize > 0) { // fNEUTTree->SetCacheEntryRange(0, fNEvents); fNEUTTree->AddBranchToCache("vectorbranch", 1); fNEUTTree->SetCacheSize(fCacheSize); } } void NEUTInputHandler::RemoveCache() { // fNEUTTree->SetCacheEntryRange(0, fNEvents); fNEUTTree->AddBranchToCache("vectorbranch", 0); fNEUTTree->SetCacheSize(0); } FitEvent* NEUTInputHandler::GetNuisanceEvent(const UInt_t entry, const bool lightweight) { // Catch too large entries if (entry >= (UInt_t)fNEvents) return NULL; // Read Entry from TTree to fill NEUT Vect in BaseFitEvt; fNEUTTree->GetEntry(entry); // Run NUISANCE Vector Filler if (!lightweight) { CalcNUISANCEKinematics(); } #ifdef __PROB3PP_ENABLED__ else { for (size_t i = 0; i < npart; i++) { NeutPart* part = fNUISANCEEvent->fNeutVect->PartInfo(i); if ((part->fIsAlive == false) && (part->fStatus == -1) && std::count(PhysConst::pdg_neutrinos, PhysConst::pdg_neutrinos + 4, part->fPID)) { fNUISANCEEvent->probe_E = part->fP.T(); fNUISANCEEvent->probe_pdg = part->fPID; break; } else { continue; } } } #endif // Setup Input scaling for joint inputs fNUISANCEEvent->InputWeight = GetInputWeight(entry); // Return event pointer return fNUISANCEEvent; } int NEUTInputHandler::GetNeutParticleStatus(NeutPart* part) { // State int state = kUndefinedState; // fStatus == -1 means initial state if (part->fIsAlive == false && part->fStatus == -1) { state = kInitialState; // NEUT has a bit of a strange convention for fIsAlive and fStatus // combinations // for NC and neutrino particle isAlive true/false and status 2 means // final state particle // for other particles in NC status 2 means it's an FSI particle // for CC it means it was an FSI particle } else if (part->fStatus == 2) { // NC case is a little strange... The outgoing neutrino might be alive or // not alive. Remaining particles with status 2 are FSI particles that // reinteracted if (abs(fNeutVect->Mode) > 30 && (abs(part->fPID) == 14 || abs(part->fPID) == 12)) { state = kFinalState; // The usual CC case } else if (part->fIsAlive == true) { state = kFSIState; } } else if (part->fIsAlive == true && part->fStatus == 2 && (abs(part->fPID) == 14 || abs(part->fPID) == 12)) { state = kFinalState; } else if (part->fIsAlive == true && part->fStatus == 0) { state = kFinalState; } else if (part->fIsAlive == true) { ERR(WRN) << "Undefined NEUT state " << " Alive: " << part->fIsAlive << " Status: " << part->fStatus << " PDG: " << part->fPID << std::endl; throw; } return state; } void NEUTInputHandler::CalcNUISANCEKinematics() { // Reset all variables fNUISANCEEvent->ResetEvent(); // Fill Globals fNUISANCEEvent->fMode = fNeutVect->Mode; fNUISANCEEvent->Mode = fNeutVect->Mode; fNUISANCEEvent->fEventNo = fNeutVect->EventNo; fNUISANCEEvent->fTargetA = fNeutVect->TargetA; fNUISANCEEvent->fTargetZ = fNeutVect->TargetZ; fNUISANCEEvent->fTargetH = fNeutVect->TargetH; fNUISANCEEvent->fBound = bool(fNeutVect->Ibound); if (fNUISANCEEvent->fBound) { fNUISANCEEvent->fTargetPDG = TargetUtils::GetTargetPDGFromZA( fNUISANCEEvent->fTargetZ, fNUISANCEEvent->fTargetA); } else { fNUISANCEEvent->fTargetPDG = 1000010010; } // Check Particle Stack UInt_t npart = fNeutVect->Npart(); UInt_t kmax = fNUISANCEEvent->kMaxParticles; if (npart > kmax) { ERR(FTL) << "NEUT has too many particles. Expanding stack." << std::endl; fNUISANCEEvent->ExpandParticleStack(npart); throw; } // Fill Particle Stack for (size_t i = 0; i < npart; i++) { // Get Current Count int curpart = fNUISANCEEvent->fNParticles; // Get NEUT Particle NeutPart* part = fNeutVect->PartInfo(i); // State int state = GetNeutParticleStatus(part); // Remove Undefined if (kRemoveUndefParticles && state == kUndefinedState) continue; // Remove FSI if (kRemoveFSIParticles && state == kFSIState) continue; // Remove Nuclear if (kRemoveNuclearParticles && (state == kNuclearInitial || state == kNuclearRemnant)) continue; // State fNUISANCEEvent->fParticleState[curpart] = state; // Mom fNUISANCEEvent->fParticleMom[curpart][0] = part->fP.X(); fNUISANCEEvent->fParticleMom[curpart][1] = part->fP.Y(); fNUISANCEEvent->fParticleMom[curpart][2] = part->fP.Z(); fNUISANCEEvent->fParticleMom[curpart][3] = part->fP.T(); // PDG fNUISANCEEvent->fParticlePDG[curpart] = part->fPID; // Add up particle count fNUISANCEEvent->fNParticles++; } // Save Extra Generator Info if (fSaveExtra) { fNeutInfo->FillGeneratorInfo(fNeutVect); } // 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 NEUTUtils::FillNeutCommons(NeutVect* nvect) { // WARNING: This has only been implemented for a neuttree and not GENIE // This should be kept in sync with T2KNIWGUtils::GetNIWGEvent(TTree) // NEUT version info. Can't get it to compile properly with this yet // neutversion_.corev = nvect->COREVer; // neutversion_.nucev = nvect->NUCEVer; // neutversion_.nuccv = nvect->NUCCVer; // Documentation: See nework.h nework_.modene = nvect->Mode; nework_.numne = nvect->Npart(); nemdls_.mdlqeaf = nvect->QEVForm; nemdls_.mdlqe = nvect->QEModel; nemdls_.mdlspi = nvect->SPIModel; nemdls_.mdldis = nvect->DISModel; nemdls_.mdlcoh = nvect->COHModel; neutcoh_.necohepi = nvect->COHModel; nemdls_.xmaqe = nvect->QEMA; nemdls_.xmvqe = nvect->QEMV; nemdls_.kapp = nvect->KAPPA; // nemdls_.sccfv = SCCFVdef; // nemdls_.sccfa = SCCFAdef; // nemdls_.fpqe = FPQEdef; nemdls_.xmaspi = nvect->SPIMA; nemdls_.xmvspi = nvect->SPIMV; nemdls_.xmares = nvect->RESMA; nemdls_.xmvres = nvect->RESMV; neut1pi_.xmanffres = nvect->SPIMA; neut1pi_.xmvnffres = nvect->SPIMV; neut1pi_.xmarsres = nvect->RESMA; neut1pi_.xmvrsres = nvect->RESMV; neut1pi_.neiff = nvect->SPIForm; neut1pi_.nenrtype = nvect->SPINRType; neut1pi_.rneca5i = nvect->SPICA5I; neut1pi_.rnebgscl = nvect->SPIBGScale; nemdls_.xmacoh = nvect->COHMA; nemdls_.rad0nu = nvect->COHR0; // nemdls_.fa1coh = nvect->COHA1err; // nemdls_.fb1coh = nvect->COHb1err; // neutdis_.nepdf = NEPDFdef; // neutdis_.nebodek = NEBODEKdef; neutcard_.nefrmflg = nvect->FrmFlg; neutcard_.nepauflg = nvect->PauFlg; neutcard_.nenefo16 = nvect->NefO16; neutcard_.nemodflg = nvect->ModFlg; // neutcard_.nenefmodl = 1; // neutcard_.nenefmodh = 1; // neutcard_.nenefkinh = 1; // neutpiabs_.neabspiemit = 1; nenupr_.iformlen = nvect->FormLen; neutpiless_.ipilessdcy = nvect->IPilessDcy; neutpiless_.rpilessdcy = nvect->RPilessDcy; neutpiless_.ipilessdcy = nvect->IPilessDcy; neutpiless_.rpilessdcy = nvect->RPilessDcy; neffpr_.fefqe = nvect->NuceffFactorPIQE; neffpr_.fefqeh = nvect->NuceffFactorPIQEH; neffpr_.fefinel = nvect->NuceffFactorPIInel; neffpr_.fefabs = nvect->NuceffFactorPIAbs; neffpr_.fefcx = nvect->NuceffFactorPICX; neffpr_.fefcxh = nvect->NuceffFactorPICXH; neffpr_.fefcoh = nvect->NuceffFactorPICoh; neffpr_.fefqehf = nvect->NuceffFactorPIQEHKin; neffpr_.fefcxhf = nvect->NuceffFactorPICXKin; neffpr_.fefcohf = nvect->NuceffFactorPIQELKin; for (int i = 0; i < nework_.numne; i++) { nework_.ipne[i] = nvect->PartInfo(i)->fPID; nework_.pne[i][0] = (float)nvect->PartInfo(i)->fP.X() / 1000; // VC(NE)WORK in M(G)eV nework_.pne[i][1] = (float)nvect->PartInfo(i)->fP.Y() / 1000; // VC(NE)WORK in M(G)eV nework_.pne[i][2] = (float)nvect->PartInfo(i)->fP.Z() / 1000; // VC(NE)WORK in M(G)eV } // fsihist.h // neutroot fills a dummy object for events with no FSI to prevent memory leak // when // reading the TTree, so check for it here if ((int)nvect->NfsiVert() == 1) { // An event with FSI must have at least two vertices // if (nvect->NfsiPart()!=1 || nvect->Fsiprob!=-1) // ERR(WRN) << "T2KNeutUtils::fill_neut_commons(TTree) NfsiPart!=1 or // Fsiprob!=-1 when NfsiVert==1" << std::endl; fsihist_.nvert = 0; fsihist_.nvcvert = 0; fsihist_.fsiprob = 1; } else { // Real FSI event fsihist_.nvert = (int)nvect->NfsiVert(); for (int ivert = 0; ivert < fsihist_.nvert; ivert++) { fsihist_.iflgvert[ivert] = nvect->FsiVertInfo(ivert)->fVertID; fsihist_.posvert[ivert][0] = (float)nvect->FsiVertInfo(ivert)->fPos.X(); fsihist_.posvert[ivert][1] = (float)nvect->FsiVertInfo(ivert)->fPos.Y(); fsihist_.posvert[ivert][2] = (float)nvect->FsiVertInfo(ivert)->fPos.Z(); } fsihist_.nvcvert = nvect->NfsiPart(); for (int ip = 0; ip < fsihist_.nvcvert; ip++) { fsihist_.abspvert[ip] = (float)nvect->FsiPartInfo(ip)->fMomLab; fsihist_.abstpvert[ip] = (float)nvect->FsiPartInfo(ip)->fMomNuc; fsihist_.ipvert[ip] = nvect->FsiPartInfo(ip)->fPID; fsihist_.iverti[ip] = nvect->FsiPartInfo(ip)->fVertStart; fsihist_.ivertf[ip] = nvect->FsiPartInfo(ip)->fVertEnd; fsihist_.dirvert[ip][0] = (float)nvect->FsiPartInfo(ip)->fDir.X(); fsihist_.dirvert[ip][1] = (float)nvect->FsiPartInfo(ip)->fDir.Y(); fsihist_.dirvert[ip][2] = (float)nvect->FsiPartInfo(ip)->fDir.Z(); } fsihist_.fsiprob = nvect->Fsiprob; } neutcrscom_.crsx = nvect->Crsx; neutcrscom_.crsy = nvect->Crsy; neutcrscom_.crsz = nvect->Crsz; neutcrscom_.crsphi = nvect->Crsphi; neutcrscom_.crsq2 = nvect->Crsq2; neuttarget_.numbndn = nvect->TargetA - nvect->TargetZ; neuttarget_.numbndp = nvect->TargetZ; neuttarget_.numfrep = nvect->TargetH; neuttarget_.numatom = nvect->TargetA; posinnuc_.ibound = nvect->Ibound; // put empty nucleon FSI history (since it is not saved in the NeutVect // format) // Comment out as NEUT does not have the necessary proton FSI information yet // nucleonfsihist_.nfnvert = 0; // nucleonfsihist_.nfnstep = 0; } #endif diff --git a/src/InputHandler/NUANCEInputHandler.cxx b/src/InputHandler/NUANCEInputHandler.cxx index 178c36b..ad98dcd 100644 --- a/src/InputHandler/NUANCEInputHandler.cxx +++ b/src/InputHandler/NUANCEInputHandler.cxx @@ -1,835 +1,837 @@ #ifdef __NUANCE_ENABLED__ #include "NUANCEInputHandler.h" +#include "InputUtils.h" + NUANCEGeneratorInfo::~NUANCEGeneratorInfo() { DeallocateParticleStack(); } void NUANCEGeneratorInfo::AddBranchesToTree(TTree * tn) { // tn->Branch("NEUTParticleN", fNEUTParticleN, "NEUTParticleN/I"); // tn->Branch("NEUTParticleStatusCode", fNEUTParticleStatusCode, "NEUTParticleStatusCode[NEUTParticleN]/I"); // tn->Branch("NEUTParticleAliveCode", fNEUTParticleAliveCode, "NEUTParticleAliveCode[NEUTParticleN]/I"); } void NUANCEGeneratorInfo::SetBranchesFromTree(TTree* tn) { // tn->SetBranchAddress("NEUTParticleN", &fNEUTParticleN ); // tn->SetBranchAddress("NEUTParticleStatusCode", &fNEUTParticleStatusCode ); // tn->SetBranchAddress("NEUTParticleAliveCode", &fNEUTParticleAliveCode ); } void NUANCEGeneratorInfo::AllocateParticleStack(int stacksize) { // fNEUTParticleN = 0; // fNEUTParticleStatusCode = new int[stacksize]; // fNEUTParticleStatusCode = new int[stacksize]; } void NUANCEGeneratorInfo::DeallocateParticleStack() { // delete fNEUTParticleStatusCode; // delete fNEUTParticleAliveCode; } void NUANCEGeneratorInfo::FillGeneratorInfo(NuanceEvent* nevent) { Reset(); // for (int i = 0; i < nevent->Npart(); i++) { // fNEUTParticleStatusCode[i] = nevent->PartInfo(i)->fStatus; // fNEUTParticleAliveCode[i] = nevent->PartInfo(i)->fIsAlive; // fNEUTParticleN++; // } } void NUANCEGeneratorInfo::Reset() { // for (int i = 0; i < fNEUTParticleN; i++) { // fNEUTParticleStatusCode[i] = -1; // fNEUTParticleAliveCode[i] = 9; // } // fNEUTParticleN = 0; } NUANCEInputHandler::NUANCEInputHandler(std::string const& handle, std::string const& rawinputs) { LOG(SAM) << "Creating NUANCEInputHandler : " << handle << std::endl; // Run a joint input handling fName = handle; fSaveExtra = FitPar::Config().GetParB("SaveExtraNUANCE"); fCacheSize = FitPar::Config().GetParI("CacheSize"); fMaxEvents = FitPar::Config().GetParI("MAXEVENTS"); // Parse Inputs std::vector inputs = InputUtils::ParseInputFileList(rawinputs); if (inputs.size() > 1) { ERR(FTL) << "NUANCE is not currently setup to handle joint inputs sorry!" << std::endl << "If you know how to correctly normalise the events for this" << " please let us know!" << std::endl; } // Read in NUANCE Tree fNUANCETree = new TChain("h3"); fNUANCETree->AddFile(rawinputs.c_str()); // Get entries and fNuwroEvent int nevents = fNUANCETree->GetEntries(); double EnuMin = 0.0; double EnuMax = 1000.0; TH1D* fluxhist = new TH1D((fName + "_FLUX").c_str(), (fName + "_FLUX").c_str(), 100, EnuMin, EnuMax); for (int i = 0; i < fluxhist->GetNbinsX(); i++) { fluxhist->SetBinContent(i + 1, 1.0); } fluxhist->Scale(1.0 / fluxhist->Integral()); TH1D* eventhist = new TH1D((fName + "_EVT").c_str(), (fName + "_EVT").c_str(), 100, EnuMin, EnuMax); for (int i = 0; i < fluxhist->GetNbinsX(); i++) { eventhist->SetBinContent(i + 1, 1.0); } eventhist->Scale(1.0 / eventhist->Integral()); RegisterJointInput( rawinputs, nevents, fluxhist, eventhist ); SetupJointInputs(); // Setup Reader fNuanceEvent = new NuanceEvent(); fNuanceEvent->SetBranchAddresses(fNUANCETree); fNUANCETree->GetEntry(0); // Setup Event in FitEvent fNUISANCEEvent = new FitEvent(); fNUISANCEEvent->SetNuanceEvent(fNuanceEvent); // Setup extra if needed if (fSaveExtra){ ERR(FTL) << "NO SAVEExtra Implemented for NUANCE YET!" << std::endl; throw; // fNuanceInfo = new NUANCEGeneratorInfo(); // fNUISANCEEvent->AddGeneratorInfo(fNuanceInfo); } }; NUANCEInputHandler::~NUANCEInputHandler() { if (fNuanceEvent) delete fNuanceEvent; if (fNUANCETree) delete fNUANCETree; // if (fNuanceInfo) delete fNuanceInfo; } void NUANCEInputHandler::CreateCache() { if (fCacheSize > 0) { fNUANCETree->SetCacheEntryRange(0, fNEvents); fNUANCETree->AddBranchToCache("h3", 1); fNUANCETree->SetCacheSize(fCacheSize); } } void NUANCEInputHandler::RemoveCache() { fNUANCETree->SetCacheEntryRange(0, fNEvents); fNUANCETree->AddBranchToCache("h3", 0); fNUANCETree->SetCacheSize(0); } FitEvent* NUANCEInputHandler::GetNuisanceEvent(const UInt_t entry, const bool lightweight) { // Check out of bounds if (entry >= (UInt_t)fNEvents) return NULL; // Read Entry from TTree to fill NEUT Vect in BaseFitEvt; fNUANCETree->GetEntry(entry); // Setup Input scaling for joint inputs fNUISANCEEvent->InputWeight = GetInputWeight(entry); // Run NUISANCE Vector Filler if (!lightweight) { CalcNUISANCEKinematics(); } return fNUISANCEEvent; } void NUANCEInputHandler::CalcNUISANCEKinematics() { // Reset all variables fNUISANCEEvent->ResetEvent(); // Get shortened pointer FitEvent* evt = fNUISANCEEvent; // Fill Global evt->fMode = ConvertNuanceMode(fNuanceEvent); evt->Mode = evt->fMode; evt->fEventNo = 0.0; evt->fTotCrs = 1.0; evt->fTargetA = 0.0; evt->fTargetZ = 0.0; evt->fTargetH = 0; evt->fBound = 0.0; // Fill particle Stack evt->fNParticles = 0; // Check Particle Stack UInt_t npart = 2 + fNuanceEvent->n_leptons + fNuanceEvent->n_hadrons; UInt_t kmax = evt->kMaxParticles; if (npart > kmax) { ERR(FTL) << "NUANCE has too many particles" << std::endl; ERR(FTL) << "npart=" << npart << " kMax=" << kmax << std::endl; throw; } // Fill Neutrino evt->fParticleState[0] = kInitialState; evt->fParticleMom[0][0] = fNuanceEvent->p_neutrino[0]; evt->fParticleMom[0][1] = fNuanceEvent->p_neutrino[1]; evt->fParticleMom[0][2] = fNuanceEvent->p_neutrino[2]; evt->fParticleMom[0][3] = fNuanceEvent->p_neutrino[3]; evt->fParticlePDG[0] = fNuanceEvent->neutrino; // Fill Target Nucleon evt->fParticleState[1] = kInitialState; evt->fParticleMom[1][0] = fNuanceEvent->p_targ[0]; evt->fParticleMom[1][1] = fNuanceEvent->p_targ[1]; evt->fParticleMom[1][2] = fNuanceEvent->p_targ[2]; evt->fParticleMom[1][3] = fNuanceEvent->p_targ[3]; evt->fParticlePDG[1] = fNuanceEvent->target; evt->fNParticles = 2; // Fill Outgoing Leptons for (int i = 0; i < fNuanceEvent->n_leptons; i++) { evt->fParticleState[evt->fNParticles] = kFinalState; evt->fParticleMom[evt->fNParticles][0] = fNuanceEvent->p_lepton[i][0]; evt->fParticleMom[evt->fNParticles][1] = fNuanceEvent->p_lepton[i][1]; evt->fParticleMom[evt->fNParticles][2] = fNuanceEvent->p_lepton[i][2]; evt->fParticleMom[evt->fNParticles][3] = fNuanceEvent->p_lepton[i][3]; evt->fParticlePDG[evt->fNParticles] = fNuanceEvent->lepton[i]; evt->fNParticles++; } // Fill Outgoing Hadrons for (int i = 0; i < fNuanceEvent->n_hadrons; i++) { evt->fParticleState[evt->fNParticles] = kFinalState; evt->fParticleMom[evt->fNParticles][0] = fNuanceEvent->p_hadron[i][0]; evt->fParticleMom[evt->fNParticles][1] = fNuanceEvent->p_hadron[i][1]; evt->fParticleMom[evt->fNParticles][2] = fNuanceEvent->p_hadron[i][2]; evt->fParticleMom[evt->fNParticles][3] = fNuanceEvent->p_hadron[i][3]; evt->fParticlePDG[evt->fNParticles] = fNuanceEvent->hadron[i]; evt->fNParticles++; } // Save Extra info if (fSaveExtra) { // fNuanceInfo->FillGeneratorInfo(fNuanceEvent); } // Run Initial, FSI, Final, Other ordering. fNUISANCEEvent-> OrderStack(); return; } void NUANCEInputHandler::Print() {} int NUANCEInputHandler::ConvertNuanceMode(NuanceEvent * evt) { int ch = evt->channel; int sg = 1; if (evt->neutrino < 0) sg = -1; switch (ch) { // 1 NUANCE CCQE -> NEUT CCQE 1 case 1: return sg * 1; // 2 NUANCE NCEL -> NEUT NCEL 51,52 -> Set from whether target is p or n case 2: if (evt->target == 2212) return sg * 51; else return sg * 52; // 3 NUANCE CCPIP -> NEUT CCPIP 11 case 3: return sg * 11; // 4 NUANCE CCPI0 -> NEUT CCPI0 = 12 case 4: return sg * 12; // 5 NUANCE CCPIPn -> NEUT CCPIPn 13 case 5: return sg * 13; // 6 NUANCE NCpPI0 -> NEUT NCpPI0 32 case 6: return sg * 32; // 7 NUANCE NCpPI+ -> NEUT NCpPI+ 34 case 7: return sg * 34; // 8 NUANCE NCnPI0 -> NEUT NCnPI0 31 case 8: return sg * 31; // 9 NUANCE NCnPIM -> NEUT NCnPIM 33 case 9: return sg * 33; // 10 NUANCE CCPIP -> NEUT CCPIP -11 case 10: return sg * 11; // 11 NUANCE CCPI0 -> NEUT CCPI0 -12 case 11: return sg * 12; // 12 NUANCE CCPIPn -> NEUT CCPIPn 13 case 12: return sg * 13; // 13 NUANCE NCpPI0 -> NEUT NCnPI0 -32 case 13: return sg * 32; // 14 NUANCE NCpPI+ -> NEUT NCpPI+ -34 case 14: return sg * 34; // 15 NUANCE NCnPI0 -> NEUT NCnPI0 -31 case 15: return sg * 31; // 16 NUANCE NCnPIM -> NEUT NCnPIM -33 case 16: return sg * 33; // 17 NUANCE -> NEUT 21 CC MULTIPI case 17: return sg * 21; // 18 NUANCE -> NEUT 21 CC MULTIPI case 18: return sg * 21; // 19 NUANCE -> NEUT 21 CC MULTIPI case 19: return sg * 21; // 20 NUANCE -> NEUT 21 CC MULTIPI case 20: return sg * 21; // 21 NUANCE -> NEUT 21 CC MULTIPI case 21: return sg * 21; // 22 NUANCE -> NEUT 41 NC MULTIPI case 22: return sg * 41; // 23 NUANCE -> NEUT 41 NC MULTIPI case 23: return sg * 41; // 24 NUANCE -> NEUT 41 NC MULTIPI case 24: return sg * 41; // 25 NUANCE -> NEUT 41 NC MULTIPI case 25: return sg * 41; // 26 NUANCE -> NEUT 41 NC MULTIPI case 26: return sg * 41; // 27 NUANCE -> NEUT -41 "NC (1.3 < W < 2 GeV) case 27: return sg * 41; // 28 NUANCE -> NEUT -21 CC (1.3 < W < 2 GeV) case 28: return sg * 21; // 29 NUANCE -> NEUT -21 CC (1.3 < W < 2 GeV) case 29: return sg * 21; // 30 NUANCE -> NEUT -21 CC (1.3 < W < 2 GeV) case 30: return sg * 21; // 31 NUANCE -> NEUT -21 CC (1.3 < W < 2 GeV) case 31: return sg * 21; // 32 NUANCE -> NEUT -21 CC (1.3 < W < 2 GeV) case 32: return sg * 21; // 33 NUANCE -> NEUT -41 "NC (1.3 < W < 2 GeV) case 33: return sg * 41; // 34 NUANCE -> NEUT -41 "NC (1.3 < W < 2 GeV) case 34: return sg * 41; // 35 NUANCE -> NEUT -41 "NC (1.3 < W < 2 GeV) case 35: return sg * 41; // 36 NUANCE -> NEUT -41 "NC (1.3 < W < 2 GeV) case 36: return sg * 41; // 37 NUANCE -> NEUT -41 "NC (1.3 < W < 2 GeV) case 37: return sg * 41; // 38 NUANCE -> NEUT -41 "NC (1.3 < W < 2 GeV) case 38: return sg * 41; // 39 NUANCE -> NEUT 22 case 39: return sg * 22; // 40 NUANCE -> NEUT 22 case 40: return sg * 22; // 41 NUANCE -> NEUT 22 case 41: return sg * 22; // 42 NUANCE -> NEUT 43 case 42: return sg * 43; // 43 NUANCE -> NEUT 43 case 43: return sg * 43; // 44 NUANCE -> NUET 42 case 44: return sg * 42; // 45 NUANCE -> NEUT -42 case 45: return sg * 42; // 46 NUANCE -> NEUT -22 case 46: return sg * 22; // 47 NUANCE -> NEUT -22 case 47: return sg * 22; // 48 NUANCE -> NEUT -22 case 48: return sg * 22; // 49 NUANCE -> NEUT -43 case 49: return sg * 43; // 50 NUANCE -> NEUT -43 case 50: return sg * 43; // 51 NUANCE -> NEUT -42 case 51: return sg * 42; // 52 NUANCE -> NEUT -42 case 52: return sg * 42; // 53 NUANCE -> NEUT 23 CC 1K case 53: return sg * 23; // 54 NUANCE -> NEUT 23 CC 1K case 54: return sg * 23; // 55 NUANCE -> NEUT 23 CC 1K case 55: return sg * 23; // 56 NUANCE -> NEUT 45 NC 1K case 56: return sg * 45; // 57 NUANCE -> NEUT 44 NC 1K case 57: return sg * 44; // 58 NUANCE -> NEUT 44 NC 1K case 58: return sg * 44; // 59 NUANCE -> NEUT 44 NC 1K case 59: return sg * 44; // 60 NUANCE -> NEUT -23 CC 1K case 60: return sg * 23; // 61 NUANCE -> NEUT -23 CC 1K case 61: return sg * 23; // 62 NUANCE -> NEUT -23 CC 1K case 62: return sg * 23; // 63 NUANCE -> NEUT -23 CC 1K case 63: return sg * 23; // 64 NUANCE -> NEUT -44 NC 1K case 64: return sg * 44; // 65 NUANCE -> NEUT -44 NC 1K case 65: return sg * 44; // 66 NUANCE -> NEUT -45 NC 1K case 66: return sg * 45; // 67 NUANCE -> NEUT 22 CC1eta case 67: return sg * 22; // 68 NUANCE -> NEUT 43 NC p eta case 68: return sg * 43; // 69 NUANCE -> NEUT 43 NC n eta case 69: return sg * 43; // 70 NUANCE -> NEUT -22 CC1eta case 70: return sg * 22; // 71 NUANCE -> NEUT -43 NC p eta case 71: return sg * 43; // 72 NUANCE -> NEUT 42 NC n eta case 72: return sg * 42; // 73 NUANCE -> NEUT 21 CC Multi Pi case 73: return sg * 21; // 74 NUANCE -> NEUT 41 NC Multi Pi case 74: return sg * 41; // 75 NUANCE -> NEUT 41 NC Multi Pi case 75: return sg * 41; // 76 NUANCE -> NEUT -21 CC Multi Pi case 76: return sg * 21; // 77 NUANCE -> NEUT -41 NC Multi Pi case 77: return sg * 41; // 78 NUANCE -> NEUT -41 NC Multi Pi case 78: return sg * 41; // 79 NUANCE -> NEUT 21 CC Multi Pi case 79: return sg * 21; // 80 NUANCE -> NEUT 21 CC Multi Pi case 80: return sg * 21; // 81 NUANCE -> NEUT 41 NC Multi Pi case 81: return sg * 41; // 82 NUANCE -> NEUT 41 NC Multi Pi case 82: return sg * 41; // 83 NUANCE -> NEUT 41 NC Multi Pi case 83: return sg * 41; // 84 NUANCE -> NEUT 41 NC Multi Pi case 84: return sg * 84; // 85 NUANCE -> NEUT -21 CC Multi Pi case 85: return sg * 21; // 86 NUANCE -> NEUT -21 CC Multi Pi case 86: return sg * 21; // 87 NUANCE -> NEUT -41 CC Multi Pi case 87: return sg * 41; // 88 NUANCE -> NEUT -41 case 88: return sg * 41; // 89 NUANCE -> NEUT -41 case 89: return sg * 41; // 90 NUANCE -> NEUT -41 case 90: return sg * 41; // 91 NUANCE -> NEUT 26 CC DIS case 91: return sg * 26; // 92 NUANCE -> NEUT 46 NC DIS case 92: return sg * 46; // 93 NUANCE -> NEUT 17 1#gamma from #Delta case 93: return sg * 17; // 94 NUANCE -> NEUT 39 1#gamma from #Delta case 94: return sg * 39; // 95 -> UNKOWN NEUT MODE case 95: return sg * 0; // 96 NUANCE -> NEUT 36 NC COH case 96: return sg * 36; // 97 NUANCE -> NEUT 16 case 97: return sg * 16; // 98 -> UNKNOWN NEUT MODE case 98: return sg * 0; // 99 -> UNKNOWN NEUT MODE case 99: return sg * 0; default: ERR(FTL) << "Unknown Nuance Channel ID = " << ch << std::endl; throw ("Exiting."); return 0; } return 0; } /* // Notes copied from NuanceChannels.pdf 1 NUANCE CCQE -> NEUT CCQE 1 CC, numu n --> mu- p Cabibbo-allowed quasi-elastic scattering from nucleons 2 NUANCE NCEL -> NEUT NCEL 51,52 -> Set from whether target is p or n NC, numu N --> num N, (N=n,p) (quasi)-elastic scattering from nucleons 3 NUANCE CCPIP -> NEUT CCPIP 11 CC, numu p --> mu- p pi+ resonant single pion production 4 NUANCE CCPI0 -> NEUT CCPI0 = 12 CC, numu n --> mu- p pi0 resonant single pion production 5 NUANCE CCPIPn -> NEUT CCPIPn 13 CC, numu n --> mu- n pi+ resonant single pion production 6 NUANCE NCpPI0 -> NEUT NCpPI0 32 NC, numu p --> numu p pi0 resonant single pion production 7 NUANCE NCpPI+ -> NEUT NCpPI+ 34 NC, numu p --> numu n pi+ resonant single pion production 8 NUANCE NCnPI0 -> NEUT NCnPI0 31 NC, numu n --> numu n pi0 resonant single pion production 9 NUANCE NCnPIM -> NEUT NCnPIM 33 NC, numu n --> numu p pi- resonant single pion production 10 NUANCE CCPIP -> NEUT CCPIP -11 CC, numubar p --> mu- p pi+ resonant single pion production 11 NUANCE CCPI0 -> NEUT CCPI0 -12 CC, numubar n --> mu- p pi0 resonant single pion production 12 NUANCE CCPIPn -> NEUT CCPIPn -13 CC, numubar n --> mu- n pi+ resonant single pion production 13 NUANCE NCpPI0 -> NEUT NCnPI0 -32 NC, numubar p --> numubar p pi0 resonant single pion production 14 NUANCE NCpPI+ -> NEUT NCpPI+ -34 NC, numubar p --> numubar n pi+ resonant single pion production 15 NUANCE NCnPI0 -> NEUT NCnPI0 -31 NC, numubar n --> numubar n pi0 resonant single pion production 16 NUANCE NCnPIM -> NEUT NCnPIM -33 NC, numubar n --> numubar p pi- resonant single pion production 17 NUANCE -> NEUT 21 CC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow l^{-} N' multi-#pi CC, numu p --> mu- Delta+ pi+ resonant processes involving more than a single pion 18 NUANCE -> NEUT 21 CC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow l^{-} N' multi-#pi CC, numu p --> mu- Delta++ pi0 resonant processes involving more than a single pion 19 NUANCE -> NEUT 21 CC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow l^{-} N' multi-#pi CC, numu n --> mu- Delta+ pi0 resonant processes involving more than a single pion 20 NUANCE -> NEUT 21 CC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow l^{-} N' multi-#pi CC, numu n --> mu- Delta0 pi+ resonant processes involving more than a single pion 21 NUANCE -> NEUT 21 CC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow l^{-} N' multi-#pi CC, numu n --> mu- Delta++ pi- resonant processes involving more than a single pion 22 NUANCE -> NEUT 41 "NC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow #nu_{l} N multi-#pi" NC, numu p+ --> numu Delta+ pi0 resonant processes involving more than a single pion 23 NUANCE -> NEUT 41 "NC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow #nu_{l} N multi-#pi" NC,numu p --> numu Delta0 pi+ resonant processes involving more than a single pion 24 NUANCE -> NEUT 41 "NC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow #nu_{l} N multi-#pi" NC, numu p --> numu Delta++ pi- resonant processes involving more than a single pion 25 NUANCE -> NEUT 41 "NC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow #nu_{l} N multi-#pi" NC, numu n --> numu Delta+ pi- resonant processes involving more than a single pion 26 NUANCE -> NEUT 41 "NC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow #nu_{l} N multi-#pi" NC, numu n --> numu Delta0 pi0 resonant processes involving more than a single pion 27 NUANCE -> NEUT -41 "NC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow #nu_{l} N multi-#pi" NC, numubar n --> numubar Delta- pi+ resonant processes involving more than a single pion 28 NUANCE -> NEUT -21 CC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow l^{-} N' multi-#pi CC, numubar p --> mu- Delta+ pi+ resonant processes involving more than a single pion 29 UANCE -> NEUT -21 CC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow l^{-} N' multi-#pi CC, numubar p --> mu- Delta++ pi0 resonant processes involving more than a single pion 30 NUANCE -> NEUT -21 CC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow l^{-} N' multi-#pi CC, numubar n --> mu- Delta+ pi0 resonant processes involving more than a single pion 31 NUANCE -> NEUT -21 CC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow l^{-} N' multi-#pi CC, numubar n --> mu- Delta0 pi+ resonant processes involving more than a single pion 32 NUANCE -> NEUT -21 CC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow l^{-} N' multi-#pi CC, numubar n --> mu- Delta++ pi- resonant processes involving more than a single pion 33 NUANCE -> NEUT -41 "NC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow #nu_{l} N multi-#pi" NC, numubar p+ --> numubar Delta+ pi0 resonant processes involving more than a single pion 34 NUANCE -> NEUT -41 "NC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow #nu_{l} N multi-#pi" NC,numubar p --> numubar Delta0 pi+ resonant processes involving more than a single pion 35 NUANCE -> NEUT -41 "NC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow #nu_{l} N multi-#pi" NC, numubar p --> numubar Delta++ pi- resonant processes involving more than a single pion 36 NUANCE -> NEUT -41 "NC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow #nu_{l} N multi-#pi" NC, numubar n --> numubar Delta+ pi- resonant processes involving more than a single pion 37 NUANCE -> NEUT -41 "NC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow #nu_{l} N multi-#pi" NC, numubar n --> numubar Delta0 pi0 resonant processes involving more than a single pion 38 NUANCE -> NEUT -41 "NC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow #nu_{l} N multi-#pi" NC, numubar n --> numubar Delta- pi+ resonant processes involving more than a single pion // RHO Production lumped in with eta production 22 CCeta 43 NCeta on p 42 NCeta on n 39 NUANCE -> NEUT 22 CC, numu p --> mu- p rho+(770) resonant processes involving more than a single pion 40 NUANCE -> NEUT 22 CC, numu n --> mu- p rho0(770) resonant processes involving more than a single pion 41 NUANCE -> NEUT 22 CC, numu n --> mu- n rho+(770) resonant processes involving more than a single pion 42 NUANCE -> NEUT 43 NC, numu p --> numu p rho0(770) resonant processes involving more than a single pion 43 NUANCE -> NEUT 43 NC, numu p --> numu n rho+(770) resonant processes involving more than a single pion 44 NUANCE -> NUET 42 NC, numu n --> numu n rho0(770) resonant processes involving more than a single pion 45 NUANCE -> NEUT -42 NC, numubar n --> numubar p rho-(770) resonant processes involving more than a single pion 46 NUANCE -> NEUT -22 CC, numubar p --> mu- p rho+(770) resonant processes involving more than a single pion 47 NUANCE -> NEUT -22 CC, numubar n --> mu- p rho0(770) resonant processes involving more than a single pion 48 NUANCE -> NEUT -22 CC, numubar n --> mu- n rho+(770) resonant processes involving more than a single pion 49 NUANCE -> NEUT -43 NC, numubar p --> numubar p rho0(770) resonant processes involving more than a single pion 50 NUANCE -> NEUT -43 NC, numubar p --> numubar n rho+(770) resonant processes involving more than a single pion 51 NUANCE -> NEUT -42 NC, numubar n --> numubar n rho0(770) resonant processes involving more than a single pion 52 NUANCE -> NEUT -42 NC, numubar n --> numubar p rho-(770) resonant processes involving more than a single pion 53 NUANCE -> NEUT 23 CC 1K: #nu_{l} n #rightarrow l^{-} #Lambda K^{+} CC, numu p --> mu- Sigma+ K+ resonant processes involving more than a single pion 54 NUANCE -> NEUT 23 CC 1K: #nu_{l} n #rightarrow l^{-} #Lambda K^{+} CC, numu n --> mu- Sigma0 K+ resonant processes involving more than a single pion 55 NUANCE -> NEUT 23 CC 1K: #nu_{l} n #rightarrow l^{-} #Lambda K^{+} CC, numu n --> mu- Sigma+ K0 resonant processes involving more than a single pion 56 NUANCE -> NEUT 45 NC 1K: #nu_{l} n #rightarrow #nu_{l} #Lambda K^{+} NC, numu p --> numu Sigma0 K+ resonant processes involving more than a single pion 57 NUANCE -> NEUT 44 NC 1K: #nu_{l} n #rightarrow #nu_{l} #Lambda K^{0} NC, numu p --> numu Sigma+ K0 resonant processes involving more than a single pion 58 NUANCE -> NEUT 44 NC 1K: #nu_{l} n #rightarrow #nu_{l} #Lambda K^{0} NC, numu n --> numu Sigma0 K0 resonant processes involving more than a single pion 59 NUANCE -> NEUT 45 NC 1K: #nu_{l} n #rightarrow #nu_{l} #Lambda K^{+} NC, numu n --> numu Sigma- K+ resonant processes involving more than a single pion 60 NUANCE -> NEUT -23 CC 1K: #nu_{l} n #rightarrow l^{-} #Lambda K^{+} CC, numubar p --> mu- Sigma+ K+ resonant processes involving more than a single pion 61 NUANCE -> NEUT -23 CC 1K: #nu_{l} n #rightarrow l^{-} #Lambda K^{+} CC, numubar n --> mu- Sigma0 K+ resonant processes involving more than a single pion 62 NUANCE -> NEUT -23 CC 1K: #nu_{l} n #rightarrow l^{-} #Lambda K^{+} CC, numubar n --> mu- Sigma+ K0 resonant processes involving more than a single pion 63 NUANCE -> NEUT -45 NC 1K: #nu_{l} n #rightarrow #nu_{l} #Lambda K^{+} NC, numubar p --> numubar Sigma0 K+ resonant processes involving more than a single pion 64 NUANCE -> NEUT -44 NC 1K: #nu_{l} n #rightarrow #nu_{l} #Lambda K^{0} NC, numubar p --> numubar Sigma+ K0 resonant processes involving more than a single pion 65 NUANCE -> NEUT -44 NC 1K: #nu_{l} n #rightarrow #nu_{l} #Lambda K^{0} NC, numubar n --> numubar Sigma0 K0 resonant processes involving more than a single pion 66 NUANCE -> NEUT -45 NC 1K: #nu_{l} n #rightarrow #nu_{l} #Lambda K^{+} NC, numubar n --> numubar Sigma- K+ resonant processes involving more than a single pion 67 NUANCE -> NEUT 22 ModeStack[22]->SetTitle("CC1#eta^{0} on n"); CC, numu n --> mu- p eta resonant processes involving more than a single pion 68 NUANCE -> NEUT 43 NC, numu p --> numu p eta resonant processes involving more than a single pion 69 NUANCE -> NEUT 42 NC, numu n --> numu n eta resonant processes involving more than a single pion 70 NUANCE -> NEUT -22 ModeStack[22]->SetTitle("CC1#eta^{0} on n"); CC, numubar n --> mu- p eta resonant processes involving more than a single pion 71 NUANCE -> NEUT -43 ModeStack[43]->SetTitle("NC1#eta^{0} on p"); NC, numubar p --> numubar p eta resonant processes involving more than a single pion 72 NUANCE -> NEUT -42 ModeStack[42]->SetTitle("NC1#eta^{0} on n"); NC, numubar n --> numubar n eta resonant processes involving more than a single pion 73 NUANCE -> NEUT 21 ModeStack[21]->SetTitle("Multi #pi (1.3 < W < 2.0)"); CC, numu n --> mu- K+ Lambda resonant processes involving more than a single pion 74 NUANCE -> NEUT 41 ModeStack[41]->SetTitle("Multi #pi (1.3 < W < 2.0)"); NC, numu p --> numu K+ Lambda resonant processes involving more than a single pion 75 NUANCE -> NEUT 41 ModeStack[41]->SetTitle("Multi #pi (1.3 < W < 2.0)"); NC, numu n --> numu K0 Lambda resonant processes involving more than a single pion 76 NUANCE -> NEUT -21 ModeStack[21]->SetTitle("Multi #pi (1.3 < W < 2.0)"); CC, numubar n --> mu- K+ Lambda resonant processes involving more than a single pion 77 NUANCE -> NEUT -41 ModeStack[41]->SetTitle("Multi #pi (1.3 < W < 2.0)"); NC, numubar p --> numubar K+ Lambda resonant processes involving more than a single pion 78 NUANCE -> NEUT -41 ModeStack[41]->SetTitle("Multi #pi (1.3 < W < 2.0)"); NC, numubar n --> numubar K0 Lambda resonant processes involving more than a single pion CC Multipi ModeStack[21]->SetTitle("Multi #pi (1.3 < W < 2.0)"); NC Multipi ModeStack[41]->SetTitle("Multi #pi (1.3 < W < 2.0)"); 79 NUANCE -> NEUT 21 CC, numu n --> mu- p pi+ pi- two pion production 80 NUANCE -> NEUT 21 CC, numu n --> mu- p pi0 pi0 two pion production 81 NUANCE -> NEUT 41 NC, numu p --> numu p pi+ pi- two pion production 82 NUANCE -> NEUT 41 NC, numu p --> numu p pi0 pi0 two pion production 83 NUANCE -> NEUT 41 NC, numu n --> numu n pi+ pi- two pion production 84 NUANCE -> NEUT 41 NC, numu n --> numu n pi0 pi0 two pion production 85 NUANCE -> NEUT -21 CC, numubar n --> mu- p pi+ pi- two pion production 86 NUANCE -> NEUT -21 CC, numubar n --> mu- p pi0 pi0 two pion production 87 NUANCE -> NEUT -41 ModeStack[41]->SetTitle("Multi #pi (1.3 < W < 2.0)"); NC, numubar p --> numubar p pi+ pi- two pion production 88 NUANCE -> NEUT -41 ModeStack[41]->SetTitle("Multi #pi (1.3 < W < 2.0)"); NC, numubar p --> numubar p pi0 pi0 two pion production 89 NUANCE -> NEUT -41 ModeStack[41]->SetTitle("Multi #pi (1.3 < W < 2.0)"); NC, numubar n --> numubar n pi+ pi- two pion production 90 NUANCE -> NEUT -41 ModeStack[41]->SetTitle("Multi #pi (1.3 < W < 2.0)"); NC, numubar n --> numubar n pi0 pi0 two pion production 91 NUANCE -> NEUT 26 ModeStack[26]->SetTitle("DIS (W > 2.0)"); CC, numu N --> mu- X (where N=n,p) deep inelastic scattering (nu or nubar) 92 NUANCE -> NEUT 46 ModeStack[46]->SetTitle("DIS (W > 2.0)"); NC, numu N --> numu X (where N=n,p) deep inelastic scattering (nu or nubar) 93 NUANCE -> NEUT 17 1#gamma from #Delta: #nu_{l} n #rightarrow l^{-} p #gamma CC, numu n --> mu- p gamma Delta radiative decay, Delta --> N gamma (only in NUANCE versions v3 and and higher) 94 NUANCE -> NEUT 39 1#gamma from #Delta: #nu_{l} p #rightarrow #nu_{l} p #gamma neutModeID[15] = 38; neutModeName[15] = "ncngam"; neutModeTitle[15] = "1#gamma from #Delta: #nu_{l} n #rightarrow #nu_{l} n #gamma"; neutModeID[16] = 39; neutModeName[16] = "ncpgam"; neutModeTitle[16] = "1#gamma from #Delta: #nu_{l} p #rightarrow #nu_{l} p #gamma"; NC, numu N --> numu N gamma Delta radiative decay, Delta --> N gamma (only in NUANCE versions v3 and and higher) 95 -> UNKOWN NEUT MODE CC, numubar p --> mu+ Lambda, numubar n -- > mu+ Sigma-, numubar p --> mu+ Sigma0 Cabibbo-suppressed QE hyperon production from nucleons 96 NUANCE -> NEUT 36 neutModeID[14] = 36; neutModeName[14] = "nccoh"; neutModeTitle[14] = "NC coherent-#pi: #nu_{l} ^{16}O #rightarrow #nu_{l} ^{16}O #pi^{0}"; NC, numu A --> numu pi0 A coherent or diffractive pi0 production 97 NUANCE -> NEUT 16 neutModeID[4] = 16; neutModeName[4] = "cccoh"; neutModeTitle[4] = "CC coherent-#pi: #nu_{l} ^{16}O #rightarrow l^{-} ^{16}O #pi^{+}"; CC, numu A --> mu- pi+ A (or numubar A --> coherent or diffractive pi0 production 98 -> UNKNOWN NEUT MODE NC, numu e- --> numu e- (or numubar e- --> neutrino + electron elastic scattering 99 -> UNKNOWN NEUT MODE CC, numu e- --> mu- nue neutrino + electron inverse muon decay NEUT Modes: // CC Modes neutModeID[0] = 1; neutModeName[0] = "ccqe"; neutModeTitle[0] = "CCQE: #nu_{l} n #rightarrow l^{-} p"; neutModeID[1] = 11; neutModeName[1] = "ccppip"; neutModeTitle[1] = "CC 1#pi: #nu_{l} p #rightarrow l^{-} p #pi^{+}"; neutModeID[2] = 12; neutModeName[2] = "ccppi0"; neutModeTitle[2] = "CC 1#pi: #nu_{l} n #rightarrow l^{-} p #pi^{0}"; neutModeID[3] = 13; neutModeName[3] = "ccnpip"; neutModeTitle[3] = "CC 1#pi: #nu_{l} n #rightarrow l^{-} n #pi^{+}"; neutModeID[4] = 16; neutModeName[4] = "cccoh"; neutModeTitle[4] = "CC coherent-#pi: #nu_{l} ^{16}O #rightarrow l^{-} ^{16}O #pi^{+}"; neutModeID[5] = 17; neutModeName[5] = "ccgam"; neutModeTitle[5] = "1#gamma from #Delta: #nu_{l} n #rightarrow l^{-} p #gamma"; neutModeID[6] = 21; neutModeName[6] = "ccmpi"; neutModeTitle[6] = "CC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow l^{-} N' multi-#pi"; neutModeID[7] = 22; neutModeName[7] = "cceta"; neutModeTitle[7] = "CC 1#eta: #nu_{l} n #rightarrow l^{-} p #eta"; neutModeID[8] = 23; neutModeName[8] = "cck"; neutModeTitle[8] = "CC 1K: #nu_{l} n #rightarrow l^{-} #Lambda K^{+}"; neutModeID[9] = 26; neutModeName[9] = "ccdis"; neutModeTitle[9] = "CC DIS (2 GeV < W): #nu_{l} N #rightarrow l^{-} N' mesons"; neutModeID[10] = 31; neutModeName[10] = "ncnpi0"; neutModeTitle[10] = "NC 1#pi: #nu_{l} n #rightarrow #nu_{l} n #pi^{0}"; neutModeID[11] = 32; neutModeName[11] = "ncppi0"; neutModeTitle[11] = "NC 1#pi: #nu_{l} p #rightarrow #nu_{l} p #pi^{0}"; neutModeID[12] = 33; neutModeName[12] = "ncppim"; neutModeTitle[12] = "NC 1#pi: #nu_{l} n #rightarrow #nu_{l} p #pi^{-}"; neutModeID[13] = 34; neutModeName[13] = "ncnpip"; neutModeTitle[13] = "NC 1#pi: #nu_{l} p #rightarrow #nu_{l} n #pi^{+}"; neutModeID[14] = 36; neutModeName[14] = "nccoh"; neutModeTitle[14] = "NC coherent-#pi: #nu_{l} ^{16}O #rightarrow #nu_{l} ^{16}O #pi^{0}"; neutModeID[15] = 38; neutModeName[15] = "ncngam"; neutModeTitle[15] = "1#gamma from #Delta: #nu_{l} n #rightarrow #nu_{l} n #gamma"; neutModeID[16] = 39; neutModeName[16] = "ncpgam"; neutModeTitle[16] = "1#gamma from #Delta: #nu_{l} p #rightarrow #nu_{l} p #gamma"; neutModeID[17] = 41; neutModeName[17] = "ncmpi"; neutModeTitle[17] = "NC (1.3 < W < 2 GeV): #nu_{l} N #rightarrow #nu_{l} N multi-#pi"; neutModeID[18] = 42; neutModeName[18] = "ncneta"; neutModeTitle[18] = "NC 1#eta: #nu_{l} n #rightarrow #nu_{l} n #eta"; neutModeID[19] = 43; neutModeName[19] = "ncpeta"; neutModeTitle[19] = "NC 1#eta: #nu_{l} p #rightarrow #nu_{l} p #eta"; neutModeID[20] = 44; neutModeName[20] = "nck0"; neutModeTitle[20] = "NC 1K: #nu_{l} n #rightarrow #nu_{l} #Lambda K^{0}"; neutModeID[21] = 45; neutModeName[21] = "nckp"; neutModeTitle[21] = "NC 1K: #nu_{l} n #rightarrow #nu_{l} #Lambda K^{+}"; neutModeID[22] = 46; neutModeName[22] = "ncdis"; neutModeTitle[22] = "NC DIS (2 GeV < W): #nu_{l} N #rightarrow #nu_{l} N' mesons"; neutModeID[23] = 51; neutModeName[23] = "ncqep"; neutModeTitle[23] = "NC elastic: #nu_{l} p #rightarrow #nu_{l} p"; neutModeID[24] = 52; neutModeName[24] = "ncqen"; neutModeTitle[24] = "NC elastic: #nu_{l} n #rightarrow #nu_{l} n"; */ #endif diff --git a/src/InputHandler/NuWroInputHandler.cxx b/src/InputHandler/NuWroInputHandler.cxx index cc32720..62c6b00 100644 --- a/src/InputHandler/NuWroInputHandler.cxx +++ b/src/InputHandler/NuWroInputHandler.cxx @@ -1,476 +1,477 @@ #ifdef __NUWRO_ENABLED__ #include "NuWroInputHandler.h" +#include "InputUtils.h" NuWroGeneratorInfo::~NuWroGeneratorInfo() { delete fNuWroParticlePDGs; } void NuWroGeneratorInfo::AddBranchesToTree(TTree* tn) { tn->Branch("NuWroParticlePDGs", &fNuWroParticlePDGs, "NuWroParticlePDGs/I"); } void NuWroGeneratorInfo::SetBranchesFromTree(TTree* tn) { tn->SetBranchAddress("NuWroParticlePDGs", &fNuWroParticlePDGs); } void NuWroGeneratorInfo::AllocateParticleStack(int stacksize) { fNuWroParticlePDGs = new int[stacksize]; } void NuWroGeneratorInfo::DeallocateParticleStack() { delete fNuWroParticlePDGs; } void NuWroGeneratorInfo::FillGeneratorInfo(event* e) { Reset(); } void NuWroGeneratorInfo::Reset() { for (int i = 0; i < kMaxParticles; i++) { fNuWroParticlePDGs[i] = 0; } } int event1_nof(event* e, int pdg) { int c = 0; for (size_t i = 0; i < e->out.size(); i++) if (e->out[i].pdg == pdg) c++; return c; } NuWroInputHandler::NuWroInputHandler(std::string const& handle, std::string const& rawinputs) { LOG(SAM) << "Creating NuWroInputHandler : " << handle << std::endl; // Run a joint input handling fName = handle; fMaxEvents = FitPar::Config().GetParI("MAXEVENTS"); fSaveExtra = false; // FitPar::Config().GetParB("NuWroSaveExtra"); // Setup the TChain fNuWroTree = new TChain("treeout"); // 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(inputs[inp_it].c_str(), "READ"); if (!inp_file or inp_file->IsZombie()) { ERR(FTL) << "nuwro File IsZombie() at " << inputs[inp_it] << std::endl; throw; } // Get Flux/Event hist TH1D* fluxhist = (TH1D*)inp_file->Get( (PlotUtils::GetObjectWithName(inp_file, "FluxHist")).c_str()); TH1D* eventhist = (TH1D*)inp_file->Get( (PlotUtils::GetObjectWithName(inp_file, "EvtHist")).c_str()); if (!fluxhist or !eventhist) { ERR(FTL) << "nuwro FILE doesn't contain flux/xsec info" << std::endl; if (FitPar::Config().GetParB("regennuwro")) { ERR(FTL) << "Regen NuWro has not been added yet. Email the developers!" << std::endl; // ProcessNuWroInputFlux(inputs[inp_it]); throw; } else { ERR(FTL) << "If you would like NUISANCE to generate these for you " << "please set parameter regennuwro=1 and re-run." << std::endl; throw; } } // Get N Events TTree* nuwrotree = (TTree*)inp_file->Get("treeout"); if (!nuwrotree) { ERR(FTL) << "treeout not located in nuwro file! " << inputs[inp_it] << std::endl; throw; } int nevents = nuwrotree->GetEntries(); // Register input to form flux/event rate hists RegisterJointInput(inputs[inp_it], nevents, fluxhist, eventhist); // Add to TChain fNuWroTree->Add(inputs[inp_it].c_str()); } // Registor all our file inputs SetupJointInputs(); // Setup Events fNuWroEvent = NULL; fNuWroTree->SetBranchAddress("e", &fNuWroEvent); fNuWroTree->GetEntry(0); fNUISANCEEvent = new FitEvent(); fNUISANCEEvent->fType = kNUWRO; fNUISANCEEvent->fNuwroEvent = fNuWroEvent; fNUISANCEEvent->HardReset(); if (fSaveExtra) { fNuWroInfo = new NuWroGeneratorInfo(); fNUISANCEEvent->AddGeneratorInfo(fNuWroInfo); } }; NuWroInputHandler::~NuWroInputHandler() { if (fNuWroTree) delete fNuWroTree; } void NuWroInputHandler::CreateCache() { // fNuWroTree->SetCacheEntryRange(0, fNEvents); // fNuWroTree->AddBranchToCache("*", 1); // fNuWroTree->SetCacheSize(fCacheSize); } void NuWroInputHandler::RemoveCache() { // fNuWroTree->SetCacheEntryRange(0, fNEvents); // fNuWroTree->AddBranchToCache("*", 0); // fNuWroTree->SetCacheSize(0); } void NuWroInputHandler::ProcessNuWroInputFlux(const std::string file) {} FitEvent* NuWroInputHandler::GetNuisanceEvent(const UInt_t entry, const bool lightweight) { // Catch too large entries if (entry >= (UInt_t)fNEvents) return NULL; // Read Entry from TTree to fill NEUT Vect in BaseFitEvt; fNuWroTree->GetEntry(entry); // Run NUISANCE Vector Filler if (!lightweight) { CalcNUISANCEKinematics(); } #ifdef __PROB3PP_ENABLED__ for (size_t i = 0; i < fNUISANCEEvent->fNuwroEvent->in.size(); i++) { if (std::count(PhysConst::pdg_neutrinos, PhysConst::pdg_neutrinos + 4, fNUISANCEEvent->fNuwroEvent->in[i].pdg)) { fNUISANCEEvent->probe_E = fNUISANCEEvent->fNuwroEvent->in[i].t; fNUISANCEEvent->probe_pdg = fNUISANCEEvent->fNuwroEvent->in[i].pdg; break; } } #endif // Setup Input scaling for joint inputs fNUISANCEEvent->InputWeight = GetInputWeight(entry); #ifdef __USE_NUWRO_SRW_EVENTS__ if (!rwEvs.size()) { fNuwroParams = fNuWroEvent->par; } if (entry >= rwEvs.size()) { rwEvs.push_back(BaseFitEvt()); rwEvs.back().fNuwroSRWEvent = SRW::SRWEvent(*fNuWroEvent); rwEvs.back().fNuwroEvent = NULL; rwEvs.back().fNuwroParams = &fNuwroParams; rwEvs.back().probe_E = rwEvs.back().fNuwroSRWEvent.NeutrinoEnergy; rwEvs.back().probe_pdg = rwEvs.back().fNuwroSRWEvent.NeutrinoPDG; } #endif return fNUISANCEEvent; } int NuWroInputHandler::ConvertNuwroMode(event* e) { Int_t proton_pdg, neutron_pdg, pion_pdg, pion_plus_pdg, pion_minus_pdg, lambda_pdg, eta_pdg, kaon_pdg, kaon_plus_pdg; proton_pdg = 2212; eta_pdg = 221; neutron_pdg = 2112; pion_pdg = 111; pion_plus_pdg = 211; pion_minus_pdg = -211; // O_16_pdg = 100069; // oznacznie z Neuta lambda_pdg = 3122; kaon_pdg = 311; kaon_plus_pdg = 321; if (e->flag.qel) // kwiazielastyczne oddziaływanie { if (e->flag.anty) // jeśli jest to oddziaływanie z antyneutrinem { if (e->flag.cc) return -1; else { if (event1_nof(e, proton_pdg)) return -51; else if (event1_nof(e, neutron_pdg)) return -52; // sprawdzam dodatkowo ? } } else // oddziaływanie z neutrinem { if (e->flag.cc) return 1; else { if (event1_nof(e, proton_pdg)) return 51; else if (event1_nof(e, neutron_pdg)) return 52; } } } if (e->flag.mec) { if (e->flag.anty) return -2; else return 2; } if (e->flag.res) // rezonansowa produkcja: pojedynczy pion, pojed.eta, kaon, // multipiony { Int_t liczba_pionow, liczba_kaonow; liczba_pionow = event1_nof(e, pion_pdg) + event1_nof(e, pion_plus_pdg) + event1_nof(e, pion_minus_pdg); liczba_kaonow = event1_nof(e, kaon_pdg) + event1_nof(e, kaon_pdg); if (liczba_pionow > 1 || liczba_pionow == 0) // multipiony { if (e->flag.anty) { if (e->flag.cc) return -21; else return -41; } else { if (e->flag.cc) return 21; else return 41; } } if (liczba_pionow == 1) { if (e->flag.anty) // jeśli jest to oddziaływanie z antyneutrinem { if (e->flag.cc) { if (event1_nof(e, neutron_pdg) && event1_nof(e, pion_minus_pdg)) return -11; if (event1_nof(e, neutron_pdg) && event1_nof(e, pion_pdg)) return -12; if (event1_nof(e, proton_pdg) && event1_nof(e, pion_minus_pdg)) return -13; } else { if (event1_nof(e, proton_pdg)) { if (event1_nof(e, pion_minus_pdg)) return -33; else if (event1_nof(e, pion_pdg)) return -32; } else if (event1_nof(e, neutron_pdg)) { if (event1_nof(e, pion_plus_pdg)) return -34; else if (event1_nof(e, pion_pdg)) return -31; } } } else // oddziaływanie z neutrinem { if (e->flag.cc) { if (event1_nof(e, proton_pdg) && event1_nof(e, pion_plus_pdg)) return 11; if (event1_nof(e, proton_pdg) && event1_nof(e, pion_pdg)) return 12; if (event1_nof(e, neutron_pdg) && event1_nof(e, pion_plus_pdg)) return 13; } else { if (event1_nof(e, proton_pdg)) { if (event1_nof(e, pion_minus_pdg)) return 33; else if (event1_nof(e, pion_pdg)) return 32; } else if (event1_nof(e, neutron_pdg)) { if (event1_nof(e, pion_plus_pdg)) return 34; else if (event1_nof(e, pion_pdg)) return 31; } } } } if (event1_nof(e, eta_pdg)) // produkcja rezonansowa ety { if (e->flag.anty) // jeśli jest to oddziaływanie z antyneutrinem { if (e->flag.cc) return -22; else { if (event1_nof(e, neutron_pdg)) return -42; else if (event1_nof(e, proton_pdg)) return -43; // sprawdzam dodatkowo ? } } else // oddziaływanie z neutrinem { if (e->flag.cc) return 22; else { if (event1_nof(e, neutron_pdg)) return 42; else if (event1_nof(e, proton_pdg)) return 43; } } } if (event1_nof(e, lambda_pdg) == 1 && liczba_kaonow == 1) // produkcja rezonansowa kaonu { if (e->flag.anty) // jeśli jest to oddziaływanie z antyneutrinem { if (e->flag.cc && event1_nof(e, kaon_pdg)) return -23; else { if (event1_nof(e, kaon_pdg)) return -44; else if (event1_nof(e, kaon_plus_pdg)) return -45; } } else // oddziaływanie z neutrinem { if (e->flag.cc && event1_nof(e, kaon_plus_pdg)) return 23; else { if (event1_nof(e, kaon_pdg)) return 44; else if (event1_nof(e, kaon_plus_pdg)) return 45; } } } } if (e->flag.coh) // koherentne oddziaływanie tylko na O(16) { Int_t _target; _target = e->par.nucleus_p + e->par.nucleus_n; // liczba masowa O(16) if (_target == 16) { if (e->flag.anty) // jeśli jest to oddziaływanie z antyneutrinem { if (e->flag.cc && event1_nof(e, pion_minus_pdg)) return -16; else if (event1_nof(e, pion_pdg)) return -36; } else // oddziaływanie z neutrinem { if (e->flag.cc && event1_nof(e, pion_plus_pdg)) return 16; else if (event1_nof(e, pion_pdg)) return 36; } } } // gleboko nieelastyczne rozpraszanie if (e->flag.dis) { if (e->flag.anty) { if (e->flag.cc) return -26; else return -46; } else { if (e->flag.cc) return 26; else return 46; } } return 9999; } void NuWroInputHandler::CalcNUISANCEKinematics() { // std::cout << "NuWro Event Address " << fNuWroEvent << std::endl; // Reset all variables fNUISANCEEvent->ResetEvent(); FitEvent* evt = fNUISANCEEvent; // Sort Event Info evt->fMode = ConvertNuwroMode(fNuWroEvent); if (abs(evt->fMode) > 60) { evt->fMode = 0; // Remove failed mode converts // return; } evt->Mode = evt->fMode; evt->fEventNo = 0.0; evt->fTotCrs = 0.0; evt->fTargetA = fNuWroEvent->par.nucleus_p + fNuWroEvent->par.nucleus_n; evt->fTargetZ = fNuWroEvent->par.nucleus_p; evt->fTargetH = 0; evt->fBound = (evt->fTargetA) == 1; // Check Particle Stack UInt_t npart_in = fNuWroEvent->in.size(); UInt_t npart_out = fNuWroEvent->out.size(); UInt_t npart_post = fNuWroEvent->post.size(); UInt_t npart = npart_in + npart_out + npart_post; UInt_t kmax = evt->kMaxParticles; if (npart > kmax) { ERR(WRN) << "NUWRO has too many particles. Expanding stack." << std::endl; fNUISANCEEvent->ExpandParticleStack(npart); } // Sort Particles evt->fNParticles = 0; std::vector::iterator p_iter; // Initial State for (p_iter = fNuWroEvent->in.begin(); p_iter != fNuWroEvent->in.end(); p_iter++) { AddNuWroParticle(fNUISANCEEvent, (*p_iter), kInitialState); } // FSI State // for (size_t i = 0; i < npart_in; i++ ) { // AddNuWroParticle(fNUISANCEEvent, (*p_iter), kFSIState); // } // Final State for (p_iter = fNuWroEvent->post.begin(); p_iter != fNuWroEvent->post.end(); p_iter++) { AddNuWroParticle(fNUISANCEEvent, (*p_iter), kFinalState); } // Fill Generator Info if (fSaveExtra) fNuWroInfo->FillGeneratorInfo(fNuWroEvent); // 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 NuWroInputHandler::AddNuWroParticle(FitEvent* evt, particle& p, int state) { // Add Mom evt->fParticleMom[evt->fNParticles][0] = static_cast(p).x; evt->fParticleMom[evt->fNParticles][1] = static_cast(p).y; evt->fParticleMom[evt->fNParticles][2] = static_cast(p).z; evt->fParticleMom[evt->fNParticles][3] = static_cast(p).t; // Status/PDG evt->fParticleState[evt->fNParticles] = state; evt->fParticlePDG[evt->fNParticles] = p.pdg; // Add to particle count evt->fNParticles++; } void NuWroInputHandler::Print() {} #endif diff --git a/src/InputHandler/SigmaQ0HistogramInputHandler.cxx b/src/InputHandler/SigmaQ0HistogramInputHandler.cxx index 1f306bf..3db265f 100644 --- a/src/InputHandler/SigmaQ0HistogramInputHandler.cxx +++ b/src/InputHandler/SigmaQ0HistogramInputHandler.cxx @@ -1,265 +1,265 @@ #include "SigmaQ0HistogramInputHandler.h" SigmaQ0HistogramInputHandler::SigmaQ0HistogramInputHandler(std::string const& handle, std::string const& rawinputs) { LOG(SAM) << "Creating SigmaQ0HistogramInputHandler : " << handle << std::endl; // Run a joint input handling fName = handle; // Assign to hist event format - fEventType = kHISTEVENT; + fEventType = kSIGMAQ0HIST; // Parse our input file // SIGMAQ0HIST:path.txt,ENERGY=0.25,THETA=0.34,Q0COL=1,XSCOL=2,SCL=10 std::vector parsedinputs = GeneralUtils::ParseToStr(rawinputs, ","); fFilePath = parsedinputs[0]; // Setup Defaults incase none given fEnergy = -1.0; fTheta = -1.0; fQ0Column = 0; fSigmaColumn = 1; fBeamPDG = -1; // Assume electron by default fDelim = " "; fScaling = 1.E38; // Now Loop through and parse possible inputs for (uint i = 1; i < parsedinputs.size(); i++) { std::vector parsedspec = GeneralUtils::ParseToStr(parsedinputs[i], "="); if (parsedspec.size() < 2) { THROW("NO VALUE GIVEN TO SPECIFIER : " << parsedinputs[0]); } std::string spec = parsedspec[0]; std::string value = parsedspec[1]; // Read Energy if (!spec.compare("ENERGY") or !spec.compare("E")) { fEnergy = GeneralUtils::StrToDbl(value); // Read Theta } else if (!spec.compare("THETA") or !spec.compare("T")) { fTheta = GeneralUtils::StrToDbl(value); // Set Q0 Column } else if (!spec.compare("Q0") or !spec.compare("Q0COL")) { fQ0Column = GeneralUtils::StrToInt(value); // Set XSec Column } else if (!spec.compare("XSCOL") or !spec.compare("XS") or !spec.compare("X") or !spec.compare("SIG") or !spec.compare("SIGMA")) { fSigmaColumn = GeneralUtils::StrToInt(value); } else if (!spec.compare("BEAM") or !spec.compare("P") or !spec.compare("PDG")) { fBeamPDG = GeneralUtils::StrToInt(value); } else if (!spec.compare("SCL") or !spec.compare("SC") or !spec.compare("S")) { fScaling = GeneralUtils::StrToDbl(value); // Throw } else { THROW("Unknown argument given to SigmaQ0 InputHandler!" ); } } // Check we got everything if (fEnergy == -1 or fEnergy < 0) { THROW("Energy for SigmaQ0 Handler either invalid or not given! Specify with ',E=ENERGY' in the input spec."); } // Default to Electron if (fBeamPDG == -1) { ERR(WRN) << "No Beam PDG Given in SigmaQ0 Handler so assuming electron. " << "If input is not electron scattering please specify using : PDG=PDGCODE" << std::endl; } // Convert Theta fTheta = fTheta * M_PI / 180.0; LOG(FIT) << "Set Theta to = " << fTheta << std::endl; // Have to create a dummy flux and event rate histogram :( fFluxHist = new TH1D("fluxhist", "fluxhist", 100.0, 0.0, 2.0 * fEnergy); fFluxHist->SetBinContent( fFluxHist->FindBin(fEnergy), 1.0 ); fEventHist = new TH1D("eventhist", "eventhist", 100.0, 0.0, 2.0 * fEnergy); fEventHist->SetBinContent( fEventHist->FindBin(fEnergy), 1.0 ); fEnergy = fEnergy * 1.E3; LOG(FIT) << "Set E energy" << std::endl; // Now parse the lines in our input file. fApplyInterpolation = FitPar::Config().GetParB("InterpolateSigmaQ0Histogram"); double interpolation_res = FitPar::Config().GetParD("InterpolateSigmaQ0HistogramRes"); fMaxValue = 0.0; fMaxX = 0.0; fMinX = 1.E10; // Create a TGraph of Points TGraph* gr = new TGraph(); std::vector inputlines = GeneralUtils::ParseFileToStr(fFilePath, "\n"); for (uint i = 0; i < inputlines.size(); i++) { std::vector splitline = GeneralUtils::ParseToDbl(inputlines[i], fDelim.c_str()); double q0 = splitline[fQ0Column]; double sig = splitline[fSigmaColumn]; gr->SetPoint(gr->GetN(), q0, sig); if (sig > fMaxValue) fMaxValue = sig; if (q0 > fMaxX) fMaxX = q0; if (q0 < fMinX) fMinX = q0; } fInputGraph = new TGraph(); for (int i = 0; i < gr->GetN(); i++){ fInputGraph->SetPoint(fInputGraph->GetN(), gr->GetX()[i], gr->GetY()[i]); fNEvents++; if (fApplyInterpolation){ // If not last point create extra events if (i != gr->GetN()-1){ double xlow = gr->GetX()[i]; double xhigh = gr->GetX()[i+1]; for (int j = 1; j < int(interpolation_res); j++){ double x = xlow + double(j) * (xhigh - xlow) / interpolation_res; fInputGraph->SetPoint(fInputGraph->GetN(),x, gr->Eval(x)); fNEvents++; } } } } delete gr; - + fFluxHist->Scale(1.0 / fFluxHist->Integral("width") ); fEventHist->Scale( fScaling * double(fNEvents) / fEventHist->Integral() ); if (fApplyInterpolation){ fEventHist->Scale(1.0 / interpolation_res); } - + fUseAcceptReject = FitPar::Config().GetParB("InterpolateSigmaQ0HistogramThrow"); if (fUseAcceptReject){ std::cout << "USING ACCEPT REJECT" << std::endl; fEventHist->Scale( fMaxValue / double(fNEvents) ); fNEvents = FitPar::Config().GetParI("InterpolateSigmaQ0HistogramNTHROWS"); std::cout << "NEvents = " << fNEvents << std::endl; sleep(1); } fNUISANCEEvent = new FitEvent(); - + }; SigmaQ0HistogramInputHandler::~SigmaQ0HistogramInputHandler() { }; FitEvent* SigmaQ0HistogramInputHandler::GetNuisanceEvent(const UInt_t entry, const bool lightweight) { // Catch too large entries if (entry >= (UInt_t)fNEvents) return NULL; // Evaluate Graph to Create an Event if (!fUseAcceptReject){ double q0 = fInputGraph->GetX()[entry]; double sig = fInputGraph->GetY()[entry]; FillNuisanceEvent(q0, sig); } else { double q0 = ThrowQ0(); FillNuisanceEvent(q0, 1.0); } // Return event pointer return fNUISANCEEvent; } double SigmaQ0HistogramInputHandler::ThrowQ0(){ // Use input graph to Throw Q0. int count = 0; while (count < 1E7){ double x = fRandom.Uniform(fMinX,fMaxX); if (fRandom.Uniform(0.0,1.0) <= fInputGraph->Eval(x) / fMaxValue){ return x; }; std::cout << "THROW " << count << " : " << x << std::endl; } return 0.0; } - + void SigmaQ0HistogramInputHandler::FillNuisanceEvent(double q0, double sig) { - + // Reset all variables - + fNUISANCEEvent->ResetEvent(); - + // Fill Globals fNUISANCEEvent->fMode = 1; // Assume CCQE for now... fNUISANCEEvent->Mode = 1; fNUISANCEEvent->fEventNo = 0; fNUISANCEEvent->fTargetA = 0; // Should the User Specify these? fNUISANCEEvent->fTargetZ = 0; // Should the User Specify these? fNUISANCEEvent->fTargetH = 0; // Should the User Specify these? fNUISANCEEvent->fBound = 1; // Should the User Specify these? fNUISANCEEvent->InputWeight = sig; // Add incoming beam particle along Z with energy E and outgoing with theta if (fBeamPDG == 11) { // Initial Beam fNUISANCEEvent->fParticleState[0] = kInitialState; fNUISANCEEvent->fParticlePDG[0] = 11; double mass = 0.511; // Get Momentum of Electron moving along Z fNUISANCEEvent->fParticleMom[0][0] = 0.0; fNUISANCEEvent->fParticleMom[0][1] = 0.0; LOG(FIT) << "Setting Energy = " << fEnergy << std::endl; fNUISANCEEvent->fParticleMom[0][2] = sqrt(fEnergy * fEnergy - mass * mass); fNUISANCEEvent->fParticleMom[0][3] = fEnergy; // Outgoing particle fNUISANCEEvent->fParticleState[1] = kFinalState; fNUISANCEEvent->fParticlePDG[1] = 11; // Get Momentum of Electron outgoing minus q0 double oute = fEnergy - q0; double outp = sqrt(oute * oute - mass * mass); fNUISANCEEvent->fParticleMom[1][0] = 0.0; fNUISANCEEvent->fParticleMom[1][1] = sin(fTheta) * outp; fNUISANCEEvent->fParticleMom[1][2] = cos(fTheta) * outp; fNUISANCEEvent->fParticleMom[1][3] = oute; } // Update Particles fNUISANCEEvent->fNParticles = 2; // Run Initial, FSI, Final, Other ordering. fNUISANCEEvent-> OrderStack(); // Check Q0 // FitParticle* ein = fNUISANCEEvent->PartInfo(0); // FitParticle* eout = fNUISANCEEvent->GetHMFSParticle(11); // double newq0 = fabs(ein->fP.E() - eout->fP.E()) / 1000.0; // double E = ein->fP.E() / 1000.0; // double theta = ein->fP.Vect().Angle(eout->fP.Vect()) * 180. / M_PI; // LOG(FIT) << "Extracted event from line: theirs-" << q0/1.E3 << " ours-" << newq0 << " E-" << fEnergy << " T-" << theta << " X-" << sig << std::endl; return; } diff --git a/src/MCStudies/OscStudies.md b/src/MCStudies/OscStudies.md new file mode 100644 index 0000000..6dc1941 --- /dev/null +++ b/src/MCStudies/OscStudies.md @@ -0,0 +1,150 @@ +# Oscillation studies in NUISANCE + +This simple module allows the construction of simple NOvA-style unfold/propagate/refold/compare style neutrino oscillation studies in NUSIANCE. It is implemented as a standard NUSIANCE sample, although with signficantly more complicated markup than usual. + +## Full example + +```xml + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +## Details + +### NUISANCE Parameters + +Explained in detail elsewhere, but briefly repeated here for completeness. +A reweightable parameter is specified by an element like: +```xml + +``` +where the attributes are hopefully self explanatory. The state should be `FREE` +or `FIXED` depending on whether in a minimisation or chi2 scan the parameter +should be allowed to vary. The valid names for oscillation parameters currently +implemented through Prob3++ are: +* `sinsq_theta12` +* `sinsq_theta13` +* `sinsq_theta23` +* `dm12` +* `dm23` +* `dcp` + +In general, all parameters should be specified if any are, as the default values +may not be sensible. + +The baseline is calculated from the assumption of a beam passing through the +earth to be detected on the surface. + +### Analysis structure + +The oscillation analysis inputs are near detector observations, far detector +observations and neutrino energy migration matricies that encode how detector +effects cause interactions of some true neutrino energy to be reconstructed +with some other neutrino energy. As oscillations happen as a function of +neutrino energy, being able to corectly identify the energy spectrum of +neutrinos before and after oscillation is the most key aspect of an oscillation +analysis. + +The obseved near detector reconstructed energy spectrum is unfolded through the +near detector migration matrix to give the data-motivated, estimated true energy +spectrum of interactions at the near detector. This is then oscillated according +to the current PMNS parameters and corrected for far/near beam divergence and +detector mass. The true energy spectrum at the far detector is then smeared with +the far detector migration matrix, which may or may not be the same as the near +detector one, to give the predicted far detector reconstructed energy spectrum. +A test statistic is evaluated between the predicted and observed far detector +spectrum for the current set of oscillation, and potentially nuisance, +parameters. + +In general the unfolding can be used to estimate the true energy spectrum of +the observed interactions, the true energy spectrum of the interactions that +occured (including efficiency), or the true energy spectrum of the neutrino +flux (also including cross-section). As the far over near correction can +currently only be a single number to account for beam divergence, it is advised +that the supplied migration matrices should account for the migration from true +interactions to true energy spectra (i.e. include the efficiency +correction/application at the near and far detectors). Currently, the nue and +numu cross sections are assumed identical. + +**N.B.:** The near and far detector samples are assigned a neutrino PDG code, *i.e.* they must represent a CCInclusive sample of a single neutrino flavor. There is no support for interaction model-fitting style (T2K) analyses. + +### The Sample element + +```xml + +... + +``` + +Every oscillation analysis needs at least one near and one far detector sample. +To keep the structure of NUISANCE sample elements, the first near +detector sample is specified slightly differently to subsequent samples. + +The sample element specifies the near detector mass through the attributes `DetectorVolume` and `DetectorDensity`, the separation is purely for your bookkeeping, they must multiply to give a mass in the same units as the far detector masses that will be specified. This is purely used for near-to-far extrapolation, the input histograms are expected to be well-normalised event rate predictions in the relevant near and far detector configurations. + +The `ScalePOT` attribute is applied to all input histograms as a re-normalisation factor, this allows event rate predictions to be recalculated by a simple scale factor at runtime. + +The `SetErrorsFromRate` attribute specifies whether the input histogram errors should be respected or they should be rescaled to the poisson error on the fully normalised event rate (included the `ScalePOT` attributed) in each bin. + +**N.B.:** Only a single near detector can be specified, it would be fairly trivial to add multiple near detector setups, but that is currently not implemented. However, multiple near detector CCInc samples may be declared. + +### ND sample descriptors + +```xml + +``` + +The input histograms for each ND sample should be given in the order: [observed rate in ERec], [ERec:ETrue migration matrix]. These can come from a single ROOT file, as shown above, or from two separate ROOT files, specified like: `ObsInput="FILE1.root[ObsRateERecHistName],FILE2.root[ERecETrueMigrationMatrixTH2DName]"`. The first ND sample, which is specified in the sample element, as opposed to in a child element named `NDObs`, must be prefixed with `HISTO:` to satisfy NUISANCE's requirement for input types. + +The `NuPDG` attribute specifies the neutrinp PDG code which is observed sample corresponds to, most likely one of `-12,12,-14,14`, depending on the analysis setup. + +The `TruncateStart` and `TruncateUpTo` attributes specify the number of singular values that may be set to 0 in the SVD decoposition to ensure that the unfolded spectrum at the near detector is >= 0 within the union of specified `FitRegion`s in the far detector samples (see the next section). If there are still negative values after the maximum allowed regularisation has been attempted, the analysis will throw an exception. + +### FD sample descriptors + +```xml + + + + +``` + +Each far detector sample has the same inputs as each near detector sample, an observed histogram (correctly normalised) and a migration matrix. For the far detector samples, the migration matrix is not inverted, but used to forward-fold the true spectrum prediction at the far detector. + +The two elements `FitRegion_min` and `FitRegion_max` are used to specify the range of the observation histogram that is included in the Chi2 calculation. These ranges are also used to inform the regularisation of the SVD inversion used ont he near detector samples. + +Each far detector sample receives contributions from every near detector sample, these may well be 0, but the extrapolation is performed independently for each far detector sample. Therefore, each far detector sample element must set up its detector mass, even if they are all the same. In the example shown above the far detector is set up to have a 40 kilotonne fiducial mass. + +The `OscillateToPDG` attribtue functions similarly to the `NuPDG` attribute for the near detector samples and specifies what species of neutrino the sample characterises, muon neutrino, electron anti-neutrino, etc... This is used to calculate the correction oscillation probability from each of the near detector samples. *e.g.* For a electron neutrino far detector sample, the muon neutrino to electron neutrino appearance probability is applied during the propagation to a muon neutrino near detector sample, and the electron neutrino survival probability is applied to an intrinsic electron neutrino near detector sample. + +To inform the correct propagation of each near detector sample, a child `FDNDRatio` tag must be supplied. This specifies the beam divergence factor for each near detector sample --- linked via its `NuPDG` --- this is applied as a simple scale factor during near-to-far propagation. It would be possible to allow this a functional form to account for the relative difference in shape of the unoscillated flux at the near and far detector, but this is not yet implemented. Any near detector samples which do not have a corresponding `FDNDRatio` tag are given a divergence factor of `0` and effectively do not contribute to the far detector prediction. *e.g.* In the example at the top of this note, the far detector muon neutrino disapeerance sample recieves no contribution from the intrinsic electron neutrino sample, this is trivial to enable, but makes a completely insignificant difference to the far detector prediction. + +## Input generation details + +The input histograms are simplest to prepare through the `nuissmear` application, which by default will output both that are required for each input. + +The observed ERec distribution for each sample should be self-explanatory. The response matrix should be supplied as a TH2D, with the true energy on the X axis and the reconstructed energy on the Y axis. The generation shape should be divided out of this. There is a small choice to be made here, either the efficiency correction can be included as part of the unfolding, this would involve dividing every bin by the total number of interaction generated in that bin of true neutrino energy -- events that are not reconstructed and thus do not make it into the histogram are accounted for by the sum of each Y slice of bins not totalling unity. Alternatively, you could re-normalised each Y slice so that the sum of bins totals to unity and this would mean that the unfolding only accounted for the migration and not the detector/selection efficiency. This implicitly would include the assumption into any susequent analysis that the detectors are functionally identical. It would also be possible to apply the efficiency ratio during the propagation, but this can only be a flat scale calculated from the ratio of detector masses and the beam divergence factor, it is not currently possible. diff --git a/src/MCStudies/Smear_SVDUnfold_Propagation_Osc.cxx b/src/MCStudies/Smear_SVDUnfold_Propagation_Osc.cxx index 60818db..67896da 100644 --- a/src/MCStudies/Smear_SVDUnfold_Propagation_Osc.cxx +++ b/src/MCStudies/Smear_SVDUnfold_Propagation_Osc.cxx @@ -1,380 +1,823 @@ // 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 . *******************************************************************************/ #include "Smear_SVDUnfold_Propagation_Osc.h" #include "SmearceptanceUtils.h" #include "OscWeightEngine.h" -//******************************************************************** -Smear_SVDUnfold_Propagation_Osc::Smear_SVDUnfold_Propagation_Osc( - nuiskey samplekey) { - //******************************************************************** +#include "HistogramInputHandler.h" - // Sample overview --------------------------------------------------- - std::string descrip = - "Simple measurement class for doing fake data oscillation studies.\n"; +void Smear_SVDUnfold_Propagation_Osc::AddNDInputs(nuiskey &samplekey) { + NDSample nds; - // Setup common settings - fSettings = LoadSampleSettings(samplekey); + // Plot Setup ------------------------------------------------------- + // Check that we have the relevant near detector histograms specified. + + if (!NDSamples.size()) { // If this is the first ND sample, take from the + // sample input + InputHandlerBase *InputBase = GetInput(); + if (InputBase->GetType() != kHISTO) { + THROW( + "Smear_SVDUnfold_Propagation_Osc expects a Histogram input that " + "contains the ND observed spectrum."); + } + HistoInputHandler *HInput = dynamic_cast(InputBase); + if (!HInput) { + THROW( + "Smear_SVDUnfold_Propagation_Osc expects a Histogram input that " + "contains the ND observed spectrum."); + } + if (HInput->NHistograms() != 2) { + THROW( + "Input expected to contain 2 histograms. " + "HISTO:input.root[NDObs_TH1D,NDSmear_TH2D]"); + } + nds.NDDataHist = dynamic_cast(HInput->GetHistogram(0)); + nds.NDToSpectrumSmearingMatrix = + dynamic_cast(HInput->GetHistogram(1)); - fSettings.SetTitle("Osc Studies"); - fSettings.SetDescription(descrip); - fSettings.SetXTitle("XXX"); - fSettings.SetYTitle("Number of events"); - fSettings.SetEnuRange(0.0, 50); - fSettings.SetAllowedTypes("EVT/SHAPE/DIAG", "EVT/SHAPE/DIAG"); - fSettings.DefineAllowedTargets("*"); - fSettings.DefineAllowedSpecies("numu"); + if (!nds.NDDataHist) { + THROW("Expected a valid TH1D input for the ND observed spectrum."); + } - FinaliseSampleSettings(); + if (!nds.NDToSpectrumSmearingMatrix) { + THROW("Expected a valid TH2D input for the ND observed smearing."); + } + } else { + std::vector NDObsInputs = + PlotUtils::GetTH1sFromRootFile(samplekey.GetS("ObsInput")); + if (NDObsInputs.size() < 2) { + THROW( + "Near detector sample must contain the observed ERec spectrum and " + "the " + "ND ETrue/ERec smearing matrix. e.g. " + "ObsInput=\"input.root[NDObs_species,NDSmearing_species]\""); + } - // Scaling Setup --------------------------------------------------- - // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon - fScaleFactor = GetEventHistogram()->Integral("width") / (fNEvents + 0.); + nds.NDDataHist = dynamic_cast(NDObsInputs[0]); + if (!nds.NDDataHist) { + ERROR(FTL, + "First histogram from ObsInput attribute was not a TH1D containing " + "the near detector observed ERec spectrum (" + << samplekey.GetS("ObsInput") << ")."); + THROW( + "Near detector sample must contain the observed ERec spectrum and " + "the " + "ND ETrue/ERec smearing matrix. e.g. " + "ObsInput=\"input.root[FDObs_species,FDSmearing_species]\""); + } - // Plot Setup ------------------------------------------------------- - // Check that we have the relevant histograms specified. - if (!samplekey.Has("NDDataHist") || !samplekey.Has("FDDataHist") || - !samplekey.Has("NDToSpectrumSmearingMatrix")) { - THROW( - "Expected to attributes named: NDDataHist, FDDataHist, " - "NDToSpectrumSmearingMatrix on the Smear_SVDUnfold_Propagation_Osc " - "sample " - "tag."); + nds.NDToSpectrumSmearingMatrix = dynamic_cast(NDObsInputs[1]); + if (!nds.NDToSpectrumSmearingMatrix) { + ERROR( + FTL, + "Second histogram from ObsInput attribute was not a TH2D containing " + "the near detector ETrue/ERec smearing matrix (" + << samplekey.GetS("ObsInput") << ")."); + THROW( + "Near detector sample must contain the observed ERec spectrum and " + "the " + "ND ETrue/ERec smearing matrix. e.g. " + "ObsInput=\"input.root[FDObs_species,FDSmearing_species]\""); + } } - NDDataHist = NULL; - FDDataHist = NULL; - NDToSpectrumSmearingMatrix = NULL; - fMCHist = NULL; - fDataHist = NULL; + nds.NDDataHist->Scale(ScalePOT); + + if (UseRateErrors) { + for (Int_t bi_it = 1; bi_it < nds.NDDataHist->GetXaxis()->GetNbins() + 1; + ++bi_it) { + nds.NDDataHist->SetBinError(bi_it, + sqrt(nds.NDDataHist->GetBinContent(bi_it))); + } + } - std::vector NDHistDescriptor = - GeneralUtils::ParseToStr(samplekey.GetS("NDDataHist"), ","); - if (NDHistDescriptor.size() == 2) { - NDDataHist = PlotUtils::GetTH1DFromRootFile(NDHistDescriptor[0], - NDHistDescriptor[1]); - ND_True_Spectrum_Hist = - PlotUtils::GetTH1DFromRootFile(NDHistDescriptor[0], "ELep_rate"); + nds.TruncateStart = 0; + if (samplekey.Has("TruncateStart")) { + nds.TruncateStart = samplekey.GetI("TruncateStart"); } - if (!NDDataHist) { - THROW("Attempted to load NDDataHist from the descriptor: \"" - << samplekey.GetS("NDDataHist") - << "\", but failed. Does it look correct? \",\""); + nds.TruncateUpTo = 0; + if (samplekey.Has("TruncateUpTo")) { + nds.TruncateUpTo = samplekey.GetI("TruncateUpTo"); + QLOG(SAM, "\tAllowed to truncate unfolding matrix by up to " + << nds.TruncateUpTo + << " singular values to limit negative ENu spectra."); + } + nds.NuPDG = 14; + if (samplekey.Has("NuPDG")) { + nds.NuPDG = samplekey.GetI("NuPDG"); } - std::vector FDHistDescriptor = - GeneralUtils::ParseToStr(samplekey.GetS("FDDataHist"), ","); - if (FDHistDescriptor.size() == 2) { - FDDataHist = PlotUtils::GetTH1DFromRootFile(FDHistDescriptor[0], - FDHistDescriptor[1]); + NDSamples.push_back(nds); +} + +void Smear_SVDUnfold_Propagation_Osc::SetupNDInputs() { + for (size_t nd_it = 0; nd_it < NDSamples.size(); ++nd_it) { + NDSample &nds = NDSamples[nd_it]; + + TMatrixD NDToSpectrumResponseMatrix_l = SmearceptanceUtils::GetMatrix( + SmearceptanceUtils::SVDGetInverse(nds.NDToSpectrumSmearingMatrix)); + + nds.NDToSpectrumResponseMatrix.ResizeTo(NDToSpectrumResponseMatrix_l); + nds.NDToSpectrumResponseMatrix = NDToSpectrumResponseMatrix_l; + + if (nds.TruncateStart != 0) { + TMatrixD NDToSpectrumResponseMatrix_l = + SmearceptanceUtils::GetMatrix(SmearceptanceUtils::SVDGetInverse( + nds.NDToSpectrumSmearingMatrix, nds.TruncateStart)); + + nds.NDToSpectrumResponseMatrix.ResizeTo(NDToSpectrumResponseMatrix_l); + nds.NDToSpectrumResponseMatrix = NDToSpectrumResponseMatrix_l; + } + + if (nds.TruncateStart >= nds.TruncateUpTo) { + nds.TruncateUpTo = nds.TruncateStart + 1; + } - FD_True_Spectrum_Hist = - PlotUtils::GetTH1DFromRootFile(FDHistDescriptor[0], "ELep_rate"); + UnfoldToNDETrueSpectrum(nd_it); } +} - if (!FDDataHist) { - THROW("Attempted to load FDDataHist from the descriptor: \"" - << samplekey.GetS("FDDataHist") - << "\", but failed. Does it look correct? \",\""); +void Smear_SVDUnfold_Propagation_Osc::ReadExtraConfig(nuiskey &samplekey) { + UseRateErrors = false; + if (samplekey.Has("SetErrorsFromRate")) { + UseRateErrors = samplekey.GetI("SetErrorsFromRate"); } - std::vector NDToEvSmearingDescriptor = GeneralUtils::ParseToStr( - samplekey.GetS("NDToSpectrumSmearingMatrix"), ","); - if (NDToEvSmearingDescriptor.size() == 2) { - NDToSpectrumSmearingMatrix = PlotUtils::GetTH2DFromRootFile( - NDToEvSmearingDescriptor[0], NDToEvSmearingDescriptor[1]); + NDetectorInfo.first = 0xdeadbeef; + if (samplekey.Has("DetectorVolume") && samplekey.Has("DetectorDensity")) { + NDetectorInfo.first = samplekey.GetD("DetectorVolume"); + NDetectorInfo.second = samplekey.GetD("DetectorDensity"); + + double TargetMass_kg = NDetectorInfo.first * NDetectorInfo.second; + + QLOG(SAM, "\tND sample detector mass : "); + QLOG(SAM, "\t\tTarget volume : " << NDetectorInfo.first); + QLOG(SAM, "\t\tTarget density : " << NDetectorInfo.second); + QLOG(SAM, "\t\tTarget mass : " << TargetMass_kg << " kg"); } - if (!NDToSpectrumSmearingMatrix) { - THROW("Attempted to load NDToSpectrumSmearingMatrix from the descriptor: \"" - << samplekey.GetS("NDToSpectrumSmearingMatrix") - << "\", but failed. Does it look correct? \",\""); + ScalePOT = 1; + if (samplekey.Has("ScalePOT")) { + ScalePOT = samplekey.GetD("ScalePOT"); } +} - TMatrixD NDToSpectrumResponseMatrix_l = SmearceptanceUtils::GetMatrix( - SmearceptanceUtils::SVDGetInverse(NDToSpectrumSmearingMatrix)); +void Smear_SVDUnfold_Propagation_Osc::AddFDTarget(nuiskey &nk) { + FDSample fds; - NDToSpectrumResponseMatrix.ResizeTo(NDToSpectrumResponseMatrix_l); - NDToSpectrumResponseMatrix = NDToSpectrumResponseMatrix_l; + fds.FitRegion_Min = 0xdeadbeef; + if (nk.Has("FitRegion_Min")) { + fds.FitRegion_Min = nk.GetD("FitRegion_Min"); + } + if ((FitRegion_Min == 0xdeadbeef) || FitRegion_Min > fds.FitRegion_Min) { + FitRegion_Min = fds.FitRegion_Min; + } - TMatrixD SpectrumToFDResponseMatrix_l = - SmearceptanceUtils::GetMatrix(NDToSpectrumSmearingMatrix); + fds.FitRegion_Max = 0xdeadbeef; + if (nk.Has("FitRegion_Max")) { + fds.FitRegion_Max = nk.GetD("FitRegion_Max"); + } + if ((FitRegion_Max == 0xdeadbeef) || FitRegion_Max < fds.FitRegion_Max) { + FitRegion_Max = fds.FitRegion_Max; + } - SpectrumToFDResponseMatrix.ResizeTo(SpectrumToFDResponseMatrix_l); - SpectrumToFDResponseMatrix = SpectrumToFDResponseMatrix_l; + fds.OscillateToPDG = 0; + if (nk.Has("OscillateToPDG")) { + fds.OscillateToPDG = nk.GetD("OscillateToPDG"); + } - fDataHist = static_cast(FDDataHist->Clone()); - fDataHist->SetNameTitle((fSettings.GetName() + "_data").c_str(), - (fSettings.GetFullTitles()).c_str()); + std::vector FDNDRatioElements = nk.GetListOfChildNodes("FDNDRatio"); + for (size_t fdnd_it = 0; fdnd_it < FDNDRatioElements.size(); ++fdnd_it) { + nuiskey &fnr = FDNDRatioElements[fdnd_it]; + if (fnr.Has("FromPDG") && fnr.Has("DivergenceFactor")) { + fds.FDNDRatios[fnr.GetI("FromPDG")] = fnr.GetD("DivergenceFactor"); + QLOG(SAM, "FDND DivergenceFactor for far detector sample index: " + << FDSamples.size() << " for PDG: " << fnr.GetI("FromPDG") + << " -> " << fds.OscillateToPDG << " = " + << fnr.GetD("DivergenceFactor")); + } else { + THROW( + "Far detector sample contained FDNDRatio element, but couldn't find " + "both FromPDG and Factor attributes."); + } + } - fMCHist = static_cast(FDDataHist->Clone()); - fMCHist->SetNameTitle((fSettings.GetName() + "_MC").c_str(), - (fSettings.GetFullTitles()).c_str()); + fds.FDNDMassRatio = 1; + if (NDetectorInfo.first != 0xdeadbeef) { + if ((!nk.Has("DetectorVolume")) || (!nk.Has("DetectorDensity"))) { + THROW( + "Near detector sample has specified volume but FD doesn't. This is " + "needed to scale the predicted event rate by the mass ratio."); + } + fds.DetectorInfo.first = nk.GetD("DetectorVolume"); + fds.DetectorInfo.second = nk.GetD("DetectorDensity"); + double TargetMass_kg = fds.DetectorInfo.first * fds.DetectorInfo.second; - SetCovarFromDiagonal(); + fds.FDNDMassRatio = + TargetMass_kg / (NDetectorInfo.first * NDetectorInfo.second); - TruncateUpTo = 0; - if (samplekey.Has("TruncateUpTo")) { - TruncateUpTo = samplekey.GetI("TruncateUpTo"); - QLOG(SAM, "Allowed to truncate unfolding matrix by up to " - << TruncateUpTo - << " singular values to limit negative ENu spectra."); + QLOG(SAM, "\tFD[" << FDSamples.size() << "] Event rate prediction : "); + QLOG(SAM, "\t\tTarget volume : " << fds.DetectorInfo.first); + QLOG(SAM, "\t\tTarget density : " << fds.DetectorInfo.second); + QLOG(SAM, "\t\tFD/ND mass : " << fds.FDNDMassRatio); } - if (samplekey.Has("FitRegion_Min")) { - FitRegion_Min = samplekey.GetD("FitRegion_Min"); - } else { - FitRegion_Min = 0xdeadbeef; + if (!nk.Has("ObsInput")) { + THROW("Far detector sample must specify at least ObsInput."); } - if (samplekey.Has("FitRegion_Max")) { - FitRegion_Max = samplekey.GetD("FitRegion_Max"); - } else { - FitRegion_Max = 0xdeadbeef; + + std::vector FDObsInputs = + PlotUtils::GetTH1sFromRootFile(nk.GetS("ObsInput")); + if (FDObsInputs.size() < 2) { + THROW( + "Far detector sample must contain the observed ERec spectrum and the " + "FD ETrue/ERec smearing matrix. " + "ObsInput=\"input.root[FDObs_species,FDSmearing_species]\""); + } + + fds.FDDataHist = NULL; + for (size_t hist_it = 0; hist_it < FDObsInputs.size() - 1; ++hist_it) { + if (!dynamic_cast(FDObsInputs[hist_it])) { + ERROR(FTL, "Input spectrum index " + << hist_it + << " from ObsInput attribute was not a TH1D containing " + "a far detector observed ERec spectrum (" + << nk.GetS("ObsInput") << ")."); + THROW( + "Far detector sample must contain the observed ERec spectrum and the " + "FD ETrue/ERec smearing matrix. " + "ObsInput=\"input.root[FDObs_species,(FDObs_species2),FDSmearing_" + "species]\""); + } + FDObsInputs[hist_it]->Scale(ScalePOT); + if (!fds.FDDataHist) { + fds.FDDataHist = dynamic_cast(FDObsInputs[hist_it]); + } else { + fds.FDDataHist->Add(dynamic_cast(FDObsInputs[hist_it])); + } + QLOG(SAM, "Added " << (FDObsInputs.size() - 1) + << " far detector component spectra to form Observed " + "spectra for sample index " + << FDSamples.size() << "."); + } + + fds.SpectrumToFDSmearingMatrix_TH2 = dynamic_cast(FDObsInputs.back()); + if (!fds.SpectrumToFDSmearingMatrix_TH2) { + ERROR(FTL, + "last histogram from ObsInput attribute was not a TH2D containing " + "the far detector ETrue/ERec smearing matrix (" + << nk.GetS("ObsInput") << ")."); + THROW( + "Far detector sample must contain the observed ERec spectrum and the " + "FD ETrue/ERec smearing matrix. " + "ObsInput=\"input.root[FDObs_species,FDSmearing_species]\""); } - //---------------------------- - // Mask data hist if needed - fDataHist->SetBinContent(0, 0); - fDataHist->SetBinError(0, 0); - fDataHist->SetBinContent(fDataHist->GetXaxis()->GetNbins() + 1, 0); - fDataHist->SetBinError(fDataHist->GetXaxis()->GetNbins() + 1, 0); + TMatrixD SpectrumToFDSmearingMatrix_l = + SmearceptanceUtils::GetMatrix(fds.SpectrumToFDSmearingMatrix_TH2); + + fds.SpectrumToFDSmearingMatrix.ResizeTo(SpectrumToFDSmearingMatrix_l); + fds.SpectrumToFDSmearingMatrix = SpectrumToFDSmearingMatrix_l; + + FDSamples.push_back(fds); +} + +void Smear_SVDUnfold_Propagation_Osc::FinaliseFDSamples() { + std::stringstream ss(""); + + for (size_t fds_it = 0; fds_it < FDSamples.size(); ++fds_it) { + FDSample &fds = FDSamples[fds_it]; + // Set up FD histograms. + // ============================== + + for (size_t nd_it = 0; nd_it < NDSamples.size(); ++nd_it) { + NDSample &nds = NDSamples[nd_it]; + + TH1D *sampleHist = + static_cast(nds.ND_Unfolded_Spectrum_Hist->Clone()); + sampleHist->Reset(); + ss.str(""); + ss << "FD_Propagated_Spectrum_Hist_" << fds_it << "_NDSample_" << nd_it; + sampleHist->SetName(ss.str().c_str()); + + fds.FD_Propagated_Spectrum_Hist_NDSamples.push_back(sampleHist); + } + + fds.FD_Propagated_Spectrum_Hist = static_cast( + fds.FD_Propagated_Spectrum_Hist_NDSamples[0]->Clone()); + fds.FD_Propagated_Spectrum_Hist->Reset(); + ss.str(""); + ss << "FD_Propagated_Spectrum_Hist_" << fds_it; + + fds.FD_Propagated_Spectrum_Hist->SetName(ss.str().c_str()); + + for (size_t nd_it = 0; nd_it < NDSamples.size(); ++nd_it) { + NDSample &nds = NDSamples[nd_it]; + + TH1D *sampleHist = + static_cast(fds.FD_Propagated_Spectrum_Hist->Clone()); + sampleHist->Reset(); + ss.str(""); + ss << "NDFD_Corrected_Spectrum_Hist_" << fds_it << "_NDSample_" << nd_it; + sampleHist->SetName(ss.str().c_str()); - for (Int_t bi_it = 1; bi_it < fDataHist->GetXaxis()->GetNbins() + 1; + fds.NDFD_Corrected_Spectrum_Hist_NDSamples.push_back(sampleHist); + } + + fds.NDFD_Corrected_Spectrum_Hist = + static_cast(fds.FD_Propagated_Spectrum_Hist->Clone()); + fds.NDFD_Corrected_Spectrum_Hist->Reset(); + ss.str(""); + ss << "NDFD_Corrected_Spectrum_Hist_" << fds_it; + + fds.NDFD_Corrected_Spectrum_Hist->SetName(ss.str().c_str()); + + fds.FD_Smeared_Spectrum_Hist = + new TH1D(*fds.SpectrumToFDSmearingMatrix_TH2->ProjectionX()); + fds.FD_Smeared_Spectrum_Hist->SetDirectory(NULL); + fds.FD_Smeared_Spectrum_Hist->Reset(); + ss.str(""); + ss << "FD_Smeared_Spectrum_Hist_" << fds_it; + + fds.FD_Smeared_Spectrum_Hist->SetName(ss.str().c_str()); + + for (size_t nd_it = 0; nd_it < NDSamples.size(); ++nd_it) { + NDSample &nds = NDSamples[nd_it]; + + if (!fds.FDNDRatios.count(nds.NuPDG)) { + ERROR(WRN, "Have an ND sample that provides PDG:" + << nds.NuPDG + << " neutrinos but far detector sample index " << fds_it + << " doesn't have an NDFD ratio for this sample. " + "Setting to 0 (contribution from sample ignored.)"); + fds.FDNDRatios[nds.NuPDG] = 0; + } + } + } +} + +Int_t Smear_SVDUnfold_Propagation_Osc::GetFDSampleNAnalysisBins(size_t fds_it) { + if (fds_it >= FDSamples.size()) { + THROW("Requested FD sample index " << fds_it << " but only initialised " + << FDSamples.size()); + } + FDSample &fds = FDSamples[fds_it]; + Int_t NAnalysisBins = 0; + for (Int_t bi_it = 1; bi_it < fds.FDDataHist->GetXaxis()->GetNbins() + 1; ++bi_it) { - if ((FitRegion_Min != 0xdeadbeef) && - (fDataHist->GetXaxis()->GetBinUpEdge(bi_it) <= FitRegion_Min)) { - fDataHist->SetBinContent(bi_it, 0); - fDataHist->SetBinError(bi_it, 0); + if ((fds.FitRegion_Min != 0xdeadbeef) && + (fds.FDDataHist->GetXaxis()->GetBinUpEdge(bi_it) <= + fds.FitRegion_Min)) { + continue; + } + if ((fds.FitRegion_Max != 0xdeadbeef) && + (fds.FDDataHist->GetXaxis()->GetBinLowEdge(bi_it) > + fds.FitRegion_Max)) { + continue; } - if ((FitRegion_Max != 0xdeadbeef) && - (fDataHist->GetXaxis()->GetBinLowEdge(bi_it) > FitRegion_Max)) { - fDataHist->SetBinContent(bi_it, 0); - fDataHist->SetBinError(bi_it, 0); + NAnalysisBins++; + } + return NAnalysisBins; +} + +void Smear_SVDUnfold_Propagation_Osc::SetupChi2Hists() { + fDataHist = + new TH1D("SmearSVDUnfold", "", NFDAnalysisBins, 0, NFDAnalysisBins); + fDataHist->SetNameTitle((fSettings.GetName() + "_data").c_str(), + (fSettings.GetFullTitles()).c_str()); + + Int_t CurrAnalysisBin = 1; + for (size_t fds_it = 0; fds_it < FDSamples.size(); ++fds_it) { + FDSample &fds = FDSamples[fds_it]; + for (Int_t bi_it = 1; bi_it < fds.FDDataHist->GetXaxis()->GetNbins() + 1; + ++bi_it) { + if ((fds.FitRegion_Min != 0xdeadbeef) && + (fds.FDDataHist->GetXaxis()->GetBinUpEdge(bi_it) <= + fds.FitRegion_Min)) { + continue; + } + if ((fds.FitRegion_Max != 0xdeadbeef) && + (fds.FDDataHist->GetXaxis()->GetBinLowEdge(bi_it) > + fds.FitRegion_Max)) { + continue; + } + fDataHist->SetBinContent(CurrAnalysisBin, + fds.FDDataHist->GetBinContent(bi_it)); + if (UseRateErrors) { + fDataHist->SetBinError(CurrAnalysisBin, + sqrt(fds.FDDataHist->GetBinContent(bi_it))); + } else { + fDataHist->SetBinError(CurrAnalysisBin, + fds.FDDataHist->GetBinError(bi_it)); + } + CurrAnalysisBin++; } } - TruncateStart = 0; - if (Config::Get().GetConfigNode("smear.SVD.truncation")) { - TruncateStart = Config::Get().ConfI("smear.SVD.truncation"); + fMCHist = static_cast(fDataHist->Clone()); + fMCHist->SetNameTitle((fSettings.GetName() + "_MC").c_str(), + (fSettings.GetFullTitles()).c_str()); + fMCHist->Reset(); +} - TMatrixD NDToSpectrumResponseMatrix_l = - SmearceptanceUtils::GetMatrix(SmearceptanceUtils::SVDGetInverse( - NDToSpectrumSmearingMatrix, TruncateStart)); +void Smear_SVDUnfold_Propagation_Osc::UpdateChi2Hists() { + Int_t CurrAnalysisBin = 1; + for (size_t fds_it = 0; fds_it < FDSamples.size(); ++fds_it) { + FDSample &fds = FDSamples[fds_it]; + for (Int_t bi_it = 1; + bi_it < fds.FD_Smeared_Spectrum_Hist->GetXaxis()->GetNbins() + 1; + ++bi_it) { + if ((fds.FitRegion_Min != 0xdeadbeef) && + (fds.FD_Smeared_Spectrum_Hist->GetXaxis()->GetBinUpEdge(bi_it) <= + fds.FitRegion_Min)) { + continue; + } + if ((fds.FitRegion_Max != 0xdeadbeef) && + (fds.FD_Smeared_Spectrum_Hist->GetXaxis()->GetBinLowEdge(bi_it) > + fds.FitRegion_Max)) { + continue; + } + fMCHist->SetBinContent( + CurrAnalysisBin, fds.FD_Smeared_Spectrum_Hist->GetBinContent(bi_it)); - NDToSpectrumResponseMatrix.ResizeTo(NDToSpectrumResponseMatrix_l); - NDToSpectrumResponseMatrix = NDToSpectrumResponseMatrix_l; + fMCHist->SetBinError(CurrAnalysisBin, + fds.FD_Smeared_Spectrum_Hist->GetBinError(bi_it)); + CurrAnalysisBin++; + } } +} + +//******************************************************************** +Smear_SVDUnfold_Propagation_Osc::Smear_SVDUnfold_Propagation_Osc( + nuiskey samplekey) { + //******************************************************************** + + // Sample overview --------------------------------------------------- + std::string descrip = + "Simple measurement class for doing fake data oscillation studies.\n"; + + // Setup common settings + fSettings = LoadSampleSettings(samplekey); + + fSettings.SetTitle("Osc Studies"); + fSettings.SetDescription(descrip); + fSettings.SetXTitle("XXX"); + fSettings.SetYTitle("Number of events"); + fSettings.SetEnuRange(0.0, 50); + fSettings.SetAllowedTypes("EVT/SHAPE/DIAG", "EVT/SHAPE/DIAG"); + fSettings.DefineAllowedTargets("*"); + fSettings.DefineAllowedSpecies("numu"); + + FinaliseSampleSettings(); + + // Scaling Setup --------------------------------------------------- + // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon + fScaleFactor = GetEventHistogram()->Integral("width") / (fNEvents + 0.); + + fMCHist = NULL; + fDataHist = NULL; - if (TruncateStart >= TruncateUpTo) { - TruncateUpTo = TruncateStart + 1; + ReadExtraConfig(samplekey); + + AddNDInputs(samplekey); + std::vector NDTargets = samplekey.GetListOfChildNodes("NDObs"); + for (size_t nd_it = 0; nd_it < NDTargets.size(); ++nd_it) { + AddNDInputs(NDTargets[nd_it]); } - NDFDRatio = 1; - if (samplekey.Has("FDNDRatio")) { - NDFDRatio = samplekey.GetD("FDNDRatio"); + std::vector FDTargets = samplekey.GetListOfChildNodes("FDObs"); + NFDAnalysisBins = 0; + if (!FDTargets.size()) { // If no child elements, assume that everything is + // contained on the sample element + AddFDTarget(samplekey); + } else { + for (size_t fd_it = 0; fd_it < FDTargets.size(); ++fd_it) { + AddFDTarget(FDTargets[fd_it]); + NFDAnalysisBins += GetFDSampleNAnalysisBins(fd_it); + } } - UnfoldToNDETrueSpectrum(); + SetupNDInputs(); + + FinaliseFDSamples(); + + QLOG(SAM, "Set up " << FDSamples.size() + << " samples for oscillation analysis with " + << NFDAnalysisBins << " analysis bins."); + + SetupChi2Hists(); + + SetCovarFromDiagonal(); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; void Smear_SVDUnfold_Propagation_Osc::FillEventVariables(FitEvent *event){}; bool Smear_SVDUnfold_Propagation_Osc::isSignal(FitEvent *event) { return false; } -void Smear_SVDUnfold_Propagation_Osc::UnfoldToNDETrueSpectrum(void) { - ND_Unfolded_Spectrum_Hist = NDToSpectrumSmearingMatrix->ProjectionY(); - ND_Unfolded_Spectrum_Hist->Clear(); - ND_Unfolded_Spectrum_Hist->SetName("ND_Unfolded_Spectrum_Hist"); +void Smear_SVDUnfold_Propagation_Osc::UnfoldToNDETrueSpectrum(size_t nd_it) { + if (nd_it >= NDSamples.size()) { + THROW("Attempting to unfold ND sample index " + << nd_it << " but only have " << NDSamples.size() << " ND samples."); + } + + NDSample &nds = NDSamples[nd_it]; + + nds.ND_Unfolded_Spectrum_Hist = + new TH1D(*nds.NDToSpectrumSmearingMatrix->ProjectionY()); + nds.ND_Unfolded_Spectrum_Hist->SetDirectory(NULL); + nds.ND_Unfolded_Spectrum_Hist->Clear(); + std::stringstream ss(""); + ss << "ND_Unfolded_Spectrum_Hist_" << nd_it; + nds.ND_Unfolded_Spectrum_Hist->SetName(ss.str().c_str()); bool HasNegValue = false; - int truncations = TruncateStart; + int truncations = nds.TruncateStart; do { - if (truncations >= TruncateUpTo) { + if (truncations >= nds.TruncateUpTo) { THROW("Unfolded enu spectrum had negative values even after " << truncations << " SVD singular value truncations."); } // Unfold ND ERec -> Enu spectrum // ------------------------------ SmearceptanceUtils::PushTH1ThroughMatrixWithErrors( - NDDataHist, ND_Unfolded_Spectrum_Hist, NDToSpectrumResponseMatrix, 1000, - false); + nds.NDDataHist, nds.ND_Unfolded_Spectrum_Hist, + nds.NDToSpectrumResponseMatrix, 1000, false); HasNegValue = false; for (Int_t bi_it = 1; - bi_it < ND_Unfolded_Spectrum_Hist->GetXaxis()->GetNbins() + 1; + bi_it < nds.ND_Unfolded_Spectrum_Hist->GetXaxis()->GetNbins() + 1; ++bi_it) { if ((FitRegion_Min != 0xdeadbeef) && - (ND_Unfolded_Spectrum_Hist->GetXaxis()->GetBinUpEdge(bi_it) <= + (nds.ND_Unfolded_Spectrum_Hist->GetXaxis()->GetBinUpEdge(bi_it) <= FitRegion_Min)) { continue; } if ((FitRegion_Max != 0xdeadbeef) && - (ND_Unfolded_Spectrum_Hist->GetXaxis()->GetBinLowEdge(bi_it) > + (nds.ND_Unfolded_Spectrum_Hist->GetXaxis()->GetBinLowEdge(bi_it) > FitRegion_Max)) { continue; } - if (ND_Unfolded_Spectrum_Hist->GetBinContent(bi_it) < 0) { + if (nds.ND_Unfolded_Spectrum_Hist->GetBinContent(bi_it) < 0) { HasNegValue = true; break; } } if (HasNegValue) { TMatrixD NDToSpectrumResponseMatrix_l = SmearceptanceUtils::GetMatrix(SmearceptanceUtils::SVDGetInverse( - NDToSpectrumSmearingMatrix, truncations)); + nds.NDToSpectrumSmearingMatrix, truncations)); - NDToSpectrumResponseMatrix.ResizeTo(NDToSpectrumResponseMatrix_l); - NDToSpectrumResponseMatrix = NDToSpectrumResponseMatrix_l; + nds.NDToSpectrumResponseMatrix.ResizeTo(NDToSpectrumResponseMatrix_l); + nds.NDToSpectrumResponseMatrix = NDToSpectrumResponseMatrix_l; } truncations++; } while (HasNegValue); +} - NDFD_Corrected_Spectrum_Hist = - static_cast(ND_Unfolded_Spectrum_Hist->Clone()); - NDFD_Corrected_Spectrum_Hist->Clear(); - NDFD_Corrected_Spectrum_Hist->SetName("NDFD_Corrected_Spectrum_Hist"); - FD_Propagated_Spectrum_Hist = - static_cast(ND_Unfolded_Spectrum_Hist->Clone()); - FD_Propagated_Spectrum_Hist->Clear(); - FD_Propagated_Spectrum_Hist->SetName("FD_Propagated_Spectrum_Hist"); - - // Apply FD/ND weights - // ------------------------------ - for (Int_t bi_it = 1; - bi_it < ND_Unfolded_Spectrum_Hist->GetXaxis()->GetNbins() + 1; ++bi_it) { - NDFD_Corrected_Spectrum_Hist->SetBinContent( - bi_it, ND_Unfolded_Spectrum_Hist->GetBinContent(bi_it) * NDFDRatio); - NDFD_Corrected_Spectrum_Hist->SetBinError( - bi_it, ND_Unfolded_Spectrum_Hist->GetBinError(bi_it) * NDFDRatio); +void Smear_SVDUnfold_Propagation_Osc::PropagateFDSample(size_t fds_it) { + if (fds_it >= FDSamples.size()) { + THROW("Requested FD sample index " << fds_it << " but only initialised " + << FDSamples.size()); } -} + FDSample &fds = FDSamples[fds_it]; -void Smear_SVDUnfold_Propagation_Osc::ConvertEventRates(void) { // Apply Oscillations // ------------------------------ FitWeight *fw = FitBase::GetRW(); OscWeightEngine *oscWE = dynamic_cast(fw->GetRWEngine(kOSCILLATION)); if (!oscWE) { THROW( "Couldn't load oscillation weight engine for sample: " "Smear_SVDUnfold_Propagation_Osc."); } for (Int_t bi_it = 1; - bi_it < NDFD_Corrected_Spectrum_Hist->GetXaxis()->GetNbins() + 1; + bi_it < fds.NDFD_Corrected_Spectrum_Hist->GetXaxis()->GetNbins() + 1; ++bi_it) { - double oscWeight = oscWE->CalcWeight( - NDFD_Corrected_Spectrum_Hist->GetXaxis()->GetBinCenter(bi_it), 14); - FD_Propagated_Spectrum_Hist->SetBinContent( - bi_it, NDFD_Corrected_Spectrum_Hist->GetBinContent(bi_it) * oscWeight); - FD_Propagated_Spectrum_Hist->SetBinError( - bi_it, NDFD_Corrected_Spectrum_Hist->GetBinError(bi_it) * oscWeight); + double content_osc = 0; + double error_osc = 0; + double content_fdnd = 0; + double error_fdnd = 0; + // Oscillate each ND sample to FD neutrino + for (size_t nd_it = 0; nd_it < NDSamples.size(); ++nd_it) { + NDSample &nds = NDSamples[nd_it]; + + double oscWeight = oscWE->CalcWeight( + nds.ND_Unfolded_Spectrum_Hist->GetXaxis()->GetBinCenter(bi_it), + nds.NuPDG, fds.OscillateToPDG); + + double sample_content_osc = + nds.ND_Unfolded_Spectrum_Hist->GetBinContent(bi_it) * oscWeight; + double sample_error_osc = + nds.ND_Unfolded_Spectrum_Hist->GetBinError(bi_it) * oscWeight; + + fds.FD_Propagated_Spectrum_Hist_NDSamples[nd_it]->SetBinContent( + bi_it, sample_content_osc); + fds.FD_Propagated_Spectrum_Hist_NDSamples[nd_it]->SetBinError( + bi_it, sample_error_osc); + + double sample_content_fdnd = + sample_content_osc * fds.FDNDRatios[nds.NuPDG] * fds.FDNDMassRatio; + double sample_error_fdnd = + sample_error_osc * fds.FDNDRatios[nds.NuPDG] * fds.FDNDMassRatio; + + fds.NDFD_Corrected_Spectrum_Hist_NDSamples[nd_it]->SetBinContent( + bi_it, sample_content_fdnd); + fds.NDFD_Corrected_Spectrum_Hist_NDSamples[nd_it]->SetBinError( + bi_it, sample_error_fdnd); + + content_osc += sample_content_osc; + error_osc += sample_error_osc * sample_error_osc; + + content_fdnd += sample_content_fdnd; + error_fdnd += sample_error_fdnd * sample_error_fdnd; + } + + fds.FD_Propagated_Spectrum_Hist->SetBinContent(bi_it, content_osc); + fds.FD_Propagated_Spectrum_Hist->SetBinError(bi_it, sqrt(error_osc)); + + fds.NDFD_Corrected_Spectrum_Hist->SetBinContent(bi_it, content_fdnd); + fds.NDFD_Corrected_Spectrum_Hist->SetBinError(bi_it, sqrt(error_fdnd)); } // Forward fold Spectrum -> ERec FD // ------------------------------ - SmearceptanceUtils::PushTH1ThroughMatrixWithErrors( - FD_Propagated_Spectrum_Hist, fMCHist, SpectrumToFDResponseMatrix, 1000, - true); - - fMCHist->SetBinContent(0, 0); - fMCHist->SetBinError(0, 0); + fds.NDFD_Corrected_Spectrum_Hist, fds.FD_Smeared_Spectrum_Hist, + fds.SpectrumToFDSmearingMatrix, 1000, true); +} - fMCHist->SetBinContent(fMCHist->GetXaxis()->GetNbins() + 1, 0); - fMCHist->SetBinError(fMCHist->GetXaxis()->GetNbins() + 1, 0); - for (Int_t bi_it = 1; bi_it < fMCHist->GetXaxis()->GetNbins() + 1; ++bi_it) { - if ((FitRegion_Min != 0xdeadbeef) && - (fMCHist->GetXaxis()->GetBinUpEdge(bi_it) <= FitRegion_Min)) { - fMCHist->SetBinContent(bi_it, 0); - fMCHist->SetBinError(bi_it, 0); - } - if ((FitRegion_Max != 0xdeadbeef) && - (fMCHist->GetXaxis()->GetBinLowEdge(bi_it) > FitRegion_Max)) { - fMCHist->SetBinContent(bi_it, 0); - fMCHist->SetBinError(bi_it, 0); - } +void Smear_SVDUnfold_Propagation_Osc::ConvertEventRates(void) { + for (size_t fds_it = 0; fds_it < FDSamples.size(); ++fds_it) { + PropagateFDSample(fds_it); } + UpdateChi2Hists(); } void Smear_SVDUnfold_Propagation_Osc::Write(std::string drawOpt) { - NDToSpectrumSmearingMatrix->Write("SmearingMatrix_ND", TObject::kOverwrite); + TDirectory *ogDir = gDirectory; - NDDataHist->Write("Obs_ND", TObject::kOverwrite); + ConvertEventRates(); - ND_Unfolded_Spectrum_Hist->Write(ND_Unfolded_Spectrum_Hist->GetName(), - TObject::kOverwrite); - NDFD_Corrected_Spectrum_Hist->Write(NDFD_Corrected_Spectrum_Hist->GetName(), - TObject::kOverwrite); - FD_Propagated_Spectrum_Hist->Write(FD_Propagated_Spectrum_Hist->GetName(), - TObject::kOverwrite); - - fMCHist->Write("Pred_FD", TObject::kOverwrite); - fDataHist->Write("Obs_FD", TObject::kOverwrite); - - // Apply Oscillations - // ------------------------------ FitWeight *fw = FitBase::GetRW(); OscWeightEngine *oscWE = dynamic_cast(fw->GetRWEngine(kOSCILLATION)); if (!oscWE) { THROW( "Couldn't load oscillation weight engine for sample: " "Smear_SVDUnfold_Propagation_Osc."); } + oscWE->Print(); + + // Write ND samples + //---------------- + for (size_t nd_it = 0; nd_it < NDSamples.size(); ++nd_it) { + NDSample &nds = NDSamples[nd_it]; + std::stringstream ss(""); + ss << "Smear_SVDUnfold_Propagation_Osc_NDSample_" << nd_it; + if (ogDir) { + ogDir->mkdir(ss.str().c_str()); + ogDir->cd(ss.str().c_str()); + } else { + FitPar::Config().out->mkdir(ss.str().c_str()); + FitPar::Config().out->cd(ss.str().c_str()); + } + + nds.NDToSpectrumSmearingMatrix->Write("SmearingMatrix_ND", + TObject::kOverwrite); + nds.NDDataHist->Write("Obs_ND", TObject::kOverwrite); + + nds.ND_Unfolded_Spectrum_Hist->Write( + nds.ND_Unfolded_Spectrum_Hist->GetName(), TObject::kOverwrite); + + if (ogDir) { + ogDir->cd(); + } else { + FitPar::Config().out->cd(); + } + } + + // Write FD samples + //---------------- + for (size_t fds_it = 0; fds_it < FDSamples.size(); ++fds_it) { + FDSample &fds = FDSamples[fds_it]; + + std::stringstream ss(""); + ss << "Smear_SVDUnfold_Propagation_Osc_FDSample_" << fds_it; + if (ogDir) { + ogDir->mkdir(ss.str().c_str()); + ogDir->cd(ss.str().c_str()); + } else { + FitPar::Config().out->mkdir(ss.str().c_str()); + FitPar::Config().out->cd(ss.str().c_str()); + } + + // Calc oscillation probability + // ------------------------------ + FitWeight *fw = FitBase::GetRW(); + OscWeightEngine *oscWE = + dynamic_cast(fw->GetRWEngine(kOSCILLATION)); + + if (!oscWE) { + THROW( + "Couldn't load oscillation weight engine for sample: " + "Smear_SVDUnfold_Propagation_Osc."); + } - TGraph POsc; + for (size_t nd_it = 0; nd_it < NDSamples.size(); ++nd_it) { + NDSample &nds = NDSamples[nd_it]; + ss.str(""); + ss << "NDSample_" << nd_it << "_contribution"; + fds.FD_Propagated_Spectrum_Hist_NDSamples[nd_it]->Write( + ss.str().c_str(), TObject::kOverwrite); + ss.str(""); + + ss << "NDSample_" << nd_it << "_FDNDCorrected_contribution"; + fds.NDFD_Corrected_Spectrum_Hist_NDSamples[nd_it]->Write( + ss.str().c_str(), TObject::kOverwrite); + + ss.str(""); + ss << "NDSample_" << nd_it << "_OscillationProb"; + + TGraph POsc; + + POsc.Set(1E4 - 1); + + double min = nds.ND_Unfolded_Spectrum_Hist->GetXaxis()->GetBinLowEdge(1); + double step = + (nds.ND_Unfolded_Spectrum_Hist->GetXaxis()->GetBinUpEdge( + nds.ND_Unfolded_Spectrum_Hist->GetXaxis()->GetNbins()) - + nds.ND_Unfolded_Spectrum_Hist->GetXaxis()->GetBinLowEdge(1)) / + double(1E4); + + for (size_t i = 1; i < 1E4; ++i) { + double enu = min + i * step; + double ow = oscWE->CalcWeight(enu, nds.NuPDG, fds.OscillateToPDG); + if (ow != ow) { + std::cout << "Bad osc weight for ENu: " << enu << std::endl; + } + POsc.SetPoint(i - 1, enu, ow); + } + + POsc.Write(ss.str().c_str(), TObject::kOverwrite); + } - POsc.Set(1E4 - 1); + fds.FDDataHist->Write("Obs_FD", TObject::kOverwrite); - double min = ND_Unfolded_Spectrum_Hist->GetXaxis()->GetBinLowEdge(1); - double step = (ND_Unfolded_Spectrum_Hist->GetXaxis()->GetBinUpEdge( - ND_Unfolded_Spectrum_Hist->GetXaxis()->GetNbins()) - - ND_Unfolded_Spectrum_Hist->GetXaxis()->GetBinLowEdge(1)) / - double(1E4); + fds.FD_Propagated_Spectrum_Hist->Write( + fds.FD_Propagated_Spectrum_Hist->GetName(), TObject::kOverwrite); - for (size_t i = 1; i < 1E4; ++i) { - double enu = min + i * step; - double ow = oscWE->CalcWeight(enu, 14); - if (ow != ow) { - std::cout << "Bad osc weight for ENu: " << enu << std::endl; + fds.NDFD_Corrected_Spectrum_Hist->Write( + fds.NDFD_Corrected_Spectrum_Hist->GetName(), TObject::kOverwrite); + + fds.SpectrumToFDSmearingMatrix_TH2->Write("SmearingMatrix_FD", + TObject::kOverwrite); + + fds.FD_Smeared_Spectrum_Hist->Write(fds.FD_Smeared_Spectrum_Hist->GetName(), + TObject::kOverwrite); + + if (ogDir) { + ogDir->cd(); + } else { + FitPar::Config().out->cd(); } - POsc.SetPoint(i - 1, enu, ow); } - POsc.Write("POsc", TObject::kOverwrite); + fMCHist->Write("Pred_FD", TObject::kOverwrite); + fDataHist->Write("Obs_FD", TObject::kOverwrite); + Measurement1D::Write(drawOpt); } diff --git a/src/MCStudies/Smear_SVDUnfold_Propagation_Osc.h b/src/MCStudies/Smear_SVDUnfold_Propagation_Osc.h index 5fd754b..874b081 100644 --- a/src/MCStudies/Smear_SVDUnfold_Propagation_Osc.h +++ b/src/MCStudies/Smear_SVDUnfold_Propagation_Osc.h @@ -1,61 +1,118 @@ // 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 Smear_SVDUnfold_Propagation_Osc_H_SEEN #define Smear_SVDUnfold_Propagation_Osc_H_SEEN #include "Measurement1D.h" - +/// Class for building simple oscillation analyses. +/// +/// An example tag which runs a FHC beam and performs a numudisp and nue app +/// measurement might look like: +/// +/// +/// +/// +/// +/// class Smear_SVDUnfold_Propagation_Osc : public Measurement1D { + struct FDSample { + TH1D *FDDataHist; + + std::vector FD_Propagated_Spectrum_Hist_NDSamples; + std::vector NDFD_Corrected_Spectrum_Hist_NDSamples; + + TH1D *FD_Propagated_Spectrum_Hist; + TH1D *NDFD_Corrected_Spectrum_Hist; + TH1D *FD_Smeared_Spectrum_Hist; + + TH2D *SpectrumToFDSmearingMatrix_TH2; + TMatrixD SpectrumToFDSmearingMatrix; + Int_t OscillateToPDG; + + double FitRegion_Min; + double FitRegion_Max; + std::map FDNDRatios; + double FDNDMassRatio; + + std::pair DetectorInfo; + }; + + struct NDSample { + TH1D *NDDataHist; + Int_t TruncateStart; + Int_t TruncateUpTo; + + TH1D *ND_Unfolded_Spectrum_Hist; + TH2D *NDToSpectrumSmearingMatrix; + + TMatrixD NDToSpectrumResponseMatrix; + + Int_t NuPDG; + + double XSecToEvRateScale; + }; + public: Smear_SVDUnfold_Propagation_Osc(nuiskey samplekey); virtual ~Smear_SVDUnfold_Propagation_Osc(){}; void FillEventVariables(FitEvent *event); bool isSignal(FitEvent *event); - void UnfoldToNDETrueSpectrum(void); + void UnfoldToNDETrueSpectrum(size_t); void ConvertEventRates(void); void Write(std::string drawOpt); - TH1D *NDDataHist; - TH1D *FDDataHist; - - TH1D *ND_Unfolded_Spectrum_Hist; - TH1D *NDFD_Corrected_Spectrum_Hist; - TH1D *FD_Propagated_Spectrum_Hist; + void ReadExtraConfig(nuiskey &samplekey); + void SetupChi2Hists(); + void UpdateChi2Hists(); - TH1D *ND_True_Spectrum_Hist; - TH1D *FD_True_Spectrum_Hist; + // ----- Near detector things + void AddNDInputs(nuiskey &samplekey); + void SetupNDInputs(); + std::vector NDSamples; - TH2D *NDToSpectrumSmearingMatrix; - - TMatrixD NDToSpectrumResponseMatrix; - TMatrixD SpectrumToFDResponseMatrix; - - Int_t TruncateStart; - Int_t TruncateUpTo; + std::pair NDetectorInfo; double FitRegion_Min; double FitRegion_Max; - double NDFDRatio; + // ----- Far detector things + Int_t NFDAnalysisBins; + Int_t GetFDSampleNAnalysisBins(size_t fds_it); + void AddFDTarget(nuiskey &nk); + void PropagateFDSample(size_t fds_it); + void FinaliseFDSamples(); + std::vector FDSamples; + + double ScalePOT; + + // ----- Other config + bool UseRateErrors; }; #endif diff --git a/src/MCStudies/Smearceptance_Tester.cxx b/src/MCStudies/Smearceptance_Tester.cxx index f93c17e..67677e2 100644 --- a/src/MCStudies/Smearceptance_Tester.cxx +++ b/src/MCStudies/Smearceptance_Tester.cxx @@ -1,711 +1,785 @@ // 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 . *******************************************************************************/ #include "Smearceptance_Tester.h" #include "SmearceptanceUtils.h" #include "Smearcepterton.h" #define DEBUG_SMEARTESTER //******************************************************************** /// @brief Class to perform smearceptance MC Studies on a custom measurement Smearceptance_Tester::Smearceptance_Tester(nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "Simple measurement class for producing an event summary tree of smeared " "events.\n"; if (Config::Get().GetConfigNode("NPOT")) { samplekey.SetS("NPOT", Config::Get().ConfS("NPOT")); } if (Config::Get().GetConfigNode("FluxIntegralOverride")) { samplekey.SetS("FluxIntegralOverride", Config::Get().ConfS("FluxIntegralOverride")); } if (Config::Get().GetConfigNode("TargetVolume")) { samplekey.SetS("TargetVolume", Config::Get().ConfS("TargetVolume")); } if (Config::Get().GetConfigNode("TargetMaterialDensity")) { samplekey.SetS("TargetMaterialDensity", Config::Get().ConfS("TargetMaterialDensity")); } + + OutputSummaryTree = true; + if (Config::Get().GetConfigNode("smear.OutputSummaryTree")) { + OutputSummaryTree = Config::Get().ConfI("smear.OutputSummaryTree"); + } + // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetTitle("Smearceptance Studies"); fSettings.SetDescription(descrip); fSettings.SetXTitle("XXX"); fSettings.SetYTitle("Number of events"); fSettings.SetEnuRange(0.0, 1E5); fSettings.SetAllowedTypes("EVT/SHAPE/DIAG", "EVT/SHAPE/DIAG"); fSettings.DefineAllowedTargets("*"); fSettings.DefineAllowedSpecies("*"); FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon fScaleFactor = (GetEventHistogram()->Integral("width") * 1E-38 / (fNEvents + 0.)) / TotalIntegratedFlux(); // Measurement Details std::vector splitName = GeneralUtils::ParseToStr(fName, "_"); size_t firstUS = fName.find_first_of("_"); std::string smearceptorName = fName.substr(firstUS + 1); fDataHist = new TH1D(("empty_data"), ("empty-data"), 1, 0, 1); SetupDefaultHist(); fFullCovar = StatUtils::MakeDiagonalCovarMatrix(fDataHist); covar = StatUtils::GetInvert(fFullCovar); eventVariables = NULL; LOG(SAM) << "Smearceptance Flux Scaling Factor = " << fScaleFactor << std::endl; if (fScaleFactor <= 0.0) { ERR(WRN) << "SCALE FACTOR TOO LOW " << std::endl; sleep(20); } // Setup our TTrees AddEventVariablesToTree(); smearceptor = &Smearcepterton::Get().GetSmearcepter(smearceptorName); Int_t RecNBins = 20, TrueNBins = 20; - double RecBinL = 0, TrueBinL = 0, RecBinH = 10, TrueBinH = 10; + double RecBinL = 0xdeadbeef, TrueBinL = 0, RecBinH = 10, TrueBinH = 10; if (Config::Get().GetConfigNode("smear.reconstructed.binning")) { std::vector args = GeneralUtils::ParseToStr( Config::Get().ConfS("smear.reconstructed.binning"), ","); RecNBins = GeneralUtils::StrToInt(args[0]); RecBinL = GeneralUtils::StrToDbl(args[1]); RecBinH = GeneralUtils::StrToDbl(args[2]); TrueNBins = RecNBins; TrueBinL = RecBinL; TrueBinH = RecBinH; } if (Config::Get().GetConfigNode("smear.true.binning")) { std::vector args = GeneralUtils::ParseToStr( Config::Get().ConfS("smear.true.binning"), ","); TrueNBins = GeneralUtils::StrToInt(args[0]); TrueBinL = GeneralUtils::StrToDbl(args[1]); TrueBinH = GeneralUtils::StrToDbl(args[2]); } SVDTruncation = 0; if (Config::Get().GetConfigNode("smear.true.binning")) { SVDTruncation = Config::Get().ConfI("smear.SVD.truncation"); QLOG(SAM, "Applying SVD truncation of: " << SVDTruncation) } - QLOG(SAM, "Using binning True: " << TrueNBins << ", [" << TrueBinL << " -- " - << TrueBinH << "], Rec: " << RecNBins - << ", [" << RecBinL << " -- " << RecBinH - << "]"); - - ETrueDistrib = new TH1D("ELep_rate", ";True E_{#nu};Count", TrueNBins, - TrueBinL, TrueBinH); - ERecDistrib = new TH1D("ELepRec_rate", ";Rec E_{#nu};Count", RecNBins, - RecBinL, RecBinH); - ETrueDistrib->Sumw2(); - ERecDistrib->Sumw2(); - - RecoSmear = - new TH2D("ELepHadVis_Recon", ";True E_{#nu};Recon. E_{#nu}", RecNBins, - RecBinL, RecBinH, TrueNBins, TrueBinL, TrueBinH); - RecoSmear->Sumw2(); + ETrueDistrib = NULL; + ETrueDistrib_noweight = NULL; + ERecDistrib = NULL; + RecoSmear = NULL; + if (RecBinL != 0xdeadbeef) { + QLOG(SAM, "Using binning True: " << TrueNBins << ", [" << TrueBinL << " -- " + << TrueBinH << "], Rec: " << RecNBins + << ", [" << RecBinL << " -- " << RecBinH + << "]"); + + ETrueDistrib = new TH1D("ELep_rate", ";True E_{#nu};Count", TrueNBins, + TrueBinL, TrueBinH); + ETrueDistrib_noweight = + new TH1D("ELep_rate_noweight", ";True E_{#nu};Count", TrueNBins, + TrueBinL, TrueBinH); + ERecDistrib = new TH1D("ELepRec_rate", ";Rec E_{#nu};Count", RecNBins, + RecBinL, RecBinH); + ETrueDistrib->Sumw2(); + ERecDistrib->Sumw2(); + + RecoSmear = + new TH2D("ELepHadVis_Recon", ";True E_{#nu};Recon. E_{#nu}", RecNBins, + RecBinL, RecBinH, TrueNBins, TrueBinL, TrueBinH); + RecoSmear->Sumw2(); + } // Final setup --------------------------------------------------- FinaliseMeasurement(); } void Smearceptance_Tester::AddEventVariablesToTree() { - // Setup the TTree to save everything - if (!eventVariables) { - FitPar::Config().out->cd(); - eventVariables = - new TTree((fName + "_VARS").c_str(), (fName + "_VARS").c_str()); - } - - LOG(SAM) << "Adding Event Variables" << std::endl; - - eventVariables->Branch("Omega_true", &Omega_true, "Omega_true/F"); - eventVariables->Branch("Q2_true", &Q2_true, "Q2_true/F"); - eventVariables->Branch("Mode_true", &Mode_true, "Mode_true/I"); - - eventVariables->Branch("EISLep_true", &EISLep_true, "EISLep_true/F"); - - eventVariables->Branch("HMFS_mu_true", &HMFS_mu_true); - eventVariables->Branch("HMFS_pip_true", &HMFS_pip_true); - eventVariables->Branch("HMFS_pim_true", &HMFS_pim_true); - eventVariables->Branch("HMFS_cpi_true", &HMFS_cpi_true); - eventVariables->Branch("HMFS_p_true", &HMFS_p_true); - - eventVariables->Branch("KEFSHad_cpip_true", &KEFSHad_cpip_true, - "KEFSHad_cpip_true/F"); - eventVariables->Branch("KEFSHad_cpim_true", &KEFSHad_cpim_true, - "KEFSHad_cpim_true/F"); - eventVariables->Branch("KEFSHad_cpi_true", &KEFSHad_cpi_true, - "KEFSHad_cpi_true/F"); - eventVariables->Branch("TEFSHad_pi0_true", &TEFSHad_pi0_true, - "TEFSHad_pi0_true/F"); - eventVariables->Branch("KEFSHad_p_true", &KEFSHad_p_true, "KEFSHad_p_true/F"); - eventVariables->Branch("KEFSHad_n_true", &KEFSHad_n_true, "KEFSHad_n_true/F"); - - eventVariables->Branch("EFSHad_true", &EFSHad_true, "EFSHad_true/F"); - eventVariables->Branch("EFSChargedEMHad_true", &EFSChargedEMHad_true, - "EFSChargedEMHad_true/F"); - - eventVariables->Branch("EFSLep_true", &EFSLep_true, "EFSLep_true/F"); - eventVariables->Branch("EFSgamma_true", &EFSgamma_true, "EFSgamma_true/F"); - - eventVariables->Branch("PDGISLep_true", &PDGISLep_true, "PDGISLep_true/I"); - eventVariables->Branch("PDGFSLep_true", &PDGFSLep_true, "PDGFSLep_true/I"); - - eventVariables->Branch("Nprotons_true", &Nprotons_true, "Nprotons_true/I"); - eventVariables->Branch("Nneutrons_true", &Nneutrons_true, "Nneutrons_true/I"); - eventVariables->Branch("Ncpiplus_true", &Ncpiplus_true, "Ncpiplus_true/I"); - eventVariables->Branch("Ncpiminus_true", &Ncpiminus_true, "Ncpiminus_true/I"); - eventVariables->Branch("Ncpi_true", &Ncpi_true, "Ncpi_true/I"); - eventVariables->Branch("Npi0_true", &Npi0_true, "Npi0_true/I"); - - eventVariables->Branch("HMFS_mu_rec", &HMFS_mu_rec); - eventVariables->Branch("HMFS_pip_rec", &HMFS_pip_rec); - eventVariables->Branch("HMFS_pim_rec", &HMFS_pim_rec); - eventVariables->Branch("HMFS_cpi_rec", &HMFS_cpi_rec); - eventVariables->Branch("HMFS_p_rec", &HMFS_p_rec); - - eventVariables->Branch("KEFSHad_cpip_rec", &KEFSHad_cpip_rec, - "KEFSHad_cpip_rec/F"); - eventVariables->Branch("KEFSHad_cpim_rec", &KEFSHad_cpim_rec, - "KEFSHad_cpim_rec/F"); - eventVariables->Branch("KEFSHad_cpi_rec", &KEFSHad_cpi_rec, - "KEFSHad_cpi_rec/F"); - eventVariables->Branch("TEFSHad_pi0_rec", &TEFSHad_pi0_rec, - "TEFSHad_pi0_rec/F"); - eventVariables->Branch("KEFSHad_p_rec", &KEFSHad_p_rec, "KEFSHad_p_rec/F"); - eventVariables->Branch("KEFSHad_n_rec", &KEFSHad_n_rec, "KEFSHad_n_rec/F"); - - eventVariables->Branch("EFSHad_rec", &EFSHad_rec, "EFSHad_rec/F"); - eventVariables->Branch("EFSLep_rec", &EFSLep_rec, "EFSLep_rec/F"); - - eventVariables->Branch("EFSVis_cpip", &EFSVis_cpip, "EFSVis_cpip/F"); - eventVariables->Branch("EFSVis_cpim", &EFSVis_cpim, "EFSVis_cpim/F"); - eventVariables->Branch("EFSVis_cpi", &EFSVis_cpi, "EFSVis_cpi/F"); - eventVariables->Branch("EFSVis_pi0", &EFSVis_pi0, "EFSVis_pi0/F"); - eventVariables->Branch("EFSVis_p", &EFSVis_p, "EFSVis_p/F"); - eventVariables->Branch("EFSVis_n", &EFSVis_n, "EFSVis_n/F"); - eventVariables->Branch("EFSVis_gamma", &EFSVis_gamma, "EFSVis_gamma/F"); - eventVariables->Branch("EFSVis_other", &EFSVis_other, "EFSVis_other/F"); - eventVariables->Branch("EFSVis", &EFSVis, "EFSVis/F"); - - eventVariables->Branch("FSCLep_seen", &FSCLep_seen, "FSCLep_seen/I"); - eventVariables->Branch("Nprotons_seen", &Nprotons_seen, "Nprotons_seen/I"); - eventVariables->Branch("Nneutrons_seen", &Nneutrons_seen, "Nneutrons_seen/I"); - eventVariables->Branch("Ncpip_seen", &Ncpip_seen, "Ncpip_seen/I"); - eventVariables->Branch("Ncpim_seen", &Ncpim_seen, "Ncpim_seen/I"); - eventVariables->Branch("Ncpi_seen", &Ncpi_seen, "Ncpi_seen/I"); - eventVariables->Branch("Npi0_seen", &Npi0_seen, "Npi0_seen/I"); - eventVariables->Branch("Nothers_seen", &Nothers_seen, "Nothers_seen/I"); - - eventVariables->Branch("EISLep_QE_rec", &EISLep_QE_rec, "EISLep_QE_rec/F"); - eventVariables->Branch("EISLep_LepHad_rec", &EISLep_LepHad_rec, - "EISLep_LepHad_rec/F"); - eventVariables->Branch("EISLep_LepHadVis_rec", &EISLep_LepHadVis_rec, - "EISLep_LepHadVis_rec/F"); - - eventVariables->Branch("Nprotons_contributed", &Nprotons_contributed, - "Nprotons_contributed/I"); - eventVariables->Branch("Nneutrons_contributed", &Nneutrons_contributed, - "Nneutrons_contributed/I"); - eventVariables->Branch("Ncpip_contributed", &Ncpip_contributed, - "Ncpip_contributed/I"); - eventVariables->Branch("Ncpim_contributed", &Ncpim_contributed, - "Ncpim_contributed/I"); - eventVariables->Branch("Ncpi_contributed", &Ncpi_contributed, - "Ncpi_contributed/I"); - eventVariables->Branch("Npi0_contributed", &Npi0_contributed, - "Npi0_contributed/I"); - eventVariables->Branch("Ngamma_contributed", &Ngamma_contributed, - "Ngamma_contributed/I"); - eventVariables->Branch("Nothers_contibuted", &Nothers_contibuted, - "Nothers_contibuted/I"); - - eventVariables->Branch("Weight", &Weight, "Weight/F"); - eventVariables->Branch("RWWeight", &RWWeight, "RWWeight/F"); - eventVariables->Branch("InputWeight", &InputWeight, "InputWeight/F"); - eventVariables->Branch("FluxWeight", &FluxWeight, "FluxWeight/F"); - eventVariables->Branch("EffWeight", &EffWeight, "EffWeight/F"); - - xsecScaling = fScaleFactor; - eventVariables->Branch("xsecScaling", &xsecScaling, "xsecScaling/F"); - - eventVariables->Branch("flagCCINC_true", &flagCCINC_true, "flagCCINC_true/O"); - eventVariables->Branch("flagCC0Pi_true", &flagCC0Pi_true, "flagCC0Pi_true/O"); - - eventVariables->Branch("flagCCINC_rec", &flagCCINC_rec, "flagCCINC_rec/O"); - eventVariables->Branch("flagCC0Pi_rec", &flagCC0Pi_rec, "flagCC0Pi_rec/O"); + if (OutputSummaryTree) { + // Setup the TTree to save everything + if (!eventVariables) { + FitPar::Config().out->cd(); + eventVariables = + new TTree((fName + "_VARS").c_str(), (fName + "_VARS").c_str()); + } + + LOG(SAM) << "Adding Event Variables" << std::endl; + + eventVariables->Branch("Omega_true", &Omega_true, "Omega_true/F"); + eventVariables->Branch("Q2_true", &Q2_true, "Q2_true/F"); + eventVariables->Branch("Mode_true", &Mode_true, "Mode_true/I"); + + eventVariables->Branch("EISLep_true", &EISLep_true, "EISLep_true/F"); + + eventVariables->Branch("HMFS_mu_true", &HMFS_mu_true); + eventVariables->Branch("HMFS_pip_true", &HMFS_pip_true); + eventVariables->Branch("HMFS_pim_true", &HMFS_pim_true); + eventVariables->Branch("HMFS_cpi_true", &HMFS_cpi_true); + eventVariables->Branch("HMFS_p_true", &HMFS_p_true); + + eventVariables->Branch("KEFSHad_cpip_true", &KEFSHad_cpip_true, + "KEFSHad_cpip_true/F"); + eventVariables->Branch("KEFSHad_cpim_true", &KEFSHad_cpim_true, + "KEFSHad_cpim_true/F"); + eventVariables->Branch("KEFSHad_cpi_true", &KEFSHad_cpi_true, + "KEFSHad_cpi_true/F"); + eventVariables->Branch("TEFSHad_pi0_true", &TEFSHad_pi0_true, + "TEFSHad_pi0_true/F"); + eventVariables->Branch("KEFSHad_p_true", &KEFSHad_p_true, + "KEFSHad_p_true/F"); + eventVariables->Branch("KEFSHad_n_true", &KEFSHad_n_true, + "KEFSHad_n_true/F"); + + eventVariables->Branch("EFSHad_true", &EFSHad_true, "EFSHad_true/F"); + eventVariables->Branch("EFSChargedEMHad_true", &EFSChargedEMHad_true, + "EFSChargedEMHad_true/F"); + + eventVariables->Branch("EFSLep_true", &EFSLep_true, "EFSLep_true/F"); + eventVariables->Branch("EFSgamma_true", &EFSgamma_true, "EFSgamma_true/F"); + + eventVariables->Branch("PDGISLep_true", &PDGISLep_true, "PDGISLep_true/I"); + eventVariables->Branch("PDGFSLep_true", &PDGFSLep_true, "PDGFSLep_true/I"); + + eventVariables->Branch("Nprotons_true", &Nprotons_true, "Nprotons_true/I"); + eventVariables->Branch("Nneutrons_true", &Nneutrons_true, + "Nneutrons_true/I"); + eventVariables->Branch("Ncpiplus_true", &Ncpiplus_true, "Ncpiplus_true/I"); + eventVariables->Branch("Ncpiminus_true", &Ncpiminus_true, + "Ncpiminus_true/I"); + eventVariables->Branch("Ncpi_true", &Ncpi_true, "Ncpi_true/I"); + eventVariables->Branch("Npi0_true", &Npi0_true, "Npi0_true/I"); + + eventVariables->Branch("HMFS_mu_rec", &HMFS_mu_rec); + eventVariables->Branch("HMFS_pip_rec", &HMFS_pip_rec); + eventVariables->Branch("HMFS_pim_rec", &HMFS_pim_rec); + eventVariables->Branch("HMFS_cpi_rec", &HMFS_cpi_rec); + eventVariables->Branch("HMFS_p_rec", &HMFS_p_rec); + + eventVariables->Branch("KEFSHad_cpip_rec", &KEFSHad_cpip_rec, + "KEFSHad_cpip_rec/F"); + eventVariables->Branch("KEFSHad_cpim_rec", &KEFSHad_cpim_rec, + "KEFSHad_cpim_rec/F"); + eventVariables->Branch("KEFSHad_cpi_rec", &KEFSHad_cpi_rec, + "KEFSHad_cpi_rec/F"); + eventVariables->Branch("TEFSHad_pi0_rec", &TEFSHad_pi0_rec, + "TEFSHad_pi0_rec/F"); + eventVariables->Branch("KEFSHad_p_rec", &KEFSHad_p_rec, "KEFSHad_p_rec/F"); + eventVariables->Branch("KEFSHad_n_rec", &KEFSHad_n_rec, "KEFSHad_n_rec/F"); + + eventVariables->Branch("EFSHad_rec", &EFSHad_rec, "EFSHad_rec/F"); + eventVariables->Branch("EFSLep_rec", &EFSLep_rec, "EFSLep_rec/F"); + + eventVariables->Branch("EFSVis_cpip", &EFSVis_cpip, "EFSVis_cpip/F"); + eventVariables->Branch("EFSVis_cpim", &EFSVis_cpim, "EFSVis_cpim/F"); + eventVariables->Branch("EFSVis_cpi", &EFSVis_cpi, "EFSVis_cpi/F"); + eventVariables->Branch("EFSVis_pi0", &EFSVis_pi0, "EFSVis_pi0/F"); + eventVariables->Branch("EFSVis_p", &EFSVis_p, "EFSVis_p/F"); + eventVariables->Branch("EFSVis_n", &EFSVis_n, "EFSVis_n/F"); + eventVariables->Branch("EFSVis_gamma", &EFSVis_gamma, "EFSVis_gamma/F"); + eventVariables->Branch("EFSVis_other", &EFSVis_other, "EFSVis_other/F"); + eventVariables->Branch("EFSVis", &EFSVis, "EFSVis/F"); + + eventVariables->Branch("FSCLep_seen", &FSCLep_seen, "FSCLep_seen/I"); + eventVariables->Branch("Nprotons_seen", &Nprotons_seen, "Nprotons_seen/I"); + eventVariables->Branch("Nneutrons_seen", &Nneutrons_seen, + "Nneutrons_seen/I"); + eventVariables->Branch("Ncpip_seen", &Ncpip_seen, "Ncpip_seen/I"); + eventVariables->Branch("Ncpim_seen", &Ncpim_seen, "Ncpim_seen/I"); + eventVariables->Branch("Ncpi_seen", &Ncpi_seen, "Ncpi_seen/I"); + eventVariables->Branch("Npi0_seen", &Npi0_seen, "Npi0_seen/I"); + eventVariables->Branch("Nothers_seen", &Nothers_seen, "Nothers_seen/I"); + + eventVariables->Branch("EISLep_QE_rec", &EISLep_QE_rec, "EISLep_QE_rec/F"); + eventVariables->Branch("EISLep_LepHad_rec", &EISLep_LepHad_rec, + "EISLep_LepHad_rec/F"); + eventVariables->Branch("EISLep_LepHadVis_rec", &EISLep_LepHadVis_rec, + "EISLep_LepHadVis_rec/F"); + + eventVariables->Branch("Nprotons_contributed", &Nprotons_contributed, + "Nprotons_contributed/I"); + eventVariables->Branch("Nneutrons_contributed", &Nneutrons_contributed, + "Nneutrons_contributed/I"); + eventVariables->Branch("Ncpip_contributed", &Ncpip_contributed, + "Ncpip_contributed/I"); + eventVariables->Branch("Ncpim_contributed", &Ncpim_contributed, + "Ncpim_contributed/I"); + eventVariables->Branch("Ncpi_contributed", &Ncpi_contributed, + "Ncpi_contributed/I"); + eventVariables->Branch("Npi0_contributed", &Npi0_contributed, + "Npi0_contributed/I"); + eventVariables->Branch("Ngamma_contributed", &Ngamma_contributed, + "Ngamma_contributed/I"); + eventVariables->Branch("Nothers_contibuted", &Nothers_contibuted, + "Nothers_contibuted/I"); + + eventVariables->Branch("Weight", &Weight, "Weight/F"); + eventVariables->Branch("RWWeight", &RWWeight, "RWWeight/F"); + eventVariables->Branch("InputWeight", &InputWeight, "InputWeight/F"); + eventVariables->Branch("FluxWeight", &FluxWeight, "FluxWeight/F"); + eventVariables->Branch("EffWeight", &EffWeight, "EffWeight/F"); + + xsecScaling = fScaleFactor; + eventVariables->Branch("xsecScaling", &xsecScaling, "xsecScaling/F"); + + eventVariables->Branch("flagCCINC_true", &flagCCINC_true, + "flagCCINC_true/O"); + eventVariables->Branch("flagCC0Pi_true", &flagCC0Pi_true, + "flagCC0Pi_true/O"); + eventVariables->Branch("flagCC1Pi_true", &flagCC1Pi_true, + "flagCC1Pi_true/O"); + + eventVariables->Branch("flagCCINC_rec", &flagCCINC_rec, "flagCCINC_rec/O"); + eventVariables->Branch("flagCC0Pi_rec", &flagCC0Pi_rec, "flagCC0Pi_rec/O"); + eventVariables->Branch("flagCC1Pi_rec", &flagCC1Pi_rec, "flagCC1Pi_rec/O"); + } + PredEvtRateWeight = 1; if (fEvtRateScaleFactor != 0xdeadbeef) { - eventVariables->Branch("PredEvtRateWeight", &PredEvtRateWeight, - "PredEvtRateWeight/F"); + if (OutputSummaryTree) { + eventVariables->Branch("PredEvtRateWeight", &PredEvtRateWeight, + "PredEvtRateWeight/F"); + } PredEvtRateWeight = fScaleFactor * fEvtRateScaleFactor; } } template int CountNPdgsSeen(RecoInfo ri, int const (&pdgs)[N]) { int sum = 0; for (size_t pdg_it = 0; pdg_it < N; ++pdg_it) { sum += std::count(ri.RecObjClass.begin(), ri.RecObjClass.end(), pdgs[pdg_it]); } return sum; } template int CountNNotPdgsSeen(RecoInfo ri, int const (&pdgs)[N]) { int sum = 0; for (size_t pdg_it = 0; pdg_it < N; ++pdg_it) { sum += (std::count(ri.RecObjClass.begin(), ri.RecObjClass.end(), pdgs[pdg_it]) ? 0 : 1); } return sum; } template int CountNPdgsContributed(RecoInfo ri, int const (&pdgs)[N]) { int sum = 0; for (size_t pdg_it = 0; pdg_it < N; ++pdg_it) { sum += std::count(ri.TrueContribPDGs.begin(), ri.TrueContribPDGs.end(), pdgs[pdg_it]); } return sum; } template int CountNNotPdgsContributed(RecoInfo ri, int const (&pdgs)[N]) { int sum = 0; for (size_t pdg_it = 0; pdg_it < N; ++pdg_it) { sum += (std::count(ri.TrueContribPDGs.begin(), ri.TrueContribPDGs.end(), pdgs[pdg_it]) ? 0 : 1); } return sum; } TLorentzVector GetHMFSRecParticles(RecoInfo ri, int pdg) { TLorentzVector mom(0, 0, 0, 0); for (size_t p_it = 0; p_it < ri.RecObjMom.size(); ++p_it) { if ((ri.RecObjClass[p_it] == pdg) && (mom.Mag() < ri.RecObjMom[p_it].Mag())) { mom.SetXYZM(ri.RecObjMom[p_it].X(), ri.RecObjMom[p_it].Y(), ri.RecObjMom[p_it].Z(), PhysConst::GetMass(ri.RecObjClass[p_it]) * 1.0E3); } } return mom; } template double SumKE_RecoInfo(RecoInfo ri, int const (&pdgs)[N], double mass) { double sum = 0; for (size_t p_it = 0; p_it < ri.RecObjMom.size(); ++p_it) { if (!std::count(pdgs, pdgs + N, ri.RecObjClass[p_it])) { // If we don't care about this // particle type. continue; } sum += sqrt(ri.RecObjMom[p_it].Mag2() + mass * mass) - mass; } return sum; } template double SumTE_RecoInfo(RecoInfo ri, int const (&pdgs)[N], double mass) { double sum = 0; for (size_t p_it = 0; p_it < ri.RecObjMom.size(); ++p_it) { if (!std::count(pdgs, pdgs + N, ri.RecObjClass[p_it])) { // If we don't care about this // particle type. continue; } sum += sqrt(ri.RecObjMom[p_it].Mag2() + mass * mass); } return sum; } template double SumVisE_RecoInfo(RecoInfo ri, int const (&pdgs)[N]) { double sum = 0; for (size_t p_it = 0; p_it < ri.RecVisibleEnergy.size(); ++p_it) { if (!std::count(pdgs, pdgs + N, ri.TrueContribPDGs[p_it])) { // If we don't care about this // particle type. continue; } sum += ri.RecVisibleEnergy[p_it]; } return sum; } template double SumVisE_RecoInfo_NotPdgs(RecoInfo ri, int const (&pdgs)[N]) { double sum = 0; for (size_t p_it = 0; p_it < ri.RecVisibleEnergy.size(); ++p_it) { if (std::count(pdgs, pdgs + N, ri.TrueContribPDGs[p_it])) { // If we know about this // particle type. continue; } sum += ri.RecVisibleEnergy[p_it]; } return sum; } //******************************************************************** void Smearceptance_Tester::FillEventVariables(FitEvent *event) { //******************************************************************** static int const cpipPDG[] = {211}; static int const cpimPDG[] = {-211}; static int const pi0PDG[] = {111}; static int const ProtonPDG[] = {2212}; static int const NeutronPDG[] = {2112}; static int const GammaPDG[] = {22}; static int const CLeptonPDGs[] = {11, 13, 15}; static int const ExplicitPDGs[] = {211, -211, 111, 2212, 2112, 22, 11, 13, 15, 12, 14, 16}; RecoInfo *ri = smearceptor->Smearcept(event); HMFS_mu_true = TLorentzVector(0, 0, 0, 0); HMFS_mu_rec = TLorentzVector(0, 0, 0, 0); FitParticle *fsMu = event->GetHMFSMuon(); if (fsMu) { HMFS_mu_true = fsMu->P4(); HMFS_mu_rec = GetHMFSRecParticles(*ri, 13); } HMFS_pip_true = TLorentzVector(0, 0, 0, 0); HMFS_pip_rec = TLorentzVector(0, 0, 0, 0); FitParticle *fsPip = event->GetHMFSPiPlus(); if (fsPip) { HMFS_pip_true = fsPip->P4(); HMFS_pip_rec = GetHMFSRecParticles(*ri, 211); } HMFS_pim_true = TLorentzVector(0, 0, 0, 0); HMFS_pim_rec = TLorentzVector(0, 0, 0, 0); FitParticle *fsPim = event->GetHMFSPiMinus(); if (fsPim) { HMFS_pim_true = fsPim->P4(); HMFS_pim_rec = GetHMFSRecParticles(*ri, -211); } HMFS_cpi_true = TLorentzVector(0, 0, 0, 0); HMFS_cpi_rec = TLorentzVector(0, 0, 0, 0); if (fsPip || fsPim) { if (!fsPip) { HMFS_cpi_true = HMFS_pim_true; HMFS_cpi_rec = HMFS_pim_rec; } else if (!fsPim) { HMFS_cpi_true = HMFS_pip_true; HMFS_cpi_rec = HMFS_pip_rec; } else { HMFS_cpi_true = (fsPip->p2() > fsPim->p2()) ? HMFS_pip_true : HMFS_pim_true; HMFS_cpi_rec = (fsPip->p2() > fsPim->p2()) ? HMFS_pip_rec : HMFS_pim_rec; } } HMFS_p_true = TLorentzVector(0, 0, 0, 0); HMFS_p_rec = TLorentzVector(0, 0, 0, 0); FitParticle *fsP = event->GetHMFSProton(); if (fsP) { HMFS_p_true = fsP->P4(); HMFS_p_rec = GetHMFSRecParticles(*ri, 2212); } TLorentzVector FourMomentumTransfer = (event->GetHMISAnyLeptons()->P4() - event->GetHMFSAnyLeptons()->P4()); Omega_true = FourMomentumTransfer.E(); Q2_true = -1 * FourMomentumTransfer.Mag2(); Mode_true = event->Mode; EISLep_true = event->GetHMISAnyLeptons()->E(); KEFSHad_cpip_true = FitUtils::SumTE_PartVect(event->GetAllFSPiPlus()); KEFSHad_cpim_true = FitUtils::SumTE_PartVect(event->GetAllFSPiMinus()); KEFSHad_cpi_true = KEFSHad_cpip_true + KEFSHad_cpim_true; TEFSHad_pi0_true = FitUtils::SumTE_PartVect(event->GetAllFSPiZero()); KEFSHad_p_true = FitUtils::SumKE_PartVect(event->GetAllFSProton()); KEFSHad_n_true = FitUtils::SumKE_PartVect(event->GetAllFSNeutron()); EFSHad_true = KEFSHad_cpi_true + TEFSHad_pi0_true + KEFSHad_p_true + KEFSHad_n_true; EFSChargedEMHad_true = KEFSHad_cpi_true + TEFSHad_pi0_true + KEFSHad_p_true; EFSLep_true = event->GetHMFSAnyLeptons()->E(); EFSgamma_true = FitUtils::SumTE_PartVect(event->GetAllFSPhoton()); PDGISLep_true = event->GetHMISAnyLeptons()->PDG(); PDGFSLep_true = event->GetHMFSAnyLeptons()->PDG(); Nprotons_true = event->GetAllFSProton().size(); Nneutrons_true = event->GetAllFSNeutron().size(); Ncpiplus_true = event->GetAllFSPiPlus().size(); Ncpiminus_true = event->GetAllFSPiMinus().size(); Ncpi_true = Ncpiplus_true + Ncpiminus_true; Npi0_true = event->GetAllFSPiZero().size(); KEFSHad_cpip_rec = SumKE_RecoInfo(*ri, cpipPDG, PhysConst::mass_cpi * PhysConst::mass_MeV); KEFSHad_cpim_rec = SumKE_RecoInfo(*ri, cpimPDG, PhysConst::mass_cpi * PhysConst::mass_MeV); KEFSHad_cpi_rec = KEFSHad_cpip_rec + KEFSHad_cpim_rec; TEFSHad_pi0_rec = SumTE_RecoInfo(*ri, pi0PDG, PhysConst::mass_pi0 * PhysConst::mass_MeV); KEFSHad_p_rec = SumKE_RecoInfo(*ri, ProtonPDG, PhysConst::mass_proton * PhysConst::mass_MeV); KEFSHad_n_rec = SumKE_RecoInfo(*ri, NeutronPDG, PhysConst::mass_neutron * PhysConst::mass_MeV); EFSHad_rec = KEFSHad_cpi_rec + TEFSHad_pi0_rec + KEFSHad_p_rec + KEFSHad_n_rec; TLorentzVector FSLepMom_rec(0, 0, 0, 0); if (event->GetHMFSAnyLeptons()) { FSLepMom_rec = GetHMFSRecParticles(*ri, event->GetHMFSAnyLeptons()->PDG()); EFSLep_rec = FSLepMom_rec.E(); } else { EFSLep_rec = 0; } EFSVis_cpip = SumVisE_RecoInfo(*ri, cpipPDG); EFSVis_cpim = SumVisE_RecoInfo(*ri, cpimPDG); EFSVis_cpi = EFSVis_cpip + EFSVis_cpim; EFSVis_pi0 = SumVisE_RecoInfo(*ri, pi0PDG); EFSVis_p = SumVisE_RecoInfo(*ri, ProtonPDG); EFSVis_n = SumVisE_RecoInfo(*ri, NeutronPDG); EFSVis_gamma = SumVisE_RecoInfo(*ri, GammaPDG); EFSVis_other = SumVisE_RecoInfo_NotPdgs(*ri, ExplicitPDGs); EFSVis = EFSVis_cpi + EFSVis_pi0 + EFSVis_p + EFSVis_n + EFSVis_gamma; FSCLep_seen = CountNPdgsSeen(*ri, CLeptonPDGs); Nprotons_seen = CountNPdgsSeen(*ri, ProtonPDG); Nneutrons_seen = CountNPdgsSeen(*ri, NeutronPDG); Ncpip_seen = CountNPdgsSeen(*ri, cpipPDG); Ncpim_seen = CountNPdgsSeen(*ri, cpimPDG); Ncpi_seen = Ncpip_seen + Ncpim_seen; Npi0_seen = CountNPdgsSeen(*ri, pi0PDG); Nothers_seen = CountNNotPdgsSeen(*ri, ExplicitPDGs); if (FSCLep_seen && (FSLepMom_rec.Mag() > 1E-8)) { EISLep_QE_rec = FitUtils::EnuQErec(FSLepMom_rec.Mag() / 1000.0, FSLepMom_rec.CosTheta(), 34, PDGFSLep_true > 0) * 1000.0; } else { EISLep_QE_rec = 0; } EISLep_LepHad_rec = EFSLep_rec + EFSHad_rec; EISLep_LepHadVis_rec = EFSLep_rec + EFSHad_rec + EFSVis; Nprotons_contributed = CountNPdgsContributed(*ri, ProtonPDG); Nneutrons_contributed = CountNPdgsContributed(*ri, NeutronPDG); Ncpip_contributed = CountNPdgsContributed(*ri, cpipPDG); Ncpim_contributed = CountNPdgsContributed(*ri, cpimPDG); Ncpi_contributed = Ncpip_contributed + Ncpim_contributed; Npi0_contributed = CountNPdgsContributed(*ri, pi0PDG); Ngamma_contributed = CountNPdgsContributed(*ri, GammaPDG); Nothers_contibuted = CountNNotPdgsContributed(*ri, ExplicitPDGs); Weight = event->RWWeight * event->InputWeight; RWWeight = event->RWWeight; InputWeight = event->InputWeight; FluxWeight = GetFluxHistogram()->GetBinContent( GetFluxHistogram()->FindBin(EISLep_true)) / GetFluxHistogram()->Integral(); EffWeight = ri->Weight; flagCCINC_true = PDGFSLep_true & 1; flagCC0Pi_true = (Ncpi_true + Npi0_true) == 0; + flagCC1Pi_true = (Ncpi_true + Npi0_true) == 1; flagCCINC_rec = FSCLep_seen && PDGFSLep_true & 1; flagCC0Pi_rec = ((Ncpi_seen + Npi0_seen) == 0) && flagCCINC_rec; + flagCC1Pi_rec = ((Ncpi_seen + Npi0_seen) == 1) && flagCCINC_rec; - // Fill the eventVariables Tree - eventVariables->Fill(); + if (OutputSummaryTree) { + // Fill the eventVariables Tree + eventVariables->Fill(); + } - RecoSmear->Fill(EISLep_true / 1000.0, - flagCCINC_rec ? EISLep_LepHadVis_rec / 1000.0 : -1, Weight); - ETrueDistrib->Fill(EISLep_true / 1000.0, flagCCINC_true ? Weight : 0); + if (RecoSmear) { + RecoSmear->Fill(EISLep_true / 1000.0, + flagCCINC_rec ? EISLep_LepHadVis_rec / 1000.0 : -1, Weight); + ETrueDistrib_noweight->Fill(EISLep_true / 1000.0, + flagCCINC_true ? Weight : 0); - ERecDistrib->Fill(EISLep_LepHadVis_rec / 1000.0, flagCCINC_rec ? Weight : 0); + ETrueDistrib->Fill(EISLep_true / 1000.0, + flagCCINC_true ? Weight * PredEvtRateWeight : 0); - return; + ERecDistrib->Fill(EISLep_LepHadVis_rec / 1000.0, + flagCCINC_rec ? Weight * PredEvtRateWeight : 0); + } }; //******************************************************************** void Smearceptance_Tester::Write(std::string drawOpt) { //******************************************************************** - // First save the TTree - eventVariables->Write(); + if (OutputSummaryTree) { + // First save the TTree + eventVariables->Write(); + } // Save Flux and Event Histograms too GetInput()->GetFluxHistogram()->Write(); GetInput()->GetEventHistogram()->Write(); + if (!RecoSmear) { + return; + } + TH2D *SmearMatrix_ev = static_cast(RecoSmear->Clone("ELepHadVis_Smear_ev")); for (Int_t trueAxis_it = 1; trueAxis_it < RecoSmear->GetXaxis()->GetNbins() + 1; ++trueAxis_it) { - double NEISLep = ETrueDistrib->GetBinContent(trueAxis_it); + double NEISLep = ETrueDistrib_noweight->GetBinContent(trueAxis_it); for (Int_t recoAxis_it = 1; recoAxis_it < RecoSmear->GetYaxis()->GetNbins() + 1; ++recoAxis_it) { if (NEISLep > std::numeric_limits::epsilon()) { SmearMatrix_ev->SetBinContent( trueAxis_it, recoAxis_it, SmearMatrix_ev->GetBinContent(trueAxis_it, recoAxis_it) / NEISLep); } } } + ETrueDistrib_noweight->Write(); ETrueDistrib->Write(); ERecDistrib->Write(); RecoSmear->Write(); SmearMatrix_ev->Write(); TH2D *ResponseMatrix_ev = SmearceptanceUtils::SVDGetInverse(SmearMatrix_ev, SVDTruncation); ResponseMatrix_ev->SetName("ResponseMatrix_ev"); ResponseMatrix_ev->Write(); #ifdef DEBUG_SMEARTESTER TMatrixD SmearMatrix_ev_md = SmearceptanceUtils::GetMatrix(SmearMatrix_ev); TH1D *SmearedEvt = static_cast(ERecDistrib->Clone()); SmearedEvt->SetNameTitle("SmearedEvt", ";Rec E_{#nu}; count"); SmearceptanceUtils::PushTH1ThroughMatrixWithErrors( ETrueDistrib, SmearedEvt, SmearMatrix_ev_md, 5000, false); SmearedEvt->Write(); SmearedEvt->Scale(1, "width"); SmearedEvt->SetName("SmearedEvt_bw"); SmearedEvt->Write(); #endif + FitWeight *fw = FitBase::GetRW(); + if (fw->HasRWEngine(kOSCILLATION)) { + OscWeightEngine *oscWE = + dynamic_cast(fw->GetRWEngine(kOSCILLATION)); + TGraph POsc; + + POsc.Set(1E4 - 1); + + double min = ETrueDistrib->GetXaxis()->GetBinLowEdge(1); + double step = (ETrueDistrib->GetXaxis()->GetBinUpEdge( + ETrueDistrib->GetXaxis()->GetNbins()) - + ETrueDistrib->GetXaxis()->GetBinLowEdge(1)) / + double(1E4); + + for (size_t i = 1; i < 1E4; ++i) { + double enu = min + i * step; + double ow = oscWE->CalcWeight(enu, 14); + if (ow != ow) { + std::cout << "Bad osc weight for ENu: " << enu << std::endl; + } + POsc.SetPoint(i - 1, enu, ow); + } + + POsc.Write("POsc", TObject::kOverwrite); + } + TMatrixD ResponseMatrix_evt_md = SmearceptanceUtils::GetMatrix(ResponseMatrix_ev); TH1D *Unfolded_enu_obs = static_cast(ETrueDistrib->Clone()); Unfolded_enu_obs->SetNameTitle("UnfoldedENu_evt", ";True E_{#nu};count"); SmearceptanceUtils::PushTH1ThroughMatrixWithErrors( ERecDistrib, Unfolded_enu_obs, ResponseMatrix_evt_md, 5000, false); Unfolded_enu_obs->Write(); Unfolded_enu_obs->Scale(1, "width"); Unfolded_enu_obs->SetName("UnfoldedENu_evt_bw"); Unfolded_enu_obs->Write(); ETrueDistrib->Scale(1, "width"); ETrueDistrib->SetName("ELep_rate_bw"); ETrueDistrib->Write(); ERecDistrib->Scale(1, "width"); ERecDistrib->SetName("ELepRec_rate_bw"); ERecDistrib->Write(); } // ------------------------------------------------------------------- // Purely MC Plot // Following functions are just overrides to handle this // ------------------------------------------------------------------- //******************************************************************** /// Everything is classed as signal... bool Smearceptance_Tester::isSignal(FitEvent *event) { //******************************************************************** (void)event; return true; }; //******************************************************************** void Smearceptance_Tester::ScaleEvents() { //******************************************************************** // Saving everything to a TTree so no scaling required return; } //******************************************************************** void Smearceptance_Tester::ApplyNormScale(float norm) { //******************************************************************** // Saving everything to a TTree so no scaling required fCurrentNorm = norm; return; } //******************************************************************** void Smearceptance_Tester::FillHistograms() { //******************************************************************** // No Histograms need filling........ return; } //******************************************************************** void Smearceptance_Tester::ResetAll() { //******************************************************************** - eventVariables->Reset(); + if (OutputSummaryTree) { + eventVariables->Reset(); + } return; } //******************************************************************** float Smearceptance_Tester::GetChi2() { //******************************************************************** // No Likelihood to test, purely MC return 0.0; } diff --git a/src/MCStudies/Smearceptance_Tester.h b/src/MCStudies/Smearceptance_Tester.h index 3025580..dc471db 100644 --- a/src/MCStudies/Smearceptance_Tester.h +++ b/src/MCStudies/Smearceptance_Tester.h @@ -1,176 +1,181 @@ // 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 Smearceptance_Tester_H_SEEN #define Smearceptance_Tester_H_SEEN #include "Measurement1D.h" #include "ISmearcepter.h" #ifdef __PROB3PP_ENABLED__ #include "OscWeightEngine.h" #endif //******************************************************************** class Smearceptance_Tester : public Measurement1D { //******************************************************************** public: Smearceptance_Tester(nuiskey samplekey); virtual ~Smearceptance_Tester(){}; //! Grab info from event void FillEventVariables(FitEvent *event); //! Fill Custom Histograms void FillHistograms(); //! ResetAll void ResetAll(); //! Scale void ScaleEvents(); //! Norm void ApplyNormScale(float norm); //! Define this samples signal bool isSignal(FitEvent *nvect); //! Write Files void Write(std::string drawOpt); //! Get Chi2 float GetChi2(); void AddEventVariablesToTree(); private: ISmearcepter *smearceptor; TTree *eventVariables; float Omega_true; float Q2_true; int Mode_true; float EISLep_true; TLorentzVector HMFS_mu_true; TLorentzVector HMFS_pip_true; TLorentzVector HMFS_pim_true; TLorentzVector HMFS_cpi_true; TLorentzVector HMFS_p_true; float KEFSHad_cpip_true; float KEFSHad_cpim_true; float KEFSHad_cpi_true; float TEFSHad_pi0_true; float KEFSHad_p_true; float KEFSHad_n_true; float EFSHad_true; float EFSChargedEMHad_true; float EFSLep_true; float EFSgamma_true; int PDGISLep_true; int PDGFSLep_true; int Nprotons_true; int Nneutrons_true; int Ncpiplus_true; int Ncpiminus_true; int Ncpi_true; int Npi0_true; TLorentzVector HMFS_mu_rec; TLorentzVector HMFS_pip_rec; TLorentzVector HMFS_pim_rec; TLorentzVector HMFS_cpi_rec; TLorentzVector HMFS_p_rec; float KEFSHad_cpip_rec; float KEFSHad_cpim_rec; float KEFSHad_cpi_rec; float TEFSHad_pi0_rec; float KEFSHad_p_rec; float KEFSHad_n_rec; float EFSHad_rec; float EFSLep_rec; float EFSVis_cpip; float EFSVis_cpim; float EFSVis_cpi; float EFSVis_pi0; float EFSVis_p; float EFSVis_n; float EFSVis_gamma; float EFSVis_other; float EFSVis; int FSCLep_seen; int Nprotons_seen; int Nneutrons_seen; int Ncpip_seen; int Ncpim_seen; int Ncpi_seen; int Npi0_seen; int Nothers_seen; float EISLep_QE_rec; float EISLep_LepHad_rec; float EISLep_LepHadVis_rec; int Nprotons_contributed; int Nneutrons_contributed; int Ncpip_contributed; int Ncpim_contributed; int Ncpi_contributed; int Npi0_contributed; int Ngamma_contributed; int Nothers_contibuted; float Weight; float RWWeight; float InputWeight; float FluxWeight; float EffWeight; float PredEvtRateWeight; float xsecScaling; bool flagCCINC_true; bool flagCC0Pi_true; + bool flagCC1Pi_true; bool flagCCINC_rec; bool flagCC0Pi_rec; + bool flagCC1Pi_rec; + bool OutputSummaryTree; int SVDTruncation; TH2D *RecoSmear; TH1D *ETrueDistrib; + TH1D *ETrueDistrib_noweight; TH1D *ERecDistrib; + }; #endif diff --git a/src/MiniBooNE/MiniBooNE_CCQE_XSec_1DQ2_antinu.cxx b/src/MiniBooNE/MiniBooNE_CCQE_XSec_1DQ2_antinu.cxx index 8483e70..3ee0d65 100644 --- a/src/MiniBooNE/MiniBooNE_CCQE_XSec_1DQ2_antinu.cxx +++ b/src/MiniBooNE/MiniBooNE_CCQE_XSec_1DQ2_antinu.cxx @@ -1,196 +1,196 @@ // 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 . *******************************************************************************/ #include "MiniBooNE_CCQE_XSec_1DQ2_antinu.h" #include MiniBooNE_CCQE_XSec_1DQ2_antinu::MiniBooNE_CCQE_XSec_1DQ2_antinu(nuiskey samplekey) { // Sample overview std::string descrip = "MiniBooNE CCQE/CC0pi sample. \n" \ "Target: CH2.08 \n" \ "Flux: CCQE = Forward Horn Current numu \n" \ " CC0pi = Forward Horn Current numu+numub \n" \ "Signal: CCQE = True CCQE + True 2p2h (Mode == 1 or 2) \n" \ " CC0pi = Events with 1 mu+/mu-, N nucleons, 0 other"; // 1. Initalise sample Settings --------------------------------------- fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); fSettings.SetXTitle("Q^{2}_{QE} (GeV^{2})"); fSettings.SetYTitle("d#sigma/dQ_{QE}^{2} (cm^{2}/GeV^{2})"); fSettings.SetAllowedTypes("FIX,FREE,SHAPE/DIAG/NORM/MASK", "FIX/DIAG"); fSettings.SetEnuRange(0.0, 3.0); fSettings.SetSuggestedFlux( FitPar::GetDataBase() + "/MiniBooNE/ccqe/mb_ccqe_flux.root"); // Define input data information fSettings.FoundFill("name", "CCQELike", fCCQElike, true); fSettings.FoundFill("name", "CTarg", fUseCorrectedCTarget, true); if (fCCQElike && fUseCorrectedCTarget) { ERR(FTL) << "Sample: MiniBooNE_CCQE_XSec_1DQ2_antinu cannot run in both " "QELike and C-Target mode. You're welcome to add the data set." << std::endl; throw; } if (fCCQElike) { // CCQELike plot information fSettings.SetTitle("MiniBooNE #nu_#mu CCQE on CH"); - fSettings.SetDataInput( FitPar::GetDataBase() + "/MiniBooNE/anti-ccqe/asqq_like.txt" ); + fSettings.SetDataInput( FitPar::GetDataBase() + "/MiniBooNE/anti-ccqe/asqq_con.txt" ); fSettings.SetCovarInput( FitPar::GetDataBase() + "/MiniBooNE/anti-ccqe/asqq_diagcovar" ); fSettings.SetDefault( "ccqelikebkg_input", FitPar::GetDataBase() + "/MiniBooNE/anti-ccqe/asqq_bkg_ccqe.txt" ); fSettings.SetDefault( "ccpimbkg_input", FitPar::GetDataBase() + "/MiniBooNE/anti-ccqe/asqq_bkg_ccpim.txt" ); fSettings.SetHasExtraHistograms(true); fSettings.DefineAllowedSpecies("numu,numub"); fSettings.DefineAllowedTargets("C,H"); } else if (!fUseCorrectedCTarget) { // CCQE Plot Information fSettings.SetTitle("MiniBooNE #nu_#mu CC0#pi on CH"); fSettings.SetDataInput( FitPar::GetDataBase() + "/MiniBooNE/anti-ccqe/asqq_con.txt" ); fSettings.SetCovarInput( FitPar::GetDataBase() + "/MiniBooNE/anti-ccqe/asqq_diagcovar" ); fSettings.DefineAllowedSpecies("numu"); fSettings.DefineAllowedTargets("C,H"); } else { // CCQE Corrected Target Plot Information fSettings.SetTitle("MiniBooNE #nu_#mu CC0#pi on C"); fSettings.SetDataInput( FitPar::GetDataBase() + "/MiniBooNE/anti-ccqe/asqq_con_ctarget.txt" ); fSettings.SetCovarInput( FitPar::GetDataBase() + "/MiniBooNE/anti-ccqe/asqq_diagcovar" ); fSettings.DefineAllowedSpecies("numu"); fSettings.DefineAllowedTargets("C"); } FinaliseSampleSettings(); // 2. Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon // Multiply by 14.08/6.0 to get per neutron double NNucPerNTarg = fUseCorrectedCTarget ? 12.0 / 6.0 : 14.08 / 8.0; fScaleFactor = ((GetEventHistogram()->Integral("width") * 1E-38 / (fNEvents + 0.)) * NNucPerNTarg / TotalIntegratedFlux()); // 3. Plot Setup ------------------------------------------------------- SetDataFromTextFile( fSettings.GetDataInput() ); SetCovarFromDiagonal(); /// /// If CCQELike is used an additional the CCQELike BKG is used and a PDG /// Histogram is saved if (fCCQElike) { // CCQELike Data fDataHist_CCQELIKE = PlotUtils::GetTH1DFromFile( fSettings.GetS("ccqelikebkg_input"), fSettings.GetName() + "_CCQELIKE_data" ); fDataHist_CCQELIKE->SetNameTitle( (fSettings.Name() + "_CCQELIKE_BKG").c_str(), ("MiniBooNE #nu_#mu CCQE-Like Backgrounds" + fSettings.PlotTitles()).c_str() ); fDataHist->Add(fDataHist_CCQELIKE); SetAutoProcessTH1(fDataHist_CCQELIKE, kCMD_Write); // CCQELike MC fMCHist_CCQELIKE = new NuNuBarTrueModeStack( fSettings.Name() + "_CCQELIKE_MC", "CCQE-like MC" + fSettings.PlotTitles(), fDataHist_CCQELIKE ); SetAutoProcessTH1(fMCHist_CCQELIKE); // Data CCRES fDataHist_CCPIM = PlotUtils::GetTH1DFromFile( fSettings.GetS("ccpimbkg_input"), fSettings.GetName() + "_CCPIM_BKG_data" ); fDataHist_CCPIM->SetNameTitle( (fSettings.Name() + "_CCPIM_data").c_str(), ("MiniBooNE #nu_#mu CCQE-Like Backgrounds" + fSettings.PlotTitles()).c_str() ); SetAutoProcessTH1(fDataHist_CCQELIKE, kCMD_Write); // MC CCRES fMCHist_CCPIM = new NuNuBarTrueModeStack(fSettings.Name() + "_CCPIM_BKG_MC", "CCQE-like BKG CC-RES" + fSettings.PlotTitles(), fDataHist_CCPIM); SetAutoProcessTH1(fMCHist_CCPIM); // Make NON CCPIM fDataHist_NONCCPIM = (TH1D *)fDataHist_CCQELIKE->Clone(); fDataHist_NONCCPIM->SetNameTitle((fName + "_data_NONCCPIM").c_str(), (fName + "_data_NONCCPIM").c_str()); fDataHist_NONCCPIM->Add( fDataHist_CCPIM, -1.0 ); SetAutoProcessTH1(fDataHist_NONCCPIM, kCMD_Write); fMCHist_NONCCPIM = new NuNuBarTrueModeStack( fSettings.Name() + "_NONCCPIM_BKG", "CCQE-like BKG CC-NonRES" + fSettings.PlotTitles(), fDataHist_NONCCPIM); SetAutoProcessTH1(fMCHist_NONCCPIM); } FinaliseMeasurement(); }; void MiniBooNE_CCQE_XSec_1DQ2_antinu::FillEventVariables(FitEvent * event) { if (event->NumFSParticle(PhysConst::pdg_muons) == 0) return; TLorentzVector Pnu = event->GetNeutrinoIn()->fP; // The highest momentum mu+/mu-. The isSignal definition should make sure we // only // accept events we want, so no need to do an additional check here. TLorentzVector Pmu = event->GetHMFSParticle(PhysConst::pdg_muons)->fP; // Set X Variables fXVar = FitUtils::Q2QErec(Pmu, cos(Pnu.Vect().Angle(Pmu.Vect())), 30., false); fPDGnu = event->PDGnu(); return; }; bool MiniBooNE_CCQE_XSec_1DQ2_antinu::isSignal(FitEvent * event) { // If CC0pi, include both charges if (fCCQElike) { if (SignalDef::isCC0pi(event, 14, EnuMin, EnuMax) || SignalDef::isCC0pi(event, -14, EnuMin, EnuMax)) { return true; } } else { if (SignalDef::isCCQELike(event, -14, EnuMin, EnuMax)) return true; } return false; }; void MiniBooNE_CCQE_XSec_1DQ2_antinu::FillExtraHistograms(MeasurementVariableBox* vars, double weight) { // No Extra Hists if not ccqelike if (!fCCQElike or !Signal) return; // Fill Stacks if (Mode != -1 and Mode != -2) { if (fabs(Mode) == 11 or fabs(Mode) == 12 or fabs(Mode == 13)) { fMCHist_CCPIM->Fill(fPDGnu, Mode, fXVar, weight); } else { fMCHist_NONCCPIM->Fill(fPDGnu, Mode, fXVar, weight); } } fMCHist_CCQELIKE->Fill(fPDGnu, Mode, fXVar, weight); } diff --git a/src/Reweight/FitWeight.cxx b/src/Reweight/FitWeight.cxx index 0c2e7e5..84fab8e 100644 --- a/src/Reweight/FitWeight.cxx +++ b/src/Reweight/FitWeight.cxx @@ -1,285 +1,303 @@ #include "FitWeight.h" #include "OscWeightEngine.h" void FitWeight::AddRWEngine(int type) { switch (type) { case kNEUT: fAllRW[type] = new NEUTWeightEngine("neutrw"); break; case kNUWRO: fAllRW[type] = new NuWroWeightEngine("nuwrorw"); break; case kGENIE: fAllRW[type] = new GENIEWeightEngine("genierw"); break; case kNORM: fAllRW[type] = new SampleNormEngine("normrw"); break; case kLIKEWEIGHT: fAllRW[type] = new LikelihoodWeightEngine("likerw"); break; case kT2K: fAllRW[type] = new T2KWeightEngine("t2krw"); break; case kCUSTOM: fAllRW[type] = new NUISANCEWeightEngine("nuisrw"); break; case kSPLINEPARAMETER: fAllRW[type] = new SplineWeightEngine("splinerw"); break; case kNIWG: fAllRW[type] = new NIWGWeightEngine("niwgrw"); break; case kOSCILLATION: fAllRW[type] = new OscWeightEngine(); break; default: THROW("CANNOT ADD RW Engine for unknown dial type: " << type); break; } } WeightEngineBase* FitWeight::GetRWEngine(int type) { switch (type) { case kNEUT: if (fAllRW.count(type)) { return fAllRW[type]; } case kNUWRO: if (fAllRW.count(type)) { return fAllRW[type]; } case kGENIE: if (fAllRW.count(type)) { return fAllRW[type]; } case kNORM: if (fAllRW.count(type)) { return fAllRW[type]; } case kLIKEWEIGHT: if (fAllRW.count(type)) { return fAllRW[type]; } case kT2K: if (fAllRW.count(type)) { return fAllRW[type]; } case kCUSTOM: if (fAllRW.count(type)) { return fAllRW[type]; } case kSPLINEPARAMETER: if (fAllRW.count(type)) { return fAllRW[type]; } case kNIWG: if (fAllRW.count(type)) { return fAllRW[type]; } case kOSCILLATION: if (fAllRW.count(type)) { return fAllRW[type]; } default: { THROW("CANNOT get RW Engine for dial type: " << type); } } } +bool FitWeight::HasRWEngine(int type){ +switch (type) { + case kNEUT: + case kNUWRO: + case kGENIE: + case kNORM: + case kLIKEWEIGHT: + case kT2K: + case kCUSTOM: + case kSPLINEPARAMETER: + case kNIWG: + case kOSCILLATION:{ + return fAllRW.count(type); + } + default: { THROW("CANNOT get RW Engine for dial type: " << type); } + } +} + void FitWeight::IncludeDial(std::string name, std::string type, double val) { // Should register the dial here. int typeenum = Reweight::ConvDialType(type); IncludeDial(name, typeenum, val); } void FitWeight::IncludeDial(std::string name, int dialtype, double val) { // Get the dial enum int nuisenum = Reweight::ConvDial(name, dialtype); if (nuisenum == -1) { THROW("NUISENUM == " << nuisenum << " for " << name); } // Setup RW Engine Pointer if (fAllRW.find(dialtype) == fAllRW.end()) { AddRWEngine(dialtype); } WeightEngineBase* rw = fAllRW[dialtype]; // Include the dial rw->IncludeDial(name, val); // Set Dial Value if (val != -9999.9) { rw->SetDialValue(name, val); } // Sort Maps fAllEnums[name] = nuisenum; fAllValues[nuisenum] = val; // Sort Lists fNameList.push_back(name); fEnumList.push_back(nuisenum); fValueList.push_back(val); } void FitWeight::Reconfigure(bool silent) { // Reconfigure all added RW engines for (std::map::iterator iter = fAllRW.begin(); iter != fAllRW.end(); iter++) { (*iter).second->Reconfigure(silent); } } void FitWeight::SetDialValue(std::string name, double val) { // Add extra check, if name not found look for one with name in it. int nuisenum = fAllEnums[name]; SetDialValue(nuisenum, val); } // Allow for name aswell using GlobalList to determine sample name. void FitWeight::SetDialValue(int nuisenum, double val) { // Conv dial type int dialtype = int(nuisenum - (nuisenum % 1000)) / 1000; if (fAllRW.find(dialtype) == fAllRW.end()) { THROW("Cannot find RW Engine for dialtype = " << dialtype << " " << nuisenum << " " << (nuisenum - (nuisenum % 1000)) / 1000); } // Get RW Engine for this dial fAllRW[dialtype]->SetDialValue(nuisenum, val); fAllValues[nuisenum] = val; // Update ValueList for (size_t i = 0; i < fEnumList.size(); i++) { if (fEnumList[i] == nuisenum) { fValueList[i] = val; } } } void FitWeight::SetAllDials(const double* x, int n) { for (size_t i = 0; i < (UInt_t)n; i++) { int rwenum = fEnumList[i]; SetDialValue(rwenum, x[i]); } Reconfigure(); } double FitWeight::GetDialValue(std::string name) { // Add extra check, if name not found look for one with name in it. int nuisenum = fAllEnums[name]; return GetDialValue(nuisenum); } double FitWeight::GetDialValue(int nuisenum) { return fAllValues[nuisenum]; } int FitWeight::GetDialPos(std::string name) { int rwenum = fAllEnums[name]; return GetDialPos(rwenum); } int FitWeight::GetDialPos(int nuisenum) { for (size_t i = 0; i < fEnumList.size(); i++) { if (fEnumList[i] == nuisenum) { return i; } } ERR(FTL) << "No Dial Found! " << std::endl; throw; return -1; } bool FitWeight::DialIncluded(std::string name) { return (fAllEnums.find(name) != fAllEnums.end()); } bool FitWeight::DialIncluded(int rwenum) { return (fAllValues.find(rwenum) != fAllValues.end()); } double FitWeight::CalcWeight(BaseFitEvt* evt) { double rwweight = 1.0; for (std::map::iterator iter = fAllRW.begin(); iter != fAllRW.end(); iter++) { double w = (*iter).second->CalcWeight(evt); // LOG(FIT) << "Iter " << (*iter).second->fCalcName << " = " << w << // std::endl; rwweight *= w; } return rwweight; } void FitWeight::UpdateWeightEngine(const double* x) { size_t count = 0; for (std::vector::iterator iter = fEnumList.begin(); iter != fEnumList.end(); iter++) { SetDialValue((*iter), x[count]); count++; } } void FitWeight::GetAllDials(double* x, int n) { for (int i = 0; i < n; i++) { x[i] = GetDialValue(fEnumList[i]); } } bool FitWeight::NeedsEventReWeight(const double* x) { bool haschange = false; size_t count = 0; // Compare old to new and decide if RW needed. for (std::vector::iterator iter = fEnumList.begin(); iter != fEnumList.end(); iter++) { int nuisenum = (*iter); int type = (nuisenum / 1000) - (nuisenum % 1000); // Compare old to new double oldval = GetDialValue(nuisenum); double newval = x[count]; if (oldval != newval) { if (fAllRW[type]->NeedsEventReWeight()) { haschange = true; } } count++; } return haschange; } double FitWeight::GetSampleNorm(std::string name) { if (name.empty()) return 1.0; // Find norm dial if (fAllEnums.find(name + "_norm") != fAllEnums.end()) { if (fAllValues.find(fAllEnums[name + "_norm"]) != fAllValues.end()) { return fAllValues[fAllEnums[name + "_norm"]]; } else { return 1.0; } } else { return 1.0; } } void FitWeight::Print() { LOG(REC) << "Fit Weight State: " << std::endl; for (size_t i = 0; i < fNameList.size(); i++) { LOG(REC) << " -> Par " << i << ". " << fNameList[i] << " " << fValueList[i] << std::endl; } } diff --git a/src/Reweight/FitWeight.h b/src/Reweight/FitWeight.h index 343648a..8393e16 100644 --- a/src/Reweight/FitWeight.h +++ b/src/Reweight/FitWeight.h @@ -1,73 +1,74 @@ #ifndef FITWEIGHT2_H #define FITWEIGHT2_H #include "WeightUtils.h" #include "WeightEngineBase.h" #include "NEUTWeightEngine.h" #include "GENIEWeightEngine.h" #include "NuWroWeightEngine.h" #include "SampleNormEngine.h" #include "LikelihoodWeightEngine.h" #include "SplineWeightEngine.h" #include "NUISANCEWeightEngine.h" #include "T2KWeightEngine.h" #include "NIWGWeightEngine.h" #include #include class FitWeight { public: FitWeight(std::string name = "") {}; // Add a new RW engine given type void AddRWEngine(int rwtype); WeightEngineBase* GetRWEngine(int type); + bool HasRWEngine(int type); // Includes void IncludeDial(std::string name, std::string type, double val = -9999.9); void IncludeDial(std::string name, int type, double val = -9999.9); // Update RW Engines void Reconfigure(bool silent = false); void SetDialValue(std::string name, double val); void SetDialValue(int rwenum, double val); double GetDialValue(std::string name); double GetDialValue(int rwenum); int GetDialPos(std::string name); int GetDialPos(int rwenum); bool DialIncluded(std::string name); bool DialIncluded(int rwenum); double CalcWeight(BaseFitEvt* evt); bool HasRWDialChanged(const double* x) { return true; }; bool NeedsEventReWeight(const double* x); void SetAllDials(const double* x, int n); double GetSampleNorm(std::string name); void UpdateWeightEngine(const double* x); inline std::vector GetDialEnums() { return fEnumList; }; inline std::vector GetDialNames() { return fNameList; }; inline std::vector GetDialValues() { return fValueList; }; void GetAllDials(double* x, int n); void Print(); std::vector fEnumList; std::vector fNameList; std::vector fValueList; std::map fAllEnums; std::map fAllValues; std::map fAllRW; }; #endif diff --git a/src/Reweight/OscWeightEngine.cxx b/src/Reweight/OscWeightEngine.cxx index 7fde603..5ab5f54 100644 --- a/src/Reweight/OscWeightEngine.cxx +++ b/src/Reweight/OscWeightEngine.cxx @@ -1,291 +1,327 @@ // 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 . *******************************************************************************/ //#define DEBUG_OSC_WE #include "OscWeightEngine.h" #include enum nuTypes { kNuebarType = -1, kNumubarType = -2, kNutaubarType = -3, kNueType = 1, kNumuType = 2, kNutauType = 3, }; nuTypes GetNuType(int pdg) { switch (pdg) { case 16: return kNutauType; case 14: return kNumuType; case 12: return kNueType; case -16: return kNutaubarType; case -14: return kNumubarType; case -12: return kNuebarType; default: { THROW("Attempting to convert \"neutrino pdg\": " << pdg); } } } OscWeightEngine::OscWeightEngine() : #ifdef __PROB3PP_ENABLED__ bp(), #endif theta12(0.825), theta13(0.10), theta23(1.0), dm12(7.9e-5), dm23(2.5e-3), dcp(0.0), LengthParam(0xdeadbeef), - TargetNuType(0) { + TargetNuType(0), + ForceFromNuPDG(0) { Config(); } void OscWeightEngine::Config() { std::vector OscParam = Config::QueryKeys("OscParam"); if (OscParam.size() < 1) { ERROR(WRN, "Oscillation parameters specified but no OscParam element " "configuring the experimental characteristics found.\nExpect at " "least . Pausing for " "10..."); sleep(10); return; } if (OscParam[0].Has("baseline_km")) { LengthParamIsZenith = false; LengthParam = OscParam[0].GetD("baseline_km"); constant_density = OscParam[0].Has("matter_density") ? OscParam[0].GetD("matter_density") : 0xdeadbeef; } else if (OscParam[0].Has("detection_zenith_deg")) { LengthParamIsZenith = true; static const double deg2rad = asin(1) / 90.0; LengthParam = cos(OscParam[0].GetD("detection_zenith_deg") * deg2rad); } else { ERROR(WRN, "It appeared that you wanted to set up an oscillation weight " "branch, but it was not correctly configured. You need to specify " "either: detection_zenith_deg or baseline_km attributes on the " "OscParam element, and if baseline_km is specified, you can " "optionally also set matter_density for oscillations through a " "constant matter density. Pausing for 10..."); sleep(10); return; } dm23 = OscParam[0].Has("dm23") ? OscParam[0].GetD("dm23") : dm23; theta23 = OscParam[0].Has("sinsq_theta23") ? OscParam[0].GetD("sinsq_theta23") : theta23; theta13 = OscParam[0].Has("sinsq_theta13") ? OscParam[0].GetD("sinsq_theta13") : theta13; dm12 = OscParam[0].Has("dm12") ? OscParam[0].GetD("dm12") : dm12; theta12 = OscParam[0].Has("sinsq_theta12") ? OscParam[0].GetD("sinsq_theta12") : theta12; dcp = OscParam[0].Has("dcp") ? OscParam[0].GetD("dcp") : dcp; TargetNuType = OscParam[0].Has("TargetNuPDG") ? GetNuType(OscParam[0].GetI("TargetNuPDG")) : 0; + ForceFromNuPDG = OscParam[0].Has("ForceFromNuPDG") + ? GetNuType(OscParam[0].GetI("ForceFromNuPDG")) + : 0; QLOG(FIT, "Configured oscillation weighter:"); if (LengthParamIsZenith) { QLOG(FIT, "Earth density profile with detection cos(zenith) = " << LengthParam); } else { if (constant_density != 0xdeadbeef) { QLOG(FIT, "Constant density with experimental baseline = " << LengthParam); } else { QLOG(FIT, "Vacuum oscillations with experimental baseline = " << LengthParam); } } params[0] = dm23; params[1] = theta23; params[2] = theta13; params[3] = dm12; params[4] = theta12; params[5] = dcp; QLOG(FIT, "\tdm23 : " << params[0]); QLOG(FIT, "\tsinsq_theta23: " << params[1]); QLOG(FIT, "\tsinsq_theta13: " << params[2]); QLOG(FIT, "\tdm12 : " << params[3]); QLOG(FIT, "\tsinsq_theta12: " << params[4]); QLOG(FIT, "\tdcp : " << params[5]); + if (TargetNuType) { + QLOG(FIT, "\tTargetNuType: " << TargetNuType); + } + if (ForceFromNuPDG) { + QLOG(FIT, "\tForceFromNuPDG: " << ForceFromNuPDG); + } + + bp.SetMNS(params[theta12_idx], params[theta13_idx], params[theta23_idx], + params[dm12_idx], params[dm23_idx], params[dcp_idx], 1, true, 2); + bp.DefinePath(LengthParam, 0); + + QLOG(FIT, "\tBaseline : " << (bp.GetBaseline() / 100.0) << " km."); } void OscWeightEngine::IncludeDial(std::string name, double startval) { #ifdef DEBUG_OSC_WE std::cout << "IncludeDial: " << name << " at " << startval << std::endl; #endif int dial = SystEnumFromString(name); if (!dial) { THROW("OscWeightEngine passed dial: " << name << " that it does not understand."); } params[dial - 1] = startval; } void OscWeightEngine::SetDialValue(int nuisenum, double val) { #ifdef DEBUG_OSC_WE std::cout << "SetDial: " << (nuisenum % 1000) << " at " << val << std::endl; #endif fHasChanged = (params[(nuisenum % 1000) - 1] - val) > std::numeric_limits::epsilon(); params[(nuisenum % 1000) - 1] = val; } void OscWeightEngine::SetDialValue(std::string name, double val) { #ifdef DEBUG_OSC_WE std::cout << "SetDial: " << name << " at " << val << std::endl; #endif int dial = SystEnumFromString(name); if (!dial) { THROW("OscWeightEngine passed dial: " << name << " that it does not understand."); } fHasChanged = (params[dial - 1] - val) > std::numeric_limits::epsilon(); params[dial - 1] = val; } bool OscWeightEngine::IsDialIncluded(std::string name) { return SystEnumFromString(name); } bool OscWeightEngine::IsDialIncluded(int nuisenum) { return ((nuisenum % 1000) > 0) && ((nuisenum % 1000) < 6); } double OscWeightEngine::GetDialValue(std::string name) { int dial = SystEnumFromString(name); if (!dial) { THROW("OscWeightEngine passed dial: " << name << " that it does not understand."); } return params[dial - 1]; } double OscWeightEngine::GetDialValue(int nuisenum) { if (!(nuisenum % 1000) || (nuisenum % 1000) > 6) { THROW("OscWeightEngine passed dial enum: " << (nuisenum % 1000) << " that it does not understand, expected [1,6]."); } return params[(nuisenum % 1000) - 1]; } void OscWeightEngine::Reconfigure(bool silent) { fHasChanged = false; }; bool OscWeightEngine::NeedsEventReWeight() { if (fHasChanged) { return true; } return false; } double OscWeightEngine::CalcWeight(BaseFitEvt* evt) { static bool Warned = false; if (evt->probe_E == 0xdeadbeef) { if (!Warned) { ERROR(WRN, "Oscillation weights asked for but using 'litemode' or " "unsupported generator input. Pasuing for 10..."); sleep(10); Warned = true; } return 1; } return CalcWeight(evt->probe_E * 1E-3, evt->probe_pdg); } -double OscWeightEngine::CalcWeight(double ENu, int PDGNu) { +double OscWeightEngine::CalcWeight(double ENu, int PDGNu, int TargetPDGNu) { if (LengthParam == 0xdeadbeef) { // not configured. return 1; } #ifdef __PROB3PP_ENABLED__ - int NuType = GetNuType(PDGNu); + int NuType = (ForceFromNuPDG != 0) ? ForceFromNuPDG : GetNuType(PDGNu); bp.SetMNS(params[theta12_idx], params[theta13_idx], params[theta23_idx], - params[dm12_idx], params[dm23_idx], params[dcp_idx], ENu, - true, NuType); + params[dm12_idx], params[dm23_idx], params[dcp_idx], ENu, true, + NuType); int pmt = 0; double prob_weight = 1; + TargetPDGNu = (TargetPDGNu == -1) ? (TargetNuType ? TargetNuType : NuType) + : GetNuType(TargetPDGNu); if (LengthParamIsZenith) { // Use earth density bp.DefinePath(LengthParam, 0); bp.propagate(NuType); pmt = 0; - prob_weight = bp.GetProb(NuType, TargetNuType ? TargetNuType : NuType); + prob_weight = bp.GetProb(NuType, TargetPDGNu); } else { if (constant_density != 0xdeadbeef) { bp.propagateLinear(NuType, LengthParam, constant_density); pmt = 1; - prob_weight = bp.GetProb(NuType, TargetNuType ? TargetNuType : NuType); + prob_weight = bp.GetProb(NuType, TargetPDGNu); } else { pmt = 2; prob_weight = - bp.GetVacuumProb(NuType, TargetNuType ? TargetNuType : NuType, - ENu * 1E-3, LengthParam); + bp.GetVacuumProb(NuType, TargetPDGNu, ENu * 1E-3, LengthParam); } } #ifdef DEBUG_OSC_WE if (prob_weight != prob_weight) { - THROW("Calculated bad prob weight: " - << prob_weight << "(Osc Type: " << pmt << " -- " << NuType << " -> " - << (TargetNuType ? TargetNuType : NuType) << ")"); + THROW("Calculated bad prob weight: " << prob_weight << "(Osc Type: " << pmt + << " -- " << NuType << " -> " + << TargetPDGNu << ")"); } + if (prob_weight > 1) { + THROW("Calculated bad prob weight: " << prob_weight << "(Osc Type: " << pmt + << " -- " << NuType << " -> " + << TargetPDGNu << ")"); + } + + std::cout << NuType << " -> " << TargetPDGNu << ": " << ENu << " = " + << prob_weight << "%%." << std::endl; #endif return prob_weight; #else return 1; #endif } int OscWeightEngine::SystEnumFromString(std::string const& name) { if (name == "dm23") { return 1; } else if (name == "sinsq_theta23") { return 2; } else if (name == "sinsq_theta13") { return 3; } else if (name == "dm12") { return 4; } else if (name == "sinsq_theta12") { return 5; } else if (name == "dcp") { return 6; } else { return 0; } } + +void OscWeightEngine::Print() { + std::cout << "OscWeightEngine: " << std::endl; + + std::cout << "\t theta12: " << params[theta12_idx] << std::endl; + std::cout << "\t theta13: " << params[theta13_idx] << std::endl; + std::cout << "\t theta23: " << params[theta23_idx] << std::endl; + std::cout << "\t dm12: " << params[dm12_idx] << std::endl; + std::cout << "\t dm23: " << params[dm23_idx] << std::endl; + std::cout << "\t dcp: " << params[dcp_idx] << std::endl; +} diff --git a/src/Reweight/OscWeightEngine.h b/src/Reweight/OscWeightEngine.h index f3c826d..8cacff7 100644 --- a/src/Reweight/OscWeightEngine.h +++ b/src/Reweight/OscWeightEngine.h @@ -1,127 +1,143 @@ // 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 . *******************************************************************************/ #include "FitLogger.h" #include "FitEvent.h" #include "PhysConst.h" #include "WeightEngineBase.h" #ifdef __PROB3PP_ENABLED__ #include "BargerPropagator.h" #endif #include +#ifdef __PROB3PP_ENABLED__ +class BG : public BargerPropagator { + public: + BG() : BargerPropagator(){}; + double GetBaseline() { return Earth->get_Pathlength(); } +}; +#endif + class OscWeightEngine : public WeightEngineBase { enum params { dm23_idx = 0, theta23_idx, theta13_idx, dm12_idx, theta12_idx, dcp_idx, }; #ifdef __PROB3PP_ENABLED__ - BargerPropagator bp; + BG bp; #endif //******************************* Osc params ****************************** double theta12; double theta13; double theta23; /// The 1-2 mass squared splitting (small) [eV] double dm12; /// The 2-3 mass squared splitting (large) [eV] double dm23; /// The PMNS CP-violating phase double dcp; ///\brief The constant matter density used for simple given baseline /// oscillation [g/cm^3] double constant_density; /// Whether LengthParam corresponds to a Zenith or a baseline. /// /// If we just want to calculate the osc. prob. with a constant matter density /// then this should be false and constant_density should be set /// (or 0 for vacuum prob). bool LengthParamIsZenith; /// Either a path length or a post oscillation zenith angle /// /// N.B. For a beamline that has a dip angle of X degrees, the post /// oscillation zenith angle will be 90+X degrees. double LengthParam; /// Holds current value of oscillation parameters. double params[6]; /// The oscillation target type /// /// If unspecified in the element, it will default to /// disappearance probability. int TargetNuType; + /// The initial neutrino species + /// + /// If unspecified in the element, it will be determined by + /// the incoming events. + int ForceFromNuPDG; + public: OscWeightEngine(); /// Configures oscillation parameters from input xml file. /// /// Osc parameters configured from OscParam XML element as: /// /// /// /// If matter_density and baseline are present, then oscillation probability /// is calculated for a constant matter density. /// If detection_zenith_deg is present, then the baseline and density are /// calculated from the density profile and radius of the earth. /// If none are present, a vacuum oscillation is calculated. /// If TargetNuPDG is unspecified, oscillation will default to /// disappearance probability. void Config(); // Functions requiring Override void IncludeDial(std::string name, double startval); void SetDialValue(int nuisenum, double val); void SetDialValue(std::string name, double val); bool IsDialIncluded(std::string name); bool IsDialIncluded(int nuisenum); double GetDialValue(std::string name); double GetDialValue(int nuisenum); void Reconfigure(bool silent); bool NeedsEventReWeight(); double CalcWeight(BaseFitEvt* evt); - double CalcWeight(double ENu, int PDGNu); + double CalcWeight(double ENu, int PDGNu, int TargetPDGNu = -1); static int SystEnumFromString(std::string const& name); + + void Print(); }; diff --git a/src/Smearceptance/TrackedMomentumMatrixSmearer.cxx b/src/Smearceptance/TrackedMomentumMatrixSmearer.cxx index 9dda0cc..1a03865 100644 --- a/src/Smearceptance/TrackedMomentumMatrixSmearer.cxx +++ b/src/Smearceptance/TrackedMomentumMatrixSmearer.cxx @@ -1,411 +1,416 @@ // 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 . *******************************************************************************/ #include "TrackedMomentumMatrixSmearer.h" namespace { TrackedMomentumMatrixSmearer::DependVar GetVarType(std::string const &axisvar) { if (axisvar == "Momentum") { return TrackedMomentumMatrixSmearer::kMomentum; } else if (axisvar == "KE") { return TrackedMomentumMatrixSmearer::kKE; } else if (axisvar == "TE") { return TrackedMomentumMatrixSmearer::kTE; } return TrackedMomentumMatrixSmearer::kNoVar; } } TH1D const *TrackedMomentumMatrixSmearer::SmearMap::GetRecoSlice(double val) { if ((val < RecoSlices.front().first.first) || (val > RecoSlices.back().first.second)) { ERROR(WRN, "Kinematic property: " << val << ", not within smearable range: [" << RecoSlices.front().first.first << " -- " << RecoSlices.back().first.second << "]."); return NULL; } int L = 0, U = RecoSlices.size(); while (true) { if (U == L) { return RecoSlices[L].second; } int R = (U - L); int m = L + (R / 2); if (val <= RecoSlices[m].first.first) { U = m - 1; continue; } if (val > RecoSlices[m].first.second) { L = m + 1; continue; } if ((val > RecoSlices[m].first.first) && (val <= RecoSlices[m].first.second)) { return RecoSlices[m].second; } THROW("Binary smearing search failed. Check logic."); } } TH1D *GetMapSlice(TH2D *mp, int SliceBin, bool AlongX) { int NBins = (AlongX ? mp->GetXaxis() : mp->GetYaxis())->GetNbins(); int NOtherBins = (AlongX ? mp->GetYaxis() : mp->GetXaxis())->GetNbins(); if (SliceBin >= NOtherBins) { THROW("Asked for slice " << SliceBin << " but the " << (AlongX ? 'Y' : 'X') << " axis only has " << NOtherBins); } if ((AlongX ? mp->GetXaxis() : mp->GetYaxis())->IsVariableBinSize() && ((NBins + 1) != (AlongX ? mp->GetXaxis() : mp->GetYaxis())->GetXbins()->GetSize())) { THROW( "Attemping to take binning slice of variable binning, but NBins+1 != " "NBinEdges: " << (NBins + 1) << " != " << (AlongX ? mp->GetXaxis() : mp->GetYaxis())->GetXbins()->GetSize()); } std::stringstream ss(""); ss << mp->GetName() << (AlongX ? 'Y' : 'X') << "Slice_" << SliceBin; std::stringstream st(""); st << mp->GetTitle() << ";" << (AlongX ? mp->GetXaxis() : mp->GetYaxis())->GetTitle() << ";" << "Count"; TH1D *Ret; if ((AlongX ? mp->GetXaxis() : mp->GetYaxis())->IsVariableBinSize()) { Ret = new TH1D( ss.str().c_str(), st.str().c_str(), NBins, (AlongX ? mp->GetXaxis() : mp->GetYaxis())->GetXbins()->GetArray()); } else { Ret = new TH1D(ss.str().c_str(), st.str().c_str(), NBins, (AlongX ? mp->GetXaxis() : mp->GetYaxis())->GetXmin(), (AlongX ? mp->GetXaxis() : mp->GetYaxis())->GetXmax()); } for (int bi_it = 0; bi_it < NBins + 2; ++bi_it) { int X = AlongX ? bi_it : SliceBin + 1; int Y = AlongX ? SliceBin + 1 : bi_it; int GBin = mp->GetBin(X, Y); Ret->SetBinContent(bi_it, mp->GetBinContent(GBin)); Ret->SetBinError(bi_it, mp->GetBinError(GBin)); } #ifdef DEBUG_MATSMEAR std::cout << "Took slice: " << SliceBin << " spanning [" << Ret->GetXaxis()->GetBinLowEdge(1) << " -- " << Ret->GetXaxis()->GetBinUpEdge(Ret->GetXaxis()->GetNbins()) << "] (Orignal span [" << (AlongX ? mp->GetXaxis() : mp->GetYaxis())->GetBinLowEdge(1) << " -- " << (AlongX ? mp->GetXaxis() : mp->GetYaxis()) ->GetBinUpEdge( (AlongX ? mp->GetXaxis() : mp->GetYaxis())->GetNbins()) << "]) " << (AlongX ? mp->GetXaxis() : mp->GetYaxis())->GetXmin() << " -- " << (AlongX ? mp->GetXaxis() : mp->GetYaxis())->GetXmax() << " IsVBin: " << (AlongX ? mp->GetXaxis() : mp->GetYaxis())->IsVariableBinSize() << std::endl; #endif Ret->SetDirectory(NULL); return Ret; } void TrackedMomentumMatrixSmearer::SmearMap::SetSlicesFromMap(TH2D *map, bool TruthIsY) { int NSlices = (TruthIsY ? map->GetYaxis() : map->GetXaxis())->GetNbins(); for (Int_t TrueSlice_it = 0; TrueSlice_it < NSlices; ++TrueSlice_it) { std::pair BinEdges; BinEdges.first = (TruthIsY ? map->GetYaxis() : map->GetXaxis()) ->GetBinLowEdge(TrueSlice_it + 1); BinEdges.second = (TruthIsY ? map->GetYaxis() : map->GetXaxis()) ->GetBinUpEdge(TrueSlice_it + 1); TH1D *slice = GetMapSlice(map, TrueSlice_it, TruthIsY); RecoSlices.push_back(std::make_pair(BinEdges, slice)); } QLOG(FIT, "\tAdded " << RecoSlices.size() << " reco slices."); } /// Reads particle efficiency nodes /// /// Nodes look like: /// /// /// void TrackedMomentumMatrixSmearer::SpecifcSetup(nuiskey &nk) { std::vector effDescriptors = nk.GetListOfChildNodes("SmearMatrix"); for (size_t t_it = 0; t_it < effDescriptors.size(); ++t_it) { std::string inputFileName = effDescriptors[t_it].GetS("InputFile"); std::string HistName = effDescriptors[t_it].GetS("HistName"); bool YIsTrue = effDescriptors[t_it].Has("YIsTrue") ? effDescriptors[t_it].GetI("YIsTrue") : true; double UnitsScale = effDescriptors[t_it].Has("MatrixToInternal") ? effDescriptors[t_it].GetD("MatrixToInternal") : 1; TFile inputFile(inputFileName.c_str()); if (!inputFile.IsOpen()) { THROW("Couldn't open specified input root file: " << inputFileName); } TH2D *inpHist = dynamic_cast(inputFile.Get(HistName.c_str())); if (!inpHist) { THROW("Couldn't get TH2D named: " << HistName << " from input root file: " << inputFileName); } TrackedMomentumMatrixSmearer::DependVar var = GetVarType(effDescriptors[t_it].GetS("Kinematics")); std::string pdgs_s = effDescriptors[t_it].GetS("PDG"); std::vector pdgs_i = GeneralUtils::ParseToInt(pdgs_s, ","); for (size_t pdg_it = 0; pdg_it < pdgs_i.size(); ++pdg_it) { if (ParticleMappings.count(pdgs_i[pdg_it])) { ERROR(WRN, "Smearceptor " << ElementName << ":" << InstanceName << " already has a smearing for PDG: " << pdgs_i[pdg_it]); } SmearMap sm; sm.SetSlicesFromMap(inpHist, YIsTrue); sm.SmearVar = var; sm.UnitsScale = UnitsScale; ParticleMappings[pdgs_i[pdg_it]] = sm; QLOG(FIT, "Added smearing map for PDG: " << pdgs_i[pdg_it]); } } SlaveGS.Setup(nk); } RecoInfo *TrackedMomentumMatrixSmearer::Smearcept(FitEvent *fe) { RecoInfo *ri = new RecoInfo(); for (size_t p_it = 0; p_it < fe->NParticles(); ++p_it) { FitParticle *fp = fe->GetParticle(p_it); #ifdef DEBUG_MATSMEAR std::cout << std::endl; std::cout << "[" << p_it << "]: " << fp->PDG() << ", " << fp->Status() << ", " << fp->E() << " -- KE:" << fp->KE() << " Mom: " << fp->P3().Mag() << std::flush; #endif if (fp->Status() != kFinalState) { #ifdef DEBUG_MATSMEAR std::cout << " -- Not final state." << std::flush; #endif continue; } if (!ParticleMappings.count(fp->PDG())) { SlaveGS.SmearceptOneParticle(ri, fp #ifdef DEBUG_GAUSSSMEAR , p_it #endif ); continue; } SmearMap &sm = ParticleMappings[fp->PDG()]; double kineProp = 0; switch (sm.SmearVar) { case kMomentum: { kineProp = fp->P3().Mag(); break; } case kKE: { kineProp = fp->KE(); break; } case kTE: { kineProp = fp->E(); break; } default: { THROW("Trying to find particle value for a kNoAxis."); } } TH1 const *recoDistrib = sm.GetRecoSlice(kineProp / sm.UnitsScale); #ifdef DEBUG_MATSMEAR std::cout << " -- Got slice spanning [" << recoDistrib->GetXaxis()->GetBinLowEdge(1) << " -- " << recoDistrib->GetXaxis()->GetBinUpEdge( recoDistrib->GetXaxis()->GetNbins()) << "]" << std::endl; #endif if (!recoDistrib) { #ifdef DEBUG_MATSMEAR std::cout << " -- outside smearable range." << std::flush; #endif continue; } if (recoDistrib->Integral() == 0) { ERROR(WRN, "True slice has no reconstructed events. Not smearing.") continue; } double Smeared = recoDistrib->GetRandom() * sm.UnitsScale; #ifdef DEBUG_MATSMEAR std::cout << "GotRandom: " << Smeared << ", MPV: " << recoDistrib->GetXaxis()->GetBinCenter( recoDistrib->GetMaximumBin()) * sm.UnitsScale << std::endl; #endif switch (sm.SmearVar) { case kMomentum: { ri->RecObjMom.push_back(fp->P3().Unit() * Smeared); #ifdef DEBUG_MATSMEAR std::cout << " -- Smeared: " << fp->p() << " -> " << Smeared << "." << std::flush; #endif break; } case kKE: { double mass = fp->P4().M(); double TE = mass + Smeared; double magP = sqrt(TE * TE - mass * mass); ri->RecObjMom.push_back(fp->P3().Unit() * magP); #ifdef DEBUG_MATSMEAR std::cout << " -- Smeared: " << fp->KE() << " (mass: " << mass << ") -> " << Smeared << ". Smear Mom: " << ri->RecObjMom.back().Mag() << "." << std::flush; #endif break; } case kTE: { double mass = fp->P4().M(); double TE = Smeared; double magP = sqrt(TE * TE - mass * mass); ri->RecObjMom.push_back(fp->P3().Unit() * magP); #ifdef DEBUG_MATSMEAR std::cout << " -- Smeared: " << fp->E() << " (mass: " << mass << ") -> " << Smeared << ". Smear Mom: " << ri->RecObjMom.back().Mag() << "." << std::flush; #endif break; } default: {} } #ifdef DEBUG_MATSMEAR std::cout << " -- momentum reconstructed as " << ri->RecObjMom.back().Mag() << "." << std::endl; #endif if (ri->RecObjMom.back().Mag() != ri->RecObjMom.back().Mag()) { ERROR(WRN, "Invalid particle built."); ri->RecObjMom.pop_back(); #include "TCanvas.h" TCanvas *Test = new TCanvas("c1", ""); static_cast(recoDistrib->Clone())->Draw(); Test->SaveAs("Fail.png"); delete Test; THROW("ARGH"); } else { ri->RecObjClass.push_back(fp->PDG()); } } #ifdef DEBUG_MATSMEAR std::cout << std::endl; #endif return ri; } void TrackedMomentumMatrixSmearer::SmearRecoInfo(RecoInfo *ri) { for (size_t p_it = 0; p_it < ri->RecObjMom.size(); ++p_it) { if (!ParticleMappings.count(ri->RecObjClass[p_it])) { SlaveGS.SmearceptOneParticle(ri->RecObjMom[p_it], ri->RecObjClass[p_it]); continue; } SmearMap &sm = ParticleMappings[ri->RecObjClass[p_it]]; double kineProp = 0; switch (sm.SmearVar) { case kMomentum: { kineProp = ri->RecObjMom[p_it].Mag(); break; } case kKE: { double mass = PhysConst::GetMass(ri->RecObjClass[p_it]) * 1E3; kineProp = sqrt(ri->RecObjMom[p_it].Mag2() + mass * mass) - mass; break; } case kTE: { double mass = PhysConst::GetMass(ri->RecObjClass[p_it]) * 1E3; kineProp = sqrt(ri->RecObjMom[p_it].Mag2() + mass * mass); break; } default: { THROW("Trying to find particle value for a kNoAxis."); } } TH1 const *recoDistrib = sm.GetRecoSlice(kineProp / sm.UnitsScale); if (!recoDistrib) { continue; } + if (recoDistrib->Integral() == 0) { + ERROR(WRN, "True slice has no reconstructed events. Not smearing.") + continue; + } + double Smeared = recoDistrib->GetRandom() * sm.UnitsScale; switch (sm.SmearVar) { case kMomentum: { ri->RecObjMom[p_it] = ri->RecObjMom[p_it].Unit() * Smeared; break; } case kKE: { double mass = PhysConst::GetMass(ri->RecObjClass[p_it]) * 1E3; double TE = mass + Smeared; double magP = sqrt(TE * TE - mass * mass); ri->RecObjMom[p_it] = ri->RecObjMom[p_it].Unit() * magP; break; } case kTE: { double mass = PhysConst::GetMass(ri->RecObjClass[p_it]) * 1E3; double TE = Smeared; double magP = sqrt(TE * TE - mass * mass); ri->RecObjMom[p_it] = ri->RecObjMom[p_it].Unit() * magP; break; } default: {} } } } diff --git a/src/Smearceptance/smearceptance.md b/src/Smearceptance/smearceptance.md index f8f7aab..b876ded 100644 --- a/src/Smearceptance/smearceptance.md +++ b/src/Smearceptance/smearceptance.md @@ -1,273 +1,273 @@ # NUISANCE Smearceptance 1. Introduction 2. Quickstart: Applying thresholds 3. Included smearcepters 4. Writing your own ## 1. Introduction A generalised 'Fast MC' interface for NUISANCE. Smearers, accepters, and smearcepters can be written and configured to mock up the effects of using a 'realistic' detection techniques on any input event format that NUISANCE can read. A simple example of this would be a threshold accepter, which lets the user define charged particle tracking thresholds for different types of final state particles. These thresholds would be applied so that any downstream analysis can only see particles above threshold. The eventual aim of such a module would be to expand the use of NUISANCE as a data-release platform so that analysers could add their reconstruction-level/uncorrected results, along with the information to forward-fold, or 'smearcept' theory inputs for comparison and model tuning. It is not currently clear that this is feasible, but it is an interesting possibility. The current use cases include generating fake data for different types of detector technology, running simple mock experiments as a first gauge of potential sensitivities, and simple model overlays for uncorrected data from both nu-A and e-A scattering experiments. The interface is designed to be abstract, and very simple. With any real data and analyses, the devil is often in the detail and it is likely that tailored Smearcepters would have to be written for each analysis. However, a number of examples and simple smearcepters already exist and are useful for applying thresholds, multi-dimensional efficiency curves, and simple detector smearing effects. ## 2. Quickstart: Applying thresholds Steps to acceptance: * Write a smearcepter card file, `WaterCherenkovThresholds.xml`: ```xml ``` * Produce a smeared event summary tree: `$ nuissmear -i InputVector.root -c WaterCherenkovThresholds.xml -t WCThresh -o WaterCherenkov_summary.root` * Draw plots from the event tree: `[root] FlatTree_VARS->Draw("EISLep_true:EISLep_LepHad_rec >> (100,0,2000,100,0,2000)","Weight*(flagCCINC_rec==1)","COLZ")` The branchs in the event summary tree are described in detail the class documentation of `src/MCStudies/Smearceptance_Tester.cxx` ## 3. Included smearcepters ### General Smearcepters are defined in a NUISANCE xml configuration file within a tag of the `` root element named ``. Any number can be defined, and each should be distinctly named with a `Name=""` attribute. An example XML tag is shown below that highlights some of the notation used in this section. ```xml ``` * `AB` and `AC` are both valid attribute names, at least one of which is a required attribute. * `D` is an optional attribute. * `` is an example attribute value. * The attribute `E` must take either the value `F` or `G`. ### ThresholdAccepter Applies tracking and visible energy thresholds to an input vector. #### Full example ```xml ``` #### Details A tracking threshold can be placed on a particles production zenith angle by the element: * `` * `` Tracking and visible energy threshold values can be applied by the following elements: * Particle momentum: Use `<[Reco|Vis]Threshold PDG="" [Reco|Vis]ThresholdMomentum_MeV="" (Contrib="[T|K]" Fraction="") />` * Particle kinetic energy: Use `<[Reco|Vis]Threshold PDG="" [Reco|Vis]ThresholdKE_MeV="" (Contrib="[T|K]" Fraction="") />` When defining visible energy thresholds, the additional attributes `Contrib="[,K]"` and `Fraction=""` can be specified to detail whether the energy deposit contribution comes from the particle total or kinetic energy only and what fraction of that deposit is visible. The deposited energy defaults to the particle total energy and the fraction defaults to 1. If a particle kinematics do not exceed a momentum or kinetic energy threshold for tracking they are tested against the visible energy deposit threshold. If a particle is rejected due to an angular threshold, it is not allowed to deposit energy. Multiple thresholds can target the same input PDG, however it is undefined behavior to use more than one energy/momentum tracking threshold, or use both `Abs` and non-`Abs` zenith angle cuts. *N.B.* If a PDG code is encountered for which there are no defined thresholds, it is not accepted. ### GaussianSmearer Documentation to follow. Sorry. ### EfficiencyApplicator Applies tracking efficiencies from one, two, or three dimensional efficiencies passed in as input. #### Full example ```xml - - - + + + ``` #### Details Each `` tag requires at least: * `PDG="<211,-211>"`: The particle IDs to apply this efficiency to. * `InputFile=""`: The location of the ROOT file containing the efficiency histogram. * `HistName=""`: The name (may include directories) of the `TH1` or `TEfficiency` that describes the efficiency. * `NDims="[1|2|3]"`: The number of kinematic axes for the efficiency curve. * `XAxis="[kMomentum|kKE|kCosTheta|kTheta|kPhi]"`: The kinematic variable spanned by the first dimension of the efficiency histogram. optional attributes: * `YAxis="[kMomentum|kKE|kCosTheta|kTheta|kPhi]"`: The kinematic variable spanned by the second dimension of the efficiency histogram. * `ZAxis="[kMomentum|kKE|kCosTheta|kTheta|kPhi]"`: The kinematic variable spanned by the third dimension of the efficiency histogram. * `Interpolate="[true|false]"`: Whether to use TH1:Interpolate or to take the bin-averaged efficiency. * `[X|Y|Z]AxisScaleToInternal=""`: A scale factor to translate the axes to the internal NUISANCE units (MeV and radians). *e.g.* Use `XAxisScaleToInternal="1E3"` if the input histogram uses kinetic energy in units of GeV. An `EfficiencyApplicator` Can also contain `` and `` tags, as described in `ThresholdAccepter`. Particles that are rejected due to inefficiency get passed to a configured `ThresholdAccepter` instance. *N.B.* it is unlikely that you want to have an `` tag and a `` tag for the same PDG. However, it is possible that particles that failed to be tracked, left some visible energy. ### GaussianSmearer Applies simple smearing to tracked particle kinematics or visible energy deposits. #### Full example ```xml ``` #### Details Each `` tag requires at least: * `PDG="<211,-211>"`: The particle IDs to apply this smearing to. * `Type="[Fractional|Absolute|Function]"`: The type of smearer to use. `Fractional` and `Absolute` use a Gaussian smearer. For `Fractional` the Gaussian width is set to `*ParticleKinematicPropertyValue` and for Absolute it is simple ``. * `Kinematics="[KE|Momentum|TEVis|KEVis|Theta|CosTheta]"`: The particle kinematics to smear. For the majority of practical uses, where an accepter is also in use, `TEVis` and `KEVis` produce the same results. As only a single property smearer can be used per PDG, the use of `Theta` and `CosTheta` are of very limited use. Additional attributes that depend on the value of the `Type` attribute are as follows: * `Width=""`: The width of the Gaussian used for `Fractional` or `Absolute` type smearers. * `Function=""`: The function to throw the smeared values from for `Function` type smearers. The example function here should give the same result as ``. * `P[1|2|3|...]=""`: Extra parameters to replace in the `Function` attribute value. *e.g.*: ``. Mostly just for clarity. An element can contain any number of numbered parameters, but they must be numbered in increasing order. ### TrackedMomentumMatrixSmearer Applies momentum or kinetic energy smearing to tracked particles. #### Full example ```xml ``` #### Details Each `` tag requires at least: * `PDG="<211,-211>"`: The particle IDs to apply this smearing to. * `InputFile=""`: The root file that contains the input smearing matrix. * `HistName=""`: The name of the histogram within in the input root file. Can be located within a subdirectory of the TFile. * `Kinematics="[KE|TE|Momentum]"`: The kinematics to smear. * `MatrixToInternal=""`: The scale factor used to scale the units used in the smearing matrix to MeV. * YIsTrue="[1|0]": Whether the Y or X axis of the input histogram denotes the true kinematic property axis. The `` element can also contain any number of `` element, which are used for PDG codes that do not have a `` element. Their behavior is as in ``. As this smearer can only smear tracked particles, using `` elements to add visible energy smearing is the expected use case. ### VisECoalescer ### EnergyShuffler ### MetaSimpleSmearcepter #### Full example ```xml - - - + + +