diff --git a/app/PrepareGENIE.cxx b/app/PrepareGENIE.cxx index 2999633..2a9cb69 100644 --- a/app/PrepareGENIE.cxx +++ b/app/PrepareGENIE.cxx @@ -1,989 +1,1009 @@ #include "FitLogger.h" #include "PlotUtils.h" #include "TFile.h" #include "TH1D.h" #include "TTree.h" #include "TFolder.h" #include #include #ifdef __GENIE_ENABLED__ #ifdef GENIE_PRE_R3 #include "Conventions/Units.h" #include "GHEP/GHepParticle.h" #include "PDG/PDGUtils.h" #else #include "Framework/Conventions/Units.h" #include "Framework/GHEP/GHepParticle.h" #include "Framework/ParticleData/PDGUtils.h" #endif #endif std::string gInputFiles = ""; std::string gOutputFile = ""; std::string gFluxFile = ""; std::string gTarget = ""; double MonoEnergy; int gNEvents = -999; bool IsMonoE = false; +bool useNOvAWeights = false; void PrintOptions(); void ParseOptions(int argc, char *argv[]); void RunGENIEPrepareMono(std::string input, std::string target, std::string output); void RunGENIEPrepare(std::string input, std::string flux, std::string target, std::string output); bool CheckConfig(std::string filename); int main(int argc, char *argv[]) { ParseOptions(argc, argv); if (IsMonoE) { RunGENIEPrepareMono(gInputFiles, gTarget, gOutputFile); } else { RunGENIEPrepare(gInputFiles, gFluxFile, gTarget, gOutputFile); } } // CWret October 2019 // We have to scale the 2p2h cross-section when the 2p2h generator in GENIE is Nieves // When the 2p2h generator is Empirical no such scaling is needed // This is needed to match the output of PrepareGENIE to GENIE splines from gspl2root // Allow the user to override this for debugging // Search for what model the user ran with bool CheckConfig(std::string filename) { TFile *f = new TFile(filename.c_str()); // Get the config TFolder *first = (TFolder*)f->Get("gconfig"); // Find the GlobalParameterList TFolder *folder = (TFolder*)first->FindObject("GlobalParameterList/Default"); TIter iter(folder->GetListOfFolders()); TKey *key; // Should we scale this? Only if Nieves 2p2h bool ShouldScale = false; while ((key = (TKey*)iter.Next())) { std::string name = key->GetName(); // Look for XSecModel (specifies the interaction model GENIE was run with) // Look for MEC (specifies it's a MEC setting) // Look for Nieves 2p2h from 2016 if (name.find("XSecModel") != std::string::npos && name.find("MEC-CC") != std::string::npos && name.find("NievesSimoVacasMECPXSec2016") != std::string::npos) { ShouldScale = true; } } f->Close(); if (!ShouldScale) { NUIS_LOG(FIT, "Not scaling 2p2h CC events with Nieves..." << std::endl); } else { NUIS_LOG(FIT, "Scaling 2p2h CC events with Nieves..." << std::endl); } return ShouldScale; } void RunGENIEPrepareMono(std::string input, std::string target, std::string output) { NUIS_LOG(FIT, "Running GENIE Prepare in mono energetic with E = " << MonoEnergy << " GeV"); // Setup TTree TChain *tn = new TChain("gtree"); std::string first_file = ""; if (input.find_first_of(',') != std::string::npos) { std::vector inputvect = GeneralUtils::ParseToStr(input, ","); for (size_t iv_it = 0; iv_it < inputvect.size(); ++iv_it) { tn->AddFile(inputvect[iv_it].c_str()); NUIS_LOG(FIT, "Added input file: " << inputvect[iv_it]); if (!first_file.length()) { first_file = inputvect[iv_it]; } } } else { // The Add form can accept wildcards. tn->Add(input.c_str()); first_file = input; } if (tn->GetFile() == NULL) { tn->Print(); NUIS_ERR(FTL, "gtree not located in GENIE file: " << input); NUIS_ABORT("Check your inputs, they may need to be completely regenerated!"); throw; } int nevt = tn->GetEntries(); if (gNEvents != -999) { NUIS_LOG(FIT, "Overriding number of events by user from " << nevt << " to " << gNEvents); nevt = gNEvents; } if (!nevt) { NUIS_ABORT("Couldn't load any events from input specification: \"" << input.c_str() << "\""); } else { NUIS_LOG(FIT, "Found " << nevt << " input entries in " << input); } + StopTalking(); NtpMCEventRecord *genientpl = NULL; tn->SetBranchAddress("gmcrec", &genientpl); + StartTalking(); // Have the TH1D go from MonoEnergy/2 to MonoEnergy/2 TH1D *fluxhist = new TH1D("flux", "flux", 1000, MonoEnergy / 2., MonoEnergy * 2.); fluxhist->Fill(MonoEnergy); fluxhist->Scale(1, "width"); // Make Event Hist TH1D *eventhist = (TH1D *)fluxhist->Clone(); eventhist->Reset(); TH1D *xsechist = (TH1D *)eventhist->Clone(); // Create maps std::map modexsec; std::map modecount; std::vector genieids; std::vector targetids; std::vector interids; // Loop over all events for (int i = 0; i < nevt; i++) { tn->GetEntry(i); StopTalking(); EventRecord &event = *(genientpl->event); GHepParticle *neu = event.Probe(); StartTalking(); // Get XSec From Spline GHepRecord genie_record = static_cast(event); double xsec = (genie_record.XSec() / (1E-38 * genie::units::cm2)); // Parse Interaction String std::string mode = genie_record.Summary()->AsString(); std::vector modevec = GeneralUtils::ParseToStr(mode, ";"); std::string targ = (modevec[0] + ";" + modevec[1]); std::string inter = mode; // Fill lists of Unique IDS if (std::find(targetids.begin(), targetids.end(), targ) == targetids.end()) { targetids.push_back(targ); } if (std::find(interids.begin(), interids.end(), inter) == interids.end()) { interids.push_back(inter); } // Create entries Mode Maps if (modexsec.find(mode) == modexsec.end()) { genieids.push_back(mode); modexsec[mode] = (TH1D *)xsechist->Clone(); modecount[mode] = (TH1D *)xsechist->Clone(); modexsec[mode]->GetYaxis()->SetTitle( "d#sigma/dE_{#nu} #times 10^{-38} (events weighted by #sigma)"); modecount[mode]->GetYaxis()->SetTitle("Number of events in file"); } // Fill XSec Histograms modexsec[mode]->Fill(neu->E(), xsec); modecount[mode]->Fill(neu->E()); // Fill total event hist eventhist->Fill(neu->E()); // Clear Event genientpl->Clear(); size_t freq = nevt / 20; if (freq && !(i % freq)) { NUIS_LOG(FIT, "Processed " << i << "/" << nevt << " GENIE events (E: " << neu->E() << " GeV, xsec: " << xsec << " E-38 cm^2/nucleon)"); } } NUIS_LOG(FIT, "Processed all events"); // Check if we need to correct MEC events before possibly deleting the TChain below bool MECcorrect = CheckConfig(std::string(tn->GetFile()->GetName())); TFile *outputfile; // If no output is specified just append to the file if (!gOutputFile.length()) { // Shut the chain; delete tn; outputfile = new TFile(first_file.c_str(), "UPDATE"); } else { outputfile = new TFile(gOutputFile.c_str(), "RECREATE"); outputfile->cd(); NUIS_LOG(FIT, "Cloning input vector to output file: " << gOutputFile); TTree *cloneTree = tn->CloneTree(-1, "fast"); cloneTree->SetDirectory(outputfile); cloneTree->Write(); - NUIS_LOG(FIT, "Cloning input nova_wgts to output file: " << gOutputFile); - // *********************************** - // *********************************** - // FUDGE FOR NOVA MINERVA WORKSHOP - // Also check for the nova_wgts tree from Jeremy - TChain *nova_chain = new TChain("nova_wgts"); - nova_chain->AddFile(input.c_str()); - TTree *nova_tree = nova_chain->GetTree(); - if (!nova_tree) { - NUIS_LOG(FIT, "Could not find nova_wgts tree in " << gOutputFile); - } else { - NUIS_LOG(FIT, "Found nova_wgts tree in " << gOutputFile); - } - if (nova_tree) { - nova_tree->SetDirectory(outputfile); - nova_tree->Write(); + if (useNOvAWeights){ + NUIS_LOG(FIT, "Cloning input nova_wgts to output file: " << gOutputFile); + // *********************************** + // *********************************** + // FUDGE FOR NOVA MINERVA WORKSHOP + // Also check for the nova_wgts tree from Jeremy + TChain *nova_chain = new TChain("nova_wgts"); + nova_chain->AddFile(input.c_str()); + TTree *nova_tree = nova_chain->GetTree(); + if (!nova_tree) { + NUIS_LOG(FIT, "Could not find nova_wgts tree in " << gOutputFile); + } else { + NUIS_LOG(FIT, "Found nova_wgts tree in " << gOutputFile); + } + if (nova_tree) { + nova_tree->SetDirectory(outputfile); + nova_tree->Write(); + } } NUIS_LOG(FIT, "Done cloning tree."); } NUIS_LOG(FIT, "Getting splines in mono-energetic..."); // Save each of the reconstructed splines to file std::map modeavg; TDirectory *inddir = (TDirectory *)outputfile->Get("IndividualGENIESplines"); if (!inddir) inddir = (TDirectory *)outputfile->mkdir("IndividualGENIESplines"); // Loop over GENIE ID's and get MEC count int MECcount = 0; // Count up the number of MEC splines for (UInt_t i = 0; i < genieids.size(); i++) { if (genieids[i].find("MEC") != std::string::npos && genieids[i].find("[CC]") != std::string::npos) { MECcount++; } } inddir->cd(); for (UInt_t i = 0; i < genieids.size(); i++) { std::string mode = genieids[i]; modexsec[mode]->Write((mode + "_summed_xsec").c_str(), TObject::kOverwrite); modecount[mode]->Write((mode + "_summed_evt").c_str(), TObject::kOverwrite); // Form extra avg xsec map -> Reconstructed spline modeavg[mode] = (TH1D *)modexsec[mode]->Clone(); modeavg[mode]->GetYaxis()->SetTitle( "#sigma (E_{#nu}) #times 10^{-38} (cm^{2}/target)"); modeavg[mode]->Divide(modecount[mode]); if (MECcorrect && mode.find("MEC") != std::string::npos && mode.find("[CC]") != std::string::npos) { NUIS_LOG(FIT, "Scaling spline " << mode << " by 1/" << MECcount << " because there are " << MECcount << " repeated Nieves 2p2h instances."); modeavg[mode]->Scale(1.0 / double(MECcount)); } modeavg[mode]->Write((mode + "_rec_spline").c_str(), TObject::kOverwrite); } TDirectory *targdir = (TDirectory *)outputfile->Get("TargetGENIESplines"); if (!targdir) targdir = (TDirectory *)outputfile->mkdir("TargetGENIESplines"); targdir->cd(); NUIS_LOG(FIT, "Getting Target Splines"); // For each target save a total spline std::map targetsplines; for (uint i = 0; i < targetids.size(); i++) { std::string targ = targetids[i]; NUIS_LOG(FIT, "Getting target " << i << ": " << targ); targetsplines[targ] = (TH1D *)xsechist->Clone(); targetsplines[targ]->GetYaxis()->SetTitle( "#sigma (E_{#nu}) #times 10^{-38} (cm^{2}/target)"); NUIS_LOG(FIT, "Created target spline for " << targ); for (uint j = 0; j < genieids.size(); j++) { std::string mode = genieids[j]; if (mode.find(targ) != std::string::npos) { NUIS_LOG(FIT, " Mode " << mode << " contains " << targ << " target"); targetsplines[targ]->Add(modeavg[mode]); NUIS_LOG(FIT, "Finished with Mode " << mode << " " << modeavg[mode]->Integral()); } } NUIS_LOG(FIT, "Saving target spline:" << targ); targetsplines[targ]->Write(("Total_" + targ).c_str(), TObject::kOverwrite); } NUIS_LOG(FIT, "Getting total splines"); // Now we have each of the targets we need to create a total cross-section. int totalnucl = 0; // Get the targets specified by the user, separated by commas // This has structure target1[fraction1], target2[fraction2] std::vector targprs = GeneralUtils::ParseToStr(target, ","); std::vector targ_list; std::vector frac_list; // Chop up the target string which has format // TARGET1[fraction1],TARGET2[fraction2] // Loop over the vector of strings "TARGET1[fraction1]" "TARGET2[fraction2]" for (std::vector::iterator it = targprs.begin(); it != targprs.end(); ++it) { // Cut into "TARGET1" and "fraction1]" std::vector targind = GeneralUtils::ParseToStr(*it, "["); // Cut into "TARGET1" and "fraction1" for (std::vector::iterator jt = targind.begin(); jt != targind.end(); ++jt) { if ((*jt).find("]") != std::string::npos) { (*jt) = (*jt).substr(0, (*jt).find("]")); frac_list.push_back(*jt); // Won't find bracket for target } else { targ_list.push_back(*jt); } } } targprs = targ_list; std::vector targ_fractions; double minimum = 1.0; for (std::vector::iterator it = frac_list.begin(); it != frac_list.end(); it++) { double frac = std::atof((*it).c_str()); targ_fractions.push_back(frac); if (frac < minimum) minimum = frac; } std::vector::iterator it = targ_fractions.begin(); std::vector::iterator jt = targ_list.begin(); double scaling = 0; for (; it != targ_fractions.end(); it++, jt++) { // First get the mass number from the targ_list int nucl = atoi((*jt).c_str()); nucl = (nucl % 10000) / 10; // Gets the relative portions right *it = (*it) / minimum; // Scale relative the atomic mass double tempscaling = double(nucl) / (*it); if (tempscaling > scaling) scaling = tempscaling; } it = targ_fractions.begin(); for (; it != targ_fractions.end(); it++) { // Round the scaling to nearest integer and multiply *it *= int(scaling + 0.5); // Round to nearest integer *it = int(*it + 0.5); totalnucl += *it; } if (totalnucl == 0) { NUIS_ABORT("Didn't find any nucleons in input file. Did you really specify the " "target ratios?\ne.g. TARGET1[fraction1],TARGET2[fraction2]"); } TH1D *totalxsec = (TH1D *)xsechist->Clone(); for (uint i = 0; i < targprs.size(); i++) { std::string targpdg = targprs[i]; // Check that we found the user requested target in GENIE bool FoundTarget = false; for (std::map::iterator iter = targetsplines.begin(); iter != targetsplines.end(); iter++) { std::string targstr = iter->first; TH1D *xsec = iter->second; // Match the user targets to the targets found in GENIE if (targstr.find(targpdg) != std::string::npos) { FoundTarget = true; NUIS_LOG(FIT, "Adding target spline " << targstr << " Integral = " << xsec->Integral("width")); totalxsec->Add(xsec); } } // Check that targets were all found if (!FoundTarget) { NUIS_ERR(WRN, "Didn't find target " << targpdg << " in the list of targets recorded by GENIE"); NUIS_ERR(WRN, " The list of targets you requested is: "); for (uint i = 0; i < targprs.size(); ++i) NUIS_ERR(WRN, " " << targprs[i]); NUIS_ERR(WRN, " The list of targets found in GENIE is: "); for (std::map::iterator iter = targetsplines.begin(); iter != targetsplines.end(); iter++) NUIS_ERR(WRN, " " << iter->first); } } outputfile->cd(); totalxsec->GetYaxis()->SetTitle( "#sigma (E_{#nu}) #times 10^{-38} (cm^{2}/nucleon)"); totalxsec->Write("nuisance_xsec", TObject::kOverwrite); eventhist = (TH1D *)fluxhist->Clone(); eventhist->Multiply(totalxsec); eventhist->GetYaxis()->SetTitle( (std::string("Event rate (N = #sigma #times #Phi) #times 10^{-38} " "(cm^{2}/nucleon) #times ") + eventhist->GetYaxis()->GetTitle()) .c_str()); NUIS_LOG(FIT, "Dividing by Total Nucl = " << totalnucl); eventhist->Scale(1.0 / double(totalnucl)); eventhist->Write("nuisance_events", TObject::kOverwrite); fluxhist->Write("nuisance_flux", TObject::kOverwrite); NUIS_LOG(FIT, "Inclusive XSec Per Nucleon = " << eventhist->Integral("width") * 1E-38 / fluxhist->Integral("width")); NUIS_LOG(FIT, "XSec Hist Integral = " << totalxsec->Integral("width")); outputfile->Close(); return; } void RunGENIEPrepare(std::string input, std::string flux, std::string target, std::string output) { NUIS_LOG(FIT, "Running GENIE Prepare with flux..."); // Get Flux Hist std::vector fluxvect = GeneralUtils::ParseToStr(flux, ","); TH1 *fluxhist = NULL; if (fluxvect.size() == 3) { double from = GeneralUtils::StrToDbl(fluxvect[0]); double to = GeneralUtils::StrToDbl(fluxvect[1]); double step = GeneralUtils::StrToDbl(fluxvect[2]); int nstep = ceil((to - from) / step); to = from + step * nstep; NUIS_LOG(FIT, "Generating flat flux histogram from " << from << " to " << to << " with bins " << step << " wide (NBins = " << nstep << ")."); fluxhist = new TH1D("spectrum", ";E_{#nu} (GeV);Count (A.U.)", nstep, from, to); for (Int_t bi_it = 1; bi_it < fluxhist->GetXaxis()->GetNbins(); ++bi_it) { fluxhist->SetBinContent(bi_it, 1.0 / double(step * nstep)); } fluxhist->SetDirectory(0); } else if (fluxvect.size() == 2) { TFile *fluxfile = new TFile(fluxvect[0].c_str(), "READ"); if (!fluxfile->IsZombie()) { fluxhist = dynamic_cast(fluxfile->Get(fluxvect[1].c_str())); if (!fluxhist) { NUIS_ERR(FTL, "Couldn't find histogram named: \"" << fluxvect[1] << "\" in file: \"" << fluxvect[0]); throw; } fluxhist->SetDirectory(0); } } else if (fluxvect.size() == 1) { MonoEnergy = GeneralUtils::StrToDbl(fluxvect[0]); RunGENIEPrepareMono(input, target, output); return; } else { NUIS_LOG(FTL, "Bad flux specification: \"" << flux << "\"."); throw; } // Setup TTree TChain *tn = new TChain("gtree"); std::string first_file = ""; if (input.find_first_of(',') != std::string::npos) { std::vector inputvect = GeneralUtils::ParseToStr(input, ","); for (size_t iv_it = 0; iv_it < inputvect.size(); ++iv_it) { tn->AddFile(inputvect[iv_it].c_str()); NUIS_LOG(FIT, "Added input file: " << inputvect[iv_it]); if (!first_file.length()) { first_file = inputvect[iv_it]; } } } else { // The Add form can accept wildcards. tn->Add(input.c_str()); first_file = input; } if (tn->GetFile() == NULL) { tn->Print(); NUIS_ERR(FTL, "gtree not located in GENIE file: " << input); NUIS_ABORT("Check your inputs, they may need to be completely regenerated!"); throw; } int nevt = tn->GetEntries(); if (gNEvents != -999) { NUIS_LOG(FIT, "Overriding number of events by user from " << nevt << " to " << gNEvents); nevt = gNEvents; } if (!nevt) { NUIS_ABORT("Couldn't load any events from input specification: \"" << input.c_str() << "\""); } else { NUIS_LOG(FIT, "Found " << nevt << " input entries in " << input); } + StopTalking(); NtpMCEventRecord *genientpl = NULL; tn->SetBranchAddress("gmcrec", &genientpl); + StartTalking(); // Make Event and xsec Hist TH1D *eventhist = (TH1D *)fluxhist->Clone(); eventhist->SetDirectory(NULL); eventhist->Reset(); TH1D *xsechist = (TH1D *)eventhist->Clone(); xsechist->SetDirectory(NULL); // Create maps std::map modexsec; std::map modecount; std::vector genieids; std::vector targetids; std::vector interids; // Loop over all events for (int i = 0; i < nevt; i++) { tn->GetEntry(i); // Hussssch GENIE StopTalking(); // Get the event EventRecord &event = *(genientpl->event); // Get the neutrino GHepParticle *neu = event.Probe(); StartTalking(); // Get XSec From Spline // Get the GHepRecord GHepRecord genie_record = static_cast(event); double xsec = (genie_record.XSec() / (1E-38 * genie::units::cm2)); // Parse Interaction String std::string mode = genie_record.Summary()->AsString(); std::vector modevec = GeneralUtils::ParseToStr(mode, ";"); std::string targ = (modevec[0] + ";" + modevec[1]); std::string inter = mode; // Get target nucleus // Alternative ways of getting the summaries // GHepParticle *target = genie_record.TargetNucleus(); // int pdg = target->Pdg(); // Fill lists of Unique IDS (neutrino and target) if (std::find(targetids.begin(), targetids.end(), targ) == targetids.end()) { targetids.push_back(targ); } // The full interaction list if (std::find(interids.begin(), interids.end(), inter) == interids.end()) { interids.push_back(inter); } // Create entries Mode Maps if (modexsec.find(mode) == modexsec.end()) { genieids.push_back(mode); modexsec[mode] = (TH1D *)xsechist->Clone(); modecount[mode] = (TH1D *)xsechist->Clone(); modexsec[mode]->SetDirectory(NULL); modecount[mode]->SetDirectory(NULL); modexsec[mode]->GetYaxis()->SetTitle( "d#sigma/dE_{#nu} #times 10^{-38} (events weighted by #sigma)"); modecount[mode]->GetYaxis()->SetTitle("Number of events in file"); } // Fill XSec Histograms modexsec[mode]->Fill(neu->E(), xsec); modecount[mode]->Fill(neu->E()); // Fill total event hist eventhist->Fill(neu->E()); if (i % (nevt / 20) == 0) { NUIS_LOG(FIT, "Processed " << i << "/" << nevt << " GENIE events (E: " << neu->E() << " GeV, xsec: " << xsec << " E-38 cm^2/nucleon)"); } // Clear Event genientpl->Clear(); } NUIS_LOG(FIT, "Processed all events"); // Check if we need to correct MEC events before possibly deleting the TChain below bool MECcorrect = CheckConfig(std::string(tn->GetFile()->GetName())); // Once event loop is done we can start saving stuff into the file TFile *outputfile; if (!gOutputFile.length()) { // Shut the chain; delete tn; outputfile = new TFile(first_file.c_str(), "UPDATE"); } else { outputfile = new TFile(gOutputFile.c_str(), "RECREATE"); outputfile->cd(); NUIS_LOG(FIT, "Cloning input vector to output file: " << gOutputFile); TTree *cloneTree = tn->CloneTree(-1, "fast"); cloneTree->SetDirectory(outputfile); cloneTree->Write(); - // ******************************** - // CLUDGE KLUDGE KLUDGE FOR NOVA - NUIS_LOG(FIT, "Cloning input nova_wgts to output file: " << gOutputFile); - // Also check for the nova_wgts tree from Jeremy - TChain *nova_chain = new TChain("nova_wgts"); - nova_chain->AddFile(input.c_str()); - TTree *nova_tree = nova_chain->CloneTree(-1, "fast"); - if (!nova_tree) { - NUIS_LOG(FIT, "Could not find nova_wgts tree in " << input); - } else { - NUIS_LOG(FIT, "Found nova_wgts tree in " << input); - nova_tree->SetDirectory(outputfile); - nova_tree->Write(); + if (useNOvAWeights){ + // ******************************** + // CLUDGE KLUDGE KLUDGE FOR NOVA + NUIS_LOG(FIT, "Cloning input nova_wgts to output file: " << gOutputFile); + // Also check for the nova_wgts tree from Jeremy + TChain *nova_chain = new TChain("nova_wgts"); + nova_chain->AddFile(input.c_str()); + TTree *nova_tree = nova_chain->CloneTree(-1, "fast"); + if (!nova_tree) { + NUIS_LOG(FIT, "Could not find nova_wgts tree in " << input); + } else { + NUIS_LOG(FIT, "Found nova_wgts tree in " << input); + nova_tree->SetDirectory(outputfile); + nova_tree->Write(); + } } NUIS_LOG(FIT, "Done cloning tree."); } NUIS_LOG(FIT, "Getting splines..."); // Save each of the reconstructed splines to file std::map modeavg; TDirectory *inddir = (TDirectory *)outputfile->Get("IndividualGENIESplines"); if (!inddir) inddir = (TDirectory *)outputfile->mkdir("IndividualGENIESplines"); // Loop over GENIE ID's and get MEC count int MECcount = 0; for (UInt_t i = 0; i < genieids.size(); i++) { if (genieids[i].find("MEC") != std::string::npos && genieids[i].find("[CC]") != std::string::npos) { MECcount++; } } inddir->cd(); for (UInt_t i = 0; i < genieids.size(); i++) { std::string mode = genieids[i]; modexsec[mode]->Write((mode + "_summed_xsec").c_str(), TObject::kOverwrite); modecount[mode]->Write((mode + "_summed_evt").c_str(), TObject::kOverwrite); // Form extra avg xsec map -> Reconstructed spline modeavg[mode] = (TH1D *)modexsec[mode]->Clone(); modeavg[mode]->GetYaxis()->SetTitle( "#sigma (E_{#nu}) #times 10^{-38} (cm^{2}/target)"); modeavg[mode]->Divide(modecount[mode]); if (MECcorrect && mode.find("MEC") != std::string::npos && mode.find("[CC]") != std::string::npos) { NUIS_LOG(FIT, "Scaling spline " << mode << " by 1/" << MECcount << " because there are " << MECcount << " repeated Nieves 2p2h instances."); modeavg[mode]->Scale(1.0 / double(MECcount)); } modeavg[mode]->Write((mode + "_rec_spline").c_str(), TObject::kOverwrite); } TDirectory *targdir = (TDirectory *)outputfile->Get("TargetGENIESplines"); if (!targdir) targdir = (TDirectory *)outputfile->mkdir("TargetGENIESplines"); targdir->cd(); NUIS_LOG(FIT, "Getting Target Splines"); // For each target save a total spline std::map targetsplines; for (uint i = 0; i < targetids.size(); i++) { std::string targ = targetids[i]; NUIS_LOG(FIT, "Getting target " << i << ": " << targ); targetsplines[targ] = (TH1D *)xsechist->Clone(); targetsplines[targ]->GetYaxis()->SetTitle( "#sigma (E_{#nu}) #times 10^{-38} (cm^{2}/target)"); NUIS_LOG(FIT, "Created target spline for " << targ); for (uint j = 0; j < genieids.size(); j++) { std::string mode = genieids[j]; // Look at all matching modes/targets if (mode.find(targ) != std::string::npos) { NUIS_LOG(FIT, " Mode " << mode << " contains " << targ << " target"); targetsplines[targ]->Add(modeavg[mode]); NUIS_LOG(FIT, "Finished with Mode " << mode << " " << modeavg[mode]->Integral()); } } NUIS_LOG(FIT, "Saving target spline: " << targ); targetsplines[targ]->Write(("Total_" + targ).c_str(), TObject::kOverwrite); } NUIS_LOG(FIT, "Getting total splines"); // Now we have each of the targets we need to create a total cross-section. int totalnucl = 0; // This has structure target1[fraction1], target2[fraction2] std::vector targprs = GeneralUtils::ParseToStr(target, ","); std::vector targ_list; std::vector frac_list; // Chop up the target string which has format // TARGET1[fraction1],TARGET2[fraction2] // Loop over the vector of strings "TARGET1[fraction1]" "TARGET2[fraction2]" for (std::vector::iterator it = targprs.begin(); it != targprs.end(); ++it) { // Cut into "TARGET1" and "fraction1]" std::vector targind = GeneralUtils::ParseToStr(*it, "["); // Cut into "TARGET1" and "fraction1" for (std::vector::iterator jt = targind.begin(); jt != targind.end(); ++jt) { if ((*jt).find("]") != std::string::npos) { (*jt) = (*jt).substr(0, (*jt).find("]")); frac_list.push_back(*jt); // Won't find bracket for target } else { targ_list.push_back(*jt); } } } targprs = targ_list; std::vector targ_fractions; double minimum = 1.0; for (std::vector::iterator it = frac_list.begin(); it != frac_list.end(); it++) { double frac = std::atof((*it).c_str()); targ_fractions.push_back(frac); if (frac < minimum) minimum = frac; } std::vector::iterator it = targ_fractions.begin(); std::vector::iterator jt = targ_list.begin(); double scaling = 0; for (; it != targ_fractions.end(); it++, jt++) { // First get the mass number from the targ_list int nucl = atoi((*jt).c_str()); nucl = (nucl % 10000) / 10; // Gets the relative portions right *it = (*it) / minimum; // Scale relative the atomic mass //(*it) *= (double(nucl)/(*it)); double tempscaling = double(nucl) / (*it); if (tempscaling > scaling) scaling = tempscaling; } it = targ_fractions.begin(); for (; it != targ_fractions.end(); it++) { // Round the scaling to nearest integer and multiply *it *= int(scaling + 0.5); // Round to nearest integer *it = int(*it + 0.5); totalnucl += *it; } if (totalnucl == 0) { NUIS_ABORT("Didn't find any nucleons in input file. Did you really specify the " "target ratios?\ne.g. TARGET1[fraction1],TARGET2[fraction2]"); } TH1D *totalxsec = (TH1D *)xsechist->Clone(); // Loop over the specified targets by the user for (uint i = 0; i < targprs.size(); i++) { std::string targpdg = targprs[i]; // Check that we found the user requested target in GENIE bool FoundTarget = false; for (std::map::iterator iter = targetsplines.begin(); iter != targetsplines.end(); iter++) { std::string targstr = iter->first; TH1D *xsec = iter->second; // Match the user targets to the targets found in GENIE if (targstr.find(targpdg) != std::string::npos) { FoundTarget = true; NUIS_LOG(FIT, "Adding target spline " << targstr << " Integral = " << xsec->Integral("width")); totalxsec->Add(xsec); // int nucl = atoi(targpdg.c_str()); // totalnucl += int((nucl % 10000) / 10); } } // Looped over target splines // Check that targets were all found if (!FoundTarget) { NUIS_ERR(WRN, "Didn't find target " << targpdg << " in the list of targets recorded by GENIE"); NUIS_ERR(WRN, " The list of targets you requested is: "); for (uint i = 0; i < targprs.size(); ++i) NUIS_ERR(WRN, " " << targprs[i]); NUIS_ERR(WRN, " The list of targets found in GENIE is: "); for (std::map::iterator iter = targetsplines.begin(); iter != targetsplines.end(); iter++) NUIS_ERR(WRN, " " << iter->first); } } outputfile->cd(); totalxsec->GetYaxis()->SetTitle( "#sigma (E_{#nu}) #times 10^{-38} (cm^{2}/nucleon)"); totalxsec->Write("nuisance_xsec", TObject::kOverwrite); eventhist = (TH1D *)fluxhist->Clone(); eventhist->Multiply(totalxsec); eventhist->GetYaxis()->SetTitle( (std::string("Event rate (N = #sigma #times #Phi) #times 10^{-38} " "(cm^{2}/nucleon) #times ") + eventhist->GetYaxis()->GetTitle()) .c_str()); NUIS_LOG(FIT, "Dividing by Total Nucl = " << totalnucl); eventhist->Scale(1.0 / double(totalnucl)); eventhist->Write("nuisance_events", TObject::kOverwrite); fluxhist->Write("nuisance_flux", TObject::kOverwrite); NUIS_LOG(FIT, "Inclusive XSec Per Nucleon = " << eventhist->Integral("width") * 1E-38 / fluxhist->Integral("width")); NUIS_LOG(FIT, "XSec Hist Integral = " << totalxsec->Integral()); outputfile->Close(); return; }; void PrintOptions() { std::cout << "PrepareGENIE events NUISANCE app. " << std::endl << "Takes GHep Outputs and prepares events for NUISANCE." << std::endl << std::endl << "PrepareGENIE [-h,-help,--h,--help] [-i " "inputfile1.root,inputfile2.root,inputfile3.root,...] " << "[-f flux_root_file.root,flux_hist_name] [-t " "target1[frac1],target2[frac2],...]" << "[-n number_of_events (experimental)]" << std::endl << std::endl; std::cout << "Prepare Mode [Default] : Takes a single GHep file, " "reconstructs the original GENIE splines, " << " and creates a duplicate file that also contains the flux, " "event rate, and xsec predictions that NUISANCE needs. " << std::endl; std::cout << "Following options are required for Prepare Mode:" << std::endl; std::cout << " [ -i inputfile.root ] : Reads in a single GHep input file " "that needs the xsec calculation ran on it. " << std::endl; std::cout << " [ -f flux_file.root,hist_name ] : Path to root file " "containing the flux histogram the GHep records were generated " "with." << " A simple method is to point this to the flux histogram genie " "generatrs '-f /path/to/events/input-flux.root,spectrum'. " << std::endl; std::cout << " [ -f elow,ehigh,estep ] : Energy range specification when no " "flux file was used." << std::endl; std::cout << " [ -t target ] : Target that GHepRecords were generated with. " - "Comma seperated list with fractions. E.g. for CH2 " + "Comma separated list with fractions. E.g. for CH2 " "target=1000060120[0.923076],1000010010[0.076924]" << std::endl; std::cout << " [ -o outputfile.root ] : File to write prepared input file to." << std::endl; std::cout << " [ -m Mono_E_nu_GeV ] : Run in mono-energetic mode with m GeV " "neutrino energy." << std::endl; std::cout << " [ -n number_of_evt ] : Run with a reduced number of events " "for debugging purposes" << std::endl; } void ParseOptions(int argc, char *argv[]) { bool flagopt = false; + int verbocount = 0; + int errorcount = 0; + verbocount += Config::GetParI("VERBOSITY"); + errorcount += Config::GetParI("ERROR"); + bool trace = Config::GetParB("TRACE"); + std::cout << "[ NUISANCE ]: Setting VERBOSITY=" << verbocount << std::endl; + std::cout << "[ NUISANCE ]: Setting ERROR=" << errorcount << std::endl; + SETVERBOSITY(verbocount); + SETTRACE(trace); + + // If No Arguments print commands for (int i = 1; i < argc; ++i) { if (!std::strcmp(argv[i], "-h")) { flagopt = true; break; } if (i + 1 != argc) { // Cardfile if (!std::strcmp(argv[i], "-h")) { flagopt = true; break; } else if (!std::strcmp(argv[i], "-i")) { gInputFiles = argv[i + 1]; ++i; } else if (!std::strcmp(argv[i], "-o")) { gOutputFile = argv[i + 1]; ++i; } else if (!std::strcmp(argv[i], "-f")) { gFluxFile = argv[i + 1]; ++i; } else if (!std::strcmp(argv[i], "-t")) { gTarget = argv[i + 1]; ++i; } else if (!std::strcmp(argv[i], "-n")) { gNEvents = GeneralUtils::StrToInt(argv[i + 1]); ++i; } else if (!std::strcmp(argv[i], "-m")) { MonoEnergy = GeneralUtils::StrToDbl(argv[i + 1]); IsMonoE = true; ++i; } else { NUIS_ERR(FTL, "ERROR: unknown command line option given! - '" << argv[i] << " " << argv[i + 1] << "'"); PrintOptions(); break; } } } if (gInputFiles == "" && !flagopt) { NUIS_ERR(FTL, "No input file(s) specified!"); flagopt = true; } if (gFluxFile == "" && !flagopt && !IsMonoE) { NUIS_ERR(FTL, "No flux input specified for Prepare Mode"); flagopt = true; } if (gTarget == "" && !flagopt) { NUIS_ERR(FTL, "No target specified for Prepare Mode"); flagopt = true; } if (gTarget.find("[") == std::string::npos || gTarget.find("]") == std::string::npos) { NUIS_ERR(FTL, "Didn't specify target ratios in Prepare Mode"); NUIS_ERR(FTL, "Are you sure you gave it as -t " "\"TARGET1[fraction1],TARGET2[fraction]\"?"); flagopt = true; } if (argc < 1 || flagopt) { PrintOptions(); exit(-1); } return; } diff --git a/app/PrepareNuwroEvents.cxx b/app/PrepareNuwroEvents.cxx index 2f777b9..720be7b 100644 --- a/app/PrepareNuwroEvents.cxx +++ b/app/PrepareNuwroEvents.cxx @@ -1,492 +1,507 @@ #include "event1.h" #include #include // Hopefully we don't need these as they're included above. // #include "params_all.h" // #include "params.h" #include "FitLogger.h" #include "PlotUtils.h" #include "TFile.h" #include "TH1D.h" #include "TTree.h" void printInputCommands(char *argv[]) { std::cout << "[USAGE]: " << argv[0] << " [-h] [-f] [-F ,[,PDG[,speciesFraction]] [-o output.root] " "inputfile.root [file2.root ...]" << std::endl << "\t-h : Print this message." << std::endl << "\t-f : Pass -f argument to '$ hadd' invocation." << std::endl << "\t-F : Read input flux from input descriptor." << std::endl << "\t-o : Write full output to a new file." << std::endl << std::endl; }; void CreateRateHistograms(std::string inputs, bool force_out); void HaddNuwroFiles(std::vector &inputs, bool force_out); bool outputNewFile = false; std::string ofile = ""; bool haveFluxInputs = false; struct FluxInputBlob { FluxInputBlob(std::string _File, std::string _Hist, int _PDG, double _Fraction) : File(_File), Hist(_Hist), PDG(_PDG), Fraction(_Fraction) {} std::string File; std::string Hist; int PDG; double Fraction; }; std::vector FluxInputs; bool haddedFiles = false; TH1D *F2D(TH1F *f) { Double_t *bins = new Double_t[f->GetXaxis()->GetNbins() + 1]; for (Int_t bi_it = 0; bi_it < f->GetXaxis()->GetNbins(); ++bi_it) { bins[bi_it] = f->GetXaxis()->GetBinLowEdge(bi_it + 1); } bins[f->GetXaxis()->GetNbins()] = f->GetXaxis()->GetBinUpEdge(f->GetXaxis()->GetNbins()); TH1D *d = new TH1D((std::string(f->GetName()) + "_f").c_str(), f->GetTitle(), f->GetXaxis()->GetNbins(), bins); std::cout << "Converted TH1F with " << f->GetXaxis()->GetXbins() << " bins : " << std::endl; for (Int_t bi_it = 0; bi_it < f->GetXaxis()->GetNbins() + 2; ++bi_it) { d->SetBinContent(bi_it, f->GetBinContent(bi_it)); d->SetBinError(bi_it, f->GetBinError(bi_it)); std::cout << "\tF " << f->GetXaxis()->GetBinLowEdge(bi_it) << "--[" << bi_it << "]--" << f->GetXaxis()->GetBinUpEdge(bi_it) << ": " << f->GetBinContent(bi_it) << " D " << d->GetXaxis()->GetBinLowEdge(bi_it) << "--[" << bi_it << "]--" << d->GetXaxis()->GetBinUpEdge(bi_it) << ": " << d->GetBinContent(bi_it) << std::endl; } delete bins; return d; } TH1D *GetTH1DFromFile(std::string const &rootFile, std::string const &histName) { TFile *inpFile = new TFile(rootFile.c_str(), "READ"); if (!inpFile || !inpFile->IsOpen()) { NUIS_ABORT("Cannot open input root file: " << rootFile << " to read input histo."); } TH1D *histD = dynamic_cast(inpFile->Get(histName.c_str())); if (!histD) { TH1F *histF = dynamic_cast(inpFile->Get(histName.c_str())); if (!histF) { NUIS_ABORT("Cannot find TH1D/F: " << histName << " in root file: " << rootFile << "."); } histD = F2D(histF); } else { histD = static_cast(histD->Clone()); } histD->SetDirectory(NULL); inpFile->Close(); return histD; } //******************************* int main(int argc, char *argv[]) { //******************************* // If No Arguments print commands if (argc == 1) { printInputCommands(argv); return 0; } + + int verbocount = 0; + int errorcount = 0; + verbocount += Config::GetParI("VERBOSITY"); + errorcount += Config::GetParI("ERROR"); + bool trace = Config::GetParB("TRACE"); + std::cout << "[ NUISANCE ]: Setting VERBOSITY=" << verbocount << std::endl; + std::cout << "[ NUISANCE ]: Setting ERROR=" << errorcount << std::endl; + SETVERBOSITY(verbocount); + SETTRACE(trace); + std::vector inputfiles; bool force_output = false; // Get Inputs for (int i = 1; i < argc; ++i) { if (!std::strcmp(argv[i], "-h")) { printInputCommands(argv); return 0; } else if (!std::strcmp(argv[i], "-f")) { force_output = true; } else if (!std::strcmp(argv[i], "-o")) { outputNewFile = true; ofile = argv[++i]; } else if (!std::strcmp(argv[i], "-F")) { std::string inpLine = argv[++i]; std::vector fluxInputDescriptor = GeneralUtils::ParseToStr(inpLine, ","); if ((fluxInputDescriptor.size() != 2) && (fluxInputDescriptor.size() != 3) && (fluxInputDescriptor.size() != 4)) { NUIS_ABORT("Received -F argument with option: \"" << inpLine << "\", was expecting " ",[,PDG[,speciesFraction]]."); } haveFluxInputs = true; FluxInputs.push_back( FluxInputBlob(fluxInputDescriptor[0], fluxInputDescriptor[1], (fluxInputDescriptor.size() > 2) ? GeneralUtils::StrToInt(fluxInputDescriptor[2]) : 14, (fluxInputDescriptor.size() > 3) ? GeneralUtils::StrToDbl(fluxInputDescriptor[3]) : 1)); if (!FluxInputs.back().File.length() || !FluxInputs.back().Hist.length()) { NUIS_ABORT("Received -F argument with option: \"" << inpLine << "\", was expecting " ",[,PDG[,speciesFraction]]."); } } else { inputfiles.push_back(std::string(argv[i])); } } // If one input file just create flux histograms if (inputfiles.size() > (UInt_t)1) { HaddNuwroFiles(inputfiles, force_output); } else if (inputfiles.size() < (UInt_t)1) { printInputCommands(argv); } CreateRateHistograms(inputfiles[0], force_output); NUIS_LOG(FIT, "Finished NUWRO Prep."); }; //******************************* void CreateRateHistograms(std::string inputs, bool force_out) { //******************************* // Open root file TFile *outRootFile = 0; TTree *nuwrotree = 0; if (!haddedFiles && outputNewFile) { // we need to make the new file and clone the tree. TFile *inpFile = new TFile(inputs.c_str(), "READ"); if (!inpFile || !inpFile->IsOpen()) { NUIS_ABORT("Cannot open input root file: " << inputs); } TTree *inpTree = dynamic_cast(inpFile->Get("treeout")); if (!inpTree) { NUIS_ABORT("Cannot find TTree \"treeout\" in input root file: " << inputs.c_str()); } outRootFile = new TFile(ofile.c_str(), force_out ? "RECREATE" : "CREATE"); if (!outRootFile || !outRootFile->IsOpen()) { NUIS_ABORT("Couldn't open root file: " << ofile << " for writing, does it already exist?"); } nuwrotree = inpTree->CloneTree(-1, "fast"); nuwrotree->SetDirectory(outRootFile); nuwrotree->Write(nuwrotree->GetName()); } else { outRootFile = new TFile(inputs.c_str(), "UPDATE"); if (!outRootFile || !outRootFile->IsOpen()) { NUIS_ABORT("Cannot open input root file: " << inputs); } nuwrotree = dynamic_cast(outRootFile->Get("treeout")); if (!nuwrotree) { NUIS_ABORT("Cannot find TTree \"treeout\" in input root file: " << inputs.c_str()); } } // Get Flux Histogram event *evt = new event(); nuwrotree->SetBranchAddress("e", &evt); nuwrotree->GetEntry(0); int fluxtype = evt->par.beam_type; std::map fluxlist; std::map eventlist; std::vector allpdg; std::map nevtlist; std::map intxseclist; // Did the input file have a mono-energetic flux? bool isMono = false; nevtlist[0] = 0.0; intxseclist[0] = 0.0; allpdg.push_back(0); NUIS_LOG(FIT, "Nuwro fluxtype = " << fluxtype); if (haveFluxInputs) { double totalFraction = 0; for (size_t flux_it = 0; flux_it < FluxInputs.size(); ++flux_it) { FluxInputBlob &fb = FluxInputs[flux_it]; int pdg = fb.PDG; TH1D *fluxHist = GetTH1DFromFile(fb.File, fb.Hist); double pctg = fb.Fraction; totalFraction += pctg; double Elow = fluxHist->GetXaxis()->GetBinLowEdge(1); double Ehigh = fluxHist->GetXaxis()->GetBinLowEdge( fluxHist->GetXaxis()->GetNbins() + 1); NUIS_LOG(FIT, "Adding new nuwro flux " << "pdg: " << pdg << " pctg: " << pctg << " Elow: " << Elow << " Ehigh: " << Ehigh); // Sort total flux plot if (!fluxlist[0]) { // Setup total flux fluxlist[0] = (TH1D *)fluxHist->Clone(); fluxlist[0]->SetNameTitle("FluxHist", "FluxHist"); // Prep empty total events eventlist[0] = (TH1D *)fluxHist->Clone(); eventlist[0]->SetNameTitle("EvtHist", "EvtHist"); eventlist[0]->Reset(); } else { // Add up each new plot fluxlist[0]->Add(fluxHist); } fluxHist->SetNameTitle(Form("nuwro_pdg%i_pct%f_Flux", pdg, pctg), Form("nuwro_pdg%i_pct%f_Flux", pdg, pctg)); TH1D *eventplot = (TH1D *)fluxHist->Clone(); eventplot->SetNameTitle(Form("nuwro_pdg%i_pct%f_Evt", pdg, pctg), Form("nuwro_pdg%i_pct%f_Evt", pdg, pctg)); eventplot->Reset(); fluxlist[pdg] = (TH1D *)fluxHist->Clone(); eventlist[pdg] = eventplot; nevtlist[pdg] = 0; intxseclist[pdg] = 0.0; allpdg.push_back(pdg); delete fluxHist; } if (fabs(totalFraction - 1) > 1E-5) { NUIS_ABORT("Total species fraction for input flux histos = " << totalFraction << ", expected to sum to 1."); } } else if (fluxtype == 0) { std::string fluxstring = evt->par.beam_energy; std::vector fluxvals = GeneralUtils::ParseToDbl(fluxstring, " "); int pdg = evt->par.beam_particle; double Elow = double(fluxvals[0]) / 1000.0; double Ehigh = double(fluxvals[1]) / 1000.0; TH1D *fluxplot = NULL; if (Elow > Ehigh) isMono = true; // For files produced with a flux distribution if (!isMono) { NUIS_LOG(FIT, "Adding new nuwro flux " << "pdg: " << pdg << " Elow: " << Elow << " Ehigh: " << Ehigh); fluxplot = new TH1D("fluxplot", "fluxplot", fluxvals.size() - 4, Elow, Ehigh); for (uint j = 2; j < fluxvals.size(); j++) { NUIS_LOG(DEB, j << " " << fluxvals[j]); fluxplot->SetBinContent(j - 1, fluxvals[j]); } } else { // For monoenergetic fluxes NUIS_LOG(FIT, "Adding mono-energetic nuwro flux " << "pdg: " << pdg << " E: " << Elow); fluxplot = new TH1D("fluxplot", "fluxplot", 100, 0, Elow * 2); fluxplot->SetBinContent(fluxplot->FindBin(Elow), 1); } // Setup total flux fluxlist[0] = (TH1D *)fluxplot->Clone(); fluxlist[0]->SetNameTitle("FluxHist", "FluxHist"); // Prep empty total events eventlist[0] = (TH1D *)fluxplot->Clone(); eventlist[0]->SetNameTitle("EvtHist", "EvtHist"); eventlist[0]->Reset(); fluxplot->SetNameTitle(Form("nuwro_pdg%i_Flux", pdg), Form("nuwro_pdg%i_Flux", pdg)); TH1D *eventplot = (TH1D *)fluxplot->Clone(); eventplot->SetNameTitle(Form("nuwro_pdg%i_Evt", pdg), Form("nuwro_pdg%i_Evt", pdg)); eventplot->Reset(); fluxlist[pdg] = fluxplot; eventlist[pdg] = eventplot; nevtlist[pdg] = 0; intxseclist[pdg] = 0.0; allpdg.push_back(pdg); } else if (fluxtype == 1) { std::string fluxstring = evt->par.beam_content; std::vector fluxlines = GeneralUtils::ParseToStr(fluxstring, "\n"); for (uint i = 0; i < fluxlines.size(); i++) { std::vector fluxvals = GeneralUtils::ParseToDbl(fluxlines[i], " "); int pdg = int(fluxvals[0]); double pctg = double(fluxvals[1]) / 100.0; double Elow = double(fluxvals[2]) / 1000.0; double Ehigh = double(fluxvals[3]) / 1000.0; NUIS_LOG(FIT, "Adding new nuwro flux " << "pdg: " << pdg << " pctg: " << pctg << " Elow: " << Elow << " Ehigh: " << Ehigh); TH1D *fluxplot = new TH1D("fluxplot", "fluxplot", fluxvals.size() - 4, Elow, Ehigh); for (uint j = 4; j < fluxvals.size(); j++) { fluxplot->SetBinContent(j + 1, fluxvals[j]); } // Sort total flux plot if (!fluxlist[0]) { // Setup total flux fluxlist[0] = (TH1D *)fluxplot->Clone(); fluxlist[0]->SetNameTitle("FluxHist", "FluxHist"); // Prep empty total events eventlist[0] = (TH1D *)fluxplot->Clone(); eventlist[0]->SetNameTitle("EvtHist", "EvtHist"); eventlist[0]->Reset(); } else { // Add up each new plot fluxlist[0]->Add(fluxplot); } fluxplot->SetNameTitle(Form("nuwro_pdg%i_pct%f_Flux", pdg, pctg), Form("nuwro_pdg%i_pct%f_Flux", pdg, pctg)); TH1D *eventplot = (TH1D *)fluxplot->Clone(); eventplot->SetNameTitle(Form("nuwro_pdg%i_pct%f_Evt", pdg, pctg), Form("nuwro_pdg%i_pct%f_Evt", pdg, pctg)); eventplot->Reset(); fluxlist[pdg] = fluxplot; eventlist[pdg] = eventplot; nevtlist[pdg] = 0; intxseclist[pdg] = 0.0; allpdg.push_back(pdg); } } // Start main event loop to fill plots int nevents = nuwrotree->GetEntries(); double Enu = 0.0; double TotXSec = 0.0; // double totaleventmode = 0.0; // double totalevents = 0.0; int pdg = 0; int countwidth = nevents / 50.0; countwidth = countwidth ? countwidth : 1; for (int i = 0; i < nevents; i++) { nuwrotree->GetEntry(i); // Get Variables Enu = evt->in[0].t / 1000.0; TotXSec = evt->weight; pdg = evt->in[0].pdg; + + if (std::find(allpdg.begin(), allpdg.end(), pdg) == allpdg.end()) { + NUIS_ABORT("Not set up to handle PDG: " << pdg << " check your inputs"); + } eventlist[0]->Fill(Enu); eventlist[pdg]->Fill(Enu); nevtlist[0] += 1; nevtlist[pdg] += 1; intxseclist[0] += TotXSec; intxseclist[pdg] += TotXSec; if (i % countwidth == 0) { NUIS_LOG(FIT, "Processed " << i << " events " << " (" << int(i * 100.0 / nevents) << "%)" << " : E, W, PDG = " << Enu << ", " << TotXSec << ", " << pdg) } } TH1D *zeroevents = (TH1D *)eventlist[0]->Clone(); outRootFile->cd(); // Loop over eventlist for (uint i = 0; i < allpdg.size(); i++) { int pdg = allpdg[i]; double AvgXSec = intxseclist[0] * 1E38 / double(nevtlist[0]); NUIS_LOG(FIT, pdg << " Avg XSec = " << AvgXSec); NUIS_LOG(FIT, pdg << " nevents = " << double(nevtlist[pdg])); if (!isMono) { // Convert events to PDF eventlist[pdg]->Scale(1.0 / zeroevents->Integral("width")); // Multiply by total predicted event rate eventlist[pdg]->Scale(fluxlist[0]->Integral("width") * AvgXSec); } else { // If a mono-energetic flux was used, width should not be used // The output is (now) forced to be flux = 1, evtrt = xsec (in 1E38 * nb // cm^2) eventlist[pdg]->Scale(1.0 / zeroevents->Integral()); eventlist[pdg]->Scale(fluxlist[0]->Integral() * AvgXSec); } // Save everything fluxlist[pdg]->Write("", TObject::kOverwrite); eventlist[pdg]->Write("", TObject::kOverwrite); } // Tidy up outRootFile->Close(); fluxlist.clear(); eventlist.clear(); // Exit Program return; } //******************************* void HaddNuwroFiles(std::vector &inputs, bool force_out) { //******************************* // Get output file name std::string outputname = inputs[0]; // Make command line string std::string cmd = "hadd "; if (outputNewFile) { cmd += ofile + " "; outputname = ofile; } else if (force_out) { cmd += "-f "; } for (UInt_t i = 0; i < inputs.size(); i++) { cmd += inputs[i] + " "; } NUIS_LOG(FIT, " Running HADD from PrepareNuwro: " << cmd); // Start HADD system(cmd.c_str()); // Return name of output file inputs.clear(); inputs.push_back(outputname); haddedFiles = true; return; } diff --git a/app/neut_NUISANCE.cxx b/app/neut_NUISANCE.cxx index c3d0a39..55bfa30 100644 --- a/app/neut_NUISANCE.cxx +++ b/app/neut_NUISANCE.cxx @@ -1,911 +1,911 @@ #ifdef __NEUT_ENABLED__ #include "ComparisonRoutines.h" #include "ParserUtils.h" #include "TargetUtils.h" #ifdef WINDOWS #include #define GetCurrentDir _getcwd #else #include #define GetCurrentDir getcwd #endif // 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/neut/Default_params.txt int gOptSeed = time(NULL); std::string gOptTargetDef = ""; std::string gOptFluxDef = ""; std::string gOptOutputFile = ""; int gOptRunNumber = -1; using namespace TargetUtils; void GetCommandLineArgs(int argc, char **argv); void PrintSyntax(void); std::string GETCWD() { char cCurrentPath[FILENAME_MAX]; if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))) { NUIS_ABORT("CANT FIND CURRENT DIRECTORY!"); } std::string curdir = std::string(cCurrentPath); return curdir; } std::string ExpandPath(std::string name) { // Get Current char cCurrentPath[FILENAME_MAX]; if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath))) { NUIS_ABORT("CANT FIND CURRENT DIRECTORY!"); } std::string curdir = std::string(cCurrentPath); // If first entry is not / then add the current working directory if (!name.empty() and name.at(0) != '/') { name = curdir + "/" + name; } return name; } std::string GetBaseName(std::string name) { std::vector splitfile = GeneralUtils::ParseToStr(name, "/"); std::string filename = ""; if (splitfile.size() == 1) { filename = splitfile[0]; } else if (splitfile.size() > 1) { filename = splitfile[splitfile.size() - 1]; } else { NUIS_ABORT("Cannot split filename: " << name); } return filename; } std::string GetDynamicModes(std::string list, bool neutrino) { NUIS_LOG(FIT, "Using " << list << " to define interaction modes for Neutrino=" << neutrino); std::map modes; std::vector ids; // Create vector of ids for the print out and future reference /* C C nu nub C 1: CC Q.E. CC Q.E.( Free ) C 2-4: CC 1pi CC 1pi C 5: CC DIS 1320 CC DIS 1.3 < W < 2.0 C 6-9: NC 1pi NC 1pi C 10: NC DIS 1320 NC DIS 1.3 < W < 2.0 C 11: NC els CC Q.E.( Bound ) C 12: NC els NC els C 13: NC els NC els C 14: coherent NC els C 15: coherent coherent C 16: CC eta coherent C 17 NC eta CC eta C 18: NC eta NC eta C 19: CC K NC eta C 20 NC K CC K C 21: NC K NC K C 22: N/A NC K C 23: CC DIS CC DIS (W > 2.0) C 24: NC DIS NC DIS (W > 2.0) C 25: CC 1 gamma CC 1 gamma C 26: NC 1 gamma NC 1 gamma C 27: NC 1 gamma NC 1 gamma C 28: 2p2h 2p2h */ ids.push_back("crsmode_CCQE"); ids.push_back("crsmode_CC2P2H"); ids.push_back("crsmode_CC1pi"); ids.push_back("crsmode_CCDIS_lowW"); ids.push_back("crsmode_NC1pi"); ids.push_back("crsmode_NCDIS_lowW"); ids.push_back("crsmode_NCEL"); ids.push_back("crsmode_CCCOH"); ids.push_back("crsmode_NCCOH"); ids.push_back("crsmode_CCETA"); ids.push_back("crsmode_NCETA"); ids.push_back("crsmode_CCKAON"); ids.push_back("crsmode_NCKAON"); ids.push_back("crsmode_CCDIS_highW"); ids.push_back("crsmode_NCDIS_highW"); ids.push_back("crsmode_CCGAMMA"); ids.push_back("crsmode_NCGAMMA"); // Now define possible models if (!list.compare("Default")) { // Everything but MEC modes["crsmode_CCQE"] = 1; modes["crsmode_CC2P2H"] = 0; modes["crsmode_CC1pi"] = 1; modes["crsmode_CCDIS_lowW"] = 1; modes["crsmode_CCCOH"] = 1; modes["crsmode_CCETA"] = 1; modes["crsmode_CCKAON"] = 1; modes["crsmode_CCDIS_highW"] = 1; modes["crsmode_CCGAMMA"] = 1; modes["crsmode_NC1pi"] = 1; modes["crsmode_NCDIS_lowW"] = 1; modes["crsmode_NCEL"] = 1; modes["crsmode_NCCOH"] = 1; modes["crsmode_NCETA"] = 1; modes["crsmode_NCKAON"] = 1; modes["crsmode_NCDIS_highW"] = 1; modes["crsmode_NCGAMMA"] = 1; } else if (!list.compare("DefaultFree")) { modes["crsmode_CCQE"] = 1; modes["crsmode_CC2P2H"] = 0; modes["crsmode_CC1pi"] = 1; modes["crsmode_CCDIS_lowW"] = 1; modes["crsmode_CCCOH"] = 0; modes["crsmode_CCETA"] = 1; modes["crsmode_CCKAON"] = 1; modes["crsmode_CCDIS_highW"] = 1; modes["crsmode_CCGAMMA"] = 1; modes["crsmode_NC1pi"] = 1; modes["crsmode_NCDIS_lowW"] = 1; modes["crsmode_NCEL"] = 1; modes["crsmode_NCCOH"] = 0; modes["crsmode_NCETA"] = 1; modes["crsmode_NCKAON"] = 1; modes["crsmode_NCDIS_highW"] = 1; modes["crsmode_NCGAMMA"] = 1; } else if (!list.compare("Default+MEC")) { modes["crsmode_CCQE"] = 1; modes["crsmode_CC2P2H"] = 1; modes["crsmode_CC1pi"] = 1; modes["crsmode_CCDIS_lowW"] = 1; modes["crsmode_CCCOH"] = 1; modes["crsmode_CCETA"] = 1; modes["crsmode_CCKAON"] = 1; modes["crsmode_CCDIS_highW"] = 1; modes["crsmode_CCGAMMA"] = 1; modes["crsmode_NC1pi"] = 1; modes["crsmode_NCDIS_lowW"] = 1; modes["crsmode_NCEL"] = 1; modes["crsmode_NCCOH"] = 1; modes["crsmode_NCETA"] = 1; modes["crsmode_NCKAON"] = 1; modes["crsmode_NCDIS_highW"] = 1; modes["crsmode_NCGAMMA"] = 1; } else { NUIS_ABORT("Event generator list " << list << " not found!"); } // Now we actually have to make the conversion because NEUTS modes // organisation are a mess. /* C C nu nub C 1: CC Q.E. CC Q.E.( Free ) C 2-4: CC 1pi CC 1pi C 5: CC DIS 1320 CC DIS 1.3 < W < 2.0 C 6-9: NC 1pi NC 1pi C 10: NC DIS 1320 NC DIS 1.3 < W < 2.0 C 11: NC els CC Q.E.( Bound ) C 12: NC els NC els C 13: NC els NC els C 14: coherent NC els C 15: coherent coherent C 16: CC eta coherent C 17 NC eta CC eta C 18: NC eta NC eta C 19: CC K NC eta C 20 NC K CC K C 21: NC K NC K C 22: N/A NC K C 23: CC DIS CC DIS (W > 2.0) C 24: NC DIS NC DIS (W > 2.0) C 25: CC 1 gamma CC 1 gamma C 26,27: NC 1 gamma NC 1 gamma */ std::string modestring_neutrino = "NEUT-CRS "; std::string modestring_antineutrino = "NEUT-CRSB "; // Neutrino First if (neutrino) { // Fill empty NEUT-CRSB for (size_t i = 0; i < 27; i++) { modestring_antineutrino += " 0"; } modestring_neutrino += (modes["crsmode_CCQE"] ? " 1" : " 0"); modestring_neutrino += (modes["crsmode_CC1pi"] ? " 1 1 1" : " 0 0 0"); modestring_neutrino += (modes["crsmode_CCDIS_lowW"] ? " 1" : " 0"); modestring_neutrino += (modes["crsmode_NC1pi"] ? " 1 1 1 1" : " 0 0 0 0"); modestring_neutrino += (modes["crsmode_NCDIS_lowW"] ? " 1" : " 0"); modestring_neutrino += (modes["crsmode_NCEL"] ? " 1 1 1" : " 0 0 0"); modestring_neutrino += (modes["crsmode_CCCOH"] ? " 1" : " 0"); modestring_neutrino += (modes["crsmode_NCCOH"] ? " 1" : " 0"); modestring_neutrino += (modes["crsmode_CCETA"] ? " 1" : " 0"); modestring_neutrino += (modes["crsmode_NCETA"] ? " 1 1" : " 0 0"); modestring_neutrino += (modes["crsmode_CCKAON"] ? " 1" : " 0"); modestring_neutrino += (modes["crsmode_NCKAON"] ? " 1 1" : " 0 0"); modestring_neutrino += " 1"; // /NA modestring_neutrino += (modes["crsmode_CCDIS_highW"] ? " 1" : " 0"); modestring_neutrino += (modes["crsmode_NCDIS_highW"] ? " 1" : " 0"); modestring_neutrino += (modes["crsmode_CCGAMMA"] ? " 1" : " 0"); modestring_neutrino += (modes["crsmode_NCGAMMA"] ? " 1" : " 0"); modestring_neutrino += (modes["crsmode_CC2P2H"] ? " 1" : " 0"); } else { // Fill Empty NEUT CRS for (size_t i = 0; i < 27; i++) { modestring_neutrino += " 0"; } modestring_antineutrino += (modes["crsmode_CCQE"] ? " 1" : " 0"); modestring_antineutrino += (modes["crsmode_CC1pi"] ? " 1 1 1" : " 0 0 0"); modestring_antineutrino += (modes["crsmode_CCDIS_lowW"] ? " 1" : " 0"); modestring_antineutrino += (modes["crsmode_NC1pi"] ? " 1 1 1 1" : " 0 0 0 0"); modestring_antineutrino += (modes["crsmode_NCDIS_lowW"] ? " 1" : " 0"); modestring_antineutrino += (modes["crsmode_CCQE"] ? " 1" : " 0"); modestring_antineutrino += (modes["crsmode_NCEL"] ? " 1 1 1" : " 0 0 0"); modestring_antineutrino += (modes["crsmode_CCCOH"] ? " 1" : " 0"); modestring_antineutrino += (modes["crsmode_NCCOH"] ? " 1" : " 0"); modestring_antineutrino += (modes["crsmode_CCETA"] ? " 1" : " 0"); modestring_antineutrino += (modes["crsmode_NCETA"] ? " 1 1" : " 0 0"); modestring_antineutrino += (modes["crsmode_CCKAON"] ? " 1" : " 0"); modestring_antineutrino += (modes["crsmode_NCKAON"] ? " 1 1" : " 0 0"); modestring_antineutrino += (modes["crsmode_CCDIS_highW"] ? " 1" : " 0"); modestring_antineutrino += (modes["crsmode_NCDIS_highW"] ? " 1" : " 0"); modestring_antineutrino += (modes["crsmode_CCGAMMA"] ? " 1" : " 0"); modestring_antineutrino += (modes["crsmode_NCGAMMA"] ? " 1" : " 0"); modestring_antineutrino += (modes["crsmode_CC2P2H"] ? " 1" : " 0"); } return "NEUT-MODE -1 \n" + modestring_neutrino + "\n" + modestring_antineutrino; } std::map MakeNewFluxFile(std::string flux, std::string out) { NUIS_LOG(FIT, "Using " << flux << " to define NEUT beam."); std::vector fluxargs = GeneralUtils::ParseToStr(flux, ","); if (fluxargs.size() < 2) { NUIS_ABORT("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_nutaub"] = ""; // Split by beam bdgs for (uint i = 1; i < fluxargs.size(); i++) { std::string histdef = fluxargs[i]; 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_tau"] = name; else if (pdg == -16) fluxmap["beam_inputroot_taub"] = 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++) { 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); } } } // Check Flux if (cuthist->Integral() <= 0.0) { NUIS_ABORT("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 fluxmap; } std::string GetFluxDefinition(std::string fluxfile, std::string fluxhist, std::string fluxid) { // Get base name of flux file as its being copied to NEUT Run Directory std::vector splitfluxfile = GeneralUtils::ParseToStr(fluxfile, "/"); std::string filename = ""; if (splitfluxfile.size() == 1) { filename = splitfluxfile[0]; } else if (splitfluxfile.size() > 1) { filename = splitfluxfile[splitfluxfile.size() - 1]; } else { NUIS_ABORT("NO FILENAME FOR FLUX DEFINITION FOUND!"); } // Build string std::string fluxparams = ""; fluxparams += "EVCT-FILENM \'" + filename + "\' \n"; fluxparams += "EVCT-HISTNM \'" + fluxhist + "\' \n"; fluxparams += "EVCT-INMEV 0 \n"; fluxparams += "EVCT-MPV 3 \n"; // Set PDG Code if (!fluxid.compare("nue")) fluxparams += "EVCT-IDPT 12"; else if (!fluxid.compare("nueb")) fluxparams += "EVCT-IDPT -12"; else if (!fluxid.compare("numu")) fluxparams += "EVCT-IDPT 14"; else if (!fluxid.compare("numub")) fluxparams += "EVCT-IDPT -14"; else if (!fluxid.compare("nutau")) fluxparams += "EVCT-IDPT 16"; else if (!fluxid.compare("nutaub")) fluxparams += "EVCT-IDPT -16"; else { NUIS_ABORT("UNKNOWN FLUX ID GIVEN!"); } return fluxparams; } std::string GetTargetDefinition(std::string target) { NUIS_LOG(FIT, "Defining NEUT Target from : " << 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 = ""; // NEUT only lets us pass C and CH type inputs. // Single Target if (trgts.size() == 1) { int PDG = GeneralUtils::StrToInt(trgts[0]); int Z = TargetUtils::GetTargetZFromPDG(PDG); int N = TargetUtils::GetTargetAFromPDG(PDG) - Z; targetstring += "NEUT-NUMBNDP " + GeneralUtils::IntToStr(Z) + "\n"; targetstring += "NEUT-NUMBNDN " + GeneralUtils::IntToStr(N) + "\n"; targetstring += "NEUT-NUMFREP 0\n"; targetstring += "NEUT-NUMATOM " + GeneralUtils::IntToStr(Z + N) + "\n"; // Combined target } else if (trgts.size() == 3) { int NUCLEONS = GeneralUtils::StrToInt(trgts[0]); std::string target1 = trgts[1]; std::string target2 = trgts[2]; // Parse target strings string::size_type open_bracket = target1.find("["); string::size_type close_bracket = target1.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 PDG1 = atoi(target1.substr(ibeg, iend).c_str()); double W1 = atof(target1.substr(jbeg, jend).c_str()); open_bracket = target2.find("["); close_bracket = target2.find("]"); ibeg = 0; iend = open_bracket; jbeg = open_bracket + 1; jend = close_bracket - 1; int PDG2 = atoi(target2.substr(ibeg, iend).c_str()); double W2 = atof(target2.substr(jbeg, jend).c_str()); // Can only have H as a secondary target! if (PDG1 != 1000010010 && PDG2 != 1000010010) { NUIS_ABORT( "NEUT Doesn't support composite targets apart fromn Target+H. E.g. " "CH"); } // Switch so H is PDG2 if given if (PDG1 == 1000010010 && PDG2 != 1000010010) { PDG1 = PDG2; PDG2 = 1000010010; double temp1 = W1; W1 = W2; W2 = temp1; } // Now build string int Z = TargetUtils::GetTargetZFromPDG(PDG1); int N = TargetUtils::GetTargetAFromPDG(PDG1) - Z; int NHydrogen = int(W2 * double(NUCLEONS)); if (double(W2 * double(NUCLEONS)) - (double(NHydrogen)) > 0.5) { NHydrogen++; // awkward rounding bug fix } targetstring += "NEUT-NUMBNDP " + GeneralUtils::IntToStr(Z) + "\n"; targetstring += "NEUT-NUMBNDN " + GeneralUtils::IntToStr(N) + "\n"; targetstring += "NEUT-NUMFREP " + GeneralUtils::IntToStr(NHydrogen) + "\n"; targetstring += "NEUT-NUMATOM " + GeneralUtils::IntToStr(Z + N) + "\n"; } else { NUIS_ABORT("NEUT only supports single targets or ones with a secondary H!"); } return targetstring; } std::string GetEventAndSeedDefinition(int nevents, int seed) { std::string eventdef = ""; eventdef += "EVCT-NEVT " + GeneralUtils::IntToStr(nevents) + "\n"; NUIS_LOG(FIT, "Event Definition: "); std::cout << " -> EVCT-NEVT : " << nevents << std::endl; return eventdef; } //____________________________________________________________________________ int main(int argc, char **argv) { NUIS_LOG(FIT, "==== RUNNING neut_nuisance Event Generator ====="); GetCommandLineArgs(argc, argv); std::string neutroot = std::string(getenv("NEUT_ROOT")) + "/src/neutsmpl/"; // Calculate the dynamic modes definition // Read Target string std::string targetparamsdef = GetTargetDefinition(gOptTargetDef); //____________________________ // NEUT doesn't let us do combined flux inputs so have to loop over each flux. std::map newfluxdef = MakeNewFluxFile(gOptFluxDef, gOptOutputFile); // Quick fix to make flux also save to pid_time.root.flux.root std::stringstream ss; ss << getpid() << "_" << time(NULL) << ".root"; newfluxdef = MakeNewFluxFile(gOptFluxDef, ss.str()); // Copy this file to the NEUT working directory NUIS_LOG(FIT, "Copying flux to NEUT working directory"); system( ("cp -v " + newfluxdef["beam_inputroot"] + " " + neutroot + "/").c_str()); TFile *fluxrootfile = new TFile(newfluxdef["beam_inputroot"].c_str(), "READ"); // Setup possible beams and get relative fractions std::vector possiblefluxids; std::vector fluxfractions; possiblefluxids.push_back("nue"); possiblefluxids.push_back("nueb"); possiblefluxids.push_back("numu"); possiblefluxids.push_back("numub"); possiblefluxids.push_back("tau"); possiblefluxids.push_back("taub"); // Total up integrals double totintflux = 0.0; for (size_t i = 0; i < possiblefluxids.size(); i++) { if (newfluxdef["beam_inputroot_" + possiblefluxids[i]].empty()) { fluxfractions.push_back(0.0); } else { TH1D *fluxhist = (TH1D *)fluxrootfile->Get( newfluxdef["beam_inputroot_" + possiblefluxids[i]].c_str()); if (!fluxhist) { NUIS_ABORT("FLUX HIST : " << newfluxdef["beam_inputroot_" + possiblefluxids[i]] << " not found!"); } fluxfractions.push_back(fluxhist->Integral()); totintflux += fluxhist->Integral(); } } fluxrootfile->Close(); // Now loop over and actually generate jobs! for (size_t i = 0; i < possiblefluxids.size(); i++) { if (fluxfractions[i] == 0.0) continue; // Get number of events for this subbeam int nevents = int(double(gOptNumberEvents) * fluxfractions[i] / totintflux); std::cout << "NEVENTS = " << gOptNumberEvents << " " << fluxfractions[i] << " " << totintflux << " " << nevents << std::endl; std::string eventparamsdef = GetEventAndSeedDefinition(nevents, gOptSeed); bool neutrino = true; if (possiblefluxids[i].find("b") != std::string::npos) neutrino = false; std::string dynparamsdef = GetDynamicModes(gOptGeneratorList, neutrino); std::string fluxparamsdef = GetFluxDefinition( newfluxdef["beam_inputroot"], newfluxdef["beam_inputroot_" + possiblefluxids[i]], possiblefluxids[i]); NUIS_LOG(FIT,"==== Generating CardFiles NEUT! ==="); std::cout << dynparamsdef << std::endl; std::cout << targetparamsdef << std::endl; std::cout << eventparamsdef << std::endl; std::cout << fluxparamsdef << std::endl; // Create card file std::ifstream incardfile; std::ofstream outcardfile; std::string line; incardfile.open(gOptCrossSections.c_str(), ios::in); outcardfile.open( (gOptOutputFile + "." + possiblefluxids[i] + ".par").c_str(), ios::out); // Copy base card file if (incardfile.is_open()) { while (getline(incardfile, line)) { outcardfile << line << '\n'; } } else { NUIS_ABORT("Cannot find card file : " << gOptCrossSections); } // Now copy our strings outcardfile << eventparamsdef << '\n'; outcardfile << dynparamsdef << '\n'; outcardfile << targetparamsdef << '\n'; outcardfile << fluxparamsdef << '\n'; // Close card and keep name for future use. outcardfile.close(); } NUIS_LOG(FIT, "GENERATING"); for (size_t i = 0; i < possiblefluxids.size(); i++) { if (fluxfractions[i] == 0.0) continue; int nevents = int(double(gOptNumberEvents) * fluxfractions[i] / totintflux); if (nevents <= 0) continue; std::string cardfile = ExpandPath(gOptOutputFile + "." + possiblefluxids[i] + ".par"); std::string outputfile = ExpandPath(gOptOutputFile + "." + possiblefluxids[i] + ".root"); std::string basecardfile = GetBaseName(cardfile); std::string baseoutputfile = ss.str(); std::cout << "CARDFILE = " << cardfile << " : " << basecardfile << std::endl; std::cout << "OUTPUTFILE = " << outputfile << " : " << baseoutputfile << std::endl; system(("cp " + cardfile + " " + neutroot).c_str()); std::string cwd = GETCWD(); chdir(neutroot.c_str()); // int attempts = 0; // while(true){ // Break if too many attempts // attempts++; // if (attempts > 20) continue; // Actually run neutroot2 system(("./neutroot2 " + basecardfile + " " + baseoutputfile).c_str()); // Check the output is valid, sometimes NEUT aborts mid run. // TFile* f = new TFile(baseoutputfile.c_str(),"READ"); // if (!f or f->IsZombie()) continue; // Check neutttree is there and filled correctly. // TTree* tn = (TTree*) f->Get("neuttree"); // if (!tn) continue; // if (tn->GetEntries() < nevents * 0.9) continue; // break; // } // Move the finished file back and clean this directory of card files system(("mv -v " + baseoutputfile + " " + outputfile).c_str()); system(("rm -v " + basecardfile).c_str()); chdir(cwd.c_str()); } return 0; } //____________________________________________________________________________ void GetCommandLineArgs(int argc, char **argv) { // Check for -h flag. for (int i = 0; i < argc; i++) { if (!std::string(argv[i]).compare("-h")) PrintSyntax(); } // Format is neut -r run_number -n n events std::vector args = GeneralUtils::LoadCharToVectStr(argc, argv); ParserUtils::ParseArgument(args, "-n", gOptNumberEvents, false); if (gOptNumberEvents == -1) { NUIS_ABORT("No event count passed to neut_NUISANCE!"); } // Flux/Energy Specs ParserUtils::ParseArgument(args, "-e", gOptEnergyDef, false); gOptEnergyRange = GeneralUtils::ParseToDbl(gOptEnergyDef, ","); ParserUtils::ParseArgument(args, "-f", gOptFluxDef, false); if (gOptFluxDef.empty() and gOptEnergyRange.size() < 1) { NUIS_ABORT("No flux or energy range given to neut_nuisance!"); } else if (gOptFluxDef.empty() and gOptEnergyRange.size() == 1) { // Fixed energy, make sure -p is given NUIS_ABORT("neut_NUISANCE cannot yet do fixed energy!"); } else if (gOptFluxDef.empty() and gOptEnergyRange.size() == 2) { // Uniform energy range NUIS_ABORT("neut_NUISANCE cannot yet do a uniform energy range!"); } else if (!gOptFluxDef.empty()) { // Try to convert the flux definition if possible. std::string convflux = BeamUtils::ConvertFluxIDs(gOptFluxDef); if (!convflux.empty()) gOptFluxDef = convflux; } else { NUIS_ABORT("Unknown flux energy range combination!"); } ParserUtils::ParseArgument(args, "-t", gOptTargetDef, false); if (gOptTargetDef.empty()) { NUIS_ABORT("No Target passed to neut_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 (gOptRunNumber == -1) gOptRunNumber = 1; NUIS_LOG(FIT, "No output file given! Saving file to : neutgen." << gOptRunNumber << ".neutvect.root"); gOptOutputFile = "neutgen." + GeneralUtils::IntToStr(gOptRunNumber) + ".neutvect.root"; } else { // if no run number given leave as is, else add run number. if (gOptRunNumber != -1) { gOptOutputFile += "." + GeneralUtils::IntToStr(gOptRunNumber) + ".root"; } else { gOptRunNumber = 0; } } ParserUtils::ParseArgument(args, "--cross-section", gOptCrossSections, false); if (!gOptCrossSections.compare("Default")) { NUIS_LOG(FIT, "No Parameters File passed. Using default neut one."); char *const var = getenv("NUISANCE"); if (!var) { std::cout << "Cannot find top level directory! Set the NUISANCE " "environmental variable" << std::endl; exit(-1); } std::string topnuisancedir = string(var); gOptCrossSections = topnuisancedir + "/neut/Default_params.txt"; } ParserUtils::ParseArgument(args, "--event-generator-list", gOptGeneratorList, false); // Final Check and output if (args.size() > 0) { PrintSyntax(); ParserUtils::CheckBadArguments(args); } NUIS_LOG(FIT, "Generating Neut Events with the following properties:" << std::endl << " -> Energy : " << gOptEnergyDef << " (" << gOptEnergyRange.size() << ")" << std::endl << " -> NEvents : " << gOptNumberEvents << std::endl << " -> Generators : " << gOptGeneratorList << std::endl << " -> XSecPars : " << gOptCrossSections << std::endl << " -> Target : " << gOptTargetDef << std::endl << " -> Flux : " << gOptFluxDef << std::endl << " -> Output : " << gOptOutputFile << std::endl << " -> Run : " << gOptRunNumber); return; } //____________________________________________________________________________ void PrintSyntax(void) { NUIS_LOG(FIT, "\n\n" << "Syntax:" << "\n" << "\n neut_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 \n"); NUIS_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 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 WARNING: NEUT can't actually generate combined fluxes yet" << "\n if you want a composite flux, pass them in as normal, but " "the " "app" - << "\n will generate you the files seperately, with reduced " + << "\n will generate you the files separately, with reduced " "nevents " "in each" << "\n so that the statistics are roughly okay." << "\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 WARNING: NEUT can only generate A+H targets. E.g. CH or " "CH2 " "will work, but " - << "\n Fe+Pb will not. You will have to generate each seperately " + << "\n Fe+Pb will not. You will have to generate each separately " "if " "you want" << "\n something other than A+NH." << "\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 neut_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 'neutgen.run_number.neutvect.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 neut model definition. If this is not given, " "then " "this " << "\n will default to $NUISANCE/data/neut/Default_params.txt" << "\n" << "\n Look in $NUISANCE/data/neut/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 CRS and CRSB values in " "NEUT." << "\n e.g. --event-generator-list Default+MEC" << "\n" << "\n Allowed mode_definitions are given at the end of this help " "message." << "\n" << "\n\n"); std::cout << "-----------------" << std::endl; TargetUtils::ListTargetIDs(); std::cout << "-----------------" << std::endl; BeamUtils::ListFluxIDs(); std::cout << "-----------------" << std::endl; NUIS_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::cout << "----------------" << std::endl; exit(0); } //____________________________________________________________________________ #endif diff --git a/app/nuismin.cxx b/app/nuismin.cxx index 7b965d5..0d1eb14 100644 --- a/app/nuismin.cxx +++ b/app/nuismin.cxx @@ -1,141 +1,141 @@ // 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 . *******************************************************************************/ // Author: Callum Wilkinson 01/2014 // Patrick Stowell 09/2015 /** Usage: ./GSLminimizerWithReWeight.exe -c card file, where samples and parameters are defined -o output file, where the results of the fit are stored where: */ #include "MinimizerRoutines.h" //******************************* void printInputCommands() { //******************************* std::cout << "ExtFit_minimizer.exe -c cardFile -o outFile [-f fitStategy] [-d " "fakeDataFile] [-i inputFile] [-q config_name=config_val] \n"; std::cout << std::endl; std::cout << "Arguments:" << std::endl; std::cout << " -c cardFile: Path to card file that defines fit " "samples, free parameters, and config overrides \n"; std::cout << " -o outFile: Path to root file that will be created to " "save output file.\n"; std::cout << " To turn automatically overwrite outFile if " "one exists turn off use 'config overwrite_output 1'\n"; std::cout << " To automatically use previous outFile as " "an inputFile if it exists so that the fit can be continued\n"; std::cout << " use the flag 'config use_previous_output " "1'. (A warning will be printed when doing this). \n"; - std::cout << " -f fitStategy: Pass a comma seperated list of fit " + std::cout << " -f fitStategy: Pass a comma separated list of fit " "routines to run in order. Default is Migrad,FixAtLim \n"; std::cout << " Possible Options: \n"; std::cout << " 1. Migrad - Minuit2 Migrad Minimizer \n"; std::cout << " 2. Simplex - Simplex Minimizer \n"; std::cout << " 3. Scan - Brute force scan of parameter " "space \n"; std::cout << " 4. FixAtLim - Takes any free parameters " "close to a limit and fixes them \n"; std::cout << " 5. Scan1D - Make 1D Scans and save them " "in a folder \n"; std::cout << " 6. Contours - Make Contour Scans \n"; std::cout << " 7. Save - Will save the state of the " "fitter (Always done by default at the end) \n"; std::cout << " Extra option LowStatFit will perform " "each of these options with a lower number \n"; std::cout << " of fit events (config lowstat). Example: " "LowStatMigrad, LowStatScan \n"; std::cout << " -d fakeDataFile: Uses the MC generated from a previous " "fit as a fake data set for these fits \n"; std::cout << " Can also specify MC to set the fake-data " "to the Monte-Carlo prediction\n"; std::cout << " In this case, you can specify " "fake_parameter PARAM_NAME PARAM_VALUE in the card\n"; std::cout << " to reweight the MC parameter " "PARAM_NAME to some PARAM_VALUE. The minimiser will start\n"; std::cout << " at whatever neut_parameter or " "genie_parameter is set to in the cardfile.\n"; std::cout << " -i inputFile: Uses the results from a previous fit file " "as starting input for these fits \n"; std::cout << " -q config_name=config_val : Allows any config parameter " "to be overridden from the command line.\n"; std::cout << " This will take priority over " "those given in the default, or cardFile. \n"; std::cout << " example: -q verbosity=6 -q " "maxevents=10000 \n"; exit(-1); }; //******************************* int main(int argc, char *argv[]) { //******************************* // Program status; int status = 0; // If No Arguments print commands if (argc == 1) printInputCommands(); for (int i = 1; i < argc; ++i) { // Cardfile if (!std::strcmp(argv[i], "-h")) printInputCommands(); else break; } // Read input arguments such as card file, parameter arguments, and fit // routines NUIS_LOG(FIT, "Starting ExtFit_minimizer.exe"); // Make minimizer class and run fit MinimizerRoutines *min = new MinimizerRoutines(argc, argv); // Save Starting States if (FitPar::Config().GetParB("savenominal")) min->SaveNominal(); if (FitPar::Config().GetParB("saveprefit")) min->SavePrefit(); // Run the fit routines min->Run(); // Save by default min->SaveResults(); // Get Status status = min->GetStatus(); // Show Final Status NUIS_LOG(FIT, "-------------------------------------"); if (status == 0) { NUIS_LOG(FIT, "Minimizer Complete."); } else { NUIS_ERR(WRN, "Minimizer Failed (error state = " << status << ")"); } NUIS_LOG(FIT, "-------------------------------------"); return status; } diff --git a/app/nuissplines.cxx b/app/nuissplines.cxx index 2ab79eb..63ed81e 100644 --- a/app/nuissplines.cxx +++ b/app/nuissplines.cxx @@ -1,105 +1,105 @@ // 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 . *******************************************************************************/ // Author: Callum Wilkinson 01/2014 // Patrick Stowell 09/2015 /** Usage: ./GSLminimizerWithReWeight.exe -c card file, where samples and parameters are defined -o output file, where the results of the fit are stored where: */ #include "SplineRoutines.h" //******************************* void printInputCommands(){ //******************************* /* std::cout<<"ExtFit_splines.exe -c cardFile -f [spline_routines] [-q config_name=config_val] \n"; std::cout<Run(); // Show Final Status NUIS_LOG(FIT, "-------------------------------------"); NUIS_LOG(FIT, "Spline Generation/Validation Finished."); NUIS_LOG(FIT, "-------------------------------------"); return 0; } diff --git a/cmake/NEUTSetup.cmake b/cmake/NEUTSetup.cmake index 4cd20ba..fed7715 100644 --- a/cmake/NEUTSetup.cmake +++ b/cmake/NEUTSetup.cmake @@ -1,232 +1,246 @@ # 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(cmake/parseConfigApp.cmake) find_program(NEUTCONFIG NAMES neut-config) LIST(APPEND EXTRA_CXX_FLAGS -DNEED_FILL_NEUT_COMMONS) SET(HAVENEUTCONFIG FALSE) # We are dealing with shiny NEUT if(NOT "${NEUTCONFIG}" STREQUAL "NEUTCONFIG-NOTFOUND") SET(HAVENEUTCONFIG TRUE) cmessage(STATUS "Found neut-config, using it to determine configuration.") else() cmessage(STATUS "Failed to find neut-config, assuming older NEUT build.") endif() if(HAVENEUTCONFIG) execute_process (COMMAND neut-config --version OUTPUT_VARIABLE NEUT_VER OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process (COMMAND neut-config --incdir OUTPUT_VARIABLE NEUT_INCLUDE_DIRS OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process (COMMAND neut-config --libdir OUTPUT_VARIABLE NEUT_LINK_DIRS OUTPUT_STRIP_TRAILING_WHITESPACE) GETLIBDIRS(neut-config --cernflags CERN_LIB_DIR) LIST(APPEND NEUT_LINK_DIRS ${CERN_LIB_DIR}) GETLIBS(neut-config --cernflags CERN_LIBS) if(USE_REWEIGHT) execute_process (COMMAND neut-config --rwlibflags OUTPUT_VARIABLE NEUT_RWLIBS OUTPUT_STRIP_TRAILING_WHITESPACE) GETLIBS(neut-config --rwlibflags NEUT_RWLIBS) LIST(APPEND NEUT_LIBS ${NEUT_RWLIBS}) else() GETLIBS(neut-config --libflags NEUT_GENLIBS) GETLIBS(neut-config --iolibflags NEUT_LIBS) LIST(APPEND NEUT_LIBS ${NEUT_IOLIBS}) LIST(APPEND NEUT_LIBS ${NEUT_GENLIBS}) endif() LIST(APPEND NEUT_LIBS ${CERN_LIBS};gfortran) LIST(APPEND EXTRA_LIBS ${NEUT_LIBS}) string(REPLACE "." "" NEUT_VERSION ${NEUT_VER}) PrefixList(NEUT_INCLUDE_DIRS "-I" ${NEUT_INCLUDE_DIRS}) LIST(APPEND EXTRA_CXX_FLAGS ${NEUT_INCLUDE_DIRS} -D__NEUT_ENABLED__ -D__NEUT_VERSION__=${NEUT_VERSION}) LIST(APPEND EXTRA_LINK_DIRS ${NEUT_LINK_DIRS}) + include(CheckCXXCompilerFlag) + CHECK_CXX_COMPILER_FLAG(-no-pie COMPILER_SUPPORTS_NO_PIE) + CHECK_CXX_COMPILER_FLAG(-fno-pie COMPILER_SUPPORTS_FNO_PIE) + CHECK_CXX_COMPILER_FLAG(-fno-PIE COMPILER_SUPPORTS_FNO_PIE_CAP) + if(COMPILER_SUPPORTS_NO_PIE) + set(PIE_FLAGS "-no-pie") + elseif(COMPILER_SUPPORTS_FNO_PIE) + set(PIE_FLAGS "-fno-pie") + elseif(COMPILER_SUPPOERTS_FNO_PIE_CAP) + set(PIE_FLAGS "-fno-PIE") + else() + message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") + endif() + LIST(APPEND EXTRA_EXE_FLAGS - -fno-pie -fno-PIE -no-pie) + ${PIE_FLAGS}) cmessage(STATUS "NEUT") cmessage(STATUS " Version : ${NEUT_VER}") cmessage(STATUS " Flags : ${NEUT_CXX_FLAGS}") cmessage(STATUS " Includes : ${NEUT_INCLUDE_DIRS}") cmessage(STATUS " Link Dirs : ${NEUT_LINK_DIRS}") cmessage(STATUS " Libs : ${NEUT_LIBS}") - cmessage(STATUS " Exe Flags : -fno-pie -fno-PIE -no-pie") + cmessage(STATUS " Exe Flags : ${EXTRA_EXE_FLAGS}") else() # Everything better be set up already if(NEUT_ROOT STREQUAL "") cmessage(FATAL_ERROR "Variable NEUT_ROOT is not defined. Please export environment variable NEUT_ROOT or configure with -DNEUT_ROOT=/path/to/NEUT. This must be set to point to a prebuilt NEUT instance.") endif() if(CERN STREQUAL "") cmessage(FATAL_ERROR "Variable CERN is not defined. Please export environment variable CERN or configure with -DCERN=/path/to/CERNLIB. This must be set to point to a prebuilt CERNLIB instance.") endif() if(CERN_LEVEL STREQUAL "") cmessage(FATAL_ERROR "Variable CERN_LEVEL is not defined. Please export environment variable CERN_LEVEL or configure with -DCERN_LEVEL=XXXX (likely to be 2005).") endif() if(${NEUT_VERSION} VERSION_LESS 5.4.0) set(NEUT_LIB_DIR ${NEUT_ROOT}/lib/Linux_pc) else() set(NEUT_LIB_DIR ${NEUT_ROOT}/lib) endif() set(NEUT_CLASS ${NEUT_ROOT}/src/neutclass) LIST(APPEND EXTRA_CXX_FLAGS -D__NEUT_ENABLED__ -DNEUT_VERSION=${NEUT_VERSION}) LIST(APPEND EXTRA_CXX_FLAGS -I${NEUT_ROOT}/include -I${NEUT_ROOT}/src/neutclass) LIST(APPEND EXTRA_LINK_DIRS ${NEUT_LIB_DIR} ${CERN}/${CERN_LEVEL}/lib) if(USE_REWEIGHT) LIST(APPEND EXTRA_CXX_FLAGS -I${NEUT_ROOT}/src/reweight) LIST(APPEND EXTRA_LINK_DIRS ${NEUT_ROOT}/src/reweight) endif() if(${NEUT_VERSION} VERSION_EQUAL 5.4.2) LIST(APPEND EXTRA_LIBS -Wl,--as-needed) if(USE_REWEIGHT) LIST(APPEND EXTRA_LIBS NReWeight) endif() LIST(APPEND EXTRA_LIBS -Wl,--start-group neutcore_5.4.2 nuccorspl_5.4.2 #typo in NEUT, may hopefully disappear nuceff_5.4.2 partnuck_5.4.2 skmcsvc_5.4.2 tauola_5.4.2 HT2p2h_5.4.0 N1p1h_5.4.0 -Wl,--end-group jetset74 pdflib804 mathlib packlib pawlib) LIST(APPEND EXTRA_CXX_FLAGS -DNEUT_COMMON_QEAV) elseif(${NEUT_VERSION} VERSION_EQUAL 5.4.0) LIST(APPEND EXTRA_LIBS -Wl,--as-needed) if(USE_REWEIGHT) LIST(APPEND EXTRA_LIBS NReWeight) endif() LIST(APPEND EXTRA_LIBS -Wl,--start-group neutcore_5.4.0 nuccorspl_5.4.0 #typo in NEUT, may hopefully disappear nuceff_5.4.0 partnuck_5.4.0 skmcsvc_5.4.0 tauola_5.4.0 HT2p2h_5.4.0 N1p1h_5.4.0 specfunc_5.4.0 radcorr_5.4.0 gfortran -Wl,--end-group jetset74 pdflib804 mathlib packlib pawlib) else() LIST(APPEND EXTRA_LIBS -Wl,--as-needed) if(USE_REWEIGHT) LIST(APPEND EXTRA_LIBS NReWeight) endif() LIST(APPEND EXTRA_LIBS -Wl,--start-group neutcore nuccorrspl nuceff partnuck skmcsvc tauola -Wl,--end-group jetset74 pdflib804 mathlib packlib pawlib) endif() set(NEUT_ROOT_LIBS) LIST(APPEND NEUT_ROOT_LIBS ${NEUT_CLASS}/neutctrl.so ${NEUT_CLASS}/neutfsivert.so) # Check for new versions of NEUT with NUCLEON FSI if(EXISTS "${NEUT_CLASS}/neutnucfsistep.so") set(NEUT_NUCFSI 1) LIST(APPEND EXTRA_CXX_FLAGS -DNEUT_NUCFSI_ENABLED) LIST(APPEND NEUT_ROOT_LIBS ${NEUT_CLASS}/neutnucfsistep.so ${NEUT_CLASS}/neutnucfsivert.so ) endif() if(${NEUT_VERSION} VERSION_LESS 5.4.0) LIST(APPEND NEUT_ROOT_LIBS ${NEUT_CLASS}/neutrootTreeSingleton.so) endif() LIST(APPEND NEUT_ROOT_LIBS ${NEUT_CLASS}/neutvtx.so ${NEUT_CLASS}/neutfsipart.so ${NEUT_CLASS}/neutpart.so ${NEUT_CLASS}/neutvect.so ) foreach(OBJ ${NEUT_ROOT_LIBS}) LIST(APPEND EXTRA_SHAREDOBJS ${OBJ}) endforeach() endif() diff --git a/data/flux/MicroBooNE_FHC_numu_flux.root b/data/flux/MicroBooNE_FHC_numu_flux.root new file mode 100644 index 0000000..9de8508 Binary files /dev/null and b/data/flux/MicroBooNE_FHC_numu_flux.root differ diff --git a/doc/tutorial_inputs.dox b/doc/tutorial_inputs.dox index 54433b2..4a95fd1 100644 --- a/doc/tutorial_inputs.dox +++ b/doc/tutorial_inputs.dox @@ -1,149 +1,149 @@ /*! \page tutorial_inputs Fitting Input Card To determine what samples need to be loaded and the location of the event files to be read the fitter parses a premade input fit card which contains everything piece of information for the fit. This tutorial details how to load a simple sample of events from each of the generators and compare them against each other. \section fitcards The Fit Card For this very simple case so all that is required in the fit card is a single line to read in which sample we want to plot. For a list of samples see \ref samplelist. -We want a set of Monte Carlo events to make the data/MC comparison so first you will need to generate this in Neut and NuWro seperately. No explicit tutorial is given for this, but please see \ref generators for tips on what generator output format the events need to be in. +We want a set of Monte Carlo events to make the data/MC comparison so first you will need to generate this in Neut and NuWro separately. No explicit tutorial is given for this, but please see \ref generators for tips on what generator output format the events need to be in. Once we have a set of events create a fit card "fittertutorial1.card" in the current directory and include the "MiniBooNE_CCQE_XSec_1DQ2_nu" sample as follows. \code # Identifier - Sample Name ----------------- Type - Events File Name ------------------- Normalisation sample MiniBooNE_CCQE_XSec_1DQ2_nu FIX /path/to/miniboone_ccqe_events.root 1.0 \endcode - The "sample" argument lets the fitter know we want to include a new sample in this fit. Multiple samples can be included if required assuming they are uncorrelated by creating multiple sample lines in the fit card. - The Sample Name is a simple string identifier that lets the fitter know which dataset comparison should be performed, for a list of samples see \ref samplelist. - The sample Type is used to specify any other options required to describe how this sample is handled. Common examples are "FIX - fix this samples overall normalisation", "SHAPE - normalise MC to data before doing calculations", "DIAG - use only uncorrelated bin errors", "NORM - Add a normalisation penalty term to the fit". Some samples have extra possible fit types so it is worth checking the doxygen documentation for a sample before using it. -- The events file name is just simply the directory to the MC events you want to use for this fit. In the case of joint datasets that require multiple input MC files, the path to each can be provided in this field by passing a semi-colon seperated list, e.g. "/path/to/miniboone_ccqe_events1.root;/path/to/miniboone_ccqe_events2.root". +- The events file name is just simply the directory to the MC events you want to use for this fit. In the case of joint datasets that require multiple input MC files, the path to each can be provided in this field by passing a semi-colon separated list, e.g. "/path/to/miniboone_ccqe_events1.root;/path/to/miniboone_ccqe_events2.root". - The normalisation term is used to float the overall normalisation of this sample. The fitter will complain and scale the samples to 0.0 if you forget to include this! \section fittingrun Running a Fit Once we have a sample card produced it is possible to run a default Migrad fit by passing this fit card to the minimizer. \code ExtFit_minimizer.exe -c fittertutorial1.card -o fittertutorial1_output.root \endcode Since we have not included any MC ReWeight dials to be minimized yet this should run relatively quickly, requiring only a single reconfigure. The final output should look as follows: \code [LOG Fitter]: Making the minimizerFCN [LOG Minmzr]: Initializing Samples [LOG Minmzr]: MINERvA_CCQE_XSec_1DQ2_nu [LOG Fitter]: Running Routine: Migrad [LOG Fitter]: Fixed Param: MINERvA_CCQE_XSec_1DQ2_nu_norm [LOG Fitter]: Setup Minimizer: 1(NDim) 0(NFree) [LOG Minmzr]: Reconfiguring all samples in series [LOG Minmzr]: Iteration = 1 [LOG Minmzr]: Time taken for this reconfigure: 40 [LOG Fitter]: Current Stat = 47.8123 [LOG Fitter]: Minimizer State: [LOG Fitter]: # Parameter = Value +- Error Units (Sigma Variation) [LOG Fitter]: 0 . MINERvA_CCQE_XSec_1DQ2_nu_norm = 1 Frac. (Fixed) [LOG Fitter]: Running Routine: FixAtLim [LOG Fitter]: Minimizer State: [LOG Fitter]: # Parameter = Value +- Error Units (Sigma Variation) [LOG Fitter]: 0 . MINERvA_CCQE_XSec_1DQ2_nu_norm = 1 Frac. (Fixed) Error in : matrix not positive definite Error in : matrix not positive definite [LOG Fitter]: Saving current FCN predictions [LOG Minmzr]: Reconfiguring all samples in series [LOG Minmzr]: Iteration = 1 [LOG Minmzr]: Time taken for this reconfigure: 39 [LOG Minmzr]: Writing each of the data classes: ------------------------------------- Minimizer Complete. ------------------------------------- \endcode - Note: The error messages about TDecompChol correspond to problems where teh minimizer didn't actually produce a good covariance matrix. This can happen if the fit fails, but also if you are fitting with 1 or 0 free parameters. If that is the case don't worry too much about it. \section analysing Analysing the Output The root file produced then contains the results from the fit. To list the contents run: \code root -l fittertutorial1_output.root root[1]: _file0->ls(); TFile** fittertutorial1_output.root TFile* fittertutorial1_output.root KEY: TTree fit_result;1 fit_result KEY: TH1D fit_dials;1 fit_dials KEY: TH1D start_dials;1 start_dials KEY: TH1D min_dials;1 min_dials KEY: TH1D max_dials;1 max_dials KEY: TH1D fit_status;1 fit_status KEY: TH2D covariance;1 covariance KEY: TH2D correlation;1 correlation KEY: TH2D decomposition;1 decomposition KEY: TH1D MINERvA_CCQE_XSec_1DQ2_nu_data;1 MINERvA_CCQE_XSec_1DQ2_nu_data KEY: TH1D MINERvA_CCQE_XSec_1DQ2_nu_MC;1 47.812 KEY: TH1D MINERvA_CCQE_XSec_1DQ2_nu_MC_FINE;1 MINERvA_CCQE_XSec_1DQ2_nu_MC_FINE KEY: TH1D MINERvA_CCQE_XSec_1DQ2_nu_FLUX;1 MINERvA_CCQE_XSec_1DQ2_nu KEY: TH1D MINERvA_CCQE_XSec_1DQ2_nu_EVT;1 MINERvA_CCQE_XSec_1DQ2_nu_EVT KEY: THStack MINERvA_CCQE_XSec_1DQ2_nu_MC_PDG;1 MINERvA_CCQE_XSec_1DQ2_nu_MC_PDG KEY: TH1D MINERvA_CCQE_XSec_1DQ2_nu_MC_RATIO;1 47.812 KEY: TH1D MINERvA_CCQE_XSec_1DQ2_nu_data_RATIO;1 MINERvA_CCQE_XSec_1DQ2_nu_data KEY: TH1D MINERvA_CCQE_XSec_1DQ2_nu_MC_SHAPE;1 47.812 KEY: TH1D MINERvA_CCQE_XSec_1DQ2_nu_MC_SHAPE_RATIO;1 47.812 KEY: TH1D MINERvA_CCQE_XSec_1DQ2_nu_data_SHAPE_RATIO;1 MINERvA_CCQE_XSec_1DQ2_nu_data KEY: TH1D sample_xsecs_MC;1 sample_xsecs_MC KEY: TH1D sample_xsecs_data;1 sample_xsecs_data root[2]: fit_result->Show(0); ======> EVENT:0 parameter_names = (vector*)0x1aa80e0 parameter_values = (vector*)0x1aa93b0 parameter_errors = (vector*)0x1aa9b40 parameter_min = (vector*)0x1aa9f30 parameter_max = (vector*)0x1aaa2f0 parameter_start = (vector*)0x1aaa6b0 parameter_fix = (vector*)0x1aaacb0 parameter_startfix = (vector*)0x1aab690 CHI2 = 47.8123 NDOF = 8 NBINS = 8 NDIM = 1 NFREE = 0 \endcode Each of the following plots are added to every output file following a minimization fit. - fit_results -> A TTree containing each of the dial names, values, limits, etc. The best fit chi2 point and number of fit degrees of freedom is given in this tree. - fit_dials -> Best fit results and fit errors for each dial in units of 1-sigam variation. Dials with 0.0 bin errors are fixed. - start_dials -> Nominal values for these fit parameters in units of 1-sigma variation. - min_dials -> Mnimium limit for each dial in units of 1-sigma variation. (If a dial is fit very close to the limit within fit error... worry) - max_dials -> Maximum limit for each dial in units of 1-sigma variation. (If a dial is fit very close to the limit within fit error... worry) - fit_status -> Plot of some variables from the fit, mostly unimportant. - covariance -> Fit result covariance that the ROOT minimizer gives out. - correlation -> Correlation matrix form the fit - decomposition -> Decomposed covariance matrix from the fit, useful for fake data studies and producing error bands for correlated parameters.. The following plots are specific to a given fit depending on what samples where included. The structure is generally the same, and the sample identifier used in the fit card will correspond to which sample made these plots. By default the following distributions should be created, but whether they are saved is determined by the configuration option "drawOpts" given in the config file. - MiniBooNE_CCQE_XSec_1DQ2_data -> Data distribution for the sample that was loaded in the fit. - MiniBooNE_CCQE_XSec_1DQ2_MC -> Best fit MC distribution after the fit has been ran. Titles on these plots give the best fit Chi2 for that single sample which is useful when running joint fits. Error bands show the statistical errors only for the MC prediction. - MiniBooNE_CCQE_XSec_1DQ2_MC_Fine -> Finely binned MC distribution at best fit (Can sometimes disagree with coarse MC histogram because of scaling factors..) - MiniBooNE_CCQE_XSec_1DQ2_MC_Shape -> MC plot normalised to match the data normalisation - MiniBooNE_CCQE_XSec_1DQ2_data_Ratio -> Data/MC Ratio Plot - MiniBooNE_CCQE_XSec_1DQ2_MC_Ratio -> Baseline for Data/MC Ratio (Unity) - MiniBooNE_CCQE_XSec_1DQ2_data_Shape_Ratio -> Data/MC Ratio where the MC is normalised to match the dataset before the ratio is calculated. */ diff --git a/parameters/config.xml b/parameters/config.xml index 6766fb4..ff5c579 100644 --- a/parameters/config.xml +++ b/parameters/config.xml @@ -1,234 +1,235 @@ + - + diff --git a/scripts/nuiscardcreator.py b/scripts/nuiscardcreator.py index a1f61d1..43f5174 100755 --- a/scripts/nuiscardcreator.py +++ b/scripts/nuiscardcreator.py @@ -1,280 +1,280 @@ import argparse from ROOT import * import os, sys import xml.etree.ElementTree as ET from subprocess import call import inspect def PrintCard(): inputlist = {} inputtype = {} i = ET.parse('mysample.xml') for itype in i.findall('input'): filetype = itype.get('type') filename = itype.get('file') if filetype and filename: filegen = filename.split(":")[0] filename = filename.split(":")[1] if not filename: continue inputlist[filetype] = filename inputtype[filetype] = filegen e = ET.parse('sample_list.xml') for atype in e.findall('input'): samplename = atype.get('sample') sampletype = atype.get('type') newgen = "" typesplit = sampletype.replace(",",";").split(";") oldf = len(typesplit) newf = 0 for obj in typesplit: newobj = obj.replace("TYPE:","").replace("(","").replace(")","") if newobj in inputlist: sampletype = sampletype.replace(newobj, inputlist[newobj]) sampletype = sampletype.replace("TYPE", inputtype[newobj]) newf += 1 if newf != oldf: continue def PrintTypes(): print "" objlist = [] e = ET.parse('sample_list.xml') for atype in e.findall('input'): sampletype = atype.get('type') sampletype = sampletype.replace("TYPE:","").replace("(","").replace(")","") typesplit = sampletype.replace(",",";").split(";") for obj in typesplit: if obj not in objlist: objlist.append(obj) print '< type="'+obj+'" file="TYPE:" />' print "" forceful = False xmlformat = True def CreateBlankInputXML(outputcard): # Parse Sample List samplelist = str(os.environ['NUISANCE']) + '/src/FCN/sample_list.xml' samplelistxml = ET.parse(samplelist) # Keep track of unique ids idlist = [] commentlist = [] # Loop over all samples and find unique ids for sample in samplelistxml.findall('input'): # Read Comments comment = sample.get('eventcomment') if (comment): commentlist.append(comment) continue # Read Inputs inputid = sample.get('type') if (inputid): inputid = inputid.replace("TYPE:","").replace("(","").replace(")","") # Get all unique ids after split inputsplit = inputid.replace(",",";").split(";") for id in inputsplit: if id not in idlist: idlist.append(id) # Check for output card if os.path.isfile(outputcard) and not forceful: print "File:", outputcard, "already exists. Use -f flag to overwrite." sys.exit(-1) # Save out unique ids to xml (by writing manually...) f = open(outputcard,"w") f.write("\n\n") f.write(' \n') for comment in commentlist: f.write(' \n') f.write('\n\n') for id in idlist: f.write(' \n') f.write("") # Print out useage print "Created a new blank input example inside :", outputcard print "Fill in all the data files you care about, and then run: \n" print " $ nuiscardcreator -inputs " + outputcard + " -output nuisance.card \n" print "to generate a working nuisance card file. " sys.exit(0) def CheckComment(checks, comparison): for check in checks.split("/"): found = True for obj2 in check.split("+"): if obj2 not in comparison: found = False if found: return True return False def GenerateCardXML(inputs, outputs): inputfiles = {} inputtypes = {} # Parse our input card first inputlistxml = ET.parse(inputs) for inputfile in inputlistxml.findall('input'): # Get type and file filetype = inputfile.get('type') filename = inputfile.get('file') # Check valid if not filetype or not filename: continue # Split by path and type filegenr, filepath = filename.split(":") # Check both valid if not filegenr or not filepath: continue # Fill our containers inputfiles[filetype] = filepath inputtypes[filetype] = filegenr print inputfiles # Parse Sample List samplelist = str(os.environ['NUISANCE']) + '/src/FCN/sample_list.xml' samplelistxml = ET.parse(samplelist) # container for output lines sampleoutputs = [] allsamples = '' # Parser for sample in samplelistxml.findall('input'): # Allow for actions + comments if (sample.get('comment')): # Add to list sampleoutputs.append( ['@COMMENT', sample.get('comment'), sample.get('check')] ) continue if (sample.get('action')): sampleoutputs.append( ['@ACTION', sample.get('action')] ) continue # Get information samplename = sample.get('sample') sampletype = sample.get('type') # Check valid if not samplename or not sampletype: continue - # Seperate into uids + # Separate into uids typesplit = sampletype.replace(",",";").split(";") # Make sure we can replace all uids startlength = len(typesplit) endlength = 0 # Loop over all ids for uid in typesplit: parseduid = uid.replace("TYPE:","").replace("(","").replace(")","") # Check we have this file given if not parseduid in inputfiles: continue # Replace UID in samplelist with file given by user sampletype = sampletype.replace(parseduid, inputfiles[parseduid]) sampletype = sampletype.replace("TYPE", inputtypes[parseduid]) # Count how many uids replaced endlength += 1 # If not all uids caught, skip if startlength != endlength: continue sampleoutputs.append( [samplename, sampletype] ) allsamples += " " + samplename # Setup outputs outputfile = outputs if not outputfile: outputfile = inputs.replace(".xml","") + ".nuisance.xml" if os.path.isfile(outputfile) and not forceful: print "File:", outputfile, "already exists. Use -f flag to overwrite." sys.exit(-1) f = open(outputfile,"w") f.write("\n") for id in sampleoutputs: # Actions if id[0] == '@ACTION': if id[1] == 'BREAK': f.write(' \n' ) if id[1] == 'SKIP': f.write(' \n' ) continue # Comments if id[0] == '@COMMENT': if id[2] and not CheckComment(id[2],allsamples): continue f.write( ' \n') continue # Main Writing f.write(' \n') f.write("") sys.exit(0) if __name__ == '__main__': searchdescrip = "Set of tools used to generate nuisance card files" parser = argparse.ArgumentParser(description=searchdescrip) parser.add_argument('-blankinput' , help='Produce blank input file.') parser.add_argument('-blankcard' , help='Copies src/FCN/sample_list.xml to current directory') parser.add_argument('-f' , help='Force overwrites', action='store_true') parser.add_argument('-generate' , help='Generates a cardfile') parser.add_argument('-output' , help='Output') parser.add_argument('-format' , help='Format') args = parser.parse_args() if (args.f): forceful = True if (args.format): if args.format == "xml": xmlformat = True elif args.format == "txt": xmlformat = False if (xmlformat): if (args.blankinput): CreateBlankInputXML(args.blankinput) if (args.generate): GenerateCardXML(args.generate, args.output) diff --git a/src/ANL/ANL_CCQE_XSec_1DEnu_nu.cxx b/src/ANL/ANL_CCQE_XSec_1DEnu_nu.cxx index aca2998..aba8733 100644 --- a/src/ANL/ANL_CCQE_XSec_1DEnu_nu.cxx +++ b/src/ANL/ANL_CCQE_XSec_1DEnu_nu.cxx @@ -1,152 +1,152 @@ // 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 "ANL_CCQE_XSec_1DEnu_nu.h" //******************************************************************** ANL_CCQE_XSec_1DEnu_nu::ANL_CCQE_XSec_1DEnu_nu(nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "ANL CCQ2 XSec 1DEnu nu sample. \n" \ "Target: D2 \n" \ "Flux: \n" \ "Signal: \n"; // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); fSettings.SetXTitle("E_{#nu} (GeV)"); - fSettings.SetYTitle("#sigma(#E_{#nu}) (cm^{2}/neutron)"); + fSettings.SetYTitle("#sigma(E_{#nu}) (cm^{2}/neutron)"); fSettings.SetAllowedTypes("EVT/SHAPE/DIAG", "EVT/SHAPE/DIAG/Q2CORR/MASK"); fSettings.SetEnuRange(0.0, 6.0); fSettings.DefineAllowedTargets("D,H"); // plot information fSettings.SetTitle("ANL #nu_mu CCQE"); fSettings.DefineAllowedSpecies("numu"); // Hadronic Cut Info if (fSettings.Found("name", "PRL31")) { fSettings.SetDataInput( FitPar::GetDataBase() + "ANL/ANL_CCQE_Data_PRL31_844.root;ANL_1DEnu_Data" ); fSettings.SetEnuRange(0.0, 3.0); } else { fSettings.SetDataInput( FitPar::GetDataBase() + "ANL/ANL_CCQE_Data_PRD16_3103.root;ANL_1DEnu_fluxtuned_Data" ); } // is Q2 Correction applied applyQ2correction = fSettings.Found("type", "Q2CORR"); fSettings.SetS("q2correction_file", FitPar::GetDataBase() + "/ANL/ANL_CCQE_Data_PRL31_844.root"); fSettings.SetS("q2correction_hist", "ANL_1DQ2_Correction"); FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor for shape fScaleFactor = (GetEventHistogram()->Integral("width") * 2.0 / 1.0 * 1E-38 / (fNEvents + 0.)); // Plot Setup ------------------------------------------------------- SetDataFromRootFile( fSettings.GetDataInput() ); SetCovarFromDiagonal(); // Correction Histogram if (applyQ2correction) { // Correction Hist CorrectionHist = PlotUtils::GetTH1DFromFile( fSettings.GetS("q2correction_file"), fSettings.GetS("q2correction_hist") ); SetAutoProcessTH1(CorrectionHist, kCMD_Write); // Make uncorrected MC hist fMCHist_NoCorr = (TH1D*) fDataHist->Clone(); fMCHist_NoCorr->Reset(); fMCHist_NoCorr->SetNameTitle( (fName + "_NOCORR").c_str(), (fName + "_NOCORR").c_str()); SetAutoProcessTH1(fMCHist_NoCorr); } // Final setup --------------------------------------------------- FinaliseMeasurement(); } //******************************************************************** void ANL_CCQE_XSec_1DEnu_nu::FillEventVariables(FitEvent *event) { //******************************************************************** if (event->NumFSParticle(13) == 0) return; // Get Q2 double q2qe = 0.0; TLorentzVector Pnu = event->GetNeutrinoIn()->fP; TLorentzVector Pmu = event->GetHMFSParticle(13)->fP; ThetaMu = Pnu.Vect().Angle(Pmu.Vect()); q2qe = FitUtils::Q2QErec(Pmu, cos(ThetaMu), 0., true); Enu_rec = FitUtils::EnuQErec(Pmu, cos(ThetaMu), 0., true); fXVar = Enu_rec; GetQ2Box()->fQ2 = q2qe; return; }; //******************************************************************** bool ANL_CCQE_XSec_1DEnu_nu::isSignal(FitEvent *event) { //******************************************************************** return SignalDef::isCCQE(event, 14, EnuMin, EnuMax); }; //******************************************************************** void ANL_CCQE_XSec_1DEnu_nu::FillHistograms() { //******************************************************************** if (applyQ2correction) { fMCHist_NoCorr->Fill( GetQ2Box()->fQ2, Weight); if (GetQ2Box()->fQ2 < CorrectionHist->GetXaxis()->GetXmax() && GetQ2Box()->fQ2 > CorrectionHist->GetXaxis()->GetXmin()) Weight *= CorrectionHist->Interpolate(GetQ2Box()->fQ2); } Measurement1D::FillHistograms(); } //******************************************************************** void ANL_CCQE_XSec_1DEnu_nu::ScaleEvents() { //******************************************************************** Measurement1D::ScaleEvents(); // Flux unfold our extra histogram if (applyQ2correction) { PlotUtils::FluxUnfoldedScaling(fMCHist_NoCorr, GetFluxHistogram(), GetEventHistogram(), fScaleFactor, fNEvents); } } diff --git a/src/BNL/BNL_CC1npip_Evt_1DQ2_nu.cxx b/src/BNL/BNL_CC1npip_Evt_1DQ2_nu.cxx index 68957bb..df844bb 100644 --- a/src/BNL/BNL_CC1npip_Evt_1DQ2_nu.cxx +++ b/src/BNL/BNL_CC1npip_Evt_1DQ2_nu.cxx @@ -1,83 +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 . *******************************************************************************/ #include "BNL_CC1npip_Evt_1DQ2_nu.h" +// T. Kitagaki et al. "Charged-current exclusive pion production in neutrino-deuterium interactions" +// Physical Review D, Volume 34, Number 9, 1 Nov 1986 +// Figure 3 +// +// Also see +// N. J. Baker et al. "Study of the isospin structure of single-pion production in charged-current neutrino interactions" +// Physical Review D, Volume 23, Number 11, 1 June 1981 +// +// K. Furuno et al. NuInt02 proceedings, (supposedly published in Nucl. Phys. B but I never found it), Retreieved from KEK preprints. +// KEK Preprint 2003-48, RCNS-03-01, September 2003 //******************************************************************** BNL_CC1npip_Evt_1DQ2_nu::BNL_CC1npip_Evt_1DQ2_nu(nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "BNL_CC1npip_Evt_1DQ2_nu sample. \n" \ "Target: D2 \n" \ "Flux: \n" \ "Signal: \n"; // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); fSettings.SetXTitle("Q^{2}_{CC#pi} (GeV^{2})"); fSettings.SetYTitle("Number of events"); fSettings.SetAllowedTypes("EVT/SHAPE/DIAG", "EVT/SHAPE/DIAG"); fSettings.SetEnuRange(0.0, 3.0); fSettings.DefineAllowedTargets("D,H"); // CCQELike plot information fSettings.SetTitle("BNL_CC1npip_Evt_1DQ2_nu"); fSettings.SetDataInput( FitPar::GetDataBase() + "/BNL/CC1pip_on_n/BNL_CC1pip_on_n_noEvents_q2_noWcut_HighQ2Gone.txt" ); fSettings.DefineAllowedSpecies("numu"); FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon fScaleFactor =GetEventHistogram()->Integral("width")/(fNEvents+0.)*2./1.; // Plot Setup ------------------------------------------------------- SetDataFromTextFile( fSettings.GetDataInput() ); SetPoissonErrors(); SetCovarFromDiagonal(); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; void BNL_CC1npip_Evt_1DQ2_nu::FillEventVariables(FitEvent *event) { if (event->NumFSParticle(13) == 0) return; TLorentzVector Pnu = event->GetNeutrinoIn()->fP; TLorentzVector Pmu = event->GetHMFSParticle(13)->fP; // No hadronic mass constraint in BNL CC1n1pi+ // This Q2 is Q2 true double q2CCpip = -1*(Pnu-Pmu).Mag2()/1.E6; fXVar = q2CCpip; return; }; bool BNL_CC1npip_Evt_1DQ2_nu::isSignal(FitEvent *event) { return SignalDef::isCC1pi3Prong(event, 14, 211, 2112, EnuMin, EnuMax); } diff --git a/src/BNL/BNL_CC1npip_Evt_1DQ2_nu.h b/src/BNL/BNL_CC1npip_Evt_1DQ2_nu.h index 0c985cd..4a85f6a 100644 --- a/src/BNL/BNL_CC1npip_Evt_1DQ2_nu.h +++ b/src/BNL/BNL_CC1npip_Evt_1DQ2_nu.h @@ -1,36 +1,47 @@ // 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 BNL_CC1NPIP_EVT_1DQ2_NU_H_SEEN #define BNL_CC1NPIP_EVT_1DQ2_NU_H_SEEN #include "Measurement1D.h" +// T. Kitagaki et al. "Charged-current exclusive pion production in neutrino-deuterium interactions" +// Physical Review D, Volume 34, Number 9, 1 Nov 1986 +// Figure 3 +// +// Also see +// N. J. Baker et al. "Study of the isospin structure of single-pion production in charged-current neutrino interactions" +// Physical Review D, Volume 23, Number 11, 1 June 1981 +// +// K. Furuno et al. NuInt02 proceedings, (supposedly published in Nucl. Phys. B but I never found it), Retreieved from KEK preprints. +// KEK Preprint 2003-48, RCNS-03-01, September 2003 + class BNL_CC1npip_Evt_1DQ2_nu : public Measurement1D { public: BNL_CC1npip_Evt_1DQ2_nu(nuiskey samplekey); virtual ~BNL_CC1npip_Evt_1DQ2_nu() {}; void FillEventVariables(FitEvent *event); bool isSignal(FitEvent *event); private: }; #endif diff --git a/src/BNL/BNL_CC1npip_XSec_1DEnu_nu.cxx b/src/BNL/BNL_CC1npip_XSec_1DEnu_nu.cxx index 5a67861..a2f8080 100644 --- a/src/BNL/BNL_CC1npip_XSec_1DEnu_nu.cxx +++ b/src/BNL/BNL_CC1npip_XSec_1DEnu_nu.cxx @@ -1,104 +1,114 @@ // 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 "BNL_CC1npip_XSec_1DEnu_nu.h" +// T. Kitagaki et al. "Charged-current exclusive pion production in neutrino-deuterium interactions" +// Physical Review D, Volume 34, Number 9, 1 Nov 1986 +// Figure 7 +// +// Also see +// N. J. Baker et al. "Study of the isospin structure of single-pion production in charged-current neutrino interactions" +// Physical Review D, Volume 23, Number 11, 1 June 1981 +// +// K. Furuno et al. NuInt02 proceedings, (supposedly published in Nucl. Phys. B but I never found it), Retreieved from KEK preprints. +// KEK Preprint 2003-48, RCNS-03-01, September 2003 //******************************************************************** BNL_CC1npip_XSec_1DEnu_nu::BNL_CC1npip_XSec_1DEnu_nu(nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "BNL_CC1npip_XSec_1DEnu_nu sample. \n" \ "Target: D2 \n" \ "Flux: \n" \ "Signal: \n"; // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); fSettings.SetXTitle("E_{#nu} (GeV)"); fSettings.SetYTitle("#sigma (cm^{2}/neutron)"); fSettings.SetAllowedTypes("FIX/DIAG", "FIX,FREE,SHAPE/DIAG"); fSettings.SetEnuRange(0.0, 3.0); fSettings.SetS("norm_error", "0.15"); fSettings.DefineAllowedTargets("D,H"); // plot information fSettings.SetTitle("BNL_CC1npip_XSec_1DEnu_nu"); fSettings.DefineAllowedSpecies("numu"); // User can specifiy to use uncorrected data UseCorrectedData = !fSettings.Found("name", "Uncorr"); // Now read in different data depending on what the user has specified std::string DataLocation = GeneralUtils::GetTopLevelDir() + "/data/BNL/CC1pip_on_n/"; // If we're using corrected data if (UseCorrectedData) { DataLocation += "BNL_CC1pip_on_n_1986_corr.txt"; // If we're using raw uncorrected data } else { DataLocation += "BNL_CC1pip_on_n_1986.txt"; } fSettings.SetDataInput(DataLocation); FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/proton fScaleFactor = (GetEventHistogram()->Integral("width") * 1E-38) / ((fNEvents + 0.)) * 2. / 1.; // Plot Setup ------------------------------------------------------- SetDataFromTextFile( fSettings.GetDataInput() ); SetCovarFromDiagonal(); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; void BNL_CC1npip_XSec_1DEnu_nu::FillEventVariables(FitEvent *event) { TLorentzVector Pnu = event->GetNeutrinoIn()->fP; // No W cut for BNL CC1pi+ on neutron (I'm happy if you can find it!!!) double Enu = Pnu.E()/1000.; fXVar = Enu; return; }; bool BNL_CC1npip_XSec_1DEnu_nu::isSignal(FitEvent *event) { // BNL has somewhat tricky signal definition for the selection: // P_visible = visible 4-momentum, so the three tracks total momentum // P_visible > 150 MeV/c2 // Theta_Pvis_nu (angle between visible momentum and neutrino direction) < 50 degrees // At least one negative track leaves chamber without interacting or stops consistent with muon // THESE ARE NOT IMPLEMENTED BUT SHOULD BE KNOWN BY ANYONE WHO FITS THIS DATA! (see Kitagaki et al. 2556) // // The only actual restriction seems to be the final state particles. There's no mention of E_nu restrictions either (events span to 10GeV in fig 2, Kitagaki) // There's a mention of uncertainity in the neutrino flux for Enu > 6.0 GeV return SignalDef::isCC1pi3Prong(event, 14, 211, 2112, EnuMin, EnuMax); } diff --git a/src/BNL/BNL_CC1npip_XSec_1DEnu_nu.h b/src/BNL/BNL_CC1npip_XSec_1DEnu_nu.h index 5cdab22..0770b35 100644 --- a/src/BNL/BNL_CC1npip_XSec_1DEnu_nu.h +++ b/src/BNL/BNL_CC1npip_XSec_1DEnu_nu.h @@ -1,38 +1,48 @@ // 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 BNL_CC1NPIP_XSEC_1DENU_NU_H_SEEN #define BNL_CC1NPIP_XSEC_1DENU_NU_H_SEEN #include "Measurement1D.h" +// T. Kitagaki et al. "Charged-current exclusive pion production in neutrino-deuterium interactions" +// Physical Review D, Volume 34, Number 9, 1 Nov 1986 +// Figure 7 +// +// Also see +// N. J. Baker et al. "Study of the isospin structure of single-pion production in charged-current neutrino interactions" +// Physical Review D, Volume 23, Number 11, 1 June 1981 +// +// K. Furuno et al. NuInt02 proceedings, (supposedly published in Nucl. Phys. B but I never found it), Retreieved from KEK preprints. +// KEK Preprint 2003-48, RCNS-03-01, September 2003 class BNL_CC1npip_XSec_1DEnu_nu : public Measurement1D { public: BNL_CC1npip_XSec_1DEnu_nu(nuiskey samplekey); virtual ~BNL_CC1npip_XSec_1DEnu_nu() {}; void FillEventVariables(FitEvent *event); bool isSignal(FitEvent *event); private: bool UseCorrectedData; }; #endif diff --git a/src/BNL/BNL_CC1pi0_Evt_1DQ2_nu.cxx b/src/BNL/BNL_CC1pi0_Evt_1DQ2_nu.cxx index 5ce9ba0..11ff3c4 100644 --- a/src/BNL/BNL_CC1pi0_Evt_1DQ2_nu.cxx +++ b/src/BNL/BNL_CC1pi0_Evt_1DQ2_nu.cxx @@ -1,85 +1,95 @@ // 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 "BNL_CC1pi0_Evt_1DQ2_nu.h" +// T. Kitagaki et al. "Charged-current exclusive pion production in neutrino-deuterium interactions" +// Physical Review D, Volume 34, Number 9, 1 Nov 1986 +// Figure 3 +// +// Also see +// N. J. Baker et al. "Study of the isospin structure of single-pion production in charged-current neutrino interactions" +// Physical Review D, Volume 23, Number 11, 1 June 1981 +// +// K. Furuno et al. NuInt02 proceedings, (supposedly published in Nucl. Phys. B but I never found it), Retreieved from KEK preprints. +// KEK Preprint 2003-48, RCNS-03-01, September 2003 //******************************************************************** BNL_CC1pi0_Evt_1DQ2_nu::BNL_CC1pi0_Evt_1DQ2_nu(nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "BNL_CC1pi0_Evt_1DQ2_nu sample. \n" \ "Target: D2 \n" \ "Flux: \n" \ "Signal: \n"; // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); fSettings.SetXTitle("Q^{2}_{CC#pi} (GeV^{2})"); fSettings.SetYTitle("Number of events"); fSettings.SetAllowedTypes("EVT/SHAPE/DIAG", "EVT/SHAPE/DIAG"); fSettings.SetEnuRange(0.0, 6.0); fSettings.DefineAllowedTargets("D,H"); // CCQELike plot information fSettings.SetTitle("BNL_CC1pi0_Evt_1DQ2_nu"); fSettings.SetDataInput( FitPar::GetDataBase() + "/BNL/CC1pi0_on_n/BNL_CC1pi0_on_n_noEvents_q2_noWcut_HighQ2Gone.txt" ); fSettings.DefineAllowedSpecies("numu"); FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon fScaleFactor = GetEventHistogram()->Integral("width")/(fNEvents+0.); // Plot Setup ------------------------------------------------------- SetDataFromTextFile( fSettings.GetDataInput() ); SetPoissonErrors(); SetCovarFromDiagonal(); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; void BNL_CC1pi0_Evt_1DQ2_nu::FillEventVariables(FitEvent *event) { if (event->NumFSParticle(13) == 0) return; TLorentzVector Pnu = event->GetNeutrinoIn()->fP; TLorentzVector Pmu = event->GetHMFSParticle(13)->fP; // No W cut on BNL CC1pi0 // Want true Q2 double q2CCpi0 = -1*(Pnu-Pmu).Mag2()/1.E6; fXVar = q2CCpi0; return; }; bool BNL_CC1pi0_Evt_1DQ2_nu::isSignal(FitEvent *event) { return SignalDef::isCC1pi3Prong(event, 14, 111, 2212, EnuMin, EnuMax); } diff --git a/src/BNL/BNL_CC1pi0_Evt_1DQ2_nu.h b/src/BNL/BNL_CC1pi0_Evt_1DQ2_nu.h index 7ae08e2..87d137a 100644 --- a/src/BNL/BNL_CC1pi0_Evt_1DQ2_nu.h +++ b/src/BNL/BNL_CC1pi0_Evt_1DQ2_nu.h @@ -1,37 +1,47 @@ // 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 BNL_CC1PI0_EVT_1DQ2_NU_H_SEEN #define BNL_CC1PI0_EVT_1DQ2_NU_H_SEEN #include "Measurement1D.h" +// T. Kitagaki et al. "Charged-current exclusive pion production in neutrino-deuterium interactions" +// Physical Review D, Volume 34, Number 9, 1 Nov 1986 +// Figure 3 +// +// Also see +// N. J. Baker et al. "Study of the isospin structure of single-pion production in charged-current neutrino interactions" +// Physical Review D, Volume 23, Number 11, 1 June 1981 +// +// K. Furuno et al. NuInt02 proceedings, (supposedly published in Nucl. Phys. B but I never found it), Retreieved from KEK preprints. +// KEK Preprint 2003-48, RCNS-03-01, September 2003 class BNL_CC1pi0_Evt_1DQ2_nu : public Measurement1D { public: BNL_CC1pi0_Evt_1DQ2_nu(nuiskey samplekey); virtual ~BNL_CC1pi0_Evt_1DQ2_nu() {}; void FillEventVariables(FitEvent *event); bool isSignal(FitEvent *event); private: }; #endif diff --git a/src/BNL/BNL_CC1pi0_XSec_1DEnu_nu.cxx b/src/BNL/BNL_CC1pi0_XSec_1DEnu_nu.cxx index 13c0251..30330cf 100644 --- a/src/BNL/BNL_CC1pi0_XSec_1DEnu_nu.cxx +++ b/src/BNL/BNL_CC1pi0_XSec_1DEnu_nu.cxx @@ -1,97 +1,107 @@ // 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 "BNL_CC1pi0_XSec_1DEnu_nu.h" +// T. Kitagaki et al. "Charged-current exclusive pion production in neutrino-deuterium interactions" +// Physical Review D, Volume 34, Number 9, 1 Nov 1986 +// Figure 7 +// +// Also see +// N. J. Baker et al. "Study of the isospin structure of single-pion production in charged-current neutrino interactions" +// Physical Review D, Volume 23, Number 11, 1 June 1981 +// +// K. Furuno et al. NuInt02 proceedings, (supposedly published in Nucl. Phys. B but I never found it), Retreieved from KEK preprints. +// KEK Preprint 2003-48, RCNS-03-01, September 2003 //******************************************************************** BNL_CC1pi0_XSec_1DEnu_nu::BNL_CC1pi0_XSec_1DEnu_nu(nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "BNL_CC1pi0_XSec_1DEnu_nu sample. \n" \ "Target: D2 \n" \ "Flux: \n" \ "Signal: \n"; // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); fSettings.SetXTitle("E_{#nu} (GeV)"); fSettings.SetYTitle("#sigma (cm^{2}/neutron)"); fSettings.SetAllowedTypes("FIX/DIAG", "FIX,FREE,SHAPE/DIAG"); fSettings.SetEnuRange(0.0, 6.0); fSettings.SetS("norm_error", "0.15"); fSettings.DefineAllowedTargets("D,H"); // plot information fSettings.SetTitle("BNL_CC1pi0_XSec_1DEnu_nu"); fSettings.DefineAllowedSpecies("numu"); // User can specifiy to use uncorrected data UseCorrectedData = !fSettings.Found("name", "Uncorr"); // Now read in different data depending on what the user has specified std::string DataLocation = GeneralUtils::GetTopLevelDir() + "/data/BNL/CC1pi0_on_n/"; // If we're using corrected data if (UseCorrectedData) { DataLocation += "BNL_CC1pi0_on_n_1986_corr.txt"; // If we're using raw uncorrected data } else { DataLocation += "BNL_CC1pi0_on_n_1986.txt"; } fSettings.SetDataInput(DataLocation); FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/proton fScaleFactor = (GetEventHistogram()->Integral("width") * 1E-38) / (fNEvents + 0.) * 2. / 1.; // Plot Setup ------------------------------------------------------- SetDataFromTextFile( fSettings.GetDataInput() ); SetCovarFromDiagonal(); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; void BNL_CC1pi0_XSec_1DEnu_nu::FillEventVariables(FitEvent *event) { TLorentzVector Pnu = event->GetNeutrinoIn()->fP; //BNL doesn't have a W cut for CC1pi0 sadly (I'm super happy if you can find it!) double Enu = Pnu.E() / 1000.; fXVar = Enu; return; } bool BNL_CC1pi0_XSec_1DEnu_nu::isSignal(FitEvent *event) { return SignalDef::isCC1pi3Prong(event, 14, 111, 2212, EnuMin, EnuMax); } diff --git a/src/BNL/BNL_CC1pi0_XSec_1DEnu_nu.h b/src/BNL/BNL_CC1pi0_XSec_1DEnu_nu.h index 688acab..ede614d 100644 --- a/src/BNL/BNL_CC1pi0_XSec_1DEnu_nu.h +++ b/src/BNL/BNL_CC1pi0_XSec_1DEnu_nu.h @@ -1,37 +1,47 @@ // 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 BNL_CC1PI0_XSEC_1DENU_NU_H_SEEN #define BNL_CC1PI0_XSEC_1DENU_NU_H_SEEN #include "Measurement1D.h" +// T. Kitagaki et al. "Charged-current exclusive pion production in neutrino-deuterium interactions" +// Physical Review D, Volume 34, Number 9, 1 Nov 1986 +// Figure 7 +// +// Also see +// N. J. Baker et al. "Study of the isospin structure of single-pion production in charged-current neutrino interactions" +// Physical Review D, Volume 23, Number 11, 1 June 1981 +// +// K. Furuno et al. NuInt02 proceedings, (supposedly published in Nucl. Phys. B but I never found it), Retreieved from KEK preprints. +// KEK Preprint 2003-48, RCNS-03-01, September 2003 class BNL_CC1pi0_XSec_1DEnu_nu : public Measurement1D { public: BNL_CC1pi0_XSec_1DEnu_nu(nuiskey samplekey); virtual ~BNL_CC1pi0_XSec_1DEnu_nu() {}; void FillEventVariables(FitEvent *event); bool isSignal(FitEvent *event); private: bool UseCorrectedData; }; #endif diff --git a/src/BNL/BNL_CC1ppip_Evt_1DQ2_nu.cxx b/src/BNL/BNL_CC1ppip_Evt_1DQ2_nu.cxx index c1f4573..b303d44 100644 --- a/src/BNL/BNL_CC1ppip_Evt_1DQ2_nu.cxx +++ b/src/BNL/BNL_CC1ppip_Evt_1DQ2_nu.cxx @@ -1,110 +1,114 @@ // 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 . *******************************************************************************/ -/** - * Kitagaki et al. Phys Rev D, Volume 34, Number 9, 1 November 1986, p2254-2565 - * K. Furuno et al. NuInt02 proceedings, (supposedly published in Nucl. Phys. B but I never found it), Retreieved from KEK preprints. - * KEK Preprint 2003-48, RCNS-03-01, September 2003 -*/ +// T. Kitagaki et al. "Charged-current exclusive pion production in neutrino-deuterium interactions" +// Physical Review D, Volume 34, Number 9, 1 Nov 1986 +// Figure 3 +// +// K. Furuno et al. NuInt02 proceedings, (supposedly published in Nucl. Phys. B but I never found it), Retreieved from KEK preprints. +// KEK Preprint 2003-48, RCNS-03-01, September 2003 +// Figure 8 +// +// Also see +// N. J. Baker et al. "Study of the isospin structure of single-pion production in charged-current neutrino interactions" +// Physical Review D, Volume 23, Number 11, 1 June 1981 #include "BNL_CC1ppip_Evt_1DQ2_nu.h" - - //******************************************************************** BNL_CC1ppip_Evt_1DQ2_nu::BNL_CC1ppip_Evt_1DQ2_nu(nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "BNL_CC1ppip_Evt_1DQ2_nu sample. \n" \ "Target: D2 \n" \ "Flux: \n" \ "Signal: \n"; // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); fSettings.SetXTitle("Q^{2}_{CC#pi} (GeV^{2})"); fSettings.SetYTitle("Number of events"); fSettings.SetAllowedTypes("EVT/SHAPE/DIAG", "EVT/SHAPE/DIAG"); fSettings.SetEnuRange(0.5, 6.0); fSettings.DefineAllowedTargets("D,H"); // plot information fSettings.SetTitle("BNL #nu_mu CC1n#pi^{+}"); fSettings.DefineAllowedSpecies("numu"); // Hadronic Cut Info HadCut = fSettings.Found("name", "W14Cut") ? 1.4 : 10.0; if (HadCut == 1.4) { fSettings.SetDataInput( FitPar::GetDataBase() + "/BNL/CC1pip_on_p/BNL_CC1pip_on_p_noEvents_q2_w14_enu05to6_firstQ2rem.txt" ); } else { fSettings.SetDataInput( FitPar::GetDataBase() + "/BNL/CC1pip_on_p/BNL_CC1pip_on_p_noEvents_q2_noWcut_HighQ2Gone.txt"); fSettings.SetEnuRange(0.0, 10.0); } FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon fScaleFactor = GetEventHistogram()->Integral("width") / (fNEvents + 0.); // Plot Setup ------------------------------------------------------- SetDataFromTextFile( fSettings.GetDataInput() ); SetPoissonErrors(); SetCovarFromDiagonal(); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; void BNL_CC1ppip_Evt_1DQ2_nu::FillEventVariables(FitEvent *event) { if (event->NumFSParticle(2212) == 0 || event->NumFSParticle(211) == 0 || event->NumFSParticle(13) == 0) { return; } TLorentzVector Pnu = event->GetNeutrinoIn()->fP; TLorentzVector Pp = event->GetHMFSParticle(2212)->fP; TLorentzVector Ppip = event->GetHMFSParticle(211)->fP; TLorentzVector Pmu = event->GetHMFSParticle(13)->fP; double hadMass = FitUtils::MpPi(Pp, Ppip); double q2CCpip = -1.0; // BNL has a M(pi, p) < 1.4 GeV cut and no W cut. // This should be specified by user in "type" field // Reverts to 10 GeV (essentially no W cut!) if (hadMass < HadCut * 1000.) { q2CCpip = -1 * (Pnu - Pmu).Mag2() / 1.E6; } fXVar = q2CCpip; return; }; bool BNL_CC1ppip_Evt_1DQ2_nu::isSignal(FitEvent *event) { return SignalDef::isCC1pi3Prong(event, 14, 211, 2212, EnuMin, EnuMax); } diff --git a/src/BNL/BNL_CC1ppip_Evt_1DQ2_nu.h b/src/BNL/BNL_CC1ppip_Evt_1DQ2_nu.h index 9c58c22..d8d435e 100644 --- a/src/BNL/BNL_CC1ppip_Evt_1DQ2_nu.h +++ b/src/BNL/BNL_CC1ppip_Evt_1DQ2_nu.h @@ -1,37 +1,48 @@ // 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 BNL_CC1PPIP_EVT_1DQ2_NU_H_SEEN #define BNL_CC1PPIP_EVT_1DQ2_NU_H_SEEN #include "Measurement1D.h" +// T. Kitagaki et al. "Charged-current exclusive pion production in neutrino-deuterium interactions" +// Physical Review D, Volume 34, Number 9, 1 Nov 1986 +// Figure 3 +// +// K. Furuno et al. NuInt02 proceedings, (supposedly published in Nucl. Phys. B but I never found it), Retreieved from KEK preprints. +// KEK Preprint 2003-48, RCNS-03-01, September 2003 +// Figure 8 +// +// Also see +// N. J. Baker et al. "Study of the isospin structure of single-pion production in charged-current neutrino interactions" +// Physical Review D, Volume 23, Number 11, 1 June 1981 class BNL_CC1ppip_Evt_1DQ2_nu : public Measurement1D { public: BNL_CC1ppip_Evt_1DQ2_nu(nuiskey samplekey); virtual ~BNL_CC1ppip_Evt_1DQ2_nu() {}; void FillEventVariables(FitEvent *event); bool isSignal(FitEvent *event); private: double HadCut; // Hadronic mass cut, specified by user (W < 1.4 or no W cut) }; #endif diff --git a/src/BNL/BNL_CC1ppip_Evt_1DcosthAdler_nu.cxx b/src/BNL/BNL_CC1ppip_Evt_1DcosthAdler_nu.cxx index 306cc6a..7ae0582 100644 --- a/src/BNL/BNL_CC1ppip_Evt_1DcosthAdler_nu.cxx +++ b/src/BNL/BNL_CC1ppip_Evt_1DcosthAdler_nu.cxx @@ -1,90 +1,100 @@ // 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 "BNL_CC1ppip_Evt_1DcosthAdler_nu.h" +// T. Kitagaki et al. "Charged-current exclusive pion production in neutrino-deuterium interactions" +// Physical Review D, Volume 34, Number 9, 1 Nov 1986 +// Figure 12 and related +// +// Also see +// N. J. Baker et al. "Study of the isospin structure of single-pion production in charged-current neutrino interactions" +// Physical Review D, Volume 23, Number 11, 1 June 1981 +// +// K. Furuno et al. NuInt02 proceedings, (supposedly published in Nucl. Phys. B but I never found it), Retreieved from KEK preprints. +// KEK Preprint 2003-48, RCNS-03-01, September 2003 //******************************************************************** BNL_CC1ppip_Evt_1DcosthAdler_nu::BNL_CC1ppip_Evt_1DcosthAdler_nu(nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "BNL_CC1ppip_Evt_1DcosthAdler_nu sample. \n" \ "Target: D2 \n" \ "Flux: \n" \ "Signal: \n"; // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); fSettings.SetXTitle("cos#theta_{Adler}"); fSettings.SetYTitle("Number of events"); fSettings.SetAllowedTypes("EVT/SHAPE/DIAG", "EVT/SHAPE/DIAG"); fSettings.SetEnuRange(0.5, 6.0); fSettings.DefineAllowedTargets("D,H"); // CCQELike plot information fSettings.SetTitle("BNL_CC1ppip_Evt_1DcosthAdler_nu"); fSettings.SetDataInput( FitPar::GetDataBase() + "/BNL/CC1pip_on_p/BNL_CC1ppip_W14_cosThAdler.csv" ); fSettings.DefineAllowedSpecies("numu"); FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon fScaleFactor =GetEventHistogram()->Integral("width")/(fNEvents+0.)*2./1.; // Plot Setup ------------------------------------------------------- SetDataFromTextFile( fSettings.GetDataInput() ); SetPoissonErrors(); SetCovarFromDiagonal(); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; void BNL_CC1ppip_Evt_1DcosthAdler_nu::FillEventVariables(FitEvent *event) { fXVar = -999.99; if (event->NumFSParticle(2212) == 0 || event->NumFSParticle(211) == 0 || event->NumFSParticle(13) == 0) return; TLorentzVector Pnu = event->GetNeutrinoIn()->fP; TLorentzVector Pp = event->GetHMFSParticle(2212)->fP; TLorentzVector Ppip = event->GetHMFSParticle(211)->fP; TLorentzVector Pmu = event->GetHMFSParticle(13)->fP; // Get the hadronic mass double hadMass = FitUtils::MpPi(Pp, Ppip); if (hadMass > 1400) return; // Get Adler cos theta double cosThAdler = FitUtils::CosThAdler(Pnu, Pmu, Ppip, Pp); fXVar = cosThAdler; }; bool BNL_CC1ppip_Evt_1DcosthAdler_nu::isSignal(FitEvent *event) { return SignalDef::isCC1pi3Prong(event, 14, 211, 2212,EnuMin,EnuMax); } diff --git a/src/BNL/BNL_CC1ppip_Evt_1DcosthAdler_nu.h b/src/BNL/BNL_CC1ppip_Evt_1DcosthAdler_nu.h index a60c714..8db8ed7 100644 --- a/src/BNL/BNL_CC1ppip_Evt_1DcosthAdler_nu.h +++ b/src/BNL/BNL_CC1ppip_Evt_1DcosthAdler_nu.h @@ -1,38 +1,48 @@ // 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 BNL_CC1PPIP_EVT_1DCOSTHADLER_NU_H_SEEN #define BNL_CC1PPIP_EVT_1DCOSTHADLER_NU_H_SEEN #include "Measurement1D.h" +// T. Kitagaki et al. "Charged-current exclusive pion production in neutrino-deuterium interactions" +// Physical Review D, Volume 34, Number 9, 1 Nov 1986 +// Figure 12 and related +// +// Also see +// N. J. Baker et al. "Study of the isospin structure of single-pion production in charged-current neutrino interactions" +// Physical Review D, Volume 23, Number 11, 1 June 1981 +// +// K. Furuno et al. NuInt02 proceedings, (supposedly published in Nucl. Phys. B but I never found it), Retreieved from KEK preprints. +// KEK Preprint 2003-48, RCNS-03-01, September 2003 class BNL_CC1ppip_Evt_1DcosthAdler_nu : public Measurement1D { public: BNL_CC1ppip_Evt_1DcosthAdler_nu(nuiskey samplekey); virtual ~BNL_CC1ppip_Evt_1DcosthAdler_nu() {}; void FillEventVariables(FitEvent *event); bool isSignal(FitEvent *event); private: }; #endif diff --git a/src/BNL/BNL_CC1ppip_Evt_1Dphi_nu.cxx b/src/BNL/BNL_CC1ppip_Evt_1Dphi_nu.cxx index 03b4826..dd39272 100644 --- a/src/BNL/BNL_CC1ppip_Evt_1Dphi_nu.cxx +++ b/src/BNL/BNL_CC1ppip_Evt_1Dphi_nu.cxx @@ -1,113 +1,123 @@ // 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 "BNL_CC1ppip_Evt_1Dphi_nu.h" +// T. Kitagaki et al. "Charged-current exclusive pion production in neutrino-deuterium interactions" +// Physical Review D, Volume 34, Number 9, 1 Nov 1986 +// Figure 12 and related +// +// Also see +// N. J. Baker et al. "Study of the isospin structure of single-pion production in charged-current neutrino interactions" +// Physical Review D, Volume 23, Number 11, 1 June 1981 +// +// K. Furuno et al. NuInt02 proceedings, (supposedly published in Nucl. Phys. B but I never found it), Retreieved from KEK preprints. +// KEK Preprint 2003-48, RCNS-03-01, September 2003 //******************************************************************** BNL_CC1ppip_Evt_1Dphi_nu::BNL_CC1ppip_Evt_1Dphi_nu(nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "BNL_CC1ppip_Evt_1Dphi_nu sample. \n" \ "Target: D2 \n" \ "Flux: \n" \ "Signal: \n"; // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); fSettings.SetXTitle("#phi_{Adler}"); fSettings.SetYTitle("Number of events"); fSettings.SetAllowedTypes("EVT/SHAPE/DIAG", "EVT/SHAPE/DIAG"); fSettings.SetEnuRange(0.0, 6.0); fSettings.DefineAllowedTargets("D,H"); // CCQELike plot information fSettings.SetTitle("BNL_CC1ppip_Evt_1Dphi_nu"); fSettings.SetDataInput( FitPar::GetDataBase() + "/BNL/CC1pip_on_p/BNL_CC1ppip_W14_phiAdler.csv" ); fSettings.DefineAllowedSpecies("numu"); FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon fScaleFactor =GetEventHistogram()->Integral("width")/(fNEvents+0.)*2./1.; // Plot Setup ------------------------------------------------------- SetDataFromTextFile( fSettings.GetDataInput() ); SetPoissonErrors(); SetCovarFromDiagonal(); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; void BNL_CC1ppip_Evt_1Dphi_nu::FillEventVariables(FitEvent *event) { fXVar = -999.99; if (event->NumFSParticle(2212) == 0 || event->NumFSParticle(211) == 0 || event->NumFSParticle(13) == 0) return; TLorentzVector Pnu = event->GetNeutrinoIn()->fP; TLorentzVector Pp = event->GetHMFSParticle(2212)->fP; TLorentzVector Ppip = event->GetHMFSParticle(211)->fP; TLorentzVector Pmu = event->GetHMFSParticle(13)->fP; // Get the hadronic mass double hadMass = FitUtils::MpPi(Pp, Ppip); if (hadMass > 1400) return; // Get phi Adler double phi = FitUtils::PhiAdler(Pnu, Pmu, Ppip, Pp); fXVar = phi; }; bool BNL_CC1ppip_Evt_1Dphi_nu::isSignal(FitEvent *event) { return SignalDef::isCC1pi3Prong(event, 14, 211, 2212,EnuMin,EnuMax); } /* void BNL_CC1ppip_Evt_1Dphi_nu::FillHistograms() { if (makeHadronicMassHist) { hadMassHist->Fill(hadMass); } Measurement1D::FillHistograms(); } void BNL_CC1ppip_Evt_1Dphi_nu::ScaleEvents() { PlotUtils::FluxUnfoldedScaling(fMCHist, GetFluxHistogram()); PlotUtils::FluxUnfoldedScaling(fMCFine, GetFluxHistogram()); fMCHist->Scale(fScaleFactor); fMCFine->Scale(fScaleFactor); return; } */ diff --git a/src/BNL/BNL_CC1ppip_Evt_1Dphi_nu.h b/src/BNL/BNL_CC1ppip_Evt_1Dphi_nu.h index 867c0a7..d9b077f 100644 --- a/src/BNL/BNL_CC1ppip_Evt_1Dphi_nu.h +++ b/src/BNL/BNL_CC1ppip_Evt_1Dphi_nu.h @@ -1,39 +1,49 @@ // 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 BNL_CC1PPIP_EVT_1DPHI_NU_H_SEEN #define BNL_CC1PPIP_EVT_1DPHI_NU_H_SEEN #include "Measurement1D.h" +// T. Kitagaki et al. "Charged-current exclusive pion production in neutrino-deuterium interactions" +// Physical Review D, Volume 34, Number 9, 1 Nov 1986 +// Figure 12 and related +// +// Also see +// N. J. Baker et al. "Study of the isospin structure of single-pion production in charged-current neutrino interactions" +// Physical Review D, Volume 23, Number 11, 1 June 1981 +// +// K. Furuno et al. NuInt02 proceedings, (supposedly published in Nucl. Phys. B but I never found it), Retreieved from KEK preprints. +// KEK Preprint 2003-48, RCNS-03-01, September 2003 class BNL_CC1ppip_Evt_1Dphi_nu : public Measurement1D { public: BNL_CC1ppip_Evt_1Dphi_nu(nuiskey samplekey); virtual ~BNL_CC1ppip_Evt_1Dphi_nu() {}; void FillEventVariables(FitEvent *event); bool isSignal(FitEvent *event); private: TRandom3 rand; }; #endif diff --git a/src/BNL/BNL_CC1ppip_XSec_1DEnu_nu.cxx b/src/BNL/BNL_CC1ppip_XSec_1DEnu_nu.cxx index e4a9675..cf78d78 100644 --- a/src/BNL/BNL_CC1ppip_XSec_1DEnu_nu.cxx +++ b/src/BNL/BNL_CC1ppip_XSec_1DEnu_nu.cxx @@ -1,117 +1,128 @@ // 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 "BNL_CC1ppip_XSec_1DEnu_nu.h" +// T. Kitagaki et al. "Charged-current exclusive pion production in neutrino-deuterium interactions" +// Physical Review D, Volume 34, Number 9, 1 Nov 1986 +// Figure 7 +// +// Also see +// N. J. Baker et al. "Study of the isospin structure of single-pion production in charged-current neutrino interactions" +// Physical Review D, Volume 23, Number 11, 1 June 1981 +// +// K. Furuno et al. NuInt02 proceedings, (supposedly published in Nucl. Phys. B but I never found it), Retreieved from KEK preprints. +// KEK Preprint 2003-48, RCNS-03-01, September 2003 + //******************************************************************** BNL_CC1ppip_XSec_1DEnu_nu::BNL_CC1ppip_XSec_1DEnu_nu(nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "BNL_CC1ppip_XSec_1DEnu_nu sample. \n" \ "Target: D2 \n" \ "Flux: \n" \ "Signal: \n"; // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); fSettings.SetXTitle("E_{#nu} (GeV)"); fSettings.SetYTitle("#sigma (cm^{2}/proton)"); fSettings.SetAllowedTypes("FIX/DIAG", "FIX,FREE,SHAPE/DIAG"); fSettings.SetEnuRange(0.0, 6.0); fSettings.SetS("norm_error", "0.15"); fSettings.DefineAllowedTargets("D,H"); // plot information fSettings.SetTitle("BNL_CC1ppip_XSec_1DEnu_nu"); fSettings.DefineAllowedSpecies("numu"); // User can specifiy to use uncorrected data UseCorrectedData = !fSettings.Found("name", "Uncorr"); // User can specify 1.4 or no W cut if (fSettings.Found("name", "W14Cut")) wTrueCut = 1.4; else wTrueCut = 10.0; // Now read in different data depending on what the user has specified std::string DataLocation = GeneralUtils::GetTopLevelDir() + "/data/BNL/CC1pip_on_p/"; // If we're using corrected data if (UseCorrectedData) { if (wTrueCut == 1.4) { DataLocation += "BNL_CC1pip_on_p_W14_1986_corr.txt"; fSettings.SetEnuRange(0.5, 3.0); } else { DataLocation += "BNL_CC1pip_on_p_1986_corr.txt"; fSettings.SetEnuRange(0.4, 4.0); } // If we're using raw uncorrected data } else { if (wTrueCut == 1.4) { DataLocation += "BNL_CC1pip_on_p_W14_1986.txt"; fSettings.SetEnuRange(0.6, 3.0); } else { DataLocation += "BNL_CC1pip_on_p_1986.txt"; fSettings.SetEnuRange(0.5, 14.0); } } fSettings.SetDataInput(DataLocation); FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/proton fScaleFactor = (GetEventHistogram()->Integral("width") * 1E-38) / ((fNEvents + 0.)) * 2. / 1.; // Plot Setup ------------------------------------------------------- SetDataFromTextFile( fSettings.GetDataInput() ); SetCovarFromDiagonal(); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; void BNL_CC1ppip_XSec_1DEnu_nu::FillEventVariables(FitEvent *event) { if (event->NumFSParticle(2212) == 0 || event->NumFSParticle(211) == 0 || event->NumFSParticle(13) == 0) return; TLorentzVector Pnu = event->GetNeutrinoIn()->fP; TLorentzVector Pp = event->GetHMFSParticle(2212)->fP; TLorentzVector Ppip = event->GetHMFSParticle(211)->fP; TLorentzVector Pmu = event->GetHMFSParticle(13)->fP; double hadMass = FitUtils::MpPi(Pp, Ppip); double Enu = -1.0; if (hadMass/1000. < wTrueCut) { Enu = Pnu.E() / 1000.; } fXVar = Enu; return; }; bool BNL_CC1ppip_XSec_1DEnu_nu::isSignal(FitEvent *event) { return SignalDef::isCC1pi3Prong(event, 14, 211, 2212, EnuMin, EnuMax); } diff --git a/src/BNL/BNL_CC1ppip_XSec_1DEnu_nu.h b/src/BNL/BNL_CC1ppip_XSec_1DEnu_nu.h index 61592da..a69c357 100644 --- a/src/BNL/BNL_CC1ppip_XSec_1DEnu_nu.h +++ b/src/BNL/BNL_CC1ppip_XSec_1DEnu_nu.h @@ -1,38 +1,48 @@ // 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 BNL_CC1PPIP_XSEC_1DENU_NU_H_SEEN #define BNL_CC1PPIP_XSEC_1DENU_NU_H_SEEN #include "Measurement1D.h" +// T. Kitagaki et al. "Charged-current exclusive pion production in neutrino-deuterium interactions" +// Physical Review D, Volume 34, Number 9, 1 Nov 1986 +// Figure 7 +// +// Also see +// N. J. Baker et al. "Study of the isospin structure of single-pion production in charged-current neutrino interactions" +// Physical Review D, Volume 23, Number 11, 1 June 1981 +// +// K. Furuno et al. NuInt02 proceedings, (supposedly published in Nucl. Phys. B but I never found it), Retreieved from KEK preprints. +// KEK Preprint 2003-48, RCNS-03-01, September 2003 class BNL_CC1ppip_XSec_1DEnu_nu : public Measurement1D { public: BNL_CC1ppip_XSec_1DEnu_nu(nuiskey samplekey); virtual ~BNL_CC1ppip_XSec_1DEnu_nu() {}; void FillEventVariables(FitEvent *event); bool isSignal(FitEvent *event); private: double wTrueCut; bool UseCorrectedData; }; #endif diff --git a/src/Config/NuisConfig.cxx b/src/Config/NuisConfig.cxx index 4a33b29..6bf56ef 100644 --- a/src/Config/NuisConfig.cxx +++ b/src/Config/NuisConfig.cxx @@ -1,817 +1,817 @@ // 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 "NuisConfig.h" #include "FitLogger.h" #include "GeneralUtils.h" #include "TXMLEngine.h" namespace Config { nuisconfig &Get() { return nuisconfig::GetConfig(); }; std::string GetPar(std::string const &name) { return Get().GetConfig(name); } bool HasPar(std::string const &name) { return Get().HasConfig(name); } std::string GetParS(std::string const &name) { return Get().GetConfigS(name); } int GetParI(std::string const &name) { return Get().GetConfigI(name); } bool GetParB(std::string const &name) { return Get().GetConfigB(name); } float GetParF(std::string const &name) { return Get().GetConfigF(name); } double GetParD(std::string const &name) { return Get().GetConfigD(name); } void SetPar(std::string const &name, std::string const &val) { Get().SetConfig(name, val); } void SetPar(std::string const &name, char const *val) { Get().SetConfig(name, val); } void SetPar(std::string const &name, bool val) { Get().SetConfig(name, val); } void SetPar(std::string const &name, int val) { Get().SetConfig(name, val); } void SetPar(std::string const &name, float val) { Get().SetConfig(name, val); } void SetPar(std::string const &name, double val) { Get().SetConfig(name, val); } } namespace FitPar { std::string GetDataBase() { return GeneralUtils::GetTopLevelDir() + "/data/"; }; nuisconfig &Config() { return Config::Get(); }; } nuisconfig *nuisconfig::m_nuisconfigInstance = NULL; nuisconfig &nuisconfig::GetConfig(void) { if (!m_nuisconfigInstance) m_nuisconfigInstance = new nuisconfig; return *m_nuisconfigInstance; }; // Main Class Definition nuisconfig::nuisconfig() { // Load default Parameters std::string filename = (GeneralUtils::GetTopLevelDir() + "/parameters/config.xml"); std::cout << "[ NUISANCE ]: Loading DEFAULT settings from : " << filename << std::endl; // Create XML Engine fXML = new TXMLEngine; fXML->SetSkipComments(true); // Load in documents fXMLDocs.push_back(fXML->ParseFile(filename.c_str(), 1000000)); if (!fXMLDocs[0]) { NUIS_ABORT("Cannot Read Parameters File!"); } // Setup Main XML Node to be the first file read fMainNode = fXML->DocGetRootElement(fXMLDocs[0]); // Print result std::cout << "[ NUISANCE ]: Finished nuisconfig." << std::endl; } nuisconfig::~nuisconfig() { // Should really delete XML objects here but we don't } void nuisconfig::LoadSettings(std::string const &filename, std::string const &state) { // Open file and see if its XML std::cout << "[ NUISANCE ]: Trying to parse file : " << filename; StopTalking(); XMLDocPointer_t readdoc = fXML->ParseFile(filename.c_str(), 1000000); StartTalking(); // If it is parse it as a nice XML config file if (readdoc) { std::cout << " -> Found XML file." << std::endl; LoadXMLSettings(filename, state); // Otherwise its an old simple card file } else { std::cout << " -> Assuming its a simple card file." << std::endl; LoadCardSettings(filename, state); } } void nuisconfig::LoadXMLSettings(std::string const &filename, std::string const &state) { std::cout << "[ NUISANCE ]: Loading XML settings from : " << filename << std::endl; // Add new file to xml docs list fXMLDocs.push_back(fXML->ParseFile(filename.c_str(), 1000000)); if (!fXMLDocs.back()) { NUIS_ABORT("Failed to read: " << filename); } // Loop over children and add XMLNodePointer_t child = fXML->GetChild(fXML->DocGetRootElement(fXMLDocs.back())); // // Here we manually load all the children from the card file into our root // node if (!child) { NUIS_ABORT("CANNOT Find child inside settings file!"); } while (child) { // SPECIAL CONFIG CASE // If its a config node, then remove previous attributes, overriding old // value if (!std::string(fXML->GetNodeName(child)).compare("config")) { // Loop over attribues XMLAttrPointer_t attr1 = fXML->GetFirstAttr(child); while (attr1) { // If a valid attribute name is given then compare if (!GetConfigS(fXML->GetAttrName(attr1)).empty()) { // Get full list of present configs std::vector confignodes = GetNodes("config"); // Loop over present configs and compare for (size_t i = 0; i < confignodes.size(); i++) { // If we already have this config, free the old attribute if (fXML->HasAttr(confignodes[i], fXML->GetAttrName(attr1))) { fXML->FreeAttr(confignodes[i], fXML->GetAttrName(attr1)); break; } } } // Move onto next config attribute attr1 = fXML->GetNextAttr(attr1); } } TString nodeStr; fXML->SaveSingleNode(child, &nodeStr); XMLNodePointer_t copyNode = fXML->ReadSingleNode(nodeStr.Data()); // std::cout << "copying node..." << std::endl; // PrintXML(copyNode); // Add this child to the main config list fXML->AddChild(fMainNode, copyNode); // std::cout << "Done, was it added?" << std::endl; // PrintXML(fMainNode); // Get Next Child child = fXML->GetNext(child); } std::cout << "[ NUISANCE ]: Finished loading XML settings" << std::endl; } void nuisconfig::LoadCardSettings(std::string const &filename, std::string const &state) { std::cout << "[ NUISANCE ]: Loading simple config from : " << filename << std::endl; // Build XML Config from the card file by parsing each line std::vector cardlines = GeneralUtils::ParseFileToStr(filename, "\n"); int linecount = 0; // Loop over all input lines for (std::vector::iterator iter = cardlines.begin(); iter != cardlines.end(); iter++) { std::string line = (*iter); linecount++; // Skip Comments if (line.empty()) continue; if (line.c_str()[0] == '#') continue; // Parse whitespace std::vector strvct = GeneralUtils::ParseToStr(line, " "); if (strvct.empty()) continue; // Get Identifier std::string id = strvct[0]; // Build backwards compatible xml configs // Sample structure if (!id.compare("sample")) { CreateSampleNodeFromLine(line); } // Any parameter structure if (id.find("_parameter") != std::string::npos) { CreateParameterNodeFromLine(line); } // Any covar structure if (!id.compare("covar") || !id.compare("pull") || !id.compare("throw")) { CreatePullNodeFromLine(line); } // Any config structure if (!id.compare("config")) { CreateOldConfigNodeFromLine(line); } } std::cout << "[ NUISANCE ]: Finished loading simple config" << std::endl; } XMLNodePointer_t nuisconfig::CreateSampleNodeFromLine(std::string const &line) { // Create new node entry XMLNodePointer_t samplenode = CreateNode("sample"); // Parse line std::vector strvct = GeneralUtils::ParseToStr(line, " "); // Add line elements to the node // name input type norm if (strvct.size() > 1) Set(samplenode, "name", strvct[1]); if (strvct.size() > 2) Set(samplenode, "input", strvct[2]); if (strvct.size() > 3) Set(samplenode, "type", strvct[3]); if (strvct.size() > 4) Set(samplenode, "norm", strvct[4]); return samplenode; } XMLNodePointer_t nuisconfig::CreateParameterNodeFromLine( std::string const &line) { // Create new node entry XMLNodePointer_t parnode = CreateNode("parameter"); // Parse line std::vector strvct = GeneralUtils::ParseToStr(line, " "); // Add line elements to the node // type name nominal [low] [high] [step] state if (strvct.size() > 0) Set(parnode, "type", strvct[0]); if (strvct.size() > 1) Set(parnode, "name", strvct[1]); if (strvct.size() > 2) Set(parnode, "nominal", strvct[2]); // If free structure if (strvct.size() == 7) { Set(parnode, "low", strvct[3]); Set(parnode, "high", strvct[4]); Set(parnode, "step", strvct[5]); Set(parnode, "state", strvct[6]); // Fixed param structure } else if (strvct.size() == 3) { Set(parnode, "state", "FIX"); } else if (strvct.size() == 4) { Set(parnode, "state", strvct[3]); } return parnode; } XMLNodePointer_t nuisconfig::CreatePullNodeFromLine(std::string const &line) { // Create new node entry XMLNodePointer_t parnode = CreateNode("covar"); // Parse line std::vector strvct = GeneralUtils::ParseToStr(line, " "); // Add line elements to the node // name input type if (strvct.size() > 1) Set(parnode, "name", strvct[1]); if (strvct.size() > 2) Set(parnode, "input", strvct[2]); if (strvct.size() > 3) Set(parnode, "type", strvct[3]); return parnode; } XMLNodePointer_t nuisconfig::CreateOldConfigNodeFromLine( std::string const &line) { // Create new node entry XMLNodePointer_t confignode = CreateNode("config"); // Parse line std::vector strvct = GeneralUtils::ParseToStr(line, " "); // Add line elements to the node // name value if (strvct.size() > 2) Set(confignode, strvct[1], strvct[2]); return confignode; } void nuisconfig::FinaliseSettings(std::string const &name) { std::cout << "[ NUISANCE ]: Finalising run settings" << std::endl; WriteSettings(name); // Save full config to file RemoveEmptyNodes(); RemoveIdenticalNodes(); std::cout << "[ NUISANCE ]: Finished finalising run settings" << std::endl; } void nuisconfig::WriteSettings(std::string const &outputname) { // Create a New XML Doc XMLDocPointer_t newxmldoc = fXML->NewDoc(); fXML->DocSetRootElement(newxmldoc, fMainNode); // Save document to file if (GetConfigB("SaveParsedXMLFile")) { fXML->SaveDoc(newxmldoc, outputname.c_str()); } } void nuisconfig::PrintXML(XMLNodePointer_t node, int indent) { if (!node) { node = fMainNode; } std::stringstream ss(""); for (int i = 0; i < indent; ++i) { ss << " "; } std::cout << ss.str() << "<" << fXML->GetNodeName(node) << std::flush; XMLAttrPointer_t attr = fXML->GetFirstAttr(node); while (attr) { std::cout << " " << fXML->GetAttrName(attr) << "=\"" << fXML->GetAttrValue(attr) << "\"" << std::flush; attr = fXML->GetNextAttr(attr); } if (!fXML->GetChild(node)) { std::cout << " />" << std::endl; return; } std::cout << " >" << std::endl; XMLNodePointer_t child = fXML->GetChild(node); while (child) { PrintXML(child, indent + 1); child = fXML->GetNext(child); } std::cout << ss.str() << "GetNodeName(node) << ">" << std::endl; } XMLNodePointer_t nuisconfig::CreateNode(std::string const &name) { return fXML->NewChild(fMainNode, 0, name.c_str()); } XMLNodePointer_t nuisconfig::CreateNode(XMLNodePointer_t node, std::string const &name) { return fXML->NewChild(node, 0, name.c_str()); } XMLNodePointer_t nuisconfig::GetNode(XMLNodePointer_t node, std::string const &type) { /// Loop over all children XMLNodePointer_t child = fXML->GetChild(node); while (child != 0) { /// Get nodes for given type (if type empty return all) if (std::string(fXML->GetNodeName(child)) == type.c_str() or type.empty()) { return child; } // Next child child = fXML->GetNext(child); } // Child not found return 0; } void nuisconfig::RemoveEmptyNodes() { std::vector nodelist = Config::Get().GetNodes(); for (size_t i = 0; i < nodelist.size(); i++) { if (fXML->IsEmptyNode(nodelist[i])) { std::cout << "Removing empty node: " << fXML->GetNodeName(nodelist[i]) << ", with child ?" << bool(fXML->GetChild(nodelist[i])) << std::endl; RemoveNode(nodelist[i]); } } } void nuisconfig::RemoveIdenticalNodes() { std::vector removed; // Loop over all nodes and check for identical nodes std::vector nodelist = Config::Get().GetNodes(); for (size_t i = 0; i < nodelist.size(); i++) { for (size_t j = 0; j < nodelist.size(); j++) { if (i == j) continue; XMLNodePointer_t node1 = nodelist[i]; XMLNodePointer_t node2 = nodelist[j]; // Check node already removed. if (std::find(removed.begin(), removed.end(), node1) != removed.end()) { continue; } if (std::find(removed.begin(), removed.end(), node2) != removed.end()) { continue; } // Check matching if (!MatchingNodes(node1, node2)) { continue; } if (std::string(fXML->GetNodeName(node1)).compare("config") and fXML->IsEmptyNode(node1)) { // Matching so print out warning std::cout << "Matching nodes given! Removing node1!" << std::endl << "Node 1" << std::endl; PrintNode(node1); std::cout << "Node 2" << std::endl; PrintNode(node2); } // Remove node removed.push_back(node1); } } // Now go through and remove this node. for (size_t i = 0; i < removed.size(); i++) { RemoveNode(removed.at(i)); } return; } void nuisconfig::RemoveNode(XMLNodePointer_t node) { - std::cout << "[INFO]: Removing node: " << fXML->GetNodeName(node) - << std::endl; + std::cout << "[ CONFIG ]: Removing node: "; + PrintNode(node); fXML->FreeAllAttr(node); fXML->CleanNode(node); fXML->FreeNode(node); fXML->UnlinkNode(node); } void nuisconfig::PrintNode(XMLNodePointer_t node) { // Print Node Name std::cout << fXML->GetNodeName(node) << std::endl; // Loop and print all attributes XMLAttrPointer_t attr = fXML->GetFirstAttr(node); while (attr != 0) { - std::cout << " -> " << fXML->GetAttrName(attr) << " : " + std::cout << "\t\t|-> " << fXML->GetAttrName(attr) << " : " << fXML->GetAttrValue(attr) << std::endl; attr = fXML->GetNextAttr(attr); } } bool nuisconfig::MatchingNodes(XMLNodePointer_t node1, XMLNodePointer_t node2) { bool matching = true; XMLAttrPointer_t attr = fXML->GetFirstAttr(node1); while (attr != 0) { if (GetS(node2, fXML->GetAttrName(attr)) != fXML->GetAttrValue(attr)) matching = false; attr = fXML->GetNextAttr(attr); } return matching; } XMLNodePointer_t nuisconfig::GetNode(std::string const &type) { return GetNode(fMainNode, type); } std::vector nuisconfig::GetNodes(XMLNodePointer_t node, std::string const &type) { // Create new vector for nodes std::vector nodelist; /// Loop over all children XMLNodePointer_t child = fXML->GetChild(node); while (child != 0) { /// Get nodes for given type (if type empty return all) if (std::string(fXML->GetNodeName(child)) == type.c_str() or type.empty()) { nodelist.push_back(child); } // Next child child = fXML->GetNext(child); } // return list return nodelist; } std::vector nuisconfig::GetNodes(std::string const &type) { return GetNodes(fMainNode, type); } void nuisconfig::Set(XMLNodePointer_t node, std::string const &name, std::string const &val) { // Remove and re-add attribute if (fXML->HasAttr(node, name.c_str())) { fXML->FreeAttr(node, name.c_str()); } fXML->NewAttr(node, 0, name.c_str(), val.c_str()); } void nuisconfig::Set(XMLNodePointer_t node, std::string const &name, char const *val) { Set(node, name, std::string(val)); } void nuisconfig::Set(XMLNodePointer_t node, std::string const &name, bool val) { Set(node, name, GeneralUtils::BoolToStr(val)); } void nuisconfig::Set(XMLNodePointer_t node, std::string const &name, int val) { Set(node, name, GeneralUtils::IntToStr(val)); } void nuisconfig::Set(XMLNodePointer_t node, std::string const &name, float val) { Set(node, name, GeneralUtils::DblToStr(val)); } void nuisconfig::Set(XMLNodePointer_t node, std::string const &name, double val) { Set(node, name, GeneralUtils::DblToStr(val)); } void nuisconfig::SetS(XMLNodePointer_t node, std::string const &name, std::string const &val) { Set(node, name, val); } void nuisconfig::SetB(XMLNodePointer_t node, std::string const &name, bool val) { Set(node, name, GeneralUtils::BoolToStr(val)); } void nuisconfig::SetI(XMLNodePointer_t node, std::string const &name, int val) { Set(node, name, GeneralUtils::IntToStr(val)); } void nuisconfig::SetF(XMLNodePointer_t node, std::string const &name, float val) { Set(node, name, GeneralUtils::DblToStr(val)); } void nuisconfig::SetD(XMLNodePointer_t node, std::string const &name, double val) { Set(node, name, GeneralUtils::DblToStr(val)); } bool nuisconfig::Has(XMLNodePointer_t node, std::string const &name) { // If node empty return empty if (node == 0) return false; // Search attributes XMLAttrPointer_t attr = fXML->GetFirstAttr(node); bool found = false; // Loop over all attributes while (attr != 0) { // Find value of correct name if (std::string(fXML->GetAttrName(attr)) == name.c_str()) { found = true; break; } // Next Attribute attr = fXML->GetNextAttr(attr); } return found; } std::string nuisconfig::Get(XMLNodePointer_t node, std::string const &name) { // If node empty return empty if (node == 0) return ""; // Get Attribute from child with name XMLAttrPointer_t attr = fXML->GetFirstAttr(node); std::string temp = ""; // Loop over all attributes while (attr != 0) { // If valid match then save if (std::string(fXML->GetAttrName(attr)) == name.c_str()) { temp = fXML->GetAttrValue(attr); } // Next Attribute attr = fXML->GetNextAttr(attr); } return temp; } std::string nuisconfig::GetS(XMLNodePointer_t node, std::string const &name) { return Get(node, name); } bool nuisconfig::GetB(XMLNodePointer_t node, std::string const &name) { std::string tempattr = Get(node, name); return GeneralUtils::StrToBool(tempattr); } int nuisconfig::GetI(XMLNodePointer_t node, std::string const &name) { std::string tempattr = Get(node, name); return GeneralUtils::StrToInt(tempattr); } float nuisconfig::GetF(XMLNodePointer_t node, std::string const &name) { std::string tempattr = Get(node, name); return GeneralUtils::StrToDbl(tempattr); } double nuisconfig::GetD(XMLNodePointer_t node, std::string const &name) { std::string tempattr = Get(node, name); return GeneralUtils::StrToDbl(tempattr); } std::vector nuisconfig::GetVS(XMLNodePointer_t node, std::string const &name, const char *del) { std::string tempattr = Get(node, name); return GeneralUtils::ParseToStr(tempattr, del); } // std::vector nuisconfig::GetVB(XMLNodePointer_t node, // std::string name, // const char* del) { // std::string tempattr = Get(node, name); // return GeneralUtils::ParseToBool(tempattr, del); // } std::vector nuisconfig::GetVI(XMLNodePointer_t node, std::string const &name, const char *del) { std::string tempattr = Get(node, name); return GeneralUtils::ParseToInt(tempattr, del); } // std::vector nuisconfig::GetVF(XMLNodePointer_t node, // std::string name, // const char* del) { // std::string tempattr = Get(node, name); // return GeneralUtils::ParseToDouble(tempattr, del); // } std::vector nuisconfig::GetVD(XMLNodePointer_t node, std::string const &name, char const *del) { std::string tempattr = Get(node, name); return GeneralUtils::ParseToDbl(tempattr, del); } std::vector nuisconfig::GetAllKeysForNode(XMLNodePointer_t node) { //bool matching = true; XMLAttrPointer_t attr = fXML->GetFirstAttr(node); std::vector keys; while (attr != 0) { if (!std::string(fXML->GetAttrName(attr)).empty()) { keys.push_back(std::string(fXML->GetAttrName(attr))); } attr = fXML->GetNextAttr(attr); } return keys; } XMLNodePointer_t nuisconfig::GetConfigNode(std::string const &name) { // Loop over children and look for name XMLNodePointer_t child = fXML->GetChild(fMainNode); while (child != 0) { // Select only config parameters if (!std::string(fXML->GetNodeName(child)).compare("config")) { // Loop over config attributes and search for name XMLAttrPointer_t attr = fXML->GetFirstAttr(child); while (attr != 0) { // Save name value if (std::string(fXML->GetAttrName(attr)) == name.c_str()) { return child; } // Get Next Attribute attr = fXML->GetNextAttr(attr); } } // Next Child child = fXML->GetNext(child); } return 0; } void nuisconfig::SetConfig(std::string const &name, std::string const &val) { XMLNodePointer_t node = GetConfigNode(name); if (!node) node = CreateNode("config"); Set(node, name, val); } void nuisconfig::SetConfig(std::string const &name, char const *val) { SetConfig(name, std::string(val)); } void nuisconfig::SetConfig(std::string const &name, bool val) { XMLNodePointer_t node = GetConfigNode(name); if (!node) node = CreateNode("config"); Set(node, name, val); } void nuisconfig::SetConfig(std::string const &name, int val) { XMLNodePointer_t node = GetConfigNode(name); if (!node) node = CreateNode("config"); Set(node, name, val); } void nuisconfig::SetConfig(std::string const &name, float val) { XMLNodePointer_t node = GetConfigNode(name); if (!node) node = CreateNode("config"); Set(node, name, val); } void nuisconfig::SetConfig(std::string const &name, double val) { XMLNodePointer_t node = GetConfigNode(name); if (!node) node = CreateNode("config"); Set(node, name, val); } void nuisconfig::OverrideConfig(std::string const &conf) { std::vector opts = GeneralUtils::ParseToStr(conf, "="); SetConfig(opts[0], opts[1]); } std::string nuisconfig::GetConfig(std::string const &name) { XMLNodePointer_t node = GetConfigNode(name); if (!node) return ""; XMLAttrPointer_t attr = fXML->GetFirstAttr(node); std::string temp = ""; // Loop config attributes while (attr != 0) { // Find match if (std::string(fXML->GetAttrName(attr)) == name.c_str()) { temp = fXML->GetAttrValue(attr); } // Get Next Attribute attr = fXML->GetNextAttr(attr); } return temp; } bool nuisconfig::HasConfig(std::string const &name) { return bool(GetConfigNode(name)); } std::string nuisconfig::GetConfigS(std::string const &name) { return GetConfig(name); } bool nuisconfig::GetConfigB(std::string const &name) { std::string pars = GetConfig(name); return GeneralUtils::StrToBool(pars); } int nuisconfig::GetConfigI(std::string const &name) { std::string pars = GetConfig(name); return GeneralUtils::StrToInt(pars); } float nuisconfig::GetConfigF(std::string const &name) { std::string pars = GetConfig(name); return GeneralUtils::StrToDbl(pars); } double nuisconfig::GetConfigD(std::string const &name) { std::string pars = GetConfig(name); return GeneralUtils::StrToDbl(pars); } std::string nuisconfig::GetParDIR(std::string const &parName) { std::string outstr = this->GetParS(parName); // Make replacements in the string const int nfiletypes = 2; const std::string filetypes[nfiletypes] = {"@data", "@nuisance"}; std::string filerepl[nfiletypes] = {FitPar::GetDataBase(), FitPar::GetDataBase() + "/../"}; for (int i = 0; i < nfiletypes; i++) { std::string findstring = filetypes[i]; std::string replstring = filerepl[i]; if (outstr.find(findstring) != std::string::npos) { outstr.replace(outstr.find(findstring), findstring.size(), filerepl[i]); break; } } return outstr; }; diff --git a/src/FCN/JointFCN.cxx b/src/FCN/JointFCN.cxx index 85ed5a1..b5ea56f 100755 --- a/src/FCN/JointFCN.cxx +++ b/src/FCN/JointFCN.cxx @@ -1,1154 +1,1157 @@ #include "JointFCN.h" #include "FitUtils.h" #include //*************************************************** JointFCN::JointFCN(TFile *outfile) { //*************************************************** fOutputDir = gDirectory; if (outfile) Config::Get().out = outfile; std::vector samplekeys = Config::QueryKeys("sample"); LoadSamples(samplekeys); std::vector covarkeys = Config::QueryKeys("covar"); LoadPulls(covarkeys); fCurIter = 0; fMCFilled = false; fIterationTree = false; fDialVals = NULL; fNDials = 0; fUsingEventManager = FitPar::Config().GetParB("EventManager"); fOutputDir->cd(); } //*************************************************** JointFCN::JointFCN(std::vector samplekeys, TFile *outfile) { //*************************************************** fOutputDir = gDirectory; if (outfile) Config::Get().out = outfile; LoadSamples(samplekeys); fCurIter = 0; fMCFilled = false; fOutputDir->cd(); fIterationTree = false; fDialVals = NULL; fNDials = 0; fUsingEventManager = FitPar::Config().GetParB("EventManager"); fOutputDir->cd(); } //*************************************************** JointFCN::~JointFCN() { //*************************************************** // Delete Samples for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end(); iter++) { MeasurementBase *exp = *iter; delete exp; } for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) { ParamPull *pull = *iter; delete pull; } // Sort Tree if (fIterationTree) DestroyIterationTree(); if (fDialVals) delete fDialVals; if (fSampleLikes) delete fSampleLikes; }; //*************************************************** void JointFCN::CreateIterationTree(std::string name, FitWeight *rw) { //*************************************************** NUIS_LOG(FIT, " Creating new iteration container! "); DestroyIterationTree(); fIterationTreeName = name; // Add sample likelihoods and ndof for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end(); iter++) { MeasurementBase *exp = *iter; std::string name = exp->GetName(); std::string liketag = name + "_likelihood"; fNameValues.push_back(liketag); fCurrentValues.push_back(0.0); std::string ndoftag = name + "_ndof"; fNameValues.push_back(ndoftag); fCurrentValues.push_back(0.0); } // Add Pull terms for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) { ParamPull *pull = *iter; std::string name = pull->GetName(); std::string liketag = name + "_likelihood"; fNameValues.push_back(liketag); fCurrentValues.push_back(0.0); std::string ndoftag = name + "_ndof"; fNameValues.push_back(ndoftag); fCurrentValues.push_back(0.0); } // Add Likelihoods fNameValues.push_back("total_likelihood"); fCurrentValues.push_back(0.0); fNameValues.push_back("total_ndof"); fCurrentValues.push_back(0.0); // Setup Containers fSampleN = fSamples.size() + fPulls.size(); fSampleLikes = new double[fSampleN]; fSampleNDOF = new int[fSampleN]; // Add Dials std::vector dials = rw->GetDialNames(); for (size_t i = 0; i < dials.size(); i++) { fNameValues.push_back(dials[i]); fCurrentValues.push_back(0.0); } fNDials = dials.size(); fDialVals = new double[fNDials]; // Set IterationTree Flag fIterationTree = true; } //*************************************************** void JointFCN::DestroyIterationTree() { //*************************************************** fIterationCount.clear(); fCurrentValues.clear(); fNameValues.clear(); fIterationValues.clear(); } //*************************************************** void JointFCN::WriteIterationTree() { //*************************************************** NUIS_LOG(FIT, "Writing iteration tree"); // Make a new TTree TTree *itree = new TTree(fIterationTreeName.c_str(), fIterationTreeName.c_str()); double *vals = new double[fNameValues.size()]; int count = 0; itree->Branch("iteration", &count, "Iteration/I"); for (size_t i = 0; i < fNameValues.size(); i++) { itree->Branch(fNameValues[i].c_str(), &vals[i], (fNameValues[i] + "/D").c_str()); } // Fill Iterations for (size_t i = 0; i < fIterationValues.size(); i++) { std::vector itervals = fIterationValues[i]; // Fill iteration state count = fIterationCount[i]; for (size_t j = 0; j < itervals.size(); j++) { vals[j] = itervals[j]; } // Save to TTree itree->Fill(); } // Write to file itree->Write(); } //*************************************************** void JointFCN::FillIterationTree(FitWeight *rw) { //*************************************************** // Loop over samples count int count = 0; for (int i = 0; i < fSampleN; i++) { fCurrentValues[count++] = fSampleLikes[i]; fCurrentValues[count++] = double(fSampleNDOF[i]); } // Fill Totals fCurrentValues[count++] = fLikelihood; fCurrentValues[count++] = double(fNDOF); // Loop Over Parameter Counts rw->GetAllDials(fDialVals, fNDials); for (int i = 0; i < fNDials; i++) { fCurrentValues[count++] = double(fDialVals[i]); } // Push Back Into Container fIterationCount.push_back(fCurIter); fIterationValues.push_back(fCurrentValues); } //*************************************************** double JointFCN::DoEval(const double *x) { //*************************************************** double *par_vals = new double[fNPars]; for (int i = 0; i < fNPars; ++i) { if (fMirroredParams.count(i)) { if (!fMirroredParams[i].mirror_above && (x[i] < fMirroredParams[i].mirror_value)) { double xabove = fMirroredParams[i].mirror_value - x[i]; par_vals[i] = fMirroredParams[i].mirror_value + xabove; std::cout << "\t--Parameter " << i << " mirrored from " << x[i] << " -> " << par_vals[i] << std::endl; } else if (fMirroredParams[i].mirror_above && (x[i] >= fMirroredParams[i].mirror_value)) { double xabove = x[i] - fMirroredParams[i].mirror_value; par_vals[i] = fMirroredParams[i].mirror_value - xabove; std::cout << "\t--Parameter " << i << " mirrored from " << x[i] << " -> " << par_vals[i] << std::endl; } else { par_vals[i] = x[i]; } } else { par_vals[i] = x[i]; } } // WEIGHT ENGINE fDialChanged = FitBase::GetRW()->HasRWDialChanged(par_vals); FitBase::GetRW()->UpdateWeightEngine(par_vals); if (fDialChanged) { FitBase::GetRW()->Reconfigure(); FitBase::EvtManager().ResetWeightFlags(); } if (LOG_LEVEL(REC)) { FitBase::GetRW()->Print(); } // SORT SAMPLES ReconfigureSamples(); // GET TEST STAT fLikelihood = GetLikelihood(); fNDOF = GetNDOF(); // PRINT PROGRESS NUIS_LOG(FIT, "Current Stat (iter. " << this->fCurIter << ") = " << fLikelihood); // UPDATE TREE if (fIterationTree) FillIterationTree(FitBase::GetRW()); delete[] par_vals; return fLikelihood; } //*************************************************** int JointFCN::GetNDOF() { //*************************************************** int totaldof = 0; int count = 0; // Total number of Free bins in each MC prediction for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end(); iter++) { MeasurementBase *exp = *iter; int dof = exp->GetNDOF(); - // Save Seperate DOF + // Save Separate DOF if (fIterationTree) { fSampleNDOF[count] = dof; } // Add to total totaldof += dof; count++; } // Loop over pulls for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) { ParamPull *pull = *iter; double dof = pull->GetLikelihood(); - // Save seperate DOF + // Save separate DOF if (fIterationTree) { fSampleNDOF[count] = dof; } // Add to total totaldof += dof; count++; } // Set Data Variable if (fIterationTree) { fSampleNDOF[count] = totaldof; } return totaldof; } //*************************************************** double JointFCN::GetLikelihood() { //*************************************************** NUIS_LOG(MIN, std::left << std::setw(43) << "Getting likelihoods..." << " : " << "-2logL"); // Loop and add up likelihoods in an uncorrelated way double like = 0.0; int count = 0; for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end(); iter++) { MeasurementBase *exp = *iter; double newlike = exp->GetLikelihood(); int ndof = exp->GetNDOF(); - // Save seperate likelihoods + // Save separate likelihoods if (fIterationTree) { fSampleLikes[count] = newlike; } NUIS_LOG(MIN, "-> " << std::left << std::setw(40) << exp->GetName() << " : " << newlike << "/" << ndof); // Add Weight Scaling // like *= FitBase::GetRW()->GetSampleLikelihoodWeight(exp->GetName()); // Add to total like += newlike; count++; } // Loop over pulls for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) { ParamPull *pull = *iter; double newlike = pull->GetLikelihood(); - // Save seperate likelihoods + // Save separate likelihoods if (fIterationTree) { fSampleLikes[count] = newlike; } // Add to total like += newlike; count++; } // Set Data Variable fLikelihood = like; if (fIterationTree) { fSampleLikes[count] = fLikelihood; } return like; }; void JointFCN::LoadSamples(std::vector samplekeys) { NUIS_LOG(MIN, "Loading Samples : " << samplekeys.size()); for (size_t i = 0; i < samplekeys.size(); i++) { nuiskey key = samplekeys[i]; // Get Sample Options std::string samplename = key.GetS("name"); std::string samplefile = key.GetS("input"); std::string sampletype = key.GetS("type"); std::string fakeData = ""; NUIS_LOG(MIN, "Loading Sample : " << samplename); fOutputDir->cd(); MeasurementBase *NewLoadedSample = SampleUtils::CreateSample(key); if (!NewLoadedSample) { NUIS_ERR(FTL, "Could not load sample provided: " << samplename); NUIS_ERR(FTL, "Check spelling with that in src/FCN/SampleList.cxx"); throw; } else { fSamples.push_back(NewLoadedSample); } } } //*************************************************** void JointFCN::LoadPulls(std::vector pullkeys) { //*************************************************** for (size_t i = 0; i < pullkeys.size(); i++) { nuiskey key = pullkeys[i]; std::string pullname = key.GetS("name"); std::string pullfile = key.GetS("input"); std::string pulltype = key.GetS("type"); fOutputDir->cd(); fPulls.push_back(new ParamPull(pullname, pullfile, pulltype)); } } //*************************************************** void JointFCN::ReconfigureSamples(bool fullconfig) { //*************************************************** int starttime = time(NULL); NUIS_LOG(REC, "Starting Reconfigure iter. " << this->fCurIter); // std::cout << fUsingEventManager << " " << fullconfig << " " << fMCFilled // << std::endl; Event Manager Reconf if (fUsingEventManager) { if (!fullconfig && fMCFilled) ReconfigureFastUsingManager(); else ReconfigureUsingManager(); } else { // Loop over all Measurement Classes for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end(); iter++) { MeasurementBase *exp = *iter; // If RW Either do signal or full reconfigure. if (fDialChanged or !fMCFilled or fullconfig) { if (!fullconfig and fMCFilled) exp->ReconfigureFast(); else exp->Reconfigure(); // If RW Not needed just do normalisation } else { exp->Renormalise(); } } } // Loop over pulls and update for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) { ParamPull *pull = *iter; pull->Reconfigure(); } fMCFilled = true; NUIS_LOG(MIN, "Finished Reconfigure iter. " << fCurIter << " in " << time(NULL) - starttime << "s"); fCurIter++; } //*************************************************** void JointFCN::ReconfigureSignal() { //*************************************************** ReconfigureSamples(false); } //*************************************************** void JointFCN::ReconfigureAllEvents() { //*************************************************** FitBase::GetRW()->Reconfigure(); FitBase::EvtManager().ResetWeightFlags(); ReconfigureSamples(true); } std::vector JointFCN::GetInputList() { std::vector InputList; fIsAllSplines = true; MeasListConstIter iterSam = fSamples.begin(); for (; iterSam != fSamples.end(); iterSam++) { MeasurementBase *exp = (*iterSam); std::vector subsamples = exp->GetSubSamples(); for (size_t i = 0; i < subsamples.size(); i++) { InputHandlerBase *inp = subsamples[i]->GetInput(); if (std::find(InputList.begin(), InputList.end(), inp) == InputList.end()) { if (subsamples[i]->GetInput()->GetType() != kSPLINEPARAMETER) fIsAllSplines = false; InputList.push_back(subsamples[i]->GetInput()); } } } return InputList; } std::vector JointFCN::GetSubSampleList() { std::vector SampleList; MeasListConstIter iterSam = fSamples.begin(); for (; iterSam != fSamples.end(); iterSam++) { MeasurementBase *exp = (*iterSam); std::vector subsamples = exp->GetSubSamples(); for (size_t i = 0; i < subsamples.size(); i++) { SampleList.push_back(subsamples[i]); } } return SampleList; } //*************************************************** void JointFCN::ReconfigureUsingManager() { //*************************************************** // 'Slow' Event Manager Reconfigure NUIS_LOG(REC, "Event Manager Reconfigure"); int timestart = time(NULL); // Reset all samples MeasListConstIter iterSam = fSamples.begin(); for (; iterSam != fSamples.end(); iterSam++) { MeasurementBase *exp = (*iterSam); exp->ResetAll(); } // If we are siving signal, reset all containers. bool savesignal = (FitPar::Config().GetParB("SignalReconfigures")); if (savesignal) { // Reset all of our event signal vectors fSignalEventBoxes.clear(); fSignalEventFlags.clear(); fSampleSignalFlags.clear(); fSignalEventSplines.clear(); } // Make sure we have a list of inputs if (fInputList.empty()) { fInputList = GetInputList(); fSubSampleList = GetSubSampleList(); } // If all inputs are splines make sure the readers are told // they need to be reconfigured. std::vector::iterator inp_iter = fInputList.begin(); if (fIsAllSplines) { for (; inp_iter != fInputList.end(); inp_iter++) { InputHandlerBase *curinput = (*inp_iter); // Tell reader in each BaseEvent it needs a Reconfigure next weight // calc. BaseFitEvt *curevent = curinput->FirstBaseEvent(); if (curevent->fSplineRead) { curevent->fSplineRead->SetNeedsReconfigure(true); } } } // MAIN INPUT LOOP ==================== int fillcount = 0; int inputcount = 0; inp_iter = fInputList.begin(); // Loop over each input in manager for (; inp_iter != fInputList.end(); inp_iter++) { InputHandlerBase *curinput = (*inp_iter); // Get event information FitEvent *curevent = curinput->FirstNuisanceEvent(); curinput->CreateCache(); int i = 0; int nevents = curinput->GetNEvents(); int countwidth = nevents / 10; + uint textwidth = strlen(Form("%i", nevents)); // Start event loop iterating until we get a NULL pointer. while (curevent) { // Get Event Weight // The reweighting weight curevent->RWWeight = FitBase::GetRW()->CalcWeight(curevent); // The Custom weight and reweight curevent->Weight = curevent->RWWeight * curevent->InputWeight * curevent->CustomWeight; if (LOGGING(REC)) { if (countwidth && (i % countwidth == 0)) { NUIS_LOG(REC, curinput->GetName() - << " : Processed " << i << " events. [M, W] = [" - << curevent->Mode << ", " << curevent->Weight - << "]"); + << " : Processed " << std::setw(textwidth) << i + << " events. [M, W] = [" << std::setw(3) + << curevent->Mode << ", " << std::setw(5) + << Form("%.3lf", curevent->Weight) << "]"); } } // Setup flag for if signal found in at least one sample bool foundsignal = false; // Create a new signal bitset for this event std::vector signalbitset(fSubSampleList.size()); // Create a new signal box vector for this event std::vector signalboxes; // Start measurement iterator size_t measitercount = 0; std::vector::iterator meas_iter = fSubSampleList.begin(); // Loop over all subsamples (sub in JointMeas) for (; meas_iter != fSubSampleList.end(); meas_iter++) { MeasurementBase *curmeas = (*meas_iter); // Compare input pointers, to current input, skip if not. // Pointer tells us if it matches without doing ID checks. if (curinput != curmeas->GetInput()) { if (savesignal) { // Set bit to 0 as definitely not signal signalbitset[measitercount] = 0; } // Count up what measurement we are on. measitercount++; // Skip sample as input not signal. continue; } // Fill events for matching inputs. MeasurementVariableBox *box = curmeas->FillVariableBox(curevent); bool signal = curmeas->isSignal(curevent); curmeas->SetSignal(signal); curmeas->FillHistograms(curevent->Weight); // If its Signal tally up fills if (signal) { fillcount++; } // If we are saving signal/splines fill the bitset if (savesignal) { signalbitset[measitercount] = signal; } // If signal save a clone of the event box for use later. if (savesignal and signal) { foundsignal = true; signalboxes.push_back(box->CloneSignalBox()); } // Keep track of Measurement we are on. measitercount++; } // Once we've filled the measurements, if saving signal // push back if any sample flagged this event as signal if (savesignal) { fSignalEventFlags.push_back(foundsignal); } // Save the vector of signal boxes for this event if (savesignal && foundsignal) { fSignalEventBoxes.push_back(signalboxes); fSampleSignalFlags.push_back(signalbitset); } // If all inputs are splines we can save the spline coefficients // for fast in memory reconfigures later. if (fIsAllSplines && savesignal && foundsignal) { // Make temp vector to push back with std::vector coeff; for (size_t l = 0; l < (UInt_t)curevent->fSplineRead->GetNPar(); l++) { coeff.push_back(curevent->fSplineCoeff[l]); } // Push back to signal event splines. Kept in sync with // fSignalEventBoxes size. // int splinecount = fSignalEventSplines.size(); fSignalEventSplines.push_back(coeff); // if (splinecount % 1000 == 0) { // std::cout << "Pushed Back Coeff " << splinecount << " : "; // for (size_t l = 0; l < fSignalEventSplines[splinecount].size(); // l++) // { // std::cout << " " << fSignalEventSplines[splinecount][l]; // } // std::cout << std::endl; // } } // Clean up vectors once done with this event signalboxes.clear(); signalbitset.clear(); // Iterate to the next event. curevent = curinput->NextNuisanceEvent(); i++; } // curinput->RemoveCache(); // Keep track of what input we are on. inputcount++; } // End of Event Loop =============================== // Now event loop is finished loop over all Measurements // Converting Binned events to XSec Distributions iterSam = fSamples.begin(); for (; iterSam != fSamples.end(); iterSam++) { MeasurementBase *exp = (*iterSam); exp->ConvertEventRates(); } // Print out statements on approximate memory usage for profiling. NUIS_LOG(REC, "Filled " << fillcount << " signal events."); if (savesignal) { int mem = ( // sizeof(fSignalEventBoxes) + // fSignalEventBoxes.size() * sizeof(fSignalEventBoxes.at(0)) + sizeof(MeasurementVariableBox1D) * fillcount) * 1E-6; NUIS_LOG(REC, " -> Saved " << fillcount << " signal boxes for faster access. (~" << mem << " MB)"); if (fIsAllSplines and !fSignalEventSplines.empty()) { int splmem = sizeof(float) * fSignalEventSplines.size() * fSignalEventSplines[0].size() * 1E-6; NUIS_LOG(REC, " -> Saved " << fillcount << " " << fSignalEventSplines.size() << " spline sets into memory. (~" << splmem << " MB)"); } } NUIS_LOG(REC, "Time taken ReconfigureUsingManager() : " << time(NULL) - timestart); // Check SignalReconfigures works for all samples if (savesignal) { double likefull = GetLikelihood(); ReconfigureFastUsingManager(); double likefast = GetLikelihood(); if (fabs(likefull - likefast) > 0.0001) { NUIS_ERR(FTL, "Fast and Full Likelihoods DIFFER! : " << likefull << " : " << likefast); NUIS_ERR(FTL, "This means some samples you are using are not setup to use " "SignalReconfigures=1"); NUIS_ERR(FTL, "Please turn OFF signal reconfigures."); throw; } else { NUIS_LOG(FIT, "Likelihoods for FULL and FAST match. Will use FAST next time."); } } }; //*************************************************** void JointFCN::ReconfigureFastUsingManager() { //*************************************************** NUIS_LOG(FIT, " -> Doing FAST using manager"); // Get Start time for profilling int timestart = time(NULL); // Reset all samples MeasListConstIter iterSam = fSamples.begin(); for (; iterSam != fSamples.end(); iterSam++) { MeasurementBase *exp = (*iterSam); exp->ResetAll(); } // Check for saved variables if not do a full reconfigure. if (fSignalEventFlags.empty()) { NUIS_ERR(WRN, "Signal Flags Empty! Using normal manager."); ReconfigureUsingManager(); return; } bool fFillNuisanceEvent = FitPar::Config().GetParB("FullEventOnSignalReconfigure"); // Setup fast vector iterators. std::vector::iterator inpsig_iter = fSignalEventFlags.begin(); std::vector >::iterator box_iter = fSignalEventBoxes.begin(); std::vector >::iterator spline_iter = fSignalEventSplines.begin(); std::vector >::iterator samsig_iter = fSampleSignalFlags.begin(); int splinecount = 0; // Setup stuff for logging int fillcount = 0; // This is just the total number of events // int nevents = fSignalEventFlags.size(); // This is the number of events that are signal int nevents = fSignalEventBoxes.size(); int countwidth = nevents / 10; // If All Splines tell splines they need a reconfigure. std::vector::iterator inp_iter = fInputList.begin(); if (fIsAllSplines) { NUIS_LOG(REC, "All Spline Inputs so using fast spline loop."); for (; inp_iter != fInputList.end(); inp_iter++) { InputHandlerBase *curinput = (*inp_iter); // Tell each fSplineRead in BaseFitEvent to reconf next weight calc BaseFitEvt *curevent = curinput->FirstBaseEvent(); if (curevent->fSplineRead) curevent->fSplineRead->SetNeedsReconfigure(true); } } // Loop over all possible spline inputs double *coreeventweights = new double[fSignalEventBoxes.size()]; splinecount = 0; inp_iter = fInputList.begin(); inpsig_iter = fSignalEventFlags.begin(); spline_iter = fSignalEventSplines.begin(); // Loop over all signal flags // For each valid signal flag add one to splinecount // Get Splines from that count and add to weight // Add splinecount int sigcount = 0; // #pragma omp parallel for shared(splinecount,sigcount) for (uint iinput = 0; iinput < fInputList.size(); iinput++) { InputHandlerBase *curinput = fInputList[iinput]; BaseFitEvt *curevent = curinput->FirstBaseEvent(); // Loop over the events in each input for (int i = 0; i < curinput->GetNEvents(); i++) { double rwweight = 0.0; // If the event is a signal event if (fSignalEventFlags[sigcount]) { // Get Event Info if (!fIsAllSplines) { if (fFillNuisanceEvent) { curevent = curinput->GetNuisanceEvent(i); } else { curevent = curinput->GetBaseEvent(i); } } else { curevent->fSplineCoeff = &fSignalEventSplines[splinecount][0]; } curevent->RWWeight = FitBase::GetRW()->CalcWeight(curevent); curevent->Weight = curevent->RWWeight * curevent->InputWeight * curevent->CustomWeight; rwweight = curevent->Weight; coreeventweights[splinecount] = rwweight; if (countwidth && ((splinecount % countwidth) == 0)) { NUIS_LOG(REC, curinput->GetName() << " : Processed " << i << " events. W = " << curevent->Weight << std::endl); } // #pragma omp atomic splinecount++; } // #pragma omp atomic sigcount++; } } NUIS_LOG(SAM, "Processed event weights."); // #pragma omp barrier // Reset Iterators inpsig_iter = fSignalEventFlags.begin(); spline_iter = fSignalEventSplines.begin(); box_iter = fSignalEventBoxes.begin(); samsig_iter = fSampleSignalFlags.begin(); int nsplineweights = splinecount; splinecount = 0; // Start of Fast Event Loop ============================ // Start input iterators // Loop over number of inputs for (int ispline = 0; ispline < nsplineweights; ispline++) { double rwweight = coreeventweights[ispline]; // Get iterators for this event std::vector::iterator subsamsig_iter = (*samsig_iter).begin(); std::vector::iterator subbox_iter = (*box_iter).begin(); // Loop over all sub measurements. std::vector::iterator meas_iter = fSubSampleList.begin(); for (; meas_iter != fSubSampleList.end(); meas_iter++, subsamsig_iter++) { MeasurementBase *curmeas = (*meas_iter); // If event flagged as signal for this sample fill from the box. if (*subsamsig_iter) { curmeas->SetSignal(true); curmeas->FillHistogramsFromBox((*subbox_iter), rwweight); // Move onto next box if there is one. subbox_iter++; fillcount++; } } if (ispline % countwidth == 0) { NUIS_LOG(REC, "Filled " << ispline << " sample weights."); } // Iterate over the main signal event containers. samsig_iter++; box_iter++; spline_iter++; splinecount++; } // End of Fast Event Loop =================== NUIS_LOG(SAM, "Filled sample distributions."); // Now loop over all Measurements // Convert Binned events iterSam = fSamples.begin(); for (; iterSam != fSamples.end(); iterSam++) { MeasurementBase *exp = (*iterSam); exp->ConvertEventRates(); } // Cleanup coreeventweights delete coreeventweights; // Print some reconfigure profiling. NUIS_LOG(REC, "Filled " << fillcount << " signal events."); NUIS_LOG(REC, "Time taken ReconfigureFastUsingManager() : " << time(NULL) - timestart); } //*************************************************** void JointFCN::Write() { //*************************************************** // Save a likelihood/ndof plot NUIS_LOG(MIN, "Writing likelihood plot..."); std::vector likes; std::vector ndofs; std::vector names; for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end(); iter++) { MeasurementBase *exp = *iter; double like = exp->GetLikelihood(); double ndof = exp->GetNDOF(); std::string name = exp->GetName(); likes.push_back(like); ndofs.push_back(ndof); names.push_back(name); } if (likes.size()) { - TH1D likehist = TH1D("likelihood_hist", "likelihood_hist", likes.size(), - 0.0, double(likes.size())); - TH1D ndofhist = - TH1D("ndof_hist", "ndof_hist", ndofs.size(), 0.0, double(ndofs.size())); - TH1D divhist = TH1D("likedivndof_hist", "likedivndof_hist", likes.size(), - 0.0, double(likes.size())); + TH1D likehist = TH1D("likelihood_hist", "likelihood_hist;Sample;#chi^{2}", + likes.size(), 0.0, double(likes.size())); + TH1D ndofhist = TH1D("ndof_hist", "ndof_hist;Sample;NDOF", ndofs.size(), + 0.0, double(ndofs.size())); + TH1D divhist = + TH1D("likedivndof_hist", "likedivndof_hist;Sample;#chi^{2}/NDOF", + likes.size(), 0.0, double(likes.size())); for (int i = 0; i < likehist.GetNbinsX(); i++) { likehist.SetBinContent(i + 1, likes[i]); ndofhist.SetBinContent(i + 1, ndofs[i]); if (ndofs[i] != 0.0) { divhist.SetBinContent(i + 1, likes[i] / ndofs[i]); } likehist.GetXaxis()->SetBinLabel(i + 1, names[i].c_str()); ndofhist.GetXaxis()->SetBinLabel(i + 1, names[i].c_str()); divhist.GetXaxis()->SetBinLabel(i + 1, names[i].c_str()); } likehist.Write(); ndofhist.Write(); divhist.Write(); } // Loop over individual experiments and call Write NUIS_LOG(MIN, "Writing each of the data classes..."); for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end(); iter++) { MeasurementBase *exp = *iter; exp->Write(); } // Save Pull Terms for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) { ParamPull *pull = *iter; pull->Write(); } if (FitPar::Config().GetParB("EventManager")) { // Get list of inputs std::map fInputs = FitBase::EvtManager().GetInputs(); std::map::const_iterator iterInp; for (iterInp = fInputs.begin(); iterInp != fInputs.end(); iterInp++) { InputHandlerBase *input = (iterInp->second); input->GetFluxHistogram()->Write(); input->GetXSecHistogram()->Write(); input->GetEventHistogram()->Write(); } } }; //*************************************************** void JointFCN::SetFakeData(std::string fakeinput) { //*************************************************** NUIS_LOG(MIN, "Setting fake data from " << fakeinput); for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end(); iter++) { MeasurementBase *exp = *iter; exp->SetFakeDataValues(fakeinput); } return; } //*************************************************** void JointFCN::ThrowDataToy() { //*************************************************** for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end(); iter++) { MeasurementBase *exp = *iter; exp->ThrowDataToy(); } return; } //*************************************************** std::vector JointFCN::GetAllNames() { //*************************************************** // Vect of all likelihoods and total std::vector namevect; // Loop over samples first for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end(); iter++) { MeasurementBase *exp = *iter; // Get Likelihoods and push to vector namevect.push_back(exp->GetName()); } // Loop over pulls second for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) { ParamPull *pull = *iter; // Push back to vector namevect.push_back(pull->GetName()); } // Finally add the total namevect.push_back("total"); return namevect; } //*************************************************** std::vector JointFCN::GetAllLikelihoods() { //*************************************************** // Vect of all likelihoods and total std::vector likevect; double total_likelihood = 0.0; NUIS_LOG(MIN, "Likelihoods : "); // Loop over samples first for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end(); iter++) { MeasurementBase *exp = *iter; // Get Likelihoods and push to vector double singlelike = exp->GetLikelihood(); likevect.push_back(singlelike); total_likelihood += singlelike; // Print Out NUIS_LOG(MIN, "-> " << std::left << std::setw(40) << exp->GetName() << " : " << singlelike); } // Loop over pulls second for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) { ParamPull *pull = *iter; // Push back to vector double singlelike = pull->GetLikelihood(); likevect.push_back(singlelike); total_likelihood += singlelike; // Print Out NUIS_LOG(MIN, "-> " << std::left << std::setw(40) << pull->GetName() << " : " << singlelike); } // Finally add the total likelihood likevect.push_back(total_likelihood); return likevect; } //*************************************************** std::vector JointFCN::GetAllNDOF() { //*************************************************** // Vect of all ndof and total std::vector ndofvect; int total_ndof = 0; // Loop over samples first for (MeasListConstIter iter = fSamples.begin(); iter != fSamples.end(); iter++) { MeasurementBase *exp = *iter; // Get Likelihoods and push to vector int singlendof = exp->GetNDOF(); ndofvect.push_back(singlendof); total_ndof += singlendof; } // Loop over pulls second for (PullListConstIter iter = fPulls.begin(); iter != fPulls.end(); iter++) { ParamPull *pull = *iter; // Push back to vector int singlendof = pull->GetNDOF(); ndofvect.push_back(singlendof); total_ndof += singlendof; } // Finally add the total ndof ndofvect.push_back(total_ndof); return ndofvect; } diff --git a/src/FCN/SampleList.cxx b/src/FCN/SampleList.cxx index b3865ac..4bf7adc 100644 --- a/src/FCN/SampleList.cxx +++ b/src/FCN/SampleList.cxx @@ -1,1477 +1,1477 @@ #include "SampleList.h" #ifndef __NO_ANL__ #include "ANL_CCQE_Evt_1DQ2_nu.h" #include "ANL_CCQE_XSec_1DEnu_nu.h" // ANL CC1ppip #include "ANL_CC1ppip_Evt_1DQ2_nu.h" #include "ANL_CC1ppip_Evt_1DcosmuStar_nu.h" #include "ANL_CC1ppip_Evt_1DcosthAdler_nu.h" #include "ANL_CC1ppip_Evt_1Dphi_nu.h" #include "ANL_CC1ppip_Evt_1Dppi_nu.h" #include "ANL_CC1ppip_Evt_1Dthpr_nu.h" #include "ANL_CC1ppip_XSec_1DEnu_nu.h" #include "ANL_CC1ppip_XSec_1DQ2_nu.h" // ANL CC1npip #include "ANL_CC1npip_Evt_1DQ2_nu.h" #include "ANL_CC1npip_Evt_1DcosmuStar_nu.h" #include "ANL_CC1npip_Evt_1Dppi_nu.h" #include "ANL_CC1npip_XSec_1DEnu_nu.h" // ANL CC1pi0 #include "ANL_CC1pi0_Evt_1DQ2_nu.h" #include "ANL_CC1pi0_Evt_1DcosmuStar_nu.h" #include "ANL_CC1pi0_XSec_1DEnu_nu.h" // ANL NC1npip (mm, exotic!) #include "ANL_NC1npip_Evt_1Dppi_nu.h" // ANL NC1ppim (mm, exotic!) #include "ANL_NC1ppim_Evt_1DcosmuStar_nu.h" #include "ANL_NC1ppim_XSec_1DEnu_nu.h" // ANL CC2pi 1pim1pip (mm, even more exotic!) #include "ANL_CC2pi_1pim1pip_Evt_1Dpmu_nu.h" #include "ANL_CC2pi_1pim1pip_Evt_1Dppim_nu.h" #include "ANL_CC2pi_1pim1pip_Evt_1Dppip_nu.h" #include "ANL_CC2pi_1pim1pip_Evt_1Dpprot_nu.h" #include "ANL_CC2pi_1pim1pip_XSec_1DEnu_nu.h" // ANL CC2pi 1pip1pip (mm, even more exotic!) #include "ANL_CC2pi_1pip1pip_Evt_1Dpmu_nu.h" #include "ANL_CC2pi_1pip1pip_Evt_1Dpneut_nu.h" #include "ANL_CC2pi_1pip1pip_Evt_1DppipHigh_nu.h" #include "ANL_CC2pi_1pip1pip_Evt_1DppipLow_nu.h" #include "ANL_CC2pi_1pip1pip_XSec_1DEnu_nu.h" // ANL CC2pi 1pip1pi0 (mm, even more exotic!) #include "ANL_CC2pi_1pip1pi0_Evt_1Dpmu_nu.h" #include "ANL_CC2pi_1pip1pi0_Evt_1Dppi0_nu.h" #include "ANL_CC2pi_1pip1pi0_Evt_1Dppip_nu.h" #include "ANL_CC2pi_1pip1pi0_Evt_1Dpprot_nu.h" #include "ANL_CC2pi_1pip1pi0_XSec_1DEnu_nu.h" #endif #ifndef __NO_ArgoNeuT__ // ArgoNeuT CC1Pi #include "ArgoNeuT_CC1Pi_XSec_1Dpmu_antinu.h" #include "ArgoNeuT_CC1Pi_XSec_1Dpmu_nu.h" #include "ArgoNeuT_CC1Pi_XSec_1Dthetamu_antinu.h" #include "ArgoNeuT_CC1Pi_XSec_1Dthetamu_nu.h" #include "ArgoNeuT_CC1Pi_XSec_1Dthetamupi_antinu.h" #include "ArgoNeuT_CC1Pi_XSec_1Dthetamupi_nu.h" #include "ArgoNeuT_CC1Pi_XSec_1Dthetapi_antinu.h" #include "ArgoNeuT_CC1Pi_XSec_1Dthetapi_nu.h" // ArgoNeuT CC-inclusive #include "ArgoNeuT_CCInc_XSec_1Dpmu_antinu.h" #include "ArgoNeuT_CCInc_XSec_1Dpmu_nu.h" #include "ArgoNeuT_CCInc_XSec_1Dthetamu_antinu.h" #include "ArgoNeuT_CCInc_XSec_1Dthetamu_nu.h" #endif #ifndef __NO_BNL__ // BNL CCQE #include "BNL_CCQE_Evt_1DQ2_nu.h" #include "BNL_CCQE_XSec_1DEnu_nu.h" // BNL CC1ppip #include "BNL_CC1ppip_Evt_1DQ2_nu.h" #include "BNL_CC1ppip_Evt_1DcosthAdler_nu.h" #include "BNL_CC1ppip_Evt_1Dphi_nu.h" #include "BNL_CC1ppip_XSec_1DEnu_nu.h" // BNL CC1npip #include "BNL_CC1npip_Evt_1DQ2_nu.h" #include "BNL_CC1npip_XSec_1DEnu_nu.h" // BNL CC1pi0 #include "BNL_CC1pi0_Evt_1DQ2_nu.h" #include "BNL_CC1pi0_XSec_1DEnu_nu.h" #endif #ifndef __NO_FNAL__ // FNAL CCQE #include "FNAL_CCQE_Evt_1DQ2_nu.h" // FNAL CC1ppip #include "FNAL_CC1ppip_Evt_1DQ2_nu.h" #include "FNAL_CC1ppip_XSec_1DEnu_nu.h" #include "FNAL_CC1ppip_XSec_1DQ2_nu.h" // FNAL CC1ppim #include "FNAL_CC1ppim_XSec_1DEnu_antinu.h" #endif #ifndef __NO_BEBC__ // BEBC CCQE #include "BEBC_CCQE_XSec_1DQ2_nu.h" // BEBC CC1ppip #include "BEBC_CC1ppip_XSec_1DEnu_nu.h" #include "BEBC_CC1ppip_XSec_1DQ2_nu.h" // BEBC CC1npip #include "BEBC_CC1npip_XSec_1DEnu_nu.h" #include "BEBC_CC1npip_XSec_1DQ2_nu.h" // BEBC CC1pi0 #include "BEBC_CC1pi0_XSec_1DEnu_nu.h" #include "BEBC_CC1pi0_XSec_1DQ2_nu.h" // BEBC CC1npim #include "BEBC_CC1npim_XSec_1DEnu_antinu.h" #include "BEBC_CC1npim_XSec_1DQ2_antinu.h" // BEBC CC1ppim #include "BEBC_CC1ppim_XSec_1DEnu_antinu.h" #include "BEBC_CC1ppim_XSec_1DQ2_antinu.h" #endif #ifndef __NO_GGM__ // GGM CC1ppip #include "GGM_CC1ppip_Evt_1DQ2_nu.h" #include "GGM_CC1ppip_XSec_1DEnu_nu.h" #endif #ifndef __NO_MiniBooNE__ // MiniBooNE CCQE #include "MiniBooNE_CCQE_XSec_1DEnu_nu.h" #include "MiniBooNE_CCQE_XSec_1DQ2_antinu.h" #include "MiniBooNE_CCQE_XSec_1DQ2_nu.h" #include "MiniBooNE_CCQE_XSec_2DTcos_antinu.h" #include "MiniBooNE_CCQE_XSec_2DTcos_nu.h" // MiniBooNE CC1pi+ 1D #include "MiniBooNE_CC1pip_XSec_1DEnu_nu.h" #include "MiniBooNE_CC1pip_XSec_1DQ2_nu.h" #include "MiniBooNE_CC1pip_XSec_1DTpi_nu.h" #include "MiniBooNE_CC1pip_XSec_1DTu_nu.h" // MiniBooNE CC1pi+ 2D #include "MiniBooNE_CC1pip_XSec_2DQ2Enu_nu.h" #include "MiniBooNE_CC1pip_XSec_2DTpiCospi_nu.h" #include "MiniBooNE_CC1pip_XSec_2DTpiEnu_nu.h" #include "MiniBooNE_CC1pip_XSec_2DTuCosmu_nu.h" #include "MiniBooNE_CC1pip_XSec_2DTuEnu_nu.h" // MiniBooNE CC1pi0 #include "MiniBooNE_CC1pi0_XSec_1DEnu_nu.h" #include "MiniBooNE_CC1pi0_XSec_1DQ2_nu.h" #include "MiniBooNE_CC1pi0_XSec_1DTu_nu.h" #include "MiniBooNE_CC1pi0_XSec_1Dcosmu_nu.h" #include "MiniBooNE_CC1pi0_XSec_1Dcospi0_nu.h" #include "MiniBooNE_CC1pi0_XSec_1Dppi0_nu.h" #include "MiniBooNE_NC1pi0_XSec_1Dcospi0_antinu.h" #include "MiniBooNE_NC1pi0_XSec_1Dcospi0_nu.h" #include "MiniBooNE_NC1pi0_XSec_1Dppi0_antinu.h" #include "MiniBooNE_NC1pi0_XSec_1Dppi0_nu.h" // MiniBooNE NC1pi0 //#include "MiniBooNE_NCpi0_XSec_1Dppi0_nu.h" // MiniBooNE NCEL #include "MiniBooNE_NCEL_XSec_Treco_nu.h" #endif #ifndef __NO_MicroBooNE__ #include "MicroBooNE_CCInc_XSec_2DPcos_nu.h" #endif #ifndef __NO_MINERvA__ // MINERvA CCQE #include "MINERvA_CCQE_XSec_1DQ2_antinu.h" #include "MINERvA_CCQE_XSec_1DQ2_joint.h" #include "MINERvA_CCQE_XSec_1DQ2_nu.h" // MINERvA CC0pi #include "MINERvA_CC0pi_XSec_1DEe_nue.h" #include "MINERvA_CC0pi_XSec_1DQ2_nu_proton.h" #include "MINERvA_CC0pi_XSec_1DQ2_nue.h" #include "MINERvA_CC0pi_XSec_1DThetae_nue.h" // 2018 MINERvA CC0pi STV #include "MINERvA_CC0pinp_STV_XSec_1D_nu.h" // 2018 MINERvA CC0pi 2D #include "MINERvA_CC0pi_XSec_1D_2018_nu.h" #include "MINERvA_CC0pi_XSec_2D_nu.h" // #include "MINERvA_CC0pi_XSec_3DptpzTp_nu.h" // 2018 MINERvA CC0pi 2D antinu #include "MINERvA_CC0pi_XSec_2D_antinu.h" // MINERvA CC1pi+ #include "MINERvA_CC1pip_XSec_1DTpi_20deg_nu.h" #include "MINERvA_CC1pip_XSec_1DTpi_nu.h" #include "MINERvA_CC1pip_XSec_1Dth_20deg_nu.h" #include "MINERvA_CC1pip_XSec_1Dth_nu.h" // 2017 data update #include "MINERvA_CC1pip_XSec_1D_2017Update.h" // MINERvA CCNpi+ #include "MINERvA_CCNpip_XSec_1DEnu_nu.h" #include "MINERvA_CCNpip_XSec_1DQ2_nu.h" #include "MINERvA_CCNpip_XSec_1DTpi_nu.h" #include "MINERvA_CCNpip_XSec_1Dpmu_nu.h" #include "MINERvA_CCNpip_XSec_1Dth_nu.h" #include "MINERvA_CCNpip_XSec_1Dthmu_nu.h" // MINERvA CC1pi0 #include "MINERvA_CC1pi0_XSec_1DEnu_antinu.h" #include "MINERvA_CC1pi0_XSec_1DQ2_antinu.h" #include "MINERvA_CC1pi0_XSec_1DTpi0_antinu.h" #include "MINERvA_CC1pi0_XSec_1Dpmu_antinu.h" #include "MINERvA_CC1pi0_XSec_1Dppi0_antinu.h" #include "MINERvA_CC1pi0_XSec_1Dth_antinu.h" #include "MINERvA_CC1pi0_XSec_1Dthmu_antinu.h" // MINERvA CC1pi0 neutrino #include "MINERvA_CC1pi0_XSec_1D_nu.h" // MINERvA CCINC #include "MINERvA_CCinc_XSec_1DEnu_ratio.h" #include "MINERvA_CCinc_XSec_1Dx_ratio.h" #include "MINERvA_CCinc_XSec_2DEavq3_nu.h" // MINERvA CCDIS #include "MINERvA_CCDIS_XSec_1DEnu_ratio.h" #include "MINERvA_CCDIS_XSec_1Dx_ratio.h" // MINERvA CCCOH pion #include "MINERvA_CCCOHPI_XSec_1DEnu_antinu.h" #include "MINERvA_CCCOHPI_XSec_1DEpi_antinu.h" #include "MINERvA_CCCOHPI_XSec_1DQ2_antinu.h" #include "MINERvA_CCCOHPI_XSec_1DEpi_nu.h" #include "MINERvA_CCCOHPI_XSec_1DQ2_nu.h" #include "MINERvA_CCCOHPI_XSec_1Dth_nu.h" #include "MINERvA_CCCOHPI_XSec_joint.h" #include "MINERvA_CC0pi_XSec_1DQ2_TgtRatio_nu.h" #include "MINERvA_CC0pi_XSec_1DQ2_Tgt_nu.h" #endif #ifndef __NO_T2K__ // T2K CC0pi 2016 #include "T2K_CC0pi_XSec_2DPcos_nu_I.h" #include "T2K_CC0pi_XSec_2DPcos_nu_II.h" // T2K CC0pi 2020 arXiv:1908.10249 #include "T2K_CC0pi_XSec_H2O_2DPcos_anu.h" // T2K CC0pi 2020 arXiv:2004.05434 #include "T2K_NuMu_CC0pi_OC_XSec_2DPcos.h" #include "T2K_NuMu_CC0pi_OC_XSec_2DPcos_joint.h" // T2K CC0pi 2020 arXiv:2002.09323 #include "T2K_NuMuAntiNuMu_CC0pi_CH_XSec_2DPcos.h" #include "T2K_NuMuAntiNuMu_CC0pi_CH_XSec_2DPcos_joint.h" // T2K CC-inclusive with full acceptance 2018 #include "T2K_CCinc_XSec_2DPcos_nu_nonuniform.h" // T2K nue CC-inclusive 2019 #include "T2K_nueCCinc_XSec_1Dpe.h" #include "T2K_nueCCinc_XSec_1Dthe.h" #include "T2K_nueCCinc_XSec_1Dpe_joint.h" #include "T2K_nueCCinc_XSec_1Dthe_joint.h" #include "T2K_nueCCinc_XSec_joint.h" // T2K STV CC0pi 2018 #include "T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np.h" #include "T2K_CC0pinp_STV_XSec_1Ddat_nu.h" #include "T2K_CC0pinp_STV_XSec_1Ddphit_nu.h" #include "T2K_CC0pinp_STV_XSec_1Ddpt_nu.h" #include "T2K_CC0pinp_ifk_XSec_3Dinfa_nu.h" #include "T2K_CC0pinp_ifk_XSec_3Dinfip_nu.h" #include "T2K_CC0pinp_ifk_XSec_3Dinfp_nu.h" // T2K CC1pi+ on CH #include "T2K_CC1pip_CH_XSec_1DAdlerPhi_nu.h" #include "T2K_CC1pip_CH_XSec_1DCosThAdler_nu.h" #include "T2K_CC1pip_CH_XSec_1DQ2_nu.h" #include "T2K_CC1pip_CH_XSec_1Dppi_nu.h" #include "T2K_CC1pip_CH_XSec_1Dthmupi_nu.h" #include "T2K_CC1pip_CH_XSec_1Dthpi_nu.h" #include "T2K_CC1pip_CH_XSec_2Dpmucosmu_nu.h" // T2K CC1pi+ on H2O #include "T2K_CC1pip_H2O_XSec_1DEnuDelta_nu.h" #include "T2K_CC1pip_H2O_XSec_1DEnuMB_nu.h" #include "T2K_CC1pip_H2O_XSec_1Dcosmu_nu.h" #include "T2K_CC1pip_H2O_XSec_1Dcosmupi_nu.h" #include "T2K_CC1pip_H2O_XSec_1Dcospi_nu.h" #include "T2K_CC1pip_H2O_XSec_1Dpmu_nu.h" #include "T2K_CC1pip_H2O_XSec_1Dppi_nu.h" // add header here #endif #ifndef __NO_SciBooNE__ // SciBooNE COH studies #include "SciBooNE_CCCOH_1TRK_1DQ2_nu.h" #include "SciBooNE_CCCOH_1TRK_1Dpmu_nu.h" #include "SciBooNE_CCCOH_1TRK_1Dthetamu_nu.h" #include "SciBooNE_CCCOH_MuPiNoVA_1DQ2_nu.h" #include "SciBooNE_CCCOH_MuPiNoVA_1Dpmu_nu.h" #include "SciBooNE_CCCOH_MuPiNoVA_1Dthetamu_nu.h" #include "SciBooNE_CCCOH_MuPiNoVA_1Dthetapi_nu.h" #include "SciBooNE_CCCOH_MuPiNoVA_1Dthetapr_nu.h" #include "SciBooNE_CCCOH_MuPiVA_1DQ2_nu.h" #include "SciBooNE_CCCOH_MuPiVA_1Dpmu_nu.h" #include "SciBooNE_CCCOH_MuPiVA_1Dthetamu_nu.h" #include "SciBooNE_CCCOH_MuPr_1DQ2_nu.h" #include "SciBooNE_CCCOH_MuPr_1Dpmu_nu.h" #include "SciBooNE_CCCOH_MuPr_1Dthetamu_nu.h" #include "SciBooNE_CCCOH_STOPFINAL_1DQ2_nu.h" #include "SciBooNE_CCCOH_STOP_NTrks_nu.h" #include "SciBooNE_CCInc_XSec_1DEnu_nu.h" #endif #ifndef __NO_K2K__ // K2K NC1pi0 #include "K2K_NC1pi0_Evt_1Dppi0_nu.h" #endif // MC Studies #include "ExpMultDist_CCQE_XSec_1DVar_FakeStudy.h" #include "ExpMultDist_CCQE_XSec_2DVar_FakeStudy.h" #include "MCStudy_CCQEHistograms.h" #include "GenericFlux_Tester.h" #include "GenericFlux_Vectors.h" #include "ElectronFlux_FlatTree.h" #include "ElectronScattering_DurhamData.h" #include "MCStudy_KaonPreSelection.h" #include "MCStudy_MuonValidation.h" #include "OfficialNIWGPlots.h" #include "T2K2017_FakeData.h" #include "SigmaEnuHists.h" #include "Simple_Osc.h" #include "Smear_SVDUnfold_Propagation_Osc.h" #include "FitWeight.h" #include "NuisConfig.h" #include "NuisKey.h" #ifdef __USE_DYNSAMPLES__ #include "TRegexp.h" #include // linux #include DynamicSampleFactory::DynamicSampleFactory() : NSamples(0), NManifests(0) { LoadPlugins(); NUIS_LOG(FIT, "Loaded " << NSamples << " from " << NManifests << " shared object libraries."); } DynamicSampleFactory *DynamicSampleFactory::glblDSF = NULL; DynamicSampleFactory::PluginManifest::~PluginManifest() { for (size_t i_it = 0; i_it < Instances.size(); ++i_it) { (*(DSF_DestroySample))(Instances[i_it]); } } std::string EnsureTrailingSlash(std::string const &inp) { if (!inp.length()) { return "/"; } if (inp[inp.length() - 1] == '/') { return inp; } return inp + "/"; } void DynamicSampleFactory::LoadPlugins() { std::vector SearchDirectories; if (Config::HasPar("dynamic_sample.path")) { SearchDirectories = GeneralUtils::ParseToStr(Config::GetParS("dynamic_sample.path"), ":"); } char const *envPath = getenv("NUISANCE_DS_PATH"); if (envPath) { std::vector envPaths = GeneralUtils::ParseToStr(envPath, ":"); for (size_t ep_it = 0; ep_it < envPaths.size(); ++ep_it) { SearchDirectories.push_back(envPaths[ep_it]); } } if (!SearchDirectories.size()) { char const *pwdPath = getenv("PWD"); if (pwdPath) { SearchDirectories.push_back(pwdPath); } } for (size_t sp_it = 0; sp_it < SearchDirectories.size(); ++sp_it) { std::string dirpath = EnsureTrailingSlash(SearchDirectories[sp_it]); NUIS_LOG(FIT, "Searching for dynamic sample manifests in: " << dirpath); Ssiz_t len = 0; DIR *dir; struct dirent *ent; dir = opendir(dirpath.c_str()); if (dir != NULL) { TRegexp matchExp("*.so", true); while ((ent = readdir(dir)) != NULL) { if (matchExp.Index(TString(ent->d_name), &len) != Ssiz_t(-1)) { NUIS_LOG(FIT, "\tFound shared object: " << ent->d_name << " checking for relevant methods..."); void *dlobj = dlopen((dirpath + ent->d_name).c_str(), RTLD_NOW | RTLD_GLOBAL); char const *dlerr_cstr = dlerror(); std::string dlerr; if (dlerr_cstr) { dlerr = dlerr_cstr; } if (dlerr.length()) { NUIS_ERR(WRN, "\tDL Load Error: " << dlerr); continue; } PluginManifest plgManif; plgManif.dllib = dlobj; plgManif.soloc = (dirpath + ent->d_name); plgManif.DSF_NSamples = reinterpret_cast(dlsym(dlobj, "DSF_NSamples")); dlerr = ""; dlerr_cstr = dlerror(); if (dlerr_cstr) { dlerr = dlerr_cstr; } if (dlerr.length()) { NUIS_ERR(WRN, "\tFailed to load symbol \"DSF_NSamples\" from " << (dirpath + ent->d_name) << ": " << dlerr); dlclose(dlobj); continue; } plgManif.DSF_GetSampleName = reinterpret_cast( dlsym(dlobj, "DSF_GetSampleName")); dlerr = ""; dlerr_cstr = dlerror(); if (dlerr_cstr) { dlerr = dlerr_cstr; } if (dlerr.length()) { NUIS_ERR(WRN, "\tFailed to load symbol \"DSF_GetSampleName\" from " << (dirpath + ent->d_name) << ": " << dlerr); dlclose(dlobj); continue; } plgManif.DSF_GetSample = reinterpret_cast( dlsym(dlobj, "DSF_GetSample")); dlerr = ""; dlerr_cstr = dlerror(); if (dlerr_cstr) { dlerr = dlerr_cstr; } if (dlerr.length()) { NUIS_ERR(WRN, "\tFailed to load symbol \"DSF_GetSample\" from " << (dirpath + ent->d_name) << ": " << dlerr); dlclose(dlobj); continue; } plgManif.DSF_DestroySample = reinterpret_cast( dlsym(dlobj, "DSF_DestroySample")); dlerr = ""; dlerr_cstr = dlerror(); if (dlerr_cstr) { dlerr = dlerr_cstr; } if (dlerr.length()) { NUIS_ERR(WRN, "Failed to load symbol \"DSF_DestroySample\" from " << (dirpath + ent->d_name) << ": " << dlerr); dlclose(dlobj); continue; } plgManif.NSamples = (*(plgManif.DSF_NSamples))(); NUIS_LOG(FIT, "\tSuccessfully loaded dynamic sample manifest: " << plgManif.soloc << ". Contains " << plgManif.NSamples << " samples."); for (size_t smp_it = 0; smp_it < plgManif.NSamples; ++smp_it) { char const *smp_name = (*(plgManif.DSF_GetSampleName))(smp_it); if (!smp_name) { NUIS_ABORT("Could not load sample " << smp_it << " / " << plgManif.NSamples << " from " << plgManif.soloc); } if (Samples.count(smp_name)) { NUIS_ERR(WRN, "Already loaded a sample named: \"" << smp_name << "\". cannot load duplciates. This " "sample will be skipped."); continue; } plgManif.SamplesProvided.push_back(smp_name); Samples[smp_name] = std::make_pair(plgManif.soloc, smp_it); NUIS_LOG(FIT, "\t\t" << smp_name); } if (plgManif.SamplesProvided.size()) { Manifests[plgManif.soloc] = plgManif; NSamples += plgManif.SamplesProvided.size(); NManifests++; } else { dlclose(dlobj); } } } closedir(dir); } else { NUIS_ERR(WRN, "Tried to open non-existant directory."); } } } DynamicSampleFactory &DynamicSampleFactory::Get() { if (!glblDSF) { glblDSF = new DynamicSampleFactory(); } return *glblDSF; } void DynamicSampleFactory::Print() { std::map > ManifestSamples; for (std::map >::iterator smp_it = Samples.begin(); smp_it != Samples.end(); ++smp_it) { if (!ManifestSamples.count(smp_it->second.first)) { ManifestSamples[smp_it->second.first] = std::vector(); } ManifestSamples[smp_it->second.first].push_back(smp_it->first); } NUIS_LOG(FIT, "Dynamic sample manifest: "); for (std::map >::iterator m_it = ManifestSamples.begin(); m_it != ManifestSamples.end(); ++m_it) { NUIS_LOG(FIT, "\tLibrary " << m_it->first << " contains: "); for (size_t s_it = 0; s_it < m_it->second.size(); ++s_it) { NUIS_LOG(FIT, "\t\t" << m_it->second[s_it]); } } } bool DynamicSampleFactory::HasSample(std::string const &name) { return Samples.count(name); } bool DynamicSampleFactory::HasSample(nuiskey &samplekey) { return HasSample(samplekey.GetS("name")); } MeasurementBase *DynamicSampleFactory::CreateSample(nuiskey &samplekey) { if (!HasSample(samplekey)) { NUIS_ERR(WRN, "Asked to load unknown sample: \"" << samplekey.GetS("name") << "\"."); return NULL; } std::pair sample = Samples[samplekey.GetS("name")]; NUIS_LOG(SAM, "\tLoading sample " << sample.second << " from " << sample.first); return (*(Manifests[sample.first].DSF_GetSample))(sample.second, &samplekey); } DynamicSampleFactory::~DynamicSampleFactory() { Manifests.clear(); } #endif //! Functions to make it easier for samples to be created and handled. namespace SampleUtils { //! Create a given sample given its name, file, type, fakdata(fkdt) file and the //! current rw engine and push it back into the list fChain. MeasurementBase *CreateSample(std::string name, std::string file, std::string type, std::string fkdt, FitWeight *rw) { nuiskey samplekey = Config::CreateKey("sample"); samplekey.Set("name", name); samplekey.Set("input", file); samplekey.Set("type", type); return CreateSample(samplekey); } MeasurementBase *CreateSample(nuiskey samplekey) { #ifdef __USE_DYNSAMPLES__ if (DynamicSampleFactory::Get().HasSample(samplekey)) { NUIS_LOG(SAM, "Instantiating dynamic sample..."); MeasurementBase *ds = DynamicSampleFactory::Get().CreateSample(samplekey); if (ds) { NUIS_LOG(SAM, "Done."); return ds; } NUIS_ABORT("Failed to instantiate dynamic sample."); } #endif FitWeight *rw = FitBase::GetRW(); std::string name = samplekey.GetS("name"); std::string file = samplekey.GetS("input"); std::string type = samplekey.GetS("type"); std::string fkdt = ""; /* ANL CCQE Samples */ #ifndef __NO_ANL__ if (!name.compare("ANL_CCQE_XSec_1DEnu_nu") || !name.compare("ANL_CCQE_XSec_1DEnu_nu_PRD26") || !name.compare("ANL_CCQE_XSec_1DEnu_nu_PRL31") || !name.compare("ANL_CCQE_XSec_1DEnu_nu_PRD16")) { return (new ANL_CCQE_XSec_1DEnu_nu(samplekey)); } else if (!name.compare("ANL_CCQE_Evt_1DQ2_nu") || !name.compare("ANL_CCQE_Evt_1DQ2_nu_PRL31") || !name.compare("ANL_CCQE_Evt_1DQ2_nu_PRD26") || !name.compare("ANL_CCQE_Evt_1DQ2_nu_PRD16")) { return (new ANL_CCQE_Evt_1DQ2_nu(samplekey)); /* ANL CC1ppip samples */ } else if (!name.compare("ANL_CC1ppip_XSec_1DEnu_nu") || !name.compare("ANL_CC1ppip_XSec_1DEnu_nu_W14Cut") || !name.compare("ANL_CC1ppip_XSec_1DEnu_nu_Uncorr") || !name.compare("ANL_CC1ppip_XSec_1DEnu_nu_W14Cut_Uncorr") || !name.compare("ANL_CC1ppip_XSec_1DEnu_nu_W16Cut_Uncorr")) { return (new ANL_CC1ppip_XSec_1DEnu_nu(samplekey)); } else if (!name.compare("ANL_CC1ppip_XSec_1DQ2_nu")) { return (new ANL_CC1ppip_XSec_1DQ2_nu(samplekey)); } else if (!name.compare("ANL_CC1ppip_Evt_1DQ2_nu") || !name.compare("ANL_CC1ppip_Evt_1DQ2_nu_W14Cut")) { return (new ANL_CC1ppip_Evt_1DQ2_nu(samplekey)); } else if (!name.compare("ANL_CC1ppip_Evt_1Dppi_nu")) { return (new ANL_CC1ppip_Evt_1Dppi_nu(samplekey)); } else if (!name.compare("ANL_CC1ppip_Evt_1Dthpr_nu")) { return (new ANL_CC1ppip_Evt_1Dthpr_nu(samplekey)); } else if (!name.compare("ANL_CC1ppip_Evt_1DcosmuStar_nu")) { return (new ANL_CC1ppip_Evt_1DcosmuStar_nu(samplekey)); } else if (!name.compare("ANL_CC1ppip_Evt_1DcosthAdler_nu")) { return (new ANL_CC1ppip_Evt_1DcosthAdler_nu(samplekey)); } else if (!name.compare("ANL_CC1ppip_Evt_1Dphi_nu")) { return (new ANL_CC1ppip_Evt_1Dphi_nu(samplekey)); /* ANL CC1npip sample */ } else if (!name.compare("ANL_CC1npip_XSec_1DEnu_nu") || !name.compare("ANL_CC1npip_XSec_1DEnu_nu_W14Cut") || !name.compare("ANL_CC1npip_XSec_1DEnu_nu_Uncorr") || !name.compare("ANL_CC1npip_XSec_1DEnu_nu_W14Cut_Uncorr") || !name.compare("ANL_CC1npip_XSec_1DEnu_nu_W16Cut_Uncorr")) { return (new ANL_CC1npip_XSec_1DEnu_nu(samplekey)); } else if (!name.compare("ANL_CC1npip_Evt_1DQ2_nu") || !name.compare("ANL_CC1npip_Evt_1DQ2_nu_W14Cut")) { return (new ANL_CC1npip_Evt_1DQ2_nu(samplekey)); } else if (!name.compare("ANL_CC1npip_Evt_1Dppi_nu")) { return (new ANL_CC1npip_Evt_1Dppi_nu(samplekey)); } else if (!name.compare("ANL_CC1npip_Evt_1DcosmuStar_nu")) { return (new ANL_CC1npip_Evt_1DcosmuStar_nu(samplekey)); /* ANL CC1pi0 sample */ } else if (!name.compare("ANL_CC1pi0_XSec_1DEnu_nu") || !name.compare("ANL_CC1pi0_XSec_1DEnu_nu_W14Cut") || !name.compare("ANL_CC1pi0_XSec_1DEnu_nu_Uncorr") || !name.compare("ANL_CC1pi0_XSec_1DEnu_nu_W14Cut_Uncorr") || !name.compare("ANL_CC1pi0_XSec_1DEnu_nu_W16Cut_Uncorr")) { return (new ANL_CC1pi0_XSec_1DEnu_nu(samplekey)); } else if (!name.compare("ANL_CC1pi0_Evt_1DQ2_nu") || !name.compare("ANL_CC1pi0_Evt_1DQ2_nu_W14Cut")) { return (new ANL_CC1pi0_Evt_1DQ2_nu(samplekey)); } else if (!name.compare("ANL_CC1pi0_Evt_1DcosmuStar_nu")) { return (new ANL_CC1pi0_Evt_1DcosmuStar_nu(samplekey)); /* ANL NC1npip sample */ } else if (!name.compare("ANL_NC1npip_Evt_1Dppi_nu")) { return (new ANL_NC1npip_Evt_1Dppi_nu(samplekey)); /* ANL NC1ppim sample */ } else if (!name.compare("ANL_NC1ppim_XSec_1DEnu_nu")) { return (new ANL_NC1ppim_XSec_1DEnu_nu(samplekey)); } else if (!name.compare("ANL_NC1ppim_Evt_1DcosmuStar_nu")) { return (new ANL_NC1ppim_Evt_1DcosmuStar_nu(samplekey)); /* ANL CC2pi sample */ } else if (!name.compare("ANL_CC2pi_1pim1pip_XSec_1DEnu_nu")) { return (new ANL_CC2pi_1pim1pip_XSec_1DEnu_nu(samplekey)); } else if (!name.compare("ANL_CC2pi_1pim1pip_Evt_1Dpmu_nu")) { return (new ANL_CC2pi_1pim1pip_Evt_1Dpmu_nu(samplekey)); } else if (!name.compare("ANL_CC2pi_1pim1pip_Evt_1Dppip_nu")) { return (new ANL_CC2pi_1pim1pip_Evt_1Dppip_nu(samplekey)); } else if (!name.compare("ANL_CC2pi_1pim1pip_Evt_1Dppim_nu")) { return (new ANL_CC2pi_1pim1pip_Evt_1Dppim_nu(samplekey)); } else if (!name.compare("ANL_CC2pi_1pim1pip_Evt_1Dpprot_nu")) { return (new ANL_CC2pi_1pim1pip_Evt_1Dpprot_nu(samplekey)); } else if (!name.compare("ANL_CC2pi_1pip1pip_XSec_1DEnu_nu")) { return (new ANL_CC2pi_1pip1pip_XSec_1DEnu_nu(samplekey)); } else if (!name.compare("ANL_CC2pi_1pip1pip_Evt_1Dpmu_nu")) { return (new ANL_CC2pi_1pip1pip_Evt_1Dpmu_nu(samplekey)); } else if (!name.compare("ANL_CC2pi_1pip1pip_Evt_1Dpneut_nu")) { return (new ANL_CC2pi_1pip1pip_Evt_1Dpneut_nu(samplekey)); } else if (!name.compare("ANL_CC2pi_1pip1pip_Evt_1DppipHigh_nu")) { return (new ANL_CC2pi_1pip1pip_Evt_1DppipHigh_nu(samplekey)); } else if (!name.compare("ANL_CC2pi_1pip1pip_Evt_1DppipLow_nu")) { return (new ANL_CC2pi_1pip1pip_Evt_1DppipLow_nu(samplekey)); } else if (!name.compare("ANL_CC2pi_1pip1pi0_XSec_1DEnu_nu")) { return (new ANL_CC2pi_1pip1pi0_XSec_1DEnu_nu(samplekey)); } else if (!name.compare("ANL_CC2pi_1pip1pi0_Evt_1Dpmu_nu")) { return (new ANL_CC2pi_1pip1pi0_Evt_1Dpmu_nu(samplekey)); } else if (!name.compare("ANL_CC2pi_1pip1pi0_Evt_1Dppip_nu")) { return (new ANL_CC2pi_1pip1pi0_Evt_1Dppip_nu(samplekey)); } else if (!name.compare("ANL_CC2pi_1pip1pi0_Evt_1Dppi0_nu")) { return (new ANL_CC2pi_1pip1pi0_Evt_1Dppi0_nu(samplekey)); } else if (!name.compare("ANL_CC2pi_1pip1pi0_Evt_1Dpprot_nu")) { return (new ANL_CC2pi_1pip1pi0_Evt_1Dpprot_nu(samplekey)); /* ArgoNeut Samples */ } else #endif #ifndef __NO_ArgoNeuT__ if (!name.compare("ArgoNeuT_CCInc_XSec_1Dpmu_antinu")) { return (new ArgoNeuT_CCInc_XSec_1Dpmu_antinu(samplekey)); } else if (!name.compare("ArgoNeuT_CCInc_XSec_1Dpmu_nu")) { return (new ArgoNeuT_CCInc_XSec_1Dpmu_nu(samplekey)); } else if (!name.compare("ArgoNeuT_CCInc_XSec_1Dthetamu_antinu")) { return (new ArgoNeuT_CCInc_XSec_1Dthetamu_antinu(samplekey)); } else if (!name.compare("ArgoNeuT_CCInc_XSec_1Dthetamu_nu")) { return (new ArgoNeuT_CCInc_XSec_1Dthetamu_nu(samplekey)); } else if (!name.compare("ArgoNeuT_CC1Pi_XSec_1Dpmu_nu")) { return (new ArgoNeuT_CC1Pi_XSec_1Dpmu_nu(samplekey)); } else if (!name.compare("ArgoNeuT_CC1Pi_XSec_1Dthetamu_nu")) { return (new ArgoNeuT_CC1Pi_XSec_1Dthetamu_nu(samplekey)); } else if (!name.compare("ArgoNeuT_CC1Pi_XSec_1Dthetapi_nu")) { return (new ArgoNeuT_CC1Pi_XSec_1Dthetapi_nu(samplekey)); } else if (!name.compare("ArgoNeuT_CC1Pi_XSec_1Dthetamupi_nu")) { return (new ArgoNeuT_CC1Pi_XSec_1Dthetamupi_nu(samplekey)); } else if (!name.compare("ArgoNeuT_CC1Pi_XSec_1Dpmu_antinu")) { return (new ArgoNeuT_CC1Pi_XSec_1Dpmu_antinu(samplekey)); } else if (!name.compare("ArgoNeuT_CC1Pi_XSec_1Dthetamu_antinu")) { return (new ArgoNeuT_CC1Pi_XSec_1Dthetamu_antinu(samplekey)); } else if (!name.compare("ArgoNeuT_CC1Pi_XSec_1Dthetapi_antinu")) { return (new ArgoNeuT_CC1Pi_XSec_1Dthetapi_antinu(samplekey)); } else if (!name.compare("ArgoNeuT_CC1Pi_XSec_1Dthetamupi_antinu")) { return (new ArgoNeuT_CC1Pi_XSec_1Dthetamupi_antinu(samplekey)); /* BNL Samples */ } else #endif #ifndef __NO_BNL__ if (!name.compare("BNL_CCQE_XSec_1DEnu_nu")) { return (new BNL_CCQE_XSec_1DEnu_nu(samplekey)); } else if (!name.compare("BNL_CCQE_Evt_1DQ2_nu")) { return (new BNL_CCQE_Evt_1DQ2_nu(samplekey)); /* BNL CC1ppip samples */ } else if (!name.compare("BNL_CC1ppip_XSec_1DEnu_nu") || !name.compare("BNL_CC1ppip_XSec_1DEnu_nu_Uncorr") || !name.compare("BNL_CC1ppip_XSec_1DEnu_nu_W14Cut") || !name.compare("BNL_CC1ppip_XSec_1DEnu_nu_W14Cut_Uncorr")) { return (new BNL_CC1ppip_XSec_1DEnu_nu(samplekey)); } else if (!name.compare("BNL_CC1ppip_Evt_1DQ2_nu") || !name.compare("BNL_CC1ppip_Evt_1DQ2_nu_W14Cut")) { return (new BNL_CC1ppip_Evt_1DQ2_nu(samplekey)); } else if (!name.compare("BNL_CC1ppip_Evt_1DcosthAdler_nu")) { return (new BNL_CC1ppip_Evt_1DcosthAdler_nu(samplekey)); } else if (!name.compare("BNL_CC1ppip_Evt_1Dphi_nu")) { return (new BNL_CC1ppip_Evt_1Dphi_nu(samplekey)); /* BNL CC1npip samples */ } else if (!name.compare("BNL_CC1npip_XSec_1DEnu_nu") || !name.compare("BNL_CC1npip_XSec_1DEnu_nu_Uncorr")) { return (new BNL_CC1npip_XSec_1DEnu_nu(samplekey)); } else if (!name.compare("BNL_CC1npip_Evt_1DQ2_nu")) { return (new BNL_CC1npip_Evt_1DQ2_nu(samplekey)); /* BNL CC1pi0 samples */ } else if (!name.compare("BNL_CC1pi0_XSec_1DEnu_nu")) { return (new BNL_CC1pi0_XSec_1DEnu_nu(samplekey)); } else if (!name.compare("BNL_CC1pi0_Evt_1DQ2_nu")) { return (new BNL_CC1pi0_Evt_1DQ2_nu(samplekey)); /* FNAL Samples */ } else #endif #ifndef __NO_FNAL__ if (!name.compare("FNAL_CCQE_Evt_1DQ2_nu")) { return (new FNAL_CCQE_Evt_1DQ2_nu(samplekey)); /* FNAL CC1ppip */ } else if (!name.compare("FNAL_CC1ppip_XSec_1DEnu_nu")) { return (new FNAL_CC1ppip_XSec_1DEnu_nu(samplekey)); } else if (!name.compare("FNAL_CC1ppip_XSec_1DQ2_nu")) { return (new FNAL_CC1ppip_XSec_1DQ2_nu(samplekey)); } else if (!name.compare("FNAL_CC1ppip_Evt_1DQ2_nu")) { return (new FNAL_CC1ppip_Evt_1DQ2_nu(samplekey)); /* FNAL CC1ppim */ } else if (!name.compare("FNAL_CC1ppim_XSec_1DEnu_antinu")) { return (new FNAL_CC1ppim_XSec_1DEnu_antinu(samplekey)); /* BEBC Samples */ } else #endif #ifndef __NO_BEBC__ if (!name.compare("BEBC_CCQE_XSec_1DQ2_nu")) { return (new BEBC_CCQE_XSec_1DQ2_nu(samplekey)); /* BEBC CC1ppip samples */ } else if (!name.compare("BEBC_CC1ppip_XSec_1DEnu_nu")) { return (new BEBC_CC1ppip_XSec_1DEnu_nu(samplekey)); } else if (!name.compare("BEBC_CC1ppip_XSec_1DQ2_nu")) { return (new BEBC_CC1ppip_XSec_1DQ2_nu(samplekey)); /* BEBC CC1npip samples */ } else if (!name.compare("BEBC_CC1npip_XSec_1DEnu_nu")) { return (new BEBC_CC1npip_XSec_1DEnu_nu(samplekey)); } else if (!name.compare("BEBC_CC1npip_XSec_1DQ2_nu")) { return (new BEBC_CC1npip_XSec_1DQ2_nu(samplekey)); /* BEBC CC1pi0 samples */ } else if (!name.compare("BEBC_CC1pi0_XSec_1DEnu_nu")) { return (new BEBC_CC1pi0_XSec_1DEnu_nu(samplekey)); } else if (!name.compare("BEBC_CC1pi0_XSec_1DQ2_nu")) { return (new BEBC_CC1pi0_XSec_1DQ2_nu(samplekey)); /* BEBC CC1npim samples */ } else if (!name.compare("BEBC_CC1npim_XSec_1DEnu_antinu")) { return (new BEBC_CC1npim_XSec_1DEnu_antinu(samplekey)); } else if (!name.compare("BEBC_CC1npim_XSec_1DQ2_antinu")) { return (new BEBC_CC1npim_XSec_1DQ2_antinu(samplekey)); /* BEBC CC1ppim samples */ } else if (!name.compare("BEBC_CC1ppim_XSec_1DEnu_antinu")) { return (new BEBC_CC1ppim_XSec_1DEnu_antinu(samplekey)); } else if (!name.compare("BEBC_CC1ppim_XSec_1DQ2_antinu")) { return (new BEBC_CC1ppim_XSec_1DQ2_antinu(samplekey)); /* GGM CC1ppip samples */ } else #endif #ifndef __NO_GGM__ if (!name.compare("GGM_CC1ppip_XSec_1DEnu_nu")) { return (new GGM_CC1ppip_XSec_1DEnu_nu(samplekey)); } else if (!name.compare("GGM_CC1ppip_Evt_1DQ2_nu")) { return (new GGM_CC1ppip_Evt_1DQ2_nu(samplekey)); /* MiniBooNE Samples */ /* CCQE */ } else #endif #ifndef __NO_MiniBooNE__ if (!name.compare("MiniBooNE_CCQE_XSec_1DQ2_nu") || !name.compare("MiniBooNE_CCQELike_XSec_1DQ2_nu")) { return (new MiniBooNE_CCQE_XSec_1DQ2_nu(samplekey)); } else if (!name.compare("MiniBooNE_CCQE_XSec_1DEnu_nu") || !name.compare("MiniBooNE_CCQELike_XSec_1DEnu_nu")) { return (new MiniBooNE_CCQE_XSec_1DEnu_nu(samplekey)); } else if (!name.compare("MiniBooNE_CCQE_XSec_1DQ2_antinu") || !name.compare("MiniBooNE_CCQELike_XSec_1DQ2_antinu") || !name.compare("MiniBooNE_CCQE_CTarg_XSec_1DQ2_antinu")) { return (new MiniBooNE_CCQE_XSec_1DQ2_antinu(samplekey)); } else if (!name.compare("MiniBooNE_CCQE_XSec_2DTcos_nu") || !name.compare("MiniBooNE_CCQELike_XSec_2DTcos_nu")) { return (new MiniBooNE_CCQE_XSec_2DTcos_nu(samplekey)); } else if (!name.compare("MiniBooNE_CCQE_XSec_2DTcos_antinu") || !name.compare("MiniBooNE_CCQELike_XSec_2DTcos_antinu")) { return (new MiniBooNE_CCQE_XSec_2DTcos_antinu(samplekey)); /* MiniBooNE CC1pi+ */ // 1D } else if (!name.compare("MiniBooNE_CC1pip_XSec_1DEnu_nu")) { return (new MiniBooNE_CC1pip_XSec_1DEnu_nu(samplekey)); } else if (!name.compare("MiniBooNE_CC1pip_XSec_1DQ2_nu")) { return (new MiniBooNE_CC1pip_XSec_1DQ2_nu(samplekey)); } else if (!name.compare("MiniBooNE_CC1pip_XSec_1DTpi_nu")) { return (new MiniBooNE_CC1pip_XSec_1DTpi_nu(samplekey)); } else if (!name.compare("MiniBooNE_CC1pip_XSec_1DTu_nu")) { return (new MiniBooNE_CC1pip_XSec_1DTu_nu(samplekey)); // 2D } else if (!name.compare("MiniBooNE_CC1pip_XSec_2DQ2Enu_nu")) { return (new MiniBooNE_CC1pip_XSec_2DQ2Enu_nu(samplekey)); } else if (!name.compare("MiniBooNE_CC1pip_XSec_2DTpiCospi_nu")) { return (new MiniBooNE_CC1pip_XSec_2DTpiCospi_nu(samplekey)); } else if (!name.compare("MiniBooNE_CC1pip_XSec_2DTpiEnu_nu")) { return (new MiniBooNE_CC1pip_XSec_2DTpiEnu_nu(samplekey)); } else if (!name.compare("MiniBooNE_CC1pip_XSec_2DTuCosmu_nu")) { return (new MiniBooNE_CC1pip_XSec_2DTuCosmu_nu(samplekey)); } else if (!name.compare("MiniBooNE_CC1pip_XSec_2DTuEnu_nu")) { return (new MiniBooNE_CC1pip_XSec_2DTuEnu_nu(samplekey)); /* MiniBooNE CC1pi0 */ } else if (!name.compare("MiniBooNE_CC1pi0_XSec_1DEnu_nu")) { return (new MiniBooNE_CC1pi0_XSec_1DEnu_nu(samplekey)); } else if (!name.compare("MiniBooNE_CC1pi0_XSec_1DQ2_nu")) { return (new MiniBooNE_CC1pi0_XSec_1DQ2_nu(samplekey)); } else if (!name.compare("MiniBooNE_CC1pi0_XSec_1DTu_nu")) { return (new MiniBooNE_CC1pi0_XSec_1DTu_nu(samplekey)); } else if (!name.compare("MiniBooNE_CC1pi0_XSec_1Dcosmu_nu")) { return (new MiniBooNE_CC1pi0_XSec_1Dcosmu_nu(samplekey)); } else if (!name.compare("MiniBooNE_CC1pi0_XSec_1Dcospi0_nu")) { return (new MiniBooNE_CC1pi0_XSec_1Dcospi0_nu(samplekey)); } else if (!name.compare("MiniBooNE_CC1pi0_XSec_1Dppi0_nu")) { return (new MiniBooNE_CC1pi0_XSec_1Dppi0_nu(samplekey)); } else if (!name.compare("MiniBooNE_NC1pi0_XSec_1Dcospi0_antinu") || !name.compare("MiniBooNE_NC1pi0_XSec_1Dcospi0_rhc")) { return (new MiniBooNE_NC1pi0_XSec_1Dcospi0_antinu(samplekey)); } else if (!name.compare("MiniBooNE_NC1pi0_XSec_1Dcospi0_nu") || !name.compare("MiniBooNE_NC1pi0_XSec_1Dcospi0_fhc")) { return (new MiniBooNE_NC1pi0_XSec_1Dcospi0_nu(samplekey)); } else if (!name.compare("MiniBooNE_NC1pi0_XSec_1Dppi0_antinu") || !name.compare("MiniBooNE_NC1pi0_XSec_1Dppi0_rhc")) { return (new MiniBooNE_NC1pi0_XSec_1Dppi0_antinu(samplekey)); } else if (!name.compare("MiniBooNE_NC1pi0_XSec_1Dppi0_nu") || !name.compare("MiniBooNE_NC1pi0_XSec_1Dppi0_fhc")) { return (new MiniBooNE_NC1pi0_XSec_1Dppi0_nu(samplekey)); /* MiniBooNE NCEL */ } else if (!name.compare("MiniBooNE_NCEL_XSec_Treco_nu")) { return (new MiniBooNE_NCEL_XSec_Treco_nu(samplekey)); } else #endif #ifndef __NO_MicroBooNE__ /* MicroBooNE Samples */ /* MicroBooNE CCinclusive */ if (!name.compare("MicroBooNE_CCInc_XSec_2DPcos_nu")) { return (new MicroBooNE_CCInc_XSec_2DPcos_nu(samplekey)); } else #endif #ifndef __NO_MINERvA__ /* MINERvA Samples */ if (!name.compare("MINERvA_CCQE_XSec_1DQ2_nu") || !name.compare("MINERvA_CCQE_XSec_1DQ2_nu_20deg") || !name.compare("MINERvA_CCQE_XSec_1DQ2_nu_oldflux") || !name.compare("MINERvA_CCQE_XSec_1DQ2_nu_20deg_oldflux")) { return (new MINERvA_CCQE_XSec_1DQ2_nu(samplekey)); } else if (!name.compare("MINERvA_CCQE_XSec_1DQ2_antinu") || !name.compare("MINERvA_CCQE_XSec_1DQ2_antinu_20deg") || !name.compare("MINERvA_CCQE_XSec_1DQ2_antinu_oldflux") || !name.compare("MINERvA_CCQE_XSec_1DQ2_antinu_20deg_oldflux")) { return (new MINERvA_CCQE_XSec_1DQ2_antinu(samplekey)); } else if (!name.compare("MINERvA_CCQE_XSec_1DQ2_joint_oldflux") || !name.compare("MINERvA_CCQE_XSec_1DQ2_joint_20deg_oldflux") || !name.compare("MINERvA_CCQE_XSec_1DQ2_joint") || !name.compare("MINERvA_CCQE_XSec_1DQ2_joint_20deg")) { return (new MINERvA_CCQE_XSec_1DQ2_joint(samplekey)); } else if (!name.compare("MINERvA_CC0pi_XSec_1DEe_nue")) { return (new MINERvA_CC0pi_XSec_1DEe_nue(samplekey)); } else if (!name.compare("MINERvA_CC0pi_XSec_1DQ2_nue")) { return (new MINERvA_CC0pi_XSec_1DQ2_nue(samplekey)); } else if (!name.compare("MINERvA_CC0pi_XSec_1DThetae_nue")) { return (new MINERvA_CC0pi_XSec_1DThetae_nue(samplekey)); } else if (!name.compare("MINERvA_CC0pinp_STV_XSec_1Dpmu_nu") || !name.compare("MINERvA_CC0pinp_STV_XSec_1Dthmu_nu") || !name.compare("MINERvA_CC0pinp_STV_XSec_1Dpprot_nu") || !name.compare("MINERvA_CC0pinp_STV_XSec_1Dthprot_nu") || !name.compare("MINERvA_CC0pinp_STV_XSec_1Dpnreco_nu") || !name.compare("MINERvA_CC0pinp_STV_XSec_1Ddalphat_nu") || !name.compare("MINERvA_CC0pinp_STV_XSec_1Ddpt_nu") || !name.compare("MINERvA_CC0pinp_STV_XSec_1Ddphit_nu")) { return (new MINERvA_CC0pinp_STV_XSec_1D_nu(samplekey)); } else if (!name.compare("MINERvA_CC0pi_XSec_1DQ2_nu_proton")) { return (new MINERvA_CC0pi_XSec_1DQ2_nu_proton(samplekey)); } else if (!name.compare("MINERvA_CC0pi_XSec_1DQ2_TgtC_nu") || !name.compare("MINERvA_CC0pi_XSec_1DQ2_TgtCH_nu") || !name.compare("MINERvA_CC0pi_XSec_1DQ2_TgtFe_nu") || !name.compare("MINERvA_CC0pi_XSec_1DQ2_TgtPb_nu")) { return (new MINERvA_CC0pi_XSec_1DQ2_Tgt_nu(samplekey)); } else if (!name.compare("MINERvA_CC0pi_XSec_1DQ2_TgtRatioC_nu") || !name.compare("MINERvA_CC0pi_XSec_1DQ2_TgtRatioFe_nu") || !name.compare("MINERvA_CC0pi_XSec_1DQ2_TgtRatioPb_nu")) { return (new MINERvA_CC0pi_XSec_1DQ2_TgtRatio_nu(samplekey)); // Dan Ruterbories measurements of late 2018 } else if (!name.compare("MINERvA_CC0pi_XSec_2Dptpz_nu")) { return (new MINERvA_CC0pi_XSec_2D_nu(samplekey)); // } else if (!name.compare("MINERvA_CC0pi_XSec_3DptpzTp_nu")) { // return (new MINERvA_CC0pi_XSec_3DptpzTp_nu(samplekey)); } else if (!name.compare("MINERvA_CC0pi_XSec_1Dpt_nu") || !name.compare("MINERvA_CC0pi_XSec_1Dpz_nu") || !name.compare("MINERvA_CC0pi_XSec_1DQ2QE_nu") || !name.compare("MINERvA_CC0pi_XSec_1DEnuQE_nu")) { return (new MINERvA_CC0pi_XSec_1D_2018_nu(samplekey)); // C. Patrick's early 2018 measurements } else if (!name.compare("MINERvA_CC0pi_XSec_2Dptpz_antinu") || !name.compare("MINERvA_CC0pi_XSec_2DQ2QEEnuQE_antinu") || !name.compare("MINERvA_CC0pi_XSec_2DQ2QEEnuTrue_antinu")) { return (new MINERvA_CC0pi_XSec_2D_antinu(samplekey)); /* CC1pi+ */ // DONE } else if (!name.compare("MINERvA_CC1pip_XSec_1DTpi_nu") || !name.compare("MINERvA_CC1pip_XSec_1DTpi_nu_20deg") || !name.compare("MINERvA_CC1pip_XSec_1DTpi_nu_fluxcorr") || !name.compare("MINERvA_CC1pip_XSec_1DTpi_nu_20deg_fluxcorr")) { return (new MINERvA_CC1pip_XSec_1DTpi_nu(samplekey)); // DONE } else if (!name.compare("MINERvA_CC1pip_XSec_1Dth_nu") || !name.compare("MINERvA_CC1pip_XSec_1Dth_nu_20deg") || !name.compare("MINERvA_CC1pip_XSec_1Dth_nu_fluxcorr") || !name.compare("MINERvA_CC1pip_XSec_1Dth_nu_20deg_fluxcorr")) { return (new MINERvA_CC1pip_XSec_1Dth_nu(samplekey)); } else if (!name.compare("MINERvA_CC1pip_XSec_1DTpi_nu_2017") || !name.compare("MINERvA_CC1pip_XSec_1Dth_nu_2017") || !name.compare("MINERvA_CC1pip_XSec_1Dpmu_nu_2017") || !name.compare("MINERvA_CC1pip_XSec_1Dthmu_nu_2017") || !name.compare("MINERvA_CC1pip_XSec_1DQ2_nu_2017") || !name.compare("MINERvA_CC1pip_XSec_1DEnu_nu_2017")) { return (new MINERvA_CC1pip_XSec_1D_2017Update(samplekey)); /* CCNpi+ */ } else if (!name.compare("MINERvA_CCNpip_XSec_1Dth_nu") || !name.compare("MINERvA_CCNpip_XSec_1Dth_nu_2015") || !name.compare("MINERvA_CCNpip_XSec_1Dth_nu_2016") || !name.compare("MINERvA_CCNpip_XSec_1Dth_nu_2015_20deg") || !name.compare("MINERvA_CCNpip_XSec_1Dth_nu_2015_fluxcorr") || !name.compare("MINERvA_CCNpip_XSec_1Dth_nu_2015_20deg_fluxcorr")) { return (new MINERvA_CCNpip_XSec_1Dth_nu(samplekey)); } else if (!name.compare("MINERvA_CCNpip_XSec_1DTpi_nu") || !name.compare("MINERvA_CCNpip_XSec_1DTpi_nu_2015") || !name.compare("MINERvA_CCNpip_XSec_1DTpi_nu_2016") || !name.compare("MINERvA_CCNpip_XSec_1DTpi_nu_2015_20deg") || !name.compare("MINERvA_CCNpip_XSec_1DTpi_nu_2015_fluxcorr") || !name.compare( "MINERvA_CCNpip_XSec_1DTpi_nu_2015_20deg_fluxcorr")) { return (new MINERvA_CCNpip_XSec_1DTpi_nu(samplekey)); } else if (!name.compare("MINERvA_CCNpip_XSec_1Dthmu_nu")) { return (new MINERvA_CCNpip_XSec_1Dthmu_nu(samplekey)); } else if (!name.compare("MINERvA_CCNpip_XSec_1Dpmu_nu")) { return (new MINERvA_CCNpip_XSec_1Dpmu_nu(samplekey)); } else if (!name.compare("MINERvA_CCNpip_XSec_1DQ2_nu")) { return (new MINERvA_CCNpip_XSec_1DQ2_nu(samplekey)); } else if (!name.compare("MINERvA_CCNpip_XSec_1DEnu_nu")) { return (new MINERvA_CCNpip_XSec_1DEnu_nu(samplekey)); /* MINERvA CC1pi0 anti-nu */ // Done } else if (!name.compare("MINERvA_CC1pi0_XSec_1Dth_antinu") || !name.compare("MINERvA_CC1pi0_XSec_1Dth_antinu_2015") || !name.compare("MINERvA_CC1pi0_XSec_1Dth_antinu_2016") || !name.compare("MINERvA_CC1pi0_XSec_1Dth_antinu_fluxcorr") || !name.compare("MINERvA_CC1pi0_XSec_1Dth_antinu_2015_fluxcorr") || !name.compare("MINERvA_CC1pi0_XSec_1Dth_antinu_2016_fluxcorr")) { return (new MINERvA_CC1pi0_XSec_1Dth_antinu(samplekey)); } else if (!name.compare("MINERvA_CC1pi0_XSec_1Dppi0_antinu") || !name.compare("MINERvA_CC1pi0_XSec_1Dppi0_antinu_fluxcorr")) { return (new MINERvA_CC1pi0_XSec_1Dppi0_antinu(samplekey)); } else if (!name.compare("MINERvA_CC1pi0_XSec_1DTpi0_antinu")) { return (new MINERvA_CC1pi0_XSec_1DTpi0_antinu(samplekey)); // Done } else if (!name.compare("MINERvA_CC1pi0_XSec_1DQ2_antinu")) { return (new MINERvA_CC1pi0_XSec_1DQ2_antinu(samplekey)); // Done } else if (!name.compare("MINERvA_CC1pi0_XSec_1Dthmu_antinu")) { return (new MINERvA_CC1pi0_XSec_1Dthmu_antinu(samplekey)); // Done } else if (!name.compare("MINERvA_CC1pi0_XSec_1Dpmu_antinu")) { return (new MINERvA_CC1pi0_XSec_1Dpmu_antinu(samplekey)); // Done } else if (!name.compare("MINERvA_CC1pi0_XSec_1DEnu_antinu")) { return (new MINERvA_CC1pi0_XSec_1DEnu_antinu(samplekey)); // MINERvA CC1pi0 nu } else if (!name.compare("MINERvA_CC1pi0_XSec_1DTpi_nu") || !name.compare("MINERvA_CC1pi0_XSec_1Dth_nu") || !name.compare("MINERvA_CC1pi0_XSec_1Dpmu_nu") || !name.compare("MINERvA_CC1pi0_XSec_1Dthmu_nu") || !name.compare("MINERvA_CC1pi0_XSec_1DQ2_nu") || !name.compare("MINERvA_CC1pi0_XSec_1DEnu_nu") || !name.compare("MINERvA_CC1pi0_XSec_1DWexp_nu") || !name.compare("MINERvA_CC1pi0_XSec_1DPPi0Mass_nu") || !name.compare("MINERvA_CC1pi0_XSec_1DPPi0MassDelta_nu") || !name.compare("MINERvA_CC1pi0_XSec_1DCosAdler_nu") || !name.compare("MINERvA_CC1pi0_XSec_1DPhiAdler_nu")) { return (new MINERvA_CC1pi0_XSec_1D_nu(samplekey)); /* CCINC */ } else if (!name.compare("MINERvA_CCinc_XSec_2DEavq3_nu")) { return (new MINERvA_CCinc_XSec_2DEavq3_nu(samplekey)); } else if (!name.compare("MINERvA_CCinc_XSec_1Dx_ratio_C12_CH") || !name.compare("MINERvA_CCinc_XSec_1Dx_ratio_Fe56_CH") || !name.compare("MINERvA_CCinc_XSec_1Dx_ratio_Pb208_CH")) { return (new MINERvA_CCinc_XSec_1Dx_ratio(samplekey)); } else if (!name.compare("MINERvA_CCinc_XSec_1DEnu_ratio_C12_CH") || !name.compare("MINERvA_CCinc_XSec_1DEnu_ratio_Fe56_CH") || !name.compare("MINERvA_CCinc_XSec_1DEnu_ratio_Pb208_CH")) { return (new MINERvA_CCinc_XSec_1DEnu_ratio(samplekey)); /* CCDIS */ } else if (!name.compare("MINERvA_CCDIS_XSec_1Dx_ratio_C12_CH") || !name.compare("MINERvA_CCDIS_XSec_1Dx_ratio_Fe56_CH") || !name.compare("MINERvA_CCDIS_XSec_1Dx_ratio_Pb208_CH")) { return (new MINERvA_CCDIS_XSec_1Dx_ratio(samplekey)); } else if (!name.compare("MINERvA_CCDIS_XSec_1DEnu_ratio_C12_CH") || !name.compare("MINERvA_CCDIS_XSec_1DEnu_ratio_Fe56_CH") || !name.compare("MINERvA_CCDIS_XSec_1DEnu_ratio_Pb208_CH")) { return (new MINERvA_CCDIS_XSec_1DEnu_ratio(samplekey)); /* CC-COH */ } else if (!name.compare("MINERvA_CCCOHPI_XSec_1DEnu_nu")) { return (new MINERvA_CCCOHPI_XSec_1DEnu_nu(samplekey)); } else if (!name.compare("MINERvA_CCCOHPI_XSec_1DEpi_nu")) { return (new MINERvA_CCCOHPI_XSec_1DEpi_nu(samplekey)); } else if (!name.compare("MINERvA_CCCOHPI_XSec_1Dth_nu")) { return (new MINERvA_CCCOHPI_XSec_1Dth_nu(samplekey)); } else if (!name.compare("MINERvA_CCCOHPI_XSec_1DQ2_nu")) { return (new MINERvA_CCCOHPI_XSec_1DQ2_nu(samplekey)); } else if (!name.compare("MINERvA_CCCOHPI_XSec_1DEnu_antinu")) { return (new MINERvA_CCCOHPI_XSec_1DEnu_antinu(samplekey)); } else if (!name.compare("MINERvA_CCCOHPI_XSec_1DEpi_antinu")) { return (new MINERvA_CCCOHPI_XSec_1DEpi_antinu(samplekey)); } else if (!name.compare("MINERvA_CCCOHPI_XSec_1Dth_antinu")) { return (new MINERvA_CCCOHPI_XSec_1Dth_antinu(samplekey)); } else if (!name.compare("MINERvA_CCCOHPI_XSec_1DQ2_antinu")) { return (new MINERvA_CCCOHPI_XSec_1DQ2_antinu(samplekey)); } else if (!name.compare("MINERvA_CCCOHPI_XSec_1DEnu_joint")) { return (new MINERvA_CCCOHPI_XSec_joint(samplekey)); } else if (!name.compare("MINERvA_CCCOHPI_XSec_1DEpi_joint")) { return (new MINERvA_CCCOHPI_XSec_joint(samplekey)); } else if (!name.compare("MINERvA_CCCOHPI_XSec_1Dth_joint")) { return (new MINERvA_CCCOHPI_XSec_joint(samplekey)); } else if (!name.compare("MINERvA_CCCOHPI_XSec_1DQ2_joint")) { return (new MINERvA_CCCOHPI_XSec_joint(samplekey)); /* T2K Samples */ } else #endif #ifndef __NO_T2K__ if (!name.compare("T2K_CC0pi_XSec_2DPcos_nu_I")) { return (new T2K_CC0pi_XSec_2DPcos_nu_I(samplekey)); } else if (!name.compare("T2K_CC0pi_XSec_2DPcos_nu_II")) { return (new T2K_CC0pi_XSec_2DPcos_nu_II(samplekey)); } else if (!name.compare("T2K_CCinc_XSec_2DPcos_nu_nonuniform")) { return (new T2K_CCinc_XSec_2DPcos_nu_nonuniform(samplekey)); } else if (!name.compare("T2K_CC0pi_XSec_H2O_2DPcos_anu")) { return (new T2K_CC0pi_XSec_H2O_2DPcos_anu(samplekey)); } else if (!name.compare("T2K_NuMu_CC0pi_O_XSec_2DPcos") || !name.compare("T2K_NuMu_CC0pi_C_XSec_2DPcos")) { return (new T2K_NuMu_CC0pi_OC_XSec_2DPcos(samplekey)); } else if (!name.compare("T2K_NuMu_CC0pi_OC_XSec_2DPcos_joint")) { return (new T2K_NuMu_CC0pi_OC_XSec_2DPcos_joint(samplekey)); } else if (!name.compare("T2K_NuMu_CC0pi_CH_XSec_2DPcos") || !name.compare("T2K_AntiNuMu_CC0pi_CH_XSec_2DPcos")) { return (new T2K_NuMuAntiNuMu_CC0pi_CH_XSec_2DPcos(samplekey)); } else if (!name.compare("T2K_NuMuAntiNuMu_CC0pi_CH_XSec_2DPcos_joint")) { return (new T2K_NuMuAntiNuMu_CC0pi_CH_XSec_2DPcos_joint(samplekey)); } else if (!name.compare("T2K_nueCCinc_XSec_1Dpe_FHC") || !name.compare("T2K_nueCCinc_XSec_1Dpe_RHC") || !name.compare("T2K_nuebarCCinc_XSec_1Dpe_RHC")) { return (new T2K_nueCCinc_XSec_1Dpe(samplekey)); } else if (!name.compare("T2K_nueCCinc_XSec_1Dthe_FHC") || !name.compare("T2K_nueCCinc_XSec_1Dthe_RHC") || !name.compare("T2K_nuebarCCinc_XSec_1Dthe_RHC")) { return (new T2K_nueCCinc_XSec_1Dthe(samplekey)); } else if (!name.compare("T2K_nueCCinc_XSec_1Dpe_joint")) { return (new T2K_nueCCinc_XSec_1Dpe_joint(samplekey)); } else if (!name.compare("T2K_nueCCinc_XSec_1Dthe_joint")) { return (new T2K_nueCCinc_XSec_1Dthe_joint(samplekey)); } else if (!name.compare("T2K_nueCCinc_XSec_joint")) { return (new T2K_nueCCinc_XSec_joint(samplekey)); /* T2K CC1pi+ CH samples */ // Comment these out for now because we don't have the proper data } else if (!name.compare("T2K_CC1pip_CH_XSec_2Dpmucosmu_nu")) { return (new T2K_CC1pip_CH_XSec_2Dpmucosmu_nu(samplekey)); } else if (!name.compare("T2K_CC1pip_CH_XSec_1Dppi_nu")) { return (new T2K_CC1pip_CH_XSec_1Dppi_nu(samplekey)); } else if (!name.compare("T2K_CC1pip_CH_XSec_1Dthpi_nu")) { return (new T2K_CC1pip_CH_XSec_1Dthpi_nu(samplekey)); } else if (!name.compare("T2K_CC1pip_CH_XSec_1Dthmupi_nu")) { return (new T2K_CC1pip_CH_XSec_1Dthmupi_nu(samplekey)); } else if (!name.compare("T2K_CC1pip_CH_XSec_1DQ2_nu")) { return (new T2K_CC1pip_CH_XSec_1DQ2_nu(samplekey)); } else if (!name.compare("T2K_CC1pip_CH_XSec_1DAdlerPhi_nu")) { return (new T2K_CC1pip_CH_XSec_1DAdlerPhi_nu(samplekey)); } else if (!name.compare("T2K_CC1pip_CH_XSec_1DCosThAdler_nu")) { return (new T2K_CC1pip_CH_XSec_1DCosThAdler_nu(samplekey)); /* T2K CC1pi+ H2O samples */ } else if (!name.compare("T2K_CC1pip_H2O_XSec_1DEnuDelta_nu")) { return (new T2K_CC1pip_H2O_XSec_1DEnuDelta_nu(samplekey)); } else if (!name.compare("T2K_CC1pip_H2O_XSec_1DEnuMB_nu")) { return (new T2K_CC1pip_H2O_XSec_1DEnuMB_nu(samplekey)); } else if (!name.compare("T2K_CC1pip_H2O_XSec_1Dcosmu_nu")) { return (new T2K_CC1pip_H2O_XSec_1Dcosmu_nu(samplekey)); } else if (!name.compare("T2K_CC1pip_H2O_XSec_1Dcosmupi_nu")) { return (new T2K_CC1pip_H2O_XSec_1Dcosmupi_nu(samplekey)); } else if (!name.compare("T2K_CC1pip_H2O_XSec_1Dcospi_nu")) { return (new T2K_CC1pip_H2O_XSec_1Dcospi_nu(samplekey)); } else if (!name.compare("T2K_CC1pip_H2O_XSec_1Dpmu_nu")) { return (new T2K_CC1pip_H2O_XSec_1Dpmu_nu(samplekey)); } else if (!name.compare("T2K_CC1pip_H2O_XSec_1Dppi_nu")) { return (new T2K_CC1pip_H2O_XSec_1Dppi_nu(samplekey)); /* T2K CC0pi + np CH samples */ } else if (!name.compare("T2K_CC0pinp_STV_XSec_1Ddpt_nu")) { return (new T2K_CC0pinp_STV_XSec_1Ddpt_nu(samplekey)); } else if (!name.compare("T2K_CC0pinp_STV_XSec_1Ddphit_nu")) { return (new T2K_CC0pinp_STV_XSec_1Ddphit_nu(samplekey)); } else if (!name.compare("T2K_CC0pinp_STV_XSec_1Ddat_nu")) { return (new T2K_CC0pinp_STV_XSec_1Ddat_nu(samplekey)); } else if (!name.compare("T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np") || !name.compare("T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p") || !name.compare("T2K_CC0piWithProtons_XSec_2018_multidif_0p") || !name.compare("T2K_CC0piWithProtons_XSec_2018_multidif_1p")) { return (new T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np(samplekey)); } else if (!name.compare("T2K_CC0pinp_ifk_XSec_3Dinfp_nu")) { return (new T2K_CC0pinp_ifk_XSec_3Dinfp_nu(samplekey)); } else if (!name.compare("T2K_CC0pinp_ifk_XSec_3Dinfa_nu")) { return (new T2K_CC0pinp_ifk_XSec_3Dinfa_nu(samplekey)); } else if (!name.compare("T2K_CC0pinp_ifk_XSec_3Dinfip_nu")) { return (new T2K_CC0pinp_ifk_XSec_3Dinfip_nu(samplekey)); // SciBooNE COH studies } else #endif #ifndef __NO_SciBooNE__ if (!name.compare("SciBooNE_CCCOH_STOP_NTrks_nu")) { return (new SciBooNE_CCCOH_STOP_NTrks_nu(samplekey)); } else if (!name.compare("SciBooNE_CCCOH_1TRK_1DQ2_nu")) { return (new SciBooNE_CCCOH_1TRK_1DQ2_nu(samplekey)); } else if (!name.compare("SciBooNE_CCCOH_1TRK_1Dpmu_nu")) { return (new SciBooNE_CCCOH_1TRK_1Dpmu_nu(samplekey)); } else if (!name.compare("SciBooNE_CCCOH_1TRK_1Dthetamu_nu")) { return (new SciBooNE_CCCOH_1TRK_1Dthetamu_nu(samplekey)); } else if (!name.compare("SciBooNE_CCCOH_MuPr_1DQ2_nu")) { return (new SciBooNE_CCCOH_MuPr_1DQ2_nu(samplekey)); } else if (!name.compare("SciBooNE_CCCOH_MuPr_1Dpmu_nu")) { return (new SciBooNE_CCCOH_MuPr_1Dpmu_nu(samplekey)); } else if (!name.compare("SciBooNE_CCCOH_MuPr_1Dthetamu_nu")) { return (new SciBooNE_CCCOH_MuPr_1Dthetamu_nu(samplekey)); } else if (!name.compare("SciBooNE_CCCOH_MuPiVA_1DQ2_nu")) { return (new SciBooNE_CCCOH_MuPiVA_1DQ2_nu(samplekey)); } else if (!name.compare("SciBooNE_CCCOH_MuPiVA_1Dpmu_nu")) { return (new SciBooNE_CCCOH_MuPiVA_1Dpmu_nu(samplekey)); } else if (!name.compare("SciBooNE_CCCOH_MuPiVA_1Dthetamu_nu")) { return (new SciBooNE_CCCOH_MuPiVA_1Dthetamu_nu(samplekey)); } else if (!name.compare("SciBooNE_CCCOH_MuPiNoVA_1DQ2_nu")) { return (new SciBooNE_CCCOH_MuPiNoVA_1DQ2_nu(samplekey)); } else if (!name.compare("SciBooNE_CCCOH_MuPiNoVA_1Dthetapr_nu")) { return (new SciBooNE_CCCOH_MuPiNoVA_1Dthetapr_nu(samplekey)); } else if (!name.compare("SciBooNE_CCCOH_MuPiNoVA_1Dthetapi_nu")) { return (new SciBooNE_CCCOH_MuPiNoVA_1Dthetapi_nu(samplekey)); } else if (!name.compare("SciBooNE_CCCOH_MuPiNoVA_1Dthetamu_nu")) { return (new SciBooNE_CCCOH_MuPiNoVA_1Dthetamu_nu(samplekey)); } else if (!name.compare("SciBooNE_CCCOH_MuPiNoVA_1Dpmu_nu")) { return (new SciBooNE_CCCOH_MuPiNoVA_1Dpmu_nu(samplekey)); } else if (!name.compare("SciBooNE_CCCOH_STOPFINAL_1DQ2_nu")) { return (new SciBooNE_CCCOH_STOPFINAL_1DQ2_nu(samplekey)); } else if (!name.compare("SciBooNE_CCInc_XSec_1DEnu_nu") || !name.compare("SciBooNE_CCInc_XSec_1DEnu_nu_NEUT") || !name.compare("SciBooNE_CCInc_XSec_1DEnu_nu_NUANCE")) { return (new SciBooNE_CCInc_XSec_1DEnu_nu(samplekey)); /* K2K Samples */ /* NC1pi0 */ } else #endif #ifndef __NO_K2K__ if (!name.compare("K2K_NC1pi0_Evt_1Dppi0_nu")) { return (new K2K_NC1pi0_Evt_1Dppi0_nu(samplekey)); /* Fake Studies */ } else #endif if (name.find("ExpMultDist_CCQE_XSec_1D") != std::string::npos && name.find("_FakeStudy") != std::string::npos) { return ( new ExpMultDist_CCQE_XSec_1DVar_FakeStudy(name, file, rw, type, fkdt)); } else if (name.find("ExpMultDist_CCQE_XSec_2D") != std::string::npos && name.find("_FakeStudy") != std::string::npos) { return ( new ExpMultDist_CCQE_XSec_2DVar_FakeStudy(name, file, rw, type, fkdt)); - } else if (name.find("GenericFlux_") != std::string::npos) { + } else if (name.find("GenericFlux") != std::string::npos) { return (new GenericFlux_Tester(name, file, rw, type, fkdt)); - } else if (name.find("GenericVectors_") != std::string::npos) { + } else if (name.find("GenericVectors") != std::string::npos) { return (new GenericFlux_Vectors(name, file, rw, type, fkdt)); } else if (!name.compare("T2K2017_FakeData")) { return (new T2K2017_FakeData(samplekey)); } else if (!name.compare("MCStudy_CCQE")) { return (new MCStudy_CCQEHistograms(name, file, rw, type, fkdt)); } else if (!name.compare("ElectronFlux_FlatTree")) { return (new ElectronFlux_FlatTree(name, file, rw, type, fkdt)); } else if (name.find("ElectronData_") != std::string::npos) { return new ElectronScattering_DurhamData(samplekey); } else if (name.find("MuonValidation_") != std::string::npos) { return (new MCStudy_MuonValidation(name, file, rw, type, fkdt)); } else if (!name.compare("NIWGOfficialPlots")) { return (new OfficialNIWGPlots(samplekey)); } else if ((name.find("SigmaEnuHists") != std::string::npos) || (name.find("SigmaEnuPerEHists") != std::string::npos)) { return (new SigmaEnuHists(samplekey)); } else if (!name.compare("Simple_Osc")) { return (new Simple_Osc(samplekey)); } else if (!name.compare("Smear_SVDUnfold_Propagation_Osc")) { return (new Smear_SVDUnfold_Propagation_Osc(samplekey)); } else { NUIS_ABORT("Error: No such sample: " << name << std::endl); } // Return NULL if no sample loaded. return NULL; } // namespace SampleUtils } // namespace SampleUtils diff --git a/src/FitBase/JointMeas1D.cxx b/src/FitBase/JointMeas1D.cxx index 6d95edb..c68e674 100644 --- a/src/FitBase/JointMeas1D.cxx +++ b/src/FitBase/JointMeas1D.cxx @@ -1,2222 +1,2222 @@ // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret /******************************************************************************* * This ile 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 "JointMeas1D.h" //******************************************************************** JointMeas1D::JointMeas1D(void) { //******************************************************************** // XSec Scalings fScaleFactor = -1.0; fCurrentNorm = 1.0; // Histograms fDataHist = NULL; fDataTrue = NULL; fMCHist = NULL; fMCFine = NULL; fMCWeighted = NULL; fMaskHist = NULL; // Covar covar = NULL; fFullCovar = NULL; fCovar = NULL; fInvert = NULL; fDecomp = NULL; // Fake Data fFakeDataInput = ""; fFakeDataFile = NULL; // Options fDefaultTypes = "FIX/FULL/CHI2"; fAllowedTypes = "FIX,FREE,SHAPE/FULL,DIAG/CHI2/NORM/ENUCORR/Q2CORR/ENU1D/MASK"; fIsFix = false; fIsShape = false; fIsFree = false; fIsDiag = false; fIsFull = false; fAddNormPen = false; fIsMask = false; fIsChi2SVD = false; fIsRawEvents = false; fIsDifXSec = false; fIsEnu1D = false; // Inputs fInput = NULL; fRW = NULL; // Extra Histograms fMCHist_Modes = NULL; for (std::vector::const_iterator iter = fSubChain.begin(); iter != fSubChain.end(); iter++) { MeasurementBase *exp = *iter; if (exp) delete exp; } fSubChain.clear(); // Flags for Joint Measurements fIsRatio = false; fIsSummed = false; fSaveSubMeas = false; fIsJoint = true; } //******************************************************************** void JointMeas1D::SetupDefaultHist() { //******************************************************************** // Setup fMCHist fMCHist = (TH1D *)fDataHist->Clone(); fMCHist->SetNameTitle((fName + "_MC").c_str(), (fName + "_MC" + fPlotTitles).c_str()); // Setup fMCFine Int_t nBins = fMCHist->GetNbinsX(); fMCFine = new TH1D( (fName + "_MC_FINE").c_str(), (fName + "_MC_FINE" + fPlotTitles).c_str(), nBins * 6, fMCHist->GetBinLowEdge(1), fMCHist->GetBinLowEdge(nBins + 1)); fMCStat = (TH1D *)fMCHist->Clone(); fMCStat->Reset(); fMCHist->Reset(); fMCFine->Reset(); // Setup the NEUT Mode Array PlotUtils::CreateNeutModeArray((TH1D *)fMCHist, (TH1 **)fMCHist_PDG); PlotUtils::ResetNeutModeArray((TH1 **)fMCHist_PDG); // Setup bin masks using sample name if (fIsMask) { std::string maskloc = FitPar::Config().GetParDIR(fName + ".mask"); if (maskloc.empty()) { maskloc = FitPar::GetDataBase() + "/masks/" + fName + ".mask"; } SetBinMask(maskloc); } fMCHist_Modes = new TrueModeStack((fName + "_MODES").c_str(), ("True Channels"), fMCHist); SetAutoProcessTH1(fMCHist_Modes); return; } //******************************************************************** JointMeas1D::~JointMeas1D(void) { //******************************************************************** if (fDataHist) delete fDataHist; if (fDataTrue) delete fDataTrue; if (fMCHist) delete fMCHist; if (fMCFine) delete fMCFine; if (fMCWeighted) delete fMCWeighted; if (fMaskHist) delete fMaskHist; if (covar) delete covar; if (fFullCovar) delete fFullCovar; if (fCovar) delete fCovar; if (fInvert) delete fInvert; if (fDecomp) delete fDecomp; for (std::vector::const_iterator iter = fSubChain.begin(); iter != fSubChain.end(); iter++) { MeasurementBase *exp = *iter; if (exp) delete exp; } fSubChain.clear(); } //******************************************************************** SampleSettings JointMeas1D::LoadSampleSettings(nuiskey samplekey) { //******************************************************************** SampleSettings s = MeasurementBase::LoadSampleSettings(samplekey); // Parse Inputs fSubInFiles.clear(); std::vector entries = GeneralUtils::ParseToStr(s.GetS("input"), ";"); if (entries.size() < 2) { NUIS_ABORT("Joint measurement expected to recieve at least two semi-colon " "separated input files, but recieved: \"" << s.GetS("input") << "\""); } std::vector first_file_descriptor = GeneralUtils::ParseToStr(entries.front(), ":"); if (first_file_descriptor.size() != 2) { NUIS_ABORT("Found Joint measurement where the input file had no type: \"" << s.GetS("input") << "\", expected \"INPUTTYPE:File.root;File2.root\"."); } std::string inpType = first_file_descriptor[0]; for (std::vector::iterator iter = entries.begin(); iter != entries.end(); iter++) { if (GeneralUtils::ParseToStr(*iter, ":").size() != 2) { std::stringstream ss(""); ss << inpType << ":" << (*iter); fSubInFiles.push_back(ss.str()); } else { fSubInFiles.push_back(*iter); } } return s; } //******************************************************************** void JointMeas1D::FinaliseSampleSettings() { //******************************************************************** // Setup naming + renaming fName = fSettings.GetName(); fSettings.SetS("originalname", fName); if (fSettings.Has("rename")) { fName = fSettings.GetS("rename"); fSettings.SetS("name", fName); } // Setup all other options NUIS_LOG(SAM, "Finalising Sample Settings: " << fName); if ((fSettings.GetS("originalname").find("Evt") != std::string::npos)) { fIsRawEvents = true; NUIS_LOG(SAM, "Found event rate measurement but using poisson likelihoods."); } if (fSettings.GetS("originalname").find("XSec_1DEnu") != std::string::npos) { fIsEnu1D = true; NUIS_LOG(SAM, "::" << fName << "::"); NUIS_LOG(SAM, "Found XSec Enu measurement, applying flux integrated scaling, " << "not flux averaged!"); } if (fIsEnu1D && fIsRawEvents) { NUIS_LOG(SAM, "Found 1D Enu XSec distribution AND fIsRawEvents, is this " "really correct?!"); NUIS_LOG(SAM, "Check experiment constructor for " << fName << " and correct this!"); NUIS_LOG(SAM, "I live in " << __FILE__ << ":" << __LINE__); exit(-1); } // Parse Inputs fSubInFiles.clear(); std::vector entries = GeneralUtils::ParseToStr(fSettings.GetS("input"), ";"); if (entries.size() < 2) { NUIS_ABORT("Joint measurement expected to recieve at least two semi-colon " "separated input files, but recieved: \"" << fSettings.GetS("input") << "\""); } std::vector first_file_descriptor = GeneralUtils::ParseToStr(entries.front(), ":"); if (first_file_descriptor.size() != 2) { NUIS_ABORT("Found Joint measurement where the input file had no type: \"" << fSettings.GetS("input") << "\", expected \"INPUTTYPE:File.root;File2.root\"."); } std::string inpType = first_file_descriptor[0]; for (std::vector::iterator iter = entries.begin(); iter != entries.end(); iter++) { if (GeneralUtils::ParseToStr(*iter, ":").size() != 2) { std::stringstream ss(""); ss << inpType << ":" << (*iter); fSubInFiles.push_back(ss.str()); } else { fSubInFiles.push_back(*iter); } } // Setup options SetFitOptions(fDefaultTypes); // defaults SetFitOptions(fSettings.GetS("type")); // user specified EnuMin = GeneralUtils::StrToDbl(fSettings.GetS("enu_min")); EnuMax = GeneralUtils::StrToDbl(fSettings.GetS("enu_max")); if (fAddNormPen) { if (fNormError <= 0.0) { NUIS_ERR(FTL, "Norm error for class " << fName << " is 0.0!"); NUIS_ERR(FTL, "If you want to use it please add fNormError=VAL"); throw; } } if (!fRW) fRW = FitBase::GetRW(); NUIS_LOG(SAM, "Finalised Sample Settings"); } //******************************************************************** void JointMeas1D::SetDataFromTextFile(std::string datafile) { //******************************************************************** NUIS_LOG(SAM, "Reading data from text file: " << datafile); fDataHist = PlotUtils::GetTH1DFromFile( datafile, fSettings.GetName() + "_data", fSettings.GetFullTitles()); } //******************************************************************** void JointMeas1D::SetDataFromRootFile(std::string datafile, std::string histname) { //******************************************************************** NUIS_LOG(SAM, "Reading data from root file: " << datafile << ";" << histname); fDataHist = PlotUtils::GetTH1DFromRootFile(datafile, histname); fDataHist->SetNameTitle((fSettings.GetName() + "_data").c_str(), (fSettings.GetFullTitles()).c_str()); return; }; //******************************************************************** void JointMeas1D::SetPoissonErrors() { //******************************************************************** if (!fDataHist) { NUIS_ERR(FTL, "Need a data hist to setup possion errors! "); NUIS_ABORT("Setup Data First!"); } for (int i = 0; i < fDataHist->GetNbinsX() + 1; i++) { fDataHist->SetBinError(i + 1, sqrt(fDataHist->GetBinContent(i + 1))); } } //******************************************************************** void JointMeas1D::SetCovarFromDiagonal(TH1D *data) { //******************************************************************** if (!data and fDataHist) { data = fDataHist; } if (data) { NUIS_LOG(SAM, "Setting diagonal covariance for: " << data->GetName()); fFullCovar = StatUtils::MakeDiagonalCovarMatrix(data); covar = StatUtils::GetInvert(fFullCovar,true); fDecomp = StatUtils::GetDecomp(fFullCovar); } else { NUIS_ERR(FTL, "No data input provided to set diagonal covar from!"); } if (!fIsDiag) { NUIS_ERR(FTL, "SetCovarMatrixFromDiag called for measurement " << "that is not set as diagonal."); throw; } } //******************************************************************** void JointMeas1D::SetCovarFromTextFile(std::string covfile, int dim) { //******************************************************************** NUIS_LOG(SAM, "Reading covariance from text file: " << covfile); fFullCovar = StatUtils::GetCovarFromTextFile(covfile, dim); covar = StatUtils::GetInvert(fFullCovar,true); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void JointMeas1D::SetCovarFromMultipleTextFiles(std::string covfiles, int dim) { //******************************************************************** if (dim == -1) { dim = fDataHist->GetNbinsX(); } std::vector covList = GeneralUtils::ParseToStr(covfiles, ";"); fFullCovar = new TMatrixDSym(dim); for (uint i = 0; i < covList.size(); ++i) { NUIS_LOG(SAM, "Reading covariance from text file: " << covList[i]); TMatrixDSym *temp_cov = StatUtils::GetCovarFromTextFile(covList[i], dim); (*fFullCovar) += (*temp_cov); delete temp_cov; } covar = StatUtils::GetInvert(fFullCovar,true); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void JointMeas1D::SetCovarFromRootFile(std::string covfile, std::string histname) { //******************************************************************** NUIS_LOG(SAM, "Reading covariance from text file: " << covfile << ";" << histname); fFullCovar = StatUtils::GetCovarFromRootFile(covfile, histname); covar = StatUtils::GetInvert(fFullCovar,true); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void JointMeas1D::SetCovarInvertFromTextFile(std::string covfile, int dim) { //******************************************************************** NUIS_LOG(SAM, "Reading inverted covariance from text file: " << covfile); covar = StatUtils::GetCovarFromTextFile(covfile, dim); fFullCovar = StatUtils::GetInvert(covar,true); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void JointMeas1D::SetCovarInvertFromRootFile(std::string covfile, std::string histname) { //******************************************************************** NUIS_LOG(SAM, "Reading inverted covariance from text file: " << covfile << ";" << histname); covar = StatUtils::GetCovarFromRootFile(covfile, histname); fFullCovar = StatUtils::GetInvert(covar,true); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void JointMeas1D::SetCorrelationFromTextFile(std::string covfile, int dim) { //******************************************************************** if (dim == -1) dim = fDataHist->GetNbinsX(); NUIS_LOG(SAM, "Reading data correlations from text file: " << covfile << ";" << dim); TMatrixDSym *correlation = StatUtils::GetCovarFromTextFile(covfile, dim); if (!fDataHist) { NUIS_ABORT("Trying to set correlations from text file but there is no " "data to build it from. \n" << "In constructor make sure data is set before " "SetCorrelationFromTextFile is called. \n"); } // Fill covar from data errors and correlations fFullCovar = new TMatrixDSym(dim); for (int i = 0; i < fDataHist->GetNbinsX(); i++) { for (int j = 0; j < fDataHist->GetNbinsX(); j++) { (*fFullCovar)(i, j) = (*correlation)(i, j) * fDataHist->GetBinError(i + 1) * fDataHist->GetBinError(j + 1) * 1.E76; } } // Fill other covars. covar = StatUtils::GetInvert(fFullCovar,true); fDecomp = StatUtils::GetDecomp(fFullCovar); delete correlation; } //******************************************************************** void JointMeas1D::SetCorrelationFromMultipleTextFiles(std::string corrfiles, int dim) { //******************************************************************** if (dim == -1) { dim = fDataHist->GetNbinsX(); } std::vector corrList = GeneralUtils::ParseToStr(corrfiles, ";"); fFullCovar = new TMatrixDSym(dim); for (uint i = 0; i < corrList.size(); ++i) { NUIS_LOG(SAM, "Reading covariance from text file: " << corrList[i]); TMatrixDSym *temp_cov = StatUtils::GetCovarFromTextFile(corrList[i], dim); for (int i = 0; i < fDataHist->GetNbinsX(); i++) { for (int j = 0; j < fDataHist->GetNbinsX(); j++) { // Note that there is a factor of 1E76 here. It is very silly indeed. // However, if you remove it, you also need to fix the factors of 1E38 // added to the chi2 calculations! (*temp_cov)(i, j) = (*temp_cov)(i, j) * fDataHist->GetBinError(i + 1) * fDataHist->GetBinError(j + 1) * 1E76; } } (*fFullCovar) += (*temp_cov); delete temp_cov; } covar = StatUtils::GetInvert(fFullCovar,true); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void JointMeas1D::SetCorrelationFromRootFile(std::string covfile, std::string histname) { //******************************************************************** NUIS_LOG(SAM, "Reading data correlations from text file: " << covfile << ";" << histname); TMatrixDSym *correlation = StatUtils::GetCovarFromRootFile(covfile, histname); if (!fDataHist) { NUIS_ABORT("Trying to set correlations from text file but there is no " "data to build it from. \n" << "In constructor make sure data is set before " "SetCorrelationFromTextFile is called. \n"); } // Fill covar from data errors and correlations fFullCovar = new TMatrixDSym(fDataHist->GetNbinsX()); for (int i = 0; i < fDataHist->GetNbinsX(); i++) { for (int j = 0; j < fDataHist->GetNbinsX(); j++) { (*fFullCovar)(i, j) = (*correlation)(i, j) * fDataHist->GetBinError(i + 1) * fDataHist->GetBinError(j + 1) * 1.E76; } } // Fill other covars. covar = StatUtils::GetInvert(fFullCovar,true); fDecomp = StatUtils::GetDecomp(fFullCovar); delete correlation; } void JointMeas1D::SetShapeCovar() { // Return if this is missing any pre-requisites if (!fFullCovar) return; if (!fDataHist) return; // Also return if it's bloody stupid under the circumstances if (fIsDiag) return; fShapeCovar = StatUtils::ExtractShapeOnlyCovar(fFullCovar, fDataHist); return; } //******************************************************************** void JointMeas1D::SetCholDecompFromTextFile(std::string covfile, int dim) { //******************************************************************** NUIS_LOG(SAM, "Reading cholesky from text file: " << covfile); TMatrixD *temp = StatUtils::GetMatrixFromTextFile(covfile, dim, dim); TMatrixD *trans = (TMatrixD *)temp->Clone(); trans->T(); (*trans) *= (*temp); fFullCovar = new TMatrixDSym(dim, trans->GetMatrixArray(), ""); covar = StatUtils::GetInvert(fFullCovar,true); fDecomp = StatUtils::GetDecomp(fFullCovar); delete temp; delete trans; } //******************************************************************** void JointMeas1D::SetCholDecompFromRootFile(std::string covfile, std::string histname) { //******************************************************************** NUIS_LOG(SAM, "Reading cholesky decomp from root file: " << covfile << ";" << histname); TMatrixD *temp = StatUtils::GetMatrixFromRootFile(covfile, histname); TMatrixD *trans = (TMatrixD *)temp->Clone(); trans->T(); (*trans) *= (*temp); fFullCovar = new TMatrixDSym(temp->GetNrows(), trans->GetMatrixArray(), ""); covar = StatUtils::GetInvert(fFullCovar,true); fDecomp = StatUtils::GetDecomp(fFullCovar); delete temp; delete trans; } //******************************************************************** void JointMeas1D::ScaleData(double scale) { //******************************************************************** fDataHist->Scale(scale); } //******************************************************************** void JointMeas1D::ScaleCovar(double scale) { //******************************************************************** (*fFullCovar) *= scale; (*covar) *= 1.0 / scale; (*fDecomp) *= sqrt(scale); } //******************************************************************** void JointMeas1D::SetBinMask(std::string maskfile) { //******************************************************************** if (!fIsMask) return; NUIS_LOG(SAM, "Reading bin mask from file: " << maskfile); // Create a mask histogram with dim of data int nbins = fDataHist->GetNbinsX(); fMaskHist = new TH1I((fSettings.GetName() + "_BINMASK").c_str(), (fSettings.GetName() + "_BINMASK; Bin; Mask?").c_str(), nbins, 0, nbins); std::string line; std::ifstream mask(maskfile.c_str(), std::ifstream::in); if (!mask.is_open()) { NUIS_ABORT(" Cannot find mask file: " << maskfile); } while (std::getline(mask >> std::ws, line, '\n')) { std::vector entries = GeneralUtils::ParseToInt(line, " "); // Skip lines with poorly formatted lines if (entries.size() < 2) { NUIS_LOG(WRN, "JointMeas1D::SetBinMask(), couldn't parse line: " << line); continue; } // The first index should be the bin number, the second should be the mask // value. int val = 0; if (entries[1] > 0) val = 1; fMaskHist->SetBinContent(entries[0], val); } // Apply masking by setting masked data bins to zero PlotUtils::MaskBins(fDataHist, fMaskHist); return; } //******************************************************************** void JointMeas1D::FinaliseMeasurement() { //******************************************************************** NUIS_LOG(SAM, "Finalising Measurement: " << fName); // Make sure data is setup if (!fDataHist) { NUIS_ABORT("No data has been setup inside " << fName << " constructor!"); } // Make sure covariances are setup if (!fFullCovar) { fIsDiag = true; SetCovarFromDiagonal(fDataHist); } if (!covar) { covar = StatUtils::GetInvert(fFullCovar,true); } if (!fDecomp) { fDecomp = StatUtils::GetDecomp(fFullCovar); } // Push the diagonals of fFullCovar onto the data histogram // Comment out until scaling is used consistently... StatUtils::SetDataErrorFromCov(fDataHist, fFullCovar, 1E-38); // Setup fMCHist from data fMCHist = (TH1D *)fDataHist->Clone(); fMCHist->SetNameTitle((fSettings.GetName() + "_MC").c_str(), (fSettings.GetFullTitles()).c_str()); fMCHist->Reset(); // Setup fMCFine fMCFine = new TH1D("mcfine", "mcfine", fDataHist->GetNbinsX(), fMCHist->GetBinLowEdge(1), fMCHist->GetBinLowEdge(fDataHist->GetNbinsX() + 1)); fMCFine->SetNameTitle((fSettings.GetName() + "_MC_FINE").c_str(), (fSettings.GetFullTitles()).c_str()); fMCFine->Reset(); // Setup MC Stat fMCStat = (TH1D *)fMCHist->Clone(); fMCStat->Reset(); // Search drawopts for possible types to include by default std::string drawopts = FitPar::Config().GetParS("drawopts"); if (drawopts.find("MODES") != std::string::npos) { fMCHist_Modes = new TrueModeStack((fSettings.GetName() + "_MODES").c_str(), ("True Channels"), fMCHist); SetAutoProcessTH1(fMCHist_Modes); } // Setup bin masks using sample name if (fIsMask) { std::string curname = fName; std::string origname = fSettings.GetS("originalname"); // Check rename.mask std::string maskloc = FitPar::Config().GetParDIR(curname + ".mask"); // Check origname.mask if (maskloc.empty()) maskloc = FitPar::Config().GetParDIR(origname + ".mask"); // Check database if (maskloc.empty()) { maskloc = FitPar::GetDataBase() + "/masks/" + origname + ".mask"; } // Setup Bin Mask SetBinMask(maskloc); } /* if (fScaleFactor < 0) { ERR(FTL) << "I found a negative fScaleFactor in " << __FILE__ << ":" << __LINE__ << std::endl; ERR(FTL) << "fScaleFactor = " << fScaleFactor << std::endl; ERR(FTL) << "EXITING" << std::endl; throw; } */ // Create and fill Weighted Histogram if (!fMCWeighted) { fMCWeighted = (TH1D *)fMCHist->Clone(); fMCWeighted->SetNameTitle((fName + "_MCWGHTS").c_str(), (fName + "_MCWGHTS" + fPlotTitles).c_str()); fMCWeighted->GetYaxis()->SetTitle("Weighted Events"); } } //******************************************************************** void JointMeas1D::SetFitOptions(std::string opt) { //******************************************************************** // Do nothing if default given if (opt == "DEFAULT") return; // CHECK Conflicting Fit Options std::vector fit_option_allow = GeneralUtils::ParseToStr(fAllowedTypes, "/"); for (UInt_t i = 0; i < fit_option_allow.size(); i++) { std::vector fit_option_section = GeneralUtils::ParseToStr(fit_option_allow.at(i), ","); bool found_option = false; for (UInt_t j = 0; j < fit_option_section.size(); j++) { std::string av_opt = fit_option_section.at(j); if (!found_option and opt.find(av_opt) != std::string::npos) { found_option = true; } else if (found_option and opt.find(av_opt) != std::string::npos) { NUIS_ABORT("ERROR: Conflicting fit options provided: " << opt << std::endl << "Conflicting group = " << fit_option_section.at(i) << std::endl << "You should only supply one of these options in card file."); } } } // Check all options are allowed std::vector fit_options_input = GeneralUtils::ParseToStr(opt, "/"); for (UInt_t i = 0; i < fit_options_input.size(); i++) { if (fAllowedTypes.find(fit_options_input.at(i)) == std::string::npos) { NUIS_ERR(FTL, "ERROR: Fit Option '" << fit_options_input.at(i) << "' Provided is not allowed for this measurement."); - NUIS_ERR(FTL, "Fit Options should be provided as a '/' seperated list " + NUIS_ERR(FTL, "Fit Options should be provided as a '/' separated list " "(e.g. FREE/DIAG/NORM)"); NUIS_ERR(FTL, "Available options for " << fName << " are '" << fAllowedTypes << "'"); throw; } } // Set TYPE fFitType = opt; // FIX,SHAPE,FREE if (opt.find("FIX") != std::string::npos) { fIsFree = fIsShape = false; fIsFix = true; } else if (opt.find("SHAPE") != std::string::npos) { fIsFree = fIsFix = false; fIsShape = true; } else if (opt.find("FREE") != std::string::npos) { fIsFix = fIsShape = false; fIsFree = true; } // DIAG,FULL (or default to full) if (opt.find("DIAG") != std::string::npos) { fIsDiag = true; fIsFull = false; } else if (opt.find("FULL") != std::string::npos) { fIsDiag = false; fIsFull = true; } // CHI2/LL (OTHERS?) if (opt.find("LOG") != std::string::npos) { fIsChi2 = false; NUIS_ERR(FTL, "No other LIKELIHOODS properly supported!"); NUIS_ERR(FTL, "Try to use a chi2!"); throw; } else { fIsChi2 = true; } // EXTRAS if (opt.find("RAW") != std::string::npos) fIsRawEvents = true; if (opt.find("DIF") != std::string::npos) fIsDifXSec = true; if (opt.find("ENU1D") != std::string::npos) fIsEnu1D = true; if (opt.find("NORM") != std::string::npos) fAddNormPen = true; if (opt.find("MASK") != std::string::npos) fIsMask = true; return; }; //******************************************************************** void JointMeas1D::SetSmearingMatrix(std::string smearfile, int truedim, int recodim) { //******************************************************************** // The smearing matrix describes the migration from true bins (rows) to reco // bins (columns) // Counter over the true bins! int row = 0; std::string line; std::ifstream smear(smearfile.c_str(), std::ifstream::in); // Note that the smearing matrix may be rectangular. fSmearMatrix = new TMatrixD(truedim, recodim); if (smear.is_open()) { NUIS_LOG(SAM, "Reading smearing matrix from file: " << smearfile); } else { NUIS_ABORT("Smearing matrix provided is incorrect: " << smearfile); } while (std::getline(smear >> std::ws, line, '\n')) { int column = 0; std::vector entries = GeneralUtils::ParseToDbl(line, " "); for (std::vector::iterator iter = entries.begin(); iter != entries.end(); iter++) { (*fSmearMatrix)(row, column) = (*iter) / 100.; // Convert to fraction from // percentage (this may not be // general enough) column++; } row++; } return; } //******************************************************************** void JointMeas1D::ApplySmearingMatrix() { //******************************************************************** if (!fSmearMatrix) { NUIS_ERR(WRN, fName << ": attempted to apply smearing matrix, but none was set"); return; } TH1D *unsmeared = (TH1D *)fMCHist->Clone(); TH1D *smeared = (TH1D *)fMCHist->Clone(); smeared->Reset(); // Loop over reconstructed bins // true = row; reco = column for (int rbin = 0; rbin < fSmearMatrix->GetNcols(); ++rbin) { // Sum up the constributions from all true bins double rBinVal = 0; // Loop over true bins for (int tbin = 0; tbin < fSmearMatrix->GetNrows(); ++tbin) { rBinVal += (*fSmearMatrix)(tbin, rbin) * unsmeared->GetBinContent(tbin + 1); } smeared->SetBinContent(rbin + 1, rBinVal); } fMCHist = (TH1D *)smeared->Clone(); return; } /* Reconfigure LOOP */ //******************************************************************** void JointMeas1D::ResetAll() { //******************************************************************** fMCHist->Reset(); fMCFine->Reset(); fMCStat->Reset(); return; }; //******************************************************************** void JointMeas1D::FillHistograms() { //******************************************************************** if (Signal) { fMCHist->Fill(fXVar, Weight); fMCFine->Fill(fXVar, Weight); fMCStat->Fill(fXVar, 1.0); if (fMCHist_Modes) fMCHist_Modes->Fill(Mode, fXVar, Weight); } return; }; //******************************************************************** void JointMeas1D::ScaleEvents() { //******************************************************************** NUIS_LOG(FIT, "Scaling JointMeas1D"); // Fill MCWeighted; for (int i = 0; i < fMCHist->GetNbinsX(); i++) { fMCWeighted->SetBinContent(i + 1, fMCHist->GetBinContent(i + 1)); fMCWeighted->SetBinError(i + 1, fMCHist->GetBinError(i + 1)); } // Setup Stat ratios for MC and MC Fine double *statratio = new double[fMCHist->GetNbinsX()]; for (int i = 0; i < fMCHist->GetNbinsX(); i++) { if (fMCHist->GetBinContent(i + 1) != 0) { statratio[i] = fMCHist->GetBinError(i + 1) / fMCHist->GetBinContent(i + 1); } else { statratio[i] = 0.0; } } double *statratiofine = new double[fMCFine->GetNbinsX()]; for (int i = 0; i < fMCFine->GetNbinsX(); i++) { if (fMCFine->GetBinContent(i + 1) != 0) { statratiofine[i] = fMCFine->GetBinError(i + 1) / fMCFine->GetBinContent(i + 1); } else { statratiofine[i] = 0.0; } } // Scaling for raw event rates if (fIsRawEvents) { double datamcratio = fDataHist->Integral() / fMCHist->Integral(); fMCHist->Scale(datamcratio); fMCFine->Scale(datamcratio); if (fMCHist_Modes) fMCHist_Modes->Scale(datamcratio); // Scaling for XSec as function of Enu } else if (fIsEnu1D) { PlotUtils::FluxUnfoldedScaling(fMCHist, GetFluxHistogram(), GetEventHistogram(), fScaleFactor, fNEvents); PlotUtils::FluxUnfoldedScaling(fMCFine, GetFluxHistogram(), GetEventHistogram(), fScaleFactor, fNEvents); // if (fMCHist_Modes) { // PlotUtils::FluxUnfoldedScaling(fMCHist_Modes, GetFluxHistogram(), // GetEventHistogram(), fScaleFactor, // fNEvents); // } // Any other differential scaling } else { fMCHist->Scale(fScaleFactor, "width"); fMCFine->Scale(fScaleFactor, "width"); if (fMCHist_Modes) { fMCHist_Modes->Scale(fScaleFactor, "width"); } } // Proper error scaling - ROOT Freaks out with xsec weights sometimes for (int i = 0; i < fMCStat->GetNbinsX(); i++) { fMCHist->SetBinError(i + 1, fMCHist->GetBinContent(i + 1) * statratio[i]); } for (int i = 0; i < fMCFine->GetNbinsX(); i++) { fMCFine->SetBinError(i + 1, fMCFine->GetBinContent(i + 1) * statratiofine[i]); } // Clean up delete statratio; delete statratiofine; return; }; //******************************************************************** void JointMeas1D::ApplyNormScale(double norm) { //******************************************************************** fCurrentNorm = norm; fMCHist->Scale(1.0 / norm); fMCFine->Scale(1.0 / norm); return; }; /* Statistic Functions - Outsources to StatUtils */ //******************************************************************** int JointMeas1D::GetNDOF() { //******************************************************************** int ndof = fDataHist->GetNbinsX(); if (fMaskHist) ndof -= fMaskHist->Integral(); return ndof; } //******************************************************************** double JointMeas1D::GetLikelihood() { //******************************************************************** // If this is for a ratio, there is no data histogram to compare to! if (fNoData || !fDataHist) return 0.; // Apply Masking to MC if Required. if (fIsMask and fMaskHist) { PlotUtils::MaskBins(fMCHist, fMaskHist); } // Sort Shape Scaling double scaleF = 0.0; if (fIsShape) { if (fMCHist->Integral(1, fMCHist->GetNbinsX(), "width")) { scaleF = fDataHist->Integral(1, fDataHist->GetNbinsX(), "width") / fMCHist->Integral(1, fMCHist->GetNbinsX(), "width"); fMCHist->Scale(scaleF); fMCFine->Scale(scaleF); } } // Likelihood Calculation double stat = 0.; if (fIsChi2) { if (fIsRawEvents) { stat = StatUtils::GetChi2FromEventRate(fDataHist, fMCHist, fMaskHist); } else if (fIsDiag) { stat = StatUtils::GetChi2FromDiag(fDataHist, fMCHist, fMaskHist); } else if (!fIsDiag and !fIsRawEvents) { stat = StatUtils::GetChi2FromCov(fDataHist, fMCHist, covar, fMaskHist); } } // Sort Penalty Terms if (fAddNormPen) { double penalty = (1. - fCurrentNorm) * (1. - fCurrentNorm) / (fNormError * fNormError); stat += penalty; } // Return to normal scaling if (fIsShape and !FitPar::Config().GetParB("saveshapescaling")) { fMCHist->Scale(1. / scaleF); fMCFine->Scale(1. / scaleF); } fLikelihood = stat; return stat; } /* Fake Data Functions */ //******************************************************************** void JointMeas1D::SetFakeDataValues(std::string fakeOption) { //******************************************************************** // Setup original/datatrue TH1D *tempdata = (TH1D *)fDataHist->Clone(); if (!fIsFakeData) { fIsFakeData = true; // Make a copy of the original data histogram. if (!fDataOrig) fDataOrig = (TH1D *)fDataHist->Clone((fName + "_data_original").c_str()); } else { ResetFakeData(); } // Setup Inputs fFakeDataInput = fakeOption; NUIS_LOG(SAM, "Setting fake data from : " << fFakeDataInput); // From MC if (fFakeDataInput.compare("MC") == 0) { fDataHist = (TH1D *)fMCHist->Clone((fName + "_MC").c_str()); // Fake File } else { if (!fFakeDataFile) fFakeDataFile = new TFile(fFakeDataInput.c_str(), "READ"); fDataHist = (TH1D *)fFakeDataFile->Get((fName + "_MC").c_str()); } // Setup Data Hist fDataHist->SetNameTitle((fName + "_FAKE").c_str(), (fName + fPlotTitles).c_str()); // Replace Data True if (fDataTrue) delete fDataTrue; fDataTrue = (TH1D *)fDataHist->Clone(); fDataTrue->SetNameTitle((fName + "_FAKE_TRUE").c_str(), (fName + fPlotTitles).c_str()); // Make a new covariance for fake data hist. int nbins = fDataHist->GetNbinsX(); double alpha_i = 0.0; double alpha_j = 0.0; for (int i = 0; i < nbins; i++) { for (int j = 0; j < nbins; j++) { alpha_i = fDataHist->GetBinContent(i + 1) / tempdata->GetBinContent(i + 1); alpha_j = fDataHist->GetBinContent(j + 1) / tempdata->GetBinContent(j + 1); (*fFullCovar)(i, j) = alpha_i * alpha_j * (*fFullCovar)(i, j); } } // Setup Covariances if (covar) delete covar; covar = StatUtils::GetInvert(fFullCovar,true); if (fDecomp) delete fDecomp; fDecomp = StatUtils::GetDecomp(fFullCovar); delete tempdata; return; }; //******************************************************************** void JointMeas1D::ResetFakeData() { //******************************************************************** if (fIsFakeData) { if (fDataHist) delete fDataHist; fDataHist = (TH1D *)fDataTrue->Clone((fSettings.GetName() + "_FKDAT").c_str()); } } //******************************************************************** void JointMeas1D::ResetData() { //******************************************************************** if (fIsFakeData) { if (fDataHist) delete fDataHist; fDataHist = (TH1D *)fDataOrig->Clone((fSettings.GetName() + "_data").c_str()); } fIsFakeData = false; } //******************************************************************** void JointMeas1D::ThrowCovariance() { //******************************************************************** // Take a fDecomposition and use it to throw the current dataset. // Requires fDataTrue also be set incase used repeatedly. if (fDataHist) delete fDataHist; fDataHist = StatUtils::ThrowHistogram(fDataTrue, fFullCovar); return; }; //******************************************************************** void JointMeas1D::ThrowDataToy() { //******************************************************************** if (!fDataTrue) fDataTrue = (TH1D *)fDataHist->Clone(); if (fMCHist) delete fMCHist; fMCHist = StatUtils::ThrowHistogram(fDataTrue, fFullCovar); } /* Access Functions */ //******************************************************************** TH1D *JointMeas1D::GetMCHistogram() { //******************************************************************** if (!fMCHist) return fMCHist; std::ostringstream chi2; chi2 << "#chi^{2}=" << std::setprecision(5) << this->GetLikelihood(); int linecolor = kRed; int linestyle = 1; int linewidth = 1; int fillcolor = 0; int fillstyle = 1001; if (fSettings.Has("linecolor")) linecolor = fSettings.GetI("linecolor"); if (fSettings.Has("linestyle")) linestyle = fSettings.GetI("linestyle"); if (fSettings.Has("linewidth")) linewidth = fSettings.GetI("linewidth"); if (fSettings.Has("fillcolor")) fillcolor = fSettings.GetI("fillcolor"); if (fSettings.Has("fillstyle")) fillstyle = fSettings.GetI("fillstyle"); fMCHist->SetTitle(chi2.str().c_str()); fMCHist->SetLineColor(linecolor); fMCHist->SetLineStyle(linestyle); fMCHist->SetLineWidth(linewidth); fMCHist->SetFillColor(fillcolor); fMCHist->SetFillStyle(fillstyle); return fMCHist; }; //******************************************************************** TH1D *JointMeas1D::GetDataHistogram() { //******************************************************************** if (!fDataHist) return fDataHist; int datacolor = kBlack; int datastyle = 1; int datawidth = 1; if (fSettings.Has("datacolor")) datacolor = fSettings.GetI("datacolor"); if (fSettings.Has("datastyle")) datastyle = fSettings.GetI("datastyle"); if (fSettings.Has("datawidth")) datawidth = fSettings.GetI("datawidth"); fDataHist->SetLineColor(datacolor); fDataHist->SetLineWidth(datawidth); fDataHist->SetMarkerStyle(datastyle); return fDataHist; }; /* Write Functions */ // Save all the histograms at once //******************************************************************** void JointMeas1D::Write(std::string drawOpt) { //******************************************************************** // Get Draw Options drawOpt = FitPar::Config().GetParS("drawopts"); // Write Settigns if (drawOpt.find("SETTINGS") != std::string::npos) { fSettings.Set("#chi^{2}", fLikelihood); fSettings.Set("NDOF", this->GetNDOF()); fSettings.Set("#chi^{2}/NDOF", fLikelihood / this->GetNDOF()); fSettings.Write(); } // Write Data/MC GetDataHistogram()->Write(); GetMCHistogram()->Write(); // Write Fine Histogram if (drawOpt.find("FINE") != std::string::npos) GetFineList().at(0)->Write(); // Write Weighted Histogram if (drawOpt.find("WEIGHTS") != std::string::npos && fMCWeighted) fMCWeighted->Write(); // Save Flux/Evt if no event manager if (!FitPar::Config().GetParB("EventManager")) { if (drawOpt.find("FLUX") != std::string::npos && GetFluxHistogram()) GetFluxHistogram()->Write(); if (drawOpt.find("EVT") != std::string::npos && GetEventHistogram()) GetEventHistogram()->Write(); if (drawOpt.find("XSEC") != std::string::npos && GetEventHistogram()) GetEventHistogram()->Write(); } // Write Mask if (fIsMask && (drawOpt.find("MASK") != std::string::npos)) { fMaskHist->Write(); } // Write Covariances if (drawOpt.find("COV") != std::string::npos && fFullCovar) { PlotUtils::GetFullCovarPlot(fFullCovar, fSettings.GetName())->Write(); } if (drawOpt.find("INVCOV") != std::string::npos && covar) { PlotUtils::GetInvCovarPlot(covar, fSettings.GetName())->Write(); } if (drawOpt.find("DECOMP") != std::string::npos && fDecomp) { PlotUtils::GetDecompCovarPlot(fDecomp, fSettings.GetName())->Write(); } // // Likelihood residual plots // if (drawOpt.find("RESIDUAL") != std::string::npos) { // WriteResidualPlots(); // } // Ratio and Shape Plots if (drawOpt.find("RATIO") != std::string::npos) { WriteRatioPlot(); } if (drawOpt.find("SHAPE") != std::string::npos) { WriteShapePlot(); if (drawOpt.find("RATIO") != std::string::npos) WriteShapeRatioPlot(); } // // RATIO // if (drawOpt.find("CANVMC") != std::string::npos) { // TCanvas* c1 = WriteMCCanvas(fDataHist, fMCHist); // c1->Write(); // delete c1; // } // // PDG // if (drawOpt.find("CANVPDG") != std::string::npos && fMCHist_Modes) { // TCanvas* c2 = WritePDGCanvas(fDataHist, fMCHist, fMCHist_Modes); // c2->Write(); // delete c2; // } // Write Extra Histograms AutoWriteExtraTH1(); WriteExtraHistograms(); if (fSaveSubMeas) { for (std::vector::const_iterator expIter = fSubChain.begin(); expIter != fSubChain.end(); expIter++) { MeasurementBase *exp = *expIter; exp->Write(drawOpt); } } // Returning NUIS_LOG(SAM, "Written Histograms: " << fName); return; } //******************************************************************** void JointMeas1D::WriteRatioPlot() { //******************************************************************** // Setup mc data ratios TH1D *dataRatio = (TH1D *)fDataHist->Clone((fName + "_data_RATIO").c_str()); TH1D *mcRatio = (TH1D *)fMCHist->Clone((fName + "_MC_RATIO").c_str()); // Extra MC Data Ratios for (int i = 0; i < mcRatio->GetNbinsX(); i++) { dataRatio->SetBinContent(i + 1, fDataHist->GetBinContent(i + 1) / fMCHist->GetBinContent(i + 1)); dataRatio->SetBinError(i + 1, fDataHist->GetBinError(i + 1) / fMCHist->GetBinContent(i + 1)); mcRatio->SetBinContent(i + 1, fMCHist->GetBinContent(i + 1) / fMCHist->GetBinContent(i + 1)); mcRatio->SetBinError(i + 1, fMCHist->GetBinError(i + 1) / fMCHist->GetBinContent(i + 1)); } // Write ratios mcRatio->Write(); dataRatio->Write(); delete mcRatio; delete dataRatio; } //******************************************************************** void JointMeas1D::WriteShapePlot() { //******************************************************************** TH1D *mcShape = (TH1D *)fMCHist->Clone((fName + "_MC_SHAPE").c_str()); double shapeScale = 1.0; if (fIsRawEvents) { shapeScale = fDataHist->Integral() / fMCHist->Integral(); } else { shapeScale = fDataHist->Integral("width") / fMCHist->Integral("width"); } mcShape->Scale(shapeScale); std::stringstream ss; ss << "Scale=" << shapeScale; mcShape->SetTitle(ss.str().c_str()); mcShape->SetLineWidth(3); mcShape->SetLineStyle(7); mcShape->Write(); delete mcShape; } //******************************************************************** void JointMeas1D::WriteShapeRatioPlot() { //******************************************************************** // Get a mcshape histogram TH1D *mcShape = (TH1D *)fMCHist->Clone((fName + "_MC_SHAPE").c_str()); double shapeScale = 1.0; if (fIsRawEvents) { shapeScale = fDataHist->Integral() / fMCHist->Integral(); } else { shapeScale = fDataHist->Integral("width") / fMCHist->Integral("width"); } mcShape->Scale(shapeScale); // Create shape ratio histograms TH1D *mcShapeRatio = (TH1D *)mcShape->Clone((fName + "_MC_SHAPE_RATIO").c_str()); TH1D *dataShapeRatio = (TH1D *)fDataHist->Clone((fName + "_data_SHAPE_RATIO").c_str()); // Divide the histograms mcShapeRatio->Divide(mcShape); dataShapeRatio->Divide(mcShape); // Colour the shape ratio plots mcShapeRatio->SetLineWidth(3); mcShapeRatio->SetLineStyle(7); mcShapeRatio->Write(); dataShapeRatio->Write(); delete mcShapeRatio; delete dataShapeRatio; } /* Setup Functions */ //******************************************************************** void JointMeas1D::SetupMeasurement(std::string input, std::string type, FitWeight *rw, std::string fkdt) { //******************************************************************** - // For joint samples, input files are given as a semi-colon seperated list. + // For joint samples, input files are given as a semi-colon separated list. // Parse this list and save it for later, and set up the types etc. if (FitPar::Config().GetParB("EventManager")) { NUIS_ERR(FTL, "Event Manager does not yet work with JointMeas1D Samples"); NUIS_ERR(FTL, "If you want good predictions for " << fName << " then run with it turned off! (-q EventManager=0)"); } fSubInFiles.clear(); std::vector entries = GeneralUtils::ParseToStr(input, ";"); if (entries.size() < 2) { NUIS_ABORT("Joint measurement expected to recieve at least two semi-colon " "separated input files, but recieved: \"" << input << "\""); } std::vector first_file_descriptor = GeneralUtils::ParseToStr(entries.front(), ":"); if (first_file_descriptor.size() != 2) { NUIS_ABORT("Found Joint measurement where the input file had no type: \"" << input << "\", expected \"INPUTTYPE:File.root;File2.root\"."); } std::string inpType = first_file_descriptor[0]; for (std::vector::iterator iter = entries.begin(); iter != entries.end(); iter++) { if (GeneralUtils::ParseToStr(*iter, ":").size() != 2) { std::stringstream ss(""); ss << inpType << ":" << (*iter); fSubInFiles.push_back(ss.str()); } else { fSubInFiles.push_back(*iter); } } // Set Engine and Fake Data fRW = rw; fFakeDataInput = fkdt; // Set Fit Options SetFitOptions(type); return; } /* XSec Functions */ //******************************************************************** double JointMeas1D::TotalIntegratedFlux(std::string intOpt, double low, double high) { //******************************************************************** double totalflux = 0.0; // Destroy the job for sub samples for (std::vector::const_iterator expIter = fSubChain.begin(); expIter != fSubChain.end(); expIter++) { MeasurementBase *exp = *expIter; double expflux = exp->TotalIntegratedFlux(intOpt, low, high); // Fill flux options if (fIsRatio) { totalflux = expflux; break; } if (fIsSummed) { totalflux += expflux; } } return totalflux; } /* Reconfigure Functions */ //******************************************************************** void JointMeas1D::Reconfigure() { //******************************************************************** for (std::vector::const_iterator expIter = fSubChain.begin(); expIter != fSubChain.end(); expIter++) { MeasurementBase *exp = *expIter; exp->Reconfigure(); } ConvertEventRates(); return; } //******************************************************************** void JointMeas1D::ConvertEventRates() { //******************************************************************** // Apply Event Scaling for (std::vector::const_iterator expIter = fSubChain.begin(); expIter != fSubChain.end(); expIter++) { MeasurementBase *exp = static_cast(*expIter); exp->ScaleEvents(); } // Joint function called by top level class MakePlots(); // Do Final Normalisation ApplyNormScale(fRW->GetSampleNorm(this->fName)); } //******************************************************************** void JointMeas1D::MakePlots() { //******************************************************************** // Reset the 1D histograms but not the subClasses ResetAll(); // If Summed if (fIsSummed) { for (std::vector::const_iterator expIter = fSubChain.begin(); expIter != fSubChain.end(); expIter++) { MeasurementBase *exp = static_cast(*expIter); this->fMCHist->Add(exp->GetMCList().at(0)); this->fMCFine->Add(exp->GetFineList().at(0)); } return; } // If Ratio if (fIsRatio) { int sample = 0; for (std::vector::const_iterator expIter = fSubChain.begin(); expIter != fSubChain.end(); expIter++) { MeasurementBase *exp = *expIter; if (sample == 0) { this->fMCHist->Add(exp->GetMCList().at(0)); this->fMCFine->Add(exp->GetFineList().at(0)); } else if (sample == 1) { this->fMCHist->Divide(exp->GetMCList().at(0)); this->fMCFine->Divide(exp->GetFineList().at(0)); } else { break; } sample++; } return; } return; } /* Access Functions */ //******************************************************************** std::vector JointMeas1D::GetMCList() { //******************************************************************** // Make Default Vector std::vector tempVect; tempVect.push_back(this->fMCHist); // Return vector from all sub samples for (std::vector::const_iterator expIter = fSubChain.begin(); expIter != fSubChain.end(); expIter++) { MeasurementBase *exp = *expIter; std::vector subTempVect = exp->GetMCList(); for (UInt_t i = 0; i < subTempVect.size(); i++) { tempVect.push_back(subTempVect.at(i)); } } return tempVect; } //******************************************************************** std::vector JointMeas1D::GetDataList() { //******************************************************************** // Make Default Vector std::vector tempVect; tempVect.push_back(this->fDataHist); // Return vector from all sub samples for (std::vector::const_iterator expIter = fSubChain.begin(); expIter != fSubChain.end(); expIter++) { MeasurementBase *exp = *expIter; std::vector subTempVect = exp->GetDataList(); for (UInt_t i = 0; i < subTempVect.size(); i++) { tempVect.push_back(subTempVect.at(i)); } } return tempVect; } //******************************************************************** std::vector JointMeas1D::GetFineList() { //******************************************************************** // Make Default Vector std::vector tempVect; tempVect.push_back(this->fMCFine); // Return vector from all sub samples for (std::vector::const_iterator expIter = fSubChain.begin(); expIter != fSubChain.end(); expIter++) { MeasurementBase *exp = *expIter; std::vector subTempVect = exp->GetFineList(); for (UInt_t i = 0; i < subTempVect.size(); i++) { tempVect.push_back(subTempVect.at(i)); } } return tempVect; } //******************************************************************** std::vector JointMeas1D::GetMaskList() { //******************************************************************** // Make Default Vector std::vector tempVect; tempVect.push_back(this->fMaskHist); // Return vector from all sub samples for (std::vector::const_iterator expIter = fSubChain.begin(); expIter != fSubChain.end(); expIter++) { MeasurementBase *exp = *expIter; std::vector subTempVect = exp->GetMaskList(); for (UInt_t i = 0; i < subTempVect.size(); i++) { tempVect.push_back(subTempVect.at(i)); } } return tempVect; } //******************************************************************** std::vector JointMeas1D::GetFluxList() { //******************************************************************** // Make Default Vector std::vector tempVect; tempVect.push_back(MeasurementBase::GetFluxHistogram()); // Return vector from all sub samples for (std::vector::const_iterator expIter = fSubChain.begin(); expIter != fSubChain.end(); expIter++) { MeasurementBase *exp = *expIter; std::vector subTempVect = exp->GetFluxList(); for (UInt_t i = 0; i < subTempVect.size(); i++) { tempVect.push_back(subTempVect.at(i)); } } return tempVect; } //******************************************************************** std::vector JointMeas1D::GetEventRateList() { //******************************************************************** // Make Default Vector std::vector tempVect; tempVect.push_back(MeasurementBase::GetEventHistogram()); // Return vector from all sub samples for (std::vector::const_iterator expIter = fSubChain.begin(); expIter != fSubChain.end(); expIter++) { MeasurementBase *exp = *expIter; std::vector subTempVect = exp->GetEventRateList(); for (UInt_t i = 0; i < subTempVect.size(); i++) { tempVect.push_back(subTempVect.at(i)); } } return tempVect; } //******************************************************************** std::vector JointMeas1D::GetXSecList() { //******************************************************************** // Make Default Vector std::vector tempVect; tempVect.push_back(MeasurementBase::GetXSecHistogram()); // Return vector from all sub samples for (std::vector::const_iterator expIter = fSubChain.begin(); expIter != fSubChain.end(); expIter++) { MeasurementBase *exp = *expIter; std::vector subTempVect = exp->GetXSecList(); for (UInt_t i = 0; i < subTempVect.size(); i++) { tempVect.push_back(subTempVect.at(i)); } } return tempVect; } //******************************************************************** TH1D *JointMeas1D::GetCombinedFlux() { //******************************************************************** TH1D *newflux = NULL; int sample = 0; for (std::vector::const_iterator expIter = fSubChain.begin(); expIter != fSubChain.end(); expIter++) { MeasurementBase *exp = *expIter; // Get flux from experiment std::vector fluxVect = exp->GetFluxList(); // Setup newflux if (sample == 0) { newflux = (TH1D *)fluxVect.at(0); newflux->Reset(); } // Add all fluxes for (UInt_t i = 0; i < fluxVect.size(); i++) { newflux->Add((TH1D *)fluxVect.at(i)); sample++; } } if (!newflux) { NUIS_ABORT("No combined flux setup in JointMeas1D"); } return newflux; } //******************************************************************** TH1D *JointMeas1D::GetCombinedEventRate() { //******************************************************************** TH1D *newflux = NULL; int sample = 0; for (std::vector::const_iterator expIter = fSubChain.begin(); expIter != fSubChain.end(); expIter++) { MeasurementBase *exp = *expIter; // Get flux from experiment std::vector fluxVect = exp->GetFluxList(); // Setup newflux if (sample == 0) { newflux = (TH1D *)fluxVect.at(0); newflux->Reset(); } // Add all fluxes for (UInt_t i = 0; i < fluxVect.size(); i++) { newflux->Add(fluxVect.at(i)); sample++; } } if (!newflux) { NUIS_ABORT("No combined event rate setup in JointMeas1D"); } return newflux; } //******************************************************************** std::vector JointMeas1D::GetSubSamples() { //******************************************************************** std::vector exps; for (std::vector::const_iterator expIter = fSubChain.begin(); expIter != fSubChain.end(); expIter++) { exps.push_back(*expIter); } return exps; } //// CRAP TO BE REMOVED //******************************************************************** void JointMeas1D::SetDataValues(std::string dataFile) { //******************************************************************** // Override this function if the input file isn't in a suitable format NUIS_LOG(SAM, "Reading data from: " << dataFile.c_str()); fDataHist = PlotUtils::GetTH1DFromFile(dataFile, (fName + "_data"), fPlotTitles); fDataTrue = (TH1D *)fDataHist->Clone(); // Number of data points is number of bins fNDataPointsX = fDataHist->GetXaxis()->GetNbins(); return; }; //******************************************************************** void JointMeas1D::SetDataFromDatabase(std::string inhistfile, std::string histname) { //******************************************************************** NUIS_LOG(SAM, "Filling histogram from " << inhistfile << "->" << histname); fDataHist = PlotUtils::GetTH1DFromRootFile( (GeneralUtils::GetTopLevelDir() + "/data/" + inhistfile), histname); fDataHist->SetNameTitle((fName + "_data").c_str(), (fName + "_data").c_str()); return; }; //******************************************************************** void JointMeas1D::SetDataFromFile(std::string inhistfile, std::string histname) { //******************************************************************** NUIS_LOG(SAM, "Filling histogram from " << inhistfile << "->" << histname); fDataHist = PlotUtils::GetTH1DFromRootFile((inhistfile), histname); fDataHist->SetNameTitle((fName + "_data").c_str(), (fName + "_data").c_str()); return; }; //******************************************************************** void JointMeas1D::SetCovarMatrix(std::string covarFile) { //******************************************************************** // Covariance function, only really used when reading in the MB Covariances. TFile *tempFile = new TFile(covarFile.c_str(), "READ"); TH2D *covarPlot = new TH2D(); TH2D *fFullCovarPlot = new TH2D(); std::string covName = ""; std::string covOption = FitPar::Config().GetParS("thrown_covariance"); if (fIsShape || fIsFree) covName = "shp_"; if (fIsDiag) covName += "diag"; else covName += "full"; covarPlot = (TH2D *)tempFile->Get((covName + "cov").c_str()); if (!covOption.compare("SUB")) fFullCovarPlot = (TH2D *)tempFile->Get((covName + "cov").c_str()); else if (!covOption.compare("FULL")) fFullCovarPlot = (TH2D *)tempFile->Get("fullcov"); else { NUIS_ERR(WRN, "Incorrect thrown_covariance option in parameters."); } int dim = int(fDataHist->GetNbinsX()); //-this->masked->Integral()); int covdim = int(fDataHist->GetNbinsX()); this->covar = new TMatrixDSym(dim); fFullCovar = new TMatrixDSym(dim); fDecomp = new TMatrixDSym(dim); int row, column = 0; row = 0; column = 0; for (Int_t i = 0; i < covdim; i++) { // if (this->masked->GetBinContent(i+1) > 0) continue; for (Int_t j = 0; j < covdim; j++) { // if (this->masked->GetBinContent(j+1) > 0) continue; (*this->covar)(row, column) = covarPlot->GetBinContent(i + 1, j + 1); (*fFullCovar)(row, column) = fFullCovarPlot->GetBinContent(i + 1, j + 1); column++; } column = 0; row++; } // Set bin errors on data if (!fIsDiag) { StatUtils::SetDataErrorFromCov(fDataHist, fFullCovar); } // Get Deteriminant and inverse matrix // fCovDet = this->covar->Determinant(); TDecompSVD LU = TDecompSVD(*this->covar); this->covar = new TMatrixDSym(dim, LU.Invert().GetMatrixArray(), ""); return; }; //******************************************************************** // Sets the covariance matrix from a provided file in a text format // scale is a multiplicative pre-factor to apply in the case where the // covariance is given in some unit (e.g. 1E-38) void JointMeas1D::SetCovarMatrixFromText(std::string covarFile, int dim, double scale) { //******************************************************************** // Make a counter to track the line number int row = 0; std::string line; std::ifstream covarread(covarFile.c_str(), std::ifstream::in); this->covar = new TMatrixDSym(dim); fFullCovar = new TMatrixDSym(dim); if (covarread.is_open()) { NUIS_LOG(SAM, "Reading covariance matrix from file: " << covarFile); } else { NUIS_ERR(FTL, "Covariance matrix provided is incorrect: " << covarFile); } // Loop over the lines in the file while (std::getline(covarread >> std::ws, line, '\n')) { int column = 0; // Loop over entries and insert them into matrix std::vector entries = GeneralUtils::ParseToDbl(line, " "); if (entries.size() <= 1) { NUIS_ERR(WRN, "SetCovarMatrixFromText -> Covariance matrix only has <= 1 " "entries on this line: " << row); } for (std::vector::iterator iter = entries.begin(); iter != entries.end(); iter++) { (*covar)(row, column) = *iter; (*fFullCovar)(row, column) = *iter; column++; } row++; } covarread.close(); // Scale the actualy covariance matrix by some multiplicative factor (*fFullCovar) *= scale; // Robust matrix inversion method TDecompSVD LU = TDecompSVD(*this->covar); // THIS IS ACTUALLY THE INVERSE COVARIANCE MATRIXA AAAAARGH delete this->covar; this->covar = new TMatrixDSym(dim, LU.Invert().GetMatrixArray(), ""); // Now need to multiply by the scaling factor // If the covariance (*this->covar) *= 1. / (scale); return; }; //******************************************************************** void JointMeas1D::SetCovarMatrixFromCorrText(std::string corrFile, int dim) { //******************************************************************** // Make a counter to track the line number int row = 0; std::string line; std::ifstream corr(corrFile.c_str(), std::ifstream::in); this->covar = new TMatrixDSym(dim); this->fFullCovar = new TMatrixDSym(dim); if (corr.is_open()) { NUIS_LOG(SAM, "Reading and converting correlation matrix from file: " << corrFile); } else { NUIS_ERR(FTL, "Correlation matrix provided is incorrect: " << corrFile); exit(-1); } while (std::getline(corr >> std::ws, line, '\n')) { int column = 0; // Loop over entries and insert them into matrix // Multiply by the errors to get the covariance, rather than the correlation // matrix std::vector entries = GeneralUtils::ParseToDbl(line, " "); for (std::vector::iterator iter = entries.begin(); iter != entries.end(); iter++) { double val = (*iter) * this->fDataHist->GetBinError(row + 1) * 1E38 * this->fDataHist->GetBinError(column + 1) * 1E38; if (val == 0) { NUIS_ERR(FTL, "Found a zero value in the covariance matrix, assuming " "this is an error!"); exit(-1); } (*this->covar)(row, column) = val; (*this->fFullCovar)(row, column) = val; column++; } row++; } // Robust matrix inversion method TDecompSVD LU = TDecompSVD(*this->covar); delete this->covar; this->covar = new TMatrixDSym(dim, LU.Invert().GetMatrixArray(), ""); return; }; //******************************************************************** // FullUnits refers to if we have "real" unscaled units in the covariance // matrix, e.g. 1E-76. If this is the case we need to scale it so that the chi2 // contribution is correct NUISANCE internally assumes the covariance matrix has // units of 1E76 void JointMeas1D::SetCovarFromDataFile(std::string covarFile, std::string covName, bool FullUnits) { //******************************************************************** NUIS_LOG(SAM, "Getting covariance from " << covarFile << "->" << covName); TFile *tempFile = new TFile(covarFile.c_str(), "READ"); TH2D *covPlot = (TH2D *)tempFile->Get(covName.c_str()); covPlot->SetDirectory(0); // Scale the covariance matrix if it comes in normal units if (FullUnits) { covPlot->Scale(1.E76); } int dim = covPlot->GetNbinsX(); fFullCovar = new TMatrixDSym(dim); for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { (*fFullCovar)(i, j) = covPlot->GetBinContent(i + 1, j + 1); } } this->covar = (TMatrixDSym *)fFullCovar->Clone(); fDecomp = (TMatrixDSym *)fFullCovar->Clone(); TDecompSVD LU = TDecompSVD(*this->covar); this->covar = new TMatrixDSym(dim, LU.Invert().GetMatrixArray(), ""); TDecompChol LUChol = TDecompChol(*fDecomp); LUChol.Decompose(); fDecomp = new TMatrixDSym(dim, LU.GetU().GetMatrixArray(), ""); return; }; // std::vector JointMeas1D::GetMCList(void){ // std::vector temp; // return temp; // } // std::vector JointMeas1D::GetDataList(void){ // std::vector temp; // return temp; // } // std::vector JointMeas1D::GetMaskList(void){ // std::vector temp; // return temp; // } // std::vector JointMeas1D::GetFineList(void){ // std::vector temp; // return temp; // } diff --git a/src/FitBase/JointMeas1D.h b/src/FitBase/JointMeas1D.h index dd8c840..71543ad 100644 --- a/src/FitBase/JointMeas1D.h +++ b/src/FitBase/JointMeas1D.h @@ -1,650 +1,650 @@ // 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 JOINTMEASUREMENT_1D_H_SEEN #define JOINTMEASUREMENT_1D_H_SEEN /*! * \addtogroup FitBase * @{ */ #include #include #include #include #include #include #include #include #include // ROOT includes #include "Measurement1D.h" #include #include #include #include #include #include #include #include #include #include #include #include // External data fit includes #include "FitEvent.h" #include "FitUtils.h" #include "MeasurementBase.h" #include "PlotUtils.h" #include "StatUtils.h" //******************************************************************** /// 1D Measurement base class. Histogram handling is done in this base layer. class JointMeas1D : public MeasurementBase { //******************************************************************** public: /* Constructor/Deconstuctor */ JointMeas1D(void); virtual ~JointMeas1D(void); /* Setup Functions */ SampleSettings LoadSampleSettings(nuiskey samplekey); /// \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 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 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. /// /// If no dimensions are given, it is assumed from the number /// entries in the first line of first covfile. 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 Try to extract a shape-only matrix from the existing covariance virtual void SetShapeCovar(); /// \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 Scale the data by some scale factor virtual void ScaleData(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 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. virtual void FinaliseMeasurement(); /// \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 ',' + /// are conflicting. Any options separated with the '/' symbol are non + /// conflicting and can be given together, whereas any separated 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); /* 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 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. virtual std::vector GetMCList(void); /// \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. virtual std::vector GetDataList(void); /// \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. virtual std::vector GetMaskList(void); /// \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. virtual std::vector GetFineList(void); /* 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(); double TotalIntegratedFlux(std::string intOpt, double low, double high); //* // 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); ////// JOINT MEAS1D Functions ////// /* Reconfigure Functions */ /// Call reconfigure on every sub sample virtual void Reconfigure(); /// Stitch the sub sample plots together to make a final fMCHist after /// reconfigure has been called virtual void MakePlots(); virtual std::vector GetSubSamples(); virtual void ConvertEventRates(); /* Access Functions */ virtual std::vector GetFluxList(); virtual std::vector GetEventRateList(); virtual std::vector GetXSecList(); //! Return a flux integrated across all sub samples virtual TH1D *GetCombinedFlux(); //! Return an event rate integrated across all sub samples virtual TH1D *GetCombinedEventRate(); virtual TH1D *GetEventHistogram() { return GetCombinedEventRate(); }; virtual TH1D *GetXSecHistogram() { NUIS_ERR(WRN, "XSec histogram not properly implemented for joint measurements."); return MeasurementBase::GetXSecHistogram(); }; virtual TH1D *GetFluxHistogram() { return GetCombinedFlux(); }; 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 *fCovar; ///< New FullCovar TMatrixDSym *fInvert; ///< New covar double fNormError; ///< Sample norm error // 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 //// JOINT MEAS1D OBJECTS //// std::vector fSubChain; //!< Vector of experimental classes //! that are the sub measurements std::vector fSubInFiles; //!< vector of input files for each of the sub measurements. bool fIsRatio; //!< Flag: is this sample a hist1/hist2 ratio sample bool fIsSummed; //!< Flag: is this sample a combination hist1 + hist2 bool fSaveSubMeas; //!< Flag: Save each of the histograms from the sub //! samples as well as this joint samples plots double fLikelihood; }; /*! @} */ #endif diff --git a/src/FitBase/Measurement1D.cxx b/src/FitBase/Measurement1D.cxx index 732befb..1c8487c 100644 --- a/src/FitBase/Measurement1D.cxx +++ b/src/FitBase/Measurement1D.cxx @@ -1,2023 +1,2026 @@ // Copyright 2016 L. Pickering, P. Stowell, R. Terri, C. Wilkinson, C. Wret /******************************************************************************* * This ile 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 "Measurement1D.h" //******************************************************************** Measurement1D::Measurement1D(void) { //******************************************************************** // XSec Scalings fScaleFactor = -1.0; fCurrentNorm = 1.0; // Histograms fDataHist = NULL; fDataTrue = NULL; fMCHist = NULL; fMCFine = NULL; fMCWeighted = NULL; fMaskHist = NULL; // Covar covar = NULL; fFullCovar = NULL; fShapeCovar = NULL; fCovar = NULL; fInvert = NULL; fDecomp = NULL; fResidualHist = NULL; fChi2LessBinHist = NULL; // Fake Data fFakeDataInput = ""; fFakeDataFile = NULL; // Options fDefaultTypes = "FIX/FULL/CHI2"; fAllowedTypes = "FIX,FREE,SHAPE/FULL,DIAG/CHI2/NORM/ENUCORR/Q2CORR/ENU1D/MASK/NOWIDTH"; fIsFix = false; fIsShape = false; fIsFree = false; fIsDiag = false; fIsFull = false; fAddNormPen = false; fIsMask = false; fIsChi2SVD = false; fIsRawEvents = false; fIsNoWidth = false; fIsDifXSec = false; fIsEnu1D = false; fIsWriting = false; // Inputs fInput = NULL; fRW = NULL; // Extra Histograms fMCHist_Modes = NULL; } //******************************************************************** Measurement1D::~Measurement1D(void) { //******************************************************************** if (fDataHist) delete fDataHist; if (fDataTrue) delete fDataTrue; if (fMCHist) delete fMCHist; if (fMCFine) delete fMCFine; if (fMCWeighted) delete fMCWeighted; if (fMaskHist) delete fMaskHist; if (covar) delete covar; if (fFullCovar) delete fFullCovar; if (fShapeCovar) delete fShapeCovar; if (fCovar) delete fCovar; if (fInvert) delete fInvert; if (fDecomp) delete fDecomp; delete fResidualHist; delete fChi2LessBinHist; } //******************************************************************** void Measurement1D::FinaliseSampleSettings() { //******************************************************************** MeasurementBase::FinaliseSampleSettings(); // Setup naming + renaming fName = fSettings.GetName(); fSettings.SetS("originalname", fName); if (fSettings.Has("rename")) { fName = fSettings.GetS("rename"); fSettings.SetS("name", fName); } // Setup all other options NUIS_LOG(SAM, "Finalising Sample Settings: " << fName); if ((fSettings.GetS("originalname").find("Evt") != std::string::npos)) { fIsRawEvents = true; NUIS_LOG(SAM, "Found event rate measurement but using poisson likelihoods."); } if (fSettings.GetS("originalname").find("XSec_1DEnu") != std::string::npos) { fIsEnu1D = true; NUIS_LOG(SAM, "::" << fName << "::"); NUIS_LOG(SAM, "Found XSec Enu measurement, applying flux integrated scaling, " << "not flux averaged!"); } if (fIsEnu1D && fIsRawEvents) { NUIS_ERR(FTL, "Found 1D Enu XSec distribution AND fIsRawEvents, is this " "really correct?!"); NUIS_ERR(FTL, "Check experiment constructor for " << fName << " and correct this!"); NUIS_ERR(FTL, "I live in " << __FILE__ << ":" << __LINE__); throw; } if (!fRW) fRW = FitBase::GetRW(); if (!fInput and !fIsJoint) SetupInputs(fSettings.GetS("input")); // Setup options SetFitOptions(fDefaultTypes); // defaults SetFitOptions(fSettings.GetS("type")); // user specified EnuMin = GeneralUtils::StrToDbl(fSettings.GetS("enu_min")); EnuMax = GeneralUtils::StrToDbl(fSettings.GetS("enu_max")); } //******************************************************************** void Measurement1D::CreateDataHistogram(int dimx, double *binx) { //******************************************************************** if (fDataHist) delete fDataHist; fDataHist = new TH1D((fSettings.GetName() + "_data").c_str(), (fSettings.GetFullTitles()).c_str(), dimx, binx); } //******************************************************************** void Measurement1D::SetDataFromTextFile(std::string datafile) { //******************************************************************** NUIS_LOG(SAM, "Reading data from text file: " << datafile); fDataHist = PlotUtils::GetTH1DFromFile( datafile, fSettings.GetName() + "_data", fSettings.GetFullTitles()); } //******************************************************************** void Measurement1D::SetDataFromRootFile(std::string datafile, std::string histname) { //******************************************************************** NUIS_LOG(SAM, "Reading data from root file: " << datafile << ";" << histname); fDataHist = PlotUtils::GetTH1DFromRootFile(datafile, histname); fDataHist->SetNameTitle((fSettings.GetName() + "_data").c_str(), (fSettings.GetFullTitles()).c_str()); return; }; //******************************************************************** void Measurement1D::SetEmptyData() { //******************************************************************** fDataHist = new TH1D("EMPTY_DATA", "EMPTY_DATA", 1, 0.0, 1.0); } //******************************************************************** void Measurement1D::SetPoissonErrors() { //******************************************************************** if (!fDataHist) { NUIS_ERR(FTL, "Need a data hist to setup possion errors! "); NUIS_ERR(FTL, "Setup Data First!"); throw; } for (int i = 0; i < fDataHist->GetNbinsX() + 1; i++) { fDataHist->SetBinError(i + 1, sqrt(fDataHist->GetBinContent(i + 1))); } } //******************************************************************** void Measurement1D::SetCovarFromDiagonal(TH1D *data) { //******************************************************************** if (!data and fDataHist) { data = fDataHist; } if (data) { NUIS_LOG(SAM, "Setting diagonal covariance for: " << data->GetName()); fFullCovar = StatUtils::MakeDiagonalCovarMatrix(data); covar = StatUtils::GetInvert(fFullCovar, true); fDecomp = StatUtils::GetDecomp(fFullCovar); } else { NUIS_ABORT("No data input provided to set diagonal covar from!"); } // if (!fIsDiag) { // ERR(FTL) << "SetCovarMatrixFromDiag called for measurement " // << "that is not set as diagonal." ); // throw; // } } //******************************************************************** void Measurement1D::SetCovarFromTextFile(std::string covfile, int dim) { //******************************************************************** if (dim == -1) { dim = fDataHist->GetNbinsX(); } NUIS_LOG(SAM, "Reading covariance from text file: " << covfile); fFullCovar = StatUtils::GetCovarFromTextFile(covfile, dim); covar = StatUtils::GetInvert(fFullCovar, true); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void Measurement1D::SetCovarFromMultipleTextFiles(std::string covfiles, int dim) { //******************************************************************** if (dim == -1) { dim = fDataHist->GetNbinsX(); } std::vector covList = GeneralUtils::ParseToStr(covfiles, ";"); fFullCovar = new TMatrixDSym(dim); for (uint i = 0; i < covList.size(); ++i) { NUIS_LOG(SAM, "Reading covariance from text file: " << covList[i]); TMatrixDSym *temp_cov = StatUtils::GetCovarFromTextFile(covList[i], dim); (*fFullCovar) += (*temp_cov); delete temp_cov; } covar = StatUtils::GetInvert(fFullCovar, true); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void Measurement1D::SetCovarFromRootFile(std::string covfile, std::string histname) { //******************************************************************** NUIS_LOG(SAM, "Reading covariance from text file: " << covfile << ";" << histname); fFullCovar = StatUtils::GetCovarFromRootFile(covfile, histname); covar = StatUtils::GetInvert(fFullCovar, true); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void Measurement1D::SetCovarInvertFromTextFile(std::string covfile, int dim) { //******************************************************************** if (dim == -1) { dim = fDataHist->GetNbinsX(); } NUIS_LOG(SAM, "Reading inverted covariance from text file: " << covfile); covar = StatUtils::GetCovarFromTextFile(covfile, dim); fFullCovar = StatUtils::GetInvert(covar, true); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void Measurement1D::SetCovarInvertFromRootFile(std::string covfile, std::string histname) { //******************************************************************** NUIS_LOG(SAM, "Reading inverted covariance from text file: " << covfile << ";" << histname); covar = StatUtils::GetCovarFromRootFile(covfile, histname); fFullCovar = StatUtils::GetInvert(covar, true); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void Measurement1D::SetCorrelationFromTextFile(std::string covfile, int dim) { //******************************************************************** if (dim == -1) dim = fDataHist->GetNbinsX(); NUIS_LOG(SAM, "Reading data correlations from text file: " << covfile << ";" << dim); TMatrixDSym *correlation = StatUtils::GetCovarFromTextFile(covfile, dim); if (!fDataHist) { NUIS_ABORT("Trying to set correlations from text file but there is no " "data to build it from. \n" << "In constructor make sure data is set before " "SetCorrelationFromTextFile is called. \n"); } // Fill covar from data errors and correlations fFullCovar = new TMatrixDSym(dim); for (int i = 0; i < fDataHist->GetNbinsX(); i++) { for (int j = 0; j < fDataHist->GetNbinsX(); j++) { (*fFullCovar)(i, j) = (*correlation)(i, j) * fDataHist->GetBinError(i + 1) * fDataHist->GetBinError(j + 1) * 1.E76; } } // Fill other covars. covar = StatUtils::GetInvert(fFullCovar, true); fDecomp = StatUtils::GetDecomp(fFullCovar); delete correlation; } //******************************************************************** void Measurement1D::SetCorrelationFromMultipleTextFiles(std::string corrfiles, int dim) { //******************************************************************** if (dim == -1) { dim = fDataHist->GetNbinsX(); } std::vector corrList = GeneralUtils::ParseToStr(corrfiles, ";"); fFullCovar = new TMatrixDSym(dim); for (uint i = 0; i < corrList.size(); ++i) { NUIS_LOG(SAM, "Reading covariance from text file: " << corrList[i]); TMatrixDSym *temp_cov = StatUtils::GetCovarFromTextFile(corrList[i], dim); for (int i = 0; i < fDataHist->GetNbinsX(); i++) { for (int j = 0; j < fDataHist->GetNbinsX(); j++) { (*temp_cov)(i, j) = (*temp_cov)(i, j) * fDataHist->GetBinError(i + 1) * fDataHist->GetBinError(j + 1) * 1.E76; } } (*fFullCovar) += (*temp_cov); delete temp_cov; } covar = StatUtils::GetInvert(fFullCovar, true); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void Measurement1D::SetCorrelationFromRootFile(std::string covfile, std::string histname) { //******************************************************************** NUIS_LOG(SAM, "Reading data correlations from text file: " << covfile << ";" << histname); TMatrixDSym *correlation = StatUtils::GetCovarFromRootFile(covfile, histname); if (!fDataHist) { NUIS_ABORT("Trying to set correlations from text file but there is no " "data to build it from. \n" << "In constructor make sure data is set before " "SetCorrelationFromTextFile is called. \n"); } // Fill covar from data errors and correlations fFullCovar = new TMatrixDSym(fDataHist->GetNbinsX()); for (int i = 0; i < fDataHist->GetNbinsX(); i++) { for (int j = 0; j < fDataHist->GetNbinsX(); j++) { (*fFullCovar)(i, j) = (*correlation)(i, j) * fDataHist->GetBinError(i + 1) * fDataHist->GetBinError(j + 1) * 1.E76; } } // Fill other covars. covar = StatUtils::GetInvert(fFullCovar, true); fDecomp = StatUtils::GetDecomp(fFullCovar); delete correlation; } //******************************************************************** void Measurement1D::SetCholDecompFromTextFile(std::string covfile, int dim) { //******************************************************************** if (dim == -1) { dim = fDataHist->GetNbinsX(); } NUIS_LOG(SAM, "Reading cholesky from text file: " << covfile); TMatrixD *temp = StatUtils::GetMatrixFromTextFile(covfile, dim, dim); TMatrixD *trans = (TMatrixD *)temp->Clone(); trans->T(); (*trans) *= (*temp); fFullCovar = new TMatrixDSym(dim, trans->GetMatrixArray(), ""); covar = StatUtils::GetInvert(fFullCovar, true); fDecomp = StatUtils::GetDecomp(fFullCovar); delete temp; delete trans; } //******************************************************************** void Measurement1D::SetCholDecompFromRootFile(std::string covfile, std::string histname) { //******************************************************************** NUIS_LOG(SAM, "Reading cholesky decomp from root file: " << covfile << ";" << histname); TMatrixD *temp = StatUtils::GetMatrixFromRootFile(covfile, histname); TMatrixD *trans = (TMatrixD *)temp->Clone(); trans->T(); (*trans) *= (*temp); fFullCovar = new TMatrixDSym(temp->GetNrows(), trans->GetMatrixArray(), ""); covar = StatUtils::GetInvert(fFullCovar, true); fDecomp = StatUtils::GetDecomp(fFullCovar); delete temp; delete trans; } void Measurement1D::SetShapeCovar() { // Return if this is missing any pre-requisites if (!fFullCovar) return; if (!fDataHist) return; // Also return if it's bloody stupid under the circumstances if (fIsDiag) return; fShapeCovar = StatUtils::ExtractShapeOnlyCovar(fFullCovar, fDataHist); return; } //******************************************************************** void Measurement1D::ScaleData(double scale) { //******************************************************************** fDataHist->Scale(scale); } //******************************************************************** void Measurement1D::ScaleDataErrors(double scale) { //******************************************************************** for (int i = 0; i < fDataHist->GetNbinsX(); i++) { fDataHist->SetBinError(i + 1, fDataHist->GetBinError(i + 1) * scale); } } //******************************************************************** void Measurement1D::ScaleCovar(double scale) { //******************************************************************** (*fFullCovar) *= scale; (*covar) *= 1.0 / scale; (*fDecomp) *= sqrt(scale); } //******************************************************************** void Measurement1D::SetBinMask(std::string maskfile) { //******************************************************************** if (!fIsMask) return; NUIS_LOG(SAM, "Reading bin mask from file: " << maskfile); // Create a mask histogram with dim of data int nbins = fDataHist->GetNbinsX(); fMaskHist = new TH1I((fSettings.GetName() + "_BINMASK").c_str(), (fSettings.GetName() + "_BINMASK; Bin; Mask?").c_str(), nbins, 0, nbins); std::string line; std::ifstream mask(maskfile.c_str(), std::ifstream::in); if (!mask.is_open()) { NUIS_ABORT("Cannot find mask file."); } while (std::getline(mask >> std::ws, line, '\n')) { std::vector entries = GeneralUtils::ParseToInt(line, " "); // Skip lines with poorly formatted lines if (entries.size() < 2) { NUIS_LOG(WRN, "Measurement1D::SetBinMask(), couldn't parse line: " << line); continue; } // The first index should be the bin number, the second should be the mask // value. int val = 0; if (entries[1] > 0) val = 1; fMaskHist->SetBinContent(entries[0], val); } // Apply masking by setting masked data bins to zero PlotUtils::MaskBins(fDataHist, fMaskHist); return; } //******************************************************************** void Measurement1D::FinaliseMeasurement() { //******************************************************************** NUIS_LOG(SAM, "Finalising Measurement: " << fName); if (fSettings.GetB("onlymc")) { if (fDataHist) delete fDataHist; fDataHist = new TH1D("empty_data", "empty_data", 1, 0.0, 1.0); } // Make sure data is setup if (!fDataHist) { NUIS_ABORT("No data has been setup inside " << fName << " constructor!"); } // Make sure covariances are setup if (!fFullCovar) { fIsDiag = true; SetCovarFromDiagonal(fDataHist); } else if (fIsDiag) { // Have covariance but also set Diag NUIS_LOG(SAM, "Have full covariance for sample " << GetName() << " but only using diagonal elements for likelihood"); int nbins = fFullCovar->GetNcols(); for (int i = 0; i < nbins; ++i) { for (int j = 0; j < nbins; ++j) { if (i != j) { (*fFullCovar)[i][j] = 0; } } } delete covar; covar = NULL; delete fDecomp; fDecomp = NULL; } if (!covar) { covar = StatUtils::GetInvert(fFullCovar, true); } if (!fDecomp) { fDecomp = StatUtils::GetDecomp(fFullCovar); } // Push the diagonals of fFullCovar onto the data histogram // Comment this out until the covariance/data scaling is consistent! StatUtils::SetDataErrorFromCov(fDataHist, fFullCovar, 1E-38); // If shape only, set covar and fDecomp using the shape-only matrix (if set) if (fIsShape && fShapeCovar && FitPar::Config().GetParB("UseShapeCovar")) { if (covar) delete covar; covar = StatUtils::GetInvert(fShapeCovar, true); if (fDecomp) delete fDecomp; fDecomp = StatUtils::GetDecomp(fFullCovar); fUseShapeNormDecomp = FitPar::Config().GetParB("UseShapeNormDecomp"); if (fUseShapeNormDecomp) { fNormError = 0; // From https://arxiv.org/pdf/2003.00088.pdf for (int i = 0; i < fFullCovar->GetNcols(); ++i) { for (int j = 0; j < fFullCovar->GetNcols(); ++j) { fNormError += (*fFullCovar)[i][j]; } } NUIS_LOG(SAM, "Sample: " << fName << ", using shape/norm decomp with norm error: " << fNormError); } } // Setup fMCHist from data fMCHist = (TH1D *)fDataHist->Clone(); fMCHist->SetNameTitle((fSettings.GetName() + "_MC").c_str(), (fSettings.GetFullTitles()).c_str()); fMCHist->Reset(); // Setup fMCFine fMCFine = new TH1D("mcfine", "mcfine", fDataHist->GetNbinsX() * 8, fMCHist->GetBinLowEdge(1), fMCHist->GetBinLowEdge(fDataHist->GetNbinsX() + 1)); fMCFine->SetNameTitle((fSettings.GetName() + "_MC_FINE").c_str(), (fSettings.GetFullTitles()).c_str()); fMCFine->Reset(); // Setup MC Stat fMCStat = (TH1D *)fMCHist->Clone(); fMCStat->Reset(); // Search drawopts for possible types to include by default std::string drawopts = FitPar::Config().GetParS("drawopts"); if (drawopts.find("MODES") != std::string::npos) { fMCHist_Modes = new TrueModeStack((fSettings.GetName() + "_MODES").c_str(), - ("True Channels"), fMCHist); + ("True Channels"), fMCHist); + fMCHist_Modes ->SetTitleX(fDataHist->GetXaxis()->GetTitle()); + fMCHist_Modes ->SetTitleY(fDataHist->GetYaxis()->GetTitle()); + SetAutoProcessTH1(fMCHist_Modes, kCMD_Reset, kCMD_Norm, kCMD_Write); } if (fSettings.Has("maskfile") && fSettings.Has("maskhist")) { fMaskHist = dynamic_cast(PlotUtils::GetTH1FromRootFile( fSettings.GetS("maskfile"), fSettings.GetS("maskhist"))); fIsMask = bool(fMaskHist); NUIS_LOG(SAM, "Loaded mask histogram: " << fSettings.GetS("maskhist") << " from " << fSettings.GetS("maskfile")); } else if (fIsMask) { // Setup bin masks using sample name std::string curname = fName; std::string origname = fSettings.GetS("originalname"); // Check rename.mask std::string maskloc = FitPar::Config().GetParDIR(curname + ".mask"); // Check origname.mask if (maskloc.empty()) maskloc = FitPar::Config().GetParDIR(origname + ".mask"); // Check database if (maskloc.empty()) { maskloc = FitPar::GetDataBase() + "/masks/" + origname + ".mask"; } // Setup Bin Mask SetBinMask(maskloc); } if (fScaleFactor < 0) { NUIS_ERR(FTL, "I found a negative fScaleFactor in " << __FILE__ << ":" << __LINE__); NUIS_ERR(FTL, "fScaleFactor = " << fScaleFactor); NUIS_ERR(FTL, "EXITING"); throw; } if (fAddNormPen) { if (!fUseShapeNormDecomp) { fNormError = fSettings.GetNormError(); } if (fNormError <= 0.0) { NUIS_ERR(FTL, "Norm error for class " << fName << " is 0.0!"); NUIS_ERR(FTL, "If you want to use it please add fNormError=VAL"); throw; } } // Create and fill Weighted Histogram if (!fMCWeighted) { fMCWeighted = (TH1D *)fMCHist->Clone(); fMCWeighted->SetNameTitle((fName + "_MCWGHTS").c_str(), (fName + "_MCWGHTS" + fPlotTitles).c_str()); fMCWeighted->GetYaxis()->SetTitle("Weighted Events"); } } //******************************************************************** void Measurement1D::SetFitOptions(std::string opt) { //******************************************************************** // Do nothing if default given if (opt == "DEFAULT") return; // CHECK Conflicting Fit Options std::vector fit_option_allow = GeneralUtils::ParseToStr(fAllowedTypes, "/"); for (UInt_t i = 0; i < fit_option_allow.size(); i++) { std::vector fit_option_section = GeneralUtils::ParseToStr(fit_option_allow.at(i), ","); bool found_option = false; for (UInt_t j = 0; j < fit_option_section.size(); j++) { std::string av_opt = fit_option_section.at(j); if (!found_option and opt.find(av_opt) != std::string::npos) { found_option = true; } else if (found_option and opt.find(av_opt) != std::string::npos) { NUIS_ABORT( "ERROR: Conflicting fit options provided: " << opt << std::endl << "Conflicting group = " << fit_option_section.at(i) << std::endl << "You should only supply one of these options in card file."); } } } // Check all options are allowed std::vector fit_options_input = GeneralUtils::ParseToStr(opt, "/"); for (UInt_t i = 0; i < fit_options_input.size(); i++) { if (fAllowedTypes.find(fit_options_input.at(i)) == std::string::npos) { NUIS_ERR(WRN, "ERROR: Fit Option '" << fit_options_input.at(i) << "' Provided is not allowed for this measurement."); - NUIS_ERR(WRN, "Fit Options should be provided as a '/' seperated list " + NUIS_ERR(WRN, "Fit Options should be provided as a '/' separated list " "(e.g. FREE/DIAG/NORM)"); NUIS_ABORT("Available options for " << fName << " are '" << fAllowedTypes << "'"); } } // Set TYPE fFitType = opt; // FIX,SHAPE,FREE if (opt.find("FIX") != std::string::npos) { fIsFree = fIsShape = false; fIsFix = true; } else if (opt.find("SHAPE") != std::string::npos) { fIsFree = fIsFix = false; fIsShape = true; } else if (opt.find("FREE") != std::string::npos) { fIsFix = fIsShape = false; fIsFree = true; } // DIAG,FULL (or default to full) if (opt.find("DIAG") != std::string::npos) { fIsDiag = true; fIsFull = false; } else if (opt.find("FULL") != std::string::npos) { fIsDiag = false; fIsFull = true; } // CHI2/LL (OTHERS?) if (opt.find("LOG") != std::string::npos) { fIsChi2 = false; NUIS_ERR(FTL, "No other LIKELIHOODS properly supported!"); NUIS_ERR(FTL, "Try to use a chi2!"); throw; } else { fIsChi2 = true; } // EXTRAS if (opt.find("RAW") != std::string::npos) fIsRawEvents = true; if (opt.find("NOWIDTH") != std::string::npos) fIsNoWidth = true; if (opt.find("DIF") != std::string::npos) fIsDifXSec = true; if (opt.find("ENU1D") != std::string::npos) fIsEnu1D = true; if (opt.find("NORM") != std::string::npos) fAddNormPen = true; if (opt.find("MASK") != std::string::npos) fIsMask = true; return; }; //******************************************************************** void Measurement1D::SetSmearingMatrix(std::string smearfile, int truedim, int recodim) { //******************************************************************** // The smearing matrix describes the migration from true bins (rows) to reco // bins (columns) // Counter over the true bins! int row = 0; std::string line; std::ifstream smear(smearfile.c_str(), std::ifstream::in); // Note that the smearing matrix may be rectangular. fSmearMatrix = new TMatrixD(truedim, recodim); if (smear.is_open()) { NUIS_LOG(SAM, "Reading smearing matrix from file: " << smearfile); } else { NUIS_ABORT("Smearing matrix provided is incorrect: " << smearfile); } while (std::getline(smear >> std::ws, line, '\n')) { int column = 0; std::vector entries = GeneralUtils::ParseToDbl(line, " "); for (std::vector::iterator iter = entries.begin(); iter != entries.end(); iter++) { (*fSmearMatrix)(row, column) = (*iter) / 100.; // Convert to fraction from // percentage (this may not be // general enough) column++; } row++; } return; } //******************************************************************** void Measurement1D::ApplySmearingMatrix() { //******************************************************************** if (!fSmearMatrix) { NUIS_ERR(WRN, fName << ": attempted to apply smearing matrix, but none was set"); return; } TH1D *unsmeared = (TH1D *)fMCHist->Clone(); TH1D *smeared = (TH1D *)fMCHist->Clone(); smeared->Reset(); // Loop over reconstructed bins // true = row; reco = column for (int rbin = 0; rbin < fSmearMatrix->GetNcols(); ++rbin) { // Sum up the constributions from all true bins double rBinVal = 0; // Loop over true bins for (int tbin = 0; tbin < fSmearMatrix->GetNrows(); ++tbin) { rBinVal += (*fSmearMatrix)(tbin, rbin) * unsmeared->GetBinContent(tbin + 1); } smeared->SetBinContent(rbin + 1, rBinVal); } fMCHist = (TH1D *)smeared->Clone(); return; } /* Reconfigure LOOP */ //******************************************************************** void Measurement1D::ResetAll() { //******************************************************************** fMCHist->Reset(); fMCFine->Reset(); fMCStat->Reset(); return; }; //******************************************************************** void Measurement1D::FillHistograms() { //******************************************************************** if (Signal) { NUIS_LOG(DEB, "Fill MCHist: " << fXVar << ", " << Weight); fMCHist->Fill(fXVar, Weight); fMCFine->Fill(fXVar, Weight); fMCStat->Fill(fXVar, 1.0); if (fMCHist_Modes) fMCHist_Modes->Fill(Mode, fXVar, Weight); } return; }; //******************************************************************** void Measurement1D::ScaleEvents() { //******************************************************************** // Fill MCWeighted; // for (int i = 0; i < fMCHist->GetNbinsX(); i++) { // fMCWeighted->SetBinContent(i + 1, fMCHist->GetBinContent(i + 1)); // fMCWeighted->SetBinError(i + 1, fMCHist->GetBinError(i + 1)); // } // Setup Stat ratios for MC and MC Fine double *statratio = new double[fMCHist->GetNbinsX()]; for (int i = 0; i < fMCHist->GetNbinsX(); i++) { if (fMCHist->GetBinContent(i + 1) != 0) { statratio[i] = fMCHist->GetBinError(i + 1) / fMCHist->GetBinContent(i + 1); } else { statratio[i] = 0.0; } } double *statratiofine = new double[fMCFine->GetNbinsX()]; for (int i = 0; i < fMCFine->GetNbinsX(); i++) { if (fMCFine->GetBinContent(i + 1) != 0) { statratiofine[i] = fMCFine->GetBinError(i + 1) / fMCFine->GetBinContent(i + 1); } else { statratiofine[i] = 0.0; } } // Scaling for raw event rates if (fIsRawEvents) { double datamcratio = fDataHist->Integral() / fMCHist->Integral(); fMCHist->Scale(datamcratio); fMCFine->Scale(datamcratio); if (fMCHist_Modes) fMCHist_Modes->Scale(datamcratio); // Scaling for XSec as function of Enu } else if (fIsEnu1D) { PlotUtils::FluxUnfoldedScaling(fMCHist, GetFluxHistogram(), GetEventHistogram(), fScaleFactor, fNEvents); PlotUtils::FluxUnfoldedScaling(fMCFine, GetFluxHistogram(), GetEventHistogram(), fScaleFactor, fNEvents); if (fMCHist_Modes) { // Loop over the modes fMCHist_Modes->FluxUnfold(GetFluxHistogram(), GetEventHistogram(), fScaleFactor, fNEvents); // PlotUtils::FluxUnfoldedScaling(fMCHist_Modes, GetFluxHistogram(), // GetEventHistogram(), fScaleFactor, // fNEvents); } } else if (fIsNoWidth) { fMCHist->Scale(fScaleFactor); fMCFine->Scale(fScaleFactor); if (fMCHist_Modes) fMCHist_Modes->Scale(fScaleFactor); // Any other differential scaling } else { fMCHist->Scale(fScaleFactor, "width"); fMCFine->Scale(fScaleFactor, "width"); if (fMCHist_Modes) fMCHist_Modes->Scale(fScaleFactor, "width"); } // Proper error scaling - ROOT Freaks out with xsec weights sometimes for (int i = 0; i < fMCStat->GetNbinsX(); i++) { fMCHist->SetBinError(i + 1, fMCHist->GetBinContent(i + 1) * statratio[i]); } for (int i = 0; i < fMCFine->GetNbinsX(); i++) { fMCFine->SetBinError(i + 1, fMCFine->GetBinContent(i + 1) * statratiofine[i]); } // Clean up delete[] statratio; delete[] statratiofine; return; }; //******************************************************************** void Measurement1D::ApplyNormScale(double norm) { //******************************************************************** fCurrentNorm = norm; fMCHist->Scale(1.0 / norm); fMCFine->Scale(1.0 / norm); return; }; /* Statistic Functions - Outsources to StatUtils */ //******************************************************************** int Measurement1D::GetNDOF() { //******************************************************************** int ndof = fDataHist->GetNbinsX(); if (fMaskHist and fIsMask) ndof -= fMaskHist->Integral(); return ndof; } //******************************************************************** double Measurement1D::GetLikelihood() { //******************************************************************** // If this is for a ratio, there is no data histogram to compare to! if (fNoData || !fDataHist) return 0.; // Apply Masking to MC if Required. if (fIsMask and fMaskHist) { PlotUtils::MaskBins(fMCHist, fMaskHist); } // Sort Shape Scaling double scaleF = 0.0; // TODO Include !fIsRawEvents if (fIsShape) { // Don't renorm based on width if we are using ShapeNormDecomp if (fUseShapeNormDecomp) { if (fMCHist->Integral(1, fMCHist->GetNbinsX())) { scaleF = fDataHist->Integral(1, fDataHist->GetNbinsX()) / fMCHist->Integral(1, fMCHist->GetNbinsX()); fMCHist->Scale(scaleF); fMCFine->Scale(scaleF); } } else { if (fMCHist->Integral(1, fMCHist->GetNbinsX(), "width")) { scaleF = fDataHist->Integral(1, fDataHist->GetNbinsX(), "width") / fMCHist->Integral(1, fMCHist->GetNbinsX(), "width"); fMCHist->Scale(scaleF); fMCFine->Scale(scaleF); } } } // Likelihood Calculation double stat = 0.; if (fIsChi2) { if (fIsRawEvents) { stat = StatUtils::GetChi2FromEventRate(fDataHist, fMCHist, fMaskHist); } else if (fIsDiag) { stat = StatUtils::GetChi2FromDiag(fDataHist, fMCHist, fMaskHist); } else if (!fIsDiag and !fIsRawEvents) { stat = StatUtils::GetChi2FromCov(fDataHist, fMCHist, covar, fMaskHist, 1, 1E76, fIsWriting ? fResidualHist : NULL); if (fChi2LessBinHist && fIsWriting) { for (int xi = 0; xi < fDataHist->GetNbinsX(); ++xi) { TH1I *binmask = fMaskHist ? static_cast(fMaskHist->Clone("mask")) : new TH1I("mask", "", fDataHist->GetNbinsX(), 0, fDataHist->GetNbinsX()); binmask->SetDirectory(NULL); binmask->SetBinContent(xi + 1, 1); fChi2LessBinHist->SetBinContent( xi + 1, StatUtils::GetChi2FromCov(fDataHist, fMCHist, covar, binmask)); delete binmask; } } } } // Sort Penalty Terms if (fAddNormPen) { if (fUseShapeNormDecomp) { // if shape norm, then add the norm penalty from // https://arxiv.org/pdf/2003.00088.pdf TH1 *masked_data = StatUtils::ApplyHistogramMasking(fDataHist, fMaskHist); TH1 *masked_mc = StatUtils::ApplyHistogramMasking(fMCHist, fMaskHist); masked_mc->Scale(scaleF); NUIS_LOG(REC, "Shape Norm Decomp mcinteg: " << masked_mc->Integral() * 1E38 << ", datainteg: " << masked_data->Integral() * 1E38 << ", normerror: " << fNormError); double normpen = std::pow((masked_data->Integral() - masked_mc->Integral()) * 1E38, 2) / fNormError; masked_data->SetDirectory(NULL); delete masked_data; masked_mc->SetDirectory(NULL); delete masked_mc; NUIS_LOG(SAM, "Using Shape/Norm decomposition: Norm penalty " << normpen << " on shape penalty of " << stat); stat += normpen; } else { double penalty = (1. - fCurrentNorm) * (1. - fCurrentNorm) / (fNormError * fNormError); stat += penalty; } } // Return to normal scaling if (fIsShape) { // and !FitPar::Config().GetParB("saveshapescaling")) { fMCHist->Scale(1. / scaleF); fMCFine->Scale(1. / scaleF); } fLikelihood = stat; return stat; } /* Fake Data Functions */ //******************************************************************** void Measurement1D::SetFakeDataValues(std::string fakeOption) { //******************************************************************** // Setup original/datatrue TH1D *tempdata = (TH1D *)fDataHist->Clone(); if (!fIsFakeData) { fIsFakeData = true; // Make a copy of the original data histogram. if (!fDataOrig) fDataOrig = (TH1D *)fDataHist->Clone((fName + "_data_original").c_str()); } else { ResetFakeData(); } // Setup Inputs fFakeDataInput = fakeOption; NUIS_LOG(SAM, "Setting fake data from : " << fFakeDataInput); // From MC if (fFakeDataInput.compare("MC") == 0) { fDataHist = (TH1D *)fMCHist->Clone((fName + "_MC").c_str()); // Fake File } else { if (!fFakeDataFile) fFakeDataFile = new TFile(fFakeDataInput.c_str(), "READ"); fDataHist = (TH1D *)fFakeDataFile->Get((fName + "_MC").c_str()); } // Setup Data Hist fDataHist->SetNameTitle((fName + "_FAKE").c_str(), (fName + fPlotTitles).c_str()); // Replace Data True if (fDataTrue) delete fDataTrue; fDataTrue = (TH1D *)fDataHist->Clone(); fDataTrue->SetNameTitle((fName + "_FAKE_TRUE").c_str(), (fName + fPlotTitles).c_str()); // Make a new covariance for fake data hist. int nbins = fDataHist->GetNbinsX(); double alpha_i = 0.0; double alpha_j = 0.0; for (int i = 0; i < nbins; i++) { for (int j = 0; j < nbins; j++) { alpha_i = fDataHist->GetBinContent(i + 1) / tempdata->GetBinContent(i + 1); alpha_j = fDataHist->GetBinContent(j + 1) / tempdata->GetBinContent(j + 1); (*fFullCovar)(i, j) = alpha_i * alpha_j * (*fFullCovar)(i, j); } } // Setup Covariances if (covar) delete covar; covar = StatUtils::GetInvert(fFullCovar, true); if (fDecomp) delete fDecomp; fDecomp = StatUtils::GetDecomp(fFullCovar); delete tempdata; return; }; //******************************************************************** void Measurement1D::ResetFakeData() { //******************************************************************** if (fIsFakeData) { if (fDataHist) delete fDataHist; fDataHist = (TH1D *)fDataTrue->Clone((fSettings.GetName() + "_FKDAT").c_str()); } } //******************************************************************** void Measurement1D::ResetData() { //******************************************************************** if (fIsFakeData) { if (fDataHist) delete fDataHist; fDataHist = (TH1D *)fDataOrig->Clone((fSettings.GetName() + "_data").c_str()); } fIsFakeData = false; } //******************************************************************** void Measurement1D::ThrowCovariance() { //******************************************************************** // Take a fDecomposition and use it to throw the current dataset. // Requires fDataTrue also be set incase used repeatedly. if (!fDataTrue) fDataTrue = (TH1D *)fDataHist->Clone(); if (fDataHist) delete fDataHist; fDataHist = StatUtils::ThrowHistogram(fDataTrue, fFullCovar); return; }; //******************************************************************** void Measurement1D::ThrowDataToy() { //******************************************************************** if (!fDataTrue) fDataTrue = (TH1D *)fDataHist->Clone(); if (fMCHist) delete fMCHist; fMCHist = StatUtils::ThrowHistogram(fDataTrue, fFullCovar); } /* Access Functions */ //******************************************************************** TH1D *Measurement1D::GetMCHistogram() { //******************************************************************** if (!fMCHist) return fMCHist; std::ostringstream chi2; chi2 << std::setprecision(5) << this->GetLikelihood(); int linecolor = kRed; int linestyle = 1; int linewidth = 1; int fillcolor = 0; int fillstyle = 1001; // if (fSettings.Has("linecolor")) linecolor = fSettings.GetI("linecolor"); // if (fSettings.Has("linestyle")) linestyle = fSettings.GetI("linestyle"); // if (fSettings.Has("linewidth")) linewidth = fSettings.GetI("linewidth"); // if (fSettings.Has("fillcolor")) fillcolor = fSettings.GetI("fillcolor"); // if (fSettings.Has("fillstyle")) fillstyle = fSettings.GetI("fillstyle"); fMCHist->SetTitle(chi2.str().c_str()); fMCHist->SetLineColor(linecolor); fMCHist->SetLineStyle(linestyle); fMCHist->SetLineWidth(linewidth); fMCHist->SetFillColor(fillcolor); fMCHist->SetFillStyle(fillstyle); return fMCHist; }; //******************************************************************** TH1D *Measurement1D::GetDataHistogram() { //******************************************************************** if (!fDataHist) return fDataHist; int datacolor = kBlack; int datastyle = 1; int datawidth = 1; // if (fSettings.Has("datacolor")) datacolor = fSettings.GetI("datacolor"); // if (fSettings.Has("datastyle")) datastyle = fSettings.GetI("datastyle"); // if (fSettings.Has("datawidth")) datawidth = fSettings.GetI("datawidth"); fDataHist->SetLineColor(datacolor); fDataHist->SetLineWidth(datawidth); fDataHist->SetMarkerStyle(datastyle); return fDataHist; }; /* Write Functions */ // Save all the histograms at once //******************************************************************** void Measurement1D::Write(std::string drawOpt) { //******************************************************************** // Get Draw Options drawOpt = FitPar::Config().GetParS("drawopts"); // Write Settigns if (drawOpt.find("SETTINGS") != std::string::npos) { fSettings.Set("#chi^{2}", fLikelihood); fSettings.Set("NDOF", this->GetNDOF()); fSettings.Set("#chi^{2}/NDOF", fLikelihood / this->GetNDOF()); fSettings.Write(); } // Write Data/MC if (drawOpt.find("DATA") != std::string::npos) GetDataList().at(0)->Write(); if (drawOpt.find("MC") != std::string::npos) { GetMCList().at(0)->Write(); if ((fEvtRateScaleFactor != 0xdeadbeef) && GetMCList().at(0)) { TH1D *PredictedEvtRate = static_cast(GetMCList().at(0)->Clone()); PredictedEvtRate->Scale(fEvtRateScaleFactor); PredictedEvtRate->GetYaxis()->SetTitle("Predicted event rate"); PredictedEvtRate->Write(); } } // Write Fine Histogram if (drawOpt.find("FINE") != std::string::npos) GetFineList().at(0)->Write(); // Write Weighted Histogram if (drawOpt.find("WEIGHTS") != std::string::npos && fMCWeighted) fMCWeighted->Write(); // Save Flux/Evt if no event manager if (!FitPar::Config().GetParB("EventManager")) { if (drawOpt.find("FLUX") != std::string::npos && GetFluxHistogram()) GetFluxHistogram()->Write(); if (drawOpt.find("EVT") != std::string::npos && GetEventHistogram()) GetEventHistogram()->Write(); if (drawOpt.find("XSEC") != std::string::npos && GetEventHistogram()) GetXSecHistogram()->Write(); } // Write Mask if (fIsMask && (drawOpt.find("MASK") != std::string::npos)) { fMaskHist->Write(); } // Write Covariances if (drawOpt.find("COV") != std::string::npos && fFullCovar) { PlotUtils::GetFullCovarPlot(fFullCovar, fSettings.GetName())->Write(); } if (drawOpt.find("INVCOV") != std::string::npos && covar) { PlotUtils::GetInvCovarPlot(covar, fSettings.GetName())->Write(); } if (drawOpt.find("DECOMP") != std::string::npos && fDecomp) { PlotUtils::GetDecompCovarPlot(fDecomp, fSettings.GetName())->Write(); } // // Likelihood residual plots // if (drawOpt.find("RESIDUAL") != std::string::npos) { // WriteResidualPlots(); // } // Ratio and Shape Plots if (drawOpt.find("RATIO") != std::string::npos) { WriteRatioPlot(); } if (drawOpt.find("SHAPE") != std::string::npos) { WriteShapePlot(); if (drawOpt.find("RATIO") != std::string::npos) WriteShapeRatioPlot(); } // // RATIO // if (drawOpt.find("CANVMC") != std::string::npos) { // TCanvas* c1 = WriteMCCanvas(fDataHist, fMCHist); // c1->Write(); // delete c1; // } // // PDG // if (drawOpt.find("CANVPDG") != std::string::npos && fMCHist_Modes) { // TCanvas* c2 = WritePDGCanvas(fDataHist, fMCHist, fMCHist_Modes); // c2->Write(); // delete c2; // } if (fIsChi2 && !fIsDiag) { fResidualHist = (TH1D *)fMCHist->Clone((fName + "_RESIDUAL").c_str()); fResidualHist->GetYaxis()->SetTitle("#Delta#chi^{2}"); fResidualHist->Reset(); fChi2LessBinHist = (TH1D *)fMCHist->Clone((fName + "_Chi2NMinusOne").c_str()); fChi2LessBinHist->GetYaxis()->SetTitle("Total #chi^{2} without bin_{i}"); fChi2LessBinHist->Reset(); fIsWriting = true; (void)GetLikelihood(); fIsWriting = false; fResidualHist->Write((fName + "_RESIDUAL").c_str()); fChi2LessBinHist->Write((fName + "_Chi2NMinusOne").c_str()); } // Write Extra Histograms AutoWriteExtraTH1(); WriteExtraHistograms(); // Returning NUIS_LOG(SAM, "Written Histograms: " << fName); return; } //******************************************************************** void Measurement1D::WriteRatioPlot() { //******************************************************************** // Setup mc data ratios TH1D *dataRatio = (TH1D *)fDataHist->Clone((fName + "_data_RATIO").c_str()); TH1D *mcRatio = (TH1D *)fMCHist->Clone((fName + "_MC_RATIO").c_str()); // Extra MC Data Ratios for (int i = 0; i < mcRatio->GetNbinsX(); i++) { dataRatio->SetBinContent(i + 1, fDataHist->GetBinContent(i + 1) / fMCHist->GetBinContent(i + 1)); dataRatio->SetBinError(i + 1, fDataHist->GetBinError(i + 1) / fMCHist->GetBinContent(i + 1)); mcRatio->SetBinContent(i + 1, fMCHist->GetBinContent(i + 1) / fMCHist->GetBinContent(i + 1)); mcRatio->SetBinError(i + 1, fMCHist->GetBinError(i + 1) / fMCHist->GetBinContent(i + 1)); } // Write ratios mcRatio->Write(); dataRatio->Write(); delete mcRatio; delete dataRatio; } //******************************************************************** void Measurement1D::WriteShapePlot() { //******************************************************************** TH1D *mcShape = (TH1D *)fMCHist->Clone((fName + "_MC_SHAPE").c_str()); TH1D *dataShape = (TH1D *)fDataHist->Clone((fName + "_data_SHAPE").c_str()); // Set the shape covariance to calculate the chi2 if (!fShapeCovar) SetShapeCovar(); // Don't check error if (fShapeCovar) StatUtils::SetDataErrorFromCov(dataShape, fShapeCovar, 1E-38, false); double shapeScale = 1.0; if (fIsRawEvents) { shapeScale = fDataHist->Integral() / fMCHist->Integral(); } else { shapeScale = fDataHist->Integral("width") / fMCHist->Integral("width"); } mcShape->Scale(shapeScale); std::stringstream ss; ss << shapeScale; mcShape->SetTitle(ss.str().c_str()); mcShape->SetLineWidth(3); mcShape->SetLineStyle(7); mcShape->Write(); dataShape->Write(); delete mcShape; } //******************************************************************** void Measurement1D::WriteShapeRatioPlot() { //******************************************************************** // Get a mcshape histogram TH1D *mcShape = (TH1D *)fMCHist->Clone((fName + "_MC_SHAPE").c_str()); double shapeScale = 1.0; if (fIsRawEvents) { shapeScale = fDataHist->Integral() / fMCHist->Integral(); } else { shapeScale = fDataHist->Integral("width") / fMCHist->Integral("width"); } mcShape->Scale(shapeScale); // Create shape ratio histograms TH1D *mcShapeRatio = (TH1D *)mcShape->Clone((fName + "_MC_SHAPE_RATIO").c_str()); TH1D *dataShapeRatio = (TH1D *)fDataHist->Clone((fName + "_data_SHAPE_RATIO").c_str()); // Divide the histograms mcShapeRatio->Divide(mcShape); dataShapeRatio->Divide(mcShape); // Colour the shape ratio plots mcShapeRatio->SetLineWidth(3); mcShapeRatio->SetLineStyle(7); mcShapeRatio->Write(); dataShapeRatio->Write(); delete mcShapeRatio; delete dataShapeRatio; } //// CRAP TO BE REMOVED //******************************************************************** void Measurement1D::SetupMeasurement(std::string inputfile, std::string type, FitWeight *rw, std::string fkdt) { //******************************************************************** nuiskey samplekey = Config::CreateKey("sample"); samplekey.Set("name", fName); samplekey.Set("type", type); samplekey.Set("input", inputfile); fSettings = LoadSampleSettings(samplekey); // Reset everything to NULL // Init(); // Check if name contains Evt, indicating that it is a raw number of events // measurements and should thus be treated as once fIsRawEvents = false; if ((fName.find("Evt") != std::string::npos) && fIsRawEvents == false) { fIsRawEvents = true; NUIS_LOG(SAM, "Found event rate measurement but fIsRawEvents == false!"); NUIS_LOG(SAM, "Overriding this and setting fIsRawEvents == true!"); } fIsEnu1D = false; if (fName.find("XSec_1DEnu") != std::string::npos) { fIsEnu1D = true; NUIS_LOG(SAM, "::" << fName << "::"); NUIS_LOG(SAM, "Found XSec Enu measurement, applying flux integrated scaling, " "not flux averaged!"); } if (fIsEnu1D && fIsRawEvents) { NUIS_ERR(FTL, "Found 1D Enu XSec distribution AND fIsRawEvents, is this " "really correct?!"); NUIS_ERR(FTL, "Check experiment constructor for " << fName << " and correct this!"); NUIS_ERR(FTL, "I live in " << __FILE__ << ":" << __LINE__); throw; } fRW = rw; if (!fInput and !fIsJoint) SetupInputs(inputfile); // Set Default Options SetFitOptions(fDefaultTypes); // Set Passed Options SetFitOptions(type); // Still adding support for flat flux inputs // // Set Enu Flux Scaling // if (isFlatFluxFolding) this->Input()->ApplyFluxFolding( // this->defaultFluxHist ); // FinaliseMeasurement(); } //******************************************************************** void Measurement1D::SetupDefaultHist() { //******************************************************************** // Setup fMCHist fMCHist = (TH1D *)fDataHist->Clone(); fMCHist->SetNameTitle((fName + "_MC").c_str(), (fName + "_MC" + fPlotTitles).c_str()); // Setup fMCFine Int_t nBins = fMCHist->GetNbinsX(); fMCFine = new TH1D( (fName + "_MC_FINE").c_str(), (fName + "_MC_FINE" + fPlotTitles).c_str(), nBins * 6, fMCHist->GetBinLowEdge(1), fMCHist->GetBinLowEdge(nBins + 1)); fMCStat = (TH1D *)fMCHist->Clone(); fMCStat->Reset(); fMCHist->Reset(); fMCFine->Reset(); // Setup the NEUT Mode Array PlotUtils::CreateNeutModeArray((TH1D *)fMCHist, (TH1 **)fMCHist_PDG); PlotUtils::ResetNeutModeArray((TH1 **)fMCHist_PDG); // Setup bin masks using sample name if (fIsMask) { std::string maskloc = FitPar::Config().GetParDIR(fName + ".mask"); if (maskloc.empty()) { maskloc = FitPar::GetDataBase() + "/masks/" + fName + ".mask"; } SetBinMask(maskloc); } fMCHist_Modes = new TrueModeStack((fName + "_MODES").c_str(), ("True Channels"), fMCHist); SetAutoProcessTH1(fMCHist_Modes, kCMD_Reset, kCMD_Norm, kCMD_Write); return; } //******************************************************************** void Measurement1D::SetDataValues(std::string dataFile) { //******************************************************************** // Override this function if the input file isn't in a suitable format NUIS_LOG(SAM, "Reading data from: " << dataFile.c_str()); fDataHist = PlotUtils::GetTH1DFromFile(dataFile, (fName + "_data"), fPlotTitles); fDataTrue = (TH1D *)fDataHist->Clone(); // Number of data points is number of bins fNDataPointsX = fDataHist->GetXaxis()->GetNbins(); return; }; //******************************************************************** void Measurement1D::SetDataFromDatabase(std::string inhistfile, std::string histname) { //******************************************************************** NUIS_LOG(SAM, "Filling histogram from " << inhistfile << "->" << histname); fDataHist = PlotUtils::GetTH1DFromRootFile( (GeneralUtils::GetTopLevelDir() + "/data/" + inhistfile), histname); fDataHist->SetNameTitle((fName + "_data").c_str(), (fName + "_data").c_str()); return; }; //******************************************************************** void Measurement1D::SetDataFromFile(std::string inhistfile, std::string histname) { //******************************************************************** NUIS_LOG(SAM, "Filling histogram from " << inhistfile << "->" << histname); fDataHist = PlotUtils::GetTH1DFromRootFile((inhistfile), histname); fDataHist->SetNameTitle((fName + "_data").c_str(), (fName + "_data").c_str()); return; }; //******************************************************************** void Measurement1D::SetCovarMatrix(std::string covarFile) { //******************************************************************** // Covariance function, only really used when reading in the MB Covariances. TFile *tempFile = new TFile(covarFile.c_str(), "READ"); TH2D *covarPlot = new TH2D(); TH2D *fFullCovarPlot = new TH2D(); std::string covName = ""; std::string covOption = FitPar::Config().GetParS("thrown_covariance"); if (fIsShape || fIsFree) covName = "shp_"; if (fIsDiag) covName += "diag"; else covName += "full"; covarPlot = (TH2D *)tempFile->Get((covName + "cov").c_str()); if (!covOption.compare("SUB")) fFullCovarPlot = (TH2D *)tempFile->Get((covName + "cov").c_str()); else if (!covOption.compare("FULL")) fFullCovarPlot = (TH2D *)tempFile->Get("fullcov"); else { NUIS_ERR(WRN, "Incorrect thrown_covariance option in parameters."); } int dim = int(fDataHist->GetNbinsX()); //-this->masked->Integral()); int covdim = int(fDataHist->GetNbinsX()); this->covar = new TMatrixDSym(dim); fFullCovar = new TMatrixDSym(dim); fDecomp = new TMatrixDSym(dim); int row, column = 0; row = 0; column = 0; for (Int_t i = 0; i < covdim; i++) { // if (this->masked->GetBinContent(i+1) > 0) continue; for (Int_t j = 0; j < covdim; j++) { // if (this->masked->GetBinContent(j+1) > 0) continue; (*this->covar)(row, column) = covarPlot->GetBinContent(i + 1, j + 1); (*fFullCovar)(row, column) = fFullCovarPlot->GetBinContent(i + 1, j + 1); column++; } column = 0; row++; } // Set bin errors on data if (!fIsDiag) { StatUtils::SetDataErrorFromCov(fDataHist, fFullCovar); } // Get Deteriminant and inverse matrix // fCovDet = this->covar->Determinant(); TDecompSVD LU = TDecompSVD(*this->covar); this->covar = new TMatrixDSym(dim, LU.Invert().GetMatrixArray(), ""); return; }; //******************************************************************** // Sets the covariance matrix from a provided file in a text format // scale is a multiplicative pre-factor to apply in the case where the // covariance is given in some unit (e.g. 1E-38) void Measurement1D::SetCovarMatrixFromText(std::string covarFile, int dim, double scale) { //******************************************************************** // Make a counter to track the line number int row = 0; std::string line; std::ifstream covarread(covarFile.c_str(), std::ifstream::in); this->covar = new TMatrixDSym(dim); fFullCovar = new TMatrixDSym(dim); if (covarread.is_open()) { NUIS_LOG(SAM, "Reading covariance matrix from file: " << covarFile); } else { NUIS_ABORT("Covariance matrix provided is incorrect: " << covarFile); } // Loop over the lines in the file while (std::getline(covarread >> std::ws, line, '\n')) { int column = 0; // Loop over entries and insert them into matrix std::vector entries = GeneralUtils::ParseToDbl(line, " "); if (entries.size() <= 1) { NUIS_ERR(WRN, "SetCovarMatrixFromText -> Covariance matrix only has <= 1 " "entries on this line: " << row); } for (std::vector::iterator iter = entries.begin(); iter != entries.end(); iter++) { (*covar)(row, column) = *iter; (*fFullCovar)(row, column) = *iter; column++; } row++; } covarread.close(); // Scale the actualy covariance matrix by some multiplicative factor (*fFullCovar) *= scale; // Robust matrix inversion method TDecompSVD LU = TDecompSVD(*this->covar); // THIS IS ACTUALLY THE INVERSE COVARIANCE MATRIXA AAAAARGH delete this->covar; this->covar = new TMatrixDSym(dim, LU.Invert().GetMatrixArray(), ""); // Now need to multiply by the scaling factor // If the covariance (*this->covar) *= 1. / (scale); return; }; //******************************************************************** void Measurement1D::SetCovarMatrixFromCorrText(std::string corrFile, int dim) { //******************************************************************** // Make a counter to track the line number int row = 0; std::string line; std::ifstream corr(corrFile.c_str(), std::ifstream::in); this->covar = new TMatrixDSym(dim); this->fFullCovar = new TMatrixDSym(dim); if (corr.is_open()) { NUIS_LOG(SAM, "Reading and converting correlation matrix from file: " << corrFile); } else { NUIS_ABORT("Correlation matrix provided is incorrect: " << corrFile); } while (std::getline(corr >> std::ws, line, '\n')) { int column = 0; // Loop over entries and insert them into matrix // Multiply by the errors to get the covariance, rather than the correlation // matrix std::vector entries = GeneralUtils::ParseToDbl(line, " "); for (std::vector::iterator iter = entries.begin(); iter != entries.end(); iter++) { double val = (*iter) * this->fDataHist->GetBinError(row + 1) * 1E38 * this->fDataHist->GetBinError(column + 1) * 1E38; if (val == 0) { NUIS_ABORT("Found a zero value in the covariance matrix, assuming " "this is an error!"); } (*this->covar)(row, column) = val; (*this->fFullCovar)(row, column) = val; column++; } row++; } // Robust matrix inversion method TDecompSVD LU = TDecompSVD(*this->covar); delete this->covar; this->covar = new TMatrixDSym(dim, LU.Invert().GetMatrixArray(), ""); return; }; //******************************************************************** // FullUnits refers to if we have "real" unscaled units in the covariance // matrix, e.g. 1E-76. If this is the case we need to scale it so that the chi2 // contribution is correct NUISANCE internally assumes the covariance matrix has // units of 1E76 void Measurement1D::SetCovarFromDataFile(std::string covarFile, std::string covName, bool FullUnits) { //******************************************************************** NUIS_LOG(SAM, "Getting covariance from " << covarFile << "->" << covName); TFile *tempFile = new TFile(covarFile.c_str(), "READ"); TH2D *covPlot = (TH2D *)tempFile->Get(covName.c_str()); covPlot->SetDirectory(0); // Scale the covariance matrix if it comes in normal units if (FullUnits) { covPlot->Scale(1.E76); } int dim = covPlot->GetNbinsX(); fFullCovar = new TMatrixDSym(dim); for (int i = 0; i < dim; i++) { for (int j = 0; j < dim; j++) { (*fFullCovar)(i, j) = covPlot->GetBinContent(i + 1, j + 1); } } this->covar = (TMatrixDSym *)fFullCovar->Clone(); fDecomp = (TMatrixDSym *)fFullCovar->Clone(); TDecompSVD LU = TDecompSVD(*this->covar); this->covar = new TMatrixDSym(dim, LU.Invert().GetMatrixArray(), ""); TDecompChol LUChol = TDecompChol(*fDecomp); LUChol.Decompose(); fDecomp = new TMatrixDSym(dim, LU.GetU().GetMatrixArray(), ""); return; }; // //******************************************************************** // void Measurement1D::SetBinMask(std::string maskFile) { // //******************************************************************** // // Create a mask histogram. // int nbins = fDataHist->GetNbinsX(); // fMaskHist = // new TH1I((fName + "_fMaskHist").c_str(), // (fName + "_fMaskHist; Bin; Mask?").c_str(), nbins, 0, nbins); // std::string line; // std::ifstream mask(maskFile.c_str(), std::ifstream::in); // if (mask.is_open()) // LOG(SAM) << "Reading bin mask from file: " << maskFile << std::endl; // else // LOG(FTL) << " Cannot find mask file." << std::endl; // while (std::getline(mask >> std::ws, line, '\n')) { // std::vector entries = GeneralUtils::ParseToInt(line, " "); // // Skip lines with poorly formatted lines // if (entries.size() < 2) { // LOG(WRN) << "Measurement1D::SetBinMask(), couldn't parse line: " << // line // << std::endl; // continue; // } // // The first index should be the bin number, the second should be the // mask // // value. // fMaskHist->SetBinContent(entries[0], entries[1]); // } // // Set masked data bins to zero // PlotUtils::MaskBins(fDataHist, fMaskHist); // return; // } // //******************************************************************** // void Measurement1D::GetBinContents(std::vector& cont, // std::vector& err) { // //******************************************************************** // // Return a vector of the main bin contents // for (int i = 0; i < fMCHist->GetNbinsX(); i++) { // cont.push_back(fMCHist->GetBinContent(i + 1)); // err.push_back(fMCHist->GetBinError(i + 1)); // } // return; // }; /* XSec Functions */ // //******************************************************************** // void Measurement1D::SetFluxHistogram(std::string fluxFile, int minE, int // maxE, // double fluxNorm) { // //******************************************************************** // // Note this expects the flux bins to be given in terms of MeV // LOG(SAM) << "Reading flux from file: " << fluxFile << std::endl; // TGraph f(fluxFile.c_str(), "%lg %lg"); // fFluxHist = // new TH1D((fName + "_flux").c_str(), (fName + "; E_{#nu} (GeV)").c_str(), // f.GetN() - 1, minE, maxE); // Double_t* yVal = f.GetY(); // for (int i = 0; i < fFluxHist->GetNbinsX(); ++i) // fFluxHist->SetBinContent(i + 1, yVal[i] * fluxNorm); // }; // //******************************************************************** // double Measurement1D::TotalIntegratedFlux(std::string intOpt, double low, // double high) { // //******************************************************************** // if (fInput->GetType() == kGiBUU) { // return 1.0; // } // // The default case of low = -9999.9 and high = -9999.9 // if (low == -9999.9) low = this->EnuMin; // if (high == -9999.9) high = this->EnuMax; // int minBin = fFluxHist->GetXaxis()->FindBin(low); // int maxBin = fFluxHist->GetXaxis()->FindBin(high); // // Get integral over custom range // double integral = fFluxHist->Integral(minBin, maxBin + 1, intOpt.c_str()); // return integral; // }; diff --git a/src/FitBase/Measurement1D.h b/src/FitBase/Measurement1D.h index aa02f5b..db4b55a 100644 --- a/src/FitBase/Measurement1D.h +++ b/src/FitBase/Measurement1D.h @@ -1,659 +1,659 @@ // 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 "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. /// /// 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 + /// are conflicting. Any options separated with the '/' symbol are non conflicting + /// and can be given together, whereas any separated 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 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) TH1D *fResidualHist; TH1D *fChi2LessBinHist; 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* fShapeInvert; ///< Inverted 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 fUseShapeNormDecomp; 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? bool fIsWriting; /// 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/Measurement2D.cxx b/src/FitBase/Measurement2D.cxx index 1758988..75ffeef 100644 --- a/src/FitBase/Measurement2D.cxx +++ b/src/FitBase/Measurement2D.cxx @@ -1,2139 +1,2143 @@ // 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 "Measurement2D.h" #include "TDecompChol.h" //******************************************************************** Measurement2D::Measurement2D(void) { //******************************************************************** covar = NULL; fDecomp = NULL; fFullCovar = NULL; fMCHist = NULL; fMCFine = NULL; fDataHist = NULL; fMCHist_X = NULL; fMCHist_Y = NULL; fDataHist_X = NULL; fDataHist_Y = NULL; fMaskHist = NULL; fMapHist = NULL; fDataOrig = NULL; fDataTrue = NULL; fMCWeighted = NULL; fResidualHist = NULL; fChi2LessBinHist = NULL; fDefaultTypes = "FIX/FULL/CHI2"; fAllowedTypes = "FIX,FREE,SHAPE/FULL,DIAG/CHI2/NORM/ENUCORR/Q2CORR/ENU1D/FITPROJX/" "FITPROJY"; fIsFix = false; fIsShape = false; fIsFree = false; fIsDiag = false; fIsFull = false; fAddNormPen = false; fIsMask = false; fIsChi2SVD = false; fIsRawEvents = false; fIsDifXSec = false; fIsEnu = false; // XSec Scalings fScaleFactor = -1.0; fCurrentNorm = 1.0; // Histograms fDataHist = NULL; fDataTrue = NULL; fMCHist = NULL; fMCFine = NULL; fMCWeighted = NULL; fMaskHist = NULL; // Covar covar = NULL; fFullCovar = NULL; fCovar = NULL; fInvert = NULL; fDecomp = NULL; // Fake Data fFakeDataInput = ""; fFakeDataFile = NULL; // Options fDefaultTypes = "FIX/FULL/CHI2"; fAllowedTypes = "FIX,FREE,SHAPE/FULL,DIAG/CHI2/NORM/ENUCORR/Q2CORR/ENU1D/MASK"; fIsFix = false; fIsShape = false; fIsFree = false; fIsDiag = false; fIsFull = false; fAddNormPen = false; fIsMask = false; fIsChi2SVD = false; fIsRawEvents = false; fIsDifXSec = false; fIsEnu1D = false; fIsWriting = false; // Inputs fInput = NULL; fRW = NULL; // Extra Histograms fMCHist_Modes = NULL; } //******************************************************************** Measurement2D::~Measurement2D(void) { //******************************************************************** if (fDataHist) delete fDataHist; if (fDataTrue) delete fDataTrue; if (fMCHist) delete fMCHist; if (fMCFine) delete fMCFine; if (fMCWeighted) delete fMCWeighted; if (fMaskHist) delete fMaskHist; if (covar) delete covar; if (fFullCovar) delete fFullCovar; if (fCovar) delete fCovar; if (fInvert) delete fInvert; if (fDecomp) delete fDecomp; delete fResidualHist; delete fChi2LessBinHist; } //******************************************************************** void Measurement2D::FinaliseSampleSettings() { //******************************************************************** MeasurementBase::FinaliseSampleSettings(); // Setup naming + renaming fName = fSettings.GetName(); fSettings.SetS("originalname", fName); if (fSettings.Has("rename")) { fName = fSettings.GetS("rename"); fSettings.SetS("name", fName); } // Setup all other options NUIS_LOG(SAM, "Finalising Sample Settings: " << fName); if ((fSettings.GetS("originalname").find("Evt") != std::string::npos)) { fIsRawEvents = true; NUIS_LOG(SAM, "Found event rate measurement but using poisson likelihoods."); } if (fSettings.GetS("originalname").find("Enu") != std::string::npos) { fIsEnu1D = true; NUIS_LOG(SAM, "::" << fName << "::"); NUIS_LOG(SAM, "Found XSec Enu measurement, applying flux integrated scaling, " << "not flux averaged!"); } if (fIsEnu1D && fIsRawEvents) { NUIS_ERR(FTL, "Found 2D Enu XSec distribution AND fIsRawEvents, is this " "really correct?!"); NUIS_ERR(FTL, "Check experiment constructor for " << fName << " and correct this!"); NUIS_ABORT("I live in " << __FILE__ << ":" << __LINE__); } if (!fRW) fRW = FitBase::GetRW(); if (!fInput) SetupInputs(fSettings.GetS("input")); // Setup options SetFitOptions(fDefaultTypes); // defaults SetFitOptions(fSettings.GetS("type")); // user specified EnuMin = GeneralUtils::StrToDbl(fSettings.GetS("enu_min")); EnuMax = GeneralUtils::StrToDbl(fSettings.GetS("enu_max")); } void Measurement2D::CreateDataHistogram(int dimx, double *binx, int dimy, double *biny) { if (fDataHist) delete fDataHist; NUIS_LOG(SAM, "Creating Data Histogram dim : " << dimx << " " << dimy); fDataHist = new TH2D((fSettings.GetName() + "_data").c_str(), (fSettings.GetFullTitles()).c_str(), dimx - 1, binx, dimy - 1, biny); } void Measurement2D::SetDataFromTextFile(std::string data, std::string binx, std::string biny) { // Get the data hist fDataHist = PlotUtils::GetTH2DFromTextFile(data, binx, biny); // Set the name properly fDataHist->SetName((fSettings.GetName() + "_data").c_str()); fDataHist->SetTitle(fSettings.GetFullTitles().c_str()); } void Measurement2D::SetDataFromRootFile(std::string datfile, std::string histname) { NUIS_LOG(SAM, "Reading data from root file: " << datfile << ";" << histname); fDataHist = PlotUtils::GetTH2DFromRootFile(datfile, histname); fDataHist->SetNameTitle((fSettings.GetName() + "_data").c_str(), (fSettings.GetFullTitles()).c_str()); } void Measurement2D::SetDataValuesFromTextFile(std::string datfile, TH2D *hist) { NUIS_LOG(SAM, "Setting data values from text file"); if (!hist) hist = fDataHist; // Read TH2D From textfile TH2D *valhist = (TH2D *)hist->Clone(); valhist->Reset(); PlotUtils::Set2DHistFromText(datfile, valhist, 1.0, true); NUIS_LOG(SAM, " -> Filling values from read hist."); for (int i = 0; i < valhist->GetNbinsX(); i++) { for (int j = 0; j < valhist->GetNbinsY(); j++) { hist->SetBinContent(i + 1, j + 1, valhist->GetBinContent(i + 1, j + 1)); } } NUIS_LOG(SAM, " --> Done"); } void Measurement2D::SetDataErrorsFromTextFile(std::string datfile, TH2D *hist) { NUIS_LOG(SAM, "Setting data errors from text file"); if (!hist) hist = fDataHist; // Read TH2D From textfile TH2D *valhist = (TH2D *)hist->Clone(); valhist->Reset(); PlotUtils::Set2DHistFromText(datfile, valhist, 1.0); // Fill Errors NUIS_LOG(SAM, " -> Filling errors from read hist."); for (int i = 0; i < valhist->GetNbinsX(); i++) { for (int j = 0; j < valhist->GetNbinsY(); j++) { hist->SetBinError(i + 1, j + 1, valhist->GetBinContent(i + 1, j + 1)); } } NUIS_LOG(SAM, " --> Done"); } void Measurement2D::SetMapValuesFromText(std::string dataFile) { TH2D *hist = fDataHist; std::vector edgex; std::vector edgey; for (int i = 0; i <= hist->GetNbinsX(); i++) edgex.push_back(hist->GetXaxis()->GetBinLowEdge(i + 1)); for (int i = 0; i <= hist->GetNbinsY(); i++) edgey.push_back(hist->GetYaxis()->GetBinLowEdge(i + 1)); fMapHist = new TH2I((fName + "_map").c_str(), (fName + fPlotTitles).c_str(), edgex.size() - 1, &edgex[0], edgey.size() - 1, &edgey[0]); NUIS_LOG(SAM, "Reading map from: " << dataFile); PlotUtils::Set2DHistFromText(dataFile, fMapHist, 1.0); } //******************************************************************** void Measurement2D::SetPoissonErrors() { //******************************************************************** if (!fDataHist) { NUIS_ERR(FTL, "Need a data hist to setup possion errors! "); NUIS_ABORT("Setup Data First!"); } for (int i = 0; i < fDataHist->GetNbinsX() + 1; i++) { fDataHist->SetBinError(i + 1, sqrt(fDataHist->GetBinContent(i + 1))); } } //******************************************************************** void Measurement2D::SetCovarFromDiagonal(TH2D *data) { //******************************************************************** if (!data and fDataHist) { data = fDataHist; } if (data) { NUIS_LOG(SAM, "Setting diagonal covariance for: " << data->GetName()); fFullCovar = StatUtils::MakeDiagonalCovarMatrix(data); covar = StatUtils::GetInvert(fFullCovar,true); fDecomp = StatUtils::GetDecomp(fFullCovar); } else { NUIS_ABORT("No data input provided to set diagonal covar from!"); } // if (!fIsDiag) { // ERR(FTL) << "SetCovarMatrixFromDiag called for measurement " // << "that is not set as diagonal." << std::endl; // throw; // } } //******************************************************************** void Measurement2D::SetCovarFromTextFile(std::string covfile, int dim) { //******************************************************************** if (dim == -1) { dim = this->GetNDOF(); } NUIS_LOG(SAM, "Reading covariance from text file: " << covfile << " " << dim); fFullCovar = StatUtils::GetCovarFromTextFile(covfile, dim); covar = StatUtils::GetInvert(fFullCovar,true); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void Measurement2D::SetCovarFromRootFile(std::string covfile, std::string histname) { //******************************************************************** NUIS_LOG(SAM, "Reading covariance from text file: " << covfile << ";" << histname); fFullCovar = StatUtils::GetCovarFromRootFile(covfile, histname); covar = StatUtils::GetInvert(fFullCovar,true); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void Measurement2D::SetCovarInvertFromTextFile(std::string covfile, int dim) { //******************************************************************** if (dim == -1) { dim = this->GetNDOF(); } NUIS_LOG(SAM, "Reading inverted covariance from text file: " << covfile); covar = StatUtils::GetCovarFromTextFile(covfile, dim); fFullCovar = StatUtils::GetInvert(covar,true); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void Measurement2D::SetCovarInvertFromRootFile(std::string covfile, std::string histname) { //******************************************************************** NUIS_LOG(SAM, "Reading inverted covariance from text file: " << covfile << ";" << histname); covar = StatUtils::GetCovarFromRootFile(covfile, histname); fFullCovar = StatUtils::GetInvert(covar,true); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void Measurement2D::SetCorrelationFromTextFile(std::string covfile, int dim) { //******************************************************************** if (dim == -1) dim = this->GetNDOF(); NUIS_LOG(SAM, "Reading data correlations from text file: " << covfile << ";" << dim); TMatrixDSym *correlation = StatUtils::GetCovarFromTextFile(covfile, dim); if (!fDataHist) { NUIS_ABORT("Trying to set correlations from text file but there is no " "data to build it from. \n" << "In constructor make sure data is set before " "SetCorrelationFromTextFile is called. \n"); } // Fill covar from data errors and correlations fFullCovar = new TMatrixDSym(dim); for (int i = 0; i < fDataHist->GetNbinsX(); i++) { for (int j = 0; j < fDataHist->GetNbinsX(); j++) { (*fFullCovar)(i, j) = (*correlation)(i, j) * fDataHist->GetBinError(i + 1) * fDataHist->GetBinError(j + 1) * 1.E76; } } // Fill other covars. covar = StatUtils::GetInvert(fFullCovar,true); fDecomp = StatUtils::GetDecomp(fFullCovar); delete correlation; } //******************************************************************** void Measurement2D::SetCorrelationFromRootFile(std::string covfile, std::string histname) { //******************************************************************** NUIS_LOG(SAM, "Reading data correlations from text file: " << covfile << ";" << histname); TMatrixDSym *correlation = StatUtils::GetCovarFromRootFile(covfile, histname); if (!fDataHist) { NUIS_ABORT("Trying to set correlations from text file but there is no " "data to build it from. \n" << "In constructor make sure data is set before " "SetCorrelationFromTextFile is called. \n"); } // Fill covar from data errors and correlations fFullCovar = new TMatrixDSym(fDataHist->GetNbinsX()); for (int i = 0; i < fDataHist->GetNbinsX(); i++) { for (int j = 0; j < fDataHist->GetNbinsX(); j++) { (*fFullCovar)(i, j) = (*correlation)(i, j) * fDataHist->GetBinError(i + 1) * fDataHist->GetBinError(j + 1) * 1.E76; } } // Fill other covars. covar = StatUtils::GetInvert(fFullCovar,true); fDecomp = StatUtils::GetDecomp(fFullCovar); delete correlation; } //******************************************************************** void Measurement2D::SetCholDecompFromTextFile(std::string covfile, int dim) { //******************************************************************** if (dim == -1) { dim = this->GetNDOF(); } NUIS_LOG(SAM, "Reading cholesky from text file: " << covfile << " " << dim); TMatrixD *temp = StatUtils::GetMatrixFromTextFile(covfile, dim, dim); TMatrixD *trans = (TMatrixD *)temp->Clone(); trans->T(); (*trans) *= (*temp); fFullCovar = new TMatrixDSym(dim, trans->GetMatrixArray(), ""); covar = StatUtils::GetInvert(fFullCovar,true); fDecomp = StatUtils::GetDecomp(fFullCovar); delete temp; delete trans; } //******************************************************************** void Measurement2D::SetCholDecompFromRootFile(std::string covfile, std::string histname) { //******************************************************************** NUIS_LOG(SAM, "Reading cholesky decomp from root file: " << covfile << ";" << histname); TMatrixD *temp = StatUtils::GetMatrixFromRootFile(covfile, histname); TMatrixD *trans = (TMatrixD *)temp->Clone(); trans->T(); (*trans) *= (*temp); fFullCovar = new TMatrixDSym(temp->GetNrows(), trans->GetMatrixArray(), ""); covar = StatUtils::GetInvert(fFullCovar,true); fDecomp = StatUtils::GetDecomp(fFullCovar); delete temp; delete trans; } void Measurement2D::SetShapeCovar() { // Return if this is missing any pre-requisites if (!fFullCovar) return; if (!fDataHist) return; // Also return if it's bloody stupid under the circumstances if (fIsDiag) return; fShapeCovar = StatUtils::ExtractShapeOnlyCovar(fFullCovar, fDataHist, fMapHist); return; } //******************************************************************** void Measurement2D::ScaleData(double scale) { //******************************************************************** fDataHist->Scale(scale); } //******************************************************************** void Measurement2D::ScaleDataErrors(double scale) { //******************************************************************** for (int i = 0; i < fDataHist->GetNbinsX(); i++) { for (int j = 0; j < fDataHist->GetNbinsY(); j++) { fDataHist->SetBinError(i + 1, j + 1, fDataHist->GetBinError(i + 1, j + 1) * scale); } } } //******************************************************************** void Measurement2D::ScaleCovar(double scale) { //******************************************************************** (*fFullCovar) *= scale; (*covar) *= 1.0 / scale; (*fDecomp) *= sqrt(scale); } //******************************************************************** void Measurement2D::SetBinMask(std::string maskfile) { //******************************************************************** if (!fIsMask) return; NUIS_LOG(SAM, "Reading bin mask from file: " << maskfile); // Create a mask histogram with dim of data int nbinsx = fDataHist->GetNbinsX(); int nbinxy = fDataHist->GetNbinsY(); fMaskHist = new TH2I((fSettings.GetName() + "_BINMASK").c_str(), (fSettings.GetName() + "_BINMASK; Bin; Mask?").c_str(), nbinsx, 0, nbinsx, nbinxy, 0, nbinxy); std::string line; std::ifstream mask(maskfile.c_str(), std::ifstream::in); if (!mask.is_open()) { NUIS_LOG(FTL, " Cannot find mask file."); throw; } while (std::getline(mask >> std::ws, line, '\n')) { std::vector entries = GeneralUtils::ParseToInt(line, " "); // Skip lines with poorly formatted lines if (entries.size() < 2) { NUIS_LOG(WRN, "Measurement2D::SetBinMask(), couldn't parse line: " << line); continue; } // The first index should be the bin number, the second should be the mask // value. int val = 0; if (entries[2] > 0) val = 1; fMaskHist->SetBinContent(entries[0], entries[1], val); } // Apply masking by setting masked data bins to zero PlotUtils::MaskBins(fDataHist, fMaskHist); return; } //******************************************************************** void Measurement2D::FinaliseMeasurement() { //******************************************************************** NUIS_LOG(SAM, "Finalising Measurement: " << fName); if (fSettings.GetB("onlymc")) { if (fDataHist) delete fDataHist; fDataHist = new TH2D("empty_data", "empty_data", 1, 0.0, 1.0, 1, 0.0, 1.0); } // Make sure data is setup if (!fDataHist) { NUIS_ABORT("No data has been setup inside " << fName << " constructor!"); } // Make sure covariances are setup if (!fFullCovar) { fIsDiag = true; SetCovarFromDiagonal(fDataHist); } else if (fIsDiag) { // Have covariance but also set Diag NUIS_LOG(SAM, "Have full covariance for sample " << GetName() << " but only using diagonal elements for likelihood"); size_t nbins = fFullCovar->GetNcols(); - for (int i = 0; i < nbins; ++i) { - for (int j = 0; j < nbins; ++j) { + for (size_t i = 0; i < nbins; ++i) { + for (size_t j = 0; j < nbins; ++j) { if (i != j) { (*fFullCovar)[i][j] = 0; } } } delete covar; covar = NULL; delete fDecomp; fDecomp = NULL; } if (!covar) { covar = StatUtils::GetInvert(fFullCovar,true); } if (!fDecomp) { fDecomp = StatUtils::GetDecomp(fFullCovar); } // If shape only, set covar and fDecomp using the shape-only matrix (if set) if (fIsShape && fShapeCovar && FitPar::Config().GetParB("UseShapeCovar")) { if (covar) delete covar; covar = StatUtils::GetInvert(fShapeCovar,true); if (fDecomp) delete fDecomp; fDecomp = StatUtils::GetDecomp(fFullCovar); fUseShapeNormDecomp = FitPar::Config().GetParB("UseShapeNormDecomp"); if (fUseShapeNormDecomp) { fNormError = 0; // From https://arxiv.org/pdf/2003.00088.pdf for (int i = 0; i < fFullCovar->GetNcols(); ++i) { for (int j = 0; j < fFullCovar->GetNcols(); ++j) { fNormError += (*fFullCovar)[i][j]; } } NUIS_LOG(SAM, "Sample: " << fName << ", using shape/norm decomp with norm error: " << fNormError); } } // Setup fMCHist from data fMCHist = (TH2D *)fDataHist->Clone(); fMCHist->SetNameTitle((fSettings.GetName() + "_MC").c_str(), (fSettings.GetFullTitles()).c_str()); fMCHist->Reset(); // Setup fMCFine fMCFine = new TH2D( "mcfine", "mcfine", fDataHist->GetNbinsX() * 6, fMCHist->GetXaxis()->GetBinLowEdge(1), fMCHist->GetXaxis()->GetBinLowEdge(fDataHist->GetNbinsX() + 1), fDataHist->GetNbinsY() * 6, fMCHist->GetYaxis()->GetBinLowEdge(1), fMCHist->GetYaxis()->GetBinLowEdge(fDataHist->GetNbinsY() + 1)); fMCFine->SetNameTitle((fSettings.GetName() + "_MC_FINE").c_str(), (fSettings.GetFullTitles()).c_str()); fMCFine->Reset(); // Setup MC Stat fMCStat = (TH2D *)fMCHist->Clone(); fMCStat->Reset(); // Search drawopts for possible types to include by default std::string drawopts = FitPar::Config().GetParS("drawopts"); if (drawopts.find("MODES") != std::string::npos) { fMCHist_Modes = new TrueModeStack((fSettings.GetName() + "_MODES").c_str(), - ("True Channels"), fMCHist); + ("True Channels"), fMCHist); + fMCHist_Modes ->SetTitleX(fDataHist->GetXaxis()->GetTitle()); + fMCHist_Modes ->SetTitleY(fDataHist->GetYaxis()->GetTitle()); + fMCHist_Modes ->SetTitleZ(fDataHist->GetZaxis()->GetTitle()); + SetAutoProcessTH1(fMCHist_Modes); } if (fSettings.Has("maskfile") && fSettings.Has("maskhist")) { fMaskHist = PlotUtils::GetTH2FromRootFile(fSettings.GetS("maskfile"), fSettings.GetS("maskhist")); fIsMask = bool(fMaskHist); NUIS_LOG(SAM, "Loaded mask histogram: " << fSettings.GetS("maskhist") << " from " << fSettings.GetS("maskfile")); } else if (fIsMask) { // Setup bin masks using sample name std::string curname = fName; std::string origname = fSettings.GetS("originalname"); // Check rename.mask std::string maskloc = FitPar::Config().GetParDIR(curname + ".mask"); // Check origname.mask if (maskloc.empty()) maskloc = FitPar::Config().GetParDIR(origname + ".mask"); // Check database if (maskloc.empty()) { maskloc = FitPar::GetDataBase() + "/masks/" + origname + ".mask"; } // Setup Bin Mask SetBinMask(maskloc); } if (fScaleFactor < 0) { NUIS_ERR(FTL, "I found a negative fScaleFactor in " << __FILE__ << ":" << __LINE__); NUIS_ERR(FTL, "fScaleFactor = " << fScaleFactor); NUIS_ABORT("EXITING"); } if (fAddNormPen) { if (!fUseShapeNormDecomp) { fNormError = fSettings.GetNormError(); } if (fNormError <= 0.0) { NUIS_ERR(FTL, "Norm error for class " << fName << " is 0.0!"); NUIS_ABORT("If you want to use it please add fNormError=VAL"); } } // Create and fill Weighted Histogram if (!fMCWeighted) { fMCWeighted = (TH2D *)fMCHist->Clone(); fMCWeighted->SetNameTitle((fName + "_MCWGHTS").c_str(), (fName + "_MCWGHTS" + fPlotTitles).c_str()); fMCWeighted->GetYaxis()->SetTitle("Weighted Events"); } if (!fMapHist) fMapHist = StatUtils::GenerateMap(fDataHist); } //******************************************************************** void Measurement2D::SetFitOptions(std::string opt) { //******************************************************************** // Do nothing if default given if (opt == "DEFAULT") return; // CHECK Conflicting Fit Options std::vector fit_option_allow = GeneralUtils::ParseToStr(fAllowedTypes, "/"); for (UInt_t i = 0; i < fit_option_allow.size(); i++) { std::vector fit_option_section = GeneralUtils::ParseToStr(fit_option_allow.at(i), ","); bool found_option = false; for (UInt_t j = 0; j < fit_option_section.size(); j++) { std::string av_opt = fit_option_section.at(j); if (!found_option and opt.find(av_opt) != std::string::npos) { found_option = true; } else if (found_option and opt.find(av_opt) != std::string::npos) { NUIS_ABORT( "ERROR: Conflicting fit options provided: " << opt << std::endl << "Conflicting group = " << fit_option_section.at(i) << std::endl << "You should only supply one of these options in card file."); } } } // Check all options are allowed std::vector fit_options_input = GeneralUtils::ParseToStr(opt, "/"); for (UInt_t i = 0; i < fit_options_input.size(); i++) { if (fAllowedTypes.find(fit_options_input.at(i)) == std::string::npos) { NUIS_ERR(FTL, "ERROR: Fit Option '" << fit_options_input.at(i) << "' Provided is not allowed for this measurement."); - NUIS_ERR(FTL, "Fit Options should be provided as a '/' seperated list " + NUIS_ERR(FTL, "Fit Options should be provided as a '/' separated list " "(e.g. FREE/DIAG/NORM)"); NUIS_ABORT("Available options for " << fName << " are '" << fAllowedTypes << "'"); } } // Set TYPE fFitType = opt; // FIX,SHAPE,FREE if (opt.find("FIX") != std::string::npos) { fIsFree = fIsShape = false; fIsFix = true; } else if (opt.find("SHAPE") != std::string::npos) { fIsFree = fIsFix = false; fIsShape = true; } else if (opt.find("FREE") != std::string::npos) { fIsFix = fIsShape = false; fIsFree = true; } // DIAG,FULL (or default to full) if (opt.find("DIAG") != std::string::npos) { fIsDiag = true; fIsFull = false; } else if (opt.find("FULL") != std::string::npos) { fIsDiag = false; fIsFull = true; } // CHI2/LL (OTHERS?) if (opt.find("LOG") != std::string::npos) { fIsChi2 = false; NUIS_ERR(FTL, "No other LIKELIHOODS properly supported!"); NUIS_ABORT("Try to use a chi2!"); } else { fIsChi2 = true; } // EXTRAS if (opt.find("RAW") != std::string::npos) fIsRawEvents = true; if (opt.find("DIF") != std::string::npos) fIsDifXSec = true; if (opt.find("ENU1D") != std::string::npos) fIsEnu1D = true; if (opt.find("NORM") != std::string::npos) fAddNormPen = true; if (opt.find("MASK") != std::string::npos) fIsMask = true; // Set TYPE fFitType = opt; // FIX,SHAPE,FREE if (opt.find("FIX") != std::string::npos) { fIsFree = fIsShape = false; fIsFix = true; } else if (opt.find("SHAPE") != std::string::npos) { fIsFree = fIsFix = false; fIsShape = true; } else if (opt.find("FREE") != std::string::npos) { fIsFix = fIsShape = false; fIsFree = true; } // DIAG,FULL (or default to full) if (opt.find("DIAG") != std::string::npos) { fIsDiag = true; fIsFull = false; } else if (opt.find("FULL") != std::string::npos) { fIsDiag = false; fIsFull = true; } // CHI2/LL (OTHERS?) if (opt.find("LOG") != std::string::npos) fIsChi2 = false; else fIsChi2 = true; // EXTRAS if (opt.find("RAW") != std::string::npos) fIsRawEvents = true; if (opt.find("DIF") != std::string::npos) fIsDifXSec = true; if (opt.find("ENU1D") != std::string::npos) fIsEnu = true; if (opt.find("NORM") != std::string::npos) fAddNormPen = true; if (opt.find("MASK") != std::string::npos) fIsMask = true; fIsProjFitX = (opt.find("FITPROJX") != std::string::npos); fIsProjFitY = (opt.find("FITPROJY") != std::string::npos); return; }; /* Reconfigure LOOP */ //******************************************************************** void Measurement2D::ResetAll() { //******************************************************************** fMCHist->Reset(); fMCFine->Reset(); fMCStat->Reset(); return; }; //******************************************************************** void Measurement2D::FillHistograms() { //******************************************************************** if (Signal) { fMCHist->Fill(fXVar, fYVar, Weight); fMCFine->Fill(fXVar, fYVar, Weight); fMCStat->Fill(fXVar, fYVar, 1.0); if (fMCHist_Modes) fMCHist_Modes->Fill(Mode, fXVar, fYVar, Weight); } return; }; //******************************************************************** void Measurement2D::ScaleEvents() { //******************************************************************** // Fill MCWeighted; // for (int i = 0; i < fMCHist->GetNbinsX(); i++) { // fMCWeighted->SetBinContent(i + 1, fMCHist->GetBinContent(i + 1)); // fMCWeighted->SetBinError(i + 1, fMCHist->GetBinError(i + 1)); // } // Setup Stat ratios for MC and MC Fine double *statratio = new double[fMCHist->GetNbinsX()]; for (int i = 0; i < fMCHist->GetNbinsX(); i++) { if (fMCHist->GetBinContent(i + 1) != 0) { statratio[i] = fMCHist->GetBinError(i + 1) / fMCHist->GetBinContent(i + 1); } else { statratio[i] = 0.0; } } double *statratiofine = new double[fMCFine->GetNbinsX()]; for (int i = 0; i < fMCFine->GetNbinsX(); i++) { if (fMCFine->GetBinContent(i + 1) != 0) { statratiofine[i] = fMCFine->GetBinError(i + 1) / fMCFine->GetBinContent(i + 1); } else { statratiofine[i] = 0.0; } } // Scaling for raw event rates if (fIsRawEvents) { double datamcratio = fDataHist->Integral() / fMCHist->Integral(); fMCHist->Scale(datamcratio); fMCFine->Scale(datamcratio); if (fMCHist_Modes) fMCHist_Modes->Scale(datamcratio); // Scaling for XSec as function of Enu } else if (fIsEnu1D) { PlotUtils::FluxUnfoldedScaling(fMCHist, GetFluxHistogram(), GetEventHistogram(), fScaleFactor); PlotUtils::FluxUnfoldedScaling(fMCFine, GetFluxHistogram(), GetEventHistogram(), fScaleFactor); // if (fMCHist_Modes) { // PlotUtils::FluxUnfoldedScaling(fMCHist_Modes, GetFluxHistogram(), // GetEventHistogram(), fScaleFactor, // fNEvents); // } // Any other differential scaling } else { fMCHist->Scale(fScaleFactor, "width"); fMCFine->Scale(fScaleFactor, "width"); // if (fMCHist_Modes) fMCHist_Modes->Scale(fScaleFactor, "width"); } // Proper error scaling - ROOT Freaks out with xsec weights sometimes for (int i = 0; i < fMCStat->GetNbinsX(); i++) { fMCHist->SetBinError(i + 1, fMCHist->GetBinContent(i + 1) * statratio[i]); } for (int i = 0; i < fMCFine->GetNbinsX(); i++) { fMCFine->SetBinError(i + 1, fMCFine->GetBinContent(i + 1) * statratiofine[i]); } // Clean up delete statratio; delete statratiofine; return; }; //******************************************************************** void Measurement2D::ApplyNormScale(double norm) { //******************************************************************** fCurrentNorm = norm; fMCHist->Scale(1.0 / norm); fMCFine->Scale(1.0 / norm); return; }; /* Statistic Functions - Outsources to StatUtils */ //******************************************************************** int Measurement2D::GetNDOF() { //******************************************************************** // Just incase it has gone... if (!fDataHist) return -1; int nDOF = 0; // If datahist has no errors make sure we don't include those bins as they are // not data points for (int xBin = 0; xBin < fDataHist->GetNbinsX(); ++xBin) { for (int yBin = 0; yBin < fDataHist->GetNbinsY(); ++yBin) { if (fDataHist->GetBinError(xBin + 1, yBin + 1) != 0) ++nDOF; } } // Account for possible bin masking int nMasked = 0; if (fMaskHist and fIsMask) if (fMaskHist->Integral() > 0) for (int xBin = 0; xBin < fMaskHist->GetNbinsX() + 1; ++xBin) for (int yBin = 0; yBin < fMaskHist->GetNbinsY() + 1; ++yBin) if (fMaskHist->GetBinContent(xBin, yBin) > 0.5) ++nMasked; // Take away those masked DOF if (fIsMask) { nDOF -= nMasked; } return nDOF; } //******************************************************************** double Measurement2D::GetLikelihood() { //******************************************************************** // If this is for a ratio, there is no data histogram to compare to! if (fNoData || !fDataHist) return 0.; // Fix weird masking bug if (!fIsMask) { if (fMaskHist) { fMaskHist = NULL; } } else { if (fMaskHist) { PlotUtils::MaskBins(fMCHist, fMaskHist); } } // if (fIsProjFitX or fIsProjFitY) return GetProjectedChi2(); // Scale up the results to match each other (Not using width might be // inconsistent with Meas1D) double scaleF = fDataHist->Integral() / fMCHist->Integral(); if (fIsShape) { fMCHist->Scale(scaleF); fMCFine->Scale(scaleF); // PlotUtils::ScaleNeutModeArray((TH1**)fMCHist_PDG, scaleF); } if (!fMapHist) { fMapHist = StatUtils::GenerateMap(fDataHist); } // Get the chi2 from either covar or diagonals double chi2 = 0.0; if (fIsChi2) { if (fIsDiag) { chi2 = StatUtils::GetChi2FromDiag(fDataHist, fMCHist, fMapHist, fMaskHist); } else { chi2 = StatUtils::GetChi2FromCov(fDataHist, fMCHist, covar, fMapHist, fMaskHist, fIsWriting ? fResidualHist : NULL); if (fChi2LessBinHist && fIsWriting) { NUIS_LOG(SAM, "Building n-1 chi2 contribution plot for " << GetName()); for (int xi = 0; xi < fDataHist->GetNbinsX(); ++xi) { for (int yi = 0; yi < fDataHist->GetNbinsY(); ++yi) { TH2I *binmask = fMaskHist ? static_cast(fMaskHist->Clone("mask")) : new TH2I("mask", "", fDataHist->GetNbinsX(), 0, fDataHist->GetNbinsX(), fDataHist->GetNbinsY(), 0, fDataHist->GetNbinsY()); binmask->SetDirectory(NULL); binmask->SetBinContent(xi + 1, yi + 1, 1); fChi2LessBinHist->SetBinContent( xi + 1, yi + 1, StatUtils::GetChi2FromCov(fDataHist, fMCHist, covar, fMapHist, binmask)); delete binmask; } } } } } // Add a normal penalty term if (fAddNormPen) { if (fUseShapeNormDecomp) { // if shape norm, then add the norm penalty from // https://arxiv.org/pdf/2003.00088.pdf TH2 *masked_data = StatUtils::ApplyHistogramMasking(fDataHist, fMaskHist); TH2 *masked_mc = StatUtils::ApplyHistogramMasking(fMCHist, fMaskHist); masked_mc->Scale(scaleF); NUIS_LOG(REC, "ShapeNormDecomp: mcinteg: " << masked_mc->Integral() * 1E38 << ", datainteg: " << masked_data->Integral() * 1E38 << ", normerror: " << fNormError); double normpen = std::pow((masked_data->Integral() - masked_mc->Integral()) * 1E38, 2) / fNormError; masked_data->SetDirectory(NULL); delete masked_data; masked_mc->SetDirectory(NULL); delete masked_mc; NUIS_LOG(REC, "Using Shape/Norm decomposition: Norm penalty " << normpen << " on shape penalty of " << chi2); chi2 += normpen; } else { chi2 += (1 - (fCurrentNorm)) * (1 - (fCurrentNorm)) / (fNormError * fNormError); NUIS_LOG(SAM, "Norm penalty = " << (1 - (fCurrentNorm)) * (1 - (fCurrentNorm)) / (fNormError * fNormError)); } } // Adjust the shape back to where it was. if (fIsShape and !FitPar::Config().GetParB("saveshapescaling")) { fMCHist->Scale(1. / scaleF); fMCFine->Scale(1. / scaleF); } fLikelihood = chi2; return chi2; } /* Fake Data Functions */ //******************************************************************** void Measurement2D::SetFakeDataValues(std::string fakeOption) { //******************************************************************** // Setup original/datatrue TH2D *tempdata = (TH2D *)fDataHist->Clone(); if (!fIsFakeData) { fIsFakeData = true; // Make a copy of the original data histogram. if (!fDataOrig) fDataOrig = (TH2D *)fDataHist->Clone((fName + "_data_original").c_str()); } else { ResetFakeData(); } // Setup Inputs fFakeDataInput = fakeOption; NUIS_LOG(SAM, "Setting fake data from : " << fFakeDataInput); // From MC if (fFakeDataInput.compare("MC") == 0) { fDataHist = (TH2D *)fMCHist->Clone((fName + "_MC").c_str()); // Fake File } else { if (!fFakeDataFile) fFakeDataFile = new TFile(fFakeDataInput.c_str(), "READ"); fDataHist = (TH2D *)fFakeDataFile->Get((fName + "_MC").c_str()); } // Setup Data Hist fDataHist->SetNameTitle((fName + "_FAKE").c_str(), (fName + fPlotTitles).c_str()); // Replace Data True if (fDataTrue) delete fDataTrue; fDataTrue = (TH2D *)fDataHist->Clone(); fDataTrue->SetNameTitle((fName + "_FAKE_TRUE").c_str(), (fName + fPlotTitles).c_str()); // Make a new covariance for fake data hist. int nbins = fDataHist->GetNbinsX() * fDataHist->GetNbinsY(); double alpha_i = 0.0; double alpha_j = 0.0; for (int i = 0; i < nbins; i++) { for (int j = 0; j < nbins; j++) { if (tempdata->GetBinContent(i + 1) && tempdata->GetBinContent(j + 1)) { alpha_i = fDataHist->GetBinContent(i + 1) / tempdata->GetBinContent(i + 1); alpha_j = fDataHist->GetBinContent(j + 1) / tempdata->GetBinContent(j + 1); } else { alpha_i = 0.0; alpha_j = 0.0; } (*fFullCovar)(i, j) = alpha_i * alpha_j * (*fFullCovar)(i, j); } } // Setup Covariances if (covar) delete covar; covar = StatUtils::GetInvert(fFullCovar,true); if (fDecomp) delete fDecomp; fDecomp = StatUtils::GetDecomp(fFullCovar); delete tempdata; return; }; //******************************************************************** void Measurement2D::ResetFakeData() { //******************************************************************** if (fIsFakeData) { if (fDataHist) delete fDataHist; fDataHist = (TH2D *)fDataTrue->Clone((fSettings.GetName() + "_FKDAT").c_str()); } } //******************************************************************** void Measurement2D::ResetData() { //******************************************************************** if (fIsFakeData) { if (fDataHist) delete fDataHist; fDataHist = (TH2D *)fDataOrig->Clone((fSettings.GetName() + "_data").c_str()); } fIsFakeData = false; } //******************************************************************** void Measurement2D::ThrowCovariance() { //******************************************************************** // Take a fDecomposition and use it to throw the current dataset. // Requires fDataTrue also be set incase used repeatedly. if (fDataHist) delete fDataHist; fDataHist = StatUtils::ThrowHistogram(fDataTrue, fFullCovar); return; }; //******************************************************************** void Measurement2D::ThrowDataToy() { //******************************************************************** if (!fDataTrue) fDataTrue = (TH2D *)fDataHist->Clone(); if (fMCHist) delete fMCHist; fMCHist = StatUtils::ThrowHistogram(fDataTrue, fFullCovar); } /* Access Functions */ //******************************************************************** TH2D *Measurement2D::GetMCHistogram() { //******************************************************************** if (!fMCHist) return fMCHist; std::ostringstream chi2; chi2 << std::setprecision(5) << this->GetLikelihood(); int linecolor = kRed; int linestyle = 1; int linewidth = 1; int fillcolor = 0; int fillstyle = 1001; if (fSettings.Has("linecolor")) linecolor = fSettings.GetI("linecolor"); if (fSettings.Has("linestyle")) linestyle = fSettings.GetI("linestyle"); if (fSettings.Has("linewidth")) linewidth = fSettings.GetI("linewidth"); if (fSettings.Has("fillcolor")) fillcolor = fSettings.GetI("fillcolor"); if (fSettings.Has("fillstyle")) fillstyle = fSettings.GetI("fillstyle"); fMCHist->SetTitle(chi2.str().c_str()); fMCHist->SetLineColor(linecolor); fMCHist->SetLineStyle(linestyle); fMCHist->SetLineWidth(linewidth); fMCHist->SetFillColor(fillcolor); fMCHist->SetFillStyle(fillstyle); return fMCHist; }; //******************************************************************** TH2D *Measurement2D::GetDataHistogram() { //******************************************************************** if (!fDataHist) return fDataHist; int datacolor = kBlack; int datastyle = 1; int datawidth = 1; if (fSettings.Has("datacolor")) datacolor = fSettings.GetI("datacolor"); if (fSettings.Has("datastyle")) datastyle = fSettings.GetI("datastyle"); if (fSettings.Has("datawidth")) datawidth = fSettings.GetI("datawidth"); fDataHist->SetLineColor(datacolor); fDataHist->SetLineWidth(datawidth); fDataHist->SetMarkerStyle(datastyle); return fDataHist; }; /* Write Functions */ // Save all the histograms at once //******************************************************************** void Measurement2D::Write(std::string drawOpt) { //******************************************************************** // Get Draw Options drawOpt = FitPar::Config().GetParS("drawopts"); // Write Settigns if (drawOpt.find("SETTINGS") != std::string::npos) { fSettings.Set("#chi^{2}", fLikelihood); fSettings.Set("NDOF", this->GetNDOF()); fSettings.Set("#chi^{2}/NDOF", fLikelihood / this->GetNDOF()); fSettings.Write(); } // // Likelihood residual plots // if (drawOpt.find("RESIDUAL") != std::string::npos) { // WriteResidualPlots(); //} // // RATIO // if (drawOpt.find("CANVMC") != std::string::npos) { // TCanvas* c1 = WriteMCCanvas(fDataHist, fMCHist); // c1->Write(); // delete c1; // } // // PDG // if (drawOpt.find("CANVPDG") != std::string::npos && fMCHist_Modes) { // TCanvas* c2 = WritePDGCanvas(fDataHist, fMCHist, fMCHist_Modes); // c2->Write(); // delete c2; // } /// 2D VERSION // If null pointer return if (!fMCHist and !fDataHist) { NUIS_LOG(SAM, fName << "Incomplete histogram set!"); return; } // Config::Get().out->cd(); // Get Draw Options drawOpt = FitPar::Config().GetParS("drawopts"); bool drawData = (drawOpt.find("DATA") != std::string::npos); bool drawNormal = (drawOpt.find("MC") != std::string::npos); bool drawEvents = (drawOpt.find("EVT") != std::string::npos); bool drawFine = (drawOpt.find("FINE") != std::string::npos); bool drawRatio = (drawOpt.find("RATIO") != std::string::npos); // bool drawModes = (drawOpt.find("MODES") != std::string::npos); bool drawShape = (drawOpt.find("SHAPE") != std::string::npos); bool residual = (drawOpt.find("RESIDUAL") != std::string::npos); bool drawMatrix = (drawOpt.find("MATRIX") != std::string::npos); bool drawFlux = (drawOpt.find("FLUX") != std::string::npos); bool drawMask = (drawOpt.find("MASK") != std::string::npos); bool drawMap = (drawOpt.find("MAP") != std::string::npos); bool drawProj = (drawOpt.find("PROJ") != std::string::npos); // bool drawCanvPDG = (drawOpt.find("CANVPDG") != std::string::npos); bool drawCov = (drawOpt.find("COV") != std::string::npos); bool drawSliceMC = (drawOpt.find("CANVSLICEMC") != std::string::npos); bool drawWeighted = (drawOpt.find("WEIGHTS") != std::string::npos && fMCWeighted); if (FitPar::Config().GetParB("EventManager")) { drawFlux = false; drawEvents = false; } // Save standard plots if (drawData) { GetDataList().at(0)->Write(); // Generate a simple map if (!fMapHist) fMapHist = StatUtils::GenerateMap(fDataHist); // Convert to 1D Lists TH1D *data_1D = StatUtils::MapToTH1D(fDataHist, fMapHist); data_1D->Write(); delete data_1D; } if (drawNormal) { GetMCList().at(0)->Write(); if (!fMapHist) fMapHist = StatUtils::GenerateMap(fDataHist); TH1D *mc_1D = StatUtils::MapToTH1D(fMCHist, fMapHist); mc_1D->SetLineColor(kRed); mc_1D->Write(); delete mc_1D; } if (fIsChi2 && !fIsDiag) { fResidualHist = (TH2D *)fMCHist->Clone((fName + "_RESIDUAL").c_str()); fResidualHist->GetYaxis()->SetTitle("#Delta#chi^{2}"); fResidualHist->Reset(); fChi2LessBinHist = (TH2D *)fMCHist->Clone((fName + "_Chi2NMinusOne").c_str()); fChi2LessBinHist->GetYaxis()->SetTitle("Total #chi^{2} without bin_{i}"); fChi2LessBinHist->Reset(); fIsWriting = true; (void)GetLikelihood(); fIsWriting = false; fResidualHist->Write((fName + "_RESIDUAL").c_str()); fChi2LessBinHist->Write((fName + "_Chi2NMinusOne").c_str()); if (fMapHist) { TH1D *ResidualHist_1D = StatUtils::MapToTH1D(fResidualHist, fMapHist); TH1D *Chi2LessBinHist_1D = StatUtils::MapToTH1D(fChi2LessBinHist, fMapHist); ResidualHist_1D->Write((fName + "_RESIDUAL_1D").c_str()); Chi2LessBinHist_1D->Write((fName + "_Chi2NMinusOne_1D").c_str()); } } // Write Weighted Histogram if (drawWeighted) fMCWeighted->Write(); if (drawCov) { TH2D(*fFullCovar).Write((fName + "_COV").c_str()); } if (drawOpt.find("INVCOV") != std::string::npos) { TH2D(*covar).Write((fName + "_INVCOV").c_str()); } // Save only mc and data if splines if (fEventType == 4 or fEventType == 3) { return; } // Draw Extra plots if (drawFine) this->GetFineList().at(0)->Write(); if (drawFlux and GetFluxHistogram()) { GetFluxHistogram()->Write(); } if (drawEvents and GetEventHistogram()) { GetEventHistogram()->Write(); } if (fIsMask and drawMask) { fMaskHist->Write((fName + "_MSK").c_str()); //< save mask TH1I *mask_1D = StatUtils::MapToMask(fMaskHist, fMapHist); if (mask_1D) { mask_1D->Write(); TMatrixDSym *calc_cov = StatUtils::ApplyInvertedMatrixMasking(covar, mask_1D); TH1D *data_1D = StatUtils::MapToTH1D(fDataHist, fMapHist); TH1D *mc_1D = StatUtils::MapToTH1D(fMCHist, fMapHist); TH1D *calc_data = StatUtils::ApplyHistogramMasking(data_1D, mask_1D); TH1D *calc_mc = StatUtils::ApplyHistogramMasking(mc_1D, mask_1D); TH2D *bin_cov = new TH2D(*calc_cov); bin_cov->Write(); calc_data->Write(); calc_mc->Write(); delete mask_1D; delete calc_cov; delete calc_data; delete calc_mc; delete bin_cov; delete data_1D; delete mc_1D; } } if (drawMap) fMapHist->Write((fName + "_MAP").c_str()); //< save map // // Save neut stack // if (drawModes) { // THStack combo_fMCHist_PDG = PlotUtils::GetNeutModeStack( // (fName + "_MC_PDG").c_str(), // (TH1**)fMCHist_PDG, 0); // combo_fMCHist_PDG.Write(); // } // Save Matrix plots if (drawMatrix and fFullCovar and covar and fDecomp) { TH2D cov = TH2D((*fFullCovar)); cov.SetNameTitle((fName + "_cov").c_str(), (fName + "_cov;Bins; Bins;").c_str()); cov.Write(); TH2D covinv = TH2D((*this->covar)); covinv.SetNameTitle((fName + "_covinv").c_str(), (fName + "_cov;Bins; Bins;").c_str()); covinv.Write(); TH2D covdec = TH2D((*fDecomp)); covdec.SetNameTitle((fName + "_covdec").c_str(), (fName + "_cov;Bins; Bins;").c_str()); covdec.Write(); } // Save ratio plots if required if (drawRatio) { // Needed for error bars for (int i = 0; i < fMCHist->GetNbinsX() * fMCHist->GetNbinsY(); i++) fMCHist->SetBinError(i + 1, 0.0); fDataHist->GetSumw2(); fMCHist->GetSumw2(); // Create Ratio Histograms TH2D *dataRatio = (TH2D *)fDataHist->Clone((fName + "_data_RATIO").c_str()); TH2D *mcRatio = (TH2D *)fMCHist->Clone((fName + "_MC_RATIO").c_str()); mcRatio->Divide(fMCHist); dataRatio->Divide(fMCHist); // Cancel bin errors on MC for (int i = 0; i < mcRatio->GetNbinsX() * mcRatio->GetNbinsY(); i++) { mcRatio->SetBinError(i + 1, fMCHist->GetBinError(i + 1) / fMCHist->GetBinContent(i + 1)); } mcRatio->SetMinimum(0); mcRatio->SetMaximum(2); dataRatio->SetMinimum(0); dataRatio->SetMaximum(2); mcRatio->Write(); dataRatio->Write(); delete mcRatio; delete dataRatio; } // Save Shape Plots if required if (drawShape) { // Create Shape Histogram TH2D *mcShape = (TH2D *)fMCHist->Clone((fName + "_MC_SHAPE").c_str()); double shapeScale = 1.0; if (fIsRawEvents) { shapeScale = fDataHist->Integral() / fMCHist->Integral(); } else { shapeScale = fDataHist->Integral("width") / fMCHist->Integral("width"); } mcShape->Scale(shapeScale); mcShape->SetLineWidth(3); mcShape->SetLineStyle(7); // dashes mcShape->Write(); // Save shape ratios if (drawRatio) { // Needed for error bars mcShape->GetSumw2(); // Create shape ratio histograms TH2D *mcShapeRatio = (TH2D *)mcShape->Clone((fName + "_MC_SHAPE_RATIO").c_str()); TH2D *dataShapeRatio = (TH2D *)fDataHist->Clone((fName + "_data_SHAPE_RATIO").c_str()); // Divide the histograms mcShapeRatio->Divide(mcShape); dataShapeRatio->Divide(mcShape); // Colour the shape ratio plots mcShapeRatio->SetLineWidth(3); mcShapeRatio->SetLineStyle(7); // dashes mcShapeRatio->Write(); dataShapeRatio->Write(); delete mcShapeRatio; delete dataShapeRatio; } delete mcShape; } // Save residual calculations of what contributed to the chi2 values. if (residual) { } if (fIsProjFitX || fIsProjFitY || drawProj) { // If not already made, make the projections if (!fMCHist_X) { PlotUtils::MatchEmptyBins(fDataHist, fMCHist); fMCHist_X = PlotUtils::GetProjectionX(fMCHist, fMaskHist); fMCHist_Y = PlotUtils::GetProjectionY(fMCHist, fMaskHist); fDataHist_X = PlotUtils::GetProjectionX(fDataHist, fMaskHist); fDataHist_Y = PlotUtils::GetProjectionY(fDataHist, fMaskHist); // This is not the correct way of doing it // double chi2X = StatUtils::GetChi2FromDiag(fDataHist_X, fMCHist_X); // double chi2Y = StatUtils::GetChi2FromDiag(fDataHist_Y, fMCHist_Y); // fMCHist_X->SetTitle(Form("%f", chi2X)); // fMCHist_Y->SetTitle(Form("%f", chi2Y)); } // Save the histograms fDataHist_X->Write(); fMCHist_X->Write(); fDataHist_Y->Write(); fMCHist_Y->Write(); } if (drawSliceMC) { TCanvas *c1 = new TCanvas((fName + "_MC_CANV_Y").c_str(), (fName + "_MC_CANV_Y").c_str(), 1024, 1024); c1->Divide(2, int(fDataHist->GetNbinsY() / 3. + 1)); TH2D *mcShape = (TH2D *)fMCHist->Clone((fName + "_MC_SHAPE").c_str()); double shapeScale = fDataHist->Integral("width") / fMCHist->Integral("width"); mcShape->Scale(shapeScale); mcShape->SetLineStyle(7); c1->cd(1); TLegend *leg = new TLegend(0.0, 0.0, 1.0, 1.0); leg->AddEntry(fDataHist, (fName + " Data").c_str(), "lep"); leg->AddEntry(fMCHist, (fName + " MC").c_str(), "l"); leg->AddEntry(mcShape, (fName + " Shape").c_str(), "l"); leg->SetLineColor(0); leg->SetLineStyle(0); leg->SetFillColor(0); leg->SetLineStyle(0); leg->Draw("SAME"); // Make Y slices for (int i = 1; i < fDataHist->GetNbinsY() + 1; i++) { c1->cd(i + 1); TH1D *fDataHist_SliceY = PlotUtils::GetSliceY(fDataHist, i); fDataHist_SliceY->Draw("E1"); TH1D *fMCHist_SliceY = PlotUtils::GetSliceY(fMCHist, i); fMCHist_SliceY->Draw("SAME"); TH1D *mcShape_SliceY = PlotUtils::GetSliceY(mcShape, i); mcShape_SliceY->Draw("SAME"); mcShape_SliceY->SetLineStyle(mcShape->GetLineStyle()); } c1->Write(); delete c1; delete leg; TCanvas *c2 = new TCanvas((fName + "_MC_CANV_X").c_str(), (fName + "_MC_CANV_X").c_str(), 1024, 1024); c2->Divide(2, int(fDataHist->GetNbinsX() / 3. + 1)); mcShape = (TH2D *)fMCHist->Clone((fName + "_MC_SHAPE").c_str()); shapeScale = fDataHist->Integral("width") / fMCHist->Integral("width"); mcShape->Scale(shapeScale); mcShape->SetLineStyle(7); c2->cd(1); TLegend *leg2 = new TLegend(0.0, 0.0, 1.0, 1.0); leg2->AddEntry(fDataHist, (fName + " Data").c_str(), "lep"); leg2->AddEntry(fMCHist, (fName + " MC").c_str(), "l"); leg2->AddEntry(mcShape, (fName + " Shape").c_str(), "l"); leg2->SetLineColor(0); leg2->SetLineStyle(0); leg2->SetFillColor(0); leg2->SetLineStyle(0); leg2->Draw("SAME"); // Make Y slices for (int i = 1; i < fDataHist->GetNbinsX() + 1; i++) { c2->cd(i + 1); TH1D *fDataHist_SliceX = PlotUtils::GetSliceX(fDataHist, i); fDataHist_SliceX->Draw("E1"); TH1D *fMCHist_SliceX = PlotUtils::GetSliceX(fMCHist, i); fMCHist_SliceX->Draw("SAME"); TH1D *mcShape_SliceX = PlotUtils::GetSliceX(mcShape, i); mcShape_SliceX->Draw("SAME"); mcShape_SliceX->SetLineStyle(mcShape->GetLineStyle()); } c2->Write(); delete c2; delete leg2; } // Write Extra Histograms AutoWriteExtraTH1(); WriteExtraHistograms(); // Returning NUIS_LOG(SAM, "Written Histograms: " << fName); return; } /* Setup Functions */ //******************************************************************** void Measurement2D::SetupMeasurement(std::string inputfile, std::string type, FitWeight *rw, std::string fkdt) { //******************************************************************** // Check if name contains Evt, indicating that it is a raw number of events // measurements and should thus be treated as once fIsRawEvents = false; if ((fName.find("Evt") != std::string::npos) && fIsRawEvents == false) { fIsRawEvents = true; NUIS_LOG(SAM, "Found event rate measurement but fIsRawEvents == false!"); NUIS_LOG(SAM, "Overriding this and setting fIsRawEvents == true!"); } fIsEnu = false; if ((fName.find("XSec") != std::string::npos) && (fName.find("Enu") != std::string::npos)) { fIsEnu = true; NUIS_LOG(SAM, "::" << fName << "::"); NUIS_LOG(SAM, "Found XSec Enu measurement, applying flux integrated scaling, " "not flux averaged!"); if (FitPar::Config().GetParB("EventManager")) { NUIS_ERR(FTL, "Enu Measurements do not yet work with the Event Manager!"); NUIS_ERR(FTL, "If you want decent flux unfolded results please run in " "series mode (-q EventManager=0)"); sleep(2); throw; } } if (fIsEnu && fIsRawEvents) { NUIS_ERR(FTL, "Found 1D Enu XSec distribution AND fIsRawEvents, is this " "really correct?!"); NUIS_ERR(FTL, "Check experiment constructor for " << fName << " and correct this!"); NUIS_ABORT("I live in " << __FILE__ << ":" << __LINE__); } // Reset everything to NULL fRW = rw; // Setting up 2D Inputs this->SetupInputs(inputfile); // Set Default Options SetFitOptions(fDefaultTypes); // Set Passed Options SetFitOptions(type); } //******************************************************************** void Measurement2D::SetupDefaultHist() { //******************************************************************** // Setup fMCHist fMCHist = (TH2D *)fDataHist->Clone(); fMCHist->SetNameTitle((fName + "_MC").c_str(), (fName + "_MC" + fPlotTitles).c_str()); // Setup fMCFine Int_t nBinsX = fMCHist->GetNbinsX(); Int_t nBinsY = fMCHist->GetNbinsY(); fMCFine = new TH2D((fName + "_MC_FINE").c_str(), (fName + "_MC_FINE" + fPlotTitles).c_str(), nBinsX * 3, fMCHist->GetXaxis()->GetBinLowEdge(1), fMCHist->GetXaxis()->GetBinLowEdge(nBinsX + 1), nBinsY * 3, fMCHist->GetYaxis()->GetBinLowEdge(1), fMCHist->GetYaxis()->GetBinLowEdge(nBinsY + 1)); // Setup MC Stat fMCStat = (TH2D *)fMCHist->Clone(); fMCStat->Reset(); // Setup the NEUT Mode Array // PlotUtils::CreateNeutModeArray(fMCHist, (TH1**)fMCHist_PDG); // Setup bin masks using sample name if (fIsMask) { std::string maskloc = FitPar::Config().GetParDIR(fName + ".mask"); if (maskloc.empty()) { maskloc = FitPar::GetDataBase() + "/masks/" + fName + ".mask"; } SetBinMask(maskloc); } return; } //******************************************************************** void Measurement2D::SetDataValues(std::string dataFile, std::string TH2Dname) { //******************************************************************** if (dataFile.find(".root") == std::string::npos) { NUIS_ERR(FTL, "Error! " << dataFile << " is not a .root file"); NUIS_ERR(FTL, "Currently only .root file reading is supported (MiniBooNE " "CC1pi+ 2D), but implementing .txt should be dirt easy"); NUIS_ABORT("See me at " << __FILE__ << ":" << __LINE__); } else { TFile *inFile = new TFile(dataFile.c_str(), "READ"); fDataHist = (TH2D *)(inFile->Get(TH2Dname.c_str())->Clone()); fDataHist->SetDirectory(0); fDataHist->SetNameTitle((fName + "_data").c_str(), (fName + "_MC" + fPlotTitles).c_str()); delete inFile; } return; } //******************************************************************** void Measurement2D::SetDataValues(std::string dataFile, double dataNorm, std::string errorFile, double errorNorm) { //******************************************************************** // Make a counter to track the line number int yBin = 0; std::string line; std::ifstream data(dataFile.c_str(), std::ifstream::in); fDataHist = new TH2D((fName + "_data").c_str(), (fName + fPlotTitles).c_str(), fNDataPointsX - 1, fXBins, fNDataPointsY - 1, fYBins); if (data.is_open()) { NUIS_LOG(SAM, "Reading data from: " << dataFile.c_str()); } while (std::getline(data >> std::ws, line, '\n')) { int xBin = 0; // Loop over entries and insert them into the histogram std::vector entries = GeneralUtils::ParseToDbl(line, " "); for (std::vector::iterator iter = entries.begin(); iter != entries.end(); iter++) { fDataHist->SetBinContent(xBin + 1, yBin + 1, (*iter) * dataNorm); xBin++; } yBin++; } yBin = 0; std::ifstream error(errorFile.c_str(), std::ifstream::in); if (error.is_open()) { NUIS_LOG(SAM, "Reading errors from: " << errorFile.c_str()); } while (std::getline(error >> std::ws, line, '\n')) { int xBin = 0; // Loop over entries and insert them into the histogram std::vector entries = GeneralUtils::ParseToDbl(line, " "); for (std::vector::iterator iter = entries.begin(); iter != entries.end(); iter++) { fDataHist->SetBinError(xBin + 1, yBin + 1, (*iter) * errorNorm); xBin++; } yBin++; } return; }; //******************************************************************** void Measurement2D::SetDataValuesFromText(std::string dataFile, double dataNorm) { //******************************************************************** fDataHist = new TH2D((fName + "_data").c_str(), (fName + fPlotTitles).c_str(), fNDataPointsX - 1, fXBins, fNDataPointsY - 1, fYBins); NUIS_LOG(SAM, "Reading data from: " << dataFile); PlotUtils::Set2DHistFromText(dataFile, fDataHist, dataNorm, true); return; }; //******************************************************************** void Measurement2D::SetCovarMatrix(std::string covarFile) { //******************************************************************** // Used to read a covariance matrix from a root file TFile *tempFile = new TFile(covarFile.c_str(), "READ"); // Make plots that we want TH2D *covarPlot = new TH2D(); TH2D *fFullCovarPlot = new TH2D(); // Get covariance options for fake data studies std::string covName = ""; std::string covOption = FitPar::Config().GetParS("throw_covariance"); // Which matrix to get? if (fIsShape || fIsFree) covName = "shp_"; if (fIsDiag) covName += "diag"; else covName += "full"; covarPlot = (TH2D *)tempFile->Get((covName + "cov").c_str()); // Throw either the sub matrix or the full matrix if (!covOption.compare("SUB")) fFullCovarPlot = (TH2D *)tempFile->Get((covName + "cov").c_str()); else if (!covOption.compare("FULL")) fFullCovarPlot = (TH2D *)tempFile->Get("fullcov"); else { NUIS_ERR(WRN, " Incorrect thrown_covariance option in parameters."); } // Bin masking? int dim = int(fDataHist->GetNbinsX()); //-this->masked->Integral()); int covdim = int(fDataHist->GetNbinsX()); // Make new covars this->covar = new TMatrixDSym(dim); fFullCovar = new TMatrixDSym(dim); fDecomp = new TMatrixDSym(dim); // Full covariance values int row, column = 0; row = 0; column = 0; for (Int_t i = 0; i < covdim; i++) { // masking can be dodgy // if (this->masked->GetBinContent(i+1) > 0) continue; for (Int_t j = 0; j < covdim; j++) { // if (this->masked->GetBinContent(j+1) > 0) continue; (*this->covar)(row, column) = covarPlot->GetBinContent(i + 1, j + 1); (*fFullCovar)(row, column) = fFullCovarPlot->GetBinContent(i + 1, j + 1); column++; } column = 0; row++; } // Set bin errors on data if (!fIsDiag) { for (Int_t i = 0; i < fDataHist->GetNbinsX(); i++) { fDataHist->SetBinError( i + 1, sqrt((covarPlot->GetBinContent(i + 1, i + 1))) * 1E-38); } } TDecompSVD LU = TDecompSVD(*this->covar); this->covar = new TMatrixDSym(dim, LU.Invert().GetMatrixArray(), ""); tempFile->Close(); delete tempFile; return; }; //******************************************************************** void Measurement2D::SetCovarMatrixFromText(std::string covarFile, int dim) { //******************************************************************** // Make a counter to track the line number int row = 0; std::string line; std::ifstream covar(covarFile.c_str(), std::ifstream::in); this->covar = new TMatrixDSym(dim); fFullCovar = new TMatrixDSym(dim); if (covar.is_open()) { NUIS_LOG(SAM, "Reading covariance matrix from file: " << covarFile); } while (std::getline(covar >> std::ws, line, '\n')) { int column = 0; // Loop over entries and insert them into matrix // Multiply by the errors to get the covariance, rather than the correlation // matrix std::vector entries = GeneralUtils::ParseToDbl(line, " "); for (std::vector::iterator iter = entries.begin(); iter != entries.end(); iter++) { double val = (*iter) * fDataHist->GetBinError(row + 1) * 1E38 * fDataHist->GetBinError(column + 1) * 1E38; (*this->covar)(row, column) = val; (*fFullCovar)(row, column) = val; column++; } row++; } // Robust matrix inversion method TDecompSVD LU = TDecompSVD(*this->covar); this->covar = new TMatrixDSym(dim, LU.Invert().GetMatrixArray(), ""); return; }; //******************************************************************** void Measurement2D::SetCovarMatrixFromChol(std::string covarFile, int dim) { //******************************************************************** // Make a counter to track the line number int row = 0; std::string line; std::ifstream covarread(covarFile.c_str(), std::ifstream::in); TMatrixD *newcov = new TMatrixD(dim, dim); if (covarread.is_open()) { NUIS_LOG(SAM, "Reading covariance matrix from file: " << covarFile); } while (std::getline(covarread >> std::ws, line, '\n')) { int column = 0; // Loop over entries and insert them into matrix // Multiply by the errors to get the covariance, rather than the correlation // matrix std::vector entries = GeneralUtils::ParseToDbl(line, " "); for (std::vector::iterator iter = entries.begin(); iter != entries.end(); iter++) { (*newcov)(row, column) = *iter; column++; } row++; } covarread.close(); // Form full covariance TMatrixD *trans = (TMatrixD *)(newcov)->Clone(); trans->T(); (*trans) *= (*newcov); fFullCovar = new TMatrixDSym(dim, trans->GetMatrixArray(), ""); delete newcov; delete trans; // Robust matrix inversion method TDecompChol LU = TDecompChol(*this->fFullCovar); this->covar = new TMatrixDSym(dim, LU.Invert().GetMatrixArray(), ""); return; }; // //******************************************************************** // void Measurement2D::SetMapValuesFromText(std::string dataFile) { // //******************************************************************** // fMapHist = new TH2I((fName + "_map").c_str(), (fName + // fPlotTitles).c_str(), // fNDataPointsX - 1, fXBins, fNDataPointsY - 1, fYBins); // LOG(SAM) << "Reading map from: " << dataFile << std::endl; // PlotUtils::Set2DHistFromText(dataFile, fMapHist, 1.0); // return; // }; diff --git a/src/FitBase/Measurement2D.h b/src/FitBase/Measurement2D.h index a06326c..eb0a5b1 100644 --- a/src/FitBase/Measurement2D.h +++ b/src/FitBase/Measurement2D.h @@ -1,631 +1,631 @@ // 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 MEASUREMENT_2D_HXX_SEEN #define MEASUREMENT_2D_HXX_SEEN /*! * \addtogroup FitBase * @{ */ #include #include #include #include #include #include #include #include #include // ROOT includes #include #include #include #include #include #include #include #include #include // External data fit includes #include "FitEvent.h" #include "FitUtils.h" #include "MeasurementBase.h" #include "MeasurementVariableBox2D.h" #include "PlotUtils.h" #include "SignalDef.h" #include "StatUtils.h" //******************************************************************** //! 2D Measurement base class. Histogram handling is done in this base layer. class Measurement2D : public MeasurementBase { //******************************************************************** public: /* Constructor/Deconstuctor */ //! Default Constructor Measurement2D(); //! Default Destructor virtual ~Measurement2D(); /* 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 2D data distribution given the binning provided. virtual void CreateDataHistogram(int dimx, double *binx, int dimy, double *biny); /// \brief Set Data Histogram from a list of contents in a text file /// /// Assumes the format: \n /// x_low_1 y_low_1 cont_11 err_11 \n /// x_low_1 y_low_2 cont_12 err_12 \n /// x_low_2 y_low_1 cont_21 err_21 \n /// x_low_2 y_low_2 cont_22 err_22 \n /// x_low_2 y_low_3 cont_23 err_23 \n /// x_low_3 y_low_2 cont_32 err_32 \n virtual void SetDataFromTextFile(std::string data, std::string binx, std::string biny); /// \brief Set Data Histogram from a TH2D in a file /// /// - datfile = Full path to data file /// - histname = Name of histogram /// /// If histname not given it assumes that datfile /// is in the format: \n /// 'file.root;histname' virtual void SetDataFromRootFile(std::string datfile, std::string histname = ""); /// \brief Set data values from a 2D array in text file /// /// \warning requires DATA HISTOGRAM TO BE SET FIRST /// /// Assumes form: \n /// cont_11 cont_12 ... cont_1N \n /// cont_21 cont_22 ... cont_2N \n /// ... ... ... ... \n /// cont_N1 cont_N2 ... cont_NN \n virtual void SetDataValuesFromTextFile(std::string datfile, TH2D *hist = NULL); /// \brief Set data errors from a 2D array in text file /// /// \warning requires DATA HISTOGRAM TO BE SET FIRST /// /// Assumes form: \n /// errs_11 errs_12 ... errs_1N \n /// errs_21 errs_22 ... errs_2N \n /// ... ... ... ... \n /// errs_N1 errs_N2 ... errs_NN \n virtual void SetDataErrorsFromTextFile(std::string datfile, TH2D *hist = NULL); /// \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(TH2D *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); /// \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 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 = ""); void SetShapeCovar(); /// \brief Read the map values from a text file /// /// \warning Requires DATA hist to be set beforehand. /// Format should be a 2D array of mappings. /// -1 indicates empty bins. \n /// e.g.: \n /// 1 2 3 4 5 \n /// -1 6 7 8 9 \n /// -1 -1 10 11 -1 \n virtual void SetMapValuesFromText(std::string dataFile); /// \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_x_1 bin_index_y_1 1 \n /// bin_index_x_2 bin_index_y_2 1 \n /// bin_index_x_3 bin_index_y_3 1 \n /// /// If 0 is given then a bin entry will NOT be masked. So for example: \n\n /// 1 1 1 \n /// 2 0 1 \n /// 3 4 0 \n /// 4 0 1 \n\n /// Will mask only the (1,1), (2,0), and (4,0) 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 ',' + /// are conflicting. Any options separated with the '/' symbol are non + /// conflicting and can be given together, whereas any separated 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(); /* Reconfigure */ /// \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 MeasurementVariableBox2D(); }; /// \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, YVar /// /// Fill standard histograms using fXVar, fYVar, 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(); /// \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 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 TH2D *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 TH2D *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); //////// OLD FUNCTIONS //////////// //! Intial setup of common measurement variables. Parse input files, types, //! etc. virtual void SetupMeasurement(std::string input, std::string type, FitWeight *rw, std::string fkdt); //! Setup the default mc Hist given a data histogram virtual void SetupDefaultHist(); //! Set the data values and errors from two files virtual void SetDataValues(std::string dataFile, double dataNorm, std::string errorFile, double errorNorm); virtual void SetDataValues(std::string dataFile, std::string TH2Dname); //! Set the data values only from a text file virtual void SetDataValuesFromText(std::string dataFile, double norm); //! Read a covariance matrix from a file (Default name "covar" in file) virtual void SetCovarMatrix(std::string covarFile); //! Set the covariance matrix from a text file virtual void SetCovarMatrixFromText(std::string covarFile, int dim); //! Set the covariance matrix from a text file containing the cholesky //! fDecomposition virtual void SetCovarMatrixFromChol(std::string covarFile, int dim); protected: // The data histograms TH2D *fDataHist; //!< default data histogram (use in chi2 calculations) TH2D *fDataOrig; //!< histogram to store original data before throws. TH2D *fDataTrue; //!< histogram to store true dataset TH1D *fDataHist_X; //!< Projections onto X of the fDataHist TH1D *fDataHist_Y; //!< Projections onto Y of the fDataHist // The MC histograms TH2D *fMCHist; //!< MC Histogram (used in chi2 calculations) TH2D *fMCFine; //!< Finely binned MC Histogram TH2D *fMCHist_PDG[61]; //!< MC Histograms for each interaction mode TH1D *fMCHist_X; //!< Projections onto X of the fMCHist TH1D *fMCHist_Y; //!< Projections onto Y of the fMCHist TH2D *fMCWeighted; //!< Raw Event Weights TH2D *fMCStat; TH2I *fMaskHist; //!< mask histogram for the data TH2I *fMapHist; //!< map histogram used to convert 2D to 1D distributions TH2D *fResidualHist; TH2D *fChi2LessBinHist; bool fIsFakeData; //!< is current data actually fake std::string fakeDataFile; //!< MC fake data input file std::string fPlotTitles; //!< X and Y plot titles. std::string fFitType; std::string fDefaultTypes; //!< Default Fit Options std::string fAllowedTypes; //!< Any allowed Fit Options TMatrixDSym *covar; //!< inverted covariance matrix TMatrixDSym *fFullCovar; //!< covariance matrix TMatrixDSym *fDecomp; //!< fDecomposed covariance matrix TMatrixDSym *fCorrel; //!< correlation matrix TMatrixDSym *fShapeCovar; double fCovDet; //!< covariance deteriminant double fNormError; //!< Normalisation on the error on the data double fLikelihood; //!< Likelihood value Double_t *fXBins; //!< X Bin Edges Double_t *fYBins; //!< Y Bin Edges Int_t fNDataPointsX; //!< Number of X data points Int_t fNDataPointsY; //!< NUmber of Y data points // Fit specific flags bool fIsShape; //!< Flag: Perform shape-only fit bool fUseShapeNormDecomp; bool fIsFree; //!< Flag: Perform normalisation free fit bool fIsDiag; //!< Flag: Only use diagonal bin errors in stats bool fIsMask; //!< Flag: Apply bin masking bool fIsRawEvents; //!< Flag: Only event rates in histograms bool fIsEnu; //!< Needs Enu Unfolding bool fIsChi2SVD; //!< Flag: Chi2 SVD Method (DO NOT USE) bool fAddNormPen; //!< Flag: Add normalisation penalty to fi bool fIsProjFitX; //!< Flag: Use 1D projections onto X and Y to calculate the //! Chi2 Method. If flagged X will be used to set the rate. bool fIsProjFitY; //!< Flag: Use 1D projections onto X and Y to calculate the //! Chi2 Method. If flagged Y will be used to set the rate. bool fIsFix; //!< Flag: Fixed Histogram Norm bool fIsFull; //!< Flag; Use Full Covar bool fIsDifXSec; //!< Flag: Differential XSec bool fIsEnu1D; //!< Flag: Flux Unfolded XSec bool fIsChi2; //!< Flag; Use Chi2 over LL bool fIsWriting; TrueModeStack *fMCHist_Modes; ///< Optional True Mode Stack TMatrixDSym *fCovar; ///< New FullCovar TMatrixDSym *fInvert; ///< New covar // Fake Data std::string fFakeDataInput; ///< Input fake data file path TFile *fFakeDataFile; ///< Input fake data file // Arrays for data entries Double_t *fDataValues; ///< REMOVE data bin contents Double_t *fDataErrors; ///< REMOVE data bin errors }; /*! @} */ #endif diff --git a/src/FitBase/ParamPull.cxx b/src/FitBase/ParamPull.cxx index 0464a7a..bea9af0 100644 --- a/src/FitBase/ParamPull.cxx +++ b/src/FitBase/ParamPull.cxx @@ -1,867 +1,867 @@ // 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 "ParamPull.h" //******************************************************************************* ParamPull::ParamPull(std::string name, std::string inputfile, std::string type, std::string dials) { //******************************************************************************* fMinHist = NULL; fMaxHist = NULL; fTypeHist = NULL; fDialSelection = dials; fLimitHist = NULL; fName = name; fInput = inputfile; fType = type; // Set the pull type SetType(fType); // Setup Histograms from input file SetupHistograms(fInput); }; //******************************************************************************* void ParamPull::SetType(std::string type) { //******************************************************************************* fType = type; // Assume Default if empty if (type.empty() || type == "DEFAULT") { NUIS_ERR(WRN, "No type specified for ParmPull class " << fName); NUIS_ERR(WRN, "Assuming GAUSTHROW/GAUSPULL"); type = "GAUSTHROW/GAUSPULL"; } // Set Dial options if (type.find("FRAC") != std::string::npos) { fDialOptions = "FRAC"; fPlotTitles = ";; Fractional RW Value"; } else if (type.find("ABS") != std::string::npos) { fDialOptions = "ABS"; fPlotTitles = ";; ABS RW Value"; } else { fDialOptions = ""; fPlotTitles = ";; RW Value"; } // Parse throw types if (type.find("GAUSPULL") != std::string::npos) fCalcType = kGausPull; else fCalcType = kNoPull; if (type.find("GAUSTHROW") != std::string::npos) fThrowType = kGausThrow; else if (type.find("FLATTHROW") != std::string::npos) fThrowType = kFlatThrow; else fThrowType = kNoThrow; // Extra check to see if throws or pulls are turned off if (type.find("NOPULL") != std::string::npos) fCalcType = kNoPull; if (type.find("NOTHROW") != std::string::npos) fThrowType = kNoThrow; } //******************************************************************************* void ParamPull::SetupHistograms(std::string input) { //******************************************************************************* // Extract Types from Input fFileType = ""; const int nfiletypes = 4; const std::string filetypes[nfiletypes] = {"FIT", "ROOT", "TXT", "DIAL"}; for (int i = 0; i < nfiletypes; i++) { std::string tempTypes = filetypes[i] + ":"; if (input.find(tempTypes) != std::string::npos) { fFileType = filetypes[i]; input.replace(input.find(tempTypes), tempTypes.size(), ""); break; } } // Read Files if (!fFileType.compare("FIT")) ReadFitFile(input); else if (!fFileType.compare("ROOT")) ReadRootFile(input); else if (!fFileType.compare("VECT")) ReadVectFile(input); else if (!fFileType.compare("DIAL")) ReadDialInput(input); else { NUIS_ERR(FTL, "Unknown ParamPull Type: " << input); NUIS_ABORT("Need FIT, ROOT, VECT or DIAL"); } // Check Dials are all good if (!CheckDialsValid()) { NUIS_ABORT("DIALS NOT VALID"); } // Setup MC Histogram fMCHist = (TH1D *)fDataHist->Clone(); fMCHist->Reset(); fMCHist->SetNameTitle((fName + "_MC").c_str(), (fName + " MC" + fPlotTitles).c_str()); // If no Covar input make an uncorrelated one if (!fCovar) { fCovar = StatUtils::MakeDiagonalCovarMatrix(fDataHist, 1.0); } // If no types or limits are provided give them a default option if (!fMinHist) { NUIS_LOG(FIT, "No minimum histogram found for pull parameters, setting to be " "content - 1E6..."); fMinHist = (TH1D *)fDataHist->Clone(); fMinHist->SetNameTitle((fName + "_min").c_str(), (fName + " min" + fPlotTitles).c_str()); for (int i = 0; i < fMinHist->GetNbinsX(); i++) { // TODO (P.Stowell) Change this to a NULL system where limits are actually // free! fMinHist->SetBinContent(i + 1, fDataHist->GetBinContent(i + 1) - 1E6); } } if (!fMaxHist) { NUIS_LOG(FIT, "No maximum histogram found for pull parameters, setting to be " "content - 1E6..."); fMaxHist = (TH1D *)fDataHist->Clone(); fMaxHist->SetNameTitle((fName + "_min").c_str(), (fName + " min" + fPlotTitles).c_str()); for (int i = 0; i < fMaxHist->GetNbinsX(); i++) { fMaxHist->SetBinContent(i + 1, fDataHist->GetBinContent(i + 1) - 1E6); } } // Set types from state, or to unknown // Not really sure when or if this is ever used if (!fTypeHist) { int deftype = -1; if (fType.find("T2K") != std::string::npos) { deftype = kT2K; } else if (fType.find("NEUT") != std::string::npos) { deftype = kNEUT; } else if (fType.find("NIWG") != std::string::npos) { deftype = kNIWG; } else if (fType.find("GENIE") != std::string::npos) { deftype = kGENIE; } else if (fType.find("NORM") != std::string::npos) { deftype = kNORM; } else if (fType.find("NUWRO") != std::string::npos) { deftype = kNUWRO; } fTypeHist = new TH1I((fName + "_type").c_str(), (fName + " type" + fPlotTitles).c_str(), fDataHist->GetNbinsX(), 0, fDataHist->GetNbinsX()); for (int i = 0; i < fTypeHist->GetNbinsX(); i++) { fTypeHist->SetBinContent(i + 1, deftype); } } // Sort Covariances fInvCovar = StatUtils::GetInvert(fCovar); fDecomp = StatUtils::GetDecomp(fCovar); // Create DataTrue for Throws fDataTrue = (TH1D *)fDataHist->Clone(); fDataTrue->SetNameTitle((fName + "_truedata").c_str(), (fName + " truedata" + fPlotTitles).c_str()); fDataOrig = (TH1D *)fDataHist->Clone(); fDataOrig->SetNameTitle((fName + "_origdata").c_str(), (fName + " origdata" + fPlotTitles).c_str()); // Select only dials we want if (!fDialSelection.empty()) { (*fDataHist) = RemoveBinsNotInString(*fDataHist, fDialSelection); } } //******************************************************************************* TH1D ParamPull::RemoveBinsNotInString(TH1D hist, std::string mystr) { //******************************************************************************* // Make list of allowed bins std::vector allowedbins; for (int i = 0; i < hist.GetNbinsX(); i++) { std::string syst = std::string(hist.GetXaxis()->GetBinLabel(i + 1)); if (mystr.find(syst) != std::string::npos) { allowedbins.push_back(syst); } } // Make new histogram UInt_t nbins = allowedbins.size(); TH1D newhist = TH1D(hist.GetName(), hist.GetTitle(), (Int_t)nbins, 0.0, (Double_t)nbins); // Setup bins for (UInt_t i = 0; i < nbins; i++) { // Set Labels newhist.GetXaxis()->SetBinLabel(i + 1, allowedbins[i].c_str()); // Copy Values for (Int_t j = 0; j < hist.GetNbinsX(); j++) { if (!allowedbins[i].compare(hist.GetXaxis()->GetBinLabel(j + 1))) { newhist.SetBinContent(i + 1, hist.GetBinContent(j + 1)); newhist.SetBinError(i + 1, hist.GetBinError(j + 1)); } } } return newhist; } //******************************************************************************* TH1I ParamPull::RemoveBinsNotInString(TH1I hist, std::string mystr) { //******************************************************************************* // Make list of allowed bins std::vector allowedbins; for (int i = 0; i < hist.GetNbinsX(); i++) { std::string syst = std::string(hist.GetXaxis()->GetBinLabel(i + 1)); if (mystr.find(syst) != std::string::npos) { allowedbins.push_back(syst); } } // Make new histogram UInt_t nbins = allowedbins.size(); TH1I newhist = TH1I(hist.GetName(), hist.GetTitle(), (Int_t)nbins, 0.0, (Int_t)nbins); // Setup bins for (UInt_t i = 0; i < nbins; i++) { // Set Labels newhist.GetXaxis()->SetBinLabel(i + 1, allowedbins[i].c_str()); // Copy Values for (Int_t j = 0; j < hist.GetNbinsX(); j++) { if (!allowedbins[i].compare(hist.GetXaxis()->GetBinLabel(j + 1))) { newhist.SetBinContent(i + 1, hist.GetBinContent(j + 1)); newhist.SetBinError(i + 1, hist.GetBinError(j + 1)); } } } return newhist; } //******************************************************************************* void ParamPull::ReadFitFile(std::string input) { //******************************************************************************* TFile *tempfile = new TFile(input.c_str(), "READ"); // Read Data fDataHist = (TH1D *)tempfile->Get("fit_dials_free"); CheckHist(fDataHist); fDataHist->SetDirectory(0); fDataHist->SetNameTitle((fName + "_data").c_str(), (fName + " data" + fPlotTitles).c_str()); fMinHist = (TH1D *)tempfile->Get("min_dials_free"); CheckHist(fMinHist); fMinHist->SetDirectory(0); fMinHist->SetNameTitle((fName + "_min").c_str(), (fName + " min" + fPlotTitles).c_str()); fMaxHist = (TH1D *)tempfile->Get("max_dials_free"); CheckHist(fMaxHist); fMaxHist->SetDirectory(0); fMaxHist->SetNameTitle((fName + "_max").c_str(), (fName + " max" + fPlotTitles).c_str()); // Read Covar TH2D *tempcov = (TH2D *)tempfile->Get("covariance_free"); if (!tempcov) { NUIS_ERR(FTL, "Can't find TH2D covariance_free in " << fName); NUIS_ERR(FTL, "File Entries:"); tempfile->ls(); throw; } // Setup Covar int nbins = fDataHist->GetNbinsX(); fCovar = new TMatrixDSym(nbins); for (int i = 0; i < nbins; i++) { for (int j = 0; j < nbins; j++) { (*fCovar)(i, j) = tempcov->GetBinContent(i + 1, j + 1); } } return; } //******************************************************************************* void ParamPull::ReadRootFile(std::string input) { //******************************************************************************* std::vector inputlist = GeneralUtils::ParseToStr(input, ";"); // Check all given if (inputlist.size() < 2) { NUIS_ERR(FTL, "Covar supplied in 'ROOT' format should have 3 semi-colon " - "seperated entries!" + "separated entries!" << std::endl << "ROOT:filename;histname[;covarname]"); NUIS_ABORT("histname = TH1D, covarname = TH2D"); } // Get Entries std::string filename = inputlist[0]; std::string histname = inputlist[1]; // Read File TFile *tempfile = new TFile(filename.c_str(), "READ"); if (tempfile->IsZombie()) { NUIS_LOG(FIT, "Looking for ParamPull input inside database"); filename = FitPar::GetDataBase() + "/" + filename; tempfile = new TFile(filename.c_str(), "READ"); } if (tempfile->IsZombie()) { NUIS_ERR(FTL, "Can't find file in " << fName); NUIS_ABORT("location = " << filename); } // Read Hist fDataHist = (TH1D *)tempfile->Get(histname.c_str()); if (!fDataHist) { NUIS_ERR(FTL, "Can't find TH1D hist " << histname << " in " << fName); NUIS_ERR(FTL, "File Entries:"); tempfile->ls(); throw; } fDataHist->SetDirectory(0); fDataHist->SetNameTitle((fName + "_data").c_str(), (fName + " data" + fPlotTitles).c_str()); NUIS_LOG(DEB, "READING COVAR"); // Read Covar if (inputlist.size() > 2) { std::string covarname = inputlist[2]; NUIS_LOG(DEB, "COVARNAME = " << covarname); TH2D *tempcov = (TH2D *)tempfile->Get(covarname.c_str()); if (!tempcov) { NUIS_ERR(FTL, "Can't find TH2D covar " << covarname << " in " << fName); NUIS_ERR(FTL, "File Entries:"); tempfile->ls(); throw; } // Setup Covar int nbins = fDataHist->GetNbinsX(); fCovar = new TMatrixDSym(nbins); for (int i = 0; i < nbins; i++) { for (int j = 0; j < nbins; j++) { (*fCovar)(i, j) = tempcov->GetBinContent(i + 1, j + 1); } } // Uncorrelated } else { NUIS_LOG(SAM, "No Covar provided so using diagonal errors for " << fName); fCovar = NULL; } } //******************************************************************************* void ParamPull::ReadVectFile(std::string input) { //******************************************************************************* std::vector inputlist = GeneralUtils::ParseToStr(input, ";"); if (inputlist.size() < 4) { NUIS_ERR(FTL, "Need 3 inputs for vector input in " << fName); NUIS_ABORT("Inputs: " << input); } // Open File std::string rootname = inputlist[0]; TFile *tempfile = new TFile(rootname.c_str(), "READ"); if (tempfile->IsZombie()) { NUIS_ERR(FTL, "Can't find file in " << fName); NUIS_ABORT("location = " << rootname); } // Get Name std::string tagname = inputlist[1]; // TVector dialtags = tempfile->Get(tagname.c_str()); // if (!dialtags){ // ERR(FTL) << "Can't find list of dial names!" << std::endl; // } // Get Values std::string valuename = inputlist[2]; TVectorD *dialvals = (TVectorD *)tempfile->Get(valuename.c_str()); if (!dialvals) { NUIS_ERR(FTL, "Can't find dial values"); } // Get Matrix std::string matrixname = inputlist[3]; TMatrixD *matrixvals = (TMatrixD *)tempfile->Get(matrixname.c_str()); if (!matrixvals) { NUIS_ERR(FTL, "Can't find matirx values"); } // Get Types if (inputlist.size() > 4) { std::string typesname = inputlist[3]; } // Get Minimum if (inputlist.size() > 5) { std::string minname = inputlist[4]; } // Get Maximum if (inputlist.size() > 6) { std::string maxname = inputlist[5]; } } //******************************************************************************* void ParamPull::ReadDialInput(std::string input) { //******************************************************************************* std::vector inputlist = GeneralUtils::ParseToStr(input, ";"); if (inputlist.size() < 3) { NUIS_ERR(FTL, "Need 3 inputs for dial input in " << fName); NUIS_ABORT("Inputs: " << input); } std::vector inputvals = GeneralUtils::ParseToDbl(input, ";"); std::string dialname = inputlist[0]; double val = inputvals[1]; double err = inputvals[2]; fDataHist = new TH1D((fName + "_data").c_str(), (fName + "_data" + fPlotTitles).c_str(), 1, 0, 1); fDataHist->SetBinContent(1, val); fDataHist->SetBinError(1, err); fDataHist->GetXaxis()->SetBinLabel(1, dialname.c_str()); fLimitHist = new TH1D((fName + "_limits").c_str(), (fName + "_limits" + fPlotTitles).c_str(), 1, 0, 1); fLimitHist->Reset(); if (inputvals.size() > 4) { fLimitHist->SetBinContent(1, (inputvals[3] + inputvals[4]) / 2.0); fLimitHist->SetBinError(1, (inputvals[4] - inputvals[3]) / 2.0); } fCovar = NULL; } //******************************************************************************* std::map ParamPull::GetAllDials() { //******************************************************************************* std::map dialtypemap; for (int i = 0; i < fDataHist->GetNbinsX(); i++) { std::string name = fDataHist->GetXaxis()->GetBinLabel(i + 1); int type = fTypeHist->GetBinContent(i + 1); dialtypemap[name] = type; } return dialtypemap; } //******************************************************************************* bool ParamPull::CheckDialsValid() { //******************************************************************************* std::string helpstring = ""; for (int i = 0; i < fDataHist->GetNbinsX(); i++) { std::string name = std::string(fDataHist->GetXaxis()->GetBinLabel(i + 1)); // If dial exists its all good if (FitBase::GetRW()->DialIncluded(name)) { NUIS_LOG(DEB, "Found dial " << name << " in covariance " << fInput << " and matched to reweight engine "); continue; } // If it doesn't but its a sample norm also continue if (name.find("_norm") != std::string::npos) { NUIS_ERR(WRN, "Norm dial included in covar but not set in FitWeight."); NUIS_ERR(WRN, "Assuming its a sample norm and skipping..."); } // Dial unknown so print a help statement std::ostringstream tempstr; tempstr << "unknown_parameter " << name << " " << fDataHist->GetBinContent(i + 1) << " " << fDataHist->GetBinContent(i + 1) - fDataHist->GetBinError(i + 1) << " " << fDataHist->GetBinContent(i + 1) + fDataHist->GetBinError(i + 1) << " " << fDataHist->GetBinError(i + 1) << " "; if (!fType.empty()) tempstr << fType << std::endl; else tempstr << "FREE" << std::endl; helpstring += tempstr.str(); } // Show statement before failing if (!helpstring.empty()) { NUIS_ERR(FTL, "Dial(s) included in covar but not set in FitWeight."); NUIS_ERR(FTL, "ParamPulls needs to know how you want it to be treated."); NUIS_ABORT("Include the following lines into your card to throw UNCORRELATED:" << std::endl << helpstring); } else { return true; } return false; } //******************************************************************************* void ParamPull::Reconfigure() { //******************************************************************************* FitWeight *rw = FitBase::GetRW(); // Get Dial Names that are valid std::vector namevec = rw->GetDialNames(); std::vector valuevec = rw->GetDialValues(); // Set Bin Values from RW for (UInt_t i = 0; i < namevec.size(); i++) { // Loop over bins and check name matches std::string syst = namevec.at(i); double systval = valuevec.at(i); std::vector allsyst = GeneralUtils::ParseToStr(syst, ","); // Proper Reconf using RW for (int j = 0; j < fMCHist->GetNbinsX(); j++) { // Search for the name of this bin in the corrent dial std::string binname = std::string(fMCHist->GetXaxis()->GetBinLabel(j + 1)); // Check Full Name if (!syst.compare(binname.c_str())) { fMCHist->SetBinContent(j + 1, systval); break; } std::vector splitbinname = GeneralUtils::ParseToStr(binname, ","); for (size_t l = 0; l < splitbinname.size(); l++) { std::string singlebinname = splitbinname[l]; for (size_t k = 0; k < allsyst.size(); k++) { if (!allsyst[k].compare(singlebinname.c_str())) { fMCHist->SetBinContent(j + 1, systval); } } } } } return; }; //******************************************************************************* void ParamPull::ResetToy(void) { //******************************************************************************* if (fDataHist) delete fDataHist; NUIS_LOG(DEB, "Resetting toy"); NUIS_LOG(DEB, fDataTrue); fDataHist = (TH1D *)fDataTrue->Clone(); NUIS_LOG(DEB, "Setting name"); fDataHist->SetNameTitle((fName + "_data").c_str(), (fName + " data" + fPlotTitles).c_str()); } //******************************************************************************* void ParamPull::SetFakeData(std::string fakeinput) { //******************************************************************************* // Set from MC Setting if (!fakeinput.compare("MC")) { // Copy MC into data if (fDataHist) delete fDataHist; fDataHist = (TH1D *)fMCHist->Clone(); fDataHist->SetNameTitle((fName + "_data").c_str(), (fName + " fakedata" + fPlotTitles).c_str()); // Copy original data errors for (int i = 0; i < fDataOrig->GetNbinsX(); i++) { fDataHist->SetBinError(i + 1, fDataOrig->GetBinError(i + 1)); } // Make True Toy Central Value Hist fDataTrue = (TH1D *)fDataHist->Clone(); fDataTrue->SetNameTitle((fName + "_truedata").c_str(), (fName + " truedata" + fPlotTitles).c_str()); } else { NUIS_ERR(FTL, "Trying to set fake data for ParamPulls not from MC!"); NUIS_ABORT("Not currently implemented.."); } } //******************************************************************************* void ParamPull::RemoveFakeData() { //******************************************************************************* delete fDataHist; fDataHist = (TH1D *)fDataOrig->Clone(); fDataHist->SetNameTitle((fName + "_data").c_str(), (fName + " data" + fPlotTitles).c_str()); fDataTrue = (TH1D *)fDataHist->Clone(); fDataTrue->SetNameTitle((fName + "_truedata").c_str(), (fName + " truedata" + fPlotTitles).c_str()); } //******************************************************************************* double ParamPull::GetLikelihood() { //******************************************************************************* double like = 0.0; switch (fCalcType) { // Gaussian Calculation with correlations case kGausPull: like = StatUtils::GetChi2FromCov(fDataHist, fMCHist, fInvCovar, NULL); like *= 1E-76; break; // Default says this has no pull case kNoThrow: default: like = 0.0; break; } NUIS_LOG(DEB, "Likelihood = " << like << " " << fCalcType); return like; }; //******************************************************************************* int ParamPull::GetNDOF() { //******************************************************************************* int ndof = 0; if (fCalcType != kNoThrow) { ndof = fDataHist->GetNbinsX(); } return ndof; }; //******************************************************************************* void ParamPull::ThrowCovariance() { //******************************************************************************* // Reset toy for throw ResetToy(); NUIS_LOG(FIT, "Creating new toy dataset"); // Generate random Gaussian throws std::vector randthrows; for (int i = 0; i < fDataHist->GetNbinsX(); i++) { double randtemp = 0.0; switch (fThrowType) { // Gaussian Throws case kGausThrow: randtemp = gRandom->Gaus(0.0, 1.0); break; // Uniform Throws case kFlatThrow: randtemp = gRandom->Uniform(0.0, 1.0); if (fLimitHist) { randtemp = fLimitHist->GetBinContent(i + 1) + fLimitHist->GetBinError(i + 1) * (randtemp * 2 - 1); } break; // No Throws (DEFAULT) default: break; } randthrows.push_back(randtemp); } // Create Bin Modifications double totalres = 0.0; for (int i = 0; i < fDataHist->GetNbinsX(); i++) { // Calc Bin Mod double binmod = 0.0; if (fThrowType == kGausThrow) { for (int j = 0; j < fDataHist->GetNbinsX(); j++) { binmod += (*fDecomp)(j, i) * randthrows.at(j); } } else if (fThrowType == kFlatThrow) { binmod = randthrows.at(i) - fDataHist->GetBinContent(i + 1); } // Add up fraction dif totalres += binmod; // Add to current data fDataHist->SetBinContent(i + 1, fDataHist->GetBinContent(i + 1) + binmod); } // Rename fDataHist->SetNameTitle((fName + "_data").c_str(), (fName + " toydata" + fPlotTitles).c_str()); // Check Limits if (fLimitHist) { for (int i = 0; i < fLimitHist->GetNbinsX(); i++) { if (fLimitHist->GetBinError(i + 1) == 0.0) continue; if (fDataHist->GetBinContent(i + 1) > fLimitHist->GetBinContent(i + 1) + fLimitHist->GetBinError(i + 1) || fDataHist->GetBinContent(i + 1) < fLimitHist->GetBinContent(i + 1) - fLimitHist->GetBinError(i + 1)) { NUIS_LOG(FIT, "Threw outside allowed region, rethrowing..."); ThrowCovariance(); } } } }; //******************************************************************************* TH2D ParamPull::GetCovar() { //******************************************************************************* TH2D tempCov = TH2D(*fInvCovar); for (int i = 0; i < tempCov.GetNbinsX(); i++) { tempCov.GetXaxis()->SetBinLabel(i + 1, fDataHist->GetXaxis()->GetBinLabel(i + 1)); tempCov.GetYaxis()->SetBinLabel(i + 1, fDataHist->GetXaxis()->GetBinLabel(i + 1)); } tempCov.SetNameTitle((fName + "_INVCOV").c_str(), (fName + " InvertedCovariance;Dials;Dials").c_str()); return tempCov; } //******************************************************************************* TH2D ParamPull::GetFullCovar() { //******************************************************************************* TH2D tempCov = TH2D(*fCovar); for (int i = 0; i < tempCov.GetNbinsX(); i++) { tempCov.GetXaxis()->SetBinLabel(i + 1, fDataHist->GetXaxis()->GetBinLabel(i + 1)); tempCov.GetYaxis()->SetBinLabel(i + 1, fDataHist->GetXaxis()->GetBinLabel(i + 1)); } tempCov.SetNameTitle((fName + "_COV").c_str(), (fName + " Covariance;Dials;Dials").c_str()); return tempCov; } //******************************************************************************* TH2D ParamPull::GetDecompCovar() { //******************************************************************************* TH2D tempCov = TH2D(*fDecomp); for (int i = 0; i < tempCov.GetNbinsX(); i++) { tempCov.GetXaxis()->SetBinLabel(i + 1, fDataHist->GetXaxis()->GetBinLabel(i + 1)); tempCov.GetYaxis()->SetBinLabel(i + 1, fDataHist->GetXaxis()->GetBinLabel(i + 1)); } tempCov.SetNameTitle((fName + "_DEC").c_str(), (fName + " Decomposition;Dials;Dials").c_str()); return tempCov; } //******************************************************************************* void ParamPull::Write(std::string writeoptt) { //******************************************************************************* fDataHist->Write(); fMCHist->Write(); if (fLimitHist) { fLimitHist->Write(); } GetCovar().Write(); GetFullCovar().Write(); GetDecompCovar().Write(); return; }; void ParamPull::CheckHist(TH1D *hist) { if (!hist) { NUIS_ERR(FTL, "Can't find TH1D hist fit_dials in " << fName); NUIS_ERR(FTL, "File Entries:"); TFile *temp = new TFile(fInput.c_str(), "open"); temp->ls(); throw; } } diff --git a/src/FitBase/StackBase.cxx b/src/FitBase/StackBase.cxx index bd6aee0..11cac25 100644 --- a/src/FitBase/StackBase.cxx +++ b/src/FitBase/StackBase.cxx @@ -1,250 +1,251 @@ #include "StackBase.h" void StackBase::AddMode(std::string name, std::string title, int linecolor, int linewidth, int fillstyle) { // int ncur = fAllLabels.size(); fAllLabels.push_back(name); fAllTitles.push_back(title); std::vector temp; temp.push_back(linecolor); temp.push_back(linewidth); temp.push_back(fillstyle); fAllStyles.push_back(temp); } void StackBase::FluxUnfold(TH1D *flux, TH1D *events, double scalefactor, int nevents) { for (size_t i = 0; i < fAllLabels.size(); i++) { if (fNDim == 1) { PlotUtils::FluxUnfoldedScaling((TH1D *)fAllHists[i], flux, events, scalefactor, nevents); } else if (fNDim == 2) { PlotUtils::FluxUnfoldedScaling((TH2D *)fAllHists[i], flux, events, scalefactor); } } } void StackBase::AddMode(int index, std::string name, std::string title, int linecolor, int linewidth, int fillstyle) { while (fAllLabels.size() <= (UInt_t)index) { fAllLabels.push_back(""); fAllTitles.push_back(""); fAllStyles.push_back(std::vector(1, 1)); } fAllLabels[index] = (name); fAllTitles[index] = (title); std::vector temp; temp.push_back(linecolor); temp.push_back(linewidth); temp.push_back(fillstyle); fAllStyles[index] = temp; } bool StackBase::IncludeInStack(TH1 *hist) { if (!FitPar::Config().GetParB("includeemptystackhists") and hist->Integral() == 0.0) return false; return true; } bool StackBase::IncludeInStack(int index) { return true; } void StackBase::SetupStack(TH1 *hist) { fTemplate = (TH1 *)hist->Clone(fName.c_str()); fTemplate->Reset(); // Determine template dim fNDim = fTemplate->GetDimension(); for (size_t i = 0; i < fAllLabels.size(); i++) { fAllHists.push_back( (TH1 *)fTemplate->Clone((fName + "_" + fAllLabels[i]).c_str())); } }; void StackBase::Scale(double sf, std::string opt) { for (size_t i = 0; i < fAllLabels.size(); i++) { // std::cout << "Scaling Stack Hist " << i << " by " << sf << std::endl; fAllHists[i]->Scale(sf, opt.c_str()); } }; void StackBase::Reset() { for (size_t i = 0; i < fAllLabels.size(); i++) { fAllHists[i]->Reset(); } }; void StackBase::FillStack(int index, double x, double y, double z, double weight) { if (index < 0 or (UInt_t) index >= fAllLabels.size()) { NUIS_ERR(WRN, "Returning Stack Fill Because Range = " << index << " " << fAllLabels.size()); return; } if (fNDim == 1) fAllHists[index]->Fill(x, y); else if (fNDim == 2) { // std::cout << "Filling 2D Stack " << index << " " << x << " " << y << " " // << z << std::endl; ((TH2 *)fAllHists[index])->Fill(x, y, z); } else if (fNDim == 3) ((TH3 *)fAllHists[index])->Fill(x, y, z, weight); } void StackBase::SetBinContentStack(int index, int binx, int biny, int binz, double content) { if (index < 0 or (UInt_t) index >= fAllLabels.size()) { NUIS_ERR(WRN, "Returning Stack Fill Because Range = " << index << " " << fAllLabels.size()); return; } if (fNDim == 1) { fAllHists[index]->SetBinContent(binx, content); } else if (fNDim == 2) { ((TH2 *)fAllHists[index])->SetBinContent(binx, biny, content); } else if (fNDim == 3) { ((TH3 *)fAllHists[index])->SetBinContent(binx, biny, binz, content); } } void StackBase::SetBinErrorStack(int index, int binx, int biny, int binz, double error) { if (index < 0 or (UInt_t) index >= fAllLabels.size()) { NUIS_ERR(WRN, "Returning Stack Fill Because Range = " << index << " " << fAllLabels.size()); return; } if (fNDim == 1) { fAllHists[index]->SetBinError(binx, error); } else if (fNDim == 2) { ((TH2 *)fAllHists[index])->SetBinError(binx, biny, error); } else if (fNDim == 3) { ((TH3 *)fAllHists[index])->SetBinError(binx, biny, binz, error); } } void StackBase::Write() { THStack *st = new THStack(); // Loop and add all histograms - bool saveseperate = FitPar::Config().GetParB("WriteSeperateStacks"); + bool saveseparate = FitPar::Config().GetParB("WriteSeparateStacks"); for (size_t i = 0; i < fAllLabels.size(); i++) { if (!IncludeInStack(fAllHists[i])) continue; if (!IncludeInStack(i)) continue; fAllHists[i]->SetTitle(fAllTitles[i].c_str()); fAllHists[i]->GetXaxis()->SetTitle(fXTitle.c_str()); fAllHists[i]->GetYaxis()->SetTitle(fYTitle.c_str()); fAllHists[i]->GetZaxis()->SetTitle(fZTitle.c_str()); fAllHists[i]->SetLineColor(fAllStyles[i][0]); fAllHists[i]->SetLineWidth(fAllStyles[i][1]); fAllHists[i]->SetFillStyle(fAllStyles[i][2]); fAllHists[i]->SetFillColor(fAllStyles[i][0]); - if (saveseperate) + if (saveseparate) fAllHists[i]->Write(); st->Add(fAllHists[i]); } - st->SetTitle(fTitle.c_str()); + st->SetTitle((fTitle+";"+fXTitle+";"+fYTitle+";"+fZTitle).c_str()); st->SetName(fName.c_str()); + st->Write(); delete st; }; void StackBase::Multiply(TH1 *hist) { for (size_t i = 0; i < fAllLabels.size(); i++) { fAllHists[i]->Multiply(hist); } } void StackBase::Divide(TH1 *hist) { for (size_t i = 0; i < fAllLabels.size(); i++) { fAllHists[i]->Divide(hist); } } void StackBase::Add(TH1 *hist, double scale) { for (size_t i = 0; i < fAllLabels.size(); i++) { fAllHists[i]->Add(hist, scale); } } void StackBase::Add(StackBase *hist, double scale) { if (hist->GetType() != fType) { NUIS_ERR(WRN, "Trying to add two StackBases of different types!"); NUIS_ERR(WRN, fType << " + " << hist->GetType() << " = Undefined."); NUIS_ERR(WRN, "Doing nothing..."); return; } for (size_t i = 0; i < fAllLabels.size(); i++) { fAllHists[i]->Add(hist->GetHist(i)); } } TH1 *StackBase::GetHist(int entry) { return fAllHists[entry]; } TH1 *StackBase::GetHist(std::string label) { TH1 *hist = NULL; std::vector splitlabels = GeneralUtils::ParseToStr(label, "+"); for (size_t j = 0; j < splitlabels.size(); j++) { std::string newlabel = splitlabels[j]; for (size_t i = 0; i < fAllLabels.size(); i++) { if (newlabel == fAllLabels[i]) { if (!hist) hist = (TH1 *)fAllHists[i]->Clone(); else hist->Add(fAllHists[i]); } } } return hist; } THStack StackBase::GetStack() { THStack st = THStack(); for (size_t i = 0; i < fAllLabels.size(); i++) { st.Add(fAllHists[i]); } return st; } void StackBase::AddNewHist(std::string name, TH1 *hist) { AddMode(fAllLabels.size(), name, hist->GetTitle(), hist->GetLineColor()); fAllHists.push_back((TH1 *)hist->Clone()); } void StackBase::AddToCategory(std::string name, TH1 *hist) { for (size_t i = 0; i < fAllLabels.size(); i++) { if (name == fAllLabels[i]) { fAllHists[i]->Add(hist); break; } } } void StackBase::AddToCategory(int index, TH1 *hist) { fAllHists[index]->Add(hist); } diff --git a/src/FitBase/StackBase.h b/src/FitBase/StackBase.h index a2bfe1e..12047cf 100644 --- a/src/FitBase/StackBase.h +++ b/src/FitBase/StackBase.h @@ -1,129 +1,133 @@ #ifndef STACK_BASE_H #define STACK_BASE_H #include "FitLogger.h" #include "GeneralUtils.h" #include "MeasurementVariableBox.h" #include "TH1.h" #include "TH1D.h" #include "TH2.h" #include "TH2D.h" #include "TH3.h" #include "THStack.h" #include "PlotUtils.h" class StackBase { public: StackBase(){}; ~StackBase(){}; virtual void AddMode(std::string name, std::string title, int linecolor = 1, int linewidth = 1, int fillstyle = 1001); virtual void AddMode(int index, std::string name, std::string title, int linecolor = 1, int linewidth = 1, int fillstyle = 1001); virtual bool IncludeInStack(TH1 *hist); virtual bool IncludeInStack(int index); virtual void SetupStack(TH1 *hist); virtual void Scale(double sf, std::string opt = ""); virtual void FluxUnfold(TH1D *flux, TH1D *events, double scalefactor, int nevents); virtual void Reset(); virtual void FillStack(int index, double x, double y = 1.0, double z = 1.0, double weight = 1.0); virtual void SetBinContentStack(int index, int binx, int biny, int binz, double content); virtual void SetBinErrorStack(int index, int binx, int biny, int binz, double error); + virtual void SetTitleX(std::string title){fXTitle = title;}; + virtual void SetTitleY(std::string title){fYTitle = title;}; + virtual void SetTitleZ(std::string title){fZTitle = title;}; + virtual void Write(); virtual void Add(StackBase *hist, double scale); virtual void Add(TH1 *hist, double scale); virtual void AddNewHist(std::string name, TH1 *hist); virtual void AddToCategory(std::string name, TH1 *hist); virtual void AddToCategory(int index, TH1 *hist); virtual void Divide(TH1 *hist); virtual void Multiply(TH1 *hist); virtual TH1 *GetHist(int entry); virtual TH1 *GetHist(std::string label); virtual THStack GetStack(); std::string GetType() { return fType; }; std::string fName; std::string fTitle; std::string fXTitle; std::string fYTitle; std::string fZTitle; std::string fType; TH1 *fTemplate; int fNDim; // Maps incase we want to be selective std::vector > fAllStyles; std::vector fAllTitles; std::vector fAllLabels; std::vector fAllHists; }; /* class NuSpeciesStack : public StackBase { public: SetupStack(TH1* hist) { AddMode("numu", "numu", kBlue, 2, 3004); AddMode("numubar", "numubar", kRed, 2, 3004 ); AddMode("nue", "nue", kGreen, 2, 3004 ); StackBase::SetupStack(hist); }; void NuSpeciesStack::FillStack(int species, double x, double y = 1.0, double z = 1.0, double weight = 1.0) { Stackbase::FillStack(ConvertSpeciesToIndex(species), x, y, z, weight); } int ConvertSpeciesToIndex(int species) { switch (species) { case 14: return 0; case -14: return 1; case 11: return 2; default: return -1; } }; }; class TargetStack : public StackBase { public: SetupStack(TH1* hist) { AddMode("C", "C", kBlue, 2, 3004); AddMode("H", "H", kRed, 2, 3004 ); AddMode("O", "O", kGreen, 2, 3004 ); StackBase::SetupStack(hist); }; void NuSpeciesStack::FillStack(int species, double x, double y = 1.0, double z = 1.0, double weight = 1.0) { Stackbase::FillStack(ConvertTargetToIndex(species), x, y, z, weight); } int ConvertTargetToIndex(int target) { switch (species) { case 1000010010: return 0; case 1000: return 1; case 1000: return 2; default: return -1; } }; } */ #endif diff --git a/src/FitBase/TemplateMeas1D.cxx b/src/FitBase/TemplateMeas1D.cxx index efee751..8ef1892 100644 --- a/src/FitBase/TemplateMeas1D.cxx +++ b/src/FitBase/TemplateMeas1D.cxx @@ -1,221 +1,221 @@ // 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 "TemplateMeas1D.h" //******************************************************************** TemplateMeas1D::TemplateMeas1D(std::string name, std::string inputfile, FitWeight *rw, std::string type) { //******************************************************************** // Setup Main Measurement Details fName = name; fPlotTitles = "; Q^{2}_{QE} (GeV^{2}); d#sigma/dQ_{QE}^{2} (cm^{2}/GeV^{2})"; // Setup Enu Limits. NUISANCE selects only events between this limit // when a flux integrals are calculated. EnuMin = 0.; EnuMax = 3.; // Set normalisation error for data. This will be used to add a penalty // if NORM is supplied in the type. fNormError = 0.20; // 20% // Setup allowed/default types // These give the starting possible options that can be specified when making // the class. - // Different discrete fields should be seperated by '/' and conflicting + // Different discrete fields should be separated by '/' and conflicting // options - // should be seperated by ','. e.g. FIX, FREE, and SHAPE are conflicting types + // should be separated by ','. e.g. FIX, FREE, and SHAPE are conflicting types // because // they all handle the normalisation. NORM is an extra option to add a penalty // term - // so should be kept seperate as below. We also want to force DIAG as there is + // so should be kept separate as below. We also want to force DIAG as there is // no // covariance so we put that as the starting default option so it will be set // even if // the user doesn't explicitly set it. fDefaultTypes = "FIX/DIAG"; fAllowedTypes = "FIX,FREE,SHAPE/DIAG/NORM"; // Multiple similar classes can be read by a single class. // e.g. MB numu CCQE or CC0pi. // The standard is to switch from the default by using fName. fAnalysis = kTemplateMeas1D_CC0pi_Tmu; // Default Analysis if (fName == "TemplateMeas1D_CCQE_Q2") { fAnalysis = kTemplateMeas1D_CCQE_Q2; // Alternate Analysis } // Once all the options are set we setup the lower level event variables // !! This must go after all the settings above !! Measurement1D::SetupMeasurement(inputfile, type, rw, ""); // Setup a scaling factor once the measurement has been setup // !! This must go after SetupMeasurement !! // The scalefactor goes from rawevents -> xsec prediction. // First we scale the histograms to match the fEventHist prediction. // Here the data is saved as cm^2 / neutron, but we generate on a // CH2 target. We must then convert it by multiplying by (14.0/6.0). // Finally we divide by the integrated flux to get the cross-section. fScaleFactor = ((GetEventHistogram()->Integral("width") * 1E-38 / (fNEvents + 0.)) * (14.0 / 6.0) / TotalIntegratedFlux()); // After initial setup the constructor should setup the plots // according to what analysis has been stated. if (fAnalysis == kTemplateMeas1D_CC0pi_Tmu) { SetDataFromDatabase("/Template/TemplateMeas1D_Data.root", "Tmu_CC0pi_Data.root"); } else { SetDataFromDatabase("/Template/TemplateMeas1D_Data.root", "Q2_CCQE_Data.root"); } // NUISANCE uses the data histogram to setup all the default MC histograms // fMCHist,fMCFine,fMCStat,fMaskHist,fMCHist_PDG are all set here. // !! It must go after the data hist has been set !! SetupDefaultHist(); // Setup Covariance // Since its diagonal it is useful to setup a diagonal covariance matrix // for use in fake data study covariance throws. // If a covariance IS provided it should be setup here. fFullCovar = StatUtils::MakeDiagonalCovarMatrix(fDataHist); covar = StatUtils::GetInvert(fFullCovar,true); // There will be cases where we want to save optional histograms // to help with validation/studies. They should be setup in the constructor. // Here we also save a true Q2 plot split by interaction channels in CC0pi for // one analysis if (fAnalysis == kTemplateMeas1D_CC0pi_Tmu) { // Create basic plot fMCHist_ExtraQ2Plot = new TH1D( (fName + "_MC_Q2").c_str(), (fName + "_MC_Q2;" "Q^{2}_{QE} (GeV^2);d#sigma/dQ^{2}_{QE} (cm^{2}/GeV^{2})") .c_str(), 20, 0.0, 3.0); // Create Channel Plot // fMCHist_ExtraQ2Plot_PDG = NULL; } }; //******************************************************************** /// @details Extract q2qe(fXVar) from the event void TemplateMeas1D::FillEventVariables(FitEvent *event) { //******************************************************************** // Init double q2qe = -999.9; // Loop over the particle stack for (UInt_t j = 2; j < event->Npart(); ++j) { int PID = abs((event->PartInfo(j))->fPID); if (!event->PartInfo(j)->fIsAlive) continue; if (PID != 13 and !ccqelike) continue; if (abs(PID) != 13 and ccqelike) continue; // Now find the Q2QE value and fill the histogram q2qe = FitUtils::Q2QErec((event->PartInfo(j))->fP, cos(((event->PartInfo(0)) ->fP.Vect() .Angle((event->PartInfo(j))->fP.Vect()))), 34., true); break; } // Set X Variables fXVar = q2qe; return; }; //******************************************************************** bool TemplateMeas1D::isSignal(FitEvent *event) { //******************************************************************** // 2 Different Signal Definitions // if (ccqelike) return SignalDef::isCCQELike(event, 14, EnuMin, EnuMax); // else return SignalDef::isCCQE(event, 14, EnuMin, EnuMax); return true; }; //******************************************************************** /// @details Fills a ccqe-like background plot if required void TemplateMeas1D::FillHistograms() { //******************************************************************** Measurement1D::FillHistograms(); // if (Mode != 1 and Mode != 2 and ccqelike and Signal){ // PlotUtils::FillNeutModeArray(fMCHist_CCQELIKE, Mode, fXVar, Weight); // } } //******************************************************************** /// @details Extra write command to save the CCQELike PDG if required void TemplateMeas1D::Write(std::string drawOpt) { //******************************************************************** Measurement1D::Write(drawOpt); /* if (ccqelike){ fDataHist_CCQELIKE->Write(); THStack combo_fMCHist_CCQELIKE = PlotUtils::GetNeutModeStack((this->fName + "_MC_CCQELIKE").c_str(), (TH1**)this->fMCHist_CCQELIKE, 0); combo_fMCHist_CCQELIKE.Write(); } */ } //******************************************************************** void TemplateMeas1D::ResetAll() { //******************************************************************** Measurement1D::ResetAll(); // if (ccqelike) // PlotUtils::ResetNeutModeArray((TH1**)fMCHist_CCQELIKE); } //******************************************************************** void TemplateMeas1D::ScaleEvents() { //******************************************************************** Measurement1D::ScaleEvents(); // if (ccqelike) // PlotUtils::ScaleNeutModeArray((TH1**)fMCHist_CCQELIKE, // fScaleFactor,"width"); } //******************************************************************** void TemplateMeas1D::ApplyNormScale(double norm) { //******************************************************************** Measurement1D::ApplyNormScale(norm); // if (ccqelike) // PlotUtils::ScaleNeutModeArray((TH1**)fMCHist_CCQELIKE, 1.0/norm, ""); } diff --git a/src/InputHandler/FitEvent.h b/src/InputHandler/FitEvent.h index 73b876a..c104d39 100644 --- a/src/InputHandler/FitEvent.h +++ b/src/InputHandler/FitEvent.h @@ -1,660 +1,659 @@ // 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 FITEVENT2_H_SEEN #define FITEVENT2_H_SEEN /*! * \addtogroup InputHandler * @{ */ #include #include #include #include "FitParticle.h" #include "TLorentzVector.h" #include "TSpline.h" #include "BaseFitEvt.h" #include "FitLogger.h" #include "TArrayD.h" #include "TTree.h" #include "TChain.h" #include "TargetUtils.h" #include "PhysConst.h" /// Common container for event particles class FitEvent : public BaseFitEvt { public: FitEvent(); ~FitEvent() {}; void FreeFitParticles(); void ClearFitParticles(); void ResetEvent(void); void ResetParticleList(void); void HardReset(); void OrderStack(); void SetBranchAddress(TChain* tn); void AddBranchesToTree(TTree* tn); void Print(); - void PrintChris(); void DeallocateParticleStack(); void AllocateParticleStack(int stacksize); void ExpandParticleStack(int stacksize); void AddGeneratorInfo(GeneratorInfoBase* gen); // ---- HELPER/ACCESS FUNCTIONS ---- // /// Return True Interaction ID inline int GetMode (void) const { return Mode; }; /// Return Target Atomic Number inline int GetTargetA (void) const { return fTargetA; }; /// Return Target Nuclear Charge inline int GetTargetZ (void) const { return fTargetZ; }; /// Get Event Total Cross-section inline int GetTotCrs (void) const { return fTotCrs; }; /// Is Event Charged Current? inline bool IsCC() const { if (abs(this->probe_pdg) == 11) return false; return (abs(Mode) <= 30); }; /// Is Event Neutral Current? inline bool IsNC() const { if (abs(this->probe_pdg) == 11) return true; return (abs(Mode) > 30); }; // Is Event resonant? inline bool IsResonant() const { if (Mode != 11 && Mode != 12 && Mode != 13 && Mode != 31 && Mode != 32 && Mode != 33 && Mode != 34) return false; return true; }; /// Return Particle 4-momentum for given index in particle stack TLorentzVector GetParticleP4 (int index) const; /// Return Particle 3-momentum for given index in particle stack TVector3 GetParticleP3 (int index) const; /// Return Particle absolute momentum for given index in particle stack double GetParticleMom (int index) const; /// Return Particle absolute momentum-squared for given index in particle stack double GetParticleMom2 (int index) const; /// Return Particle energy for given index in particle stack double GetParticleE (int index) const; /// Return Particle State for given index in particle stack int GetParticleState (int index) const; /// Return Particle PDG for given index in particle stack int GetParticlePDG (int index) const; /// Allows the removal of KE up to total KE. inline void RemoveKE(int index, double KE){ FitParticle *fp = GetParticle(index); double mass = fp->M(); double oKE = fp->KE(); double nE = mass + (oKE - KE); if(nE < mass){ // Can't take more KE than it has nE = mass; } double n3Mom = sqrt(nE*nE - mass*mass); TVector3 np3 = fp->P3().Unit()*n3Mom; fParticleMom[index][0] = np3[0]; fParticleMom[index][1] = np3[1]; fParticleMom[index][2] = np3[2]; fParticleMom[index][3] = nE; } /// Allows the removal of KE up to total KE. inline void GiveKE(int index, double KE){ RemoveKE(index,-KE); } /// Return Particle for given index in particle stack FitParticle* GetParticle(int const index); /// Get Total Number of Particles in stack inline uint NParticles (void) const { return fNParticles; }; /// Check if event contains a particle given a pdg and state. /// If no state is passed all states are considered. bool HasParticle (int const pdg = 0, int const state = -1) const ; template inline bool HasParticle(int const (&pdgs)[N], int const state = -1) const { for (size_t i = 0; i < N; i++) { if (HasParticle( pdgs[i], state )) { return false; } } return false; } /// Get total number of particles given a pdg and state. /// If no state is passed all states are considered. int NumParticle (int const pdg = 0, int const state = -1) const; template inline int NumParticle(int const (&pdgs)[N], int const state = -1) const { int ncount = 0; for (size_t i = 0; i < N; i++) { ncount += NumParticle( pdgs[i], state ); } return ncount; } /// Return a vector of particle indices that can be used with 'GetParticle' /// functions given a particle pdg and state. /// If no state is passed all states are considered. std::vector GetAllParticleIndices (int const pdg = -1, int const state = -1) const; template inline std::vector GetAllParticleIndices(int const (&pdgs)[N], const int state = -1) const { std::vector plist; for (size_t i = 0; i < N; i++) { std::vector plisttemp = GetAllParticleIndices(pdgs[i], state); plist.insert( plist.end(), plisttemp.begin(), plisttemp.end() ); } return plist; } /// Return a vector of FitParticles given a particle pdg and state. /// This is memory intensive and slow than GetAllParticleIndices, /// but is slightly easier to use. std::vector GetAllParticle (int const pdg = -1, int const state = -1); template inline std::vector GetAllParticle(int const (&pdgs)[N], int const state = -1) { std::vector plist; for (size_t i = 0; i < N; i++) { std::vector plisttemp = GetAllParticle(pdgs[i], state); plist.insert( plist.end(), plisttemp.begin(), plisttemp.end() ); } return plist; } inline std::vector GetAllNuElectronIndices (void) { return GetAllParticleIndices(12); }; inline std::vector GetAllNuMuonIndices (void) { return GetAllParticleIndices(14); }; inline std::vector GetAllNuTauIndices (void) { return GetAllParticleIndices(16); }; inline std::vector GetAllElectronIndices (void) { return GetAllParticleIndices(11); }; inline std::vector GetAllMuonIndices (void) { return GetAllParticleIndices(13); }; inline std::vector GetAllTauIndices (void) { return GetAllParticleIndices(15); }; inline std::vector GetAllProtonIndices (void) { return GetAllParticleIndices(2212); }; inline std::vector GetAllNeutronIndices (void) { return GetAllParticleIndices(2112); }; inline std::vector GetAllPiZeroIndices (void) { return GetAllParticleIndices(111); }; inline std::vector GetAllPiPlusIndices (void) { return GetAllParticleIndices(211); }; inline std::vector GetAllPiMinusIndices (void) { return GetAllParticleIndices(-211); }; inline std::vector GetAllPhotonIndices (void) { return GetAllParticleIndices(22); }; inline std::vector GetAllNuElectron (void) { return GetAllParticle(12); }; inline std::vector GetAllNuMuon (void) { return GetAllParticle(14); }; inline std::vector GetAllNuTau (void) { return GetAllParticle(16); }; inline std::vector GetAllElectron (void) { return GetAllParticle(11); }; inline std::vector GetAllMuon (void) { return GetAllParticle(13); }; inline std::vector GetAllTau (void) { return GetAllParticle(15); }; inline std::vector GetAllProton (void) { return GetAllParticle(2212); }; inline std::vector GetAllNeutron (void) { return GetAllParticle(2112); }; inline std::vector GetAllPiZero (void) { return GetAllParticle(111); }; inline std::vector GetAllPiPlus (void) { return GetAllParticle(211); }; inline std::vector GetAllPiMinus (void) { return GetAllParticle(-211); }; inline std::vector GetAllPhoton (void) { return GetAllParticle(22); }; // --- Highest Momentum Search Functions --- // /// Returns the Index of the highest momentum particle given a pdg and state. /// If no state is given all states are considered, but that will just return the /// momentum of the beam in most cases so is not advised. int GetHMParticleIndex (int const pdg = 0, int const state = -1) const; template inline int GetHMParticleIndex (int const (&pdgs)[N], int const state = -1) const { double mom = -999.9; int rtnindex = -1; for (size_t i = 0; i < N; ++i) { // Use ParticleMom as doesn't require Particle Mem alloc int pindex = GetHMParticleIndex(pdgs[i], state); if (pindex != -1){ double momnew = GetParticleMom2(pindex); if (momnew > mom) { rtnindex = pindex; mom = momnew; } } } return rtnindex; }; /// Returns the highest momentum particle given a pdg and state. /// If no state is given all states are considered, but that will just return the /// momentum of the beam in most cases so is not advised. inline FitParticle* GetHMParticle(int const pdg = 0, int const state = -1) { return GetParticle( GetHMParticleIndex(pdg, state) ); } template inline FitParticle* GetHMParticle(int const (&pdgs)[N], int const state) { return GetParticle(GetHMParticleIndex(pdgs, state)); }; // ---- Initial State Helpers --- // /// Checks the event has a particle of a given pdg in the initial state. inline bool HasISParticle(int const pdg) const { return HasParticle(pdg, kInitialState); }; template inline bool HasISParticle(int const (&pdgs)[N]) const { return HasParticle(pdgs, kInitialState); }; /// Returns the number of particles with a given pdg in the initial state. inline int NumISParticle(int const pdg = 0) const { return NumParticle(pdg, kInitialState); }; template inline int NumISParticle(int const (&pdgs)[N]) const { return NumParticle(pdgs, kInitialState); }; /// Returns a list of indices for all particles with a given pdg /// in the initial state. These can be used with the 'GetParticle' functions. inline std::vector GetAllISParticleIndices(int const pdg = -1) const { return GetAllParticleIndices(pdg, kInitialState); }; template inline std::vector GetAllISParticleIndices(int const (&pdgs)[N]) const { return GetAllParticleIndices(pdgs, kInitialState); }; /// Returns a list of particles with a given pdg in the initial state. /// This function is more memory intensive and slower than the Indices function. inline std::vector GetAllISParticle(int const pdg = -1) { return GetAllParticle(pdg, kInitialState); }; template inline std::vector GetAllISParticle(int const (&pdgs)[N]) { return GetAllParticle(pdgs, kInitialState); }; /// Returns the highest momentum particle with a given pdg in the initial state. inline FitParticle* GetHMISParticle(int const pdg) { return GetHMParticle(pdg, kInitialState); }; template inline FitParticle* GetHMISParticle(int const (&pdgs)[N]) { return GetHMParticle(pdgs, kInitialState); }; /// Returns the highest momentum particle index with a given pdg in the initial state. inline int GetHMISParticleIndex(int const pdg) const { return GetHMParticleIndex(pdg, kInitialState); }; template inline int GetHMISParticleIndex(int const (&pdgs)[N]) const { return GetHMParticleIndex(pdgs, kInitialState); }; inline bool HasISNuElectron (void) const { return HasISParticle(12); }; inline bool HasISNuMuon (void) const { return HasISParticle(14); }; inline bool HasISNuTau (void) const { return HasISParticle(16); }; inline bool HasISElectron (void) const { return HasISParticle(11); }; inline bool HasISMuon (void) const { return HasISParticle(13); }; inline bool HasISTau (void) const { return HasISParticle(15); }; inline bool HasISProton (void) const { return HasISParticle(2212); }; inline bool HasISNeutron (void) const { return HasISParticle(2112); }; inline bool HasISPiZero (void) const { return HasISParticle(111); }; inline bool HasISPiPlus (void) const { return HasISParticle(211); }; inline bool HasISPiMinus (void) const { return HasISParticle(-211); }; inline bool HasISPhoton (void) const { return HasISParticle(22); }; inline bool HasISLeptons (void) const { return HasISParticle(PhysConst::pdg_leptons); }; inline bool HasISPions (void) const { return HasISParticle(PhysConst::pdg_pions); }; inline bool HasISChargePions (void) const { return HasISParticle(PhysConst::pdg_charged_pions); }; inline int NumISNuElectron (void) const { return NumISParticle(12); }; inline int NumISNuMuon (void) const { return NumISParticle(14); }; inline int NumISNuTau (void) const { return NumISParticle(16); }; inline int NumISElectron (void) const { return NumISParticle(11); }; inline int NumISMuon (void) const { return NumISParticle(13); }; inline int NumISTau (void) const { return NumISParticle(15); }; inline int NumISProton (void) const { return NumISParticle(2212); }; inline int NumISNeutron (void) const { return NumISParticle(2112); }; inline int NumISPiZero (void) const { return NumISParticle(111); }; inline int NumISPiPlus (void) const { return NumISParticle(211); }; inline int NumISPiMinus (void) const { return NumISParticle(-211); }; inline int NumISPhoton (void) const { return NumISParticle(22); }; inline int NumISLeptons (void) const { return NumISParticle(PhysConst::pdg_leptons); }; inline int NumISPions (void) const { return NumISParticle(PhysConst::pdg_pions); }; inline int NumISChargePions (void) const { return NumISParticle(PhysConst::pdg_charged_pions); }; inline std::vector GetAllISNuElectronIndices (void) const { return GetAllISParticleIndices(12); }; inline std::vector GetAllISNuMuonIndices (void) const { return GetAllISParticleIndices(14); }; inline std::vector GetAllISNuTauIndices (void) const { return GetAllISParticleIndices(16); }; inline std::vector GetAllISElectronIndices (void) const { return GetAllISParticleIndices(11); }; inline std::vector GetAllISMuonIndices (void) const { return GetAllISParticleIndices(13); }; inline std::vector GetAllISTauIndices (void) const { return GetAllISParticleIndices(15); }; inline std::vector GetAllISProtonIndices (void) const { return GetAllISParticleIndices(2212); }; inline std::vector GetAllISNeutronIndices (void) const { return GetAllISParticleIndices(2112); }; inline std::vector GetAllISPiZeroIndices (void) const { return GetAllISParticleIndices(111); }; inline std::vector GetAllISPiPlusIndices (void) const { return GetAllISParticleIndices(211); }; inline std::vector GetAllISPiMinusIndices (void) const { return GetAllISParticleIndices(-211); }; inline std::vector GetAllISPhotonIndices (void) const { return GetAllISParticleIndices(22); }; inline std::vector GetAllISLeptonsIndices (void) const { return GetAllISParticleIndices(PhysConst::pdg_leptons); }; inline std::vector GetAllISPionsIndices (void) const { return GetAllISParticleIndices(PhysConst::pdg_pions); }; inline std::vector GetAllISChargePionsIndices(void) const { return GetAllISParticleIndices(PhysConst::pdg_charged_pions); }; inline std::vector GetAllISNuElectron (void) { return GetAllISParticle(12); }; inline std::vector GetAllISNuMuon (void) { return GetAllISParticle(14); }; inline std::vector GetAllISNuTau (void) { return GetAllISParticle(16); }; inline std::vector GetAllISElectron (void) { return GetAllISParticle(11); }; inline std::vector GetAllISMuon (void) { return GetAllISParticle(13); }; inline std::vector GetAllISTau (void) { return GetAllISParticle(15); }; inline std::vector GetAllISProton (void) { return GetAllISParticle(2212); }; inline std::vector GetAllISNeutron (void) { return GetAllISParticle(2112); }; inline std::vector GetAllISPiZero (void) { return GetAllISParticle(111); }; inline std::vector GetAllISPiPlus (void) { return GetAllISParticle(211); }; inline std::vector GetAllISPiMinus (void) { return GetAllISParticle(-211); }; inline std::vector GetAllISPhoton (void) { return GetAllISParticle(22); }; inline std::vector GetAllISLeptons (void) { return GetAllISParticle(PhysConst::pdg_leptons); }; inline std::vector GetAllISPions (void) { return GetAllISParticle(PhysConst::pdg_pions); }; inline std::vector GetAllISChargePions(void) { return GetAllISParticle(PhysConst::pdg_charged_pions); }; inline FitParticle* GetHMISNuElectron (void) { return GetHMISParticle(12); }; inline FitParticle* GetHMISNuMuon (void) { return GetHMISParticle(14); }; inline FitParticle* GetHMISNuTau (void) { return GetHMISParticle(16); }; inline FitParticle* GetHMISElectron (void) { return GetHMISParticle(11); }; inline FitParticle* GetHMISMuon (void) { return GetHMISParticle(13); }; inline FitParticle* GetHMISTau (void) { return GetHMISParticle(15); }; inline FitParticle* GetHMISAnyLeptons (void) { return GetHMISParticle(PhysConst::pdg_all_leptons); }; inline FitParticle* GetHMISProton (void) { return GetHMISParticle(2212); }; inline FitParticle* GetHMISNeutron (void) { return GetHMISParticle(2112); }; inline FitParticle* GetHMISPiZero (void) { return GetHMISParticle(111); }; inline FitParticle* GetHMISPiPlus (void) { return GetHMISParticle(211); }; inline FitParticle* GetHMISPiMinus (void) { return GetHMISParticle(-211); }; inline FitParticle* GetHMISPhoton (void) { return GetHMISParticle(22); }; inline FitParticle* GetHMISLepton (void) { return GetHMISParticle(PhysConst::pdg_leptons); }; inline FitParticle* GetHMISPions (void) { return GetHMISParticle(PhysConst::pdg_pions); }; inline FitParticle* GetHMISChargePions(void) { return GetHMISParticle(PhysConst::pdg_charged_pions); }; inline int GetHMISNuElectronIndex (void) { return GetHMISParticleIndex(12); }; inline int GetHMISNuMuonIndex (void) { return GetHMISParticleIndex(14); }; inline int GetHMISNuTauIndex (void) { return GetHMISParticleIndex(16); }; inline int GetHMISElectronIndex (void) { return GetHMISParticleIndex(11); }; inline int GetHMISMuonIndex (void) { return GetHMISParticleIndex(13); }; inline int GetHMISTauIndex (void) { return GetHMISParticleIndex(15); }; inline int GetHMISProtonIndex (void) { return GetHMISParticleIndex(2212); }; inline int GetHMISNeutronIndex (void) { return GetHMISParticleIndex(2112); }; inline int GetHMISPiZeroIndex (void) { return GetHMISParticleIndex(111); }; inline int GetHMISPiPlusIndex (void) { return GetHMISParticleIndex(211); }; inline int GetHMISPiMinusIndex (void) { return GetHMISParticleIndex(-211); }; inline int GetHMISPhotonIndex (void) { return GetHMISParticleIndex(22); }; inline int GetHMISLeptonsIndex (void) { return GetHMISParticleIndex(PhysConst::pdg_leptons); }; inline int GetHMISPionsIndex (void) { return GetHMISParticleIndex(PhysConst::pdg_pions); }; inline int GetHMISChargePionsIndex(void) { return GetHMISParticleIndex(PhysConst::pdg_charged_pions); }; // ---- Final State Helpers --- // inline bool HasFSParticle(int const pdg) const { return HasParticle(pdg, kFinalState); }; template inline bool HasFSParticle(int const (&pdgs)[N]) const { return HasParticle(pdgs, kFinalState); }; inline int NumFSParticle(int const pdg = 0) const { return NumParticle(pdg, kFinalState); }; template inline int NumFSParticle(int const (&pdgs)[N]) const { return NumParticle(pdgs, kFinalState); }; inline std::vector GetAllFSParticleIndices(int const pdg = -1) const { return GetAllParticleIndices(pdg, kFinalState); }; template inline std::vector GetAllFSParticleIndices(int const (&pdgs)[N]) const { return GetAllParticleIndices(pdgs, kFinalState); }; inline std::vector GetAllFSParticle(int const pdg = -1) { return GetAllParticle(pdg, kFinalState); }; template inline std::vector GetAllFSParticle(int const (&pdgs)[N]) { return GetAllParticle(pdgs, kFinalState); }; inline FitParticle* GetHMFSParticle(int const pdg) { return GetHMParticle(pdg, kFinalState); }; template inline FitParticle* GetHMFSParticle(int const (&pdgs)[N]) { return GetHMParticle(pdgs, kFinalState); }; inline int GetHMFSParticleIndex(int const pdg) const { return GetHMParticleIndex(pdg, kFinalState); }; template inline int GetHMFSParticleIndex(int const (&pdgs)[N]) const { return GetHMParticleIndex(pdgs, kFinalState); }; inline bool HasFSNuElectron (void) const { return HasFSParticle(12); }; inline bool HasFSNuMuon (void) const { return HasFSParticle(14); }; inline bool HasFSNuTau (void) const { return HasFSParticle(16); }; inline bool HasFSElectron (void) const { return HasFSParticle(11); }; inline bool HasFSMuon (void) const { return HasFSParticle(13); }; inline bool HasFSTau (void) const { return HasFSParticle(15); }; inline bool HasFSProton (void) const { return HasFSParticle(2212); }; inline bool HasFSNeutron (void) const { return HasFSParticle(2112); }; inline bool HasFSPiZero (void) const { return HasFSParticle(111); }; inline bool HasFSPiPlus (void) const { return HasFSParticle(211); }; inline bool HasFSPiMinus (void) const { return HasFSParticle(-211); }; inline bool HasFSPhoton (void) const { return HasFSParticle(22); }; inline bool HasFSLeptons (void) const { return HasFSParticle(PhysConst::pdg_leptons); }; inline bool HasFSPions (void) const { return HasFSParticle(PhysConst::pdg_pions); }; inline bool HasFSChargePions (void) const { return HasFSParticle(PhysConst::pdg_charged_pions); }; inline bool HasFSNucleons (void) const { return HasFSParticle(PhysConst::pdg_nucleons); }; inline int NumFSNuElectron (void) const { return NumFSParticle(12); }; inline int NumFSNuMuon (void) const { return NumFSParticle(14); }; inline int NumFSNuTau (void) const { return NumFSParticle(16); }; inline int NumFSElectron (void) const { return NumFSParticle(11); }; inline int NumFSMuon (void) const { return NumFSParticle(13); }; inline int NumFSTau (void) const { return NumFSParticle(15); }; inline int NumFSProton (void) const { return NumFSParticle(2212); }; inline int NumFSNeutron (void) const { return NumFSParticle(2112); }; inline int NumFSPiZero (void) const { return NumFSParticle(111); }; inline int NumFSPiPlus (void) const { return NumFSParticle(211); }; inline int NumFSPiMinus (void) const { return NumFSParticle(-211); }; inline int NumFSPhoton (void) const { return NumFSParticle(22); }; int NumFSLeptons (void) const; // { return NumFSParticle(PhysConst::pdg_leptons); }; inline int NumFSPions (void) const { return NumFSParticle(PhysConst::pdg_pions); }; inline int NumFSChargePions (void) const { return NumFSParticle(PhysConst::pdg_charged_pions); }; inline int NumFSNucleons (void) const { return NumFSParticle(PhysConst::pdg_nucleons); }; inline std::vector GetAllFSNuElectronIndices (void) const { return GetAllFSParticleIndices(12); }; inline std::vector GetAllFSNuMuonIndices (void) const { return GetAllFSParticleIndices(14); }; inline std::vector GetAllFSNuTauIndices (void) const { return GetAllFSParticleIndices(16); }; inline std::vector GetAllFSElectronIndices (void) const { return GetAllFSParticleIndices(11); }; inline std::vector GetAllFSMuonIndices (void) const { return GetAllFSParticleIndices(13); }; inline std::vector GetAllFSTauIndices (void) const { return GetAllFSParticleIndices(15); }; inline std::vector GetAllFSProtonIndices (void) const { return GetAllFSParticleIndices(2212); }; inline std::vector GetAllFSNeutronIndices (void) const { return GetAllFSParticleIndices(2112); }; inline std::vector GetAllFSPiZeroIndices (void) const { return GetAllFSParticleIndices(111); }; inline std::vector GetAllFSPiPlusIndices (void) const { return GetAllFSParticleIndices(211); }; inline std::vector GetAllFSPiMinusIndices (void) const { return GetAllFSParticleIndices(-211); }; inline std::vector GetAllFSPhotonIndices (void) const { return GetAllFSParticleIndices(22); }; inline std::vector GetAllFSLeptonsIndices (void) const { return GetAllFSParticleIndices(PhysConst::pdg_leptons); }; inline std::vector GetAllFSPionsIndices (void) const { return GetAllFSParticleIndices(PhysConst::pdg_pions); }; inline std::vector GetAllFSChargePionsIndices(void) const { return GetAllFSParticleIndices(PhysConst::pdg_charged_pions); }; inline std::vector GetAllFSNucleonIndices(void) const { return GetAllFSParticleIndices(PhysConst::pdg_nucleons); }; inline std::vector GetAllFSNuElectron (void) { return GetAllFSParticle(12); }; inline std::vector GetAllFSNuMuon (void) { return GetAllFSParticle(14); }; inline std::vector GetAllFSNuTau (void) { return GetAllFSParticle(16); }; inline std::vector GetAllFSElectron (void) { return GetAllFSParticle(11); }; inline std::vector GetAllFSMuon (void) { return GetAllFSParticle(13); }; inline std::vector GetAllFSTau (void) { return GetAllFSParticle(15); }; inline std::vector GetAllFSProton (void) { return GetAllFSParticle(2212); }; inline std::vector GetAllFSNeutron (void) { return GetAllFSParticle(2112); }; inline std::vector GetAllFSPiZero (void) { return GetAllFSParticle(111); }; inline std::vector GetAllFSPiPlus (void) { return GetAllFSParticle(211); }; inline std::vector GetAllFSPiMinus (void) { return GetAllFSParticle(-211); }; inline std::vector GetAllFSPhoton (void) { return GetAllFSParticle(22); }; inline std::vector GetAllFSLeptons (void) { return GetAllFSParticle(PhysConst::pdg_leptons); }; inline std::vector GetAllFSPions (void) { return GetAllFSParticle(PhysConst::pdg_pions); }; inline std::vector GetAllFSChargePions (void) { return GetAllFSParticle(PhysConst::pdg_charged_pions); }; inline std::vector GetAllFSNucleons (void) { return GetAllFSParticle(PhysConst::pdg_nucleons); }; inline FitParticle* GetHMFSNuElectron (void) { return GetHMFSParticle(12); }; inline FitParticle* GetHMFSNuMuon (void) { return GetHMFSParticle(14); }; inline FitParticle* GetHMFSNuTau (void) { return GetHMFSParticle(16); }; inline FitParticle* GetHMFSElectron (void) { return GetHMFSParticle(11); }; inline FitParticle* GetHMFSMuon (void) { return GetHMFSParticle(13); }; inline FitParticle* GetHMFSTau (void) { return GetHMFSParticle(15); }; inline FitParticle* GetHMFSAnyLeptons (void) { return GetHMFSParticle(PhysConst::pdg_all_leptons); }; inline FitParticle* GetHMFSProton (void) { return GetHMFSParticle(2212); }; inline FitParticle* GetHMFSNeutron (void) { return GetHMFSParticle(2112); }; inline FitParticle* GetHMFSPiZero (void) { return GetHMFSParticle(111); }; inline FitParticle* GetHMFSPiPlus (void) { return GetHMFSParticle(211); }; inline FitParticle* GetHMFSPiMinus (void) { return GetHMFSParticle(-211); }; inline FitParticle* GetHMFSPhoton (void) { return GetHMFSParticle(22); }; inline FitParticle* GetHMFSLeptons (void) { return GetHMFSParticle(PhysConst::pdg_leptons); }; inline FitParticle* GetHMFSAnyLepton (void) { return GetHMFSParticle(PhysConst::pdg_all_leptons); }; inline FitParticle* GetHMFSPions (void) { return GetHMFSParticle(PhysConst::pdg_pions); }; inline FitParticle* GetHMFSChargePions(void) { return GetHMFSParticle(PhysConst::pdg_charged_pions); }; inline FitParticle* GetHMFSNucleons(void) { return GetHMFSParticle(PhysConst::pdg_nucleons); }; inline int GetHMFSNuElectronIndex (void) const { return GetHMFSParticleIndex(12); }; inline int GetHMFSNuMuonIndex (void) const { return GetHMFSParticleIndex(14); }; inline int GetHMFSNuTauIndex (void) const { return GetHMFSParticleIndex(16); }; inline int GetHMFSElectronIndex (void) const { return GetHMFSParticleIndex(11); }; inline int GetHMFSMuonIndex (void) const { return GetHMFSParticleIndex(13); }; inline int GetHMFSTauIndex (void) const { return GetHMFSParticleIndex(15); }; inline int GetHMFSProtonIndex (void) const { return GetHMFSParticleIndex(2212); }; inline int GetHMFSNeutronIndex (void) const { return GetHMFSParticleIndex(2112); }; inline int GetHMFSPiZeroIndex (void) const { return GetHMFSParticleIndex(111); }; inline int GetHMFSPiPlusIndex (void) const { return GetHMFSParticleIndex(211); }; inline int GetHMFSPiMinusIndex (void) const { return GetHMFSParticleIndex(-211); }; inline int GetHMFSPhotonIndex (void) const { return GetHMFSParticleIndex(22); }; inline int GetHMFSLeptonsIndex (void) const { return GetHMFSParticleIndex(PhysConst::pdg_leptons); }; inline int GetHMFSAnyLeptonIndex (void) const { return GetHMFSParticleIndex(PhysConst::pdg_all_leptons); }; inline int GetHMFSPionsIndex (void) const { return GetHMFSParticleIndex(PhysConst::pdg_pions); }; inline int GetHMFSChargePionsIndex(void) const { return GetHMFSParticleIndex(PhysConst::pdg_charged_pions); }; inline int GetHMFSChargeNucleonIndex(void) const { return GetHMFSParticleIndex(PhysConst::pdg_nucleons); }; // ---- NEUTRINO INCOMING Related Functions int GetBeamNeutrinoIndex (void) const; inline TLorentzVector GetBeamNeutrinoP4 (void) const { return GetParticleP4(GetBeamNeutrinoIndex()); }; inline TVector3 GetBeamNeutrinoP3 (void) const { return GetParticleP3(GetBeamNeutrinoIndex()); }; inline double GetBeamNeutrinoMom (void) const { return GetParticleMom(GetBeamNeutrinoIndex()); }; inline double GetBeamNeutrinoMom2 (void) const { return GetParticleMom2(GetBeamNeutrinoIndex()); }; inline double GetBeamNeutrinoE (void) const { return GetParticleE(GetBeamNeutrinoIndex()); }; inline double Enu (void) const { return GetBeamNeutrinoE(); }; inline int GetBeamNeutrinoPDG (void) const { return GetParticlePDG(GetBeamNeutrinoIndex()); }; inline int PDGnu (void) const { return GetBeamNeutrinoPDG(); }; inline int GetNeutrinoInPos (void) const { return GetBeamNeutrinoIndex(); }; inline FitParticle* GetBeamNeutrino (void) { return GetParticle(GetBeamNeutrinoIndex()); }; inline FitParticle* GetNeutrinoIn (void) { return GetParticle(GetBeamNeutrinoIndex()); }; // ---- Electron INCOMING Related Functions int GetBeamElectronIndex (void) const; inline TLorentzVector GetBeamElectronP4 (void) const { return GetParticleP4(GetBeamElectronIndex()); }; inline TVector3 GetBeamElectronP3 (void) const { return GetParticleP3(GetBeamElectronIndex()); }; inline double GetBeamElectronMom (void) const { return GetParticleMom(GetBeamElectronIndex()); }; inline double GetBeamElectronMom2 (void) const { return GetParticleMom2(GetBeamElectronIndex()); }; inline double GetBeamElectronE (void) const { return GetParticleE(GetBeamElectronIndex()); }; inline FitParticle* GetBeamElectron (void) { return GetParticle(GetBeamElectronIndex()); }; // ---- Pion INCOMING Functions int GetBeamPionIndex (void) const; inline TLorentzVector GetBeamPionP4 (void) const { return GetParticleP4(GetBeamPionIndex()); }; inline TVector3 GetBeamPionP3 (void) const { return GetParticleP3(GetBeamPionIndex()); }; inline double GetBeamPionMom (void) const { return GetParticleMom(GetBeamPionIndex()); }; inline double GetBeamPionMom2 (void) const { return GetParticleMom2(GetBeamPionIndex()); }; inline double GetBeamPionE (void) const { return GetParticleE(GetBeamPionIndex()); }; inline FitParticle* GetBeamPion (void) { return GetParticle(GetBeamPionIndex()); }; // ---- Generic beam incoming functions // I'm not 100% sure why these can't replace the above (FitEvent knows the type) int GetBeamPartIndex (void) const; inline TLorentzVector GetBeamPartP4 (void) const { return GetParticleP4(GetBeamPartIndex()); }; inline TVector3 GetBeamPartP3 (void) const { return GetParticleP3(GetBeamPartIndex()); }; inline double GetBeamPartMom (void) const { return GetParticleMom(GetBeamPartIndex()); }; inline double GetBeamPartMom2 (void) const { return GetParticleMom2(GetBeamPartIndex()); }; inline double GetBeamPartE (void) const { return GetParticleE(GetBeamPartIndex()); }; inline int GetBeamPartPDG (void) const { return GetParticlePDG(GetBeamPartIndex()); }; inline int GetPartInPos (void) const { return GetBeamPartIndex(); }; inline FitParticle* GetBeamPart (void) { return GetParticle(GetBeamPartIndex()); }; /// Legacy Functions inline FitParticle* PartInfo(uint i) { return GetParticle(i); }; inline UInt_t Npart (void) const { return NPart(); }; inline UInt_t NPart (void) const { return fNParticles; }; // Other Functions int NumFSMesons(); // Get outgoing lepton matching PDG of neutrino int GetLeptonOutPDG(); FitParticle* GetLeptonOut() {return GetHMFSParticle(GetLeptonOutPDG()); }; // Get the outgoing lepton index int GetLeptonIndex() { return GetHMFSParticleIndex(GetLeptonOutPDG()); }; double GetQ2(); // Event Information UInt_t fEventNo; double fTotCrs; int fTargetA; int fTargetZ; int fTargetH; bool fBound; int fDistance; int fTargetPDG; // Reduced Particle Stack UInt_t kMaxParticles; int fNParticles; double** fParticleMom; UInt_t* fParticleState; int* fParticlePDG; FitParticle** fParticleList; bool *fPrimaryVertex; double** fOrigParticleMom; UInt_t* fOrigParticleState; int* fOrigParticlePDG; bool* fOrigPrimaryVertex; double* fNEUT_ParticleStatusCode; double* fNEUT_ParticleAliveCode; GeneratorInfoBase* fGenInfo; // Config Options for this class bool kRemoveFSIParticles; bool kRemoveUndefParticles; }; /*! @} */ #endif diff --git a/src/InputHandler/InputHandler.cxx b/src/InputHandler/InputHandler.cxx index 304b445..e65591f 100644 --- a/src/InputHandler/InputHandler.cxx +++ b/src/InputHandler/InputHandler.cxx @@ -1,311 +1,305 @@ // 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; fSkip = 0; if (FitPar::Config().HasConfig("NSKIPEVENTS")) { fSkip = FitPar::Config().GetParI("NSKIPEVENTS"); } }; 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()); // } } void InputHandlerBase::Print(){}; TH1D *InputHandlerBase::GetXSecHistogram(void) { - fXSecHist = (TH1D *)fFluxHist->Clone(); - fXSecHist->Divide(fEventHist); + fXSecHist = (TH1D *)fEventHist->Clone(); + fXSecHist->SetNameTitle((fName + "_XSEC").c_str(), (fName + "_XSEC").c_str()); + fXSecHist->GetYaxis()->SetTitle("#sigma #times 10^{-38} (cm^{2}/nucleon)"); + fXSecHist->Divide(fFluxHist); return fXSecHist; }; double InputHandlerBase::PredictedEventRate(double low, double high, std::string intOpt) { Int_t minBin = fEventHist->GetXaxis()->FindFixBin(low); Int_t maxBin = fEventHist->GetXaxis()->FindFixBin(high); if ((fEventHist->IsBinOverflow(minBin) && (low != -9999.9))) { minBin = 1; } if ((fEventHist->IsBinOverflow(maxBin) && (high != -9999.9))) { maxBin = fEventHist->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) / fEventHist->GetXaxis()->GetBinWidth(minBin)) * fEventHist->Integral(minBin, minBin, intOpt.c_str()); } double lowBinUpEdge = fEventHist->GetXaxis()->GetBinUpEdge(minBin); double highBinLowEdge = fEventHist->GetXaxis()->GetBinLowEdge(maxBin); double lowBinfracIntegral = ((lowBinUpEdge - low) / fEventHist->GetXaxis()->GetBinWidth(minBin)) * fEventHist->Integral(minBin, minBin, intOpt.c_str()); double highBinfracIntegral = ((high - highBinLowEdge) / fEventHist->GetXaxis()->GetBinWidth(maxBin)) * fEventHist->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; } double ContainedIntegral = fEventHist->Integral(minBin + 1, maxBin - 1, intOpt.c_str()); // If there are filled bins between them return lowBinfracIntegral + highBinfracIntegral + ContainedIntegral; }; double InputHandlerBase::TotalIntegratedFlux(double low, double high, 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(); high = fFluxHist->GetXaxis()->GetBinLowEdge(maxBin + 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()); double highBinfracIntegral = ((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; } double ContainedIntegral = fFluxHist->Integral(minBin + 1, maxBin - 1, intOpt.c_str()); // If there are filled bins between them return lowBinfracIntegral + highBinfracIntegral + ContainedIntegral; } 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)) { 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]) { jointindexswitch++; // Loop Around if (jointindexswitch == jointindexlow.size()) { jointindexswitch = 0; } } if (fCurrentIndex > jointindexlow[jointindexswitch] + jointindexallowed[jointindexswitch]) { fCurrentIndex = jointindexlow[jointindexswitch]; } } return GetBaseEvent(fCurrentIndex); }; 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()); 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); } 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) { NUIS_ABORT("Can only handle joint inputs when config MAXEVENTS = -1!"); } - if (jointeventinputs.size() > 1) { - NUIS_ERR( - 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 *= jointeventinputs.at(i)->Integral("width"); scale /= double(jointindexhigh[i] - jointindexlow[i]); 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; } } BaseFitEvt *InputHandlerBase::GetBaseEvent(const UInt_t entry) { // Do some light processing: don't calculate the kinematics 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]) { jointindexswitch++; // Loop Around if (jointindexswitch >= jointindexlow.size()) { jointindexswitch = 0; } } return jointindexscale[jointindexswitch]; }; diff --git a/src/InputHandler/InputUtils.h b/src/InputHandler/InputUtils.h index ad53852..e344638 100644 --- a/src/InputHandler/InputUtils.h +++ b/src/InputHandler/InputUtils.h @@ -1,49 +1,49 @@ // 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_UTILS_H #define INPUT_UTILS_H #include #include "TFile.h" #include "InputTypes.h" namespace InputUtils { /// Extract Input Type from start of filename InputType ParseInputType(std::string const &inp); -/// Check for comma seperated joint input files +/// Check for comma separated joint input files bool IsJointInput(std::string const &inputs); /// Replace Input Event Diretory tags with Full Names from Config std::string ExpandInputDirectories(std::string const &inputs); /// Open ROOT file and guess what the file type is from the tree names InputType GuessInputTypeFromFile(TFile *inpF); /// Guess file input type and form an updated filename with it std::string PrependGuessedInputTypeToName(std::string const &inpFName); /// Split file inputs by commas and remove brackets before putting into a vector std::vector ParseInputFileList(std::string const& inpFile); } #endif diff --git a/src/InputHandler/NEUTInputHandler.cxx b/src/InputHandler/NEUTInputHandler.cxx index 67c1dac..0735945 100644 --- a/src/InputHandler/NEUTInputHandler.cxx +++ b/src/InputHandler/NEUTInputHandler.cxx @@ -1,547 +1,552 @@ #ifdef __NEUT_ENABLED__ #include "NEUTInputHandler.h" #include "InputUtils.h" #include "PlotUtils.h" #include "TTreePerfStats.h" #include "fsihistC.h" #include "necardC.h" #include "nefillverC.h" #include "neutcrsC.h" #include "neutfsipart.h" #include "neutfsivert.h" #include "neutmodelC.h" #include "neutparamsC.h" #include "neutpart.h" #include "neutrootTreeSingleton.h" #include "neutvect.h" #include "neworkC.h" #include "vcworkC.h" #include "posinnucC.h" #ifdef __NEUT_NUCFSI_ENABLED__ #include "neutnucfsistep.h" #include "neutnucfsivert.h" #include "nucleonfsihistC.h" #endif 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) { NUIS_LOG(SAM, "Creating NEUTInputHandler : " << handle); // 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()) { NUIS_ABORT( "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) { NUIS_ERR(FTL, "Input File Contents: " << inputs[inp_it]); inp_file->ls(); NUIS_ABORT("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) { NUIS_ERR(FTL, "neuttree not located in NEUT file: " << inputs[inp_it]); NUIS_ABORT( "Check your inputs, they may need to be completely regenerated!"); throw; } int nevents = neuttree->GetEntries(); if (nevents <= 0) { NUIS_ABORT("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); #if defined(ROOT6) && defined(__NEUT_VERSION__) && (__NEUT_VERSION__ >= 541) fNEUTTree->SetAutoDelete(true); #endif 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 ent, const bool lightweight) { UInt_t entry = ent + fSkip; // 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 { UInt_t npart = fNeutVect->Npart(); 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; } // From NEUT neutclass/neutpart.h // Bool_t fIsAlive; // Particle should be tracked or not // ( in the detector simulator ) // // Int_t fStatus; // Status flag of this particle // -2: Non existing particle // -1: Initial state particle // 0: Normal // 1: Decayed to the other particle // 2: Escaped from the detector // 3: Absorped // 4: Charge exchanged // 5: Pauli blocked // 6: N/A // 7: Produced child particles // 8: Inelastically scattered // int NEUTInputHandler::GetNeutParticleStatus(NeutPart *part) { // State int state = kUndefinedState; // Remove Pauli blocked events, probably just single pion events if (part->fStatus == 5) { state = kFSIState; // fStatus == -1 means initial state } else 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) == 16 || 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) == 16 || abs(part->fPID) == 14 || abs(part->fPID) == 12)) { state = kFinalState; } else if (part->fIsAlive == true && part->fStatus == 0) { state = kFinalState; } else if (!part->fIsAlive && (part->fStatus == 1 || part->fStatus == 3 || part->fStatus == 4 || part->fStatus == 7 || part->fStatus == 8)) { state = kFSIState; // There's one hyper weird case where fStatus = -3. This apparently // corresponds to a nucleon being ejected via pion FSI when there is "data // available" } else if (!part->fIsAlive && (part->fStatus == -3)) { state = kUndefinedState; // NC neutrino outgoing } else if (!part->fIsAlive && part->fStatus == 0 && (abs(part->fPID) == 16 || abs(part->fPID) == 14 || abs(part->fPID) == 12)) { state = kFinalState; // Warn if we still find alive particles without classifying them } else if (part->fIsAlive == true) { NUIS_ABORT("Undefined NEUT state " << " Alive: " << part->fIsAlive << " Status: " << part->fStatus - << " PDG: " << part->fPID); + << " PDG: " << part->fPID << " Mode: " << fNeutVect->Mode); + } else if (abs(fNeutVect->Mode) == 35){ + NUIS_ERR(WRN, "Marking nonsensical CC difractive event as undefined " + << " Alive: " << part->fIsAlive << " Status: " << part->fStatus + << " PDG: " << part->fPID << " Mode: " << fNeutVect->Mode); + state = kUndefinedState; // Warn if we find dead particles that we haven't classified } else { NUIS_ABORT("Undefined NEUT state " << " Alive: " << part->fIsAlive << " Status: " << part->fStatus - << " PDG: " << part->fPID); + << " PDG: " << part->fPID << " Mode: " << fNeutVect->Mode); } return state; } void NEUTInputHandler::CalcNUISANCEKinematics() { // Reset all variables fNUISANCEEvent->ResetEvent(); // Fill Globals 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) { NUIS_ERR(WRN, "NEUT has too many particles. Expanding stack."); fNUISANCEEvent->ExpandParticleStack(npart); } - int nprimary = fNeutVect->Nprimary(); + UInt_t nprimary = fNeutVect->Nprimary(); // 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; // Is the paricle associated with the primary vertex? bool primary = false; // NEUT events are just popped onto the stack as primary, then continues to // be non-primary if (i < nprimary) primary = true; fNUISANCEEvent->fPrimaryVertex[curpart] = primary; // 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 *ISAnyLepton = fNUISANCEEvent->GetHMISAnyLeptons(); if (ISAnyLepton) { fNUISANCEEvent->probe_E = ISAnyLepton->E(); fNUISANCEEvent->probe_pdg = ISAnyLepton->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(); #ifdef NEUT_COMMON_QEAV nemdls_.mdlqeaf = nvect->QEAVForm; #else nemdls_.mdlqeaf = nvect->QEVForm; #endif 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/Logger/FitLogger.cxx b/src/Logger/FitLogger.cxx index b80b718..4b7f178 100644 --- a/src/Logger/FitLogger.cxx +++ b/src/Logger/FitLogger.cxx @@ -1,327 +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 . *******************************************************************************/ #include "FitLogger.h" #include #include namespace Logger { // Logger Variables int log_verb = 4; bool use_colors = true; bool showtrace = true; std::ostream* __LOG_outstream(&std::cout); std::ofstream __LOG_nullstream; // Error Variables int err_verb = 0; std::ostream* __ERR_outstream(&std::cerr); // Extra Variables -bool external_verb = false; +bool external_verb = true; bool super_rainbow_mode = true; //!< For when fitting gets boring. unsigned int super_rainbow_mode_colour = 0; std::streambuf* default_cout = std::cout.rdbuf(); std::streambuf* default_cerr = std::cerr.rdbuf(); std::ofstream redirect_stream("/dev/null"); int silentfd = open("/dev/null", O_WRONLY); int savedstdoutfd = dup(fileno(stdout)); int savedstderrfd = dup(fileno(stderr)); int nloggercalls = 0; int timelastlog = 0; } // -------- Logging Functions --------- // bool LOGGING(int level) { // std::cout << "LOGGING : " << __FILENAME__ << " " << __FUNCTION__ << // std::endl; return (Logger::log_verb >= (int)__GETLOG_LEVEL(level, __FILENAME__, __FUNCTION__)); }; int __GETLOG_LEVEL(int level, const char* filename, const char* funct) { #ifdef __DEBUG__ int logfile = FitPar::Config().GetParI("logging." + std::string(filename)); if (logfile >= DEB and logfile <= EVT) { level = logfile; } int logfunc = FitPar::Config().GetParI("logging." + std::string(funct)); if (logfunc >= DEB and logfunc <= EVT) { level = logfunc; } #endif return level; }; std::ostream& __OUTLOG(int level, const char* filename, const char* funct, int line) { if (Logger::log_verb < (int)level && Logger::log_verb != (int)DEB) { return (Logger::__LOG_nullstream); } else { if (Logger::use_colors) { switch (level) { case FIT: std::cout << BOLDGREEN; break; case MIN: std::cout << BOLDBLUE; break; case SAM: std::cout << MAGENTA; break; case REC: std::cout << BLUE; break; case SIG: std::cout << GREEN; break; case DEB: std::cout << CYAN; break; default: break; } } switch (level) { case FIT: std::cout << "[LOG Fitter]"; break; case MIN: std::cout << "[LOG Minmzr]"; break; case SAM: std::cout << "[LOG Sample]"; break; case REC: std::cout << "[LOG Reconf]"; break; case SIG: std::cout << "[LOG Signal]"; break; case EVT: std::cout << "[LOG Event ]"; break; case DEB: std::cout << "[LOG DEBUG ]"; break; default: std::cout << "[LOG INFO ]"; break; } // Apply indent if (true) { switch (level) { case FIT: std::cout << ": "; break; case MIN: std::cout << ":- "; break; case SAM: std::cout << ":-- "; break; case REC: std::cout << ":--- "; break; case SIG: std::cout << ":---- "; break; case EVT: std::cout << ":----- "; break; case DEB: std::cout << ":------ "; break; default: std::cout << " "; break; } } if (Logger::use_colors) std::cout << RESET; if (Logger::showtrace) { std::cout << " : " << filename << "::" << funct << "[l. " << line << "] : "; } return *(Logger::__LOG_outstream); } } void SETVERBOSITY(int level) { Logger::log_verb = level; } void SETERRVERBOSITY(int level) { Logger::err_verb = level; } void SETVERBOSITY(std::string verb) { if (!verb.compare("DEB")) Logger::log_verb = -1; else if (!verb.compare("QUIET")) Logger::log_verb = 0; else if (!verb.compare("FIT")) Logger::log_verb = 1; else if (!verb.compare("MIN")) Logger::log_verb = 2; else if (!verb.compare("SAM")) Logger::log_verb = 3; else if (!verb.compare("REC")) Logger::log_verb = 4; else if (!verb.compare("SIG")) Logger::log_verb = 5; else if (!verb.compare("EVT")) Logger::log_verb = 6; else Logger::log_verb = std::atoi(verb.c_str()); } //****************************************** void SETERRVERBOSITY(std::string verb) { //****************************************** std::cout << "Setting ERROR VERB" << std::endl; if (!verb.compare("ERRQUIET")) Logger::err_verb = 0; else if (!verb.compare("FTL")) Logger::err_verb = 1; else if (!verb.compare("WRN")) Logger::err_verb = 2; // else Logger::err_verb = GeneralUtils::StrToInt(verb); std::cout << "Set error verbosity to : " << Logger::err_verb << std::endl; return; } /// Set Trace Option void SETTRACE(bool val) { Logger::showtrace = val; } // ------ ERROR FUNCTIONS ---------- // std::ostream& __OUTERR(int level, const char* filename, const char* funct, int line) { if (Logger::use_colors) std::cerr << RED; switch (level) { case FTL: std::cerr << "[ERR FATAL ]: "; break; case WRN: std::cerr << "[ERR WARN ]: "; break; } if (Logger::use_colors) std::cerr << RESET; // Allows enable error debugging trace if (true or Logger::showtrace) { std::cout << filename << "::" << funct << "[l. " << line << "] : "; } return *(Logger::__ERR_outstream); } // ----------- External Logging ----------- // void SETEXTERNALVERBOSITY(int level) { Logger::external_verb = (level > 0); } void StopTalking() { // Check verbosity set correctly if (!Logger::external_verb) return; // Only redirect if we're not debugging if (Logger::log_verb == (int)DEB) return; std::cout.rdbuf(Logger::redirect_stream.rdbuf()); std::cerr.rdbuf(Logger::redirect_stream.rdbuf()); shhnuisancepythiaitokay_(); fflush(stdout); fflush(stderr); dup2(Logger::silentfd, fileno(stdout)); dup2(Logger::silentfd, fileno(stderr)); } void StartTalking() { // Check verbosity set correctly if (!Logger::external_verb) return; std::cout.rdbuf(Logger::default_cout); std::cerr.rdbuf(Logger::default_cerr); canihaznuisancepythia_(); fflush(stdout); fflush(stderr); dup2(Logger::savedstdoutfd, fileno(stdout)); dup2(Logger::savedstderrfd, fileno(stderr)); } //****************************************** bool LOG_LEVEL(int level) { //****************************************** if (Logger::log_verb == (int)DEB) { return true; } if (Logger::log_verb < (int)level) { return false; } return true; } void SET_TRACE(bool val) { Logger::showtrace = val; } //****************************************** std::ostream& _LOG(int level, const char* filename, const char* func, int line) //****************************************** { return __OUTLOG(level, filename, func, line); } //****************************************** std::ostream& _ERR(int level, const char* filename, const char* func, int line) //****************************************** { if (Logger::use_colors) std::cerr << RED; if (Logger::showtrace) { std::cout << filename << "::" << func << "[l. " << line << "] : "; } switch (level) { case FTL: std::cerr << "[ERR FATAL ]: "; break; case WRN: std::cerr << "[ERR WARN ] : "; break; } if (Logger::use_colors) std::cerr << RESET; return *Logger::__ERR_outstream; } diff --git a/src/MCStudies/GenericFlux_Vectors.cxx b/src/MCStudies/GenericFlux_Vectors.cxx index 3eb4410..2fc224f 100644 --- a/src/MCStudies/GenericFlux_Vectors.cxx +++ b/src/MCStudies/GenericFlux_Vectors.cxx @@ -1,503 +1,502 @@ // 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 "GenericFlux_Vectors.h" #ifndef __NO_MINERvA__ #include "MINERvA_SignalDef.h" #endif #ifndef __NO_T2K__ #include "T2K_SignalDef.h" #endif GenericFlux_Vectors::GenericFlux_Vectors(std::string name, std::string inputfile, FitWeight *rw, std::string type, std::string fakeDataFile) { // Measurement Details fName = name; eventVariables = NULL; // Define our energy range for flux calcs EnuMin = 0.; EnuMax = 1E10; // Arbritrarily high energy limit if (Config::HasPar("EnuMin")) { EnuMin = Config::GetParD("EnuMin"); } if (Config::HasPar("EnuMax")) { EnuMax = Config::GetParD("EnuMax"); } SavePreFSI = Config::Get().GetParB("nuisflat_SavePreFSI"); NUIS_LOG(SAM, "Running GenericFlux_Vectors saving pre-FSI particles? " << SavePreFSI); + SaveSignalFlags = Config::Get().GetParB("nuisflat_SaveSignalFlags"); + NUIS_LOG(SAM, "Running GenericFlux_Vectors saving signal flags? " + << SaveSignalFlags); + // Set default fitter flags fIsDiag = true; fIsShape = false; fIsRawEvents = false; // This function will sort out the input files automatically and parse all the // inputs,flags,etc. // There may be complex cases where you have to do this by hand, but usually // this will do. Measurement1D::SetupMeasurement(inputfile, type, rw, fakeDataFile); eventVariables = NULL; // Setup fDataHist as a placeholder this->fDataHist = new TH1D(("empty_data"), ("empty-data"), 1, 0, 1); this->SetupDefaultHist(); fFullCovar = StatUtils::MakeDiagonalCovarMatrix(fDataHist); covar = StatUtils::GetInvert(fFullCovar); // 1. The generator is organised in SetupMeasurement so it gives the // cross-section in "per nucleon" units. // So some extra scaling for a specific measurement may be required. For // Example to get a "per neutron" measurement on carbon // which we do here, we have to multiple by the number of nucleons 12 and // divide by the number of neutrons 6. // N.B. MeasurementBase::PredictedEventRate includes the 1E-38 factor that is // often included here in other classes that directly integrate the event // histogram. This method is used here as it now respects EnuMin and EnuMax // correctly. this->fScaleFactor = (this->PredictedEventRate("width", 0, EnuMax) / double(fNEvents)) / this->TotalIntegratedFlux("width"); NUIS_LOG(SAM, " Generic Flux Scaling Factor = " << fScaleFactor << " [= " << (GetEventHistogram()->Integral("width") * 1E-38) << "/(" << (fNEvents + 0.) << "*" << TotalIntegratedFlux("width") << ")]"); if (fScaleFactor <= 0.0) { NUIS_ABORT("SCALE FACTOR TOO LOW"); } // Setup our TTrees this->AddEventVariablesToTree(); - this->AddSignalFlagsToTree(); + if (SaveSignalFlags) this->AddSignalFlagsToTree(); } void GenericFlux_Vectors::AddEventVariablesToTree() { // Setup the TTree to save everything if (!eventVariables) { Config::Get().out->cd(); eventVariables = new TTree((this->fName + "_VARS").c_str(), (this->fName + "_VARS").c_str()); } NUIS_LOG(SAM, "Adding Event Variables"); eventVariables->Branch("Mode", &Mode, "Mode/I"); eventVariables->Branch("cc", &cc, "cc/B"); eventVariables->Branch("PDGnu", &PDGnu, "PDGnu/I"); eventVariables->Branch("Enu_true", &Enu_true, "Enu_true/F"); eventVariables->Branch("tgt", &tgt, "tgt/I"); eventVariables->Branch("tgta", &tgta, "tgta/I"); eventVariables->Branch("tgtz", &tgtz, "tgtz/I"); eventVariables->Branch("PDGLep", &PDGLep, "PDGLep/I"); eventVariables->Branch("ELep", &ELep, "ELep/F"); eventVariables->Branch("CosLep", &CosLep, "CosLep/F"); // Basic interaction kinematics eventVariables->Branch("Q2", &Q2, "Q2/F"); eventVariables->Branch("q0", &q0, "q0/F"); eventVariables->Branch("q3", &q3, "q3/F"); eventVariables->Branch("Enu_QE", &Enu_QE, "Enu_QE/F"); eventVariables->Branch("Q2_QE", &Q2_QE, "Q2_QE/F"); eventVariables->Branch("W_nuc_rest", &W_nuc_rest, "W_nuc_rest/F"); eventVariables->Branch("W", &W, "W/F"); eventVariables->Branch("W_genie", &W_genie, "W_genie/F"); eventVariables->Branch("x", &x, "x/F"); eventVariables->Branch("y", &y, "y/F"); eventVariables->Branch("Eav", &Eav, "Eav/F"); eventVariables->Branch("EavAlt", &EavAlt, "EavAlt/F"); eventVariables->Branch("CosThetaAdler", &CosThetaAdler, "CosThetaAdler/F"); eventVariables->Branch("PhiAdler", &PhiAdler, "PhiAdler/F"); eventVariables->Branch("dalphat", &dalphat, "dalphat/F"); eventVariables->Branch("dpt", &dpt, "dpt/F"); eventVariables->Branch("dphit", &dphit, "dphit/F"); eventVariables->Branch("pnreco_C", &pnreco_C, "pnreco_C/F"); // Save outgoing particle vectors eventVariables->Branch("nfsp", &nfsp, "nfsp/I"); eventVariables->Branch("px", px, "px[nfsp]/F"); eventVariables->Branch("py", py, "py[nfsp]/F"); eventVariables->Branch("pz", pz, "pz[nfsp]/F"); eventVariables->Branch("E", E, "E[nfsp]/F"); eventVariables->Branch("pdg", pdg, "pdg[nfsp]/I"); eventVariables->Branch("pdg_rank", pdg_rank, "pdg_rank[nfsp]/I"); // Save init particle vectors eventVariables->Branch("ninitp", &ninitp, "ninitp/I"); eventVariables->Branch("px_init", px_init, "px_init[ninitp]/F"); eventVariables->Branch("py_init", py_init, "py_init[ninitp]/F"); eventVariables->Branch("pz_init", pz_init, "pz_init[ninitp]/F"); eventVariables->Branch("E_init", E_init, "E_init[ninitp]/F"); eventVariables->Branch("pdg_init", pdg_init, "pdg_init[ninitp]/I"); // Save pre-FSI vectors eventVariables->Branch("nvertp", &nvertp, "nvertp/I"); eventVariables->Branch("px_vert", px_vert, "px_vert[nvertp]/F"); eventVariables->Branch("py_vert", py_vert, "py_vert[nvertp]/F"); eventVariables->Branch("pz_vert", pz_vert, "pz_vert[nvertp]/F"); eventVariables->Branch("E_vert", E_vert, "E_vert[nvertp]/F"); eventVariables->Branch("pdg_vert", pdg_vert, "pdg_vert[nvertp]/I"); // Event Scaling Information eventVariables->Branch("Weight", &Weight, "Weight/F"); eventVariables->Branch("InputWeight", &InputWeight, "InputWeight/F"); eventVariables->Branch("RWWeight", &RWWeight, "RWWeight/F"); // Should be a double because may be 1E-39 and less eventVariables->Branch("fScaleFactor", &fScaleFactor, "fScaleFactor/D"); // The customs eventVariables->Branch("CustomWeight", &CustomWeight, "CustomWeight/F"); eventVariables->Branch("CustomWeightArray", CustomWeightArray, "CustomWeightArray[6]/F"); return; } void GenericFlux_Vectors::FillEventVariables(FitEvent *event) { ResetVariables(); // Fill Signal Variables - FillSignalFlags(event); + if (SaveSignalFlags) FillSignalFlags(event); NUIS_LOG(DEB, "Filling signal"); // Now fill the information Mode = event->Mode; cc = event->IsCC(); // Get the incoming neutrino and outgoing lepton FitParticle *nu = event->GetBeamPart(); FitParticle *lep = event->GetHMFSAnyLepton(); PDGnu = nu->fPID; Enu_true = nu->fP.E() / 1E3; tgt = event->fTargetPDG; tgta = event->fTargetA; tgtz = event->fTargetZ; TLorentzVector ISP4 = nu->fP; if (lep != NULL) { PDGLep = lep->fPID; ELep = lep->fP.E() / 1E3; CosLep = cos(nu->fP.Vect().Angle(lep->fP.Vect())); // Basic interaction kinematics Q2 = -1 * (nu->fP - lep->fP).Mag2() / 1E6; q0 = (nu->fP - lep->fP).E() / 1E3; q3 = (nu->fP - lep->fP).Vect().Mag() / 1E3; // These assume C12 binding from MINERvA... not ideal Enu_QE = FitUtils::EnuQErec(lep->fP, CosLep, 34., true); Q2_QE = FitUtils::Q2QErec(lep->fP, CosLep, 34., true); Eav = FitUtils::GetErecoil_MINERvA_LowRecoil(event) / 1.E3; EavAlt = FitUtils::Eavailable(event) / 1.E3; // Check if this is a 1pi+ or 1pi0 event if ((SignalDef::isCC1pi(event, PDGnu, 211) || SignalDef::isCC1pi(event, PDGnu, -211) || SignalDef::isCC1pi(event, PDGnu, 111)) && event->NumFSNucleons() == 1) { TLorentzVector Pnu = nu->fP; TLorentzVector Pmu = lep->fP; TLorentzVector Ppi = event->GetHMFSPions()->fP; TLorentzVector Pprot = event->GetHMFSNucleons()->fP; CosThetaAdler = FitUtils::CosThAdler(Pnu, Pmu, Ppi, Pprot); PhiAdler = FitUtils::PhiAdler(Pnu, Pmu, Ppi, Pprot); } // Get W_true with assumption of initial state nucleon at rest float m_n = (float)PhysConst::mass_proton; // Q2 assuming nucleon at rest W_nuc_rest = sqrt(-Q2 + 2 * m_n * q0 + m_n * m_n); + W = W_nuc_rest; // For want of a better thing to do // True Q2 x = Q2 / (2 * m_n * q0); y = 1 - ELep / Enu_true; dalphat = FitUtils::Get_STV_dalphat_HMProton(event, PDGnu, true); dpt = FitUtils::Get_STV_dpt_HMProton(event, PDGnu, true); dphit = FitUtils::Get_STV_dphit_HMProton(event, PDGnu, true); pnreco_C = FitUtils::Get_pn_reco_C_HMProton(event, PDGnu, true); } // Loop over the particles and store all the final state particles in a vector for (UInt_t i = 0; i < event->Npart(); ++i) { if (event->PartInfo(i)->fIsAlive && event->PartInfo(i)->Status() == kFinalState) partList.push_back(event->PartInfo(i)); if (SavePreFSI && event->fPrimaryVertex[i]) vertList.push_back(event->PartInfo(i)); if (SavePreFSI && event->PartInfo(i)->IsInitialState()) initList.push_back(event->PartInfo(i)); if (event->PartInfo(i)->IsInitialState()) { ISP4 += event->PartInfo(i)->fP; } } // Save outgoing particle vectors nfsp = (int)partList.size(); std::map > > pdgMap; for (int i = 0; i < nfsp; ++i) { px[i] = partList[i]->fP.X() / 1E3; py[i] = partList[i]->fP.Y() / 1E3; pz[i] = partList[i]->fP.Z() / 1E3; E[i] = partList[i]->fP.E() / 1E3; pdg[i] = partList[i]->fPID; pdgMap[pdg[i]].push_back(std::make_pair(partList[i]->fP.Vect().Mag(), i)); } for (std::map > >::iterator iter = pdgMap.begin(); iter != pdgMap.end(); ++iter) { std::vector > thisVect = iter->second; std::sort(thisVect.begin(), thisVect.end()); // Now save the order... a bit funky to avoid inverting int nPart = (int)thisVect.size() - 1; for (int i = nPart; i >= 0; --i) { pdg_rank[thisVect[i].second] = nPart - i; } } // Save pre-FSI particles nvertp = (int)vertList.size(); for (int i = 0; i < nvertp; ++i) { px_vert[i] = vertList[i]->fP.X() / 1E3; py_vert[i] = vertList[i]->fP.Y() / 1E3; pz_vert[i] = vertList[i]->fP.Z() / 1E3; E_vert[i] = vertList[i]->fP.E() / 1E3; pdg_vert[i] = vertList[i]->fPID; } // Save init particles ninitp = (int)initList.size(); for (int i = 0; i < ninitp; ++i) { px_init[i] = initList[i]->fP.X() / 1E3; py_init[i] = initList[i]->fP.Y() / 1E3; pz_init[i] = initList[i]->fP.Z() / 1E3; E_init[i] = initList[i]->fP.E() / 1E3; pdg_init[i] = initList[i]->fPID; } #ifdef __GENIE_ENABLED__ if (event->fType == kGENIE) { EventRecord *gevent = static_cast(event->genie_event->event); const Interaction *interaction = gevent->Summary(); const Kinematics &kine = interaction->Kine(); W_genie = kine.W(); } #endif - if (lep != NULL) { - W = (ISP4 - lep->fP).M(); - } else { - W = 0; - } - // Fill event weights Weight = event->RWWeight * event->InputWeight; RWWeight = event->RWWeight; InputWeight = event->InputWeight; // And the Customs CustomWeight = event->CustomWeight; for (int i = 0; i < 6; ++i) { CustomWeightArray[i] = event->CustomWeightArray[i]; } // Fill the eventVariables Tree eventVariables->Fill(); return; }; //******************************************************************** void GenericFlux_Vectors::ResetVariables() { //******************************************************************** cc = false; // Reset all Function used to extract any variables of interest to the event Mode = PDGnu = tgt = tgta = tgtz = PDGLep = 0; Enu_true = ELep = CosLep = Q2 = q0 = q3 = Enu_QE = Q2_QE = W_nuc_rest = W = x = y = Eav = EavAlt = CosThetaAdler = PhiAdler = -999.9; W_genie = -999; // Other fun variables // MINERvA-like ones dalphat = dpt = dphit = pnreco_C = -999.99; nfsp = ninitp = nvertp = 0; for (int i = 0; i < kMAX; ++i) { px[i] = py[i] = pz[i] = E[i] = -999; pdg[i] = pdg_rank[i] = 0; px_init[i] = py_init[i] = pz_init[i] = E_init[i] = -999; pdg_init[i] = 0; px_vert[i] = py_vert[i] = pz_vert[i] = E_vert[i] = -999; pdg_vert[i] = 0; } Weight = InputWeight = RWWeight = 0.0; CustomWeight = 0.0; for (int i = 0; i < 6; ++i) CustomWeightArray[i] = 0.0; partList.clear(); initList.clear(); vertList.clear(); flagCCINC = flagNCINC = flagCCQE = flagCC0pi = flagCCQELike = flagNCEL = flagNC0pi = flagCCcoh = flagNCcoh = flagCC1pip = flagNC1pip = flagCC1pim = flagNC1pim = flagCC1pi0 = flagNC1pi0 = false; #ifndef __NO_MINERvA__ flagCC0piMINERvA = false; #endif #ifndef __NO_T2K__ flagCC0Pi_T2K_AnaI = false; flagCC0Pi_T2K_AnaII = false; #endif } //******************************************************************** void GenericFlux_Vectors::FillSignalFlags(FitEvent *event) { //******************************************************************** // Some example flags are given from SignalDef. // See src/Utils/SignalDef.cxx for more. int nuPDG = event->PartInfo(0)->fPID; // Generic signal flags flagCCINC = SignalDef::isCCINC(event, nuPDG); flagNCINC = SignalDef::isNCINC(event, nuPDG); flagCCQE = SignalDef::isCCQE(event, nuPDG); flagCCQELike = SignalDef::isCCQELike(event, nuPDG); flagCC0pi = SignalDef::isCC0pi(event, nuPDG); flagNCEL = SignalDef::isNCEL(event, nuPDG); flagNC0pi = SignalDef::isNC0pi(event, nuPDG); flagCCcoh = SignalDef::isCCCOH(event, nuPDG, 211); flagNCcoh = SignalDef::isNCCOH(event, nuPDG, 111); flagCC1pip = SignalDef::isCC1pi(event, nuPDG, 211); flagNC1pip = SignalDef::isNC1pi(event, nuPDG, 211); flagCC1pim = SignalDef::isCC1pi(event, nuPDG, -211); flagNC1pim = SignalDef::isNC1pi(event, nuPDG, -211); flagCC1pi0 = SignalDef::isCC1pi(event, nuPDG, 111); flagNC1pi0 = SignalDef::isNC1pi(event, nuPDG, 111); #ifndef __NO_MINERvA__ flagCC0piMINERvA = SignalDef::isCC0pi_MINERvAPTPZ(event, 14); #endif #ifndef __NO_T2K__ flagCC0Pi_T2K_AnaI = SignalDef::isT2K_CC0pi(event, EnuMin, EnuMax, SignalDef::kAnalysis_I); flagCC0Pi_T2K_AnaII = SignalDef::isT2K_CC0pi(event, EnuMin, EnuMax, SignalDef::kAnalysis_II); #endif } void GenericFlux_Vectors::AddSignalFlagsToTree() { if (!eventVariables) { Config::Get().out->cd(); eventVariables = new TTree((this->fName + "_VARS").c_str(), (this->fName + "_VARS").c_str()); } NUIS_LOG(SAM, "Adding signal flags"); // Signal Definitions from SignalDef.cxx eventVariables->Branch("flagCCINC", &flagCCINC, "flagCCINC/O"); eventVariables->Branch("flagNCINC", &flagNCINC, "flagNCINC/O"); eventVariables->Branch("flagCCQE", &flagCCQE, "flagCCQE/O"); eventVariables->Branch("flagCC0pi", &flagCC0pi, "flagCC0pi/O"); eventVariables->Branch("flagCCQELike", &flagCCQELike, "flagCCQELike/O"); eventVariables->Branch("flagNCEL", &flagNCEL, "flagNCEL/O"); eventVariables->Branch("flagNC0pi", &flagNC0pi, "flagNC0pi/O"); eventVariables->Branch("flagCCcoh", &flagCCcoh, "flagCCcoh/O"); eventVariables->Branch("flagNCcoh", &flagNCcoh, "flagNCcoh/O"); eventVariables->Branch("flagCC1pip", &flagCC1pip, "flagCC1pip/O"); eventVariables->Branch("flagNC1pip", &flagNC1pip, "flagNC1pip/O"); eventVariables->Branch("flagCC1pim", &flagCC1pim, "flagCC1pim/O"); eventVariables->Branch("flagNC1pim", &flagNC1pim, "flagNC1pim/O"); eventVariables->Branch("flagCC1pi0", &flagCC1pi0, "flagCC1pi0/O"); eventVariables->Branch("flagNC1pi0", &flagNC1pi0, "flagNC1pi0/O"); #ifndef __NO_MINERvA__ eventVariables->Branch("flagCC0piMINERvA", &flagCC0piMINERvA, "flagCC0piMINERvA/O"); #endif #ifndef __NO_T2K__ eventVariables->Branch("flagCC0Pi_T2K_AnaI", &flagCC0Pi_T2K_AnaI, "flagCC0Pi_T2K_AnaI/O"); eventVariables->Branch("flagCC0Pi_T2K_AnaII", &flagCC0Pi_T2K_AnaII, "flagCC0Pi_T2K_AnaII/O"); #endif }; void GenericFlux_Vectors::Write(std::string drawOpt) { // First save the TTree eventVariables->Write(); // Save Flux and Event Histograms too GetInput()->GetFluxHistogram()->Write(); GetInput()->GetEventHistogram()->Write(); return; } // Override functions which aren't really necessary bool GenericFlux_Vectors::isSignal(FitEvent *event) { (void)event; return true; }; void GenericFlux_Vectors::ScaleEvents() { return; } void GenericFlux_Vectors::ApplyNormScale(float norm) { this->fCurrentNorm = norm; return; } void GenericFlux_Vectors::FillHistograms() { return; } void GenericFlux_Vectors::ResetAll() { // eventVariables->Reset(); return; } float GenericFlux_Vectors::GetChi2() { return 0.0; } diff --git a/src/MCStudies/GenericFlux_Vectors.h b/src/MCStudies/GenericFlux_Vectors.h index 3c5215d..0b1f4a4 100644 --- a/src/MCStudies/GenericFlux_Vectors.h +++ b/src/MCStudies/GenericFlux_Vectors.h @@ -1,165 +1,166 @@ // 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 GenericFlux_Vectors_H_SEEN #define GenericFlux_Vectors_H_SEEN #include "Measurement1D.h" #include "FitEvent.h" class GenericFlux_Vectors : public Measurement1D { public: GenericFlux_Vectors(std::string name, std::string inputfile, FitWeight *rw, std::string type, std::string fakeDataFile); virtual ~GenericFlux_Vectors() {}; //! Grab info from event void FillEventVariables(FitEvent *event); //! Fill signal flags void FillSignalFlags(FitEvent *event); void ResetVariables(); //! 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(); void AddSignalFlagsToTree(); private: TTree* eventVariables; std::vector partList; std::vector initList; std::vector vertList; bool SavePreFSI; + bool SaveSignalFlags; int Mode; bool cc; int PDGnu; int tgt; int tgta; int tgtz; int PDGLep; float ELep; float CosLep; // Basic interaction kinematics float Q2; float q0; float q3; float Enu_QE; float Enu_true; float Q2_QE; float W_nuc_rest; float W; float x; float y; float Eav; float EavAlt; float dalphat; float W_genie; float dpt; float dphit; float pnreco_C; float CosThetaAdler; float PhiAdler; // Save outgoing particle vectors int nfsp; static const int kMAX = 200; float px[kMAX]; float py[kMAX]; float pz[kMAX]; float E[kMAX]; int pdg[kMAX]; int pdg_rank[kMAX]; // Save incoming particle info int ninitp; float px_init[kMAX]; float py_init[kMAX]; float pz_init[kMAX]; float E_init[kMAX]; int pdg_init[kMAX]; // Save pre-FSI particle info int nvertp; float px_vert[kMAX]; float py_vert[kMAX]; float pz_vert[kMAX]; float E_vert[kMAX]; int pdg_vert[kMAX]; // Basic event info float Weight; float InputWeight; float RWWeight; double fScaleFactor; // Custom weights float CustomWeight; float CustomWeightArray[6]; // Generic signal flags bool flagCCINC; bool flagNCINC; bool flagCCQE; bool flagCC0pi; bool flagCCQELike; bool flagNCEL; bool flagNC0pi; bool flagCCcoh; bool flagNCcoh; bool flagCC1pip; bool flagNC1pip; bool flagCC1pim; bool flagNC1pim; bool flagCC1pi0; bool flagNC1pi0; #ifndef __NO_MINERvA__ bool flagCC0piMINERvA; #endif bool flagCC0Pi_T2K_AnaI; bool flagCC0Pi_T2K_AnaII; }; #endif diff --git a/src/MCStudies/MCStudy_KaonPreSelection.cxx b/src/MCStudies/MCStudy_KaonPreSelection.cxx index 8a0a53c..02640e4 100644 --- a/src/MCStudies/MCStudy_KaonPreSelection.cxx +++ b/src/MCStudies/MCStudy_KaonPreSelection.cxx @@ -1,234 +1,233 @@ // 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 "MCStudy_KaonPreSelection.h" #include "T2K_SignalDef.h" #include "MINERvA_SignalDef.h" //******************************************************************** /// @brief Class to perform MC Studies on a custom measurement MCStudy_KaonPreSelection::MCStudy_KaonPreSelection(std::string name, std::string inputfile, FitWeight *rw, std::string type, std::string fakeDataFile) { //******************************************************************** // Measurement Details fName = name; fEventTree = NULL; // Define our energy range for flux calcs EnuMin = 0.; EnuMax = 100.; // Arbritrarily high energy limit // Set default fitter flags fIsDiag = true; fIsShape = false; fIsRawEvents = false; // This function will sort out the input files automatically and parse all the // inputs,flags,etc. // There may be complex cases where you have to do this by hand, but usually // this will do. Measurement1D::SetupMeasurement(inputfile, type, rw, fakeDataFile); fEventTree = NULL; // Setup fDataHist as a placeholder this->fDataHist = new TH1D(("approximate_data"), ("kaon_data"), 5, 1.0, 6.0); // Approximate data points for now fDataHist->SetBinContent(1,0.225E-39); fDataHist->SetBinContent(2,0.215E-39); fDataHist->SetBinContent(3,0.175E-39); fDataHist->SetBinContent(4,0.230E-39); fDataHist->SetBinContent(5,0.210E-39); this->SetupDefaultHist(); fFullCovar = StatUtils::MakeDiagonalCovarMatrix(fDataHist); covar = StatUtils::GetInvert(fFullCovar); // 1. The generator is organised in SetupMeasurement so it gives the // cross-section in "per nucleon" units. // So some extra scaling for a specific measurement may be required. For // Example to get a "per neutron" measurement on carbon // which we do here, we have to multiple by the number of nucleons 12 and // divide by the number of neutrons 6. this->fScaleFactor = (GetEventHistogram()->Integral("width") * 1E-38 / (fNEvents + 0.)) / this->TotalIntegratedFlux(); // Create a new TTree and add Nuisance Events Branches Config::Get().out->cd(); fEventTree = new TTree("nuisance_events","nuisance_events"); GetInput()->GetNuisanceEvent(0)->AddBranchesToTree(fEventTree); fEventTree->Branch("nlep",&nlep, "nlep/I"); fEventTree->Branch("nkplus",&nkplus, "nkplus/I"); //fEventTree->Branch("nkaon",&nkaon, "nkaon/I"); fEventTree->Branch("kplus_mom", &kplusmom, "kplus_mom/D"); // fEventTree->Branch("kaon_mom", &kaonmom, "kaon_mom/D"); // Add Event Scaling Information // This scale factor is used to get the predicted event rate for this sample given // the input flux. Use this when merging different output event ttrees fEventTree->Branch("EventScaleFactor", &fEventScaleFactor, "EventScaleFactor/D"); fEventScaleFactor = GetEventHistogram()->Integral("width") * 1E-38 / (fNEvents + 0.); // NOTES: // To get normalised predictions weight event event by 'EventScaleFactor' to get the // predicted event rate for that sample given the flux used. Then to get cross-sections // divide by the integrated flux from all samples. // e.g. To get the numu+numubar prediction, add the event rate predictions from both // samples together, then divide by the integral of the 'nuisance_flux' histograms in each // sample. // Every particle in the nuisance event is saved into the TTree. The list of particle // status codes are given in src/FitBase/FitParticle.h. The neutrino is usually the first // particle in the list. // If selecting final state kaons, select only kaons with state=2. /* enum particle_state{ kUndefinedState = 5, kInitialState = 0, kFSIState = 1, kFinalState = 2, kNuclearInitial = 3, kNuclearRemnant = 4 }; */ // The structure of the particle lists are a dimensional array for each particle mom, then a 1D array // for the PDG and state. Mode gives the true NEUT interaction channel code. /* tn->Branch("Mode", &fMode, "Mode/I"); tn->Branch("EventNo", &fEventNo, "EventNo/i"); tn->Branch("TotCrs", &fTotCrs, "TotCrs/D"); tn->Branch("TargetA", &fTargetA, "TargetA/I"); tn->Branch("TargetH", &fTargetH, "TargetH/I"); tn->Branch("Bound", &fBound, "Bound/O"); tn->Branch("InputWeight", &InputWeight, "InputWeight/D"); tn->Branch("NParticles", &fNParticles, "NParticles/I"); tn->Branch("ParticleState", fParticleState, "ParticleState[NParticles]/i"); tn->Branch("ParticlePDG", fParticlePDG, "ParticlePDG[NParticles]/I"); tn->Branch("ParticleMom", fParticleMom, "ParticleMom[NParticles][4]/D"); */ // Logging Flag fKaonLogging = FitPar::Config().GetParB("KaonLogging"); return; } //******************************************************************** void MCStudy_KaonPreSelection::FillEventVariables(FitEvent *event) { //******************************************************************** // Reset kplusmom = -999.9; // Save Some Extra Information nkplus = event->NumFSParticle(PhysConst::pdg_kplus); // Nmuons nlep = event->NumFSParticle(13) + event->NumFSParticle(-13); // Leading K+ Mom if (event->GetHMFSParticle(PhysConst::pdg_kplus)){ kplusmom = FitUtils::T(event->GetHMFSParticle(PhysConst::pdg_kplus)->fP)*1000.0; } // Fill XVar fXVar = kplusmom / 1.E3; // Fill If Signal if (isSignal(event)){ fEventTree->Fill(); if (fKaonLogging){ int nstrangemesons = event->NumParticle(321); int nstrangefsmesons = event->NumFSParticle(321); if (nstrangemesons > 0){ std::cout << "New Event ----------------------------" << std::endl; std::cout << "N S Mesons vs NFS S Mesons : " << nstrangemesons << " : " << nstrangefsmesons << std::endl; - event->PrintChris(); event->fNeutVect->Dump(); } } } return; }; //******************************************************************** void MCStudy_KaonPreSelection::Write(std::string drawOpt) { //******************************************************************** // Save the event ttree fEventTree->Write(); // Save Flux and Event Histograms too GetInput()->GetFluxHistogram()->Write("nuisance_fluxhist"); GetInput()->GetEventHistogram()->Write("nuisance_eventhist"); return; } //******************************************************************** /// Select only events with final state Kaons bool MCStudy_KaonPreSelection::isSignal(FitEvent *event) { //******************************************************************** // Update to include all events return true; // Apply a Kaon Pre-selection // Search for Strange Mesons (included full list from MC PDG) /* PhystConst::pdg_strangemesons = {130,310,311,321, 9000311,9000321, 10311,10321,100311,100321, 9010311,9010321,9020311,9020321, 313,323, 10313,10323, 20313,20323, 100313,100323, 9000313,9000323, 30313,30323, 315,325, 9000315,9000325, 10315,10325, 20315,20325, 9010315,9010325,9020315,9020325, 317,327, 9010317,9010327}; PhysConst::pdg_antistrangemesons = {above * -1.0}; */ int nstrangemesons = event->NumParticle(PhysConst::pdg_strangemesons); nstrangemesons += event->NumParticle(PhysConst::pdg_antistrangemesons); if (nstrangemesons < 1) return false; // Do we want any other signal? return true; }; diff --git a/src/MCStudies/MCStudy_NCpi0PreSelection.cxx b/src/MCStudies/MCStudy_NCpi0PreSelection.cxx index 9d5d3ed..9873ce3 100644 --- a/src/MCStudies/MCStudy_NCpi0PreSelection.cxx +++ b/src/MCStudies/MCStudy_NCpi0PreSelection.cxx @@ -1,215 +1,214 @@ // 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 "MCStudy_NCpi0PreSelection.h" #include "T2K_SignalDef.h" #include "MINERvA_SignalDef.h" //******************************************************************** /// @brief Class to perform MC Studies on a custom measurement MCStudy_NCpi0PreSelection::MCStudy_NCpi0PreSelection(std::string name, std::string inputfile, FitWeight *rw, std::string type, std::string fakeDataFile) { //******************************************************************** // Measurement Details fName = name; fEventTree = NULL; // Define our energy range for flux calcs EnuMin = 0.; EnuMax = 100.; // Arbritrarily high energy limit // Set default fitter flags fIsDiag = true; fIsShape = false; fIsRawEvents = false; // This function will sort out the input files automatically and parse all the // inputs,flags,etc. // There may be complex cases where you have to do this by hand, but usually // this will do. Measurement1D::SetupMeasurement(inputfile, type, rw, fakeDataFile); fEventTree = NULL; // Setup fDataHist as a placeholder this->fDataHist = new TH1D(("approximate_data"), ("kaon_data"), 5, 1.0, 6.0); // Approximate data points for now fDataHist->SetBinContent(1,0.225E-39); fDataHist->SetBinContent(2,0.215E-39); fDataHist->SetBinContent(3,0.175E-39); fDataHist->SetBinContent(4,0.230E-39); fDataHist->SetBinContent(5,0.210E-39); this->SetupDefaultHist(); fFullCovar = StatUtils::MakeDiagonalCovarMatrix(fDataHist); covar = StatUtils::GetInvert(fFullCovar); // 1. The generator is organised in SetupMeasurement so it gives the // cross-section in "per nucleon" units. // So some extra scaling for a specific measurement may be required. For // Example to get a "per neutron" measurement on carbon // which we do here, we have to multiple by the number of nucleons 12 and // divide by the number of neutrons 6. this->fScaleFactor = (GetEventHistogram()->Integral("width") * 1E-38 / (fNEvents + 0.)) / this->TotalIntegratedFlux(); // Create a new TTree and add Nuisance Events Branches Config::Get().out->cd(); fEventTree = new TTree("nuisance_events","nuisance_events"); GetInput()->GetEventPointer()->AddBranchesToTree(fEventTree); fEventTree->Branch("nlep",&nlep, "nlep/I"); fEventTree->Branch("nkplus",&nkplus, "nkplus/I"); //fEventTree->Branch("nkaon",&nkaon, "nkaon/I"); fEventTree->Branch("kplus_mom", &kplusmom, "kplus_mom/D"); // fEventTree->Branch("kaon_mom", &kaonmom, "kaon_mom/D"); // Add Event Scaling Information // This scale factor is used to get the predicted event rate for this sample given // the input flux. Use this when merging different output event ttrees fEventTree->Branch("EventScaleFactor", &fEventScaleFactor, "EventScaleFactor/D"); fEventScaleFactor = GetEventHistogram()->Integral("width") * 1E-38 / (fNEvents + 0.); // NOTES: // To get normalised predictions weight event event by 'EventScaleFactor' to get the // predicted event rate for that sample given the flux used. Then to get cross-sections // divide by the integrated flux from all samples. // e.g. To get the numu+numubar prediction, add the event rate predictions from both // samples together, then divide by the integral of the 'nuisance_flux' histograms in each // sample. // Every particle in the nuisance event is saved into the TTree. The list of particle // status codes are given in src/FitBase/FitParticle.h. The neutrino is usually the first // particle in the list. // If selecting final state kaons, select only kaons with state=2. /* enum particle_state{ kUndefinedState = 5, kInitialState = 0, kFSIState = 1, kFinalState = 2, kNuclearInitial = 3, kNuclearRemnant = 4 }; */ // The structure of the particle lists are a dimensional array for each particle mom, then a 1D array // for the PDG and state. Mode gives the true NEUT interaction channel code. /* tn->Branch("Mode", &fMode, "Mode/I"); tn->Branch("EventNo", &fEventNo, "EventNo/i"); tn->Branch("TotCrs", &fTotCrs, "TotCrs/D"); tn->Branch("TargetA", &fTargetA, "TargetA/I"); tn->Branch("TargetH", &fTargetH, "TargetH/I"); tn->Branch("Bound", &fBound, "Bound/O"); tn->Branch("InputWeight", &InputWeight, "InputWeight/D"); tn->Branch("NParticles", &fNParticles, "NParticles/I"); tn->Branch("ParticleState", fParticleState, "ParticleState[NParticles]/i"); tn->Branch("ParticlePDG", fParticlePDG, "ParticlePDG[NParticles]/I"); tn->Branch("ParticleMom", fParticleMom, "ParticleMom[NParticles][4]/D"); */ // Logging Flag fNCpi0Logging = FitPar::Config().GetParB("NCpi0Logging"); return; } //******************************************************************** void MCStudy_NCpi0PreSelection::FillEventVariables(FitEvent *event) { //******************************************************************** // Reset kplusmom = -999.9; // Save Some Extra Information nkplus = event->NumFSParticle(PhysConst::pdg_kplus); // Nmuons nlep = event->NumFSParticle(13) + event->NumFSParticle(-13); // Leading K+ Mom if (event->GetHMFSParticle(PhysConst::pdg_kplus)){ kplusmom = FitUtils::T(event->GetHMFSParticle(PhysConst::pdg_kplus)->fP)*1000.0; } // Fill XVar fXVar = kplusmom / 1.E3; // Fill If Signal if (isSignal(event)){ fEventTree->Fill(); if (fNCpi0Logging){ int nstrangemesons = event->NumParticle(321); int nstrangefsmesons = event->NumFSParticle(321); if (nstrangemesons > 0){ std::cout << "New Event ----------------------------" << std::endl; std::cout << "N S Mesons vs NFS S Mesons : " << nstrangemesons << " : " << nstrangefsmesons << std::endl; - event->PrintChris(); event->fNeutVect->Dump(); } } } return; }; //******************************************************************** void MCStudy_NCpi0PreSelection::Write(std::string drawOpt) { //******************************************************************** // Save the event ttree fEventTree->Write(); // Save Flux and Event Histograms too GetInput()->GetFluxHistogram()->Write("nuisance_fluxhist"); GetInput()->GetEventHistogram()->Write("nuisance_eventhist"); return; } //******************************************************************** /// Select only events with final state NCpi0s bool MCStudy_NCpi0PreSelection::isSignal(FitEvent *event) { //******************************************************************** // Apply a NCpi0 Pre-selection // Search for Strange Mesons (included full list from MC PDG) int npi0 = event->NumParticle(111); if (npi0 <= 0) return false; int nlep = (event->NumFSParticle(11) + event->NumFSParticle(13) + event->NumFSParticle(15) + event->NumFSParticle(-11) + event->NumFSParticle(-13) + event->NumFSParticle(-15)); if (nlep > 0) return false; // Do we want any other signal? return true; }; diff --git a/src/MINERvA/MINERvA_CCinc_XSec_2DEavq3_nu.cxx b/src/MINERvA/MINERvA_CCinc_XSec_2DEavq3_nu.cxx index e95e633..e9c9d47 100644 --- a/src/MINERvA/MINERvA_CCinc_XSec_2DEavq3_nu.cxx +++ b/src/MINERvA/MINERvA_CCinc_XSec_2DEavq3_nu.cxx @@ -1,153 +1,153 @@ // 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 "MINERvA_SignalDef.h" #include "MINERvA_CCinc_XSec_2DEavq3_nu.h" //******************************************************************** MINERvA_CCinc_XSec_2DEavq3_nu::MINERvA_CCinc_XSec_2DEavq3_nu(nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "MINERvA_CCinc_XSec_2DEavq3_nu sample. \n" \ "Target: CH \n" \ "Flux: MINERvA Medium Energy FHC numu \n" \ "Signal: CC-inclusive with theta < 20deg \n"; // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); fSettings.SetXTitle("q_{3} (GeV)"); fSettings.SetYTitle("E_{avail} (GeV)"); fSettings.SetZTitle("d^{2}#sigma/dq_{3}dE_{avail} (cm^{2}/GeV^{2})"); fSettings.SetAllowedTypes("FIX,FREE,SHAPE/FULL,DIAG/MASK", "FIX/FULL"); fSettings.SetEnuRange(2.0, 6.0); fSettings.DefineAllowedTargets("C,H"); // CCQELike plot information fSettings.SetTitle("MINERvA_CCinc_XSec_2DEavq3_nu"); fSettings.SetDataInput( FitPar::GetDataBase() + "/MINERvA/CCEavq3/data_2D.txt" ); fSettings.SetCovarInput( FitPar::GetDataBase() + "/MINERvA/CCEavq3/covar_2D.txt" ); fSettings.SetMapInput( FitPar::GetDataBase() + "/MINERvA/CCEavq3/map_2D.txt" ); fSettings.DefineAllowedSpecies("numu"); hadroncut = FitPar::Config().GetParB("MINERvA_CCinc_XSec_2DEavq3_nu_hadron_cut"); useq3true = FitPar::Config().GetParB("MINERvA_CCinc_XSec_2DEavq3_nu_useq3true"); splitMEC_PN_NN = FitPar::Config().GetParB("Modes_split_PN_NN"); FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon fScaleFactor = (GetEventHistogram()->Integral("width") * 1E-42 / (fNEvents + 0.)) / this->TotalIntegratedFlux(); // Plot Setup ------------------------------------------------------- Double_t binx[7] = {0.0, 0.2, 0.3, 0.4, 0.5, 0.6, 0.8}; Double_t biny[17] = {0.0, 0.02, 0.04, 0.06, 0.08, 0.10, 0.12, 0.14, 0.16, 0.20, 0.25, 0.30, 0.35, 0.40, 0.50, 0.60, 0.80}; CreateDataHistogram(7, binx, 17, biny); SetDataValuesFromTextFile( fSettings.GetDataInput() ); ScaleData(1E-42); SetMapValuesFromText( fSettings.GetMapInput() ); SetCholDecompFromTextFile( fSettings.GetCovarInput(), 67); ScaleCovar(1E-16); StatUtils::SetDataErrorFromCov(fDataHist, fFullCovar, fMapHist, 1E-38, false); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; //******************************************************************** void MINERvA_CCinc_XSec_2DEavq3_nu::FillEventVariables(FitEvent *event) { //******************************************************************** - // Seperate MEC + // Separate MEC if (splitMEC_PN_NN) { int npr = 0; int nne = 0; for (UInt_t j = 0; j < event->Npart(); j++) { if ((event->PartInfo(j))->fIsAlive) continue; if (event->PartInfo(j)->fPID == 2212) npr++; else if (event->PartInfo(j)->fPID == 2112) nne++; } if (event->Mode == 2 and npr == 1 and nne == 1) { event->Mode = 2; Mode = 2; } else if (event->Mode == 2 and npr == 0 and nne == 2) { event->Mode = 3; Mode = 3; } } // Set Defaults double Eav = -999.9; double q3 = -999.9; // If muon found get kinematics FitParticle* muon = event->GetHMFSParticle(13); FitParticle* neutrino = event->GetNeutrinoIn(); if (muon && neutrino) { // Set Q from Muon TLorentzVector q = neutrino->fP - muon->fP; double q0 = (q.E()) / 1.E3; //double q3_true = (q.Vect().Mag())/1.E3; double thmu = muon->fP.Vect().Angle(neutrino->fP.Vect()); double pmu = muon->fP.Vect().Mag() / 1.E3; double emu = muon->fP.E() / 1.E3; double mmu = muon->fP.Mag() / 1.E3; // Get Enu Rec double enu_rec = emu + q0; // Set Q2 QE double q2qe = 2 * enu_rec * (emu - pmu * cos(thmu)) - mmu * mmu; // Calc Q3 from Q2QE and EnuTree q3 = sqrt(q2qe + q0 * q0); // Get Eav too Eav = FitUtils::GetErecoil_MINERvA_LowRecoil(event) / 1.E3; } // Set Hist Variables fXVar = q3; fYVar = Eav; return; } //******************************************************************** bool MINERvA_CCinc_XSec_2DEavq3_nu::isSignal(FitEvent *event) { //******************************************************************** return SignalDef::isCCincLowRecoil_MINERvA(event, EnuMin, EnuMax); } diff --git a/src/MicroBooNE/MicroBooNE_CCInc_XSec_2DPcos_nu.cxx b/src/MicroBooNE/MicroBooNE_CCInc_XSec_2DPcos_nu.cxx index ed9fba3..1105ab2 100644 --- a/src/MicroBooNE/MicroBooNE_CCInc_XSec_2DPcos_nu.cxx +++ b/src/MicroBooNE/MicroBooNE_CCInc_XSec_2DPcos_nu.cxx @@ -1,268 +1,268 @@ // 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 "MicroBooNE_CCInc_XSec_2DPcos_nu.h" namespace { // Mapping of polybins to costheta slices int kDUMMY = std::numeric_limits::max(); static size_t const NRows = 9; static size_t const NRowBins[] = {5, 5, 5, 4, 4, 4, 5, 5, 5}; static int const PolyBinIDs[NRows][5] = {{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}, {11, 12, 13, 14, 15}, {16, 17, 18, 19, kDUMMY}, {20, 21, 22, 23, kDUMMY}, {24, 25, 26, 27, kDUMMY}, {28, 29, 30, 31, 32}, {33, 34, 35, 36, 37}, {38, 39, 40, 41, 42}}; // Bin edges static double const EdgesCt[] = {-1.00, -0.50, 0.00, 0.27, 0.45, 0.62, 0.76, 0.86, 0.94, 1.00}; static double const EdgesP[NRows][6] = { {0.00, 0.18, 0.30, 0.45, 0.77, 2.50}, {0.00, 0.18, 0.30, 0.45, 0.77, 2.50}, {0.00, 0.18, 0.30, 0.45, 0.77, 2.50}, - {0.00, 0.30, 0.45, 0.77, 2.50, kDUMMY}, - {0.00, 0.30, 0.45, 0.77, 2.50, kDUMMY}, - {0.00, 0.30, 0.45, 0.77, 2.50, kDUMMY}, + {0.00, 0.30, 0.45, 0.77, 2.50, (double)kDUMMY}, + {0.00, 0.30, 0.45, 0.77, 2.50, (double)kDUMMY}, + {0.00, 0.30, 0.45, 0.77, 2.50, (double)kDUMMY}, {0.00, 0.30, 0.45, 0.77, 1.28, 2.50}, {0.00, 0.30, 0.45, 0.77, 1.28, 2.50}, {0.00, 0.30, 0.45, 0.77, 1.28, 2.50}}; } // namespace //******************************************************************** MicroBooNE_CCInc_XSec_2DPcos_nu::MicroBooNE_CCInc_XSec_2DPcos_nu( nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "MicroBooNE_CCInc_XSec_2DPcos_nu sample. \n" "Target: Ar \n" "Flux: BNB FHC numu \n" "Signal: CC inclusive \n"; // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); fSettings.SetXTitle("P_{#mu}^{reco} (GeV)"); fSettings.SetYTitle("cos#theta_{#mu}^{reco}"); fSettings.SetZTitle( "d^{2}#sigma/dP_{#mu}^{reco}dcos#theta_{#mu}^{reco} (cm^{2}/GeV)"); fSettings.SetAllowedTypes("FULL,DIAG/FREE,SHAPE,FIX/SYSTCOV/STATCOV", "FIX/FULL"); fSettings.SetEnuRange(0.0, 10.0); fSettings.DefineAllowedTargets("Ar"); // Plot information fSettings.SetTitle("MicroBooNE_CCInc_XSec_2DPcos_nu"); fSettings.DefineAllowedSpecies("numu"); FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon fScaleFactor = ((GetEventHistogram()->Integral("width") / (fNEvents + 0.)) * 1E-38 / (TotalIntegratedFlux())); // Setup Histograms SetHistograms(); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; bool MicroBooNE_CCInc_XSec_2DPcos_nu::isSignal(FitEvent *event) { return SignalDef::isCCINC(event, 14, EnuMin, EnuMax); }; void MicroBooNE_CCInc_XSec_2DPcos_nu::FillEventVariables(FitEvent *event) { if (event->NumFSParticle(13) == 0) { return; } TLorentzVector Pnu = event->GetNeutrinoIn()->fP; TLorentzVector Pmu = event->GetHMFSParticle(13)->fP; double pmu = Pmu.Vect().Mag() / 1000; double CosThetaMu = cos(Pnu.Vect().Angle(Pmu.Vect())); fXVar = pmu; fYVar = CosThetaMu; return; }; void MicroBooNE_CCInc_XSec_2DPcos_nu::FillHistograms() { Measurement1D::FillHistograms(); if (Signal) { fMCHist_Fine2D->Fill(fXVar, fYVar, Weight); FillMCSlice(fXVar, fYVar, Weight); } } void MicroBooNE_CCInc_XSec_2DPcos_nu::ConvertEventRates() { for (size_t i = 0; i < fMCHist_Slices.size(); i++) { fMCHist_Slices[i]->GetSumw2(); } // Do standard conversion Measurement1D::ConvertEventRates(); // Apply MC truth -> reco smearing std::vector slices_true; for (size_t i = 0; i < fMCHist_Slices.size(); i++) { TH1D *h = (TH1D *)fMCHist_Slices[i]->Clone( TString(fMCHist_Slices[i]->GetName()) + "_true"); slices_true.push_back(h); } for (int ireco = 1; ireco < fMCHist->GetNbinsX() + 1; ireco++) { double total = 0; for (int itrue = 1; itrue < fMCHist->GetNbinsX() + 1; itrue++) { std::pair idx = fPolyBinMap[itrue]; TH1D *h = slices_true[idx.first]; total += h->GetBinContent(idx.second + 1) * h->GetBinWidth(idx.second + 1) * fSmearingMatrix->operator()(ireco - 1, itrue - 1); } std::pair idx = fPolyBinMap[ireco]; TH1D *h = fMCHist_Slices[idx.first]; h->SetBinContent(idx.second + 1, total / h->GetBinWidth(idx.second + 1)); } for (size_t i = 0; i < slices_true.size(); i++) { delete slices_true[i]; } // Scale MC slices also by their width in Y for (size_t i = 0; i < fMCHist_Slices.size(); i++) { float w = EdgesCt[i + 1] - EdgesCt[i]; fMCHist_Slices[i]->Scale(1.0 / w); } // Convert into 1D list fMCHist->Reset(); int bincount = 0; for (size_t i = 0; i < fDataHist_Slices.size(); i++) { for (int j = 0; j < fDataHist_Slices[i]->GetNbinsX(); j++) { fMCHist->SetBinContent(bincount + 1, fMCHist_Slices[i]->GetBinContent(j + 1)); fMCHist->SetBinError(bincount + 1, fMCHist_Slices[i]->GetBinError(j + 1)); bincount++; } } } void MicroBooNE_CCInc_XSec_2DPcos_nu::FillMCSlice(double x, double y, double w) { if (y >= -1.00 && y < -0.50) fMCHist_Slices[0]->Fill(x, w); else if (y >= -0.50 && y < 0.00) fMCHist_Slices[1]->Fill(x, w); else if (y >= 0.00 && y < 0.27) fMCHist_Slices[2]->Fill(x, w); else if (y >= 0.27 && y < 0.45) fMCHist_Slices[3]->Fill(x, w); else if (y >= 0.45 && y < 0.62) fMCHist_Slices[4]->Fill(x, w); else if (y >= 0.62 && y < 0.76) fMCHist_Slices[5]->Fill(x, w); else if (y >= 0.76 && y < 0.86) fMCHist_Slices[6]->Fill(x, w); else if (y >= 0.86 && y < 0.94) fMCHist_Slices[7]->Fill(x, w); else if (y >= 0.94 && y <= 1.00) fMCHist_Slices[8]->Fill(x, w); } void MicroBooNE_CCInc_XSec_2DPcos_nu::SetHistograms() { // Read in 1D Data Histograms fInputFile = new TFile((FitPar::GetDataBase() + "/MicroBooNE/CCinc/microboone_numu_cc_inclusive.root") .c_str()); // Read in 1D Data fDataHist = (TH1D *)fInputFile->Get("xsec_data"); fDataHist->SetName("MicroBooNE_CCInc_XSec_2DPcos_nu_DATA"); fDataHist->Scale(1e-38); fMCHist_Fine2D = new TH2D("MicroBooNE_CCInc_XSec_2DPcos_nu_Fine2D", "MicroBooNE_CCInc_XSec_2DPcos_nu_Fine2D", 400, 0.0, 2.5, 100, -1.0, 1.0); SetAutoProcessTH1(fMCHist_Fine2D); // Load covariance matrix TH2D *tempcov = (TH2D *)fInputFile->Get("covariance_matrix"); fFullCovar = new TMatrixDSym(fDataHist->GetNbinsX()); for (int i = 0; i < fDataHist->GetNbinsX(); i++) { for (int j = 0; j < fDataHist->GetNbinsX(); j++) { (*fFullCovar)(i, j) = tempcov->GetBinContent(i + 1, j + 1); } } fDecomp = StatUtils::GetDecomp(fFullCovar); // Load smearing matrix TH2D *tempsmear = (TH2D *)fInputFile->Get("smearing_matrix"); fSmearingMatrix = new TMatrixDSym(fDataHist->GetNbinsX()); for (int i = 0; i < fDataHist->GetNbinsX(); i++) { for (int j = 0; j < fDataHist->GetNbinsX(); j++) { (*fSmearingMatrix)(i, j) = tempsmear->GetBinContent(i + 1, j + 1); } } for (size_t i = 0; i < NRows; i++) { for (size_t j = 0; j < NRowBins[i]; j++) { int id = PolyBinIDs[i][j]; - fPolyBinMap[id] = {i, j}; + fPolyBinMap[id] = std::make_pair(i, j); } } // Split 1D data into cos(theta) slices for (size_t i = 0; i < NRows; i++) { TString name = Form("MicroBooNE_CCInc_XSec_2DPcos_nu_data_Slice%lu", i); TH1D *h = new TH1D(name, name, NRowBins[i], EdgesP[i]); h->Sumw2(); fDataHist_Slices.push_back(h); for (size_t j = 0; j < NRowBins[i]; j++) { int binid = PolyBinIDs[i][j]; h->SetBinContent(j + 1, fDataHist->GetBinContent(binid)); float err = sqrt((*fFullCovar)(binid - 1, binid - 1)) * 1e-38; h->SetBinError(j + 1, err); fDataHist->SetBinError(binid, err); } fMCHist_Slices.push_back((TH1D *)h->Clone()); name = Form("MicroBooNE_CCInc_XSec_2DPcos_nu_MC_Slice%lu", i); fMCHist_Slices[i]->SetNameTitle(name, name); fMCHist_Slices[i]->Reset(); SetAutoProcessTH1(fDataHist_Slices[i], kCMD_Write); SetAutoProcessTH1(fMCHist_Slices[i]); } } diff --git a/src/MiniBooNE/MiniBooNE_CC1pip_XSec_1DQ2_nu.cxx b/src/MiniBooNE/MiniBooNE_CC1pip_XSec_1DQ2_nu.cxx index b940df7..403e066 100644 --- a/src/MiniBooNE/MiniBooNE_CC1pip_XSec_1DQ2_nu.cxx +++ b/src/MiniBooNE/MiniBooNE_CC1pip_XSec_1DQ2_nu.cxx @@ -1,84 +1,84 @@ // 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_CC1pip_XSec_1DQ2_nu.h" //******************************************************************** MiniBooNE_CC1pip_XSec_1DQ2_nu::MiniBooNE_CC1pip_XSec_1DQ2_nu(nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "MiniBooNE_CC1pip_XSec_1DQ2_nu sample. \n" \ "Target: CH \n" \ "Flux: MiniBooNE Forward Horn Current nue + nuebar \n" \ "Signal: Any event with 1 muon, any nucleons, and no other FS particles \n"; // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); fSettings.SetXTitle("Q^{2}_{CC#pi} (GeV^{2})"); fSettings.SetYTitle("d#sigma/dQ_{CC#pi^{+}}^{2} (cm^{2}/MeV^{2}/CH_{2})"); fSettings.SetAllowedTypes("FIX,FREE,SHAPE/DIAG/NORM/MASK", "FIX/DIAG"); fSettings.SetEnuRange(0.0, 100.0); // No energy range given in v1r0 fSettings.DefineAllowedTargets("C,H"); // CCQELike plot information fSettings.SetTitle("MiniBooNE CC1pi"); fSettings.SetDataInput( FitPar::GetDataBase() + "MiniBooNE/CC1pip/ccpipXSec_Q2.txt" ); fSettings.DefineAllowedSpecies("numu"); FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon fScaleFactor = GetEventHistogram()->Integral("width")*double(1E-38)/double(fNEvents)*(14.08)/TotalIntegratedFlux("width")/1E6; // Added /1E6. comes from Q2 being in MeV^2, not GeV^2 I think... Or maybe the units in the paper are simply wrong; 1E-45 is very small! :D // Plot Setup ------------------------------------------------------- SetDataFromTextFile( fSettings.GetDataInput() ); SetCovarFromDiagonal(); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; //******************************************************************** void MiniBooNE_CC1pip_XSec_1DQ2_nu::FillEventVariables(FitEvent *event){ //******************************************************************** if (event->NumFSParticle(13) == 0) return; TLorentzVector Pnu = event->GetNeutrinoIn()->fP; TLorentzVector Pmu = event->GetHMFSParticle(13)->fP; // No W cut on MiniBooNE CC1pi+ - double q2 = -1*(Pnu-Pmu).Mag2(); + double q2 = -1*(Pnu-Pmu).Mag2()/1e6; fXVar = q2; return; }; //******************************************************************** bool MiniBooNE_CC1pip_XSec_1DQ2_nu::isSignal(FitEvent *event) { //******************************************************************** return SignalDef::isCC1pi(event, 14, 211, EnuMin, EnuMax); } diff --git a/src/MiniBooNE/MiniBooNE_NC1pi0_XSec_1Dcospi0_antinu.cxx b/src/MiniBooNE/MiniBooNE_NC1pi0_XSec_1Dcospi0_antinu.cxx index 48a3f35..12b3d03 100644 --- a/src/MiniBooNE/MiniBooNE_NC1pi0_XSec_1Dcospi0_antinu.cxx +++ b/src/MiniBooNE/MiniBooNE_NC1pi0_XSec_1Dcospi0_antinu.cxx @@ -1,103 +1,103 @@ // 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_NC1pi0_XSec_1Dcospi0_antinu.h" //******************************************************************** MiniBooNE_NC1pi0_XSec_1Dcospi0_antinu::MiniBooNE_NC1pi0_XSec_1Dcospi0_antinu(nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "MiniBooNE_NC1pi0_XSec_1Dcospi0_antinu sample. \n" \ "Target: CH \n" \ "Flux: MiniBooNE Forward Horn Current nue + nuebar \n" \ "Signal: Any event with 1 muon, any nucleons, and no other FS particles \n"; // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); fSettings.SetXTitle("cos#theta_{#pi^{0}}"); fSettings.SetYTitle("d#sigma/dcos#theta_{#pi^{0}} (cm^{2}/nucleon)"); fSettings.SetAllowedTypes("FIX,FREE,SHAPE/FULL,DIAG/NORM/MASK", "FIX/FULL"); fSettings.SetEnuRange(0.0, 5.0); fSettings.DefineAllowedTargets("C,H"); fSettings.SetTitle("MiniBooNE_NC1pi0_XSec_1Dcospi0_antinu"); - nunubar_mode = fSettings.Found("name", "combined"); + nunubar_mode = fSettings.Found("name", "rhc"); if (!nunubar_mode) { fSettings.SetDataInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/nubarcosthetapi0xsec_edit.txt" ); fSettings.SetCovarInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/nubarcosthetapi0xsecerrormatrix.txt" ); fSettings.DefineAllowedSpecies("numub"); } else { - fSettings.SetDataInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/combinedsignnumodecosthetapi0xsec_edit.txt"); - fSettings.SetCovarInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/combinedsignnumodecosthetapi0xsecerrormatrix.txt"); + fSettings.SetDataInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/combinedsignnubarmodecosthetapi0xsec_edit.txt"); + fSettings.SetCovarInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/combinedsignnubarmodecosthetapi0xsecerrormatrix.txt"); fSettings.DefineAllowedSpecies("numu,numub"); } FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon fScaleFactor = (GetEventHistogram()->Integral("width") * 1E-38) / double(fNEvents) / TotalIntegratedFlux("width"); // Plot Setup ------------------------------------------------------- SetDataFromTextFile( fSettings.GetDataInput() ); SetCovarFromTextFile( fSettings.GetCovarInput() ); ScaleCovar(1.E-5); StatUtils::SetDataErrorFromCov(fDataHist, fFullCovar, 1E-38); SetShapeCovar(); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; void MiniBooNE_NC1pi0_XSec_1Dcospi0_antinu::FillEventVariables(FitEvent *event) { // (CP) require pi0 in final state (this makes some assumptions about how the // generator treats the pi0 after it is produced in the nucleus. // MB required 2 photons to make a pion signal, so check for those later if (event->NumFSParticle(111) == 0 ) { return; } if (abs(event->NumFSParticle(13)) == 1 || abs(event->NumFSParticle(11)) == 1 || abs(event->NumFSParticle(15)) == 1 || abs(event->NumFSParticle(17)) == 1) return; TLorentzVector Pnu = event->GetNeutrinoIn()->fP; TLorentzVector Ppi0 = event->GetHMFSParticle(111)->fP; double CosPi0 = cos(FitUtils::th(Pnu, Ppi0)); fXVar = CosPi0; return; }; //******************************************************************** bool MiniBooNE_NC1pi0_XSec_1Dcospi0_antinu::isSignal(FitEvent *event) { //******************************************************************** if (nunubar_mode) { return (SignalDef::isNC1pi(event, 14, 111, EnuMin, EnuMax) || SignalDef::isNC1pi(event, -14, 111, EnuMin, EnuMax)); } else { return SignalDef::isNC1pi(event, -14, 111, EnuMin, EnuMax); } } diff --git a/src/MiniBooNE/MiniBooNE_NC1pi0_XSec_1Dcospi0_nu.cxx b/src/MiniBooNE/MiniBooNE_NC1pi0_XSec_1Dcospi0_nu.cxx index fcc28a0..ac1680d 100644 --- a/src/MiniBooNE/MiniBooNE_NC1pi0_XSec_1Dcospi0_nu.cxx +++ b/src/MiniBooNE/MiniBooNE_NC1pi0_XSec_1Dcospi0_nu.cxx @@ -1,105 +1,105 @@ // 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_NC1pi0_XSec_1Dcospi0_nu.h" //******************************************************************** MiniBooNE_NC1pi0_XSec_1Dcospi0_nu::MiniBooNE_NC1pi0_XSec_1Dcospi0_nu(nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "MiniBooNE_NC1pi0_XSec_1Dcospi0_nu sample. \n" \ "Target: CH \n" \ "Flux: MiniBooNE Forward Horn Current nue + nuebar \n" \ "Signal: Any event with 1 muon, any nucleons, and no other FS particles \n"; // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); fSettings.SetXTitle("cos#theta_{#pi^{0}}"); fSettings.SetYTitle("d#sigma/dcos#theta_{#pi^{0}} (cm^{2}/nucleon)"); fSettings.SetAllowedTypes("FIX,FREE,SHAPE/FULL,DIAG/NORM/MASK", "FIX/FULL"); fSettings.SetEnuRange(0.0, 5.0); fSettings.DefineAllowedTargets("C,H"); fSettings.SetTitle("MiniBooNE_NC1pi0_XSec_1Dcospi0_nu"); - nunubarmode = fSettings.Found("name", "combined"); + nunubarmode = fSettings.Found("name", "fhc"); if (!nunubarmode) { fSettings.SetDataInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/nucosthetapi0xsec_edit.txt" ); fSettings.SetCovarInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/nucosthetapi0xsecerrormatrix.txt" ); fSettings.DefineAllowedSpecies("numu"); } else { - fSettings.SetDataInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/combinedsignnubarmodecosthetapi0xsec_edit.txt"); - fSettings.SetCovarInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/combinedsignnubarmodecosthetapi0xsecerrormatrix.txt"); + fSettings.SetDataInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/combinedsignnumodecosthetapi0xsec_edit.txt"); + fSettings.SetCovarInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/combinedsignnumodecosthetapi0xsecerrormatrix.txt"); fSettings.DefineAllowedSpecies("numu,numub"); } FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon fScaleFactor = (GetEventHistogram()->Integral("width") * 1E-38) / double(fNEvents) / TotalIntegratedFlux("width"); // Plot Setup ------------------------------------------------------- SetDataFromTextFile( fSettings.GetDataInput() ); SetCovarFromTextFile( fSettings.GetCovarInput() ); ScaleCovar(1.E-5); StatUtils::SetDataErrorFromCov(fDataHist, fFullCovar, 1E-38); SetShapeCovar(); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; void MiniBooNE_NC1pi0_XSec_1Dcospi0_nu::FillEventVariables(FitEvent *event) { // (CP) require pi0 in final state (this makes some assumptions about how the // generator treats the pi0 after it is produced in the nucleus. // MB required 2 photons to make a pion signal, so check for those later if (event->NumFSParticle(111) == 0 ) { return; } if (abs(event->NumFSParticle(13)) == 1 || abs(event->NumFSParticle(11)) == 1 || abs(event->NumFSParticle(15)) == 1 || abs(event->NumFSParticle(17)) == 1) return; TLorentzVector Pnu = event->GetNeutrinoIn()->fP; TLorentzVector Ppi0 = event->GetHMFSParticle(111)->fP; double CosPi0 = cos(FitUtils::th(Pnu, Ppi0)); fXVar = CosPi0; return; }; //******************************************************************** bool MiniBooNE_NC1pi0_XSec_1Dcospi0_nu::isSignal(FitEvent *event) { //******************************************************************** if (nunubarmode){ return (SignalDef::isNC1pi(event, 14, 111, EnuMin, EnuMax) || SignalDef::isNC1pi(event, -14, 111, EnuMin, EnuMax)); } else { return SignalDef::isNC1pi(event, 14, 111, EnuMin, EnuMax); } } diff --git a/src/MiniBooNE/MiniBooNE_NC1pi0_XSec_1Dppi0_antinu.cxx b/src/MiniBooNE/MiniBooNE_NC1pi0_XSec_1Dppi0_antinu.cxx index 3f13396..fc376b6 100644 --- a/src/MiniBooNE/MiniBooNE_NC1pi0_XSec_1Dppi0_antinu.cxx +++ b/src/MiniBooNE/MiniBooNE_NC1pi0_XSec_1Dppi0_antinu.cxx @@ -1,104 +1,104 @@ // 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_NC1pi0_XSec_1Dppi0_antinu.h" //******************************************************************** MiniBooNE_NC1pi0_XSec_1Dppi0_antinu::MiniBooNE_NC1pi0_XSec_1Dppi0_antinu(nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "MiniBooNE_NC1pi0_XSec_1Dppi0_antinu sample. \n" \ "Target: CH \n" \ "Flux: MiniBooNE Forward Horn Current nue + nuebar \n" \ "Signal: Any event with 1 muon, any nucleons, and no other FS particles \n"; // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); fSettings.SetXTitle("p_{#pi^{0}} (GeV/c)"); fSettings.SetYTitle("d#sigma/dp_{#pi^{0}} (cm^{2}/(GeV/c)/nucleon)"); fSettings.SetAllowedTypes("FIX,FREE,SHAPE/FULL,DIAG/NORM/MASK", "FIX/FULL"); fSettings.SetEnuRange(0.0, 5.0); fSettings.DefineAllowedTargets("C,H"); fSettings.SetTitle("MiniBooNE_NC1pi0_XSec_1Dppi0_antinu"); - nunubarmode = fSettings.Found("name", "combined"); + nunubarmode = fSettings.Found("name", "rhc"); if (!nunubarmode) { fSettings.SetDataInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/nubarppi0xsec_edit.txt" ); fSettings.SetCovarInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/nubarppi0xsecerrormatrix.txt" ); fSettings.DefineAllowedSpecies("numu"); } else { - fSettings.SetDataInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/combinedsignnumodeppi0xsec_edit.txt"); - fSettings.SetCovarInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/combinedsignnumodeppi0xsecerrormatrix.txt"); + fSettings.SetDataInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/combinedsignnubarmodeppi0xsec_edit.txt"); + fSettings.SetCovarInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/combinedsignnubarmodeppi0xsecerrormatrix.txt"); fSettings.DefineAllowedSpecies("numu,numub"); } FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon fScaleFactor = (GetEventHistogram()->Integral("width") * 1E-38) / double(fNEvents) / TotalIntegratedFlux("width"); // Plot Setup ------------------------------------------------------- SetDataFromTextFile( fSettings.GetDataInput() ); SetCovarFromTextFile( fSettings.GetCovarInput() ); ScaleCovar(1.E-5); StatUtils::SetDataErrorFromCov(fDataHist, fFullCovar, 1E-38); SetShapeCovar(); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; void MiniBooNE_NC1pi0_XSec_1Dppi0_antinu::FillEventVariables(FitEvent *event) { // (CP) require pi0 in final state (this makes some assumptions about how the // generator treats the pi0 after it is produced in the nucleus. // MB required 2 photons to make a pion signal, so check for those later if (event->NumFSParticle(111) == 0) { return; } if (abs(event->NumFSParticle(13)) == 1 || abs(event->NumFSParticle(11)) == 1 || abs(event->NumFSParticle(15)) == 1 || abs(event->NumFSParticle(17)) == 1) return; TLorentzVector Ppi0 = event->GetHMFSParticle(111)->fP; double p_pi0 = FitUtils::p(Ppi0); fXVar = p_pi0; return; }; //******************************************************************** bool MiniBooNE_NC1pi0_XSec_1Dppi0_antinu::isSignal(FitEvent *event) { //******************************************************************** if (nunubarmode){ return (SignalDef::isNC1pi(event, -14, 111, EnuMin, EnuMax) || SignalDef::isNC1pi(event, 14, 111, EnuMin, EnuMax) ); } else { return SignalDef::isNC1pi(event, -14, 111, EnuMin, EnuMax); } } diff --git a/src/MiniBooNE/MiniBooNE_NC1pi0_XSec_1Dppi0_nu.cxx b/src/MiniBooNE/MiniBooNE_NC1pi0_XSec_1Dppi0_nu.cxx index ea0fea1..85b8a7b 100644 --- a/src/MiniBooNE/MiniBooNE_NC1pi0_XSec_1Dppi0_nu.cxx +++ b/src/MiniBooNE/MiniBooNE_NC1pi0_XSec_1Dppi0_nu.cxx @@ -1,104 +1,104 @@ // 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_NC1pi0_XSec_1Dppi0_nu.h" //******************************************************************** MiniBooNE_NC1pi0_XSec_1Dppi0_nu::MiniBooNE_NC1pi0_XSec_1Dppi0_nu(nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "MiniBooNE_NC1pi0_XSec_1Dppi0_nu sample. \n" \ "Target: CH \n" \ "Flux: MiniBooNE Forward Horn Current nue + nuebar \n" \ "Signal: Any event with 1 muon, any nucleons, and no other FS particles \n"; // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); fSettings.SetXTitle("p_{#pi^{0}} (GeV/c)"); fSettings.SetYTitle("d#sigma/dp_{#pi^{0}} (cm^{2}/(GeV/c)/nucleon)"); fSettings.SetAllowedTypes("FIX,FREE,SHAPE/FULL,DIAG/NORM/MASK", "FIX/FULL"); fSettings.SetEnuRange(0.0, 5.0); fSettings.DefineAllowedTargets("C,H"); fSettings.SetTitle("MiniBooNE_NC1pi0_XSec_1Dppi0_nu"); - nunubar_mode_nu = fSettings.Found("name", "combined"); + nunubar_mode_nu = fSettings.Found("name", "fhc"); if (!nunubar_mode_nu) { fSettings.SetDataInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/nuppi0xsec_edit.txt" ); fSettings.SetCovarInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/nuppi0xsecerrormatrix.txt" ); fSettings.DefineAllowedSpecies("numu"); } else { - fSettings.SetDataInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/combinedsignnubarmodeppi0xsec_edit.txt"); - fSettings.SetCovarInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/combinedsignnubarmodeppi0xsecerrormatrix.txt"); + fSettings.SetDataInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/combinedsignnumodeppi0xsec_edit.txt"); + fSettings.SetCovarInput( FitPar::GetDataBase() + "MiniBooNE/NC1pi0/combinedsignnumodeppi0xsecerrormatrix.txt"); fSettings.DefineAllowedSpecies("numu,numub"); } FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon fScaleFactor = (GetEventHistogram()->Integral("width") * 1E-38) / double(fNEvents) / TotalIntegratedFlux("width"); // Plot Setup ------------------------------------------------------- SetDataFromTextFile( fSettings.GetDataInput() ); SetCovarFromTextFile( fSettings.GetCovarInput() ); ScaleCovar(1.E-5); StatUtils::SetDataErrorFromCov(fDataHist, fFullCovar, 1E-38); SetShapeCovar(); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; void MiniBooNE_NC1pi0_XSec_1Dppi0_nu::FillEventVariables(FitEvent *event) { // (CP) require pi0 in final state (this makes some assumptions about how the // generator treats the pi0 after it is produced in the nucleus. // MB required 2 photons to make a pion signal, so check for those later if (event->NumFSParticle(111) == 0) { return; } if (abs(event->NumFSParticle(13)) == 1 || abs(event->NumFSParticle(11)) == 1 || abs(event->NumFSParticle(15)) == 1 || abs(event->NumFSParticle(17)) == 1) return; TLorentzVector Ppi0 = event->GetHMFSParticle(111)->fP; double p_pi0 = FitUtils::p(Ppi0); fXVar = p_pi0; return; }; //******************************************************************** bool MiniBooNE_NC1pi0_XSec_1Dppi0_nu::isSignal(FitEvent *event) { //******************************************************************** if (nunubar_mode_nu){ return (SignalDef::isNC1pi(event, 14, 111, EnuMin, EnuMax) || SignalDef::isNC1pi(event, -14, 111, EnuMin, EnuMax)); } else { return SignalDef::isNC1pi(event, 14, 111, EnuMin, EnuMax); } } diff --git a/src/MiniBooNE/MiniBooNE_NCEL_XSec_Treco_nu.cxx b/src/MiniBooNE/MiniBooNE_NCEL_XSec_Treco_nu.cxx index 8da8ed0..37d38bd 100644 --- a/src/MiniBooNE/MiniBooNE_NCEL_XSec_Treco_nu.cxx +++ b/src/MiniBooNE/MiniBooNE_NCEL_XSec_Treco_nu.cxx @@ -1,295 +1,293 @@ // 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_NCEL_XSec_Treco_nu.h" #include "TLorentzVector.h" //******************************************************************** MiniBooNE_NCEL_XSec_Treco_nu::MiniBooNE_NCEL_XSec_Treco_nu(nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "MiniBooNE_NCEL_XSec_Treco_nu sample. \n" "Target: CH \n" "Flux: MiniBooNE Numu Flux \n" "Signal: Any event with True NCEL modes \n"; // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); fSettings.SetXTitle("T_{reco} (MeV)"); fSettings.SetYTitle("Events/(12 MeV)"); fSettings.SetAllowedTypes("FIX,FREE,SHAPE/FULL,DIAG/NORM/MASK", "FIX/FULL,DIAG"); fSettings.DefineAllowedTargets("C,H"); fSettings.DefineAllowedSpecies("numu"); fSettings.SetEnuRange(0.0, 10.0); double arr_treco[52] = { 40.0, 52.0, 63.9, 75.9, 87.8, 99.8, 111.8, 123.7, 135.7, 147.6, 159.6, 171.6, 183.5, 195.5, 207.5, 219.4, 231.4, 243.3, 255.3, 267.3, 279.2, 291.2, 303.1, 315.1, 327.1, 339.0, 351.0, 362.9, 374.9, 386.9, 398.8, 410.8, 422.7, 434.7, 446.7, 458.6, 470.6, 482.5, 494.5, 506.5, 518.4, 530.4, 542.4, 554.3, 566.3, 578.2, 590.2, 602.2, 614.1, 626.1, 638.0, 650.0}; SetDataValues(FitPar::GetDataBase() + "/MiniBooNE/ncqe/input_data.txt", arr_treco); SetCovarMatrix(FitPar::GetDataBase() + "/MiniBooNE/ncqe/ErrorMatrix.tab", 51); SetResponseMatrix(FitPar::GetDataBase() + "/MiniBooNE/ncqe/response_mat.txt", 51, arr_treco); SetFluxHistogram(FitPar::GetDataBase() + "/MiniBooNE/ncqe/flux.txt"); FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // The scale factor is quite complicated because MB didn't divide by number of // targets. nMolMB is the number of CH_2 molecules in the MB FV (610.6 cm // radius sphere) and 0.845 is the published density of the mineral oil. // UPDATE: nMolMB is the number of CH_2 molecules in the MB FV (500 cm radius // sphere) and 0.845 is the published density of the mineral oil. UPDATE // UPDATE: They didn't account for fiducial cut, so neither do we. double nMolMB = 6.023E+23 * 0.845 * 4.0 * M_PI * 610.6 * 610.6 * 610.6 / 3.0; double POT = 6.46e20; // Need to update scalefactor to reflect actual flux used fScaleFactor = (this->newFluxHist->Integral("") * POT * (GetEventHistogram()->Integral("width")) * 1E-38 * 14.08 / (fNEvents + 0.)) * nMolMB; fScaleFactor /= GetFluxHistogram()->Integral("width"); // Final setup --------------------------------------------------- FinaliseMeasurement(); // Usually the MCFine histogram is a finer binned version of MC Hist. // In this case we need to use it to save the true distribution before // smearing. if (fMCFine) delete fMCFine; fMCFine = new TH1D((this->fName + "_Ttrue").c_str(), (this->fName + this->fPlotTitles).c_str(), 50, 0, 900); }; void MiniBooNE_NCEL_XSec_Treco_nu::Write(std::string arg) { newFluxHist->Write("MB_NCEL_newFlux"); response_mat->Write("MB_NCEL_response matrix"); Measurement1D::Write(arg); return; } void MiniBooNE_NCEL_XSec_Treco_nu::FillEventVariables(FitEvent *event) { double t_raw = 0.0; // Loop and add all Tnucleon for (UInt_t i = 0; i < event->Npart(); i++) { if (event->PartInfo(i)->Status() != kFinalState) continue; int pdg = event->PartInfo(i)->fPID; if (pdg == 2212 || pdg == 2112) { t_raw += FitUtils::T(event->PartInfo(i)->fP) * 1.E3; } } fXVar = t_raw; } void MiniBooNE_NCEL_XSec_Treco_nu::ScaleEvents() { // Now convert Ttrue to Treco... for (int treco = 0; treco < 51; ++treco) { double total = 0.; for (int ttrue = 0; ttrue < 50; ++ttrue) total += fMCFine->GetBinContent(ttrue + 1) * response_mat->GetBinContent(ttrue + 1, treco + 1); fMCHist->SetBinContent(treco + 1, total); } // Scale this->fMCHist->Scale(this->fScaleFactor, "width"); this->fMCFine->Scale(this->fScaleFactor, "width"); PlotUtils::ScaleNeutModeArray((TH1 **)fMCHist_PDG, fScaleFactor, "width"); // Add in the backgrounds... for (int treco = 0; treco < 51; ++treco) { double total = this->fMCHist->GetBinContent(treco + 1) + this->BKGD_other->GetBinContent(treco + 1) + this->BKGD_irrid->GetBinContent(treco + 1); this->fMCHist->SetBinContent(treco + 1, total); } } bool MiniBooNE_NCEL_XSec_Treco_nu::isSignal(FitEvent *event) { // Should put in MB SignalDef eventually if (event->Mode != 51 && event->Mode != 52) return false; // Numu or nue if (event->PDGnu() != 14 && event->PDGnu() != 12) return false; // Enu if (event->Enu() < EnuMin * 1000.0 || event->Enu() > EnuMax * 1000.0) return false; return true; }; void MiniBooNE_NCEL_XSec_Treco_nu::SetFluxHistogram(std::string dataFile) { this->newFluxHist = PlotUtils::GetTH1DFromFile( dataFile.c_str(), (this->fName + "Real Flux Hist"), "idgaf"); - - this->newFluxHist->Print(); return; } // Read in the covariance matrix from the file specified in the constructor void MiniBooNE_NCEL_XSec_Treco_nu::SetCovarMatrix(std::string covarFile, int dim) { // Use Utils // // Make a counter to track the line number int row = 0; std::string line; std::ifstream covar(covarFile.c_str(), std::ifstream::in); this->covar = new TMatrixDSym(dim); if (covar.is_open()) NUIS_LOG(DEB, "Reading covariance matrix from file: " << covarFile); while (std::getline(covar >> std::ws, line, '\n')) { std::istringstream stream(line); double entry; int column = 0; // Loop over entries and insert them into matrix // Multiply by the errors to get the covariance, rather than the correlation // matrix while (stream >> entry) { (*this->covar)(row, column) = entry; if (row == column) this->fDataHist->SetBinError(row + 1, sqrt(entry)); column++; } row++; } // // Robust matrix inversion method TDecompSVD LU = TDecompSVD(*this->covar); this->covar = new TMatrixDSym(dim, LU.Invert().GetMatrixArray(), ""); return; }; // Override the usual function in the base class because this is more // complicated for the NCEL sample... void MiniBooNE_NCEL_XSec_Treco_nu::SetDataValues(std::string inputFile, double *arr_treco) { std::string line; std::ifstream input(inputFile.c_str(), std::ifstream::in); if (input.is_open()) { NUIS_LOG(DEB, "Reading data from file: " << inputFile); } this->fDataHist = new TH1D((this->fName + "_data").c_str(), (this->fName + this->fPlotTitles).c_str(), 51, arr_treco); this->BKGD_other = new TH1D((this->fName + "_BKGD_other").c_str(), (this->fName + this->fPlotTitles).c_str(), 51, arr_treco); this->BKGD_irrid = new TH1D((this->fName + "_BKGD_irrid").c_str(), (this->fName + this->fPlotTitles).c_str(), 51, arr_treco); // To get the nDOF correct... this->fNDataPointsX = 52; double entry = 0; int xBin = 0; // First line is the MB data std::getline(input >> std::ws, line, '\n'); std::istringstream stream1(line); while (stream1 >> entry) { this->fDataHist->SetBinContent(xBin + 1, entry); xBin++; } // Second line is "other" backgrounds std::getline(input >> std::ws, line, '\n'); std::istringstream stream2(line); entry = 0; xBin = 0; while (stream2 >> entry) { this->BKGD_other->SetBinContent(xBin + 1, entry); xBin++; } // Third line is the irreducible background std::getline(input >> std::ws, line, '\n'); std::istringstream stream3(line); entry = 0; xBin = 0; while (stream3 >> entry) { this->BKGD_irrid->SetBinContent(xBin + 1, entry); xBin++; } }; // Read in the response matrix -- thus far, a response matrix is unique to the // NCEL sample void MiniBooNE_NCEL_XSec_Treco_nu::SetResponseMatrix(std::string responseFile, int dim, double *arr_treco) { // Make a counter to track the line number int xBin = 0; std::string line; std::ifstream response(responseFile.c_str(), std::ifstream::in); // Response matrix: x axis is Ttrue, y axis is Treco this->response_mat = new TH2D((this->fName + "_RESPONSE_MATRIX").c_str(), (this->fName + this->fPlotTitles).c_str(), 50, 0, 900, 51, arr_treco); if (response.is_open()) { NUIS_LOG(DEB, "Reading in the response matrix from file: " << responseFile); } while (std::getline(response, line, '\n')) { std::istringstream stream(line); double entry; int yBin = 0; // Loop over entries and insert them into matrix // Multiply by the errors to get the covariance, rather than the correlation // matrix while (stream >> entry) { this->response_mat->SetBinContent(xBin + 1, yBin + 1, entry); yBin++; } xBin++; } }; diff --git a/src/Reweight/NEUTWeightEngine.cxx b/src/Reweight/NEUTWeightEngine.cxx index 3c7942d..73b0b4d 100644 --- a/src/Reweight/NEUTWeightEngine.cxx +++ b/src/Reweight/NEUTWeightEngine.cxx @@ -1,195 +1,196 @@ #include "NEUTWeightEngine.h" NEUTWeightEngine::NEUTWeightEngine(std::string name) { #if defined(__NEUT_ENABLED__) and !defined(__NO_REWEIGHT__) // For newer NEUT we need to set up our defaults #if __NEUT_VERSION__ >= 541 neut::CommonBlockIFace::Initialize(std::string(std::getenv("NUISANCE"))+"/data/neut/neut_minimal_6t.card"); #endif // Setup the NEUT Reweight engien fCalcName = name; NUIS_LOG(FIT, "Setting up NEUT RW : " << fCalcName); // Create RW Engine suppressing cout StopTalking(); fNeutRW = new neut::rew::NReWeight(); TDirectory *olddir = gDirectory; // get list of vetoed calc engines (just for debug really) std::string rw_engine_list = FitPar::Config().GetParS("FitWeight_fNeutRW_veto"); bool xsec_ccqe = rw_engine_list.find("xsec_ccqe") == std::string::npos; bool xsec_res = rw_engine_list.find("xsec_res") == std::string::npos; - bool xsec_ccres = rw_engine_list.find("xsec_ccres") == std::string::npos; - bool xsec_coh = rw_engine_list.find("xsec_coh") == std::string::npos; - bool xsec_dis = rw_engine_list.find("xsec_dis") == std::string::npos; - bool xsec_ncel = rw_engine_list.find("xsec_ncel") == std::string::npos; - bool xsec_nc = rw_engine_list.find("xsec_nc") == std::string::npos; - bool xsec_ncres = rw_engine_list.find("xsec_ncres") == std::string::npos; - bool nucl_casc = rw_engine_list.find("nucl_casc") == std::string::npos; - bool nucl_piless = rw_engine_list.find("nucl_piless") == std::string::npos; // Activate each calc engine if (xsec_ccqe) fNeutRW->AdoptWghtCalc("xsec_ccqe", new neut::rew::NReWeightNuXSecCCQE); if (xsec_res) fNeutRW->AdoptWghtCalc("xsec_res", new neut::rew::NReWeightNuXSecRES); // Dials removed in NEUT 5.4.1 #if __NEUT_VERSION__ < 541 + bool xsec_ccres = rw_engine_list.find("xsec_ccres") == std::string::npos; + bool xsec_coh = rw_engine_list.find("xsec_coh") == std::string::npos; + bool xsec_dis = rw_engine_list.find("xsec_dis") == std::string::npos; + bool xsec_ncel = rw_engine_list.find("xsec_ncel") == std::string::npos; + bool xsec_nc = rw_engine_list.find("xsec_nc") == std::string::npos; + bool xsec_ncres = rw_engine_list.find("xsec_ncres") == std::string::npos; + bool nucl_casc = rw_engine_list.find("nucl_casc") == std::string::npos; + bool nucl_piless = rw_engine_list.find("nucl_piless") == std::string::npos; + if (nucl_casc) fNeutRW->AdoptWghtCalc("nucl_casc", new neut::rew::NReWeightCasc); if (xsec_coh) fNeutRW->AdoptWghtCalc("xsec_coh", new neut::rew::NReWeightNuXSecCOH); if (xsec_nc) fNeutRW->AdoptWghtCalc("xsec_nc", new neut::rew::NReWeightNuXSecNC); if (nucl_piless) fNeutRW->AdoptWghtCalc("nucl_piless", new neut::rew::NReWeightNuclPiless); if (xsec_ncres) fNeutRW->AdoptWghtCalc("xsec_ncres", new neut::rew::NReWeightNuXSecNCRES); if (xsec_ccres) fNeutRW->AdoptWghtCalc("xsec_ccres", new neut::rew::NReWeightNuXSecCCRES); if (xsec_ncel) fNeutRW->AdoptWghtCalc("xsec_ncel", new neut::rew::NReWeightNuXSecNCEL); if (xsec_dis) fNeutRW->AdoptWghtCalc("xsec_dis", new neut::rew::NReWeightNuXSecDIS); #endif fNeutRW->Reconfigure(); olddir->cd(); // Set Abs Twk Config fIsAbsTwk = (FitPar::Config().GetParB("setabstwk")); // allow cout again StartTalking(); #else NUIS_ABORT("NEUT RW NOT ENABLED!"); #endif }; void NEUTWeightEngine::IncludeDial(std::string name, double startval) { #if defined(__NEUT_ENABLED__) and !defined(__NO_REWEIGHT__) // Get First enum int nuisenum = Reweight::ConvDial(name, kNEUT); // Setup Maps fEnumIndex[nuisenum]; // = std::vector(0); fNameIndex[name]; // = std::vector(0); // Split by commas std::vector allnames = GeneralUtils::ParseToStr(name, ","); for (uint i = 0; i < allnames.size(); i++) { std::string singlename = allnames[i]; // Get Syst #if __NEUT_VERSION__ < 541 neut::rew::NSyst_t gensyst = NSyst::FromString(singlename); #else neut::rew::NSyst_t gensyst = neut::rew::NSyst::FromString(singlename); #endif // Fill Maps int index = fValues.size(); fValues.push_back(0.0); fNEUTSysts.push_back(gensyst); // Initialize dial NUIS_LOG(FIT, "Registering " << singlename << " dial."); fNeutRW->Systematics().Init(fNEUTSysts[index]); // If Absolute if (fIsAbsTwk) { #if __NEUT_VERSION__ < 541 NSystUncertainty::Instance()->SetUncertainty(fNEUTSysts[index], 1.0, 1.0); #else neut::rew::NSystUncertainty::Instance()->SetUncertainty(fNEUTSysts[index], 1.0, 1.0); #endif } // Setup index fEnumIndex[nuisenum].push_back(index); fNameIndex[name].push_back(index); } // Set Value if given if (startval != _UNDEF_DIAL_VALUE_) { SetDialValue(nuisenum, startval); } #endif } void NEUTWeightEngine::SetDialValue(int nuisenum, double val) { #if defined(__NEUT_ENABLED__) and !defined(__NO_REWEIGHT__) std::vector indices = fEnumIndex[nuisenum]; for (uint i = 0; i < indices.size(); i++) { fValues[indices[i]] = val; NUIS_LOG(FIT, "Setting Dial Value for " << nuisenum << " " << i << " " << indices[i] << " " << fValues[indices[i]] << " Enum: " << fNEUTSysts[indices[i]]); fNeutRW->Systematics().Set(fNEUTSysts[indices[i]], val); } #endif } void NEUTWeightEngine::SetDialValue(std::string name, double val) { #if defined(__NEUT_ENABLED__) and !defined(__NO_REWEIGHT__) std::vector indices = fNameIndex[name]; for (uint i = 0; i < indices.size(); i++) { fValues[indices[i]] = val; NUIS_LOG(FIT, "Setting Dial Value for " << name << " = " << i << " " << indices[i] << " " << fValues[indices[i]] << " Enum: " << fNEUTSysts[indices[i]]); fNeutRW->Systematics().Set(fNEUTSysts[indices[i]], val); } #endif } void NEUTWeightEngine::Reconfigure(bool silent) { #if defined(__NEUT_ENABLED__) and !defined(__NO_REWEIGHT__) // Hush now... if (silent) StopTalking(); // Reconf fNeutRW->Reconfigure(); // if (LOG_LEVEL(DEB)){ fNeutRW->Print(); // } // Shout again if (silent) StartTalking(); #endif } double NEUTWeightEngine::CalcWeight(BaseFitEvt *evt) { double rw_weight = 1.0; #if defined(__NEUT_ENABLED__) and !defined(__NO_REWEIGHT__) // Skip Non NEUT if (evt->fType != kNEUT) return 1.0; // Hush now StopTalking(); // Fill NEUT Common blocks NEUTUtils::FillNeutCommons(evt->fNeutVect); // Call Weight calculation rw_weight = fNeutRW->CalcWeight(); // Speak Now StartTalking(); #endif // Return rw_weight return rw_weight; } diff --git a/src/Routines/ComparisonRoutines.cxx b/src/Routines/ComparisonRoutines.cxx index a651d24..f91778a 100755 --- a/src/Routines/ComparisonRoutines.cxx +++ b/src/Routines/ComparisonRoutines.cxx @@ -1,637 +1,637 @@ // 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 "ComparisonRoutines.h" /* Constructor/Destructor */ //************************ void ComparisonRoutines::Init() { //************************ fOutputFile = ""; fOutputRootFile = NULL; fStrategy = "Compare"; fRoutines.clear(); fCardFile = ""; fFakeDataInput = ""; fSampleFCN = NULL; fAllowedRoutines = ("Compare"); }; //************************************* ComparisonRoutines::~ComparisonRoutines() { //************************************* delete fOutputRootFile; }; /* Input Functions */ //************************************* ComparisonRoutines::ComparisonRoutines(int argc, char *argv[]) { //************************************* // Initialise Defaults Init(); nuisconfig configuration = Config::Get(); // Default containers std::string cardfile = ""; std::string maxevents = "-1"; std::string skipevents = "0"; int errorcount = 0; int verbocount = 0; std::vector xmlcmds; std::vector configargs; // Make easier to handle arguments. std::vector args = GeneralUtils::LoadCharToVectStr(argc, argv); ParserUtils::ParseArgument(args, "-c", fCardFile, true); ParserUtils::ParseArgument(args, "-o", fOutputFile, false, false); ParserUtils::ParseArgument(args, "-n", maxevents, false, false); ParserUtils::ParseArgument(args, "-f", fStrategy, false, false); ParserUtils::ParseArgument(args, "-d", fFakeDataInput, false, false); ParserUtils::ParseArgument(args, "-i", xmlcmds); ParserUtils::ParseArgument(args, "-q", configargs); ParserUtils::ParseArgument(args, "-s", skipevents); ParserUtils::ParseCounter(args, "e", errorcount); ParserUtils::ParseCounter(args, "v", verbocount); ParserUtils::CheckBadArguments(args); // Add extra defaults if none given if (fCardFile.empty() and xmlcmds.empty()) { NUIS_ABORT("No input supplied!"); } if (fOutputFile.empty() and !fCardFile.empty()) { fOutputFile = fCardFile + ".root"; NUIS_ERR(WRN, "No output supplied so saving it to: " << fOutputFile); } else if (fOutputFile.empty()) { NUIS_ABORT("No output file or cardfile supplied!"); } // Configuration Setup ============================= // Check no comp key is available nuiskey fCompKey; if (Config::Get().GetNodes("nuiscomp").empty()) { fCompKey = Config::Get().CreateNode("nuiscomp"); } else { fCompKey = Config::Get().GetNodes("nuiscomp")[0]; } if (!fCardFile.empty()) fCompKey.Set("cardfile", fCardFile); if (!fOutputFile.empty()) fCompKey.Set("outputfile", fOutputFile); if (!fStrategy.empty()) fCompKey.Set("strategy", fStrategy); // Load XML Cardfile configuration.LoadSettings(fCompKey.GetS("cardfile"), ""); // Add Config Args for (size_t i = 0; i < configargs.size(); i++) { configuration.OverrideConfig(configargs[i]); } if (maxevents.compare("-1")) { configuration.OverrideConfig("MAXEVENTS=" + maxevents); } configuration.OverrideConfig("NSKIPEVENTS=" + skipevents); // Finish configuration XML configuration.FinaliseSettings(fCompKey.GetS("outputfile") + ".xml"); // Add Error Verbo Lines verbocount += Config::GetParI("VERBOSITY"); errorcount += Config::GetParI("ERROR"); bool trace = Config::GetParB("TRACE"); std::cout << "[ NUISANCE ]: Setting VERBOSITY=" << verbocount << std::endl; std::cout << "[ NUISANCE ]: Setting ERROR=" << errorcount << std::endl; SETVERBOSITY(verbocount); SETTRACE(trace); // Comparison Setup ======================================== // Proper Setup fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE"); SetupComparisonsFromXML(); SetupRWEngine(); SetupFCN(); return; }; //************************************* void ComparisonRoutines::SetupComparisonsFromXML() { //************************************* NUIS_LOG(FIT, "Setting up nuiscomp"); // Setup Parameters ------------------------------------------ std::vector parkeys = Config::QueryKeys("parameter"); if (!parkeys.empty()) { NUIS_LOG(FIT, "Number of parameters : " << parkeys.size()); } for (size_t i = 0; i < parkeys.size(); i++) { nuiskey key = parkeys.at(i); // Check for type,name,nom if (!key.Has("type")) { NUIS_ERR(FTL, "No type given for parameter " << i); NUIS_ABORT("type='PARAMETER_TYPE'"); } else if (!key.Has("name")) { NUIS_ERR(FTL, "No name given for parameter " << i); NUIS_ABORT("name='SAMPLE_NAME'"); } else if (!key.Has("nominal")) { NUIS_ERR(FTL, "No nominal given for parameter " << i); NUIS_ABORT("nominal='NOMINAL_VALUE'"); } // Get Inputs std::string partype = key.GetS("type"); std::string parname = key.GetS("name"); double parnom = key.GetD("nominal"); double parlow = parnom - 1; double parhigh = parnom + 1; double parstep = 1; // override if state not given if (!key.Has("state")) { key.SetS("state", "FIX"); } std::string parstate = key.GetS("state"); // Check for incomplete limtis int limdef = ((int)key.Has("low") + (int)key.Has("high") + (int)key.Has("step")); if (limdef > 0 and limdef < 3) { NUIS_ERR(FTL, "Incomplete limit set given for parameter : " << parname); NUIS_ABORT( "Requires: low='LOWER_LIMIT' high='UPPER_LIMIT' step='STEP_SIZE' "); } // Extra limits if (key.Has("low")) { parlow = key.GetD("low"); parhigh = key.GetD("high"); parstep = key.GetD("step"); NUIS_LOG(FIT, "Read " << partype << " : " << parname << " = " << parnom << " : " << parlow << " < p < " << parhigh << " : " << parstate); } else { NUIS_LOG(FIT, "Read " << partype << " : " << parname << " = " << parnom << " : " << parstate); } bool ismirr = false; if (key.Has("mirror_point")) { ismirr = true; mirror_param mir; mir.mirror_value = key.GetD("mirror_point"); mir.mirror_above = key.GetB("mirror_above"); fMirroredParams[parname] = mir; NUIS_LOG(FIT, "\t\t" << parname << " is mirrored at " << mir.mirror_value << " " << (mir.mirror_above ? "from above" : "from below")); } // Convert if required if (parstate.find("ABS") != std::string::npos) { if (ismirr) { NUIS_ABORT("Cannot mirror parameters with ABS state!"); } parnom = FitBase::RWAbsToSigma(partype, parname, parnom); parlow = FitBase::RWAbsToSigma(partype, parname, parlow); parhigh = FitBase::RWAbsToSigma(partype, parname, parhigh); parstep = FitBase::RWAbsToSigma(partype, parname, parstep); } else if (parstate.find("FRAC") != std::string::npos) { if (ismirr) { NUIS_ABORT("Cannot mirror parameters with FRAC state!"); } parnom = FitBase::RWFracToSigma(partype, parname, parnom); parlow = FitBase::RWFracToSigma(partype, parname, parlow); parhigh = FitBase::RWFracToSigma(partype, parname, parhigh); parstep = FitBase::RWFracToSigma(partype, parname, parstep); } // Push into vectors fParams.push_back(parname); fTypeVals[parname] = FitBase::ConvDialType(partype); fCurVals[parname] = parnom; fStateVals[parname] = parstate; } // Setup Samples ---------------------------------------------- std::vector samplekeys = Config::QueryKeys("sample"); if (!samplekeys.empty()) { NUIS_LOG(FIT, "Number of samples : " << samplekeys.size()); } for (size_t i = 0; i < samplekeys.size(); i++) { nuiskey key = samplekeys.at(i); // Get Sample Options std::string samplename = key.GetS("name"); std::string samplefile = key.GetS("input"); std::string sampletype = key.Has("type") ? key.GetS("type") : "DEFAULT"; double samplenorm = key.Has("norm") ? key.GetD("norm") : 1.0; // Print out NUIS_LOG(FIT, "Read Sample " << i << ". : " << samplename << " (" << sampletype << ") [Norm=" << samplenorm << "]" << std::endl - << " -> input='" + << "\t\t|-> input='" << samplefile << "'"); // If FREE add to parameters otherwise continue if (sampletype.find("FREE") == std::string::npos) { if (samplenorm != 1.0) { NUIS_ERR(FTL, "You provided a sample normalisation but did not specify " "that the sample is free"); NUIS_ABORT("Change so sample contains type=\"FREE\" and re-run"); } continue; } // Form norm dial from samplename + sampletype + "_norm"; std::string normname = samplename + "_norm"; // Check normname not already present if (fTypeVals.find("normname") != fTypeVals.end()) { continue; } // Add new norm dial to list if its passed above checks fParams.push_back(normname); fTypeVals[normname] = kNORM; fStateVals[normname] = sampletype; fCurVals[normname] = samplenorm; } // Setup Fake Parameters ----------------------------- std::vector fakekeys = Config::QueryKeys("fakeparameter"); if (!fakekeys.empty()) { NUIS_LOG(FIT, "Number of fake parameters : " << fakekeys.size()); } for (size_t i = 0; i < fakekeys.size(); i++) { nuiskey key = fakekeys.at(i); // Check for type,name,nom if (!key.Has("name")) { NUIS_ABORT("No name given for fakeparameter " << i); } else if (!key.Has("nominal")) { NUIS_ABORT("No nominal given for fakeparameter " << i); } // Get Inputs std::string parname = key.GetS("name"); double parnom = key.GetD("nominal"); // Push into vectors fFakeVals[parname] = parnom; } } //************************************* void ComparisonRoutines::SetupRWEngine() { //************************************* NUIS_LOG(FIT, "Setting up FitWeight Engine"); for (UInt_t i = 0; i < fParams.size(); i++) { std::string name = fParams[i]; FitBase::GetRW()->IncludeDial(name, fTypeVals.at(name)); } return; } //************************************* void ComparisonRoutines::SetupFCN() { //************************************* NUIS_LOG(FIT, "Building the SampleFCN"); if (fSampleFCN) delete fSampleFCN; Config::Get().out = fOutputRootFile; fOutputRootFile->cd(); fSampleFCN = new JointFCN(fOutputRootFile); SetFakeData(); return; } //************************************* void ComparisonRoutines::SetFakeData() { //************************************* if (fFakeDataInput.empty()) return; if (fFakeDataInput.compare("MC") == 0) { NUIS_LOG(FIT, "Setting fake data from MC starting prediction."); UpdateRWEngine(fFakeVals); FitBase::GetRW()->Reconfigure(); fSampleFCN->ReconfigureAllEvents(); fSampleFCN->SetFakeData("MC"); std::map CurVals_wmirr; for (size_t i = 0; i < fParams.size(); ++i) { std::string const &pname = fParams[i]; if (fMirroredParams.count(pname)) { if (!fMirroredParams[pname].mirror_above && (fCurVals[pname] < fMirroredParams[pname].mirror_value)) { double xabove = fMirroredParams[pname].mirror_value - fCurVals[pname]; CurVals_wmirr[pname] = fMirroredParams[pname].mirror_value + xabove; std::cout << "\t--Parameter " << pname << " mirrored from " << fCurVals[pname] << " -> " << CurVals_wmirr[pname] << std::endl; } else if (fMirroredParams[pname].mirror_above && (fCurVals[pname] >= fMirroredParams[pname].mirror_value)) { double xabove = fCurVals[pname] - fMirroredParams[pname].mirror_value; CurVals_wmirr[pname] = fMirroredParams[pname].mirror_value - xabove; std::cout << "\t--Parameter " << pname << " mirrored from " << fCurVals[pname] << " -> " << CurVals_wmirr[pname] << std::endl; } else { CurVals_wmirr[pname] = fCurVals[pname]; } } else { CurVals_wmirr[pname] = fCurVals[pname]; } } UpdateRWEngine(CurVals_wmirr); NUIS_LOG(FIT, "Set all data to fake MC predictions."); } else { NUIS_LOG(FIT, "Setting fake data from: " << fFakeDataInput); fSampleFCN->SetFakeData(fFakeDataInput); } return; } /* Fitting Functions */ //************************************* void ComparisonRoutines::UpdateRWEngine( std::map &updateVals) { //************************************* for (UInt_t i = 0; i < fParams.size(); i++) { std::string name = fParams[i]; if (updateVals.find(name) == updateVals.end()) continue; FitBase::GetRW()->SetDialValue(name, updateVals.at(name)); } FitBase::GetRW()->Reconfigure(); return; } //************************************* void ComparisonRoutines::Run() { //************************************* NUIS_LOG(FIT, "Running ComparisonRoutines : " << fStrategy); if (FitPar::Config().GetParB("save_nominal")) { SaveNominal(); } // Parse given routines fRoutines = GeneralUtils::ParseToStr(fStrategy, ","); if (fRoutines.empty()) { NUIS_ABORT("Trying to run ComparisonRoutines with no routines given!"); } for (UInt_t i = 0; i < fRoutines.size(); i++) { std::string routine = fRoutines.at(i); NUIS_LOG(FIT, "Routine: " << routine); if (!routine.compare("Compare")) { std::map CurVals_wmirr; for (size_t i = 0; i < fParams.size(); ++i) { std::string const &pname = fParams[i]; if (fMirroredParams.count(pname)) { std::cout << "MA? " << fMirroredParams[pname].mirror_above << ", OVal: " << fCurVals[pname] << ", MPoint: " << fMirroredParams[pname].mirror_value << std::endl; if (!fMirroredParams[pname].mirror_above && (fCurVals[pname] < fMirroredParams[pname].mirror_value)) { double xabove = fMirroredParams[pname].mirror_value - fCurVals[pname]; CurVals_wmirr[pname] = fMirroredParams[pname].mirror_value + xabove; std::cout << "\t--Parameter " << pname << " mirrored from " << fCurVals[pname] << " -> " << CurVals_wmirr[pname] << std::endl; } else if (fMirroredParams[pname].mirror_above && (fCurVals[pname] >= fMirroredParams[pname].mirror_value)) { double xabove = fCurVals[pname] - fMirroredParams[pname].mirror_value; CurVals_wmirr[pname] = fMirroredParams[pname].mirror_value - xabove; std::cout << "\t--Parameter " << pname << " mirrored from " << fCurVals[pname] << " -> " << CurVals_wmirr[pname] << std::endl; } else { CurVals_wmirr[pname] = fCurVals[pname]; } } else { CurVals_wmirr[pname] = fCurVals[pname]; } std::cout << "~~~~~~~" << pname << " : " << fCurVals[pname] << " -> " << CurVals_wmirr[pname] << std::endl; } UpdateRWEngine(CurVals_wmirr); GenerateComparison(); PrintState(); SaveCurrentState(); } } return; } //************************************* void ComparisonRoutines::GenerateComparison() { //************************************* NUIS_LOG(FIT, "Generating Comparison."); // Main Event Loop from event Manager fSampleFCN->ReconfigureAllEvents(); return; } //************************************* void ComparisonRoutines::PrintState() { //************************************* NUIS_LOG(FIT, "------------"); // Count max size int maxcount = 0; for (UInt_t i = 0; i < fParams.size(); i++) { maxcount = max(int(fParams[i].size()), maxcount); } // Header NUIS_LOG(FIT, " # " << left << setw(maxcount) << "Parameter " << " = " << setw(10) << "Value" << " +- " << setw(10) << "Error" << " " << setw(8) << "(Units)" << " " << setw(10) << "Conv. Val" << " +- " << setw(10) << "Conv. Err" << " " << setw(8) << "(Units)"); std::map CurVals_wmirr; for (size_t i = 0; i < fParams.size(); ++i) { std::string const &pname = fParams[i]; if (fMirroredParams.count(pname)) { if (!fMirroredParams[pname].mirror_above && (fCurVals[pname] < fMirroredParams[pname].mirror_value)) { double xabove = fMirroredParams[pname].mirror_value - fCurVals[pname]; CurVals_wmirr[pname] = fMirroredParams[pname].mirror_value + xabove; std::cout << "\t--Parameter " << pname << " mirrored from " << fCurVals[pname] << " -> " << CurVals_wmirr[pname] << std::endl; } else if (fMirroredParams[pname].mirror_above && (fCurVals[pname] >= fMirroredParams[pname].mirror_value)) { double xabove = fCurVals[pname] - fMirroredParams[pname].mirror_value; CurVals_wmirr[pname] = fMirroredParams[pname].mirror_value - xabove; std::cout << "\t--Parameter " << pname << " mirrored from " << fCurVals[pname] << " -> " << CurVals_wmirr[pname] << std::endl; } else { CurVals_wmirr[pname] = fCurVals[pname]; } } else { CurVals_wmirr[pname] = fCurVals[pname]; } } // Parameters for (UInt_t i = 0; i < fParams.size(); i++) { std::string syst = fParams.at(i); std::string typestr = FitBase::ConvDialType(fTypeVals[syst]); std::string curunits = "(sig.)"; double curval = fCurVals[syst]; double curerr = 0.0; if (fStateVals[syst].find("ABS") != std::string::npos) { curval = FitBase::RWSigmaToAbs(typestr, syst, curval); curerr = (FitBase::RWSigmaToAbs(typestr, syst, curerr) - FitBase::RWSigmaToAbs(typestr, syst, 0.0)); curunits = "(Abs.)"; } else if (fStateVals[syst].find("FRAC") != std::string::npos) { curval = FitBase::RWSigmaToFrac(typestr, syst, curval); curerr = (FitBase::RWSigmaToFrac(typestr, syst, curerr) - FitBase::RWSigmaToFrac(typestr, syst, 0.0)); curunits = "(Frac)"; } std::string convunits = "(" + FitBase::GetRWUnits(typestr, syst) + ")"; double convval = FitBase::RWSigmaToAbs(typestr, syst, curval); double converr = (FitBase::RWSigmaToAbs(typestr, syst, curerr) - FitBase::RWSigmaToAbs(typestr, syst, 0.0)); std::ostringstream curparstring; curparstring << " " << setw(3) << left << i << ". " << setw(maxcount) << syst << " = " << setw(10) << curval << " +- " << setw(10) << curerr << " " << setw(8) << curunits << " " << setw(10) << convval << " +- " << setw(10) << converr << " " << setw(8) << convunits; NUIS_LOG(FIT, curparstring.str()); if (fMirroredParams.count(syst)) { NUIS_LOG(FIT, "\t\t--> Mirrored at " << fMirroredParams[syst].mirror_value << " to effective value " << CurVals_wmirr[syst]); } } NUIS_LOG(FIT, "------------"); double like = fSampleFCN->GetLikelihood(); NUIS_LOG(FIT, std::left << std::setw(46) << "Likelihood for JointFCN: " << like); NUIS_LOG(FIT, "------------"); } /* Write Functions */ //************************************* void ComparisonRoutines::SaveCurrentState(std::string subdir) { //************************************* NUIS_LOG(FIT, "Saving current full FCN predictions"); // Setup DIRS TDirectory *curdir = gDirectory; if (!subdir.empty()) { TDirectory *newdir = (TDirectory *)gDirectory->mkdir(subdir.c_str()); newdir->cd(); } fSampleFCN->Write(); // Change back to current DIR curdir->cd(); return; } //************************************* void ComparisonRoutines::SaveNominal() { //************************************* fOutputRootFile->cd(); NUIS_LOG(FIT, "Saving Nominal Predictions (be cautious with this)"); FitBase::GetRW()->Reconfigure(); GenerateComparison(); SaveCurrentState("nominal"); }; diff --git a/src/Routines/ComparisonRoutines.h b/src/Routines/ComparisonRoutines.h index 9111ef8..50cd9bb 100755 --- a/src/Routines/ComparisonRoutines.h +++ b/src/Routines/ComparisonRoutines.h @@ -1,175 +1,175 @@ // 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 COMPARISON_ROUTINES_H #define COMPARISON_ROUTINES_H /*! \addtogroup Routines @{ */ #include "TH1.h" #include "TF1.h" #include "TMatrixD.h" #include "TVectorD.h" #include "TSystem.h" #include "TFile.h" #include "TProfile.h" #include #include #include #include #include #include "FitEvent.h" #include "JointFCN.h" #include "GeneralUtils.h" #include "NuisConfig.h" #include "NuisKey.h" #include "FitLogger.h" #include "ParserUtils.h" enum minstate { kErrorStatus = -1, kGoodStatus, kFitError, kNoChange, kFitFinished, kFitUnfinished, kStateChange, }; //************************************* /// Collects all possible fit routines into a single class to avoid repeated code class ComparisonRoutines { //************************************* public: /* Constructor/Destructor */ /// Constructor reads in arguments given at the command line for the fit here. ComparisonRoutines(int argc, char* argv[]); /// Default destructor ~ComparisonRoutines(); /// Reset everything to default/NULL void Init(); /* Input Functions */ /// Queries configuration keys to setup Parameters/Samples/FakeParameters void SetupComparisonsFromXML(); /* Setup Functions */ /// Setups up our custom RW engine with all the parameters passed in the card file void SetupRWEngine(); /// Setups up the jointFCN. void SetupFCN(); /// Set the current data histograms in each sample to the fake data. void SetFakeData(); /* Fitting Functions */ /// Main function to actually start iterating over the different required fit routines void Run(); /// Creates a comparison from FCN void GenerateComparison(); /// Given a new map change the values that the RW engine is currently set to void UpdateRWEngine(std::map& updateVals); /// Print current value void PrintState(); /* Write Functions */ /// Save the sample plots for current MC /// dir if not empty forces plots to be saved in a subdirectory of outputfile void SaveCurrentState(std::string subdir=""); - /// Save starting predictions into a seperate folder + /// Save starting predictions into a separate folder void SaveNominal(); /* MISC Functions */ /// Get previous fit status from a file Int_t GetStatus(); protected: //! Our Custom ReWeight Object FitWeight* rw; std::string fOutputFile; ///< Output file name // std::string fInputFile; ///< Input file name // TFile* fInputRootFile; ///< TFile* fOutputRootFile; ///< Output ROOT TFile JointFCN* fSampleFCN; ///< Joint Samples Container that handles reconfigures. std::string fCardFile; ///< Input card/XML file. std::string fStrategy; ///< Comparison routine selection. std::vector fRoutines; ///< Split vector of comparison routine selection. std::string fAllowedRoutines; ///< Hard coded list of allowed routines. /// Fake data flag. Can be 'MC' to use 'fake_parameter' /// or 'path_to_file.root' to use previous NUISANCE MC predictions. std::string fFakeDataInput; // Input Dial Vals std::vector fParams; ///< Vector of dial names. std::map fStateVals; ///< Map of dial states std::map fCurVals; ///< Map of dial values std::map fTypeVals; ///< Map of dial type enums. struct mirror_param { double mirror_value; bool mirror_above; }; std::map fMirroredParams; // Fake Dial Vals std::map fFakeVals; ///< Map of fake data settings. // Configuration nuiskey fCompKey; ///< Configuration Key for this Comparison Instance }; /*! @} */ #endif diff --git a/src/Routines/MinimizerRoutines.h b/src/Routines/MinimizerRoutines.h index dcff46b..4b3e10c 100755 --- a/src/Routines/MinimizerRoutines.h +++ b/src/Routines/MinimizerRoutines.h @@ -1,284 +1,284 @@ // 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 MINIMIZER_ROUTINES_H #define MINIMIZER_ROUTINES_H /*! * \addtogroup Minimizer * @{ */ #include "TH1.h" #include "TF1.h" #include "TMatrixD.h" #include "TVectorD.h" #ifdef ROOT6_USE_FIT_FITTER_INTERFACE #include "Fit/Fitter.h" #else #include "Minuit2/FCNBase.h" #include "TFitterMinuit.h" #endif #include "TSystem.h" #include "TFile.h" #include "TProfile.h" #include #include #include #include #include #include "FitEvent.h" #include "JointFCN.h" #include "MinimizerFCN.h" #include "Math/Minimizer.h" #include "Math/Factory.h" #include "Math/Functor.h" #include "FitLogger.h" #include "ParserUtils.h" enum minstate { kErrorStatus = -1, kGoodStatus, kFitError, kNoChange, kFitFinished, kFitUnfinished, kStateChange, }; //************************************* //! Collects all possible fit routines into a single class to avoid repeated code class MinimizerRoutines{ //************************************* public: /* Constructor/Destructor */ MinimizerRoutines(); //! Constructor reads in arguments given at the command line for the fit here. MinimizerRoutines(int argc, char* argv[]); //! Default destructor ~MinimizerRoutines(); //! Reset everything to default/NULL void Init(); /* Input Functions */ //! Splits the arguments ready for initial setup void ParseArgs(int argc, char* argv[]); //! Sorts out configuration and verbosity right at the very start. //! Calls readCard to set everything else up. void InitialSetup(); //! Loops through each line of the card file and passes it to other read functions void ReadCard(std::string cardfile); //! Check for parameter string in the line and assign the correct type. //! Fills maps for each of the parameters int ReadParameters(std::string parstring); //! Reads in fake parameters and assigns them (Requires the parameter to be included as a normal parameter as well) int ReadFakeDataPars(std::string parstring); //! Read in the samples so we can set up the free normalisation dials if required int ReadSamples(std::string sampleString); void SetupMinimizerFromXML(); /* Setup Functions */ //! Setup the configuration given the arguments passed at the commandline and card file void SetupConfig(); //! Setups up our custom RW engine with all the parameters passed in the card file void SetupRWEngine(); //! Setups up the jointFCN. void SetupFCN(); //! Sets up the minimizerObj for ROOT. there are cases where this is called repeatedly, e.g. If you are using a brute force scan before using Migrad. void SetupFitter(std::string routine); //! Set the current data histograms in each sample to the fake data. void SetFakeData(); //! Setup the covariances with the correct dimensions. At the start this is either uncorrelated or merged given all the input covariances. //! At the end of the fit this produces the blank covariances which can then be filled by the minimizerObj with best fit covariances. void SetupCovariance(); /* Fitting Functions */ //! Main function to actually start iterating over the different required fit routines void Run(); //! Given a new map change the values that the RW engine is currently set to void UpdateRWEngine(std::map& updateVals); //! Given a single routine (see tutorial for options) run that fit routine now. int RunFitRoutine(std::string routine); //! Get the current state of minimizerObj and fill it into currentVals and currentNorms void GetMinimizerState(); //! Print current value void PrintState(); //! Performs a fit routine where the input.maxevents is set to a much lower value to try and move closer to the best fit minimum. void LowStatRoutine(std::string routine); //! Perform a chi2 scan in 1D around the current point void Create1DScans(); //! Perform a chi2 scan in 2D around the current point void Chi2Scan2D(); //! Currently a placeholder NEEDS UPDATING void CreateContours(); //! If any currentVals are close to the limits set them to the limit and fix them int FixAtLimit(); //! Throw the current covariance of dial values we have, and fill the thrownVals and thrownNorms maps. //! If uniformly is true parameters will be thrown uniformly between their upper and lower limits. void ThrowCovariance(bool uniformly); //! Given the covariance we currently have generate error bands by throwing the covariance. //! The FitPar config "error_uniform" defines whether to throw using the covariance or uniformly. //! The FitPar config "error_throws" defines how many throws are needed. //! Currently only supports TH1D plots. void GenerateErrorBands(); /* Write Functions */ //! Write plots and TTrees listing the minimizerObj result of the fit to file void SaveMinimizerState(); //! Save the sample plots for current MC //! dir if not empty forces plots to be saved in a subdirectory of outputfile void SaveCurrentState(std::string subdir=""); - //! Save starting predictions into a seperate folder + //! Save starting predictions into a separate folder void SaveNominal(); - //! Save predictions before the fit is ran into a seperate folder + //! Save predictions before the fit is ran into a separate folder void SavePrefit(); void SaveResults(); /* MISC Functions */ //! Get previous fit status from a file Int_t GetStatus(); /// Makes a histogram of likelihoods when throwing the data according to its statistics void ThrowDataToys(); protected: //! Our Custom ReWeight Object FitWeight* rw; std::string fOutputFile; std::string fInputFile; TFile* fInputRootFile; TFile* fOutputRootFile; //! Flag for whether the fit should be continued if an output file is already found. bool fitContinue; //! Minimizer Object for handling roots different minimizer methods ROOT::Math::Minimizer* fMinimizer; JointFCN* fSampleFCN; MinimizerFCN* fMinimizerFCN; ROOT::Math::Functor* fCallFunctor; int nfreepars; std::string fCardFile; std::string fStrategy; std::vector fRoutines; std::string fAllowedRoutines; std::string fFakeDataInput; // Input Dial Vals //! Vector of dial names std::vector fParams; std::map fStateVals; std::map fStartVals; std::map fCurVals; std::map fErrorVals; std::map fMinVals; std::map fMaxVals; std::map fStepVals; std::map fTypeVals; std::map fFixVals; std::map fStartFixVals; struct mirror_param { double mirror_value; bool mirror_above; }; std::map fMirroredParams; //! Vector of fake parameter names std::map fFakeVals; //! Map of thrown parameter names and values (After ThrowCovariance) std::map fThrownVals; TH2D* fCorrel; TH2D* fDecomp; TH2D* fCovar; TH2D* fCorFree; TH2D* fDecFree; TH2D* fCovFree; nuiskey fCompKey; }; /*! @} */ #endif diff --git a/src/Routines/SplineRoutines.cxx b/src/Routines/SplineRoutines.cxx index c5b1fed..7bfa6a8 100755 --- a/src/Routines/SplineRoutines.cxx +++ b/src/Routines/SplineRoutines.cxx @@ -1,2598 +1,2598 @@ // 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 "SplineRoutines.h" void SplineRoutines::Init() { fStrategy = "SaveEvents"; fRoutines.clear(); fCardFile = ""; fSampleFCN = NULL; fRW = NULL; fAllowedRoutines = ("SaveEvents,TestEvents,SaveSplineEvents"); }; SplineRoutines::~SplineRoutines(){}; SplineRoutines::SplineRoutines(int argc, char *argv[]) { // Initialise Defaults Init(); nuisconfig configuration = Config::Get(); // Default containers std::string cardfile = ""; std::string maxevents = "-1"; int errorcount = 0; int verbocount = 0; std::vector xmlcmds; std::vector configargs; // Make easier to handle arguments. std::vector args = GeneralUtils::LoadCharToVectStr(argc, argv); ParserUtils::ParseArgument(args, "-c", fCardFile, true); ParserUtils::ParseArgument(args, "-o", fOutputFile, false, false); ParserUtils::ParseArgument(args, "-n", maxevents, false, false); ParserUtils::ParseArgument(args, "-f", fStrategy, false, false); ParserUtils::ParseArgument(args, "-i", xmlcmds); ParserUtils::ParseArgument(args, "-q", configargs); ParserUtils::ParseCounter(args, "e", errorcount); ParserUtils::ParseCounter(args, "v", verbocount); ParserUtils::CheckBadArguments(args); // Add extra defaults if none given if (fCardFile.empty() and xmlcmds.empty()) { NUIS_ABORT("No input supplied!"); } if (fOutputFile.empty() and !fCardFile.empty()) { fOutputFile = fCardFile + ".root"; NUIS_ERR(WRN, "No output supplied so saving it to: " << fOutputFile); } else if (fOutputFile.empty()) { NUIS_ABORT("No output file or cardfile supplied!"); } // Configuration Setup ============================= // Check no comp key is available nuiskey fCompKey; if (Config::Get().GetNodes("nuiscomp").empty()) { fCompKey = Config::Get().CreateNode("nuiscomp"); } else { fCompKey = Config::Get().GetNodes("nuiscomp")[0]; } if (!fCardFile.empty()) fCompKey.Set("cardfile", fCardFile); fCompKey.Set("outputfile", fOutputFile); if (!fStrategy.empty()) fCompKey.Set("strategy", fStrategy); // Load XML Cardfile configuration.LoadSettings(fCompKey.GetS("cardfile"), ""); // Add Config Args for (size_t i = 0; i < configargs.size(); i++) { configuration.OverrideConfig(configargs[i]); } if (maxevents.compare("-1")) { std::cout << "[ NUISANCE ] : Overriding " << "MAXEVENTS=" + maxevents << std::endl; configuration.OverrideConfig("MAXEVENTS=" + maxevents); } // Finish configuration XML configuration.FinaliseSettings(fCompKey.GetS("outputfile") + ".xml"); // Add Error Verbo Lines verbocount += Config::GetParI("VERBOSITY"); errorcount += Config::GetParI("ERROR"); std::cout << "[ NUISANCE ]: Setting VERBOSITY=" << verbocount << std::endl; std::cout << "[ NUISANCE ]: Setting ERROR=" << errorcount << std::endl; // FitPar::log_verb = verbocount; SETVERBOSITY(verbocount); // ERR_VERB(errorcount); // Starting Setup // --------------------------- SetupRWEngine(); return; }; /* Setup Functions */ //************************************* void SplineRoutines::SetupRWEngine() { //************************************* fRW = new FitWeight("splineweight"); // std::vector splinekeys = Config::QueryKeys("spline"); std::vector parameterkeys = Config::QueryKeys("parameter"); // Add Parameters for (size_t i = 0; i < parameterkeys.size(); i++) { nuiskey key = parameterkeys[i]; std::string parname = key.GetS("name"); std::string partype = key.GetS("type"); double nom = key.GetD("nominal"); fRW->IncludeDial(key.GetS("name"), FitBase::ConvDialType(key.GetS("type")), nom); fRW->SetDialValue(key.GetS("name"), key.GetD("nominal")); } fRW->Reconfigure(); return; } /* Fitting Functions */ //************************************* void SplineRoutines::UpdateRWEngine(std::map &updateVals) { //************************************* for (UInt_t i = 0; i < fParams.size(); i++) { std::string name = fParams[i]; if (updateVals.find(name) == updateVals.end()) continue; fRW->SetDialValue(name, updateVals.at(name)); } fRW->Reconfigure(); return; } //************************************* void SplineRoutines::Run() { //************************************* std::cout << "Running " << std::endl; // Parse given routines fRoutines = GeneralUtils::ParseToStr(fStrategy, ","); if (fRoutines.empty()) { NUIS_ABORT("Trying to run ComparisonRoutines with no routines given!"); } for (size_t i = 0; i < fRoutines.size(); i++) { NUIS_LOG(FIT, "Running Routine: " << fRoutines[i]); std::string rout = fRoutines[i]; if (!rout.compare("SaveEvents")) SaveEvents(); else if (!rout.compare("TestEvents")) TestEvents(); else if (!rout.compare("GenerateEventSplines")) { GenerateEventWeights(); BuildEventSplines(); } else if (!rout.compare("GenerateEventWeights")) { GenerateEventWeights(); } else if (!rout.compare("GenerateEventWeightChunks")) { GenerateEventWeightChunks(FitPar::Config().GetParI("spline_procchunk")); } else if (!rout.compare("BuildEventSplines")) { BuildEventSplines(); } else if (!rout.compare("TestSplines_1DEventScan")) TestSplines_1DEventScan(); else if (!rout.compare("TestSplines_NDEventThrow")) TestSplines_NDEventThrow(); else if (!rout.compare("SaveSplinePlots")) SaveSplinePlots(); else if (!rout.compare("TestSplines_1DLikelihoodScan")) TestSplines_1DLikelihoodScan(); else if (!rout.compare("TestSplines_NDLikelihoodThrow")) TestSplines_NDLikelihoodThrow(); else if (!rout.compare("BuildEventSplinesChunks")) { int chunk = FitPar::Config().GetParI("spline_procchunk"); BuildEventSplines(chunk); } else if (!rout.compare("MergeEventSplinesChunks")) { MergeEventSplinesChunks(); } } } //************************************* void SplineRoutines::SaveEvents() { //************************************* if (fRW) delete fRW; SetupRWEngine(); fRW->Reconfigure(); fRW->Print(); // Generate a set of nominal events // Method, Loop over inputs, create input handler, then create a ttree std::vector eventkeys = Config::QueryKeys("events"); for (size_t i = 0; i < eventkeys.size(); i++) { nuiskey key = eventkeys.at(i); // Get I/O std::string inputfilename = key.GetS("input"); if (inputfilename.empty()) { NUIS_ABORT("No input given for set of input events!"); } std::string outputfilename = key.GetS("output"); if (outputfilename.empty()) { outputfilename = inputfilename + ".nuisance.root"; NUIS_ERR(WRN, "No output give for set of output events! Saving to " << outputfilename); } // Make new outputfile TFile *outputfile = new TFile(outputfilename.c_str(), "RECREATE"); outputfile->cd(); // Make a new input handler std::vector file_descriptor = GeneralUtils::ParseToStr(inputfilename, ":"); if (file_descriptor.size() != 2) { NUIS_ABORT("File descriptor had no filetype declaration: \"" << inputfilename << "\". expected \"FILETYPE:file.root\""); } InputUtils::InputType inptype = InputUtils::ParseInputType(file_descriptor[0]); InputHandlerBase *input = InputUtils::CreateInputHandler( "eventsaver", inptype, file_descriptor[1]); // Get info from inputhandler int nevents = input->GetNEvents(); int countwidth = (nevents / 10); FitEvent *nuisevent = input->FirstNuisanceEvent(); // Setup a TTree to save the event outputfile->cd(); TTree *eventtree = new TTree("nuisance_events", "nuisance_events"); nuisevent->AddBranchesToTree(eventtree); // Loop over all events and fill the TTree int icount = 0; // int countwidth = nevents / 5; while (nuisevent) { // Get Event Weight nuisevent->RWWeight = fRW->CalcWeight(nuisevent); // if (nuisevent->RWWeight != 1.0){ // std::cout << "Weight = " << nuisevent->RWWeight << std::endl; // } // Save everything eventtree->Fill(); // Logging if (icount % countwidth == 0) { NUIS_LOG(REC, "Saved " << icount << "/" << nevents << " nuisance events. [M, W] = [" << nuisevent->Mode << ", " << nuisevent->RWWeight << "]"); } // iterate nuisevent = input->NextNuisanceEvent(); icount++; } // Save flux and close file outputfile->cd(); eventtree->Write(); input->GetFluxHistogram()->Write("nuisance_fluxhist"); input->GetEventHistogram()->Write("nuisance_eventhist"); // Close Output outputfile->Close(); // Delete Inputs delete input; } // remove Keys eventkeys.clear(); // Finished NUIS_LOG(FIT, "Finished processing all nuisance events."); } //************************************* void SplineRoutines::TestEvents() { //************************************* NUIS_LOG(FIT, "Testing events."); // Create a new file for the test samples if (!fOutputRootFile) { fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE"); } // Loop over all tests int count = 0; std::vector testkeys = Config::QueryKeys("sampletest"); for (std::vector::iterator iter = testkeys.begin(); iter != testkeys.end(); iter++) { nuiskey key = (*iter); // 0. Create new measurement list std::list samplelist; // 1. Build Sample From Events std::string samplename = key.GetS("name"); std::string eventsid = key.GetS("inputid"); nuiskey eventskey = Config::QueryLastKey("events", "id=" + eventsid); std::string rawfile = eventskey.GetS("input"); NUIS_LOG(FIT, "Creating sample " << samplename); MeasurementBase *rawsample = SampleUtils::CreateSample( samplename, rawfile, "", "", FitBase::GetRW()); // 2. Build Sample From Nuisance Events std::string eventsfile = eventskey.GetS("output"); NUIS_LOG(FIT, "Creating Fit Eevnt Sample " << samplename << " " << eventsfile); MeasurementBase *nuissample = SampleUtils::CreateSample( samplename, "FEVENT:" + eventsfile, "", "", FitBase::GetRW()); // 3. Make some folders to save stuff TDirectory *sampledir = (TDirectory *)fOutputRootFile->mkdir( Form((samplename + "_test_%d").c_str(), count)); TDirectory *rawdir = (TDirectory *)sampledir->mkdir("raw"); TDirectory *nuisancedir = (TDirectory *)sampledir->mkdir("nuisance"); TDirectory *difdir = (TDirectory *)sampledir->mkdir("difference"); // 4. Reconfigure both rawdir->cd(); rawsample->Reconfigure(); rawsample->Write(); nuisancedir->cd(); nuissample->Reconfigure(); nuissample->Write(); // 4. Compare Raw to Nuisance Events // Loop over all keyse TIter next(rawdir->GetListOfKeys()); TKey *dirkey; while ((dirkey = (TKey *)next())) { // If not a 1D/2D histogram skip TClass *cl = gROOT->GetClass(dirkey->GetClassName()); if (!cl->InheritsFrom("TH1D") and !cl->InheritsFrom("TH2D")) continue; // Get TH1* from both dir TH1 *rawplot = (TH1 *)rawdir->Get(dirkey->GetName()); TH1 *nuisanceplot = (TH1 *)nuisancedir->Get(dirkey->GetName()); // Take Difference nuisanceplot->Add(rawplot, -1.0); // Save to dif folder difdir->cd(); nuisanceplot->Write(); } // 5. Tidy Up samplelist.clear(); // Iterator count++; } } void SplineRoutines::GenerateEventWeightChunks(int procchunk) { if (fRW) delete fRW; SetupRWEngine(); // Setup the spline reader SplineWriter *splwrite = new SplineWriter(fRW); std::vector splinekeys = Config::QueryKeys("spline"); // Add splines to splinewriter for (std::vector::iterator iter = splinekeys.begin(); iter != splinekeys.end(); iter++) { nuiskey splkey = (*iter); // Add Spline Info To Reader splwrite->AddSpline(splkey); } splwrite->SetupSplineSet(); // Event Loop // Loop over all events and calculate weights for each parameter set. // Generate a set of nominal events // Method, Loop over inputs, create input handler, then create a ttree std::vector eventkeys = Config::QueryKeys("events"); for (size_t i = 0; i < eventkeys.size(); i++) { nuiskey key = eventkeys.at(i); // Get I/O std::string inputfilename = key.GetS("input"); if (inputfilename.empty()) { NUIS_ABORT("No input given for set of input events!"); } std::string outputfilename = key.GetS("output"); if (outputfilename.empty()) { outputfilename = inputfilename + ".nuisance.root"; NUIS_ERR(WRN,"No output give for set of output events! Saving to " << outputfilename); } outputfilename += ".weights.root"; // Make new outputfile TFile *outputfile = new TFile(outputfilename.c_str(), "RECREATE"); outputfile->cd(); // Make a new input handler std::vector file_descriptor = GeneralUtils::ParseToStr(inputfilename, ":"); if (file_descriptor.size() != 2) { NUIS_ABORT("File descriptor had no filetype declaration: \"" << inputfilename << "\". expected \"FILETYPE:file.root\""); } InputUtils::InputType inptype = InputUtils::ParseInputType(file_descriptor[0]); InputHandlerBase *input = InputUtils::CreateInputHandler( "eventsaver", inptype, file_descriptor[1]); // Get info from inputhandler int nevents = input->GetNEvents(); // int countwidth = (nevents / 1000); FitEvent *nuisevent = input->FirstNuisanceEvent(); // Setup a TTree to save the event outputfile->cd(); TTree *eventtree = new TTree("nuisance_events", "nuisance_events"); // Add a flag that allows just splines to be saved. nuisevent->AddBranchesToTree(eventtree); // Save the spline reader splwrite->Write("spline_reader"); // Setup the spline TTree TTree *weighttree = new TTree("weight_tree", "weight_tree"); splwrite->AddWeightsToTree(weighttree); // Make container for all weights int nweights = splwrite->GetNWeights(); // int npar = splwrite->GetNPars(); // double* weightcont = new double[nweights]; int lasttime = time(NULL); // Load N Chunks of the Weights into Memory // Split into N processing chunks int nchunks = FitPar::Config().GetParI("spline_chunks"); if (nchunks <= 0) nchunks = 1; if (nchunks >= nevents / 2) nchunks = nevents / 2; std::cout << "Starting NChunks " << nchunks << std::endl; for (int ichunk = 0; ichunk < nchunks; ichunk++) { // Skip to only do one processing chunk if (procchunk != -1 and procchunk != ichunk) continue; NUIS_LOG(FIT, "On Processing Chunk " << ichunk); int neventsinchunk = nevents / nchunks; int loweventinchunk = neventsinchunk * ichunk; // int higheventinchunk = neventsinchunk * (ichunk + 1); double **allweightcont = new double *[neventsinchunk]; for (int k = 0; k < neventsinchunk; k++) { allweightcont[k] = new double[nweights]; } // Start Set Processing Here. for (int iset = 0; iset < nweights; iset++) { splwrite->ReconfigureSet(iset); // Could reorder this to save the weightconts in order instead of // reconfiguring per event. Loop over all events and fill the TTree for (int i = 0; i < neventsinchunk; i++) { nuisevent = input->GetNuisanceEvent(i + loweventinchunk); double w = splwrite->GetWeightForThisSet(nuisevent); if (iset == 0) { allweightcont[i][0] = w; } else { allweightcont[i][iset] = w / allweightcont[i][0]; } // Save everything if (iset == 0) { eventtree->Fill(); } } std::ostringstream timestring; int timeelapsed = time(NULL) - lasttime; if (timeelapsed) { lasttime = time(NULL); int setsleft = (nweights - iset - 1) + (nweights * (nchunks - ichunk - 1)); float proj = (float(setsleft) * timeelapsed) / 60 / 60; timestring << setsleft << " sets remaining. Last one took " << timeelapsed << ". " << proj << " hours remaining."; } NUIS_LOG(REC, "Processed Set " << iset << "/" << nweights << " in chunk " << ichunk << "/" << nchunks << " " << timestring.str()); } // Fill weights for this chunk into the TTree for (int k = 0; k < neventsinchunk; k++) { splwrite->SetWeights(allweightcont[k]); weighttree->Fill(); } } // at end of the chunk, when all sets have been done // loop over the container and fill weights to ttree outputfile->cd(); eventtree->Write(); weighttree->Write(); input->GetFluxHistogram()->Write("nuisance_fluxhist"); input->GetEventHistogram()->Write("nuisance_eventhist"); splwrite->Write("spline_reader"); outputfile->Close(); // Close Output outputfile->Close(); // Delete Inputs delete input; } // remove Keys eventkeys.clear(); } //************************************* void SplineRoutines::GenerateEventWeights() { //************************************* if (fRW) delete fRW; SetupRWEngine(); // Setup the spline reader SplineWriter *splwrite = new SplineWriter(fRW); std::vector splinekeys = Config::QueryKeys("spline"); // Add splines to splinewriter for (std::vector::iterator iter = splinekeys.begin(); iter != splinekeys.end(); iter++) { nuiskey splkey = (*iter); // Add Spline Info To Reader splwrite->AddSpline(splkey); } splwrite->SetupSplineSet(); // Event Loop // Loop over all events and calculate weights for each parameter set. // Generate a set of nominal events // Method, Loop over inputs, create input handler, then create a ttree std::vector eventkeys = Config::QueryKeys("events"); for (size_t i = 0; i < eventkeys.size(); i++) { nuiskey key = eventkeys.at(i); // Get I/O std::string inputfilename = key.GetS("input"); if (inputfilename.empty()) { NUIS_ABORT("No input given for set of input events!"); } std::string outputfilename = key.GetS("output"); if (outputfilename.empty()) { outputfilename = inputfilename + ".nuisance.root"; NUIS_ERR(WRN, "No output give for set of output events! Saving to " << outputfilename); } outputfilename += ".weights.root"; // Make new outputfile TFile *outputfile = new TFile(outputfilename.c_str(), "RECREATE"); outputfile->cd(); // Make a new input handler std::vector file_descriptor = GeneralUtils::ParseToStr(inputfilename, ":"); if (file_descriptor.size() != 2) { NUIS_ABORT("File descriptor had no filetype declaration: \"" << inputfilename << "\". expected \"FILETYPE:file.root\""); } InputUtils::InputType inptype = InputUtils::ParseInputType(file_descriptor[0]); InputHandlerBase *input = InputUtils::CreateInputHandler( "eventsaver", inptype, file_descriptor[1]); // Get info from inputhandler int nevents = input->GetNEvents(); int countwidth = (nevents / 1000); FitEvent *nuisevent = input->FirstNuisanceEvent(); // Setup a TTree to save the event outputfile->cd(); TTree *eventtree = new TTree("nuisance_events", "nuisance_events"); // Add a flag that allows just splines to be saved. nuisevent->AddBranchesToTree(eventtree); // Save the spline reader splwrite->Write("spline_reader"); // Setup the spline TTree TTree *weighttree = new TTree("weight_tree", "weight_tree"); splwrite->AddWeightsToTree(weighttree); // Make container for all weights int nweights = splwrite->GetNWeights(); // int npar = splwrite->GetNPars(); double *weightcont = new double[nweights]; int lasttime = time(NULL); // Could reorder this to save the weightconts in order instead of // reconfiguring per event. Loop over all events and fill the TTree while (nuisevent) { // Calculate the weights for each parameter set splwrite->GetWeightsForEvent(nuisevent, weightcont); // Save everything eventtree->Fill(); weighttree->Fill(); // Logging if (i % countwidth == 0) { std::ostringstream timestring; int timeelapsed = time(NULL) - lasttime; if (i != 0 and timeelapsed) { lasttime = time(NULL); int eventsleft = nevents - i; float speed = float(countwidth) / float(timeelapsed); float proj = (float(eventsleft) / float(speed)) / 60 / 60; timestring << proj << " hours remaining."; } NUIS_LOG(REC, "Saved " << i << "/" << nevents << " nuisance spline weights. " << timestring.str()); } // Iterate i++; nuisevent = input->NextNuisanceEvent(); } // at end of the chunk, when all sets have been done // loop over the container and fill weights to ttree outputfile->cd(); eventtree->Write(); weighttree->Write(); input->GetFluxHistogram()->Write("nuisance_fluxhist"); input->GetEventHistogram()->Write("nuisance_eventhist"); splwrite->Write("spline_reader"); outputfile->Close(); // Close Output outputfile->Close(); // Delete Inputs delete input; } // remove Keys eventkeys.clear(); } //************************************* void SplineRoutines::GenerateEventSplines() { //************************************* if (fRW) delete fRW; SetupRWEngine(); // Setup the spline reader SplineWriter *splwrite = new SplineWriter(fRW); std::vector splinekeys = Config::QueryKeys("spline"); // Add splines to splinewriter for (std::vector::iterator iter = splinekeys.begin(); iter != splinekeys.end(); iter++) { nuiskey splkey = (*iter); // Add Spline Info To Reader splwrite->AddSpline(splkey); } splwrite->SetupSplineSet(); // Make an ugly list for N cores int ncores = FitPar::Config().GetParI("NCORES"); // omp_get_max_threads(); std::vector splwriterlist; for (int i = 0; i < ncores; i++) { SplineWriter *tmpwriter = new SplineWriter(fRW); for (std::vector::iterator iter = splinekeys.begin(); iter != splinekeys.end(); iter++) { nuiskey splkey = (*iter); // Add Spline Info To Reader tmpwriter->AddSpline(splkey); } tmpwriter->SetupSplineSet(); splwriterlist.push_back(tmpwriter); } // Event Loop // Loop over all events and calculate weights for each parameter set. // Generate a set of nominal events // Method, Loop over inputs, create input handler, then create a ttree std::vector eventkeys = Config::QueryKeys("events"); for (size_t i = 0; i < eventkeys.size(); i++) { nuiskey key = eventkeys.at(i); // Get I/O std::string inputfilename = key.GetS("input"); if (inputfilename.empty()) { NUIS_ABORT("No input given for set of input events!"); } std::string outputfilename = key.GetS("output"); if (outputfilename.empty()) { outputfilename = inputfilename + ".nuisance.root"; NUIS_ERR(WRN, "No output give for set of output events! Saving to " << outputfilename); } // Make new outputfile TFile *outputfile = new TFile(outputfilename.c_str(), "RECREATE"); outputfile->cd(); // Make a new input handler std::vector file_descriptor = GeneralUtils::ParseToStr(inputfilename, ":"); if (file_descriptor.size() != 2) { NUIS_ABORT("File descriptor had no filetype declaration: \"" << inputfilename << "\". expected \"FILETYPE:file.root\""); } InputUtils::InputType inptype = InputUtils::ParseInputType(file_descriptor[0]); InputHandlerBase *input = InputUtils::CreateInputHandler( "eventsaver", inptype, file_descriptor[1]); // Get info from inputhandler int nevents = input->GetNEvents(); int countwidth = (nevents / 1000); FitEvent *nuisevent = input->FirstNuisanceEvent(); // Setup a TTree to save the event outputfile->cd(); TTree *eventtree = new TTree("nuisance_events", "nuisance_events"); // Add a flag that allows just splines to be saved. nuisevent->AddBranchesToTree(eventtree); // Save the spline reader splwrite->Write("spline_reader"); // Setup the spline TTree TTree *weighttree = new TTree("weight_tree", "weight_tree"); splwrite->AddWeightsToTree(weighttree); // Make container for all weights int nweights = splwrite->GetNWeights(); double **weightcont = new double *[nevents]; for (int k = 0; k < nevents; k++) { weightcont[k] = new double[nweights]; } int npar = splwrite->GetNPars(); int lasttime = time(NULL); // Could reorder this to save the weightconts in order instead of // reconfiguring per event. Loop over all events and fill the TTree while (nuisevent) { // std::cout << "Fitting event " << i << std::endl; // Calculate the weights for each parameter set // splwrite->FitSplinesForEvent(nuisevent); splwrite->GetWeightsForEvent(nuisevent, weightcont[i]); bool hasresponse = false; for (int j = 0; j < nweights; j++) { if (weightcont[i][j] != 1.0) { // std::cout << "Non Zero Weight at " << i << " " << j << // std::endl; hasresponse = true; } else { // std::cout << "Empty Weight at " << i << " " << j << std::endl; } } if (!hasresponse) { // std::cout << "Deleting flat response " << nuisevent->Mode << // std::endl; delete weightcont[i]; weightcont[i] = NULL; } // Save everything eventtree->Fill(); weighttree->Fill(); // splinetree->Fill(); // nuisevent->Print(); // std::cout << "Done with event " << i << std::endl; // Push weight sets into a the array // sleep(4); // Logging if (i % countwidth == 0) { std::ostringstream timestring; int timeelapsed = time(NULL) - lasttime; if (i != 0 and timeelapsed) { lasttime = time(NULL); int eventsleft = nevents - i; float speed = float(countwidth) / float(timeelapsed); float proj = (float(eventsleft) / float(speed)) / 60 / 60; timestring << proj << " hours remaining."; } NUIS_LOG(REC, "Saved " << i << "/" << nevents << " nuisance spline weights. " << timestring.str()); } // Iterate i++; nuisevent = input->NextNuisanceEvent(); } outputfile->cd(); eventtree->Write(); weighttree->Write(); input->GetFluxHistogram()->Write("nuisance_fluxhist"); input->GetEventHistogram()->Write("nuisance_eventhist"); outputfile->Close(); outputfile = new TFile(outputfilename.c_str(), "UPDATE"); outputfile->cd(); weighttree = (TTree *)outputfile->Get("weight_tree"); // splwrite->ReadWeightsFromTree(weighttree); // Divide weights container into Ncores. // Parrallelise this loop checking for what core we are on. // for (int i = 0; i < nevents; i++){ // splwriterlist[int(i / (nevents/4))]->FitSplinesForEvent(coeff); // } // // Now loop over weights tree // for (int i = 0; i < weighttree->GetEntries(); i++) { // weighttree->GetEntry(i); // splwrite->FitSplinesForEvent(); // splinetree->Fill(); // if (i % countwidth == 0) { // std::ostringstream timestring; // int timeelapsed = time(NULL) - lasttime; // if (i != 0 and timeelapsed) { // lasttime = time(NULL); // int eventsleft = nevents - i; // float speed = float(countwidth) / float(timeelapsed); // float proj = (float(eventsleft) / float(speed)) / 60 / 60; // timestring << proj << " hours remaining."; // } // LOG(REC) << "Built " << i << "/" << nevents << " nuisance spline // events. " << timestring.str() << std::endl; // } // } // Get Splines float **allcoeff = new float *[nevents]; for (int k = 0; k < nevents; k++) { allcoeff[k] = new float[npar]; } // #pragma omp parallel for num_threads(ncores) for (int i = 0; i < nevents; i++) { //#pragma omp atomic // printf("Using Thread %d to build event %d \n", // int(omp_get_thread_num()), (int)i ); std::cout<< " -> Writer = " // << splwriterlist[ i / (nevents/ncores) ] << std::endl; // #pragma omp atomic if (weightcont[i]) { splwriterlist[int(omp_get_thread_num())]->FitSplinesForEvent( weightcont[i], allcoeff[i]); } else { for (int j = 0; j < npar; j++) { allcoeff[i][j] = float(0.0); } } // splwrite->FitSplinesForEvent(weightcont[i], allcoeff[i]); if (i % 500 == 0) { if (LOG_LEVEL(REC)) { printf("Using Thread %d to build event %d \n", int(omp_get_thread_num()), (int)i); } } /* std::ostringstream timestring; int timeelapsed = time(NULL) - lasttime; if (i != 0 and timeelapsed) { lasttime = time(NULL); int eventsleft = nevents - i; float speed = float(countwidth) / float(timeelapsed); float proj = (float(eventsleft) / float(speed)) / 60 / 60; timestring << proj << " hours remaining."; timestring << " Using Writer at " << i / (nevents/ncores) << " = " << splwriterlist[ i / (nevents/ncores) ] << std::endl; } LOG(REC) << "Built " << i << "/" << nevents << " nuisance spline events. " << timestring.str() << std::endl; } */ } // Save Splines into TTree float *coeff = new float[npar]; outputfile->cd(); TTree *splinetree = new TTree("spline_tree", "spline_tree"); splinetree->Branch("SplineCoeff", coeff, Form("SplineCoeff[%d]/F", npar)); std::cout << "Saving to the allcoeff" << std::endl; for (int k = 0; k < nevents; k++) { for (int l = 0; l < npar; l++) { coeff[l] = allcoeff[k][l]; } std::cout << "Coeff 0, 1, 2 = " << coeff[0] << " " << coeff[1] << " " << coeff[2] << std::endl; splinetree->Fill(); } // Save flux and close file outputfile->cd(); splinetree->Write(); // Delete the container. for (int k = 0; k < nevents; k++) { delete weightcont[k]; } delete weightcont; delete coeff; // Close Output outputfile->Close(); // Delete Inputs delete input; } // remove Keys eventkeys.clear(); } //************************************* void SplineRoutines::BuildEventSplines(int procchunk) { //************************************* if (fRW) delete fRW; SetupRWEngine(); // Setup the spline reader SplineWriter *splwrite = new SplineWriter(fRW); std::vector splinekeys = Config::QueryKeys("spline"); // Add splines to splinewriter for (std::vector::iterator iter = splinekeys.begin(); iter != splinekeys.end(); iter++) { nuiskey splkey = (*iter); // Add Spline Info To Reader splwrite->AddSpline(splkey); } splwrite->SetupSplineSet(); // Make an ugly list for N cores int ncores = FitPar::Config().GetParI("spline_cores"); // omp_get_max_threads(); if (ncores > omp_get_max_threads()) ncores = omp_get_max_threads(); if (ncores <= 0) ncores = 1; std::vector splwriterlist; for (int i = 0; i < ncores; i++) { SplineWriter *tmpwriter = new SplineWriter(fRW); for (std::vector::iterator iter = splinekeys.begin(); iter != splinekeys.end(); iter++) { nuiskey splkey = (*iter); // Add Spline Info To Reader tmpwriter->AddSpline(splkey); } tmpwriter->SetupSplineSet(); splwriterlist.push_back(tmpwriter); } // Event Loop // Loop over all events and calculate weights for each parameter set. // Generate a set of nominal events // Method, Loop over inputs, create input handler, then create a ttree std::vector eventkeys = Config::QueryKeys("events"); for (size_t i = 0; i < eventkeys.size(); i++) { nuiskey key = eventkeys.at(i); // Get I/O std::string inputfilename = key.GetS("input"); if (inputfilename.empty()) { NUIS_ABORT("No input given for set of input events!"); } std::string outputfilename = key.GetS("output"); if (outputfilename.empty()) { outputfilename = inputfilename + ".nuisance.root"; NUIS_ERR(WRN, "No output give for set of output events! Saving to " << outputfilename); } // Make new outputfile TFile *outputfile; if (procchunk == -1) outputfile = new TFile(outputfilename.c_str(), "RECREATE"); else outputfile = new TFile( (outputfilename + std::string(Form(".coeffchunk_%d.root", procchunk))) .c_str(), "RECREATE"); outputfile->cd(); // Get Weights File TFile *weightsfile = new TFile((outputfilename + ".weights.root").c_str(), "READ"); TTree *weighttree = (TTree *)weightsfile->Get("weight_tree"); // Get SPLWRite Info // splwrite->ReadWeightsFromTree(weighttree); int nevents = weighttree->GetEntries(); // int countwidth = (nevents / 1000); int nweights = splwrite->GetNWeights(); int npar = splwrite->GetNPars(); // Access Weights double *eventweights = new double[nweights]; weighttree->SetBranchAddress("SplineWeights", eventweights); // Make counter // int lasttime = time(NULL); // Setup Splines To Be Saved into TTree outputfile->cd(); TTree *splinetree = new TTree("spline_tree", "spline_tree"); float *coeff = new float[npar]; splinetree->Branch("SplineCoeff", coeff, Form("SplineCoeff[%d]/F", npar)); // Load N Chunks of the Weights into Memory // Split into N processing chunks int nchunks = FitPar::Config().GetParI("spline_chunks"); if (nchunks <= 0) nchunks = 1; if (nchunks >= nevents / 2) nchunks = nevents / 2; std::cout << "Starting NChunks " << nchunks << std::endl; sleep(1); for (int ichunk = 0; ichunk < nchunks; ichunk++) { // Skip to only do one processing chunk if (procchunk != -1 and procchunk != ichunk) continue; NUIS_LOG(FIT, "On Processing Chunk " << ichunk); int neventsinchunk = nevents / nchunks; int loweventinchunk = neventsinchunk * ichunk; // int higheventinchunk = neventsinchunk * (ichunk + 1); // Build Chunk Containers for Event Weights double **weightcont = new double *[nevents]; float **allcoeff = new float *[nevents]; // Load Chunks into Containers for (int k = 0; k < neventsinchunk; k++) { weighttree->GetEntry(loweventinchunk + k); weightcont[k] = new double[nweights]; allcoeff[k] = new float[npar]; bool hasresponse = false; for (int j = 0; j < nweights; j++) { weightcont[k][j] = eventweights[j]; if (eventweights[j] != 1.0) hasresponse = true; } if (!hasresponse) delete weightcont[k]; } // Loop over ncores and process chunks // #pragma omp parallel for num_threads(ncores) for (int k = 0; k < neventsinchunk; k++) { if (weightcont[k]) { splwriterlist[int(omp_get_thread_num())]->FitSplinesForEvent( weightcont[k], allcoeff[k]); } else { for (int j = 0; j < npar; j++) { allcoeff[k][j] = float(0.0); } } if (k + loweventinchunk % 500 == 0) { if (LOG_LEVEL(REC)) { printf("Using Thread %d to build event %d in chunk %d \n", int(omp_get_thread_num()), (int)loweventinchunk + k, ichunk); } } } // Save Coeff To Tree std::cout << "Saving coeffs to Tree in Chunk " << ichunk << std::endl; for (int k = 0; k < neventsinchunk; k++) { for (int l = 0; l < npar; l++) { coeff[l] = allcoeff[k][l]; } // std::cout << "Coeff 0, 1, 2 = " << coeff[0] << " " << coeff[1] << " " // << coeff[2] << std::endl; splinetree->Fill(); } // Delete the container. for (int k = 0; k < neventsinchunk; k++) { if (weightcont[k]) delete weightcont[k]; if (allcoeff[k]) delete allcoeff[k]; } delete allcoeff; delete weightcont; } // Save flux and close file outputfile->cd(); splinetree->Write(); if (procchunk == -1 or procchunk == 0) { outputfile->cd(); splwrite->Write("spline_reader"); TTree *nuisanceevents = (TTree *)weightsfile->Get("nuisance_events"); nuisanceevents->CloneTree()->Write(); weighttree->CloneTree()->Write(); TH1D *nuisance_fluxhist = (TH1D *)weightsfile->Get("nuisance_fluxhist"); TH1D *nuisance_eventhist = (TH1D *)weightsfile->Get("nuisance_eventhist"); nuisance_fluxhist->Write("nuisance_fluxhist"); nuisance_eventhist->Write("nuisance_eventhist"); } weightsfile->Close(); - // Add option to build seperate chunks + // Add option to build separate chunks // Close Output outputfile->Close(); } // remove Keys eventkeys.clear(); } void SplineRoutines::MergeEventSplinesChunks() { if (fRW) delete fRW; SetupRWEngine(); // Setup the spline reader SplineWriter *splwrite = new SplineWriter(fRW); std::vector splinekeys = Config::QueryKeys("spline"); // Add splines to splinewriter for (std::vector::iterator iter = splinekeys.begin(); iter != splinekeys.end(); iter++) { nuiskey splkey = (*iter); // Add Spline Info To Reader splwrite->AddSpline(splkey); } splwrite->SetupSplineSet(); std::vector eventkeys = Config::QueryKeys("events"); for (size_t i = 0; i < eventkeys.size(); i++) { nuiskey key = eventkeys.at(i); // Get I/O std::string inputfilename = key.GetS("input"); if (inputfilename.empty()) { NUIS_ABORT("No input given for set of input events!"); } std::string outputfilename = key.GetS("output"); if (outputfilename.empty()) { outputfilename = inputfilename + ".nuisance.root"; NUIS_ERR(WRN, "No output give for set of output events! Saving to " << outputfilename); } // Make new outputfile TFile *outputfile = new TFile(outputfilename.c_str(), "RECREATE"); outputfile->cd(); // Get Weights File TFile *weightsfile = new TFile((outputfilename + ".weights.root").c_str(), "READ"); TTree *weighttree = (TTree *)weightsfile->Get("weight_tree"); // Get SPLWRite Info // splwrite->ReadWeightsFromTree(weighttree); int nevents = weighttree->GetEntries(); // int countwidth = (nevents / 1000); // int nweights = splwrite->GetNWeights(); int npar = splwrite->GetNPars(); // Make counter // int lasttime = time(NULL); // Setup Splines To Be Saved into TTree outputfile->cd(); TTree *splinetree = new TTree("spline_tree", "spline_tree"); float *coeff = new float[npar]; splinetree->Branch("SplineCoeff", coeff, Form("SplineCoeff[%d]/F", npar)); // Load N Chunks of the Weights into Memory // Split into N processing chunks int nchunks = FitPar::Config().GetParI("spline_chunks"); if (nchunks <= 0) nchunks = 1; if (nchunks >= nevents / 2) nchunks = nevents / 2; int neventsinchunk = nevents / nchunks; for (int ichunk = 0; ichunk < nchunks; ichunk++) { // Get Output File TFile *chunkfile = new TFile( (outputfilename + std::string(Form(".coeffchunk_%d.root", ichunk))) .c_str()); // Get TTree for spline coeffchunk TTree *splinetreechunk = (TTree *)chunkfile->Get("spline_tree"); // Set Branch Address to coeffchunk float *coeffchunk = new float[npar]; splinetreechunk->SetBranchAddress("SplineCoeff", coeffchunk); // Loop over nevents in chunk for (int k = 0; k < neventsinchunk; k++) { splinetreechunk->GetEntry(k); for (int j = 0; j < npar; j++) { coeff[j] = coeffchunk[j]; } splinetree->Fill(); } // Close up chunkfile->Close(); delete coeffchunk; std::cout << "Merged chunk " << ichunk << std::endl; } // Save flux and close file outputfile->cd(); splinetree->Write(); outputfile->cd(); splwrite->Write("spline_reader"); TTree *nuisanceevents = (TTree *)weightsfile->Get("nuisance_events"); nuisanceevents->CloneTree()->Write(); weighttree->CloneTree()->Write(); TH1D *nuisance_fluxhist = (TH1D *)weightsfile->Get("nuisance_fluxhist"); TH1D *nuisance_eventhist = (TH1D *)weightsfile->Get("nuisance_eventhist"); nuisance_fluxhist->Write("nuisance_fluxhist"); nuisance_eventhist->Write("nuisance_eventhist"); weightsfile->Close(); - // Add option to build seperate chunks + // Add option to build separate chunks // Close Output outputfile->Close(); } // remove Keys eventkeys.clear(); } // void SplineRoutines::BuildSplineChunk(){ //} // void SplineRoutines::MergeSplineChunks(){ //} //************************************* void SplineRoutines::MergeSplines() { //************************************* // Loop over all 'splinemerge' keys. // Add them to the Merger. // Call setup splines. // Get the key with eventinput // - remaining keys should have splineinput // - Loop over number of entries. // - FillEntry in merger. // - Fill NUISANCEEvent into a new TTree. SplineMerger *splmerge = new SplineMerger(); std::vector splinekeys = Config::QueryKeys("splinemerge"); for (std::vector::iterator iter = splinekeys.begin(); iter != splinekeys.end(); iter++) { nuiskey splkey = (*iter); TFile *infile = new TFile(splkey.GetS("input").c_str(), "READ"); splmerge->AddSplineSetFromFile(infile); } splmerge->SetupSplineSet(); // Now get Event File std::vector eventkeys = Config::QueryKeys("eventmerge"); nuiskey key = eventkeys[0]; std::string inputfilename = key.GetS("input"); // Make a new input handler std::vector file_descriptor = GeneralUtils::ParseToStr(inputfilename, ":"); if (file_descriptor.size() != 2) { NUIS_ABORT("File descriptor had no filetype declaration: \"" << inputfilename << "\". expected \"FILETYPE:file.root\""); } InputUtils::InputType inptype = InputUtils::ParseInputType(file_descriptor[0]); InputHandlerBase *input = InputUtils::CreateInputHandler("eventsaver", inptype, file_descriptor[1]); std::string outputfilename = key.GetS("output"); if (outputfilename.empty()) { outputfilename = inputfilename + ".nuisance.root"; NUIS_ERR(WRN, "No output give for set of output events! Saving to " << outputfilename); } // Make new outputfile TFile *outputfile = new TFile(outputfilename.c_str(), "RECREATE"); outputfile->cd(); // Get info from inputhandler int nevents = input->GetNEvents(); int countwidth = (nevents / 1000); FitEvent *nuisevent = input->FirstNuisanceEvent(); // Setup a TTree to save the event outputfile->cd(); TTree *eventtree = new TTree("nuisance_events", "nuisance_events"); // Add a flag that allows just splines to be saved. nuisevent->AddBranchesToTree(eventtree); // Save the spline reader splmerge->Write("spline_reader"); // Setup the spline TTree TTree *splinetree = new TTree("spline_tree", "spline_tree"); splmerge->AddCoefficientsToTree(splinetree); int lasttime = time(NULL); int i = 0; // Loop over all events and fill the TTree while (nuisevent) { // Calculate the weights for each parameter set splmerge->FillMergedSplines(i); // Save everything eventtree->Fill(); splinetree->Fill(); // Logging if (i % countwidth == 0) { std::ostringstream timestring; int timeelapsed = time(NULL) - lasttime; if (i != 0 and timeelapsed) { lasttime = time(NULL); int eventsleft = nevents - i; float speed = float(countwidth) / float(timeelapsed); float proj = (float(eventsleft) / float(speed)) / 60 / 60; timestring << proj << " hours remaining."; } NUIS_LOG(REC, "Saved " << i << "/" << nevents << " nuisance spline events. " << timestring.str()); } // Iterate i++; nuisevent = input->NextNuisanceEvent(); } // Save flux and close file outputfile->cd(); eventtree->Write(); splinetree->Write(); input->GetFluxHistogram()->Write("nuisance_fluxhist"); input->GetEventHistogram()->Write("nuisance_eventhist"); // Close Output outputfile->Close(); // Delete Inputs delete input; } //************************************* void SplineRoutines::TestSplines_1DEventScan() { //************************************* // Setup RW Engine if (fRW) delete fRW; SetupRWEngine(); // Make a spline RW Engine too. FitWeight *splweight = new FitWeight("splinerwaweight"); // std::vector splinekeys = Config::QueryKeys("spline"); std::vector parameterkeys = Config::QueryKeys("parameter"); TH1D *parhisttemplate = new TH1D("parhist", "parhist", parameterkeys.size(), 0.0, float(parameterkeys.size())); // Add Parameters for (size_t i = 0; i < parameterkeys.size(); i++) { nuiskey key = parameterkeys[i]; std::string parname = key.GetS("name"); std::string partype = key.GetS("type"); double nom = key.GetD("nominal"); parhisttemplate->SetBinContent(i + 1, nom); parhisttemplate->GetXaxis()->SetBinLabel(i + 1, parname.c_str()); splweight->IncludeDial(key.GetS("name"), kSPLINEPARAMETER, nom); splweight->SetDialValue(key.GetS("name"), key.GetD("nominal")); } splweight->Reconfigure(); // Make a high resolution spline set. std::vector nomvals = fRW->GetDialValues(); // int testres = FitPar::Config().GetParI("spline_test_resolution"); std::vector > scanparset_vals; std::vector scanparset_hists; // Loop over all params // Add Parameters for (size_t i = 0; i < parameterkeys.size(); i++) { nuiskey key = parameterkeys[i]; // Get Par Name std::string name = key.GetS("name"); if (!key.Has("low") or !key.Has("high") or !key.Has("step")) { continue; } // Push Back Scan double low = key.GetD("low"); double high = key.GetD("high"); double cur = low; double step = key.GetD("step"); while (cur <= high) { // Make new set std::vector newvals = nomvals; newvals[i] = cur; // Add to vects scanparset_vals.push_back(newvals); TH1D *parhist = (TH1D *)parhisttemplate->Clone(); for (size_t j = 0; j < newvals.size(); j++) { parhist->SetBinContent(j + 1, newvals[j]); } scanparset_hists.push_back(parhist); // Move to next one cur += step; } } // Print out the parameter set to test for (uint i = 0; i < scanparset_vals.size(); i++) { std::cout << "Parset " << i; for (uint j = 0; j < scanparset_vals[i].size(); j++) { std::cout << " " << scanparset_vals[i][j]; } std::cout << std::endl; } // Weight holders double *rawweights = new double[scanparset_vals.size()]; double *splweights = new double[scanparset_vals.size()]; double *difweights = new double[scanparset_vals.size()]; int nweights = scanparset_vals.size(); // int NParSets = scanparset_vals.size(); // Loop over all event I/O std::vector eventkeys = Config::QueryKeys("events"); for (size_t i = 0; i < eventkeys.size(); i++) { nuiskey key = eventkeys.at(i); // Get I/O std::string inputfilename = key.GetS("input"); if (inputfilename.empty()) { NUIS_ABORT("No input given for set of input events!") } std::string outputfilename = key.GetS("output"); if (outputfilename.empty()) { outputfilename = inputfilename + ".nuisance.root"; NUIS_ERR(WRN, "No output give for set of output events! Saving to " << outputfilename); } // Make a new input handler std::vector file_descriptor = GeneralUtils::ParseToStr(inputfilename, ":"); if (file_descriptor.size() != 2) { NUIS_ABORT("File descriptor had no filetype declaration: \"" << inputfilename << "\". expected \"FILETYPE:file.root\""); } InputUtils::InputType inptype = InputUtils::ParseInputType(file_descriptor[0]); // Make handlers for input and output InputHandlerBase *input = InputUtils::CreateInputHandler( "rawevents", inptype, file_descriptor[1]); InputHandlerBase *output = InputUtils::CreateInputHandler( "splineevents", InputUtils::kEVSPLN_Input, outputfilename); // Get Base Events for each case. FitEvent *rawevent = input->FirstNuisanceEvent(); FitEvent *splevent = output->FirstNuisanceEvent(); // Setup outputfile std::string outputtest = outputfilename + ".splinetest.1DEventScan.root"; TFile *outputtestfile = new TFile(outputtest.c_str(), "RECREATE"); outputtestfile->cd(); // Save Parameter Sets for (size_t i = 0; i < scanparset_hists.size(); i++) { scanparset_hists[i]->Write(Form("Paramater_Set_%i", (int)i)); } // Save a TTree of weights and differences. TTree *weighttree = new TTree("weightscan", "weightscan"); // Make a branch for each weight set for (size_t i = 0; i < scanparset_hists.size(); i++) { weighttree->Branch(Form("RawWeights_Set_%i", (int)i), &rawweights[i], Form("RawWeights_Set_%i/D", (int)i)); weighttree->Branch(Form("SplineWeights_Set_%i", (int)i), &splweights[i], Form("SplineWeights_Set_%i/D", (int)i)); weighttree->Branch(Form("DifWeights_Set_%i", (int)i), &difweights[i], Form("DifWeights_Set_%i/D", (int)i)); } // Count // int i = 0; int nevents = input->GetNEvents(); int lasttime = time(NULL); // Load N Chunks of the Weights into Memory // Split into N processing chunks int nchunks = FitPar::Config().GetParI("spline_chunks"); if (nchunks <= 0) nchunks = 1; if (nchunks >= nevents / 2) nchunks = nevents / 2; std::cout << "Starting NChunks " << nchunks << std::endl; for (int ichunk = 0; ichunk < nchunks; ichunk++) { // Skip to only do one processing chunk // if (procchunk != -1 and procchunk != ichunk) continue; NUIS_LOG(FIT, "On Processing Chunk " << ichunk); int neventsinchunk = nevents / nchunks; int loweventinchunk = neventsinchunk * ichunk; // int higheventinchunk = neventsinchunk * (ichunk + 1); double **allrawweights = new double *[neventsinchunk]; double **allsplweights = new double *[neventsinchunk]; double **alldifweights = new double *[neventsinchunk]; for (int k = 0; k < neventsinchunk; k++) { allrawweights[k] = new double[nweights]; allsplweights[k] = new double[nweights]; alldifweights[k] = new double[nweights]; } // Start Set Processing Here. for (int iset = 0; iset < nweights; iset++) { // Reconfigure fRW->SetAllDials(&scanparset_vals[iset][0], scanparset_vals[iset].size()); fRW->Reconfigure(); // Reconfigure spline RW splweight->SetAllDials(&scanparset_vals[iset][0], scanparset_vals[iset].size()); splweight->Reconfigure(); splevent->fSplineRead->SetNeedsReconfigure(true); // Could reorder this to save the weightconts in order instead of // reconfiguring per event. Loop over all events and fill the TTree for (int i = 0; i < neventsinchunk; i++) { rawevent = input->GetNuisanceEvent(i + loweventinchunk); splevent = output->GetNuisanceEvent(i + loweventinchunk); allrawweights[i][iset] = fRW->CalcWeight(rawevent); allsplweights[i][iset] = splweight->CalcWeight(splevent); alldifweights[i][iset] = allsplweights[i][iset] - allrawweights[i][iset]; } std::ostringstream timestring; int timeelapsed = time(NULL) - lasttime; if (timeelapsed) { lasttime = time(NULL); int setsleft = (nweights - iset - 1) + (nweights * (nchunks - ichunk - 1)); float proj = (float(setsleft) * timeelapsed) / 60 / 60; timestring << setsleft << " sets remaining. Last one took " << timeelapsed << ". " << proj << " hours remaining."; } NUIS_LOG(REC, "Processed Set " << iset << "/" << nweights << " in chunk " << ichunk << "/" << nchunks << " " << timestring.str()); } // Fill weights for this chunk into the TTree for (int k = 0; k < neventsinchunk; k++) { for (int l = 0; l < nweights; l++) { rawweights[l] = allrawweights[k][l]; splweights[l] = allsplweights[k][l]; difweights[l] = alldifweights[k][l]; } weighttree->Fill(); } } // Loop over nchunks // Loop over parameter sets // Set All Dials and reconfigure // Loop over events in chunk // Fill Chunkweightcontainers // Once all dials are done, fill the weight tree // Iterator to next chunk outputtestfile->cd(); weighttree->Write(); outputtestfile->Close(); } } /* // Make a high resolution spline set. std::vector nomvals = fRW->GetDialValues(); int testres = FitPar::Config().GetParI("spline_test_resolution"); std::vector< std::vector > scanparset_vals; std::vector< TH1D* > scanparset_hists; // Loop over all params // Add Parameters for (size_t i = 0; i < parameterkeys.size(); i++) { nuiskey key = parameterkeys[i]; // Get Par Name std::string name = key.GetS("name"); if (!key.Has("low") or !key.Has("high") or !key.Has("step")) { continue; } // Push Back Scan double low = key.GetD("low"); double high = key.GetD("high"); double cur = low; double step = key.GetD("step"); while (cur <= high) { // Make new set std::vector newvals = nomvals; newvals[i] = cur; // Add to vects scanparset_vals.push_back(newvals); TH1D* parhist = (TH1D*)parhisttemplate->Clone(); for (size_t j = 0; j < newvals.size(); j++) { parhist->SetBinContent(j + 1, newvals[j]); } scanparset_hists.push_back(parhist); // Move to next one cur += step; } } // Print out the parameter set to test for (int i = 0; i < scanparset_vals.size(); i++) { std::cout << "Parset " << i; for (int j = 0 ; j < scanparset_vals[i].size(); j++) { std::cout << " " << scanparset_vals[i][j]; } std::cout << std::endl; } // Weight holders double* rawweights = new double[scanparset_vals.size()]; double* splweights = new double[scanparset_vals.size()]; double* difweights = new double[scanparset_vals.size()]; int NParSets = scanparset_vals.size(); // Loop over all event I/O std::vector eventkeys = Config::QueryKeys("events"); for (size_t i = 0; i < eventkeys.size(); i++) { nuiskey key = eventkeys.at(i); // Get I/O std::string inputfilename = key.GetS("input"); if (inputfilename.empty()) { ERR(FTL) << "No input given for set of input events!" << std::endl; throw; } std::string outputfilename = key.GetS("output"); if (outputfilename.empty()) { outputfilename = inputfilename + ".nuisance.root"; ERR(FTL) << "No output give for set of output events! Saving to " << outputfilename << std::endl; } // Make a new input handler std::vector file_descriptor = GeneralUtils::ParseToStr(inputfilename, ":"); if (file_descriptor.size() != 2) { ERR(FTL) << "File descriptor had no filetype declaration: \"" << inputfilename << "\". expected \"FILETYPE:file.root\"" << std::endl; throw; } InputUtils::InputType inptype = InputUtils::ParseInputType(file_descriptor[0]); // Make handlers for input and output InputHandlerBase* input = InputUtils::CreateInputHandler("rawevents", inptype, file_descriptor[1]); InputHandlerBase* output = InputUtils::CreateInputHandler("splineevents", InputUtils::kEVSPLN_Input, outputfilename); // Get Base Events for each case. FitEvent* rawevent = input->FirstNuisanceEvent(); FitEvent* splevent = output->FirstNuisanceEvent(); // Setup outputfile std::string outputtest = outputfilename + ".splinetest.1DEventScan.root"; TFile* outputtestfile = new TFile(outputtest.c_str(), "RECREATE"); outputtestfile->cd(); // Save Parameter Sets for (size_t i = 0; i < scanparset_hists.size(); i++) { scanparset_hists[i]->Write(Form("Paramater_Set_%i", (int)i)); } // Save a TTree of weights and differences. TTree* weighttree = new TTree("weightscan", "weightscan"); // Make a branch for each weight set for (size_t i = 0; i < scanparset_hists.size(); i++) { weighttree->Branch(Form("RawWeights_Set_%i", (int)i), &rawweights[i], Form("RawWeights_Set_%i/D", (int)i) ); weighttree->Branch(Form("SplineWeights_Set_%i", (int)i), &splweights[i], Form("SplineWeights_Set_%i/D", (int)i) ); weighttree->Branch(Form("DifWeights_Set_%i", (int)i), &difweights[i], Form("DifWeights_Set_%i/D", (int)i) ); } // Count int i = 0; int nevents = input->GetNEvents(); while (rawevent and splevent) { // Loop over 1D parameter sets. for (size_t j = 0; j < scanparset_vals.size(); j++) { // Reconfigure fRW->SetAllDials(&scanparset_vals[j][0], scanparset_vals[j].size()); fRW->Reconfigure(); // Reconfigure spline RW splweight->SetAllDials(&scanparset_vals[j][0], scanparset_vals[j].size()); splweight->Reconfigure(); splevent->fSplineRead->SetNeedsReconfigure(true); // Calc weight for both events rawweights[j] = fRW->CalcWeight(rawevent); splweights[j] = splweight->CalcWeight(splevent); difweights[j] = splweights[j] - rawweights[j]; } if (i % 1000 == 0) { LOG(FIT) << "Processed " << i << "/" << nevents << std::endl; } // Fill Array weighttree->Fill(); // Iterate to next event. i++; rawevent = input->NextNuisanceEvent(); splevent = output->NextNuisanceEvent(); } outputtestfile->cd(); weighttree->Write(); outputtestfile->Close(); } } */ //************************************* void SplineRoutines::TestSplines_NDEventThrow() { //************************************* // Setup RW Engine if (fRW) delete fRW; SetupRWEngine(); // Make a spline RW Engine too. FitWeight *splweight = new FitWeight("splinerwaweight"); std::vector parameterkeys = Config::QueryKeys("parameter"); TH1D *parhisttemplate = new TH1D("parhist", "parhist", parameterkeys.size(), 0.0, float(parameterkeys.size())); // Add Parameters for (size_t i = 0; i < parameterkeys.size(); i++) { nuiskey key = parameterkeys[i]; std::string parname = key.GetS("name"); std::string partype = key.GetS("type"); double nom = key.GetD("nominal"); parhisttemplate->SetBinContent(i + 1, nom); parhisttemplate->GetXaxis()->SetBinLabel(i + 1, parname.c_str()); splweight->IncludeDial(key.GetS("name"), kSPLINEPARAMETER, nom); splweight->SetDialValue(key.GetS("name"), key.GetD("nominal")); } splweight->Reconfigure(); // Make a high resolution spline set. std::vector nomvals = fRW->GetDialValues(); // int testres = FitPar::Config().GetParI("spline_test_resolution"); std::vector scanparset_names; std::vector > scanparset_vals; std::vector scanparset_hists; // Loop over all params // Add Parameters int nthrows = FitPar::Config().GetParI("spline_test_throws"); for (int i = 0; i < nthrows; i++) { std::vector newvals = nomvals; for (size_t j = 0; j < parameterkeys.size(); j++) { nuiskey key = parameterkeys[j]; if (!key.Has("low") or !key.Has("high") or !key.Has("step")) { continue; } // Push Back Scan double low = key.GetD("low"); double high = key.GetD("high"); newvals[j] = gRandom->Uniform(low, high); } // Add to vects scanparset_vals.push_back(newvals); TH1D *parhist = (TH1D *)parhisttemplate->Clone(); for (size_t j = 0; j < newvals.size(); j++) { parhist->SetBinContent(j + 1, newvals[j]); } scanparset_hists.push_back(parhist); } // Print out the parameter set to test for (uint i = 0; i < scanparset_vals.size(); i++) { std::cout << "Parset " << i; for (uint j = 0; j < scanparset_vals[i].size(); j++) { std::cout << " " << scanparset_vals[i][j]; } std::cout << std::endl; } // Weight holders double *rawweights = new double[scanparset_vals.size()]; double *splweights = new double[scanparset_vals.size()]; double *difweights = new double[scanparset_vals.size()]; int nweights = scanparset_vals.size(); // int NParSets = scanparset_vals.size(); // Loop over all event I/O std::vector eventkeys = Config::QueryKeys("events"); for (size_t i = 0; i < eventkeys.size(); i++) { nuiskey key = eventkeys.at(i); // Get I/O std::string inputfilename = key.GetS("input"); if (inputfilename.empty()) { NUIS_ABORT("No input given for set of input events!"); } std::string outputfilename = key.GetS("output"); if (outputfilename.empty()) { outputfilename = inputfilename + ".nuisance.root"; NUIS_ERR(WRN, "No output give for set of output events! Saving to " << outputfilename); } // Make a new input handler std::vector file_descriptor = GeneralUtils::ParseToStr(inputfilename, ":"); if (file_descriptor.size() != 2) { NUIS_ABORT("File descriptor had no filetype declaration: \"" << inputfilename << "\". expected \"FILETYPE:file.root\""); } InputUtils::InputType inptype = InputUtils::ParseInputType(file_descriptor[0]); // Make handlers for input and output InputHandlerBase *input = InputUtils::CreateInputHandler( "rawevents", inptype, file_descriptor[1]); InputHandlerBase *output = InputUtils::CreateInputHandler( "splineevents", InputUtils::kEVSPLN_Input, outputfilename); // Get Base Events for each case. FitEvent *rawevent = input->FirstNuisanceEvent(); FitEvent *splevent = output->FirstNuisanceEvent(); // Setup outputfile std::string outputtest = outputfilename + ".splinetest.NDEventThrow.root"; TFile *outputtestfile = new TFile(outputtest.c_str(), "RECREATE"); outputtestfile->cd(); // Save Parameter Sets for (size_t i = 0; i < scanparset_hists.size(); i++) { scanparset_hists[i]->Write(Form("Paramater_Set_%i", (int)i)); } // Save a TTree of weights and differences. TTree *weighttree = new TTree("weightscan", "weightscan"); // Make a branch for each weight set for (size_t i = 0; i < scanparset_hists.size(); i++) { weighttree->Branch(Form("RawWeights_Set_%i", (int)i), &rawweights[i], Form("RawWeights_Set_%i/D", (int)i)); weighttree->Branch(Form("SplineWeights_Set_%i", (int)i), &splweights[i], Form("SplineWeights_Set_%i/D", (int)i)); weighttree->Branch(Form("DifWeights_Set_%i", (int)i), &difweights[i], Form("DifWeights_Set_%i/D", (int)i)); } // Count // int i = 0; int nevents = input->GetNEvents(); int lasttime = time(NULL); // Load N Chunks of the Weights into Memory // Split into N processing chunks int nchunks = FitPar::Config().GetParI("spline_chunks"); if (nchunks <= 0) nchunks = 1; if (nchunks >= nevents / 2) nchunks = nevents / 2; std::cout << "Starting NChunks " << nchunks << std::endl; for (int ichunk = 0; ichunk < nchunks; ichunk++) { // Skip to only do one processing chunk // if (procchunk != -1 and procchunk != ichunk) continue; NUIS_LOG(FIT, "On Processing Chunk " << ichunk); int neventsinchunk = nevents / nchunks; int loweventinchunk = neventsinchunk * ichunk; // int higheventinchunk = neventsinchunk * (ichunk + 1); double **allrawweights = new double *[neventsinchunk]; double **allsplweights = new double *[neventsinchunk]; double **alldifweights = new double *[neventsinchunk]; for (int k = 0; k < neventsinchunk; k++) { allrawweights[k] = new double[nweights]; allsplweights[k] = new double[nweights]; alldifweights[k] = new double[nweights]; } // Start Set Processing Here. for (int iset = 0; iset < nweights; iset++) { // Reconfigure fRW->SetAllDials(&scanparset_vals[iset][0], scanparset_vals[iset].size()); fRW->Reconfigure(); // Reconfigure spline RW splweight->SetAllDials(&scanparset_vals[iset][0], scanparset_vals[iset].size()); splweight->Reconfigure(); splevent->fSplineRead->SetNeedsReconfigure(true); // Could reorder this to save the weightconts in order instead of // reconfiguring per event. Loop over all events and fill the TTree for (int i = 0; i < neventsinchunk; i++) { rawevent = input->GetNuisanceEvent(i + loweventinchunk); splevent = output->GetNuisanceEvent(i + loweventinchunk); allrawweights[i][iset] = fRW->CalcWeight(rawevent); allsplweights[i][iset] = splweight->CalcWeight(splevent); alldifweights[i][iset] = allsplweights[i][iset] - allrawweights[i][iset]; } std::ostringstream timestring; int timeelapsed = time(NULL) - lasttime; if (timeelapsed) { lasttime = time(NULL); int setsleft = (nweights - iset - 1) + (nweights * (nchunks - ichunk - 1)); float proj = (float(setsleft) * timeelapsed) / 60 / 60; timestring << setsleft << " sets remaining. Last one took " << timeelapsed << ". " << proj << " hours remaining."; } NUIS_LOG(REC, "Processed Set " << iset << "/" << nweights << " in chunk " << ichunk << "/" << nchunks << " " << timestring.str()); } // Fill weights for this chunk into the TTree for (int k = 0; k < neventsinchunk; k++) { for (int l = 0; l < nweights; l++) { rawweights[l] = allrawweights[k][l]; splweights[l] = allsplweights[k][l]; difweights[l] = alldifweights[k][l]; } weighttree->Fill(); } } // Loop over nchunks // Loop over parameter sets // Set All Dials and reconfigure // Loop over events in chunk // Fill Chunkweightcontainers // Once all dials are done, fill the weight tree // Iterator to next chunk outputtestfile->cd(); weighttree->Write(); outputtestfile->Close(); } } void SplineRoutines::SaveSplinePlots() { if (fRW) delete fRW; SetupRWEngine(); // Setup the spline reader SplineWriter *splwrite = new SplineWriter(fRW); std::vector splinekeys = Config::QueryKeys("spline"); // Add splines to splinewriter for (std::vector::iterator iter = splinekeys.begin(); iter != splinekeys.end(); iter++) { nuiskey splkey = (*iter); // Add Spline Info To Reader splwrite->AddSpline(splkey); } splwrite->SetupSplineSet(); // Event Loop // Loop over all events and calculate weights for each parameter set. // Generate a set of nominal events // Method, Loop over inputs, create input handler, then create a ttree std::vector eventkeys = Config::QueryKeys("events"); for (size_t i = 0; i < eventkeys.size(); i++) { nuiskey key = eventkeys.at(i); // Get I/O std::string inputfilename = key.GetS("input"); if (inputfilename.empty()) { NUIS_ABORT("No input given for set of input events!"); } std::string outputfilename = key.GetS("output"); if (outputfilename.empty()) { outputfilename = inputfilename + ".nuisance.root"; NUIS_ERR(WRN, "No output give for set of output events! Saving to " << outputfilename); } // Make new outputfile outputfilename += ".SplinePlots.root"; TFile *outputfile = new TFile(outputfilename.c_str(), "RECREATE"); outputfile->cd(); // Make a new input handler std::vector file_descriptor = GeneralUtils::ParseToStr(inputfilename, ":"); if (file_descriptor.size() != 2) { NUIS_ABORT("File descriptor had no filetype declaration: \"" << inputfilename << "\". expected \"FILETYPE:file.root\""); } InputUtils::InputType inptype = InputUtils::ParseInputType(file_descriptor[0]); InputHandlerBase *input = InputUtils::CreateInputHandler( "eventsaver", inptype, file_descriptor[1]); // Get info from inputhandler int nevents = input->GetNEvents(); int countwidth = (nevents / 1000); FitEvent *nuisevent = input->FirstNuisanceEvent(); outputfile->cd(); // int lasttime = time(NULL); TCanvas *fitcanvas = NULL; // Loop over all events and fill the TTree while (nuisevent) { // std::cout << "Fitting event " << i << std::endl; // Calculate the weights for each parameter set splwrite->GetWeightsForEvent(nuisevent); splwrite->FitSplinesForEvent(fitcanvas, true); if (fitcanvas) { outputfile->cd(); fitcanvas->Write(Form("Event_SplineCanvas_%i", (int)i)); } // Logging if (i % countwidth == 0) { NUIS_LOG(REC, "Saved " << i << "/" << nevents << " nuisance spline plots. "); } // Iterate i++; nuisevent = input->NextNuisanceEvent(); } // Save flux and close file outputfile->cd(); // Close Output outputfile->Close(); // Delete Inputs delete input; } // remove Keys eventkeys.clear(); } void SplineRoutines::TestSplines_NDLikelihoodThrow() { // Setup RW Engine if (fRW) delete fRW; SetupRWEngine(); // Make a spline RW Engine too. FitWeight *splweight = new FitWeight("splinerwaweight"); std::vector parameterkeys = Config::QueryKeys("parameter"); TH1D *parhisttemplate = new TH1D("parhist", "parhist", parameterkeys.size(), 0.0, float(parameterkeys.size())); // Add Parameters for (size_t i = 0; i < parameterkeys.size(); i++) { nuiskey key = parameterkeys[i]; std::string parname = key.GetS("name"); std::string partype = key.GetS("type"); double nom = key.GetD("nominal"); parhisttemplate->SetBinContent(i + 1, nom); parhisttemplate->GetXaxis()->SetBinLabel(i + 1, parname.c_str()); splweight->IncludeDial(key.GetS("name"), kSPLINEPARAMETER, nom); splweight->SetDialValue(key.GetS("name"), key.GetD("nominal")); } splweight->Reconfigure(); // Make a high resolution spline set. std::vector nomvals = fRW->GetDialValues(); // int testres = FitPar::Config().GetParI("spline_test_resolution"); std::vector scanparset_names; std::vector > scanparset_vals; std::vector scanparset_hists; // Loop over all params // Add Parameters int nthrows = FitPar::Config().GetParI("spline_test_throws"); for (int i = 0; i < nthrows; i++) { std::vector newvals = nomvals; for (size_t j = 0; j < parameterkeys.size(); j++) { nuiskey key = parameterkeys[j]; if (!key.Has("low") or !key.Has("high") or !key.Has("step")) { continue; } // Push Back Scan double low = key.GetD("low"); double high = key.GetD("high"); newvals[j] = gRandom->Uniform(low, high); } // Add to vects scanparset_vals.push_back(newvals); TH1D *parhist = (TH1D *)parhisttemplate->Clone(); for (size_t j = 0; j < newvals.size(); j++) { parhist->SetBinContent(j + 1, newvals[j]); } scanparset_hists.push_back(parhist); } // Print out the parameter set to test for (uint i = 0; i < scanparset_vals.size(); i++) { std::cout << "Parset " << i; for (uint j = 0; j < scanparset_vals[i].size(); j++) { std::cout << " " << scanparset_vals[i][j]; } std::cout << std::endl; } // Make a new set of Raw/Spline Sample Keys std::vector eventkeys = Config::QueryKeys("events"); std::vector testkeys = Config::QueryKeys("sampletest"); std::vector rawkeys; std::vector splkeys; for (std::vector::iterator iter = testkeys.begin(); iter != testkeys.end(); iter++) { nuiskey key = (*iter); std::string samplename = key.GetS("name"); std::string eventsid = key.GetS("inputid"); nuiskey eventskey = Config::QueryLastKey("events", "id=" + eventsid); std::string rawfile = eventskey.GetS("input"); std::string splfile = eventskey.GetS("output"); nuiskey rawkeytemp = Config::CreateKey("sample"); rawkeytemp.SetS("name", samplename); rawkeytemp.SetS("input", rawfile); nuiskey splkeytemp = Config::CreateKey("sample"); splkeytemp.SetS("name", samplename); splkeytemp.SetS("input", "EVSPLN:" + splfile); rawkeys.push_back(rawkeytemp); splkeys.push_back(splkeytemp); } if (fOutputRootFile) delete fOutputRootFile; fOutputRootFile = new TFile(fOutputFile.c_str(), "RECREATE"); fOutputRootFile->ls(); // Make two new JointFCN JointFCN *rawfcn = new JointFCN(rawkeys, fOutputRootFile); JointFCN *splfcn = new JointFCN(splkeys, fOutputRootFile); // Create iteration tree in output file fOutputRootFile->cd(); rawfcn->CreateIterationTree("raw_iterations", fRW); splfcn->CreateIterationTree("spl_iterations", splweight); // Loop over parameter sets. for (size_t j = 0; j < scanparset_vals.size(); j++) { FitBase::SetRW(fRW); double rawtotal = rawfcn->DoEval(&scanparset_vals[j][0]); FitBase::SetRW(splweight); double spltotal = splfcn->DoEval(&scanparset_vals[j][0]); NUIS_LOG(FIT, "RAW SPLINE DIF = " << rawtotal << " " << spltotal << " " << spltotal - rawtotal); } fOutputRootFile->cd(); rawfcn->WriteIterationTree(); splfcn->WriteIterationTree(); } void SplineRoutines::TestSplines_1DLikelihoodScan() { // Setup RW Engine. if (fRW) delete fRW; SetupRWEngine(); // Setup Parameter Set. // Make a spline RW Engine too. FitWeight *splweight = new FitWeight("splinerwaweight"); // std::vector splinekeys = Config::QueryKeys("spline"); std::vector parameterkeys = Config::QueryKeys("parameter"); TH1D *parhisttemplate = new TH1D("parhist", "parhist", parameterkeys.size(), 0.0, float(parameterkeys.size())); // Add Parameters for (size_t i = 0; i < parameterkeys.size(); i++) { nuiskey key = parameterkeys[i]; std::string parname = key.GetS("name"); std::string partype = key.GetS("type"); double nom = key.GetD("nominal"); parhisttemplate->SetBinContent(i + 1, nom); parhisttemplate->GetXaxis()->SetBinLabel(i + 1, parname.c_str()); splweight->IncludeDial(key.GetS("name"), kSPLINEPARAMETER, nom); splweight->SetDialValue(key.GetS("name"), key.GetD("nominal")); } splweight->Reconfigure(); // Make a high resolution spline set. std::vector nomvals = fRW->GetDialValues(); // int testres = FitPar::Config().GetParI("spline_test_resolution"); std::vector > scanparset_vals; std::vector scanparset_hists; // Loop over all params // Add Parameters for (size_t i = 0; i < parameterkeys.size(); i++) { nuiskey key = parameterkeys[i]; // Get Par Name std::string name = key.GetS("name"); if (!key.Has("low") or !key.Has("high") or !key.Has("step")) { continue; } // Push Back Scan double low = key.GetD("low"); double high = key.GetD("high"); double cur = low; double step = key.GetD("step"); while (cur <= high) { // Make new set std::vector newvals = nomvals; newvals[i] = cur; // Add to vects scanparset_vals.push_back(newvals); TH1D *parhist = (TH1D *)parhisttemplate->Clone(); for (size_t j = 0; j < newvals.size(); j++) { parhist->SetBinContent(j + 1, newvals[j]); } scanparset_hists.push_back(parhist); // Move to next one cur += step; } } // Print out the parameter set to test for (uint i = 0; i < scanparset_vals.size(); i++) { std::cout << "Parset " << i; for (uint j = 0; j < scanparset_vals[i].size(); j++) { std::cout << " " << scanparset_vals[i][j]; } std::cout << std::endl; } // Make a new set of Raw/Spline Sample Keys std::vector eventkeys = Config::QueryKeys("events"); std::vector testkeys = Config::QueryKeys("sampletest"); std::vector rawkeys; std::vector splkeys; for (std::vector::iterator iter = testkeys.begin(); iter != testkeys.end(); iter++) { nuiskey key = (*iter); std::string samplename = key.GetS("name"); std::string eventsid = key.GetS("inputid"); nuiskey eventskey = Config::QueryLastKey("events", "id=" + eventsid); std::string rawfile = eventskey.GetS("input"); std::string splfile = eventskey.GetS("output"); nuiskey rawkeytemp = Config::CreateKey("sample"); rawkeytemp.SetS("name", samplename); rawkeytemp.SetS("input", rawfile); nuiskey splkeytemp = Config::CreateKey("sample"); splkeytemp.SetS("name", samplename); splkeytemp.SetS("input", "EVSPLN:" + splfile); rawkeys.push_back(rawkeytemp); splkeys.push_back(splkeytemp); } if (fOutputRootFile) delete fOutputRootFile; fOutputRootFile = new TFile(fOutputFile.c_str(), "RECREATE"); fOutputRootFile->ls(); // Make two new JointFCN JointFCN *rawfcn = new JointFCN(rawkeys, fOutputRootFile); JointFCN *splfcn = new JointFCN(splkeys, fOutputRootFile); // Create iteration tree in output file fOutputRootFile->cd(); rawfcn->CreateIterationTree("raw_iterations", fRW); splfcn->CreateIterationTree("spl_iterations", splweight); // Loop over parameter sets. for (size_t j = 0; j < scanparset_vals.size(); j++) { FitBase::SetRW(fRW); double rawtotal = rawfcn->DoEval(&scanparset_vals[j][0]); FitBase::SetRW(splweight); double spltotal = splfcn->DoEval(&scanparset_vals[j][0]); NUIS_LOG(FIT, "RAW SPLINE DIF = " << rawtotal << " " << spltotal << " " << spltotal - rawtotal); } fOutputRootFile->cd(); rawfcn->WriteIterationTree(); splfcn->WriteIterationTree(); } /* MISC Functions */ //************************************* int SplineRoutines::GetStatus() { //************************************* return 0; } diff --git a/src/Routines/SystematicRoutines.cxx b/src/Routines/SystematicRoutines.cxx index 2c0e39b..2054f24 100755 --- a/src/Routines/SystematicRoutines.cxx +++ b/src/Routines/SystematicRoutines.cxx @@ -1,1488 +1,1490 @@ // 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 "SystematicRoutines.h" void SystematicRoutines::Init() { fInputFile = ""; fInputRootFile = NULL; fOutputFile = ""; fOutputRootFile = NULL; fCovar = fCovarFree = NULL; fCorrel = fCorrelFree = NULL; fDecomp = fDecompFree = NULL; fStrategy = "ErrorBands"; fRoutines.clear(); fRoutines.push_back("ErrorBands"); fCardFile = ""; fFakeDataInput = ""; fSampleFCN = NULL; fAllowedRoutines = ("ErrorBands,PlotLimits"); }; SystematicRoutines::~SystematicRoutines(){}; SystematicRoutines::SystematicRoutines(int argc, char *argv[]) { // Initialise Defaults Init(); nuisconfig configuration = Config::Get(); // Default containers std::string cardfile = ""; std::string maxevents = "-1"; int errorcount = 0; int verbocount = 0; std::vector xmlcmds; std::vector configargs; fNThrows = 250; fStartThrows = 0; fThrowString = ""; // Make easier to handle arguments. std::vector args = GeneralUtils::LoadCharToVectStr(argc, argv); ParserUtils::ParseArgument(args, "-c", fCardFile, true); ParserUtils::ParseArgument(args, "-o", fOutputFile, false, false); ParserUtils::ParseArgument(args, "-n", maxevents, false, false); ParserUtils::ParseArgument(args, "-f", fStrategy, false, false); ParserUtils::ParseArgument(args, "-d", fFakeDataInput, false, false); ParserUtils::ParseArgument(args, "-s", fStartThrows, false, false); ParserUtils::ParseArgument(args, "-t", fNThrows, false, false); ParserUtils::ParseArgument(args, "-p", fThrowString, false, false); ParserUtils::ParseArgument(args, "-i", xmlcmds); ParserUtils::ParseArgument(args, "-q", configargs); ParserUtils::ParseCounter(args, "e", errorcount); ParserUtils::ParseCounter(args, "v", verbocount); ParserUtils::CheckBadArguments(args); // Add extra defaults if none given if (fCardFile.empty() and xmlcmds.empty()) { NUIS_ABORT("No input supplied!"); } if (fOutputFile.empty() and !fCardFile.empty()) { fOutputFile = fCardFile + ".root"; NUIS_ERR(WRN, "No output supplied so saving it to: " << fOutputFile); } else if (fOutputFile.empty()) { NUIS_ABORT("No output file or cardfile supplied!"); } // Configuration Setup ============================= // Check no comp key is available if (Config::Get().GetNodes("nuiscomp").empty()) { fCompKey = Config::Get().CreateNode("nuiscomp"); } else { fCompKey = Config::Get().GetNodes("nuiscomp")[0]; } if (!fCardFile.empty()) fCompKey.Set("cardfile", fCardFile); if (!fOutputFile.empty()) fCompKey.Set("outputfile", fOutputFile); if (!fStrategy.empty()) fCompKey.Set("strategy", fStrategy); // Load XML Cardfile configuration.LoadSettings(fCompKey.GetS("cardfile"), ""); // Add Config Args for (size_t i = 0; i < configargs.size(); i++) { configuration.OverrideConfig(configargs[i]); } if (maxevents.compare("-1")) { configuration.OverrideConfig("MAXEVENTS=" + maxevents); } // Finish configuration XML configuration.FinaliseSettings(fCompKey.GetS("outputfile") + ".xml"); // Add Error Verbo Lines verbocount += Config::GetParI("VERBOSITY"); errorcount += Config::GetParI("ERROR"); std::cout << "[ NUISANCE ]: Setting VERBOSITY=" << verbocount << std::endl; std::cout << "[ NUISANCE ]: Setting ERROR=" << errorcount << std::endl; SETVERBOSITY(verbocount); // Proper Setup if (fStrategy.find("ErrorBands") != std::string::npos || fStrategy.find("MergeErrors") != std::string::npos) { fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE"); } // fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), // "RECREATE"); SetupSystematicsFromXML(); SetupCovariance(); SetupRWEngine(); SetupFCN(); GetCovarFromFCN(); // Run(); return; }; void SystematicRoutines::SetupSystematicsFromXML() { NUIS_LOG(FIT, "Setting up nuismin"); // Setup Parameters ------------------------------------------ std::vector parkeys = Config::QueryKeys("parameter"); if (!parkeys.empty()) { NUIS_LOG(FIT, "Number of parameters : " << parkeys.size()); } for (size_t i = 0; i < parkeys.size(); i++) { nuiskey key = parkeys.at(i); // Check for type,name,nom if (!key.Has("type")) { NUIS_ABORT("No type given for parameter " << i); } else if (!key.Has("name")) { NUIS_ABORT("No name given for parameter " << i); } else if (!key.Has("nominal")) { NUIS_ABORT("No nominal given for parameter " << i); } // Get Inputs std::string partype = key.GetS("type"); std::string parname = key.GetS("name"); double parnom = key.GetD("nominal"); double parlow = parnom - 1; double parhigh = parnom + 1; double parstep = 1; // Override if state not given if (!key.Has("state")) { key.SetS("state", "FIX"); } std::string parstate = key.GetS("state"); // Extra limits if (key.Has("low")) { parlow = key.GetD("low"); parhigh = key.GetD("high"); parstep = key.GetD("step"); NUIS_LOG(FIT, "Read " << partype << " : " << parname << " = " << parnom << " : " << parlow << " < p < " << parhigh << " : " << parstate); } else { NUIS_LOG(FIT, "Read " << partype << " : " << parname << " = " << parnom << " : " << parstate); } // Run Parameter Conversion if needed if (parstate.find("ABS") != std::string::npos) { parnom = FitBase::RWAbsToSigma(partype, parname, parnom); parlow = FitBase::RWAbsToSigma(partype, parname, parlow); parhigh = FitBase::RWAbsToSigma(partype, parname, parhigh); parstep = FitBase::RWAbsToSigma(partype, parname, parstep); } else if (parstate.find("FRAC") != std::string::npos) { parnom = FitBase::RWFracToSigma(partype, parname, parnom); parlow = FitBase::RWFracToSigma(partype, parname, parlow); parhigh = FitBase::RWFracToSigma(partype, parname, parhigh); parstep = FitBase::RWFracToSigma(partype, parname, parstep); } // Push into vectors fParams.push_back(parname); fTypeVals[parname] = FitBase::ConvDialType(partype); fStartVals[parname] = parnom; fCurVals[parname] = parnom; fErrorVals[parname] = 0.0; fStateVals[parname] = parstate; bool fixstate = parstate.find("FIX") != std::string::npos; fFixVals[parname] = fixstate; fStartFixVals[parname] = fFixVals[parname]; fMinVals[parname] = parlow; fMaxVals[parname] = parhigh; fStepVals[parname] = parstep; } // Setup Samples ---------------------------------------------- std::vector samplekeys = Config::QueryKeys("sample"); if (!samplekeys.empty()) { NUIS_LOG(FIT, "Number of samples : " << samplekeys.size()); } for (size_t i = 0; i < samplekeys.size(); i++) { nuiskey key = samplekeys.at(i); // Get Sample Options std::string samplename = key.GetS("name"); std::string samplefile = key.GetS("input"); std::string sampletype = key.Has("type") ? key.GetS("type") : "DEFAULT"; double samplenorm = key.Has("norm") ? key.GetD("norm") : 1.0; // Print out NUIS_LOG(FIT, "Read sample info " << i << " : " << samplename << std::endl << "\t\t input -> " << samplefile << std::endl << "\t\t state -> " << sampletype << std::endl << "\t\t norm -> " << samplenorm); // If FREE add to parameters otherwise continue if (sampletype.find("FREE") == std::string::npos) { continue; } // Form norm dial from samplename + sampletype + "_norm"; std::string normname = samplename + "_norm"; // Check normname not already present if (fTypeVals.find(normname) != fTypeVals.end()) { continue; } // Add new norm dial to list if its passed above checks fParams.push_back(normname); fTypeVals[normname] = kNORM; fStateVals[normname] = sampletype; fCurVals[normname] = samplenorm; fErrorVals[normname] = 0.0; fMinVals[normname] = 0.1; fMaxVals[normname] = 10.0; fStepVals[normname] = 0.5; bool state = sampletype.find("FREE") == std::string::npos; fFixVals[normname] = state; fStartFixVals[normname] = state; } // Setup Fake Parameters ----------------------------- std::vector fakekeys = Config::QueryKeys("fakeparameter"); if (!fakekeys.empty()) { NUIS_LOG(FIT, "Number of fake parameters : " << fakekeys.size()); } for (size_t i = 0; i < fakekeys.size(); i++) { nuiskey key = fakekeys.at(i); // Check for type,name,nom if (!key.Has("name")) { NUIS_ABORT("No name given for fakeparameter " << i); } else if (!key.Has("nom")) { NUIS_ABORT("No nominal given for fakeparameter " << i); } // Get Inputs std::string parname = key.GetS("name"); double parnom = key.GetD("nom"); // Push into vectors fFakeVals[parname] = parnom; } } /* Setup Functions */ //************************************* void SystematicRoutines::SetupRWEngine() { //************************************* for (UInt_t i = 0; i < fParams.size(); i++) { std::string name = fParams[i]; FitBase::GetRW()->IncludeDial(name, fTypeVals.at(name)); } UpdateRWEngine(fStartVals); return; } //************************************* void SystematicRoutines::SetupFCN() { //************************************* NUIS_LOG(FIT, "Making the jointFCN"); if (fSampleFCN) delete fSampleFCN; fSampleFCN = new JointFCN(fOutputRootFile); SetFakeData(); return; } //************************************* void SystematicRoutines::SetFakeData() { //************************************* if (fFakeDataInput.empty()) return; if (fFakeDataInput.compare("MC") == 0) { NUIS_LOG(FIT, "Setting fake data from MC starting prediction."); UpdateRWEngine(fFakeVals); FitBase::GetRW()->Reconfigure(); fSampleFCN->ReconfigureAllEvents(); fSampleFCN->SetFakeData("MC"); UpdateRWEngine(fCurVals); NUIS_LOG(FIT, "Set all data to fake MC predictions."); } else { fSampleFCN->SetFakeData(fFakeDataInput); } return; } //***************************************** // Setup the parameter covariances from the FCN void SystematicRoutines::GetCovarFromFCN() { //***************************************** NUIS_LOG(FIT, "Loading ParamPull objects from FCN to build covariance..."); // Make helperstring std::ostringstream helperstr; // Keep track of what is being thrown std::map dialthrowhandle; // Get Covariance Objects from FCN std::list inputpulls = fSampleFCN->GetPullList(); for (PullListConstIter iter = inputpulls.begin(); iter != inputpulls.end(); iter++) { ParamPull *pull = (*iter); if (pull->GetType().find("THROW") != std::string::npos) { fInputThrows.push_back(pull); fInputCovar.push_back(pull->GetFullCovarMatrix()); fInputDials.push_back(pull->GetDataHist()); NUIS_LOG(FIT, "Read ParamPull: " << pull->GetName() << " " << pull->GetType()); } TH1D dialhist = pull->GetDataHist(); TH1D minhist = pull->GetMinHist(); TH1D maxhist = pull->GetMaxHist(); TH1I typehist = pull->GetDialTypes(); for (int i = 0; i < dialhist.GetNbinsX(); i++) { std::string name = std::string(dialhist.GetXaxis()->GetBinLabel(i + 1)); dialthrowhandle[name] = pull->GetName(); // Add to Containers // Set the starting values etc to the postfit fParams.push_back(name); fCurVals[name] = dialhist.GetBinContent(i + 1); // Set the starting values to be nominal MC fStartVals[name] = 0.0; fMinVals[name] = minhist.GetBinContent(i + 1); fMaxVals[name] = maxhist.GetBinContent(i + 1); fStepVals[name] = 1.0; fFixVals[name] = false; fStartFixVals[name] = false; fTypeVals[name] = typehist.GetBinContent(i + 1); fStateVals[name] = "FREE," + pull->GetType(); // If we find the string if (fCurVals.find(name) == fCurVals.end()) { // Maker Helper helperstr << std::string(16, ' ') << FitBase::ConvDialType(fTypeVals[name]) << " " << name << " " << fMinVals[name] << " " << fMaxVals[name] << " " << fStepVals[name] << " " << fStateVals[name] << std::endl; } } } // Check if no throws given if (fInputThrows.empty()) { NUIS_ERR(WRN, "No covariances given to nuissyst"); NUIS_ERR(WRN, "Pushing back an uncorrelated gaussian throw error for each " "free parameter using step size"); for (UInt_t i = 0; i < fParams.size(); i++) { std::string syst = fParams[i]; if (fFixVals[syst]) continue; // Make Terms std::string name = syst + "_pull"; std::ostringstream pullterm; pullterm << "DIAL:" << syst << ";" << fStartVals[syst] << ";" << fStepVals[syst]; std::string type = "GAUSTHROW/NEUT"; // Push Back Pulls ParamPull *pull = new ParamPull(name, pullterm.str(), type); fInputThrows.push_back(pull); fInputCovar.push_back(pull->GetFullCovarMatrix()); fInputDials.push_back(pull->GetDataHist()); // Print Whats added NUIS_LOG(FIT, "Added ParamPull : " << name << " " << pullterm.str() << " " << type); // Add helper string for future fits helperstr << std::string(16, ' ') << "covar " << name << " " << pullterm.str() << " " << type << std::endl; // Keep Track of Throws dialthrowhandle[syst] = pull->GetName(); } } // Print Helper String if (!helperstr.str().empty()) { NUIS_LOG(FIT, "To remove these statements in future studies, add the lines " "below to your card:"); // Can't use the logger properly because this can be multi-line. Use cout // and added spaces to look better! std::cout << helperstr.str(); sleep(2); } // Print Throw State for (UInt_t i = 0; i < fParams.size(); i++) { std::string syst = fParams[i]; if (dialthrowhandle.find(syst) != dialthrowhandle.end()) { NUIS_LOG(FIT, "Dial " << i << ". " << setw(20) << syst << " = THROWing with " << dialthrowhandle[syst]); } else { NUIS_LOG(FIT, "Dial " << i << ". " << setw(20) << syst << " = is FIXED"); } } } /* Fitting Functions */ //************************************* void SystematicRoutines::UpdateRWEngine( std::map &updateVals) { //************************************* for (UInt_t i = 0; i < fParams.size(); i++) { std::string name = fParams[i]; if (updateVals.find(name) == updateVals.end()) continue; FitBase::GetRW()->SetDialValue(name, updateVals.at(name)); } FitBase::GetRW()->Reconfigure(); } //************************************* void SystematicRoutines::PrintState() { //************************************* NUIS_LOG(FIT, "------------"); // Count max size int maxcount = 0; for (UInt_t i = 0; i < fParams.size(); i++) { maxcount = max(int(fParams[i].size()), maxcount); } // Header NUIS_LOG(FIT, " # " << left << setw(maxcount) << "Parameter " << " = " << setw(10) << "Value" << " +- " << setw(10) << "Error" << " " << setw(8) << "(Units)" << " " << setw(10) << "Conv. Val" << " +- " << setw(10) << "Conv. Err" << " " << setw(8) << "(Units)"); // Parameters for (UInt_t i = 0; i < fParams.size(); i++) { std::string syst = fParams.at(i); std::string typestr = FitBase::ConvDialType(fTypeVals[syst]); std::string curunits = "(sig.)"; double curval = fCurVals[syst]; double curerr = fErrorVals[syst]; if (fStateVals[syst].find("ABS") != std::string::npos) { curval = FitBase::RWSigmaToAbs(typestr, syst, curval); curerr = (FitBase::RWSigmaToAbs(typestr, syst, curerr) - FitBase::RWSigmaToAbs(typestr, syst, 0.0)); curunits = "(Abs.)"; } else if (fStateVals[syst].find("FRAC") != std::string::npos) { curval = FitBase::RWSigmaToFrac(typestr, syst, curval); curerr = (FitBase::RWSigmaToFrac(typestr, syst, curerr) - FitBase::RWSigmaToFrac(typestr, syst, 0.0)); curunits = "(Frac)"; } std::string convunits = "(" + FitBase::GetRWUnits(typestr, syst) + ")"; double convval = FitBase::RWSigmaToAbs(typestr, syst, curval); double converr = (FitBase::RWSigmaToAbs(typestr, syst, curerr) - FitBase::RWSigmaToAbs(typestr, syst, 0.0)); std::ostringstream curparstring; curparstring << " " << setw(3) << left << i << ". " << setw(maxcount) << syst << " = " << setw(10) << curval << " +- " << setw(10) << curerr << " " << setw(8) << curunits << " " << setw(10) << convval << " +- " << setw(10) << converr << " " << setw(8) << convunits; NUIS_LOG(FIT, curparstring.str()); } NUIS_LOG(FIT, "------------"); double like = fSampleFCN->GetLikelihood(); NUIS_LOG(FIT, std::left << std::setw(46) << "Likelihood for JointFCN: " << like); NUIS_LOG(FIT, "------------"); } /* Write Functions */ //************************************* void SystematicRoutines::SaveResults() { //************************************* if (!fOutputRootFile) fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE"); fOutputRootFile->cd(); SaveCurrentState(); } //************************************* void SystematicRoutines::SaveCurrentState(std::string subdir) { //************************************* NUIS_LOG(FIT, "Saving current full FCN predictions"); // Setup DIRS TDirectory *curdir = gDirectory; if (!subdir.empty()) { TDirectory *newdir = (TDirectory *)gDirectory->mkdir(subdir.c_str()); newdir->cd(); } FitBase::GetRW()->Reconfigure(); fSampleFCN->ReconfigureAllEvents(); fSampleFCN->Write(); // Change back to current DIR curdir->cd(); return; } //************************************* void SystematicRoutines::SaveNominal() { //************************************* if (!fOutputRootFile) fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE"); fOutputRootFile->cd(); NUIS_LOG(FIT, "Saving Nominal Predictions (be cautious with this)"); FitBase::GetRW()->Reconfigure(); SaveCurrentState("nominal"); }; //************************************* void SystematicRoutines::SavePrefit() { //************************************* if (!fOutputRootFile) fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE"); fOutputRootFile->cd(); NUIS_LOG(FIT, "Saving Prefit Predictions"); UpdateRWEngine(fStartVals); SaveCurrentState("prefit"); UpdateRWEngine(fCurVals); }; /* MISC Functions */ //************************************* int SystematicRoutines::GetStatus() { //************************************* return 0; } //************************************* void SystematicRoutines::SetupCovariance() { //************************************* // Remove covares if they exist if (fCovar) delete fCovar; if (fCovarFree) delete fCovarFree; if (fCorrel) delete fCorrel; if (fCorrelFree) delete fCorrelFree; if (fDecomp) delete fDecomp; if (fDecompFree) delete fDecompFree; int NFREE = 0; int NDIM = 0; // Get NFREE from min or from vals (for cases when doing throws) NDIM = fParams.size(); for (UInt_t i = 0; i < fParams.size(); i++) { if (!fFixVals[fParams[i]]) NFREE++; } if (NDIM == 0) return; fCovar = new TH2D("covariance", "covariance", NDIM, 0, NDIM, NDIM, 0, NDIM); if (NFREE > 0) { fCovarFree = new TH2D("covariance_free", "covariance_free", NFREE, 0, NFREE, NFREE, 0, NFREE); } // Set Bin Labels int countall = 0; int countfree = 0; for (UInt_t i = 0; i < fParams.size(); i++) { fCovar->GetXaxis()->SetBinLabel(countall + 1, fParams[i].c_str()); fCovar->GetYaxis()->SetBinLabel(countall + 1, fParams[i].c_str()); countall++; if (!fFixVals[fParams[i]] and NFREE > 0) { fCovarFree->GetXaxis()->SetBinLabel(countfree + 1, fParams[i].c_str()); fCovarFree->GetYaxis()->SetBinLabel(countfree + 1, fParams[i].c_str()); countfree++; } } fCorrel = PlotUtils::GetCorrelationPlot(fCovar, "correlation"); fDecomp = PlotUtils::GetDecompPlot(fCovar, "decomposition"); if (NFREE > 0) fCorrelFree = PlotUtils::GetCorrelationPlot(fCovarFree, "correlation_free"); if (NFREE > 0) fDecompFree = PlotUtils::GetDecompPlot(fCovarFree, "decomposition_free"); return; }; //************************************* void SystematicRoutines::ThrowCovariance(bool uniformly) { //************************************* // Set fThrownVals to all values in currentVals for (UInt_t i = 0; i < fParams.size(); i++) { std::string name = fParams.at(i); fThrownVals[name] = fCurVals[name]; } for (PullListConstIter iter = fInputThrows.begin(); iter != fInputThrows.end(); iter++) { ParamPull *pull = *iter; pull->ThrowCovariance(); TH1D dialhist = pull->GetDataHist(); for (int i = 0; i < dialhist.GetNbinsX(); i++) { std::string name = std::string(dialhist.GetXaxis()->GetBinLabel(i + 1)); if (fCurVals.find(name) != fCurVals.end()) { fThrownVals[name] = dialhist.GetBinContent(i + 1); } } // Reset throw in case pulls are calculated. pull->ResetToy(); } }; //************************************* void SystematicRoutines::PlotLimits() { //************************************* std::cout << "Plotting Limits" << std::endl; if (!fOutputRootFile) fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE"); TDirectory *limfolder = (TDirectory *)fOutputRootFile->mkdir("Limits"); limfolder->cd(); // Set all parameters at their starting values for (UInt_t i = 0; i < fParams.size(); i++) { fCurVals[fParams[i]] = fStartVals[fParams[i]]; } TDirectory *nomfolder = (TDirectory *)limfolder->mkdir("nominal"); nomfolder->cd(); UpdateRWEngine(fCurVals); fSampleFCN->ReconfigureAllEvents(); fSampleFCN->Write(); limfolder->cd(); std::vector allfolders; // Loop through each parameter for (UInt_t i = 0; i < fParams.size(); i++) { std::string syst = fParams[i]; std::cout << "Starting Param " << syst << std::endl; if (fFixVals[syst]) continue; // Loop Downwards while (fCurVals[syst] > fMinVals[syst]) { fCurVals[syst] = fCurVals[syst] - fStepVals[syst]; // Check Limit if (fCurVals[syst] < fMinVals[syst]) fCurVals[syst] = fMinVals[syst]; // Check folder exists std::string curvalstring = std::string(Form((syst + "_%f").c_str(), fCurVals[syst])); if (std::find(allfolders.begin(), allfolders.end(), curvalstring) != allfolders.end()) break; // Make new folder for variation TDirectory *minfolder = (TDirectory *)limfolder->mkdir( Form((syst + "_%f").c_str(), fCurVals[syst])); minfolder->cd(); allfolders.push_back(curvalstring); // Update Iterations double *vals = FitUtils::GetArrayFromMap(fParams, fCurVals); fSampleFCN->DoEval(vals); delete vals; // Save to folder fSampleFCN->Write(); } // Reset before next loop fCurVals[syst] = fStartVals[syst]; // Loop Upwards now while (fCurVals[syst] < fMaxVals[syst]) { fCurVals[syst] = fCurVals[syst] + fStepVals[syst]; // Check Limit if (fCurVals[syst] > fMaxVals[syst]) fCurVals[syst] = fMaxVals[syst]; // Check folder exists std::string curvalstring = std::string(Form((syst + "_%f").c_str(), fCurVals[syst])); if (std::find(allfolders.begin(), allfolders.end(), curvalstring) != allfolders.end()) break; // Make new folder TDirectory *maxfolder = (TDirectory *)limfolder->mkdir( Form((syst + "_%f").c_str(), fCurVals[syst])); maxfolder->cd(); allfolders.push_back(curvalstring); // Update Iterations double *vals = FitUtils::GetArrayFromMap(fParams, fCurVals); fSampleFCN->DoEval(vals); delete vals; // Save to file fSampleFCN->Write(); } // Reset before leaving fCurVals[syst] = fStartVals[syst]; UpdateRWEngine(fCurVals); } return; } //************************************* void SystematicRoutines::Run() { //************************************* fRoutines = GeneralUtils::ParseToStr(fStrategy, ","); for (UInt_t i = 0; i < fRoutines.size(); i++) { std::string routine = fRoutines.at(i); int fitstate = kFitUnfinished; NUIS_LOG(FIT, "Running Routine: " << routine); if (routine.compare("PlotLimits") == 0) PlotLimits(); else if (routine.compare("ErrorBands") == 0) GenerateErrorBands(); else if (routine.compare("ThrowErrors") == 0) GenerateThrows(); else if (routine.compare("MergeErrors") == 0) MergeThrows(); else if (routine.compare("EigenErrors") == 0) EigenErrors(); else { NUIS_ABORT("Unknown ROUTINE : " << routine); } // If ending early break here if (fitstate == kFitFinished || fitstate == kNoChange) { NUIS_LOG(FIT, "Ending fit routines loop."); break; } } } void SystematicRoutines::GenerateErrorBands() { GenerateThrows(); MergeThrows(); } //************************************* void SystematicRoutines::GenerateThrows() { //************************************* TFile *tempfile = new TFile((fOutputFile + ".throws.root").c_str(), "RECREATE"); tempfile->cd(); // For generating throws we check with the config int nthrows = Config::GetParI("error_throws"); int startthrows = fStartThrows; int endthrows = startthrows + nthrows; if (nthrows < 0) nthrows = endthrows; if (startthrows < 0) startthrows = 0; if (endthrows < 0) endthrows = startthrows + nthrows; // Setting Seed // Matteo Mazzanti's Fix struct timeval mytime; gettimeofday(&mytime, NULL); Double_t seed = time(NULL) + int(getpid()) + (mytime.tv_sec * 1000.) + (mytime.tv_usec / 1000.); gRandom->SetSeed(seed); // int seed = (gRandom->Uniform(0.0,1.0)*100000 + 100000000*(startthrows + // endthrows) + time(NULL) + int(getpid()) ); gRandom->SetSeed(seed); NUIS_LOG(FIT, "Using Seed : " << seed); NUIS_LOG(FIT, "nthrows = " << nthrows); NUIS_LOG(FIT, "startthrows = " << startthrows); NUIS_LOG(FIT, "endthrows = " << endthrows); UpdateRWEngine(fStartVals); fSampleFCN->ReconfigureAllEvents(); // Make the nominal if (startthrows == 0) { NUIS_LOG(FIT, "Making nominal "); TDirectory *nominal = (TDirectory *)tempfile->mkdir("nominal"); nominal->cd(); fSampleFCN->Write(); // Make the postfit reading from the pull NUIS_LOG(FIT, "Making postfit "); TDirectory *postfit = (TDirectory *)tempfile->mkdir("postfit"); postfit->cd(); UpdateRWEngine(fCurVals); fSampleFCN->ReconfigureSignal(); fSampleFCN->Write(); } fSampleFCN->CreateIterationTree("error_iterations", FitBase::GetRW()); // Would anybody actually want to do uniform throws of any parameter?? bool uniformly = FitPar::Config().GetParB("error_uniform"); // Run Throws and save for (Int_t i = 0; i < endthrows + 1; i++) { // Generate Random Parameter Throw ThrowCovariance(uniformly); if (i < startthrows) continue; if (i == 0) continue; NUIS_LOG(FIT, "Throw " << i << "/" << endthrows << " ================================"); TDirectory *throwfolder = (TDirectory *)tempfile->mkdir(Form("throw_%i", i)); throwfolder->cd(); // Run Eval double *vals = FitUtils::GetArrayFromMap(fParams, fThrownVals); fSampleFCN->DoEval(vals); delete vals; // Save the FCN fSampleFCN->Write(); } tempfile->cd(); fSampleFCN->WriteIterationTree(); tempfile->Close(); } // Merge throws together into one summary void SystematicRoutines::MergeThrows() { fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE"); fOutputRootFile->cd(); // Make a container folder TDirectory *errorDIR = (TDirectory *)fOutputRootFile->mkdir("error_bands"); errorDIR->cd(); TDirectory *outnominal = (TDirectory *)fOutputRootFile->mkdir("nominal_throw"); outnominal->cd(); // Split Input Files if (!fThrowString.empty()) fThrowList = GeneralUtils::ParseToStr(fThrowString, ","); // Add default if no throwlist given if (fThrowList.size() < 1) fThrowList.push_back(fOutputFile + ".throws.root"); /// Save location of file containing nominal std::string nominalfile; bool nominalfound; // Loop over files and check they exist. for (uint i = 0; i < fThrowList.size(); i++) { std::string file = fThrowList[i]; bool found = false; // normal std::string newfile = file; TFile *throwfile = new TFile(file.c_str(), "READ"); if (throwfile and !throwfile->IsZombie()) { found = true; } // normal.throws.root if (!found) { newfile = file + ".throws.root"; throwfile = new TFile((file + ".throws.root").c_str(), "READ"); if (throwfile and !throwfile->IsZombie()) { found = true; } } // If its found save to throwlist, else save empty. // Also search for nominal if (found) { fThrowList[i] = newfile; NUIS_LOG(FIT, "Throws File :" << newfile); // Find input which contains nominal if (throwfile->Get("nominal")) { nominalfound = true; nominalfile = newfile; } throwfile->Close(); } else { fThrowList[i] = ""; } delete throwfile; } // Make sure we have a nominal file if (!nominalfound or nominalfile.empty()) { NUIS_ABORT("No nominal found when merging! Exiting!"); } // Get the nominal throws file TFile *tempfile = new TFile((nominalfile).c_str(), "READ"); tempfile->cd(); TDirectory *nominal = (TDirectory *)tempfile->Get("nominal"); bool uniformly = FitPar::Config().GetParB("error_uniform"); // Check percentage of bad files is okay. int badfilecount = 0; for (uint i = 0; i < fThrowList.size(); i++) { if (!fThrowList[i].empty()) { NUIS_LOG(FIT, "Loading Throws From File " << i << " : " << fThrowList[i]); } else { badfilecount++; } } // Check we have at least one good file if ((uint)badfilecount == fThrowList.size()) { NUIS_ABORT("Found no good throw files for MergeThrows"); throw; } else if (badfilecount > (fThrowList.size() * 0.25)) { NUIS_ERR( WRN, "Over 25% of your throw files are dodgy. Please check this is okay!"); NUIS_ERR(WRN, "Will continue for the time being..."); sleep(5); } // Now go through the keys in the temporary file and look for TH1D, and TH2D // plots TIter next(nominal->GetListOfKeys()); TKey *key; while ((key = (TKey *)next())) { TClass *cl = gROOT->GetClass(key->GetClassName()); if (!cl->InheritsFrom("TH1D") and !cl->InheritsFrom("TH2D")) continue; TH1 *baseplot = (TH1D *)key->ReadObj(); std::string plotname = std::string(baseplot->GetName()); NUIS_LOGN(FIT, "Creating error bands for " << plotname); if (LOG_LEVEL(FIT)) { if (!uniformly) { NUIS_LOG(FIT, " : Using COVARIANCE Throws! "); } else { NUIS_LOG(FIT, " : Using UNIFORM THROWS!!! "); } } int nbins = 0; if (cl->InheritsFrom("TH1D")) nbins = ((TH1D *)baseplot)->GetNbinsX(); else nbins = ((TH1D *)baseplot)->GetNbinsX() * ((TH1D *)baseplot)->GetNbinsY(); // Setup TProfile with RMS option TProfile *tprof = new TProfile((plotname + "_prof").c_str(), (plotname + "_prof").c_str(), nbins, 0, nbins, "S"); // Setup The TTREE double *bincontents; bincontents = new double[nbins]; double *binlowest; binlowest = new double[nbins]; double *binhighest; binhighest = new double[nbins]; errorDIR->cd(); TTree *bintree = new TTree((plotname + "_tree").c_str(), (plotname + "_tree").c_str()); for (Int_t i = 0; i < nbins; i++) { bincontents[i] = 0.0; binhighest[i] = 0.0; binlowest[i] = 0.0; bintree->Branch(Form("content_%i", i), &bincontents[i], Form("content_%i/D", i)); } // Make new throw plot TH1 *newplot; // Run Throw Merging. for (UInt_t i = 0; i < fThrowList.size(); i++) { TFile *throwfile = new TFile(fThrowList[i].c_str(), "READ"); // Loop over all throws in a folder TIter nextthrow(throwfile->GetListOfKeys()); TKey *throwkey; while ((throwkey = (TKey *)nextthrow())) { // Skip non throw folders if (std::string(throwkey->GetName()).find("throw_") == std::string::npos) continue; // Get Throw DIR TDirectory *throwdir = (TDirectory *)throwkey->ReadObj(); // Get Plot From Throw newplot = (TH1 *)throwdir->Get(plotname.c_str()); if (!newplot) continue; // Loop Over Plot for (Int_t j = 0; j < nbins; j++) { tprof->Fill(j + 0.5, newplot->GetBinContent(j + 1)); bincontents[j] = newplot->GetBinContent(j + 1); if (bincontents[j] < binlowest[j] or i == 0) binlowest[j] = bincontents[j]; if (bincontents[j] > binhighest[j] or i == 0) binhighest[j] = bincontents[j]; } errorDIR->cd(); bintree->Fill(); } throwfile->Close(); delete throwfile; } errorDIR->cd(); if (uniformly) { NUIS_LOG(FIT, "Uniformly Calculating Plot Errors!"); } TH1 *statplot = (TH1 *)baseplot->Clone(); for (Int_t j = 0; j < nbins; j++) { if (!uniformly) { // if ((baseplot->GetBinError(j+1)/baseplot->GetBinContent(j+1)) //< 1.0) { // baseplot->SetBinError(j+1,sqrt(pow(tprof->GetBinError(j+1),2) //+ pow(baseplot->GetBinError(j+1),2))); } else { baseplot->SetBinContent(j + 1, tprof->GetBinContent(j + 1)); baseplot->SetBinError(j + 1, tprof->GetBinError(j + 1)); // } } else { baseplot->SetBinContent(j + 1, 0.0); //(binlowest[j] + binhighest[j]) / 2.0); baseplot->SetBinError(j + 1, 0.0); //(binhighest[j] - binlowest[j])/2.0); } } baseplot->SetTitle("Profiled throws"); errorDIR->cd(); baseplot->Write(); tprof->Write(); bintree->Write(); outnominal->cd(); for (int i = 0; i < nbins; i++) { baseplot->SetBinError(i + 1, sqrt(pow(statplot->GetBinError(i + 1), 2) + pow(baseplot->GetBinError(i + 1), 2))); } baseplot->Write(); delete statplot; delete baseplot; delete tprof; delete bintree; delete[] bincontents; } }; void SystematicRoutines::EigenErrors() { fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE"); fOutputRootFile->cd(); // Make Covariance TMatrixDSym *fullcovar = new TMatrixDSym(fParams.size()); // Extract covariance from all loaded ParamPulls for (PullListConstIter iter = fInputThrows.begin(); iter != fInputThrows.end(); iter++) { ParamPull *pull = *iter; // Check pull is actualyl Gaussian std::string pulltype = pull->GetType(); if (pulltype.find("GAUSTHROW") == std::string::npos) { NUIS_ABORT("Can only calculate EigenErrors for Gaussian pulls!"); } // Get data and covariances TH1D dialhist = pull->GetDataHist(); TH2D covhist = pull->GetFullCovar(); // Loop over all dials and compare names for (size_t pari = 0; pari < fParams.size(); pari++) { for (size_t parj = 0; parj < fParams.size(); parj++) { std::string name_pari = fParams[pari]; std::string name_parj = fParams[parj]; // Compare names to those in the pull for (int pulli = 0; pulli < dialhist.GetNbinsX(); pulli++) { for (int pullj = 0; pullj < dialhist.GetNbinsX(); pullj++) { std::string name_pulli = dialhist.GetXaxis()->GetBinLabel(pulli + 1); std::string name_pullj = dialhist.GetXaxis()->GetBinLabel(pullj + 1); if (name_pulli == name_pari && name_pullj == name_parj) { (*fullcovar)[pari][parj] = covhist.GetBinContent(pulli + 1, pullj + 1); fCurVals[name_pari] = dialhist.GetBinContent(pulli + 1); fCurVals[name_parj] = dialhist.GetBinContent(pullj + 1); } } } } } } /* TFile* test = new TFile("testingcovar.root","RECREATE"); test->cd(); TH2D* joinedcov = new TH2D("COVAR","COVAR", fullcovar->GetNrows(), 0.0, float(fullcovar->GetNrows()), fullcovar->GetNrows(), 0.0, float(fullcovar->GetNrows())); for (int i = 0; i < fullcovar->GetNrows(); i++){ for (int j = 0; j < fullcovar->GetNcols(); j++){ joinedcov->SetBinContent(i+1, j+1, (*fullcovar)[i][j]); } } joinedcov->Write("COVAR"); test->Close(); */ // Calculator all EigenVectors and EigenValues TMatrixDSymEigen *eigen = new TMatrixDSymEigen(*fullcovar); const TVectorD eigenVals = eigen->GetEigenValues(); const TMatrixD eigenVect = eigen->GetEigenVectors(); eigenVals.Print(); eigenVect.Print(); TDirectory *outnominal = (TDirectory *)fOutputRootFile->mkdir("nominal"); outnominal->cd(); - double *valst = FitUtils::GetArrayFromMap(fParams, fCurVals); + // double *valst = FitUtils::GetArrayFromMap(fParams, fCurVals); // double chi2 = fSampleFCN->DoEval( valst ); - delete valst; + // delete valst; fSampleFCN->Write(); // Loop over all throws TDirectory *throwsdir = (TDirectory *)fOutputRootFile->mkdir("throws"); throwsdir->cd(); int count = 0; // Produce all error throws. for (int i = 0; i < eigenVect.GetNrows(); i++) { TDirectory *throwfolder = (TDirectory *)throwsdir->mkdir(Form("throw_%i", count)); throwfolder->cd(); // Get New Parameter Vector NUIS_LOG(FIT, "Parameter Set " << count); for (int j = 0; j < eigenVect.GetNrows(); j++) { std::string param = fParams[j]; NUIS_LOG(FIT, " " << j << ". " << param << " : " << fCurVals[param] + sqrt(eigenVals[i]) * eigenVect[j][i]); fThrownVals[param] = fCurVals[param] + sqrt(eigenVals[i]) * eigenVect[j][i]; } // Run Eval double *vals = FitUtils::GetArrayFromMap(fParams, fThrownVals); double chi2 = fSampleFCN->DoEval(vals); + NUIS_LOG(DEB, "Chi2 = " << chi2); delete vals; count++; fSampleFCN->Write(); throwfolder = (TDirectory *)throwsdir->mkdir(Form("throw_%i", count)); throwfolder->cd(); // Get New Parameter Vector NUIS_LOG(FIT, "Parameter Set " << count); for (int j = 0; j < eigenVect.GetNrows(); j++) { std::string param = fParams[j]; NUIS_LOG(FIT, " " << j << ". " << param << " : " << fCurVals[param] - sqrt(eigenVals[i]) * eigenVect[j][i]); fThrownVals[param] = fCurVals[param] - sqrt(eigenVals[i]) * eigenVect[j][i]; } // Run Eval double *vals2 = FitUtils::GetArrayFromMap(fParams, fThrownVals); chi2 = fSampleFCN->DoEval(vals2); + NUIS_LOG(DEB, "Chi2 = " << chi2); delete vals2; count++; // Save the FCN fSampleFCN->Write(); } fOutputRootFile->Close(); fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "UPDATE"); fOutputRootFile->cd(); throwsdir = (TDirectory *)fOutputRootFile->Get("throws"); outnominal = (TDirectory *)fOutputRootFile->Get("nominal"); // Loop through Error DIR TDirectory *outerr = (TDirectory *)fOutputRootFile->mkdir("errors"); outerr->cd(); TIter next(outnominal->GetListOfKeys()); TKey *key; while ((key = (TKey *)next())) { TClass *cl = gROOT->GetClass(key->GetClassName()); if (!cl->InheritsFrom("TH1D") and !cl->InheritsFrom("TH2D")) continue; NUIS_LOG(FIT, "Creating error bands for " << key->GetName()); std::string plotname = std::string(key->GetName()); if (plotname.find("_EVT") != std::string::npos) continue; if (plotname.find("_FLUX") != std::string::npos) continue; if (plotname.find("_FLX") != std::string::npos) continue; TH1 *baseplot = (TH1D *)key->ReadObj()->Clone(Form("%s_ORIGINAL", key->GetName())); TH1 *errorplot_upper = (TH1D *)baseplot->Clone(Form("%s_ERROR_UPPER", key->GetName())); TH1 *errorplot_lower = (TH1D *)baseplot->Clone(Form("%s_ERROR_LOWER", key->GetName())); TH1 *meanplot = (TH1D *)baseplot->Clone(Form("%s_SET_MEAN", key->GetName())); TH1 *systplot = (TH1D *)baseplot->Clone(Form("%s_SYST", key->GetName())); TH1 *statplot = (TH1D *)baseplot->Clone(Form("%s_STAT", key->GetName())); TH1 *totlplot = (TH1D *)baseplot->Clone(Form("%s_TOTAL", key->GetName())); int nbins = 0; if (cl->InheritsFrom("TH1D")) nbins = ((TH1D *)baseplot)->GetNbinsX(); else nbins = ((TH1D *)baseplot)->GetNbinsX() * ((TH1D *)baseplot)->GetNbinsY(); meanplot->Reset(); errorplot_upper->Reset(); errorplot_lower->Reset(); for (int j = 0; j < nbins; j++) { errorplot_upper->SetBinError(j + 1, 0.0); errorplot_lower->SetBinError(j + 1, 0.0); } // Loop over throws and calculate mean and error for +- throws int addcount = 0; // Add baseplot first to slightly bias to central value meanplot->Add(baseplot); addcount++; for (int i = 0; i < count; i++) { TH1 *newplot = (TH1D *)throwsdir->Get(Form("throw_%i/%s", i, plotname.c_str())); if (!newplot) { NUIS_ERR(WRN, "Cannot find new plot : " << Form("throw_%i/%s", i, plotname.c_str())); NUIS_ERR(WRN, "This plot will not have the correct errors!"); continue; } newplot->SetDirectory(0); nbins = newplot->GetNbinsX(); for (int j = 0; j < nbins; j++) { if (i % 2 == 0) { errorplot_upper->SetBinContent( j + 1, errorplot_upper->GetBinContent(j + 1) + pow(baseplot->GetBinContent(j + 1) - newplot->GetBinContent(j + 1), 2)); } else { errorplot_lower->SetBinContent( j + 1, errorplot_lower->GetBinContent(j + 1) + pow(baseplot->GetBinContent(j + 1) - newplot->GetBinContent(j + 1), 2)); } meanplot->SetBinContent(j + 1, meanplot->GetBinContent(j + 1) + baseplot->GetBinContent(j + 1)); } delete newplot; addcount++; } // Get mean Average for (int j = 0; j < nbins; j++) { meanplot->SetBinContent(j + 1, meanplot->GetBinContent(j + 1) / double(addcount)); } for (int j = 0; j < nbins; j++) { errorplot_upper->SetBinContent( j + 1, sqrt(errorplot_upper->GetBinContent(j + 1))); errorplot_lower->SetBinContent( j + 1, sqrt(errorplot_lower->GetBinContent(j + 1))); statplot->SetBinError(j + 1, baseplot->GetBinError(j + 1)); systplot->SetBinError(j + 1, (errorplot_upper->GetBinContent(j + 1) + errorplot_lower->GetBinContent(j + 1)) / 2.0); totlplot->SetBinError(j + 1, sqrt(pow(statplot->GetBinError(j + 1), 2) + pow(systplot->GetBinError(j + 1), 2))); meanplot->SetBinError(j + 1, sqrt(pow(statplot->GetBinError(j + 1), 2) + pow(systplot->GetBinError(j + 1), 2))); } outerr->cd(); errorplot_upper->Write(); errorplot_lower->Write(); baseplot->Write(); meanplot->Write(); statplot->Write(); systplot->Write(); totlplot->Write(); delete errorplot_upper; delete errorplot_lower; delete baseplot; delete meanplot; delete statplot; delete systplot; delete totlplot; } } diff --git a/src/Routines/SystematicRoutines.h b/src/Routines/SystematicRoutines.h index b069a4b..e40a2bb 100755 --- a/src/Routines/SystematicRoutines.h +++ b/src/Routines/SystematicRoutines.h @@ -1,269 +1,269 @@ // 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 SYSTEMATIC_ROUTINES_H #define SYSTEMATIC_ROUTINES_H /*! * \addtogroup Minimizer * @{ */ #include "TH1.h" #include "TF1.h" #include "TMatrixD.h" #include "TVectorD.h" #include "TSystem.h" #include "TFile.h" #include "TProfile.h" #include #include #include #include #include #include #include "FitEvent.h" #include "JointFCN.h" #include "TMatrixDSymEigen.h" #include "ParserUtils.h" enum minstate { kErrorStatus = -1, kGoodStatus, kFitError, kNoChange, kFitFinished, kFitUnfinished, kStateChange, }; //************************************* //! Collects all possible fit routines into a single class to avoid repeated code class SystematicRoutines{ //************************************* public: /* Constructor/Destructor */ //! Constructor reads in arguments given at the command line for the fit here. SystematicRoutines(int argc, char* argv[]); //! Default destructor ~SystematicRoutines(); //! Reset everything to default/NULL void Init(); /* Input Functions */ //! Splits the arguments ready for initial setup void ParseArgs(int argc, char* argv[]); //! Sorts out configuration and verbosity right at the very start. //! Calls readCard to set everything else up. void InitialSetup(); //! Loops through each line of the card file and passes it to other read functions void ReadCard(std::string cardfile); //! Check for parameter string in the line and assign the correct type. //! Fills maps for each of the parameters int ReadParameters(std::string parstring); //! Reads in fake parameters and assigns them (Requires the parameter to be included as a normal parameter as well) int ReadFakeDataPars(std::string parstring); //! Read in the samples so we can set up the free normalisation dials if required int ReadSamples(std::string sampleString); /* Setup Functions */ void SetupSystematicsFromXML(); //! Setup the configuration given the arguments passed at the commandline and card file void SetupConfig(); //! Setups up our custom RW engine with all the parameters passed in the card file void SetupRWEngine(); //! Setups up the jointFCN. void SetupFCN(); //! Sets up the minimizerObj for ROOT. there are cases where this is called repeatedly, e.g. If you are using a brute force scan before using Migrad. void SetupFitter(std::string routine); //! Set the current data histograms in each sample to the fake data. void SetFakeData(); //! Setup the covariances with the correct dimensions. At the start this is either uncorrelated or merged given all the input covariances. //! At the end of the fit this produces the blank covariances which can then be filled by the minimizerObj with best fit covariances. void SetupCovariance(); void GetCovarFromFCN(); /* Fitting Functions */ //! Main function to actually start iterating over the different required fit routines void Run(); //! Given a new map change the values that the RW engine is currently set to void UpdateRWEngine(std::map& updateVals); //! Given a single routine (see tutorial for options) run that fit routine now. int RunFitRoutine(std::string routine); //! Print current value void PrintState(); //! Performs a fit routine where the input.maxevents is set to a much lower value to try and move closer to the best fit minimum. void LowStatRoutine(std::string routine); //! Perform a chi2 scan in 1D around the current point void Create1DScans(); //! Perform a chi2 scan in 2D around the current point void Chi2Scan2D(); //! Currently a placeholder NEEDS UPDATING void CreateContours(); //! If any currentVals are close to the limits set them to the limit and fix them int FixAtLimit(); //! Throw the current covariance of dial values we have, and fill the thrownVals and thrownNorms maps. //! If uniformly is true parameters will be thrown uniformly between their upper and lower limits. void ThrowCovariance(bool uniformly); //! Given the covariance we currently have generate error bands by throwing the covariance. //! The FitPar config "error_uniform" defines whether to throw using the covariance or uniformly. //! The FitPar config "error_throws" defines how many throws are needed. //! Currently only supports TH1D plots. void GenerateErrorBands(); void GenerateThrows(); void MergeThrows(); //! Step through each parameter one by one and create folders containing the MC predictions at each step. //! Doesn't handle correlated parameters well void PlotLimits(); void EigenErrors(); /* Write Functions */ //! Save the sample plots for current MC //! dir if not empty forces plots to be saved in a subdirectory of outputfile void SaveCurrentState(std::string subdir=""); - //! Save starting predictions into a seperate folder + //! Save starting predictions into a separate folder void SaveNominal(); - //! Save predictions before the main study is ran into a seperate folder + //! Save predictions before the main study is ran into a separate folder void SavePrefit(); //! Save final outputs void SaveResults(); /* MISC Functions */ //! Get previous fit status from a file Int_t GetStatus(); protected: //! Our Custom ReWeight Object FitWeight* rw; std::string fOutputFile; std::string fInputFile; TFile* fInputRootFile; TFile* fOutputRootFile; //! Flag for whether the fit should be continued if an output file is already found. bool fitContinue; //! Minimizer Object for handling roots different minimizer methods JointFCN* fSampleFCN; int nfreepars; std::string fCardFile; std::string fStrategy; std::vector fRoutines; std::string fAllowedRoutines; std::string fFakeDataInput; // Input Dial Vals //! Vector of dial names std::vector fParams; std::map fStateVals; std::map fStartVals; std::map fCurVals; std::map fErrorVals; std::map fMinVals; std::map fMaxVals; std::map fStepVals; std::map fTypeVals; std::map fFixVals; std::map fStartFixVals; //! Vector of fake parameter names std::map fFakeVals; //! Map of thrown parameter names and values (After ThrowCovariance) std::map fThrownVals; TH2D* fCorrel; TH2D* fDecomp; TH2D* fCovar; TH2D* fCorrelFree; TH2D* fDecompFree; TH2D* fCovarFree; std::list fInputThrows; //!< Pointers to pull terms std::vector fInputDials; //!< Vector of Input Histograms std::vector fInputCovar; //!< Vector of Input Covariances nuiskey fCompKey; std::vector fThrowList; std::string fThrowString; int fNThrows; int fStartThrows; }; /*! @} */ #endif diff --git a/src/Splines/SplineWriter.cxx b/src/Splines/SplineWriter.cxx index 06be1b6..4c7cb21 100644 --- a/src/Splines/SplineWriter.cxx +++ b/src/Splines/SplineWriter.cxx @@ -1,780 +1,782 @@ #include "SplineWriter.h" using namespace SplineUtils; // Spline reader should have access to every spline. // Should know when reconfigure is called what its limits are and adjust // accordingly. Then should pass it the index required in the stack as // &xvals[index], and &pars[parindex] void SplineWriter::Write(std::string name) { // Create a TTree with each form and scan points in it. TTree *tr = new TTree(name.c_str(), name.c_str()); // Loop over all splines and add a TString in the TTree for its inputs tr->Branch("Spline", &fSpline); tr->Branch("Type", &fType); tr->Branch("Form", &fForm); tr->Branch("Points", &fPoints); tr->Fill(); tr->Write(); delete tr; } void SplineWriter::AddWeightsToTree(TTree *tr) { // Add only the fitted spline coefficients to the ttree std::cout << "Saving Spline Weights to TTree = " << Form("SplineWeights[%d]/F", (int)fValList.size()) << std::endl; // sleep(1); tr->Branch("SplineWeights", fWeightList, Form("SplineWeights[%d]/D", (int)fValList.size())); } void SplineWriter::ReadWeightsFromTree(TTree *tr) { tr->SetBranchAddress("SplineWeights", fWeightList); } void SplineWriter::AddCoefficientsToTree(TTree *tr) { // Add only the fitted spline coefficients to the ttree std::cout << "Saving Spline Coeff to TTree = " << Form("SplineCoeff[%d]/F", fNCoEff) << std::endl; // sleep(1); tr->Branch("SplineCoeff", fCoEffStorer, Form("SplineCoeff[%d]/F", fNCoEff)); } void SplineWriter::SetupSplineSet() { std::cout << "Setting up spline set" << std::endl; fDrawSplines = FitPar::Config().GetParB("draw_splines"); // Create the coefficients double* fNCoEff = 0; for (size_t i = 0; i < fAllSplines.size(); i++) { fNCoEff += fAllSplines[i].GetNPar(); } fCoEffStorer = new float[fNCoEff]; std::cout << "NCoeff = " << fNCoEff << std::endl; // Calculate the grid of parsets // Setup the list of parameter coefficients. std::vector nomvals = fRW->GetDialValues(); fParVect.clear(); fSetIndex.clear(); fParVect.push_back(nomvals); fSetIndex.push_back(0); // fWeightList.push_back(1.0); fValList.push_back(std::vector(1, 0.0)); // Loop over all splines. for (size_t i = 0; i < fAllSplines.size(); i++) { // For each dial loop over all points within a given position std::vector newvals = nomvals; std::vector pos; // = SplineUtils::GetSplitDialPositions(fRW, fSpline[i]); std::vector splitnames = GeneralUtils::ParseToStr(fSpline[i], ";"); for (size_t j = 0; j < splitnames.size(); j++) { int temppos = fRW->GetDialPos(splitnames[j]); pos.push_back(temppos); } std::vector > vals = SplineUtils::GetSplitDialPoints(fPoints[i]); for (size_t j = 0; j < vals.size(); j++) { for (size_t k = 0; k < pos.size(); k++) { newvals[pos[k]] = vals[j][k]; } fParVect.push_back(newvals); fValList.push_back(vals[j]); // fWeightList.push_back(1.0); fSetIndex.push_back(i + 1); } } fWeightList = new double[fValList.size()]; for (uint i = 0; i < fValList.size(); i++) { fWeightList[i] = 1.0; } // Print out the parameter set NUIS_LOG(FIT, "Parset | Index | Pars --- "); for (size_t i = 0; i < fSetIndex.size(); i++) { NUIS_LOGN(FIT, " Set " << i << ". | " << fSetIndex[i] << " | "); if (LOG_LEVEL(FIT)) { for (size_t j = 0; j < fParVect[i].size(); j++) { NUIS_LOGN(FIT, " " << fParVect[i][j]); } NUIS_LOG(FIT, ""); } } } void SplineWriter::GetWeightsForEvent(FitEvent *event) { // Get Starting Weight fRW->SetAllDials(&fParVect[0][0], fParVect[0].size()); double nomweight = fRW->CalcWeight(event); event->RWWeight = nomweight; if (fDrawSplines) { std::cout << "Nominal Spline Weight = " << nomweight << std::endl; } fWeightList[0] = nomweight; // Loop over parameter sets for (size_t i = 1; i < fParVect.size(); i++) { // Update FRW fRW->SetAllDials(&fParVect[i][0], fParVect[i].size()); // Calculate a weight for event double weight = fRW->CalcWeight(event); if (weight >= 0.0 and weight < 200) { // Fill Weight Set fWeightList[i] = weight / nomweight; if (fDrawSplines) std::cout << "Calculating values from weight set " << i << " " << fParVect[i][0] << " = " << weight << " " << weight / nomweight << std::endl; } else { fWeightList[i] = 1.0; } } } void SplineWriter::GetWeightsForEvent(FitEvent *event, double *weights) { // Get Starting Weight fRW->SetAllDials(&fParVect[0][0], fParVect[0].size()); double nomweight = fRW->CalcWeight(event); event->RWWeight = nomweight; if (fDrawSplines) { std::cout << "Nominal Spline Weight = " << nomweight << std::endl; } weights[0] = nomweight; // Loop over parameter sets for (size_t i = 1; i < fParVect.size(); i++) { // Update FRW fRW->SetAllDials(&fParVect[i][0], fParVect[i].size()); // Calculate a weight for event double weight = fRW->CalcWeight(event); if (weight >= 0.0 and weight < 200) { // Fill Weight Set weights[i] = weight / nomweight; if (fDrawSplines) std::cout << "Calculating values from weight set " << i << " " << fParVect[i][0] << " = " << weight << " " << weight / nomweight << std::endl; } else { weights[i] = 1.0; } fWeightList[i] = weights[i]; } } void SplineWriter::ReconfigureSet(int iset) { fCurrentSet = iset; fRW->SetAllDials(&fParVect[iset][0], fParVect[iset].size()); } double SplineWriter::GetWeightForThisSet(FitEvent *event, int iset) { if (iset != -1 and iset != fCurrentSet) { ReconfigureSet(iset); } return fRW->CalcWeight(event); } void SplineWriter::SetWeights(double *weights) { for (uint i = 0; i < fParVect.size(); i++) { fWeightList[i] = weights[i]; } } void SplineWriter::FitSplinesForEvent(double *inputweights, float *coeff) { int n = fAllSplines.size(); int coeffcount = 0; for (int i = 0; i < n; i++) { // DialVals std::vector > dialvals; std::vector weightvals; bool hasresponse = false; for (size_t j = 0; j < fSetIndex.size(); j++) { if (fSetIndex[j] != i + 1) continue; dialvals.push_back(fValList[j]); double tempw = inputweights[j]; weightvals.push_back(tempw); if (tempw != 1.0) hasresponse = true; } // Perform Fit if (hasresponse) { // std::cout << "Fitting Coeff" << std::endl; FitCoeff(&fAllSplines[i], dialvals, weightvals, &coeff[coeffcount], fDrawSplines); } else { for (int j = 0; coeffcount + j < fNCoEff; j++) { // std::cout << "Setting 0.0 response " << coeffcount + i << " " << // fNCoEff << std::endl; coeff[coeffcount + j] = 0.0; } } // std::cout << "Adding coeffcount" << std::endl; // Offset coeffcount coeffcount += (fAllSplines[i]).GetNPar(); } // std::cout << "FitEvent" << std::endl; return; } void SplineWriter::FitSplinesForEvent(TCanvas *fitcanvas, bool saveplot) { // Loop over splines // int count = 0; int coeffcount = 0; int n = fAllSplines.size(); std::vector splinecounter; for (int i = 0; i < n; i++) { splinecounter.push_back(coeffcount); coeffcount += fAllSplines[i].GetNPar(); } // #pragma omp parallel for for (int i = 0; i < n; i++) { // Store X/Y Vals std::vector > dialvals; std::vector weightvals; bool hasresponse = false; int npar = (fAllSplines[i]).GetNPar(); coeffcount = splinecounter[i]; for (size_t j = 0; j < fSetIndex.size(); j++) { if (fSetIndex[j] != i + 1) continue; dialvals.push_back(fValList[j]); double tempw = fWeightList[j]; weightvals.push_back(tempw); if (tempw != 1.0) hasresponse = true; } // Make a new graph and fit coeff if response if (hasresponse) { FitCoeff(&fAllSplines[i], dialvals, weightvals, &fCoEffStorer[coeffcount], fDrawSplines); } else { for (int i = 0; i < npar; i++) { fCoEffStorer[coeffcount + i] = 0.0; } } } // Check overrides // if (saveplot) { // coeffcount = 0; // // Make new canvas to save stuff into // if (fitcanvas) delete fitcanvas; // fitcanvas = new TCanvas("c1", "c1", fAllSplines.size() * 400 , 600); // fitcanvas->Divide(fAllSplines.size(), 1); // // Clear out points // for (size_t i = 0; i < fAllDrawnGraphs.size(); i++) { // if (fAllDrawnGraphs[i]) delete fAllDrawnGraphs[i]; // if (fAllDrawnHists[i]) delete fAllDrawnHists[i]; // } // fAllDrawnGraphs.clear(); // fAllDrawnHists.clear(); // for (size_t i = 0; i < fAllSplines.size(); i++) { // fitcanvas->cd(i + 1); // // Store X/Y Vals // std::vector > dialvals; // std::vector weightvals; // bool hasresponse = false; // int npar = (fAllSplines[i]).GetNPar(); // for (size_t j = 0; j < fSetIndex.size(); j++) { // if ((UInt_t)fSetIndex[j] != (UInt_t)i + 1) continue; // dialvals.push_back(fValList[j]); // weightvals.push_back(fWeightList[j] - 0.0); // if (fWeightList[j] != 1.0) hasresponse = true; // } // if (hasresponse) { // TGraph* gr = new TGraph(dialvals.size(), dialvals, weightvals); // fAllDrawnGraphs.push_back(gr); // // Get XMax Min // int n = xvals.size(); // double xmin = 99999.9; // double xmax = -99999.9; // for (int j = 0; j < n; j++) { // if (xvals[j] > xmax) xmax = xvals[j]; // if (xvals[j] < xmin) xmin = xvals[j]; // } // TH1D* hist = new TH1D("temp", "temp", 100, xmin, xmax); // fAllDrawnHists.push_back(hist); // for (int k = 0; k < 100; k++) { // double xtemp = hist->GetXaxis()->GetBinCenter(k + 1); // fAllSplines[i].Reconfigure(xtemp); // double ytemp = fAllSplines[i].DoEval(&fCoEffStorer[coeffcount]); // hist->SetBinContent(k + 1, ytemp); // } // // gr->Draw("APL"); // hist->SetLineColor(kRed); // hist->Draw("HIST C"); // hist->SetTitle("Spline Response"); // // hist->GetYaxis()->SetRangeUser(0.0, 3.0); // // gStyle->SetOptStat(0); // hist->SetStats(0); // gr->SetMarkerStyle(20); // gr->SetTitle("True Weight Points"); // gr->Draw("P SAME"); // gPad->BuildLegend(0.6, 0.6, 0.85, 0.85); // gPad->Update(); // hist->SetTitle(fSpline[i].c_str()); // hist->GetXaxis()->SetTitle("Dial Variation"); // hist->GetYaxis()->SetTitle("Event Weight"); // fitcanvas->Update(); // } // coeffcount += npar; // } // } } // Fitting // ---------------------------------------------- void SplineWriter::FitCoeff(Spline *spl, std::vector > &v, std::vector &w, float *coeff, bool draw) { std::vector x; std::vector y; std::vector z; for (size_t i = 0; i < v.size(); i++) { x.push_back(v[i][0]); if (v[i].size() > 1) y.push_back(v[i][1]); if (v[i].size() > 2) z.push_back(v[i][2]); } switch (spl->GetType()) { // Polynominal Graph Fits case k1DPol1: case k1DPol2: case k1DPol3: case k1DPol4: case k1DPol5: case k1DPol6: FitCoeff1DGraph(spl, v.size(), &x[0], &w[0], coeff, draw); break; case k1DTSpline3: GetCoeff1DTSpline3(spl, x.size(), &x[0], &w[0], coeff, draw); break; case k2DPol6: case k2DGaus: case k2DTSpline3: FitCoeff2DGraph(spl, v.size(), &x[0], &y[0], &w[0], coeff, draw); break; default: break; } #ifdef __MINUIT2_ENABLED__ if (fDrawSplines) { fSplineFCNs[spl] = new SplineFCN(spl, v, w); fSplineFCNs[spl]->SaveAs("mysplinetest_" + spl->GetName() + ".pdf", coeff); sleep(1); delete fSplineFCNs[spl]; } #endif } void SplineWriter::FitCoeff1DGraph(Spline *spl, int n, double *x, double *y, float *coeff, bool draw) { TGraph *gr = new TGraph(n, x, y); double xmin = 99999.9; double xmax = -99999.9; for (int i = 0; i < n; i++) { if (x[i] > xmax) xmax = x[i]; if (x[i] < xmin) xmin = x[i]; } double xwidth = xmax - xmin; xmin = xmin - xwidth * 0.01; xmax = xmax + xwidth * 0.01; // Create a new function for fitting. TF1 *func = spl->GetFunction(); // Run the actual spline fit StopTalking(); // If linear fit with two points if (n == 2 and spl->GetType() == k1DPol1) { float m = (y[1] - y[0]) / (x[1] - x[0]); float c = y[0] - (0.0 - x[0]) * m; func->SetParameter(0, c); func->SetParameter(1, m); } else if (spl->GetType() == k1DPol1) { gr->Fit(func, "WQ"); } else { gr->Fit(func, "FMWQ"); } StartTalking(); for (int i = 0; i < spl->GetNPar(); i++) { coeff[i] = func->GetParameter(i); } if (draw) { gr->Draw("APL"); gPad->Update(); gPad->SaveAs(("plot_test_" + spl->GetName() + ".pdf").c_str()); std::cout << "Saving Graph" << std::endl; sleep(3); } // delete func; delete gr; } double SplineFCN::operator()(const double *x) const { return DoEval(x); } double SplineFCN::DoEval(const double *x) const { float *fx = new float[fSpl->GetNPar()]; for (int i = 0; i < fSpl->GetNPar(); i++) { fx[i] = x[i]; } // double tot = 0; for (size_t i = 0; i < fVal.size(); i++) { int nonzero = 0; for (size_t j = 0; j < fVal[i].size(); j++) { fSpl->Reconfigure(fVal[i][j], j); // std::cout << "Reconfiguring " << fVal[i][j] << " " << j << std::endl; if (fVal[i][j] != 0.0) nonzero++; } if (uncorrelated and nonzero > 1) continue; double w = fSpl->DoEval(fx); double wdif = (w - fWeight[i]); // / (fWeight[i] * 0.05); tot += sqrt(wdif * wdif); } // delete fx; return tot; } void SplineFCN::UpdateWeights(std::vector &w) { for (uint i = 0; i < w.size(); i++) { fWeight[i] = w[i]; } } void SplineFCN::SetCorrelated(bool state) { uncorrelated = !state; } void SplineFCN::SaveAs(std::string name, const float *fx) { if (fVal[0].size() > 2) { TCanvas *c1 = new TCanvas("c1", "c1", 800, 600); c1->Divide(2, 1); TH1D *histmc = new TH1D("hist", "hist", fVal.size(), 0.0, double(fVal.size())); TH1D *histdt = new TH1D("histdt", "histdt", fVal.size(), 0.0, double(fVal.size())); for (size_t i = 0; i < fVal.size(); i++) { for (size_t j = 0; j < fVal[i].size(); j++) { fSpl->Reconfigure(fVal[i][j], j); } histmc->SetBinContent(i + 1, fSpl->DoEval(fx)); histdt->SetBinContent(i + 1, fWeight[i]); } // histmc->Add(histdt,-1.0); c1->cd(1); histmc->SetTitle("Spline;Parameter Set;Weight"); histmc->Draw("HIST"); histdt->SetLineColor(kRed); histdt->Draw("SAME HIST"); c1->cd(2); TH1D *histdif = (TH1D *)histmc->Clone(); histdif->Add(histdt, -1.0); histdif->Draw("HIST"); c1->Update(); c1->SaveAs(name.c_str()); delete c1; } else if (fVal[0].size() == 2) { TGraph2D *histmc = new TGraph2D(); TGraph2D *histdt = new TGraph2D(); TGraph2D *histdif = new TGraph2D(); for (size_t i = 0; i < fVal.size(); i++) { for (size_t j = 0; j < fVal[i].size(); j++) { fSpl->Reconfigure(fVal[i][j], j); } histmc->SetPoint(histmc->GetN(), fVal[i][0], fVal[i][1], fSpl->DoEval(fx)); histdt->SetPoint(histdt->GetN(), fVal[i][0], fVal[i][1], fWeight[i]); histdif->SetPoint(histdif->GetN(), fVal[i][0], fVal[i][1], fabs(fSpl->DoEval(fx) - fWeight[i])); } TCanvas *c1 = new TCanvas("c1", "c1", 800, 600); c1->Divide(3, 1); c1->cd(1); histmc->SetTitle(("Spline;" + fSpl->GetName()).c_str()); histmc->Draw("COLZ"); gPad->Update(); c1->cd(2); histdt->SetTitle(("Raw;" + fSpl->GetName()).c_str()); histdt->Draw("COLZ"); c1->cd(3); histdif->SetTitle(("Dif;" + fSpl->GetName()).c_str()); histdif->Draw("COLZ"); gPad->SetRightMargin(0.15); // gPad->SetLogz(1); gPad->Update(); c1->SaveAs(name.c_str()); delete c1; } else if (fVal[0].size() == 1) { TGraph *histmc = new TGraph(); TGraph *histdt = new TGraph(); TGraph *histdif = new TGraph(); for (size_t i = 0; i < fVal.size(); i++) { for (size_t j = 0; j < fVal[i].size(); j++) { fSpl->Reconfigure(fVal[i][j], j); } histmc->SetPoint(histmc->GetN(), fVal[i][0], fSpl->DoEval(fx)); histdt->SetPoint(histdt->GetN(), fVal[i][0], fWeight[i]); histdif->SetPoint(histdif->GetN(), fVal[i][0], fabs(fSpl->DoEval(fx) - fWeight[i])); } TCanvas *c1 = new TCanvas("c1", "c1", 800, 600); c1->Divide(2, 1); c1->cd(1); histmc->SetTitle(("Spline;" + fSpl->GetName()).c_str()); histmc->Draw("AC"); histmc->SetLineColor(kRed); histdt->SetTitle(("Raw;" + fSpl->GetName()).c_str()); histdt->Draw("SAME P"); histdt->SetMarkerStyle(20); gPad->Update(); c1->cd(2); histdif->SetTitle(("Dif;" + fSpl->GetName()).c_str()); histdif->Draw("APL"); gPad->Update(); c1->SaveAs(name.c_str()); delete c1; } // gPad->SaveAs(name.c_str()); } void SplineWriter::FitCoeff2DGraph(Spline *spl, int n, double *x, double *y, double *w, float *coeff, bool draw) { +#ifdef __USE_OPENMP__ #pragma omp critical +#endif { TF2 *f2 = (TF2 *)spl->GetFunction(); TGraph2D *histmc = new TGraph2D(n, x, y, w); f2->SetNpx(400); StopTalking(); histmc->Fit(f2, "FMWQ"); StartTalking(); for (int i = 0; i < spl->GetNPar(); i++) { coeff[i] = f2->GetParameter(i); } // delete f2; delete histmc; } } void SplineWriter::FitCoeffNDGraph(Spline *spl, std::vector > &v, std::vector &w, float *coeff, bool draw) { #ifdef __MINUIT2_ENABLED__ if (fSplineFunctors.find(spl) != fSplineFunctors.end()) { delete fSplineFunctors[spl]; fSplineFunctors.erase(spl); } if (fSplineFCNs.find(spl) != fSplineFCNs.end()) { delete fSplineFCNs[spl]; fSplineFCNs.erase(spl); } if (fSplineMinimizers.find(spl) != fSplineMinimizers.end()) { delete fSplineMinimizers[spl]; fSplineMinimizers.erase(spl); } if (fSplineMinimizers.find(spl) == fSplineMinimizers.end()) { std::cout << "Building new ND minimizer for " << spl << std::endl; fSplineFCNs[spl] = new SplineFCN(spl, v, w); // fSplineFCNs[spl] = new SplineFCN(spl, v, w); fSplineFunctors[spl] = new ROOT::Math::Functor(*fSplineFCNs[spl], spl->GetNPar()); fSplineMinimizers[spl] = ROOT::Math::Factory::CreateMinimizer("Minuit2", "Combined"); fSplineMinimizers[spl]->SetMaxFunctionCalls(1E8); fSplineMinimizers[spl]->SetMaxIterations(1E8); fSplineMinimizers[spl]->SetTolerance(1.E-6); fSplineMinimizers[spl]->SetStrategy(2); for (int j = 0; j < spl->GetNPar(); j++) { fSplineMinimizers[spl]->SetVariable(j, Form("Par_%i", j), 0.1, 0.1); } } // Create a new function for fitting. // StopTalking(); // Update FCN fSplineFCNs[spl]->UpdateWeights(w); // fSplineMinimizers[spl]->SetDefaultOptions(); // fSplineMinimizers[spl]->Clear(); for (int j = 0; j < spl->GetNPar(); j++) { if (j != 0) { fSplineMinimizers[spl]->SetVariableValue(j, 0.1); // fSplineMinimizers[spl]->SetParameter(j, Form("Par_%i", j), 0.1, 0.1, // -100.0, 100.0 ); // fSplineMinimizers[spl]->SetVariableValue(j, 0.1); } } // fSplineFCNs[spl]->SetCorrelated(false); // fSplineFunctors[spl] = new ROOT::Math::Functor( *fSplineFCNs[spl], // spl->GetNPar() ); // fSplineMinimizers[spl]->SetFunction(*fSplineFunctors[spl]); // fSplineMinimizers[spl]->Minimize(); fSplineFCNs[spl]->SetCorrelated(true); delete fSplineFunctors[spl]; fSplineFunctors[spl] = new ROOT::Math::Functor(*fSplineFCNs[spl], spl->GetNPar()); fSplineMinimizers[spl]->SetFunction(*fSplineFunctors[spl]); // ((TFitterMinuit*)fSplineMinimizers[spl])->CreateMinimizer(TFitterMinuit::kMigrad); fSplineMinimizers[spl]->Minimize(); fSplineMinimizers[spl]->Minimize(); // ((TFitterMinuit*)fSplineMinimizers[spl])->CreateMinimizer(TFitterMinuit::kMigrad); // fSplineMinimizers[spl]->Minimize(); // delete minimizer; // StartTalking(); // Now Get Parameters const double *values = fSplineMinimizers[spl]->X(); for (int i = 0; i < spl->GetNPar(); i++) { std::cout << "Updated Coeff " << i << " " << values[i] << std::endl; coeff[i] = values[i]; } // Save a sample fSplineFCNs[spl]->SaveAs("mysplinetest_" + spl->GetName() + ".pdf", coeff); sleep(1); // delete values; // delete minimizer; #endif } // Spline extraction Functions void SplineWriter::GetCoeff1DTSpline3(Spline *spl, int n, double *x, double *y, float *coeff, bool draw) { StopTalking(); TSpline3 temp_spline = TSpline3("temp_spline", x, y, n); StartTalking(); for (size_t i = 0; i < (UInt_t)n; i++) { double a, b, c, d, e; temp_spline.GetCoeff(i, a, b, c, d, e); coeff[i * 4] = y[i]; coeff[i * 4 + 1] = c; coeff[i * 4 + 2] = d; coeff[i * 4 + 3] = e; } if (draw) { TGraph *gr = new TGraph(n, x, y); temp_spline.Draw("CA"); gr->Draw("PL SAME"); gPad->Update(); gPad->SaveAs(("plot_test_" + spl->GetName() + ".pdf").c_str()); delete gr; } return; } diff --git a/src/Statistical/StatUtils.cxx b/src/Statistical/StatUtils.cxx index 84df519..8b57374 100644 --- a/src/Statistical/StatUtils.cxx +++ b/src/Statistical/StatUtils.cxx @@ -1,1622 +1,1621 @@ // 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 "StatUtils.h" #include "GeneralUtils.h" #include "NuisConfig.h" #include "TH1D.h" //******************************************************************* Double_t StatUtils::GetChi2FromDiag(TH1D *data, TH1D *mc, TH1I *mask) { //******************************************************************* Double_t Chi2 = 0.0; TH1D *calc_data = (TH1D *)data->Clone("calc_data"); calc_data->SetDirectory(NULL); TH1D *calc_mc = (TH1D *)mc->Clone("calc_mc"); calc_mc->SetDirectory(NULL); // Add MC Error to data if required if (FitPar::Config().GetParB("addmcerror")) { for (int i = 0; i < calc_data->GetNbinsX(); i++) { double dterr = calc_data->GetBinError(i + 1); double mcerr = calc_mc->GetBinError(i + 1); if (dterr > 0.0) { calc_data->SetBinError(i + 1, sqrt(dterr * dterr + mcerr * mcerr)); } } } // Apply masking if required if (mask) { calc_data = ApplyHistogramMasking(data, mask); calc_data->SetDirectory(NULL); calc_mc = ApplyHistogramMasking(mc, mask); calc_mc->SetDirectory(NULL); } // Iterate over bins in X for (int i = 0; i < calc_data->GetNbinsX(); i++) { // Ignore bins with zero data or zero bin error if (calc_data->GetBinError(i + 1) <= 0.0 || calc_data->GetBinContent(i + 1) == 0.0) continue; // Take mc data difference double diff = calc_data->GetBinContent(i + 1) - calc_mc->GetBinContent(i + 1); double err = calc_data->GetBinError(i + 1); Chi2 += (diff * diff) / (err * err); } // cleanup delete calc_data; delete calc_mc; return Chi2; }; //******************************************************************* Double_t StatUtils::GetChi2FromDiag(TH2D *data, TH2D *mc, TH2I *map, TH2I *mask) { //******************************************************************* // Generate a simple map bool made_map = false; if (!map) { map = GenerateMap(data); made_map = true; } // Convert to 1D Histograms TH1D *data_1D = MapToTH1D(data, map); TH1D *mc_1D = MapToTH1D(mc, map); TH1I *mask_1D = MapToMask(mask, map); // Calculate 1D chi2 from 1D Plots Double_t Chi2 = StatUtils::GetChi2FromDiag(data_1D, mc_1D, mask_1D); // CleanUp delete data_1D; delete mc_1D; delete mask_1D; if (made_map) { delete map; } return Chi2; }; //******************************************************************* Double_t StatUtils::GetChi2FromCov(TH1D *data, TH1D *mc, TMatrixDSym *invcov, TH1I *mask, double data_scale, double covar_scale, TH1D *outchi2perbin) { //******************************************************************* static bool first = true; static bool UseSVDDecomp = false; if (first) { UseSVDDecomp = FitPar::Config().GetParB("UseSVDInverse"); first = false; } Double_t Chi2 = 0.0; TMatrixDSym *calc_cov = (TMatrixDSym *)invcov->Clone("local_invcov"); TH1D *calc_data = (TH1D *)data->Clone("local_data"); TH1D *calc_mc = (TH1D *)mc->Clone("local_mc"); calc_data->SetDirectory(NULL); calc_mc->SetDirectory(NULL); // If a mask if applied we need to apply it before the matrix is inverted if (mask) { calc_cov = ApplyInvertedMatrixMasking(invcov, mask); calc_data = ApplyHistogramMasking(data, mask); calc_mc = ApplyHistogramMasking(mc, mask); } if (data->GetNbinsX() != invcov->GetNcols()) { NUIS_ERR(WRN, "Inconsistent matrix and data histogram passed to " "StatUtils::GetChi2FromCov!"); NUIS_ABORT("data_hist has " << data->GetNbinsX() << " matrix has " << invcov->GetNcols() << "bins"); } // Add MC Error to data if required if (FitPar::Config().GetParB("statutils.addmcerror")) { // Make temp cov TMatrixDSym *newcov = StatUtils::GetInvert(calc_cov, true); // Add MC err to diag for (int i = 0; i < calc_data->GetNbinsX(); i++) { double mcerr = calc_mc->GetBinError(i + 1) * sqrt(covar_scale); double oldval = (*newcov)(i, i); NUIS_LOG(FIT, "Adding cov stat " << mcerr * mcerr << " to " << (*newcov)(i, i)); (*newcov)(i, i) = oldval + mcerr * mcerr; } // Reset the calc_cov to new invert delete calc_cov; calc_cov = GetInvert(newcov, true); // Delete the tempcov delete newcov; } calc_data->Scale(data_scale); calc_mc->Scale(data_scale); (*calc_cov) *= covar_scale; // iterate over bins in X (i,j) NUIS_LOG(DEB, "START Chi2 Calculation================="); for (int i = 0; i < calc_data->GetNbinsX(); i++) { double ibin_contrib = 0; NUIS_LOG(DEB, "[CHI2] i = " << i << " [" << calc_data->GetXaxis()->GetBinLowEdge(i + 1) << " -- " << calc_data->GetXaxis()->GetBinUpEdge(i + 1) << "]."); for (int j = 0; j < calc_data->GetNbinsX(); j++) { NUIS_LOG(DEB, "[CHI2]\t j = " << i << " [" << calc_data->GetXaxis()->GetBinLowEdge(j + 1) << " -- " << calc_data->GetXaxis()->GetBinUpEdge(j + 1) << "]."); if (((calc_data->GetBinContent(i + 1) != 0) && (calc_mc->GetBinContent(i + 1) != 0)) && ((*calc_cov)(i, j) != 0)) { NUIS_LOG(DEB, "[CHI2]\t\t Chi2 contribution (i,j) = (" << i << "," << j << ")"); NUIS_LOG(DEB, "[CHI2]\t\t Data - MC(i) = " << calc_data->GetBinContent(i + 1) << " - " << calc_mc->GetBinContent(i + 1) << " = " << (calc_data->GetBinContent(i + 1) - calc_mc->GetBinContent(i + 1))); NUIS_LOG(DEB, "[CHI2]\t\t Data - MC(j) = " << calc_data->GetBinContent(j + 1) << " - " << calc_mc->GetBinContent(j + 1) << " = " << (calc_data->GetBinContent(j + 1) - calc_mc->GetBinContent(j + 1))); NUIS_LOG(DEB, "[CHI2]\t\t Covar = " << (*calc_cov)(i, j)); NUIS_LOG(DEB, "[CHI2]\t\t Cont chi2 = " << ((calc_data->GetBinContent(i + 1) - calc_mc->GetBinContent(i + 1)) * (*calc_cov)(i, j) * (calc_data->GetBinContent(j + 1) - calc_mc->GetBinContent(j + 1))) << " " << Chi2); double bin_cont = ((calc_data->GetBinContent(i + 1) - calc_mc->GetBinContent(i + 1)) * (*calc_cov)(i, j) * (calc_data->GetBinContent(j + 1) - calc_mc->GetBinContent(j + 1))); if (!UseSVDDecomp && (i == j) && ((*calc_cov)(i, j) < 0)) { NUIS_ABORT("Found negative diagonal covariance element: Covar(" << i << ", " << j << ") = " << ((*calc_cov)[i][j]) << ", data = " << calc_data->GetBinContent(i + 1) << ", mc = " << calc_mc->GetBinContent(i + 1) << " would contribute: " << bin_cont << " on top of: " << Chi2); } Chi2 += bin_cont; ibin_contrib += bin_cont; } else { NUIS_LOG(DEB, "Skipping chi2 contribution (i,j) = (" << i << "," << j << "), Data = " << calc_data->GetBinContent(i + 1) << ", MC = " << calc_mc->GetBinContent(i + 1) << ", Cov = " << (*calc_cov)(i, j)); Chi2 += 0.; } } if (outchi2perbin) { outchi2perbin->SetBinContent(i + 1, ibin_contrib); } } // Cleanup delete calc_cov; delete calc_data; delete calc_mc; return Chi2; } //******************************************************************* Double_t StatUtils::GetChi2FromCov(TH2D *data, TH2D *mc, TMatrixDSym *invcov, TH2I *map, TH2I *mask, TH2D *outchi2perbin) { //******************************************************************* // Generate a simple map bool made_map = false; if (!map) { map = StatUtils::GenerateMap(data); made_map = true; } // Convert to 1D Histograms TH1D *data_1D = MapToTH1D(data, map); TH1D *mc_1D = MapToTH1D(mc, map); TH1I *mask_1D = MapToMask(mask, map); TH1D *outchi2perbin_1D = outchi2perbin ? MapToTH1D(outchi2perbin, map) : NULL; - NUIS_LOG(SAM, "Calculating 2D covariance: got map ? " + NUIS_LOG(DEB, "Calculating 2D covariance: got map ? " << (!made_map) << ", Ndata bins: " << (data->GetNbinsX() * data->GetNbinsY()) << ", ncovbins: " << invcov->GetNcols() << ", mapped 1D hist NBins: " << data_1D->GetNbinsX()); // Calculate 1D chi2 from 1D Plots Double_t Chi2 = StatUtils::GetChi2FromCov(data_1D, mc_1D, invcov, mask_1D, 1, 1E76, outchi2perbin_1D); if (outchi2perbin && outchi2perbin_1D) { MapFromTH1D(outchi2perbin, outchi2perbin_1D, map); } // CleanUp delete data_1D; delete mc_1D; delete mask_1D; delete outchi2perbin_1D; if (made_map) { delete map; } return Chi2; } //******************************************************************* Double_t StatUtils::GetChi2FromSVD(TH1D *data, TH1D *mc, TMatrixDSym *cov, TH1I *mask) { //******************************************************************* Double_t Chi2 = 0.0; TMatrixDSym *calc_cov = (TMatrixDSym *)cov->Clone(); TH1D *calc_data = (TH1D *)data->Clone(); TH1D *calc_mc = (TH1D *)mc->Clone(); // If a mask if applied we need to apply it before the matrix is inverted if (mask) { calc_cov = StatUtils::ApplyMatrixMasking(cov, mask); calc_data = StatUtils::ApplyHistogramMasking(data, mask); calc_mc = StatUtils::ApplyHistogramMasking(mc, mask); } // Decompose matrix TDecompSVD LU = TDecompSVD((*calc_cov)); LU.Decompose(); TMatrixDSym *cov_U = new TMatrixDSym(calc_data->GetNbinsX(), LU.GetU().GetMatrixArray(), ""); TVectorD *cov_S = new TVectorD(LU.GetSig()); // Apply basis rotation before adding up chi2 Double_t rotated_difference = 0.0; for (int i = 0; i < calc_data->GetNbinsX(); i++) { rotated_difference = 0.0; // Rotate basis of Data - MC for (int j = 0; j < calc_data->GetNbinsY(); j++) rotated_difference += (calc_data->GetBinContent(j + 1) - calc_mc->GetBinContent(j + 1)) * (*cov_U)(j, i); // Divide by rotated error cov_S Chi2 += rotated_difference * rotated_difference * 1E76 / (*cov_S)(i); } // Cleanup delete calc_cov; delete calc_data; delete calc_mc; delete cov_U; delete cov_S; return Chi2; } //******************************************************************* Double_t StatUtils::GetChi2FromSVD(TH2D *data, TH2D *mc, TMatrixDSym *cov, TH2I *map, TH2I *mask) { //******************************************************************* // Generate a simple map bool made_map = false; if (!map) { made_map = true; map = StatUtils::GenerateMap(data); } // Convert to 1D Histograms TH1D *data_1D = MapToTH1D(data, map); TH1D *mc_1D = MapToTH1D(mc, map); TH1I *mask_1D = MapToMask(mask, map); // Calculate from 1D Double_t Chi2 = StatUtils::GetChi2FromSVD(data_1D, mc_1D, cov, mask_1D); // CleanUp delete data_1D; delete mc_1D; delete mask_1D; if (made_map) { delete map; } return Chi2; } //******************************************************************* double StatUtils::GetChi2FromEventRate(TH1D *data, TH1D *mc, TH1I *mask) { //******************************************************************* // If just an event rate, for chi2 just use Poission Likelihood to calculate // the chi2 component double chi2 = 0.0; TH1D *calc_data = (TH1D *)data->Clone(); TH1D *calc_mc = (TH1D *)mc->Clone(); // Apply masking if required if (mask) { calc_data = ApplyHistogramMasking(data, mask); calc_mc = ApplyHistogramMasking(mc, mask); } // Iterate over bins in X for (int i = 0; i < calc_data->GetNbinsX(); i++) { double dt = calc_data->GetBinContent(i + 1); double mc = calc_mc->GetBinContent(i + 1); if (mc <= 0) continue; if (dt <= 0) { // Only add difference chi2 += 2 * (mc - dt); } else { // Do the chi2 for Poisson distributions chi2 += 2 * (mc - dt + (dt * log(dt / mc))); } /* LOG(REC)<<"Evt Chi2 cont = "<Clone(); // If a mask is provided we need to apply it before getting NDOF if (mask) { calc_hist = StatUtils::ApplyHistogramMasking(hist, mask); } // NDOF is defined as total number of bins with non-zero errors Int_t NDOF = 0; for (int i = 0; i < calc_hist->GetNbinsX(); i++) { if (calc_hist->GetBinError(i + 1) > 0.0) NDOF++; } delete calc_hist; return NDOF; }; //******************************************************************* Int_t StatUtils::GetNDOF(TH2D *hist, TH2I *map, TH2I *mask) { //******************************************************************* Int_t NDOF = 0; bool made_map = false; if (!map) { made_map = true; map = StatUtils::GenerateMap(hist); } for (int i = 0; i < hist->GetNbinsX(); i++) { for (int j = 0; j < hist->GetNbinsY(); j++) { if (mask->GetBinContent(i + 1, j + 1)) continue; if (map->GetBinContent(i + 1, j + 1) <= 0) continue; NDOF++; } } if (made_map) { delete map; } return NDOF; }; //******************************************************************* TH1D *StatUtils::ThrowHistogram(TH1D *hist, TMatrixDSym *cov, bool throwdiag, TH1I *mask) { //******************************************************************* TH1D *calc_hist = (TH1D *)hist->Clone((std::string(hist->GetName()) + "_THROW").c_str()); TMatrixDSym *calc_cov = (TMatrixDSym *)cov->Clone(); Double_t correl_val = 0.0; // If a mask if applied we need to apply it before the matrix is decomposed if (mask) { calc_cov = ApplyMatrixMasking(cov, mask); calc_hist = ApplyHistogramMasking(calc_hist, mask); } // If a covariance is provided we need a preset random vector and a decomp std::vector rand_val; TMatrixDSym *decomp_cov = NULL; if (cov) { for (int i = 0; i < hist->GetNbinsX(); i++) { rand_val.push_back(gRandom->Gaus(0.0, 1.0)); } // Decomp the matrix decomp_cov = StatUtils::GetDecomp(calc_cov); } // iterate over bins for (int i = 0; i < hist->GetNbinsX(); i++) { // By Default the errors on the histogram are thrown uncorrelated to the // other errors /* if (throwdiag) { calc_hist->SetBinContent(i + 1, (calc_hist->GetBinContent(i + 1) + \ gRandom->Gaus(0.0, 1.0) * calc_hist->GetBinError(i + 1)) ); } */ // If a covariance is provided that is also thrown if (cov) { correl_val = 0.0; for (int j = 0; j < hist->GetNbinsX(); j++) { correl_val += rand_val[j] * (*decomp_cov)(j, i); } calc_hist->SetBinContent( i + 1, (calc_hist->GetBinContent(i + 1) + correl_val * 1E-38)); } } delete calc_cov; delete decomp_cov; // return this new thrown data return calc_hist; }; //******************************************************************* TH2D *StatUtils::ThrowHistogram(TH2D *hist, TMatrixDSym *cov, TH2I *map, bool throwdiag, TH2I *mask) { //******************************************************************* // PLACEHOLDER!!!!!!!!! // Currently no support for throwing 2D Histograms from a covariance (void)hist; (void)cov; (void)map; (void)throwdiag; (void)mask; // /todo // Sort maps if required // Throw the covariance for a 1D plot // Unmap back to 2D Histogram return hist; } //******************************************************************* TH1D *StatUtils::ApplyHistogramMasking(TH1D *hist, TH1I *mask) { //******************************************************************* if (!mask) return ((TH1D *)hist->Clone()); // This masking is only sufficient for chi2 calculations, and will have dodgy // bin edges. // Get New Bin Count Int_t NBins = 0; for (int i = 0; i < hist->GetNbinsX(); i++) { if (mask->GetBinContent(i + 1)) continue; NBins++; } // Make new hist std::string newmaskname = std::string(hist->GetName()) + "_MSKD"; TH1D *calc_hist = new TH1D(newmaskname.c_str(), newmaskname.c_str(), NBins, 0, NBins); // fill new hist int binindex = 0; for (int i = 0; i < hist->GetNbinsX(); i++) { if (mask->GetBinContent(i + 1)) { NUIS_LOG(DEB, "Applying mask to bin " << i + 1 << " " << hist->GetName()); continue; } calc_hist->SetBinContent(binindex + 1, hist->GetBinContent(i + 1)); calc_hist->SetBinError(binindex + 1, hist->GetBinError(i + 1)); binindex++; } return calc_hist; }; //******************************************************************* TH2D *StatUtils::ApplyHistogramMasking(TH2D *hist, TH2I *mask) { //******************************************************************* TH2D *newhist = (TH2D *)hist->Clone(); if (!mask) return newhist; for (int i = 0; i < hist->GetNbinsX(); i++) { for (int j = 0; j < hist->GetNbinsY(); j++) { if (mask->GetBinContent(i + 1, j + 1) > 0) { newhist->SetBinContent(i + 1, j + 1, 0.0); newhist->SetBinContent(i + 1, j + 1, 0.0); } } } return newhist; } //******************************************************************* TMatrixDSym *StatUtils::ApplyMatrixMasking(TMatrixDSym *mat, TH1I *mask) { //******************************************************************* if (!mask) return (TMatrixDSym *)(mat->Clone()); // Get New Bin Count Int_t NBins = 0; for (int i = 0; i < mask->GetNbinsX(); i++) { if (mask->GetBinContent(i + 1)) continue; NBins++; } // make new matrix TMatrixDSym *calc_mat = new TMatrixDSym(NBins); int col, row; // Need to mask out bins in the current matrix row = 0; for (int i = 0; i < mask->GetNbinsX(); i++) { col = 0; // skip if masked if (mask->GetBinContent(i + 1) > 0.5) continue; for (int j = 0; j < mask->GetNbinsX(); j++) { // skip if masked if (mask->GetBinContent(j + 1) > 0.5) continue; (*calc_mat)(row, col) = (*mat)(i, j); col++; } row++; } return calc_mat; }; //******************************************************************* TMatrixDSym *StatUtils::ApplyMatrixMasking(TMatrixDSym *mat, TH2D *data, TH2I *mask, TH2I *map) { //******************************************************************* bool made_map = false; if (!map) { made_map = true; map = StatUtils::GenerateMap(data); } TH1I *mask_1D = StatUtils::MapToMask(mask, map); TMatrixDSym *newmat = StatUtils::ApplyMatrixMasking(mat, mask_1D); if (made_map) { delete map; } delete mask_1D; return newmat; } //******************************************************************* TMatrixDSym *StatUtils::ApplyInvertedMatrixMasking(TMatrixDSym *mat, TH1I *mask) { //******************************************************************* //TMatrixDSym *new_mat = GetInvert(mat, true); // Don't rescale the inverted matrix which multiplies the mask! TMatrixDSym *new_mat = GetInvert(mat); TMatrixDSym *masked_mat = ApplyMatrixMasking(new_mat, mask); TMatrixDSym *inverted_mat = GetInvert(masked_mat, true); delete masked_mat; delete new_mat; return inverted_mat; }; //******************************************************************* TMatrixDSym *StatUtils::ApplyInvertedMatrixMasking(TMatrixDSym *mat, TH2D *data, TH2I *mask, TH2I *map) { //******************************************************************* bool made_map = false; if (!map) { made_map = true; map = StatUtils::GenerateMap(data); } TH1I *mask_1D = StatUtils::MapToMask(mask, map); TMatrixDSym *newmat = ApplyInvertedMatrixMasking(mat, mask_1D); if (made_map) { delete map; } delete mask_1D; return newmat; } //******************************************************************* // bool rescale rescales the matrix when using Cholesky decomp to ensure good decomposition TMatrixDSym *StatUtils::GetInvert(TMatrixDSym *mat, bool rescale) { //******************************************************************* TMatrixDSym *new_mat = (TMatrixDSym *)mat->Clone(); // Check for diagonal bool non_diagonal = false; for (int i = 0; i < new_mat->GetNrows(); i++) { for (int j = 0; j < new_mat->GetNrows(); j++) { if (i == j) continue; if ((*new_mat)(i, j) != 0.0) { non_diagonal = true; break; } } } // If diag, just flip the diag if (!non_diagonal or new_mat->GetNrows() == 1) { for (int i = 0; i < new_mat->GetNrows(); i++) { if ((*new_mat)(i, i) != 0.0) (*new_mat)(i, i) = 1.0 / (*new_mat)(i, i); else (*new_mat)(i, i) = 0.0; } return new_mat; } static bool first = true; static bool UseSVDDecomp = false; if (first) { UseSVDDecomp = FitPar::Config().GetParB("UseSVDInverse"); first = false; } if (UseSVDDecomp) { // Invert full matrix TDecompSVD mat_decomp(*new_mat); if (!mat_decomp.Decompose()) { NUIS_ABORT("Decomposition failed, matrix singular ?"); } else { int nrows = new_mat->GetNrows(); delete new_mat; new_mat = new TMatrixDSym(nrows, mat_decomp.Invert().GetMatrixArray(), ""); } // Use Cholesky decomp } else { // Check the entries of the Matrix and scale it to be within range double scaling = 1; if (rescale) { double smallest = 999; for (int i = 0; i < new_mat->GetNrows(); ++i) { for (int j = 0; j < new_mat->GetNcols(); ++j) { - if (fabs((*new_mat)(i,j)) < smallest) smallest = fabs((*new_mat)(i,j)); + if (fabs((*new_mat)(i,j)) < smallest && + (*new_mat)(i,j) != 0) smallest = fabs((*new_mat)(i,j)); } } // Now scale the matrix so the smallest entry is 1e-5 scaling = smallest; (*new_mat) *= 1./scaling; } // Invert full matrix TDecompChol mat_decomp(*new_mat); if (!mat_decomp.Decompose()) { NUIS_ERR(FTL, "Decomposition failed, matrix singular ?"); NUIS_ABORT("If you want to use SVD decomposition set in your card file."); } else { int nrows = new_mat->GetNrows(); delete new_mat; new_mat = new TMatrixDSym(nrows, mat_decomp.Invert().GetMatrixArray(), ""); } // then scale the matrix back if (rescale) { (*new_mat) *= 1./scaling; } } return new_mat; } //******************************************************************* TMatrixDSym *StatUtils::GetDecomp(TMatrixDSym *mat) { //******************************************************************* TMatrixDSym *new_mat = (TMatrixDSym *)mat->Clone(); int nrows = new_mat->GetNrows(); // Check for diagonal bool diagonal = true; for (int i = 0; i < nrows; i++) { for (int j = 0; j < nrows; j++) { if (i == j) continue; if ((*new_mat)(i, j) != 0.0) { diagonal = false; break; } } } // If diag, just flip the diag if (diagonal or nrows == 1) { for (int i = 0; i < nrows; i++) { if ((*new_mat)(i, i) > 0.0) (*new_mat)(i, i) = sqrt((*new_mat)(i, i)); else (*new_mat)(i, i) = 0.0; } return new_mat; } TDecompChol LU = TDecompChol(*new_mat); LU.Decompose(); delete new_mat; TMatrixDSym *dec_mat = new TMatrixDSym(nrows, LU.GetU().GetMatrixArray(), ""); return dec_mat; } //******************************************************************* void StatUtils::ForceNormIntoCovar(TMatrixDSym *&mat, TH1D *hist, double norm) { //******************************************************************* if (!mat) mat = MakeDiagonalCovarMatrix(hist); int nbins = mat->GetNrows(); TMatrixDSym *new_mat = new TMatrixDSym(nbins); for (int i = 0; i < nbins; i++) { for (int j = 0; j < nbins; j++) { double valx = hist->GetBinContent(i + 1) * 1E38; double valy = hist->GetBinContent(j + 1) * 1E38; (*new_mat)(i, j) = (*mat)(i, j) + norm * norm * valx * valy; } } // Swap the two delete mat; mat = new_mat; return; }; //******************************************************************* void StatUtils::ForceNormIntoCovar(TMatrixDSym *mat, TH2D *data, double norm, TH2I *map) { //******************************************************************* bool made_map = false; if (!map) { made_map = true; map = StatUtils::GenerateMap(data); } TH1D *data_1D = MapToTH1D(data, map); StatUtils::ForceNormIntoCovar(mat, data_1D, norm); delete data_1D; if (made_map) { delete map; } return; } //******************************************************************* TMatrixDSym *StatUtils::MakeDiagonalCovarMatrix(TH1D *data, double scaleF) { //******************************************************************* TMatrixDSym *newmat = new TMatrixDSym(data->GetNbinsX()); for (int i = 0; i < data->GetNbinsX(); i++) { (*newmat)(i, i) = data->GetBinError(i + 1) * data->GetBinError(i + 1) * scaleF * scaleF; } return newmat; } //******************************************************************* TMatrixDSym *StatUtils::MakeDiagonalCovarMatrix(TH2D *data, TH2I *map, double scaleF) { //******************************************************************* bool made_map = false; if (!map) { made_map = true; map = StatUtils::GenerateMap(data); } TH1D *data_1D = MapToTH1D(data, map); if (made_map) { delete map; } return StatUtils::MakeDiagonalCovarMatrix(data_1D, scaleF); }; //******************************************************************* void StatUtils::SetDataErrorFromCov(TH1D *DataHist, TMatrixDSym *cov, double scale, bool ErrorCheck) { //******************************************************************* // Check if (ErrorCheck) { if (cov->GetNrows() != DataHist->GetNbinsX()) { NUIS_ERR( FTL, "Nrows in cov don't match nbins in DataHist for SetDataErrorFromCov"); NUIS_ERR(FTL, "Nrows = " << cov->GetNrows()); NUIS_ABORT("Nbins = " << DataHist->GetNbinsX()); } } // Set bin errors form cov diag // Check if the errors are set bool ErrorsSet = false; for (int i = 0; i < DataHist->GetNbinsX(); i++) { if (ErrorsSet == true) break; if (DataHist->GetBinError(i + 1) != 0 && DataHist->GetBinContent(i + 1) > 0) ErrorsSet = true; } // Now loop over if (ErrorsSet && ErrorCheck) { for (int i = 0; i < DataHist->GetNbinsX(); i++) { double DataHisterr = DataHist->GetBinError(i + 1); double coverr = sqrt((*cov)(i, i)) * scale; // Check that the errors are within 1% of eachother if (fabs(DataHisterr - coverr) / DataHisterr > 0.01) { NUIS_ERR(WRN, "Data error does not match covariance error for bin " << i + 1 << " (" << DataHist->GetXaxis()->GetBinLowEdge(i + 1) << "-" << DataHist->GetXaxis()->GetBinLowEdge(i + 2) << ")"); NUIS_ERR(WRN, "Data error: " << DataHisterr); NUIS_ERR(WRN, "Cov error: " << coverr); } } // Else blindly trust the covariance } else { for (int i = 0; i < DataHist->GetNbinsX(); i++) { DataHist->SetBinError(i + 1, sqrt((*cov)(i, i)) * scale); } } return; } //******************************************************************* void StatUtils::SetDataErrorFromCov(TH2D *data, TMatrixDSym *cov, TH2I *map, double scale, bool ErrorCheck) { //******************************************************************* // Check if (ErrorCheck) { if (cov->GetNrows() != data->GetNbinsX() * data->GetNbinsY()) { NUIS_ERR(FTL, "Nrows in cov don't match nbins in data for " "SetDataNUIS_ERRorFromCov"); NUIS_ERR(FTL, "Nrows = " << cov->GetNrows()); NUIS_ABORT("Nbins = " << data->GetNbinsX()); } } // Set bin errors form cov diag // Check if the errors are set bool ErrorsSet = false; for (int i = 0; i < data->GetNbinsX(); i++) { for (int j = 0; j < data->GetNbinsX(); j++) { if (ErrorsSet == true) break; if (data->GetBinError(i + 1, j + 1) != 0) ErrorsSet = true; } } // Create map if required bool made_map = false; if (!map) { made_map = true; map = StatUtils::GenerateMap(data); } // Set Bin Errors from cov diag int count = 0; for (int i = 0; i < data->GetNbinsX(); i++) { for (int j = 0; j < data->GetNbinsY(); j++) { if (data->GetBinContent(i + 1, j + 1) == 0.0) continue; // If we have errors on our histogram the map is good count = map->GetBinContent(i + 1, j + 1) - 1; double dataerr = data->GetBinError(i + 1, j + 1); double coverr = sqrt((*cov)(count, count)) * scale; // Check that the errors are within 1% of eachother if (ErrorsSet && ErrorCheck) { if (fabs(dataerr - coverr) / dataerr > 0.01) { NUIS_ERR(WRN, "Data error does not match covariance error for bin " << i + 1 << " (" << data->GetXaxis()->GetBinLowEdge(i + 1) << "-" << data->GetXaxis()->GetBinLowEdge(i + 2) << ")"); NUIS_ERR(WRN, "Data error: " << dataerr); NUIS_ERR(WRN, "Cov error: " << coverr); } } else { data->SetBinError(i + 1, j + 1, sqrt((*cov)(count, count)) * scale); } } } if (made_map) { delete map; } } TMatrixDSym *StatUtils::ExtractShapeOnlyCovar(TMatrixDSym *full_covar, TH1D *data_hist, double data_scale) { int nbins = full_covar->GetNrows(); TMatrixDSym *shape_covar = new TMatrixDSym(nbins); // Check nobody is being silly if (data_hist->GetNbinsX() != nbins) { NUIS_ERR(WRN, "Inconsistent matrix and data histogram passed to " "StatUtils::ExtractShapeOnlyCovar!"); NUIS_ABORT("data_hist has " << data_hist->GetNbinsX() << " matrix has " << nbins << "bins"); int err_bins = data_hist->GetNbinsX(); if (nbins > err_bins) err_bins = nbins; for (int i = 0; i < err_bins; ++i) { NUIS_ERR(WRN, "Matrix diag. = " << (*full_covar)(i, i) << " data = " << data_hist->GetBinContent(i + 1)); } return NULL; } double total_data = 0; double total_covar = 0; // Initial loop to calculate some constants for (int i = 0; i < nbins; ++i) { total_data += data_hist->GetBinContent(i + 1) * data_scale; for (int j = 0; j < nbins; ++j) { total_covar += (*full_covar)(i, j); } } if (total_data == 0 || total_covar == 0) { NUIS_ERR(WRN, "Stupid matrix or data histogram passed to " "StatUtils::ExtractShapeOnlyCovar! Ignoring..."); return NULL; } NUIS_LOG(SAM, "Norm error = " << sqrt(total_covar) / total_data); // Now loop over and calculate the shape-only matrix for (int i = 0; i < nbins; ++i) { double data_i = data_hist->GetBinContent(i + 1) * data_scale; for (int j = 0; j < nbins; ++j) { double data_j = data_hist->GetBinContent(j + 1) * data_scale; double norm_term = data_i * data_j * total_covar / total_data / total_data; double mix_sum1 = 0; double mix_sum2 = 0; for (int k = 0; k < nbins; ++k) { mix_sum1 += (*full_covar)(k, j); mix_sum2 += (*full_covar)(i, k); } double mix_term1 = data_i * (mix_sum1 / total_data - total_covar * data_j / total_data / total_data); double mix_term2 = data_j * (mix_sum2 / total_data - total_covar * data_i / total_data / total_data); (*shape_covar)(i, j) = (*full_covar)(i, j) - mix_term1 - mix_term2 - norm_term; } } return shape_covar; } TMatrixDSym *StatUtils::ExtractShapeOnlyCovar(TMatrixDSym *full_covar, TH2D *data_hist, TH2I *map, double data_scale) { // Generate a simple map bool made_map = false; if (!map) { map = StatUtils::GenerateMap(data_hist); made_map = true; } // Convert to 1D Histograms TH1D *data_1D = MapToTH1D(data_hist, map); // Calculate from 1D TMatrixDSym *rtn = StatUtils::ExtractShapeOnlyCovar(full_covar, data_1D, data_scale); delete data_1D; if (made_map) { delete map; } return rtn; } //******************************************************************* TH2I *StatUtils::GenerateMap(TH2D *hist) { //******************************************************************* std::string maptitle = std::string(hist->GetName()) + "_MAP"; TH2I *map = new TH2I(maptitle.c_str(), maptitle.c_str(), hist->GetNbinsX(), 0, hist->GetNbinsX(), hist->GetNbinsY(), 0, hist->GetNbinsY()); Int_t index = 1; for (int i = 0; i < hist->GetNbinsX(); i++) { for (int j = 0; j < hist->GetNbinsY(); j++) { if (hist->GetBinContent(i + 1, j + 1) > 0) { map->SetBinContent(i + 1, j + 1, index); index++; } else { map->SetBinContent(i + 1, j + 1, 0); } } } return map; } //******************************************************************* TH1D *StatUtils::MapToTH1D(TH2D *hist, TH2I *map) { //******************************************************************* if (!hist) return NULL; // Get N bins for 1D plot - Int_t Nbins = map->GetMaximum(); + Int_t Nbins = map->GetXaxis()->GetNbins()*map->GetYaxis()->GetNbins(); std::string name1D = std::string(hist->GetName()) + "_1D"; // Make new 1D Hist TH1D *newhist = new TH1D(name1D.c_str(), name1D.c_str(), Nbins, 0, Nbins); // map bin contents for (int i = 0; i < map->GetNbinsX(); i++) { for (int j = 0; j < map->GetNbinsY(); j++) { if (map->GetBinContent(i + 1, j + 1) == 0) continue; newhist->SetBinContent(map->GetBinContent(i + 1, j + 1), hist->GetBinContent(i + 1, j + 1)); newhist->SetBinError(map->GetBinContent(i + 1, j + 1), hist->GetBinError(i + 1, j + 1)); } } - // return return newhist; } void StatUtils::MapFromTH1D(TH2 *fillhist, TH1 *fromhist, TH2I *map) { - fillhist->Clear(); + fillhist->Reset(); for (int i = 0; i < map->GetNbinsX(); i++) { for (int j = 0; j < map->GetNbinsY(); j++) { if (map->GetBinContent(i + 1, j + 1) == 0) continue; int gb = map->GetBinContent(i + 1, j + 1); fillhist->SetBinContent(i + 1, j + 1, fromhist->GetBinContent(gb)); fillhist->SetBinError(i + 1, j + 1, fromhist->GetBinError(gb)); } } } //******************************************************************* TH1I *StatUtils::MapToMask(TH2I *hist, TH2I *map) { //******************************************************************* TH1I *newhist = NULL; if (!hist) return newhist; // Get N bins for 1D plot - Int_t Nbins = map->GetMaximum(); + Int_t Nbins = map->GetXaxis()->GetNbins()*map->GetYaxis()->GetNbins(); std::string name1D = std::string(hist->GetName()) + "_1D"; // Make new 1D Hist newhist = new TH1I(name1D.c_str(), name1D.c_str(), Nbins, 0, Nbins); // map bin contents for (int i = 0; i < map->GetNbinsX(); i++) { for (int j = 0; j < map->GetNbinsY(); j++) { if (map->GetBinContent(i + 1, j + 1) == 0) continue; newhist->SetBinContent(map->GetBinContent(i + 1, j + 1), hist->GetBinContent(i + 1, j + 1)); } } - // return return newhist; } TMatrixDSym *StatUtils::GetCovarFromCorrel(TMatrixDSym *correl, TH1D *data) { int nbins = correl->GetNrows(); TMatrixDSym *covar = new TMatrixDSym(nbins); for (int i = 0; i < nbins; i++) { for (int j = 0; j < nbins; j++) { (*covar)(i, j) = (*correl)(i, j) * data->GetBinError(i + 1) * data->GetBinError(j + 1); } } return covar; } //******************************************************************* TMatrixD *StatUtils::GetMatrixFromTextFile(std::string covfile, int dimx, int dimy) { //******************************************************************* // Determine dim if (dimx == -1 and dimy == -1) { std::string line; std::ifstream covar(covfile.c_str(), std::ifstream::in); int row = 0; while (std::getline(covar >> std::ws, line, '\n')) { int column = 0; std::vector entries = GeneralUtils::ParseToDbl(line, " "); if (entries.size() <= 1) { NUIS_ERR(WRN, "StatUtils::GetMatrixFromTextFile, matrix only has <= 1 " "entries on this line: " << row); } for (std::vector::iterator iter = entries.begin(); iter != entries.end(); iter++) { column++; if (column > dimx) dimx = column; } row++; if (row > dimy) dimy = row; } } // Or assume symmetric if (dimx != -1 and dimy == -1) { dimy = dimx; } assert(dimy != -1 && " matrix dimy not set."); // Make new matrix TMatrixD *mat = new TMatrixD(dimx, dimy); std::string line; std::ifstream covar(covfile.c_str(), std::ifstream::in); int row = 0; while (std::getline(covar >> std::ws, line, '\n')) { int column = 0; std::vector entries = GeneralUtils::ParseToDbl(line, " "); if (entries.size() <= 1) { NUIS_ERR(WRN, "StatUtils::GetMatrixFromTextFile, matrix only has <= 1 " "entries on this line: " << row); } for (std::vector::iterator iter = entries.begin(); iter != entries.end(); iter++) { // Check Rows // assert(row > mat->GetNrows() && " covar rows doesn't match matrix // rows."); // assert(column > mat->GetNcols() && " covar cols doesn't match matrix // cols."); // Fill Matrix (*mat)(row, column) = (*iter); column++; } row++; } return mat; } //******************************************************************* TMatrixD *StatUtils::GetMatrixFromRootFile(std::string covfile, std::string histname) { //******************************************************************* std::string inputfile = covfile + ";" + histname; std::vector splitfile = GeneralUtils::ParseToStr(inputfile, ";"); if (splitfile.size() < 2) { NUIS_ABORT("No object name given!"); } // Get file TFile *tempfile = new TFile(splitfile[0].c_str(), "READ"); // Get Object TObject *obj = tempfile->Get(splitfile[1].c_str()); if (!obj) { NUIS_ABORT("Object " << splitfile[1] << " doesn't exist!"); } // Try casting TMatrixD *mat = dynamic_cast(obj); if (mat) { TMatrixD *newmat = (TMatrixD *)mat->Clone(); delete mat; tempfile->Close(); return newmat; } TMatrixDSym *matsym = dynamic_cast(obj); if (matsym) { TMatrixD *newmat = new TMatrixD(matsym->GetNrows(), matsym->GetNrows()); for (int i = 0; i < matsym->GetNrows(); i++) { for (int j = 0; j < matsym->GetNrows(); j++) { (*newmat)(i, j) = (*matsym)(i, j); } } delete matsym; tempfile->Close(); return newmat; } TH2D *mathist = dynamic_cast(obj); if (mathist) { TMatrixD *newmat = new TMatrixD(mathist->GetNbinsX(), mathist->GetNbinsX()); for (int i = 0; i < mathist->GetNbinsX(); i++) { for (int j = 0; j < mathist->GetNbinsX(); j++) { (*newmat)(i, j) = mathist->GetBinContent(i + 1, j + 1); } } delete mathist; tempfile->Close(); return newmat; } return NULL; } //******************************************************************* TMatrixDSym *StatUtils::GetCovarFromTextFile(std::string covfile, int dim) { //******************************************************************* // Delete TempMat TMatrixD *tempmat = GetMatrixFromTextFile(covfile, dim, dim); // Make a symmetric covariance TMatrixDSym *newmat = new TMatrixDSym(tempmat->GetNrows()); for (int i = 0; i < tempmat->GetNrows(); i++) { for (int j = 0; j < tempmat->GetNrows(); j++) { (*newmat)(i, j) = (*tempmat)(i, j); } } delete tempmat; return newmat; } //******************************************************************* TMatrixDSym *StatUtils::GetCovarFromRootFile(std::string covfile, std::string histname) { //******************************************************************* TMatrixD *tempmat = GetMatrixFromRootFile(covfile, histname); TMatrixDSym *newmat = new TMatrixDSym(tempmat->GetNrows()); for (int i = 0; i < tempmat->GetNrows(); i++) { for (int j = 0; j < tempmat->GetNrows(); j++) { (*newmat)(i, j) = (*tempmat)(i, j); } } delete tempmat; return newmat; } diff --git a/src/T2K/T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np.cxx b/src/T2K/T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np.cxx index 51aacbc..d7be3af 100644 --- a/src/T2K/T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np.cxx +++ b/src/T2K/T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np.cxx @@ -1,647 +1,651 @@ // 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 "T2K_SignalDef.h" #include "T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np.h" //******************************************************************** T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np:: T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np(nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np sample. \n" "Target: CH \n" "Flux: T2K 2.5 degree off-axis (ND280) \n" "Signal: CC0piNp (N>=0) with p_p>500MeV \n" "https://doi.org/10.1103/PhysRevD.98.032003 \n" "Data release: https://t2k-experiment.org/results/2018-transverse-cc0pi/ \n"; // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); fSettings.SetXTitle("Bin number"); // fSettings.SetYTitle("d^{2}#sigma/dP_{#mu}dcos#theta_{#mu} (cm^{2}/GeV)"); fSettings.SetAllowedTypes("FULL,DIAG/FREE,SHAPE,FIX/SYSTCOV/STATCOV", "FIX/FULL"); fSettings.SetEnuRange(0.0, 10.0); fSettings.DefineAllowedTargets("C,H"); fAnalysis = 1; // CCQELike plot information fSettings.SetTitle(fName); fSettings.DefineAllowedSpecies("numu"); FinaliseSampleSettings(); - //Set useCC0pi0p, useCC0pi1p, and useCC0piNp + // Set useCC0pi0p, useCC0pi1p, and useCC0piNp, first initialize to false; + useCC0pi0p = false; + useCC0pi1p = false; + useCC0piNp = false; + if (fName == "T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np"){ useCC0pi0p = true; useCC0pi1p = true; useCC0piNp = true; } else if (fName == "T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p"){ useCC0pi0p = true; useCC0pi1p = true; } else if (fName == "T2K_CC0piWithProtons_XSec_2018_multidif_0p"){ useCC0pi0p = true; } else if (fName == "T2K_CC0piWithProtons_XSec_2018_multidif_1p"){ useCC0pi1p = true; } // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon // fScaleFactor = ((GetEventHistogram()->Integral("width")/(fNEvents+0.)) * // 1E-38 / (TotalIntegratedFlux())); fScaleFactor = ((GetEventHistogram()->Integral("width") / (fNEvents + 0.)) * 10 / (TotalIntegratedFlux())); // Setup Histograms SetHistograms(); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; bool T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np::isSignal(FitEvent *event) { // If looking at all subsamples, only requirement is that this is a CC0pi event if (useCC0pi0p && useCC0pi1p && useCC0piNp) return SignalDef::isCC0pi(event, 14, EnuMin, EnuMax); // Otherwise, evaluate each relevant signal definition separately if (useCC0pi0p && SignalDef::isT2K_CC0pi0p(event, EnuMin, EnuMax)) return true; if (useCC0pi1p && SignalDef::isT2K_CC0pi1p(event, EnuMin, EnuMax)) return true; if (useCC0piNp && SignalDef::isT2K_CC0piNp(event, EnuMin, EnuMax)) return true; // If you get here, the event has failed and is not signal return false; }; void T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np::FillEventVariables( FitEvent *event) { if (event->NumFSParticle(13) == 0) return; TLorentzVector Pnu = event->GetNeutrinoIn()->fP; TLorentzVector Pmu = event->GetHMFSParticle(13)->fP; double pmu = Pmu.Vect().Mag()/1000.; double CosThetaMu = cos(Pnu.Vect().Angle(Pmu.Vect())); // Dummy proton variables if we don't have a proton double pp = -999; double CosThetaP = -999; // Check if we do have a proton and fill variables if (event->NumFSParticle(2212) > 0){ TLorentzVector Pp = event->GetHMFSParticle(2212)->fP; pp = Pp.Vect().Mag() / 1000.; CosThetaP = cos(Pnu.Vect().Angle(Pp.Vect())); } // How many protons above threshold? std::vector protons = event->GetAllFSProton(); int nProtonsAboveThresh = 0; for (size_t i = 0; i < protons.size(); i++) { if (protons[i]->p() > 500) nProtonsAboveThresh++; } // Get bin number in total 1D histogram int binnumber = Get1DBin(nProtonsAboveThresh, pmu, CosThetaMu, pp, CosThetaP); // I'm hacking this to fit in the Measurement1D framework, but it's going to be super ugly - apologies... // The 1D histogram handled by NUISANCE is defined in terms of bin number, so that has to be fXVar // Actually needs to be binnumber-0.5 because it's treating it as a variable fXVar = binnumber-0.5; // Then fill variables so I can use them to fill the slice histograms in FillHistograms() fPP = pp; fPMu = pmu; fCosThetaP = CosThetaP; fCosThetaMu = CosThetaMu; fNp = nProtonsAboveThresh; // Also set mode so the mode histogram works Mode = event->Mode; return; }; void T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np::FillHistograms() { Measurement1D::FillHistograms(); if (Signal) { // fMCHist_Fine2D->Fill(fXVar, fYVar, Weight); if (useCC0pi0p && fNp == 0){ fMCHist_CC0pi0pCosTheta->Fill(fCosThetaMu, Weight); } else if (useCC0pi1p && fNp == 1){ fMCHist_CC0pi1pCosTheta->Fill(fCosThetaMu, Weight); } FillMCSlice(fNp, fPMu, fCosThetaMu, fPP, fCosThetaP, Weight); } } void T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np::FillMCSlice(int nProtonsAboveThresh, double pmu, double CosThetaMu, double pp, double CosThetaP, double w) { // Get slice number for 1D CosThetaMu slice int CosThetaMuSliceNo = GetCosThetaMuSlice(nProtonsAboveThresh, CosThetaMu); // If sliceno is valid (not negative), fill the relevant slice if (CosThetaMuSliceNo < 0) return; // CC0pi0p slices: fill with pmu if (useCC0pi0p && nProtonsAboveThresh == 0 && CosThetaMuSliceNo < 10){ fMCHist_Slices[CosThetaMuSliceNo]->Fill(pmu, w); } // CC0pi1p slices: fill with CosThetaP if (useCC0pi1p && nProtonsAboveThresh == 1){ fMCHist_Slices[CosThetaMuSliceNo]->Fill(CosThetaP, w); // If we're looking at CC0pi1p, also fill the CosThetaMu-CosThetaP slices with PP int CC0pi1p2DSliceNo = GetCC0pi1p2DSlice(nProtonsAboveThresh, CosThetaMu, CosThetaP); if (CC0pi1p2DSliceNo < 0) return; fMCHist_Slices[CC0pi1p2DSliceNo]->Fill(pp, w); } } void T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np::SetHistograms() { // Read in 1D Data Histograms fInputFile = new TFile( (FitPar::GetDataBase() + "/T2K/CC0pi/STV/multidif_results.root") .c_str(), "READ"); // fInputFile->ls(); // Read in 1D Data TH1D *tempDataHist = (TH1D *)fInputFile->Get("Result"); // Read in covariance matrix TH2D *tempcov = (TH2D *)fInputFile->Get("CovarianceMatrix"); // The input data and covariance matrix include bins for CC0pi0p, CC0pi1p, and CC0piNp. We may not want them all if we only want to look at one or two of the sub-samples, so go through and only keep the bins we want // CC0pi0p: bins 1-60 -> 60 bins // CC0pi1p: bins 61-92 -> 32 bins // CC0piNp: bin 93 -> 1 bin int n_binskeep = 0; if (useCC0pi0p) n_binskeep += 60; if (useCC0pi1p) n_binskeep += 32; if (useCC0piNp) n_binskeep += 1; fDataHist = new TH1D("DataHist", tempDataHist->GetTitle(),n_binskeep,0,n_binskeep); fFullCovar = new TMatrixDSym(n_binskeep); int i_binskeep = 1; for (int i_allbins=1; i_allbinsGetNbinsX()+1; i_allbins++){ if ((i_allbins >=1 && i_allbins <=60) && !useCC0pi0p) continue; if ((i_allbins >= 61 && i_allbins <=92) && !useCC0pi1p) continue; if ((i_allbins == 93) && !useCC0piNp) continue; fDataHist->SetBinContent(i_binskeep,tempDataHist->GetBinContent(i_allbins)); fDataHist->SetBinError(i_binskeep,tempDataHist->GetBinError(i_allbins)); int j_binskeep = 1; for (int j_allbins = 1; j_allbins < tempDataHist->GetNbinsX()+1; j_allbins++){ if ((j_allbins >=1 && j_allbins <=60) && !useCC0pi0p) continue; if ((j_allbins >= 61 && j_allbins <=92) && !useCC0pi1p) continue; if ((j_allbins == 93) && !useCC0piNp) continue; // std::cout << i_allbins << ", " << j_allbins << " -- " << i_binskeep-1 << ", " << j_binskeep-1 << " -- " << tempcov->GetBinContent(i_allbins, j_allbins) << std::endl; (*fFullCovar)(i_binskeep-1,j_binskeep-1) = tempcov->GetBinContent(i_allbins, j_allbins)*1e38*1e38; j_binskeep++; } // end loop over j_allbins i_binskeep++; } covar = StatUtils::GetInvert(fFullCovar); fDecomp = StatUtils::GetDecomp(fFullCovar); // Make 1D data histogram TH1D *linearResult = new TH1D(*fDataHist); // Set name based on what subsamples we are looking at if (useCC0pi0p && useCC0pi1p && useCC0piNp){ linearResult->SetName("T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np_data"); } else if (useCC0pi0p && useCC0pi1p && !useCC0piNp){ linearResult->SetName("T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_data"); } else if (useCC0pi0p && !useCC0pi1p && !useCC0piNp){ linearResult->SetName("T2K_CC0piWithProtons_XSec_2018_multidif_0p_data"); } else if (!useCC0pi0p && useCC0pi1p && !useCC0piNp){ linearResult->SetName("T2K_CC0piWithProtons_XSec_2018_multidif_1p_data"); } else{ linearResult->SetName("T2K_CC0piWithProtons_XSec_2018_multidif_data"); } SetAutoProcessTH1(linearResult, kCMD_Write); // Fine histograms - don't implement for now (this is copied from T2K_CC0pi1p_XSec_3DPcoscos_nu) // fMCHist_Fine2D = new TH2D("T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np_Fine2D", // "T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np_Fine2D", // 400, 0.0, 30.0, 100, -1.0, 1.0); // SetAutoProcessTH1(fMCHist_Fine2D); // The code below converts a relative covariance matrix to an absolute one. I think the input is absolute so we don't need it, but come back to this if the results look weird // for (int i = 0; i < fDataHist->GetNbinsX(); i++) { // for (int j = 0; j < fDataHist->GetNbinsX(); j++) { // //(*fFullCovar)(i,j) = tempcov->GetBinContent(i+1, j+1); // (*fFullCovar)(i, j) = tempcov->GetBinContent(i + 1, j + 1) * // fDataHist->GetBinContent(i + 1) * // fDataHist->GetBinContent(j + 1); // if (i == j) // fDataHist->SetBinError(i + 1, sqrt((*fFullCovar)(i, j))); // // if(i==j) std::cout << "For bin " << i+1 << ", relative covariance was " // // << tempcov->GetBinContent(i+1,j+1); if(i==j) std::cout << ". Absolute // // covariance is now " << (*fFullCovar)(i,j) << ", linear xsec is: " << // // fDataHist->GetBinContent(i+1) << std::endl; // } // } // Read in data slice histograms and make MC slices // Slices are stored in slightly different ways for 0p and 1p samples // CC0pi0p: folder NoProtonsAbove500MeV // -> TH1D ResultInMuonCosTheta // -> TH1D MuonCosThetaSlice_i where i = 0 to 9 // CC0pi1p: folder OneProtonAbove500MeV // -> TH1D ResultInMuonCosTheta // -> TH1D MuonCosThetaSlice_1D_i where i = 0 to 3 // -> TH1D MuCThSlice_1_PCthSlice_0 // -> TH1D MuCThSlice_2_PCthSlice_0 // -> TH1D MuCThSlice_2_PCthSlice_1 // -> TH1D MuCThSlice_3_PCthSlice_0 // We also have proton multiplicity, in folder ProtonMultiplicity // -> TH1D Result // -> TH2D CovarianceMatrix // TODO add this as a separate sample? Don't implement here // CC0pi0p slices if (useCC0pi0p){ fDataHist_CC0pi0pCosTheta = (TH1D*)fInputFile->Get("NoProtonsAbove500MeV/ResultInMuonCosTheta")->Clone("T2K_CC0pi0p_XSec_2018_MuonCosTheta_data"); fMCHist_CC0pi0pCosTheta = (TH1D*)fDataHist_CC0pi0pCosTheta->Clone("T2K_CC0pi0p_XSec_2018_MuonCosTheta_MC"); fMCHist_CC0pi0pCosTheta->Reset(); SetAutoProcessTH1(fDataHist_CC0pi0pCosTheta, kCMD_Write); SetAutoProcessTH1(fMCHist_CC0pi0pCosTheta, kCMD_Reset, kCMD_Scale, kCMD_Write); for (int i=0; i<=9; i++){ fDataHist_Slices.push_back((TH1D*)fInputFile->Get(Form("NoProtonsAbove500MeV/MuonCosThetaSlice_%i", i))->Clone(Form("T2K_CC0pi0p_XSec_2018_Data_Slice%i", i))); fMCHist_Slices.push_back((TH1D*)fInputFile->Get(Form("NoProtonsAbove500MeV/MuonCosThetaSlice_%i", i))->Clone(Form("T2K_CC0pi0p_XSec_2018_MC_Slice%i", i))); } // end loop over i } // CC0pi1p slices if (useCC0pi1p){ fDataHist_CC0pi1pCosTheta = (TH1D*)fInputFile->Get("OneProtonAbove500MeV/ResultInMuonCosTheta")->Clone("T2K_CC0pi1p_XSec_2018_MuonCosTheta_data"); fMCHist_CC0pi1pCosTheta = (TH1D*)fDataHist_CC0pi1pCosTheta->Clone("T2K_CC0pi1p_XSec_2018_MuonCosTheta_MC"); fMCHist_CC0pi1pCosTheta->Reset(); SetAutoProcessTH1(fDataHist_CC0pi1pCosTheta, kCMD_Write); SetAutoProcessTH1(fMCHist_CC0pi1pCosTheta, kCMD_Reset, kCMD_Scale, kCMD_Write); for (int i=0; i<=3; i++){ fDataHist_Slices.push_back((TH1D*)fInputFile->Get(Form("OneProtonAbove500MeV/MuonCosThetaSlice_1D_%i", i))->Clone(Form("T2K_CC0pi1p_XSec_2018_Data_MuonCosTh1DSlice%i", i))); fMCHist_Slices.push_back((TH1D*)fInputFile->Get(Form("OneProtonAbove500MeV/MuonCosThetaSlice_1D_%i", i))->Clone(Form("T2K_CC0pi1p_XSec_2018_MC_MuonCosTh1DSlice%i", i))); } // Add in the muon costh-p costh slices (which aren't as nicely numbered) // -> TH1D MuCThSlice_1_PCthSlice_0 fDataHist_Slices.push_back((TH1D*)fInputFile->Get("OneProtonAbove500MeV/MuCThSlice_1_PCthSlice_0")->Clone("T2K_CC0pi1p_XSec_2018_Data_MuCThSlice_1_PCthSlice_0")); fMCHist_Slices.push_back((TH1D*)fInputFile->Get("OneProtonAbove500MeV/MuCThSlice_1_PCthSlice_0")->Clone("T2K_CC0pi1p_XSec_2018_MC_MuCThSlice_1_PCthSlice_0")); // -> TH1D MuCThSlice_2_PCthSlice_0 fDataHist_Slices.push_back((TH1D*)fInputFile->Get("OneProtonAbove500MeV/MuCThSlice_2_PCthSlice_0")->Clone("T2K_CC0pi1p_XSec_2018_Data_MuCThSlice_2_PCthSlice_0")); fMCHist_Slices.push_back((TH1D*)fInputFile->Get("OneProtonAbove500MeV/MuCThSlice_2_PCthSlice_0")->Clone("T2K_CC0pi1p_XSec_2018_MC_MuCThSlice_2_PCthSlice_0")); // -> TH1D MuCThSlice_2_PCthSlice_1 fDataHist_Slices.push_back((TH1D*)fInputFile->Get("OneProtonAbove500MeV/MuCThSlice_2_PCthSlice_1")->Clone("T2K_CC0pi1p_XSec_2018_Data_MuCThSlice_2_PCthSlice_1")); fMCHist_Slices.push_back((TH1D*)fInputFile->Get("OneProtonAbove500MeV/MuCThSlice_2_PCthSlice_1")->Clone("T2K_CC0pi1p_XSec_2018_MC_MuCThSlice_2_PCthSlice_1")); // -> TH1D MuCThSlice_3_PCthSlice_0 fDataHist_Slices.push_back((TH1D*)fInputFile->Get("OneProtonAbove500MeV/MuCThSlice_3_PCthSlice_0")->Clone("T2K_CC0pi1p_XSec_2018_Data_MuCThSlice_3_PCthSlice_0")); fMCHist_Slices.push_back((TH1D*)fInputFile->Get("OneProtonAbove500MeV/MuCThSlice_3_PCthSlice_0")->Clone("T2K_CC0pi1p_XSec_2018_MC_MuCThSlice_3_PCthSlice_0")); } // Set all slice histograms to auto-process and reset MC histograms for (size_t i=0; iReset(); SetAutoProcessTH1(fDataHist_Slices[i], kCMD_Write); SetAutoProcessTH1(fMCHist_Slices[i], kCMD_Reset, kCMD_Scale, kCMD_Write); } return; }; // Yay hardcoding // Taken from multidif_binMap.txt in data release int T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np::Get1DBin(int nProtonsAboveThresh, double pmu, double CosThetaMu, double pp, double CosThetaP) { int binnumber = -999; // If you're looking at a sample you don't want to look at, return -999 if (nProtonsAboveThresh == 0 && !useCC0pi0p){return binnumber;} if (nProtonsAboveThresh == 1 && !useCC0pi1p){return binnumber;} if (nProtonsAboveThresh >= 2 && !useCC0piNp){return binnumber;} // Calculate bin number (check that we want to use this sample before looking for the correct bin to save computation -- probably redundant because of the checks above but I like to be careful) if (nProtonsAboveThresh == 0 && useCC0pi0p){ //CC0pi0p: 2D binning in CosThetaMu--pmu if (CosThetaMu >= -1 && CosThetaMu <= -0.3) {binnumber = 1;} else if (CosThetaMu > -0.3 && CosThetaMu <= 0.3){ // Now find bin in pmu if (pmu >= 0 && pmu <= 0.3) {binnumber = 2;} else if (pmu > 0.3 && pmu <= 0.4){binnumber = 3;} else if (pmu > 0.4 && pmu <= 30){binnumber = 4;} } // end if (CosThetaMu > -0.3 && CosThetaMu <= 0.3) else if (CosThetaMu > 0.3 && CosThetaMu <= 0.6){ // Now find bin in pmu if (pmu >= 0 && pmu <= 0.3){binnumber = 5;} else if (pmu > 0.3 && pmu <= 0.4){binnumber = 6;} else if (pmu > 0.4 && pmu <= 0.5){binnumber = 7;} else if (pmu > 0.5 && pmu <= 0.6){binnumber = 8;} else if (pmu > 0.6 && pmu <= 30){binnumber = 9;} } // end if (CosThetaMu > 0.3 && CosThetaMu <= 0.6) else if (CosThetaMu > 0.6 && CosThetaMu <= 0.7){ // Now find bin in pmu if (pmu >= 0 && pmu <= 0.3){binnumber = 10;} else if (pmu > 0.3 && pmu <= 0.4){binnumber = 11;} else if (pmu > 0.4 && pmu <= 0.5){binnumber = 12;} else if (pmu > 0.5 && pmu <= 0.6){binnumber = 13;} else if (pmu > 0.6 && pmu <= 30){binnumber = 14;} } // end if (CosThetaMu > 0.6 && CosThetaMu <= 0.7) else if (CosThetaMu > 0.7 && CosThetaMu <= 0.8){ // Now find bin in pmu if (pmu >= 0 && pmu <= 0.3){binnumber = 15;} else if (pmu > 0.3 && pmu <= 0.4){binnumber = 16;} else if (pmu > 0.4 && pmu <= 0.5){binnumber = 17;} else if (pmu > 0.5 && pmu <= 0.6){binnumber = 18;} else if (pmu > 0.6 && pmu <= 0.7){binnumber = 19;} else if (pmu > 0.7 && pmu <= 0.8){binnumber = 20;} else if (pmu > 0.8 && pmu <= 30){binnumber = 21;} } // end if (CosThetaMu > 0.7 && CosThetaMu <= 0.8) else if (CosThetaMu > 0.8 && CosThetaMu <= 0.85){ // Now find bin in pmu if (pmu >= 0 && pmu <= 0.4){binnumber = 22;} else if (pmu > 0.4 && pmu <= 0.5){binnumber = 23;} else if (pmu > 0.5 && pmu <= 0.6){binnumber = 24;} else if (pmu > 0.6 && pmu <= 0.7){binnumber = 25;} else if (pmu > 0.7 && pmu <= 0.8){binnumber = 26;} else if (pmu > 0.8 && pmu <= 30){binnumber = 27;} } // end if (CosThetaMu > 0.8 && CosThetaMu <= 0.85) else if (CosThetaMu > 0.85 && CosThetaMu <= 0.9){ // Now find bin in pmu if (pmu >= 0 && pmu <= 0.3){binnumber = 28;} else if (pmu > 0.3 && pmu <= 0.4){binnumber = 29;} else if (pmu > 0.4 && pmu <= 0.5){binnumber = 30;} else if (pmu > 0.5 && pmu <= 0.6){binnumber = 31;} else if (pmu > 0.6 && pmu <= 0.7){binnumber = 32;} else if (pmu > 0.7 && pmu <= 0.8){binnumber = 33;} else if (pmu > 0.8 && pmu <= 1){binnumber = 34;} else if (pmu > 1 && pmu <= 30){binnumber = 35;} } // end if (CosThetaMu > 0.85 && CosThetaMu <= 0.9) else if (CosThetaMu > 0.9 && CosThetaMu <= 0.94){ // Now find bin in pmu if (pmu >= 0 && pmu <= 0.4){binnumber = 36;} else if (pmu > 0.4 && pmu <= 0.5){binnumber = 37;} else if (pmu > 0.5 && pmu <= 0.6){binnumber = 38;} else if (pmu > 0.6 && pmu <= 0.7){binnumber = 39;} else if (pmu > 0.7 && pmu <= 0.8){binnumber = 40;} else if (pmu > 0.8 && pmu <= 1.25){binnumber = 41;} else if (pmu > 1.25 && pmu <= 30){binnumber = 42;} } // end if (CosThetaMu > 0.9 && CosThetaMu <= 0.94) else if (CosThetaMu > 0.94 && CosThetaMu <= 0.98){ // Now find bin in pmu if (pmu >= 0 && pmu <= 0.4){binnumber = 43;} else if (pmu > 0.4 && pmu <= 0.5){binnumber = 44;} else if (pmu > 0.5 && pmu <= 0.6){binnumber = 45;} else if (pmu > 0.6 && pmu <= 0.7){binnumber = 46;} else if (pmu > 0.7 && pmu <= 0.8){binnumber = 47;} else if (pmu > 0.8 && pmu <= 1){binnumber = 48;} else if (pmu > 1 && pmu <= 1.25){binnumber = 49;} else if (pmu > 1.25 && pmu <= 1.5){binnumber = 50;} else if (pmu > 1.5 && pmu <= 2){binnumber = 51;} else if (pmu > 2 && pmu <= 30){binnumber = 52;} } // end if (CosThetaMu > 0.94 && CosThetaMu <= 0.98) else if (CosThetaMu > 0.98 && CosThetaMu <= 1){ // Now find bin in pmu if (pmu >= 0 && pmu <= 0.5){binnumber = 53;} else if (pmu > 0.5 && pmu <= 0.65){binnumber = 54;} else if (pmu > 0.65 && pmu <= 0.8){binnumber = 55;} else if (pmu > 0.8 && pmu <= 1.25){binnumber = 56;} else if (pmu > 1.25 && pmu <= 2){binnumber = 57;} else if (pmu > 2 && pmu <= 3){binnumber = 58;} else if (pmu > 3 && pmu <= 5){binnumber = 59;} else if (pmu > 5 && pmu <= 30){binnumber = 60;} } // end if (CosThetaMu > 0.98 && CosThetaMu <= 1) } // end (nProtonsAboveThresh == 0) else if (nProtonsAboveThresh == 1 && useCC0pi1p){ if (CosThetaMu >= -1 && CosThetaMu <= -0.3){ // Find bin in CosThetaP if (CosThetaP >= -1 && CosThetaP <= 0.87){binnumber = 61;} else if (CosThetaP > 0.87 && CosThetaP <= 0.94){binnumber = 62;} else if (CosThetaP > 0.94 && CosThetaP <= 0.97){binnumber = 63;} else if (CosThetaP > 0.97 && CosThetaP <= 1){binnumber = 64;} } // end (CosThetaMu >= -1 && CosThetaMu <= -0.3) else if (CosThetaMu > -0.3 && CosThetaMu <= 0.3){ // Find bin in CosThetaP if (CosThetaP >= -1 && CosThetaP <= 0.75){binnumber = 65;} else if (CosThetaP > 0.75 && CosThetaP <= 0.85){binnumber = 66;} else if (CosThetaP > 0.85 && CosThetaP <= 0.94){ // Find bin in pp if (pp >= 0.5 && pp <= 0.68){binnumber = 67;} else if (pp > 0.68 && pp <= 0.78){binnumber = 68;} else if (pp > 0.78 && pp <= 0.9){binnumber = 69;} else if (pp > 0.9 && pp <= 30){binnumber = 70;} } // end if (CosThetaP > 0.85 && CosThetaP <= 0.94) else if (CosThetaP > 0.94 && CosThetaP <= 1){binnumber = 71;} } // end if (CosThetaMu > -0.3 && CosThetaMu <= 0.3) else if (CosThetaMu > 0.3 && CosThetaMu <= 0.8){ // Find bin in CosThetaP if (CosThetaP >= -1 && CosThetaP <= 0.3){binnumber = 72;} else if (CosThetaP > 0.3 && CosThetaP <= 0.5){binnumber = 73;} else if (CosThetaP > 0.5 && CosThetaP <= 0.8){ // find bin in pp if (pp >= 0.5 && pp <= 0.6){binnumber = 74;} else if (pp > 0.6 && pp <= 0.7){binnumber = 75;} else if (pp > 0.7 && pp <= 0.8){binnumber = 76;} else if (pp > 0.8 && pp <= 0.9){binnumber = 77;} else if (pp > 0.9 && pp <= 30){binnumber = 78;} } // end if (CosThetaP > 0.5 && CosThetaP <= 0.8) else if (CosThetaP > 0.8 && CosThetaP <= 1){ // find bin in pp if (pp >= 0.5 && pp <= 0.6){binnumber = 79;} else if (pp > 0.6 && pp <= 0.7){binnumber = 80;} else if (pp > 0.7 && pp <= 0.8){binnumber = 81;} else if (pp > 0.8 && pp <= 1){binnumber = 82;} else if (pp > 1 && pp <= 30){binnumber = 83;} } // end if (CosThetaP > 0.8 && CosThetaP <= 1) } // end if (CosThetaMu > 0.3 && CosThetaMu <= 0.8) else if (CosThetaMu > 0.8 && CosThetaMu <= 1){ // Find bin in CosThetaP if (CosThetaP >= -1 && CosThetaP <= 0){binnumber = 84;} else if (CosThetaP > 0 && CosThetaP <= 0.3){binnumber = 85;} else if (CosThetaP > 0.3 && CosThetaP <= 0.8){ // find bin in pp if (pp >= 0.5 && pp <= 0.6){binnumber = 86;} else if (pp > 0.6 && pp <= 0.7){binnumber = 87;} else if (pp > 0.7 && pp <= 0.8){binnumber = 88;} else if (pp > 0.8 && pp <= 0.9){binnumber = 89;} else if (pp > 0.9 && pp <= 1.1){binnumber = 90;} else if (pp > 1.1 && pp <= 30){binnumber = 91;} } // end if (CosThetaP > 0.3 && CosThetaP <= 0.8) else if (CosThetaP > 0.8 && CosThetaP <= 1){binnumber = 92;} } // end if (CosThetaMu > 0.8 && CosThetaMu <= 1) } // end if (nProtonsAboveThresh == 1) else if (nProtonsAboveThresh > 1 && useCC0piNp){ binnumber = 93; } // If binnumber is still -999, something has gone wrong if (binnumber == -999){ std::cout << "ERROR did not find correct 1D bin for an event with nProtonsAboveThresh = " << nProtonsAboveThresh << ", pmu = " << pmu << ", CosThetaMu = " << CosThetaMu << ", pp = " << pp << ", CosThetaP = " << CosThetaP << std::endl; return -999; } // Now need to work out adjustments for if we don't want to use one or more of the samples // If all samples are wanted, no adjustments required - the binning stands // If only CC0pi0p sample is wanted, no adjustments required - CC0pi0p binning is correct and the other bins won't be assigned // If CC0pi0p and CC0pi1p samples are wanted, no adjustments required // If only CC0pi1p sample is wanted or CC0pi1p and CC0piNp samples are wanted, need to subtract off total number of CC0pi0p bins if (useCC0pi1p && !useCC0pi0p){ binnumber -= 60; } // If only CC0piNp sample is wanted, need to subtract off total number of CC0pi0p and CC0pi1p bins if (useCC0piNp && !useCC0pi0p && !useCC0pi1p){ binnumber =- 92; } // If CC0pi0p and CC0piNp samples are wanted, need to subtract off CC0pi1p bins from CC0piNp bin number if (useCC0piNp && useCC0pi0p && !useCC0pi1p && binnumber == 93){ binnumber = 61; } return binnumber; }; // Yay hardcoding again! // Taken from multidif_binMap.txt in data release int T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np::GetCosThetaMuSlice(int nProtonsAboveThresh, double CosThetaMu) { int slicenumber = -999; // if (useCC0pi0p), the first 10 slices will be CC0pi0p slices // -> TH1D MuonCosThetaSlice_i where i = 0 to 9 // -> slices 0 to 9 // if (useCC0pi1p), the next 8 slices will be CC0pi1p slices // -> TH1D MuonCosThetaSlice_1D_i where i = 0 to 3 // -> TH1D MuCThSlice_1_PCthSlice_0 // -> TH1D MuCThSlice_2_PCthSlice_0 // -> TH1D MuCThSlice_2_PCthSlice_1 // -> TH1D MuCThSlice_3_PCthSlice_0 // -> slices 10 to 17 if (useCC0pi0p) // -> slices 0 to 7 if (!useCC0pi0p) // In this code, we just find the costhetamu slices // Calculate bin number (check that we want to use this sample before looking for the correct bin to save computation) if (nProtonsAboveThresh == 0 && useCC0pi0p){ //CC0pi0p: 10 slices in CosThetaMu if (CosThetaMu >= -1 && CosThetaMu <= -0.3) {slicenumber = 0;} else if (CosThetaMu > -0.3 && CosThetaMu <= 0.3){slicenumber = 1;} else if (CosThetaMu > 0.3 && CosThetaMu <= 0.6){slicenumber = 2;} else if (CosThetaMu > 0.6 && CosThetaMu <= 0.7){slicenumber = 3;} else if (CosThetaMu > 0.7 && CosThetaMu <= 0.8){slicenumber = 4;} else if (CosThetaMu > 0.8 && CosThetaMu <= 0.85){slicenumber = 5;} else if (CosThetaMu > 0.85 && CosThetaMu <= 0.9){slicenumber = 6;} else if (CosThetaMu > 0.9 && CosThetaMu <= 0.94){slicenumber = 7;} else if (CosThetaMu > 0.94 && CosThetaMu <= 0.98){slicenumber = 8;} else if (CosThetaMu > 0.98 && CosThetaMu <= 1){slicenumber = 9;} } // end (nProtonsAboveThresh == 0) else if (nProtonsAboveThresh == 1 && useCC0pi1p){ // CC0pi1p: 8 slices, either in CosThetaMu or CosThetaMu-CosThetaP, depending on the slice if (CosThetaMu >= -1 && CosThetaMu <= -0.3){slicenumber = 10;} else if (CosThetaMu > -0.3 && CosThetaMu <= 0.3){slicenumber = 11;} else if (CosThetaMu > 0.3 && CosThetaMu <= 0.8){slicenumber = 12;} else if (CosThetaMu > 0.8 && CosThetaMu <= 1){slicenumber = 13;} } // end if (nProtonsAboveThresh == 1) // slicenumber may be -999 if nProtonsAboveThresh > 1 // otherwise, something has gone wrong if (slicenumber == -999 && nProtonsAboveThresh <= 1){ std::cout << "ERROR did not find correct 1D CosThetaMu slice for an event with nProtonsAboveThresh = " << nProtonsAboveThresh << ", CosThetaMu = " << CosThetaMu << std::endl; return -999; } // If useCC0pi0p is false, adjust slice numbers for CC0pi1p if (useCC0pi1p && !useCC0pi0p){ slicenumber -= 10; } return slicenumber; }; // Hardcoding one more time // Taken from multidif_binMap.txt in data release int T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np::GetCC0pi1p2DSlice(int nProtonsAboveThresh, double CosThetaMu, double CosThetaP) { int slicenumber = -999; // Calculate slice number (note: only 2D CC0pi1p slices in CosThetaMu-CosThetaP are handled here) // These slices exist for: // CosThetaMu -0.3 - 0.3, CosThetaP 0.85 - 0.94 // CosThetaMu 0.3 - 0.8, CosThetaP 0.5 - 0.8 // CosThetaMu 0.3 - 0.8, CosThetaP 0.8 - 1.0 // CosThetaMu 0.8 - 1.0, CosThetaP 0.3 - 0.8 // If useCC0pi0p is true, these will be slices 14-17 // If useCC0pi0p is false, these will be slices 4-7 if (nProtonsAboveThresh == 1 && useCC0pi1p){ if (CosThetaMu > -0.3 && CosThetaMu <= 0.3 && CosThetaP > 0.85 && CosThetaP <= 0.94){slicenumber = 14;} else if (CosThetaMu > 0.3 && CosThetaMu <= 0.8){ // Find bin in CosThetaP if (CosThetaP > 0.5 && CosThetaP <= 0.8){slicenumber = 15;} else if (CosThetaP > 0.8 && CosThetaP <= 1){slicenumber = 16;} } // end if (CosThetaMu > 0.3 && CosThetaMu <= 0.8) else if (CosThetaMu > 0.8 && CosThetaMu <= 1 && CosThetaP > 0.3 && CosThetaP <= 0.8){slicenumber = 17;} } // end if (nProtonsAboveThresh == 1) // No check on binnumber = -999 here, because many events won't fall into one of these slices // If useCC0pi0p is false, adjust slice numbers for CC0pi1p if (useCC0pi1p && !useCC0pi0p){ slicenumber -= 10; } return slicenumber; }; // // Reimplementation of Measurement1D::Write (calling the original) to also set the slice histograms to have the chi2 of the total 1D histogram -- makes plotting easier // void T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np::Write(std::string drawOpt){ // // call Measurement1D::Write // Measurement1D::Write(drawOpt); // // // Now also set slice histogram titles to be equal to the overall chi2 // std::ostringstream chi2; // chi2 << std::setprecision(5) << GetLikelihood(); // for (size_t i=0; iSetTitle(chi2.str().c_str()); // } // }; diff --git a/src/T2K/T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np.h b/src/T2K/T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np.h index 0b378be..734d362 100644 --- a/src/T2K/T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np.h +++ b/src/T2K/T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np.h @@ -1,81 +1,81 @@ // 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 T2K_CC0PIWITHPROTONS_XSEC_2018_MULTIDIF_0P_1P_NP_H_SEEN #define T2K_CC0PIWITHPROTONS_XSEC_2018_MULTIDIF_0P_1P_NP_H_SEEN #include "Measurement1D.h" class T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np : public Measurement1D { public: /// Basic Constructor. T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np(nuiskey samplekey); /// Virtual Destructor ~T2K_CC0piWithProtons_XSec_2018_multidif_0p_1p_Np() {}; /// Numu CC0PI Signal Definition /// /// /item bool isSignal(FitEvent *nvect); /// Read histograms in a special way because format is different. /// Read from FitPar::GetDataBase()+"/T2K/CC0pi/T2K_CC0PI_2DPmuCosmu_Data.root" void SetHistograms(); /// Bin Tmu CosThetaMu void FillEventVariables(FitEvent* customEvent); // Fill Histograms void FillHistograms(); private: - bool useCC0pi0p = false; - bool useCC0pi1p = false; - bool useCC0piNp = false; + bool useCC0pi0p; + bool useCC0pi1p; + bool useCC0piNp; bool only_allowed_particles; bool numu_event; double numu_energy; int particle_pdg; int fAnalysis; double fPP, fCosThetaP, fPMu, fCosThetaMu, fNp; bool fIsSystCov, fIsStatCov, fIsNormCov; TFile* fInputFile; TH2D* fMCHist_Fine2D; TH1D *fMCHist_CC0pi0pCosTheta; TH1D *fDataHist_CC0pi0pCosTheta; TH1D *fMCHist_CC0pi1pCosTheta; TH1D *fDataHist_CC0pi1pCosTheta; std::vector fMCHist_Slices; std::vector fDataHist_Slices; void FillMCSlice(int nProtonsAboveThresh, double pmu, double CosThetaMu, double pp, double CosThetaP, double w); int Get1DBin(int nProtonsAboveThresh, double pmu, double CosThetaMu, double pp, double CosThetaP); int GetCosThetaMuSlice(int nProtonsAboveThresh, double CosThetaMu); int GetCC0pi1p2DSlice(int nProtonsAboveThresh, double CosThetaMu, double CosThetaP); // void Write(std::string drawOpt); }; #endif diff --git a/src/T2K/T2K_CC0pi_XSec_2DPcos_nu_II.cxx b/src/T2K/T2K_CC0pi_XSec_2DPcos_nu_II.cxx index 9996a83..ebfaa75 100644 --- a/src/T2K/T2K_CC0pi_XSec_2DPcos_nu_II.cxx +++ b/src/T2K/T2K_CC0pi_XSec_2DPcos_nu_II.cxx @@ -1,236 +1,243 @@ // 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 "T2K_SignalDef.h" #include "T2K_CC0pi_XSec_2DPcos_nu_II.h" //******************************************************************** T2K_CC0pi_XSec_2DPcos_nu_II::T2K_CC0pi_XSec_2DPcos_nu_II(nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "T2K_CC0pi_XSec_2DPcos_nu_II sample. \n" "Target: CH \n" "Flux: T2K 2.5 degree off-axis (ND280) \n" "Signal: CC0pi with p_mu > 200 MeV\n" " cth_mu > 0 \n" "https://journals.aps.org/prd/abstract/10.1103/" "PhysRevD.93.112012 Analysis II"; // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); fSettings.SetXTitle("P_{#mu} (GeV)"); fSettings.SetYTitle("cos#theta_{#mu}"); fSettings.SetZTitle("d^{2}#sigma/dP_{#mu}dcos#theta_{#mu} (cm^{2}/GeV)"); fSettings.SetAllowedTypes("DIAG,FULL/FREE,SHAPE,FIX/SYSTCOV/STATCOV", "FIX"); fSettings.SetEnuRange(0.0, 10.0); fSettings.DefineAllowedTargets("C,H"); // CCQELike plot information fSettings.SetTitle("T2K_CC0pi_XSec_2DPcos_nu_II"); fSettings.DefineAllowedSpecies("numu"); FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon fScaleFactor = ((GetEventHistogram()->Integral("width") / (fNEvents + 0.)) * 1E-38 / (TotalIntegratedFlux())); // Setup Histograms SetHistograms(); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; bool T2K_CC0pi_XSec_2DPcos_nu_II::isSignal(FitEvent *event) { return SignalDef::isT2K_CC0pi(event, EnuMin, EnuMax, SignalDef::kAnalysis_II); }; void T2K_CC0pi_XSec_2DPcos_nu_II::FillEventVariables(FitEvent *event) { if (event->NumFSParticle(13) == 0) return; TLorentzVector Pnu = event->GetNeutrinoIn()->fP; TLorentzVector Pmu = event->GetHMFSParticle(13)->fP; double pmu = Pmu.Vect().Mag() / 1000.; double CosThetaMu = cos(Pnu.Vect().Angle(Pmu.Vect())); fXVar = pmu; fYVar = CosThetaMu; return; }; void T2K_CC0pi_XSec_2DPcos_nu_II::SetHistograms() { - fIsSystCov = fSettings.GetS("type").find("SYSTCOV") != std::string::npos; - fIsStatCov = fSettings.GetS("type").find("STATCOV") != std::string::npos; - fIsNormCov = fSettings.GetS("type").find("NORMCOV") != std::string::npos; + // fIsSystCov = fSettings.GetS("type").find("SYSTCOV") != std::string::npos; + // fIsStatCov = fSettings.GetS("type").find("STATCOV") != std::string::npos; + // fIsNormCov = fSettings.GetS("type").find("NORMCOV") != std::string::npos; fNDataPointsX = 12; fNDataPointsY = 10; // Open file std::string infile = FitPar::GetDataBase() + "/T2K/CC0pi/T2K_CC0PI_2DPmuCosmu_Data.root"; TFile *rootfile = new TFile(infile.c_str(), "READ"); - TH2D *tempcov = NULL; + TH2D *tempcov = (TH2D *)rootfile->Get("analysis2_totcov");; // Get Data fDataHist = (TH2D *)rootfile->Get("analysis2_data"); fDataHist->SetDirectory(0); fDataHist->SetNameTitle((fName + "_data").c_str(), (fName + "_data" + fPlotTitles).c_str()); // For some reason the error on the data in the data release is 1E-20 // That is wrong, so set it to zero here for (int i = 0; i < fDataHist->GetXaxis()->GetNbins() + 1; ++i) { for (int j = 0; j < fDataHist->GetYaxis()->GetNbins() + 1; ++j) { fDataHist->SetBinError(i + 1, j + 1, 0.0); } } // Get Syst/Stat Covar - TH2D *tempsyst = 0; - rootfile->GetObject("analysis2_systcov", tempsyst); - TH2D *tempstat = 0; - rootfile->GetObject("analysis2_statcov", tempstat); - TH2D *tempnorm = 0; - rootfile->GetObject("analysis2_normcov", tempnorm); - - if (!tempsyst) { - NUIS_ABORT("tempsyst not found"); - } + // TH2D *tempsyst = 0; + // rootfile->GetObject("analysis2_systcov", tempsyst); + // TH2D *tempstat = 0; + // rootfile->GetObject("analysis2_statcov", tempstat); + // TH2D *tempnorm = 0; + // rootfile->GetObject("analysis2_normcov", tempnorm); - // Create covar [Default is both] - tempcov = (TH2D *)tempsyst->Clone(); - tempcov->Reset(); + // if (!tempsyst) { + // NUIS_ABORT("tempsyst not found"); + // } - if (fIsSystCov) { - tempcov->Add(tempsyst); - } - if (fIsStatCov) { - tempcov->Add(tempstat); - } - if (fIsNormCov) { - tempcov->Add(tempnorm); - } + // Create covar [Default is both] + // tempcov = (TH2D *)tempsyst->Clone(); + // tempcov->Reset(); + + // if (fIsSystCov) { + // tempcov->Add(tempsyst); + // } + // if (fIsStatCov) { + // tempcov->Add(tempstat); + // } + // if (fIsNormCov) { + // tempcov->Add(tempnorm); + // } // if nothing is set, add them all! - if (!fIsSystCov && !fIsStatCov && !fIsNormCov) { - tempcov->Add(tempsyst); - tempcov->Add(tempstat); - tempcov->Add(tempnorm); - } + // if (!fIsSystCov && !fIsStatCov && !fIsNormCov) { + // tempcov->Add(tempsyst); + // tempcov->Add(tempstat); + // tempcov->Add(tempnorm); + // } // Get Map TH2I *InputMap = (TH2I *)rootfile->Get("analysis2_map"); // This map doesn't skip over the 0 data/covar bins fMapHist = (TH2I *)InputMap->Clone(); fMapHist->SetDirectory(NULL); fMapHist->SetNameTitle((fName + "_map").c_str(), (fName + "_map" + fPlotTitles).c_str()); - int binit = 1; - for (int j = 0; j < fDataHist->GetYaxis()->GetNbins(); ++j) { - for (int i = 0; i < fDataHist->GetXaxis()->GetNbins(); ++i) { - int covarhistbin = InputMap->GetBinContent(i + 1, j + 1); - - std::cout << "i: " << i << ", j: " << j - << " -> covarhistbin: " << covarhistbin << " = " - << tempcov->GetBinContent(covarhistbin, covarhistbin) - << std::endl; - if (tempcov->GetBinContent(covarhistbin, covarhistbin) > 0) { - fMapHist->SetBinContent(i + 1, j + 1, binit++); - } else { - fMapHist->SetBinContent(i + 1, j + 1, 0); - } - } - } + // int binit = 1; + // for (int j = 0; j < fDataHist->GetYaxis()->GetNbins(); ++j) { + // for (int i = 0; i < fDataHist->GetXaxis()->GetNbins(); ++i) { + // int covarhistbin = InputMap->GetBinContent(i + 1, j + 1); + + // std::cout << "i: " << i << ", j: " << j + // << " -> covarhistbin: " << covarhistbin << " = " + // << tempcov->GetBinContent(covarhistbin, covarhistbin) + // << std::endl; + // if (tempcov->GetBinContent(covarhistbin, covarhistbin) > 0) { + // fMapHist->SetBinContent(i + 1, j + 1, binit++); + // } else { + // fMapHist->SetBinContent(i + 1, j + 1, 0); + // } + // } + // } int nbins = fMapHist->GetMaximum(); fFullCovar = new TMatrixDSym(nbins); - for (int j_1 = 0; j_1 < fDataHist->GetYaxis()->GetNbins(); ++j_1) { - for (int i_1 = 0; i_1 < fDataHist->GetXaxis()->GetNbins(); ++i_1) { - - for (int j_2 = 0; j_2 < fDataHist->GetYaxis()->GetNbins(); ++j_2) { - for (int i_2 = 0; i_2 < fDataHist->GetXaxis()->GetNbins(); ++i_2) { - - int i = fMapHist->GetBinContent(i_1 + 1, j_1 + 1); - int j = fMapHist->GetBinContent(i_2 + 1, j_2 + 1); - if (i == 0 || j == 0) { - continue; - } - - // get the relevant tempcov bin - int i_input = InputMap->GetBinContent(i_1 + 1, j_1 + 1); - int j_input = InputMap->GetBinContent(i_2 + 1, j_2 + 1); - - std::cout << "i: " << i << ", j: " << j << "i_input: " << i_input - << "j_input: " << j_input - << ", covar = " << tempcov->GetBinContent(i_input, j_input) - << std::endl; - - // Correct for them being 1-offset; - i -= 1; - j -= 1; - - (*fFullCovar)(i, j) = tempcov->GetBinContent(i_input, j_input); - - if ((i == j) && ((*fFullCovar)(i, j) <= 0)) { - NUIS_ABORT("Input covariance had a 0/negative diagonal element: " - << i << ", " << j << ", " << (*fFullCovar)(i, j)); - } - } - } + for (int i=0; i< nbins; ++i){ + for (int j=0;j< nbins; ++j){ + std::cout << i << " " << j << " " << tempcov->GetBinContent(i+1, j+1) << std::endl; + (*fFullCovar)(i, j) = tempcov->GetBinContent(i+1, j+1); } } - TFile *fout= new TFile("mattest.root","RECREATE"); - fout->WriteTObject(fFullCovar,"covar"); - fout->Write(); - fout->Close(); + // for (int j_1 = 0; j_1 < fDataHist->GetYaxis()->GetNbins(); ++j_1) { + // for (int i_1 = 0; i_1 < fDataHist->GetXaxis()->GetNbins(); ++i_1) { + + // for (int j_2 = 0; j_2 < fDataHist->GetYaxis()->GetNbins(); ++j_2) { + // for (int i_2 = 0; i_2 < fDataHist->GetXaxis()->GetNbins(); ++i_2) { + + // int i = fMapHist->GetBinContent(i_1 + 1, j_1 + 1); + // int j = fMapHist->GetBinContent(i_2 + 1, j_2 + 1); + // if (i == 0 || j == 0) { + // continue; + // } + + // // get the relevant tempcov bin + // int i_input = InputMap->GetBinContent(i_1 + 1, j_1 + 1); + // int j_input = InputMap->GetBinContent(i_2 + 1, j_2 + 1); + + // std::cout << "i: " << i << ", j: " << j << "i_input: " << i_input + // << "j_input: " << j_input + // << ", covar = " << tempcov->GetBinContent(i_input, j_input) + // << std::endl; + + // // Correct for them being 1-offset; + // i -= 1; + // j -= 1; + + // (*fFullCovar)(i, j) = tempcov->GetBinContent(i_input, j_input); + + // if ((i == j) && ((*fFullCovar)(i, j) <= 0)) { + // NUIS_ABORT("Input covariance had a 0/negative diagonal element: " + // << i << ", " << j << ", " << (*fFullCovar)(i, j)); + // } + // } + // } + // } + // } + + // TFile *fout= new TFile("mattest.root","RECREATE"); + // fout->WriteTObject(fFullCovar,"covar"); + // fout->Write(); + // fout->Close(); // Setup Covar covar = StatUtils::GetInvert(fFullCovar); - for (int i = 0; i < nbins; i++) { - for (int j = 0; j < nbins; j++) { - if ((i == j) && ((*covar)(i, j) <= 0)) { - NUIS_ABORT("Inverse covariance had a 0/negative diagonal element: " - << i << ", " << j << ", " << (*covar)(i, j)); - } - } - } + // for (int i = 0; i < nbins; i++) { + // for (int j = 0; j < nbins; j++) { + // if ((i == j) && ((*covar)(i, j) <= 0)) { + // NUIS_ABORT("Inverse covariance had a 0/negative diagonal element: " + // << i << ", " << j << ", " << (*covar)(i, j)); + // } + // } + // } fDecomp = StatUtils::GetDecomp(covar); SetShapeCovar(); // Set Data Errors StatUtils::SetDataErrorFromCov(fDataHist, fFullCovar, fMapHist, 1E-38); // Remove root file rootfile->Close(); }; diff --git a/src/T2K/T2K_CC0pi_XSec_H2O_2DPcos_anu.cxx b/src/T2K/T2K_CC0pi_XSec_H2O_2DPcos_anu.cxx index e07cb78..ab45c12 100755 --- a/src/T2K/T2K_CC0pi_XSec_H2O_2DPcos_anu.cxx +++ b/src/T2K/T2K_CC0pi_XSec_H2O_2DPcos_anu.cxx @@ -1,192 +1,190 @@ // 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 "T2K_SignalDef.h" #include "T2K_CC0pi_XSec_H2O_2DPcos_anu.h" -static int nmombins = 7; +static size_t nmombins = 7; static double mom_binning[] = { 400., 530., 670., 800., 1000., 1380., 2010., 3410. }; static int ncosbins[] = { 2, 3, 3, 3, 3, 3, 2 }; static double costheta_binning[][7] = { { 0.84, 0.94, 1. }, { 0.85, 0.92, 0.96, 1. }, { 0.88, 0.93, 0.97, 1. }, { 0.90, 0.94, 0.97, 1. }, { 0.91, 0.95, 0.97, 1. }, { 0.92, 0.96, 0.98, 1. }, { 0.95, 0.98, 1. } }; //******************************************************************** T2K_CC0pi_XSec_H2O_2DPcos_anu::T2K_CC0pi_XSec_H2O_2DPcos_anu(nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "T2K_CC0pi_XSec_H2O_2DPcos_anu. \n" "Target: H2O \n" "Flux: T2K 2.5 degree off-axis (ND280-P0D) \n" "Signal: CC0pi\n" "arXiv:1908.10249"; // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); fSettings.SetXTitle("cos#theta_{#mu}-p_{#mu}"); fSettings.SetYTitle("d^{2}#sigma/dp_{#mu}dcos#theta_{#mu} (cm^{2}/GeV)"); fSettings.SetAllowedTypes("FULL,DIAG/FREE,SHAPE,FIX/SYSTCOV/STATCOV","FIX/FULL"); fSettings.SetEnuRange(0.0, 10.0); fSettings.DefineAllowedTargets("H,O"); // CCQELike plot information fSettings.SetTitle("T2K_CC0pi_XSec_H2O_2DPcos_anu"); fSettings.DefineAllowedSpecies("numub"); FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/water molecule fScaleFactor = ((GetEventHistogram()->Integral("weight")/(fNEvents+0.)) * 18E-38 / (TotalIntegratedFlux(""))); // Setup Histograms SetHistograms(); // Final setup FinaliseMeasurement(); }; bool T2K_CC0pi_XSec_H2O_2DPcos_anu::isSignal(FitEvent *event){ return SignalDef::isT2K_CC0piAnuP0D(event, EnuMin, EnuMax); }; void T2K_CC0pi_XSec_H2O_2DPcos_anu::FillEventVariables(FitEvent* event){ if (event->NumFSParticle(-13) == 0) return; TLorentzVector Pnu = event->GetNeutrinoIn()->fP; TLorentzVector Pmu = event->GetHMFSParticle(-13)->fP; double pmu = Pmu.Vect().Mag(); double CosThetaMu = cos(Pnu.Vect().Angle(Pmu.Vect())); fXVar = pmu; fYVar = CosThetaMu; return; }; void T2K_CC0pi_XSec_H2O_2DPcos_anu::FillHistograms(){ Measurement1D::FillHistograms(); if (Signal){ FillMCSlice( fXVar, fYVar, Weight ); } } // Modification is needed after the full reconfigure to move bins around // Otherwise this would need to be replaced by a TH2Poly which is too awkward. void T2K_CC0pi_XSec_H2O_2DPcos_anu::ConvertEventRates(){ - for (int i = 0; i < nmombins; i++){ + for (size_t i = 0; i < nmombins; i++){ fMCHist_Slices[i]->GetSumw2(); } // Do standard conversion. Measurement1D::ConvertEventRates(); for (size_t i = 0; i < nmombins; ++i) { fMCHist_Slices[i]->Scale(1. / (mom_binning[i + 1] - mom_binning[i])); } // Now Convert into 1D list fMCHist->Reset(); int bincount = 0; - for (int i = 0; i < nmombins; i++){ + for (size_t i = 0; i < nmombins; i++){ for (int j = 0; j < fDataHist_Slices[i]->GetNbinsX(); j++){ fMCHist->SetBinContent(bincount+1, fMCHist_Slices[i]->GetBinContent(j+1)); bincount++; } } return; } void T2K_CC0pi_XSec_H2O_2DPcos_anu::FillMCSlice(double x, double y, double w){ for (size_t i = 0; i < nmombins; ++i) { if ((x > mom_binning[i]) && (x <= mom_binning[i + 1])) { fMCHist_Slices[i]->Fill(y, w); } } } void T2K_CC0pi_XSec_H2O_2DPcos_anu::SetHistograms(){ // Read in 1D Data Histograms fInputFile = new TFile( (FitPar::GetDataBase() + "/T2K/CC0pi/AntiNuMuH2O/AntiNuMuOnH2O_unreg.root").c_str(),"READ"); // Read in 1D Data - TH1D* hLinearResult = (TH1D*) fInputFile->Get("xsecDataRelease"); - int Nbins = hLinearResult->GetNbinsX(); + fDataHist = (TH1D*) fInputFile->Get("xsecDataRelease"); + fDataHist->SetNameTitle((fName + "_data").c_str(), + (fName + "_data" + fPlotTitles).c_str()); - fDataHist = new TH1D("LinarResult","LinarResult",Nbins,0,Nbins); - for (int bin = 0; bin < Nbins; bin++) { - fDataHist->SetBinContent(bin+1, hLinearResult->GetBinContent(bin+1)); - } + int Nbins = fDataHist->GetNbinsX(); // Read relative covariance matrix TH2D* tempcov = (TH2D*) fInputFile->Get("covDataRelease"); // Make absolute covariance matrix fFullCovar = new TMatrixDSym(Nbins); for (int i = 0; i < Nbins; i++){ for (int j = 0; j < Nbins; j++){ (*fFullCovar)(i,j) = tempcov->GetBinContent(i+1, j+1)*fDataHist->GetBinContent(i+1)*fDataHist->GetBinContent(j+1)*1E76; } } covar = StatUtils::GetInvert(fFullCovar); fDecomp = StatUtils::GetDecomp(fFullCovar); // Read in 2D Data Slices and Make MC Slices int bincount = 0; - for (int i = 0; i < nmombins; ++i) { - fDataHist_Slices.push_back(new TH1D(Form("T2K_CC0pi_XSec_H2O_2DPcos_anu_data_Slice%i",i),Form("T2K_CC0pi_XSec_H2O_2DPcos_anu_data_Slice%i",i),ncosbins[i],costheta_binning[i])); + for (uint i = 0; i < nmombins; ++i) { + fDataHist_Slices.push_back(new TH1D(Form("T2K_CC0pi_XSec_H2O_2DPcos_anu_data_Slice%u",i),Form("T2K_CC0pi_XSec_H2O_2DPcos_anu_data_Slice%u",i),ncosbins[i],costheta_binning[i])); for (int j = 0; j < ncosbins[i]; ++j) { fDataHist->SetBinError(bincount+1,sqrt((*fFullCovar)(bincount,bincount))*1E-38); fDataHist_Slices[i]->SetBinContent(j+1, fDataHist->GetBinContent(bincount+1)); fDataHist_Slices[i]->SetBinError(j+1, sqrt((*fFullCovar)(bincount,bincount))*1E-38); bincount++; } fMCHist_Slices.push_back((TH1D*) fDataHist_Slices[i]->Clone()); - fMCHist_Slices[i]->SetNameTitle(Form("T2K_CC0pi_XSec_H2O_2DPcos_anu_MC_Slice%i",i), - (Form("T2K_CC0pi_XSec_H2O_2DPcos_anu_MC_Slice%i",i))); + fMCHist_Slices[i]->SetNameTitle(Form("T2K_CC0pi_XSec_H2O_2DPcos_anu_MC_Slice%u",i), + (Form("T2K_CC0pi_XSec_H2O_2DPcos_anu_MC_Slice%u",i))); SetAutoProcessTH1(fDataHist_Slices[i],kCMD_Write); SetAutoProcessTH1(fMCHist_Slices[i]); } return; }; diff --git a/src/T2K/T2K_CC0pinp_STV_XSec_1Ddat_nu.cxx b/src/T2K/T2K_CC0pinp_STV_XSec_1Ddat_nu.cxx index 05bd3cc..89fedf4 100644 --- a/src/T2K/T2K_CC0pinp_STV_XSec_1Ddat_nu.cxx +++ b/src/T2K/T2K_CC0pinp_STV_XSec_1Ddat_nu.cxx @@ -1,90 +1,90 @@ // 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 "T2K_SignalDef.h" #include "T2K_CC0pinp_STV_XSec_1Ddat_nu.h" //******************************************************************** T2K_CC0pinp_STV_XSec_1Ddat_nu::T2K_CC0pinp_STV_XSec_1Ddat_nu( nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "T2K_CC0pinp_STV_XSec_1Ddpt_nu sample. \n" "Target: CH \n" "Flux: T2K 2.5 degree off-axis (ND280) \n" "Signal: CC0piNp (N>=1) with 450 MeV < p_p < 1 GeV \n" " p_mu > 250 MeV \n" " cth_p > 0.4 \n" " cth_mu > -0.6 \n" "https://doi.org/10.1103/PhysRevD.98.032003 \n"; // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); - fSettings.SetXTitle("#delta#it{#alpha}_{T} (GeV c^{-1})"); + fSettings.SetXTitle("#delta#it{#alpha}_{T} (rad.)"); fSettings.SetYTitle( - "#frac{d#sigma}{d#delta#it{#alpha}_{T}} (cm^{2} nucleon^{-1} rads^{-1})"); + "#frac{d#sigma}{d#delta#it{#alpha}_{T}} (cm^{2} nucleon^{-1} rad.^{-1})"); fSettings.SetAllowedTypes("FIX,FREE,SHAPE/DIAG,FULL/NORM/MASK", "FIX/DIAG"); fSettings.SetEnuRange(0.0, 50.0); fSettings.DefineAllowedTargets("C,H"); // CCQELike plot information fSettings.SetTitle("T2K_CC0pinp_STV_XSec_1Ddat_nu"); // fSettings.SetDataInput( GeneralUtils::GetTopLevelDir() + // "/data/T2K/T2K_CC0pinp_STV_XSec_1Ddat_nu.dat"); fSettings.SetDataInput(FitPar::GetDataBase() + "/T2K/CC0pi/STV/datResults.root;Result"); fSettings.SetCovarInput(FitPar::GetDataBase() + "/T2K/CC0pi/STV/datResults.root;Correlation_Matrix"); fSettings.DefineAllowedSpecies("numu"); FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon fScaleFactor = GetEventHistogram()->Integral("width") * double(1E-38) / (double(fNEvents) * TotalIntegratedFlux("width")); // Plot Setup ------------------------------------------------------- // SetDataFromTextFile( fSettings.GetDataInput() ); // ScaleData(1E-38); // SetCovarFromDiagonal(); SetDataFromRootFile(fSettings.GetDataInput()); SetCorrelationFromRootFile(fSettings.GetCovarInput()); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; void T2K_CC0pinp_STV_XSec_1Ddat_nu::FillEventVariables(FitEvent *event) { fXVar = FitUtils::Get_STV_dalphat_HMProton(event, 14, true); return; }; //******************************************************************** bool T2K_CC0pinp_STV_XSec_1Ddat_nu::isSignal(FitEvent *event) //******************************************************************** { return SignalDef::isT2K_CC0pi_STV(event, EnuMin, EnuMax); } diff --git a/src/T2K/T2K_CC0pinp_STV_XSec_1Ddphit_nu.cxx b/src/T2K/T2K_CC0pinp_STV_XSec_1Ddphit_nu.cxx index a01ed78..e7e88cb 100644 --- a/src/T2K/T2K_CC0pinp_STV_XSec_1Ddphit_nu.cxx +++ b/src/T2K/T2K_CC0pinp_STV_XSec_1Ddphit_nu.cxx @@ -1,90 +1,90 @@ // 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 "T2K_SignalDef.h" #include "T2K_CC0pinp_STV_XSec_1Ddphit_nu.h" //******************************************************************** T2K_CC0pinp_STV_XSec_1Ddphit_nu::T2K_CC0pinp_STV_XSec_1Ddphit_nu( nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "T2K_CC0pinp_STV_XSec_1Ddpt_nu sample. \n" "Target: CH \n" "Flux: T2K 2.5 degree off-axis (ND280) \n" "Signal: CC0piNp (N>=1) with 450 MeV < p_p < 1 GeV \n" " p_mu > 250 MeV \n" " cth_p > 0.4 \n" " cth_mu > -0.6 \n" "https://doi.org/10.1103/PhysRevD.98.032003 \n"; // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); - fSettings.SetXTitle("#delta#it{#phi}_{T} (GeV c^{-1})"); + fSettings.SetXTitle("#delta#it{#phi}_{T} (rad.)"); fSettings.SetYTitle( - "#frac{d#sigma}{d#delta#it{#phi}_{T}} (cm^{2} nucleon^{-1} rads^{-1})"); + "#frac{d#sigma}{d#delta#it{#phi}_{T}} (cm^{2} nucleon^{-1} rad.^{-1})"); fSettings.SetAllowedTypes("FIX,FREE,SHAPE/DIAG,FULL/NORM/MASK", "FIX/DIAG"); fSettings.SetEnuRange(0.0, 50.0); fSettings.DefineAllowedTargets("C,H"); // CCQELike plot information fSettings.SetTitle("T2K_CC0pinp_STV_XSec_1Ddphit_nu"); // fSettings.SetDataInput( GeneralUtils::GetTopLevelDir() + // "/data/T2K/T2K_CC0pinp_STV_XSec_1Ddphit_nu.dat"); fSettings.SetDataInput(FitPar::GetDataBase() + "/T2K/CC0pi/STV/dphitResults.root;Result"); fSettings.SetCovarInput( FitPar::GetDataBase() + "/T2K/CC0pi/STV/dphitResults.root;Correlation_Matrix"); fSettings.DefineAllowedSpecies("numu"); FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon fScaleFactor = GetEventHistogram()->Integral("width") * double(1E-38) / (double(fNEvents) * TotalIntegratedFlux("width")); // Plot Setup ------------------------------------------------------- // SetDataFromTextFile( fSettings.GetDataInput() ); // ScaleData(1E-38); // SetCovarFromDiagonal(); SetDataFromRootFile(fSettings.GetDataInput()); SetCorrelationFromRootFile(fSettings.GetCovarInput()); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; void T2K_CC0pinp_STV_XSec_1Ddphit_nu::FillEventVariables(FitEvent *event) { fXVar = FitUtils::Get_STV_dphit_HMProton(event, 14, true); return; }; //******************************************************************** bool T2K_CC0pinp_STV_XSec_1Ddphit_nu::isSignal(FitEvent *event) //******************************************************************** { return SignalDef::isT2K_CC0pi_STV(event, EnuMin, EnuMax); } diff --git a/src/T2K/T2K_CC1pip_CH_XSec_2Dpmucosmu_nu.cxx b/src/T2K/T2K_CC1pip_CH_XSec_2Dpmucosmu_nu.cxx index c321a0d..cec28d0 100644 --- a/src/T2K/T2K_CC1pip_CH_XSec_2Dpmucosmu_nu.cxx +++ b/src/T2K/T2K_CC1pip_CH_XSec_2Dpmucosmu_nu.cxx @@ -1,206 +1,211 @@ #include "T2K_CC1pip_CH_XSec_2Dpmucosmu_nu.h" #include "T2K_SignalDef.h" //******************************************************************** T2K_CC1pip_CH_XSec_2Dpmucosmu_nu::T2K_CC1pip_CH_XSec_2Dpmucosmu_nu( nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "T2K_CC1pip_CH_XSec_nu sample. \n" "Target: CH \n" "Flux: T2K FHC numu \n" "Signal: CC1pi+, costheta_mu > 0" "https://arxiv.org/abs/1909.03936"; // Setup common settings fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); fSettings.SetXTitle(" "); fSettings.SetYTitle( "d^{2}#sigma/dp_{#mu}dcos#theta_{#mu} (cm^{2}/(GeV/c)/nucleon)"); fSettings.SetAllowedTypes("FIX,FREE,SHAPE/DIAG,FULL/NORM/MASK", "FIX/DIAG"); fSettings.SetEnuRange(0.0, 100.0); fSettings.DefineAllowedTargets("C,H"); // CCQELike plot information fSettings.SetTitle("T2K_CC1pip_CH_XSec_2Dpmucosmu_nu"); fSettings.SetDataInput(GeneralUtils::GetTopLevelDir() + "/data/T2K/CC1pip/CH/PmuThetamu.root"); fSettings.SetCovarInput(GeneralUtils::GetTopLevelDir() + "/data/T2K/CC1pip/CH/PmuThetamu.root"); fSettings.DefineAllowedSpecies("numu"); FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon fScaleFactor = (GetEventHistogram()->Integral("width") * 1E-38) / double(fNEvents) / TotalIntegratedFlux("width"); // Plot Setup ------------------------------------------------------- SetHistograms(); covar = StatUtils::GetInvert(fFullCovar, true); fDecomp = StatUtils::GetDecomp(fFullCovar); SetShapeCovar(); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; void T2K_CC1pip_CH_XSec_2Dpmucosmu_nu::SetHistograms() { TFile *data = new TFile(fSettings.GetDataInput().c_str(), "open"); std::string dataname = "p_mu_theta_mu"; // Number of slices we have const int nslices = 4; int nbins = 0; for (int i = 0; i < nslices; ++i) { TH1D *slice = (TH1D *)data->Get(Form("%s_%i", dataname.c_str(), i)); slice = (TH1D *)slice->Clone((fName + Form("_data_slice%i", i)).c_str()); slice->Scale(1E-38); slice->GetXaxis()->SetTitle(fSettings.GetS("xtitle").c_str()); slice->GetYaxis()->SetTitle(fSettings.GetS("ytitle").c_str()); fDataHist_Slices.push_back(slice); fMCHist_Slices.push_back( (TH1D *)slice->Clone((fName + Form("_mc_slice%i", i)).c_str())); SetAutoProcessTH1(fDataHist_Slices[i], kCMD_Write); SetAutoProcessTH1(fMCHist_Slices[i]); fMCHist_Slices[i]->Reset(); fMCHist_Slices[i]->SetLineColor(kRed); //nbins += slice->GetXaxis()->GetNbins(); + // Skip the highest momentum bin because it's rubbish nbins += slice->GetXaxis()->GetNbins() - 1; } fDataHist = new TH1D(dataname.c_str(), dataname.c_str(), nbins, 0, nbins); fDataHist->SetNameTitle((fName + "_data").c_str(), (fName + "_data").c_str()); int bincount = 1; for (int i = 0; i < nslices; ++i) { + // Skip the highest momentum bin because it's rubbish for (int j = 0; j < fDataHist_Slices[i]->GetXaxis()->GetNbins() - 1; ++j) { //for (int j = 0; j < fDataHist_Slices[i]->GetXaxis()->GetNbins(); ++j) { fDataHist->SetBinContent(bincount, fDataHist_Slices[i]->GetBinContent(j + 1)); fDataHist->SetBinError(bincount, fDataHist_Slices[i]->GetBinError(j + 1)); TString title; if (j == 0) { title = "cos#theta_{#mu}="; if (i == 0) { title += "0-0.8, "; } else if (i == 1) { title += "0.8-0.85, "; } else if (i == 2) { title += "0.85-0.90, "; } else if (i == 3) { title += "0.90-1.00, "; } } title += Form("p_{#mu}=%.2f-%.2f", fDataHist_Slices[i]->GetBinLowEdge(j + 1), fDataHist_Slices[i]->GetBinLowEdge(j + 2)); fDataHist->GetXaxis()->SetBinLabel(bincount, title); bincount++; } } fDataHist->GetXaxis()->SetTitle(fSettings.GetS("xtitle").c_str()); fDataHist->GetYaxis()->SetTitle(fSettings.GetS("ytitle").c_str()); // Get the covariance TMatrixDSym *temp = StatUtils::GetCovarFromRootFile(fSettings.GetCovarInput(), "Covariance_pmu_thetamu"); int ncovbins = temp->GetNrows(); + // Skip the highest momentum bin because it's rubbish fFullCovar = new TMatrixDSym(ncovbins - 4); //fFullCovar = new TMatrixDSym(ncovbins); - if (ncovbins != fDataHist->GetXaxis()->GetNbins()) { + if (fFullCovar->GetNrows() != fDataHist->GetXaxis()->GetNbins()*fDataHist->GetYaxis()->GetNbins()) { NUIS_ERR(FTL, "Number of bins in covariance matrix does not match data"); } // Number of costhetamu slices is nslices // Number of pmu slices is int count1 = 0; + // Skip the highest momentum bin because it's rubbish for (int i = 0; i < ncovbins - 4; ++i) { //for (int i = 0; i < ncovbins; ++i) { int count2 = 0; + // Skip the highest momentum bin because it's rubbish for (int j = 0; j < ncovbins - 4; ++j) { //for (int j = 0; j < ncovbins; ++j) { // 1E79 matched to diagonal error (*fFullCovar)(count1, count2) = (*temp)(i, j); count2++; } count1++; } // Now reorganise the rows delete temp; }; void T2K_CC1pip_CH_XSec_2Dpmucosmu_nu::FillEventVariables(FitEvent *event) { if (event->NumFSParticle(13) == 0) return; TLorentzVector Pnu = event->GetNeutrinoIn()->fP; TLorentzVector Pmu = event->GetHMFSParticle(13)->fP; double pmu = FitUtils::p(Pmu); double costhmu = cos(FitUtils::th(Pnu, Pmu)); fXVar = pmu; fYVar = costhmu; }; void T2K_CC1pip_CH_XSec_2Dpmucosmu_nu::FillHistograms() { Measurement1D::FillHistograms(); if (Signal) { FillMCSlice(fXVar, fYVar, Weight); } }; void T2K_CC1pip_CH_XSec_2Dpmucosmu_nu::ConvertEventRates() { const int nslices = 4; for (int i = 0; i < nslices; i++) { fMCHist_Slices[i]->GetSumw2(); } // Do standard conversion. Measurement1D::ConvertEventRates(); // First scale MC slices also by their width in Y and Z fMCHist_Slices[0]->Scale(1.0 / 0.80); fMCHist_Slices[1]->Scale(1.0 / 0.05); fMCHist_Slices[2]->Scale(1.0 / 0.05); fMCHist_Slices[3]->Scale(1.0 / 0.10); // Now Convert into 1D list fMCHist->Reset(); int bincount = 1; for (int i = 0; i < nslices; i++) { for (int j = 0; j < fDataHist_Slices[i]->GetNbinsX() - 1; j++) { //for (int j = 0; j < fDataHist_Slices[i]->GetNbinsX(); j++) { fMCHist->SetBinContent(bincount, fMCHist_Slices[i]->GetBinContent(j + 1)); bincount++; } } } void T2K_CC1pip_CH_XSec_2Dpmucosmu_nu::FillMCSlice(double pmu, double cosmu, double weight) { // Hard code the bin edges in here if (cosmu < 0.8) { fMCHist_Slices[0]->Fill(pmu, weight); } else if (cosmu > 0.8 && cosmu < 0.85) { fMCHist_Slices[1]->Fill(pmu, weight); } else if (cosmu > 0.85 && cosmu < 0.90) { fMCHist_Slices[2]->Fill(pmu, weight); } else if (cosmu > 0.90 && cosmu < 1.00) { fMCHist_Slices[3]->Fill(pmu, weight); } }; //******************************************************************** bool T2K_CC1pip_CH_XSec_2Dpmucosmu_nu::isSignal(FitEvent *event) { //******************************************************************** return SignalDef::isCC1pip_T2K_arxiv1909_03936(event, EnuMin, EnuMax, SignalDef::kMuonFwd); }; diff --git a/src/T2K/T2K_NuMuAntiNuMu_CC0pi_CH_XSec_2DPcos.cxx b/src/T2K/T2K_NuMuAntiNuMu_CC0pi_CH_XSec_2DPcos.cxx index c5b030c..bef9d13 100644 --- a/src/T2K/T2K_NuMuAntiNuMu_CC0pi_CH_XSec_2DPcos.cxx +++ b/src/T2K/T2K_NuMuAntiNuMu_CC0pi_CH_XSec_2DPcos.cxx @@ -1,249 +1,249 @@ // 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 "T2K_SignalDef.h" #include "T2K_NuMuAntiNuMu_CC0pi_CH_XSec_2DPcos.h" static size_t nangbins = 9; static double angular_binning_costheta[] = {-1, 0.2, 0.6, 0.7, 0.8, 0.85, 0.9, 0.94, 0.98, 1 }; //******************************************************************** T2K_NuMuAntiNuMu_CC0pi_CH_XSec_2DPcos::T2K_NuMuAntiNuMu_CC0pi_CH_XSec_2DPcos(nuiskey samplekey) { //******************************************************************** // Samples overview --------------------------------------------------- fSettings = LoadSampleSettings(samplekey); std::string name = fSettings.GetS("name"); std::string descrip = ""; // This has to deal with NuMu FHC, and AntiNuMu RHC if (!name.compare("T2K_NuMu_CC0pi_CH_XSec_2DPcos")){ descrip = name +". \n" "Target: CH \n" "Flux: T2K 2.5 degree off-axis (ND280) \n" "Signal: CC0pi\n" "DOI:10.1103/PhysRevD.101.112001"; fSettings.SetTitle("T2K_NuMu_CC0pi_CH_XSec_2DPcos"); fSettings.DefineAllowedSpecies("numu"); NuPDG = 14; LepPDG = 13; } else if (!name.compare("T2K_AntiNuMu_CC0pi_CH_XSec_2DPcos")){ descrip = name +". \n" "Target: CH \n" "Flux: T2K 2.5 degree off-axis (ND280) \n" "Signal: CC0pi\n" "DOI:10.1103/PhysRevD.101.112001"; fSettings.SetTitle("T2K_AntiNuMu_CC0pi_CH_XSec_2DPcos"); fSettings.DefineAllowedSpecies("numub"); NuPDG = -14; LepPDG = -13; } // Setup common settings fSettings.SetDescription(descrip); fSettings.SetXTitle("p_{#mu}-cos#theta_{#mu}"); fSettings.SetYTitle("d^{2}#sigma/dP_{#mu}dcos#theta_{#mu} (cm^{2}/GeV)"); fSettings.SetAllowedTypes("DIAG,FULL/FREE,SHAPE,FIX/SYSTCOV/STATCOV","FIX"); fSettings.SetEnuRangeFromFlux(fFluxHist); fSettings.DefineAllowedTargets("C,H"); FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon fScaleFactor = ((GetEventHistogram()->Integral("width")/(fNEvents+0.)) * 1E-38 / (TotalIntegratedFlux())); // Setup Histograms SetHistograms(); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; bool T2K_NuMuAntiNuMu_CC0pi_CH_XSec_2DPcos::isSignal(FitEvent *event){ return SignalDef::isCC0pi(event, NuPDG, EnuMin, EnuMax); }; void T2K_NuMuAntiNuMu_CC0pi_CH_XSec_2DPcos::FillEventVariables(FitEvent* event){ if (event->NumFSParticle(LepPDG) == 0) return; TLorentzVector Pnu = event->GetNeutrinoIn()->fP; TLorentzVector Pmu = event->GetHMFSParticle(LepPDG)->fP; double pmu = Pmu.Vect().Mag()/1000.; double CosThetaMu = cos(Pnu.Vect().Angle(Pmu.Vect())); fXVar = pmu; fYVar = CosThetaMu; return; }; void T2K_NuMuAntiNuMu_CC0pi_CH_XSec_2DPcos::FillHistograms(){ Measurement1D::FillHistograms(); if (Signal){ FillMCSlice( fXVar, fYVar, Weight ); } } void T2K_NuMuAntiNuMu_CC0pi_CH_XSec_2DPcos::ConvertEventRates(){ - for (int i = 0; i < nangbins; i++){ + for (size_t i = 0; i < nangbins; i++){ if(NuPDG==14) fMCHistNuMu_Slices[i]->GetSumw2(); else if(NuPDG==-14) fMCHistAntiNuMu_Slices[i]->GetSumw2(); } // Do standard conversion. Measurement1D::ConvertEventRates(); // Scale MC slices by their bin area for (size_t i = 0; i < nangbins; ++i) { if(NuPDG==14) fMCHistNuMu_Slices[i]->Scale(1. / (angular_binning_costheta[i + 1] - angular_binning_costheta[i])); else if(NuPDG==-14) fMCHistAntiNuMu_Slices[i]->Scale(1. / (angular_binning_costheta[i + 1] - angular_binning_costheta[i])); } // Now Convert into 1D lists fMCHist->Reset(); int bincount = 0; - for (int i = 0; i < nangbins; i++){ + for (size_t i = 0; i < nangbins; i++){ if(NuPDG==14){ for (int j = 0; j < fDataHistNuMu_Slices[i]->GetNbinsX(); j++){ fMCHist->SetBinContent(bincount+1, fMCHistNuMu_Slices[i]->GetBinContent(j+1)); bincount++; } } else if(NuPDG==-14){ for (int j = 0; j < fMCHistAntiNuMu_Slices[i]->GetNbinsX(); j++){ fMCHist->SetBinContent(bincount+1, fMCHistAntiNuMu_Slices[i]->GetBinContent(j+1)); bincount++; } } } return; } void T2K_NuMuAntiNuMu_CC0pi_CH_XSec_2DPcos::FillMCSlice(double x, double y, double w){ for (size_t i = 0; i < nangbins; ++i) { if ((y > angular_binning_costheta[i]) && (y <= angular_binning_costheta[i + 1])) { if(NuPDG==14) fMCHistNuMu_Slices[i]->Fill(x, w); else if(NuPDG==-14) fMCHistAntiNuMu_Slices[i]->Fill(x, w); } } } void T2K_NuMuAntiNuMu_CC0pi_CH_XSec_2DPcos::SetHistograms(){ // Read in 1D Data Histograms fInputFile = new TFile( (FitPar::GetDataBase() + "/T2K/CC0pi/JointNuMu-AntiNuMu/JointNuMuAntiNuMuCC0piXsecDataRelease.root").c_str(),"READ"); TH1D* hLinearResult; if(NuPDG==14) hLinearResult = (TH1D*) fInputFile->Get("hNuMuCC0piXsecLinearResult"); else if(NuPDG==-14) hLinearResult = (TH1D*) fInputFile->Get("hAntiNuMuCC0piXsecLinearResult"); int Nbins = hLinearResult->GetNbinsX(); std::string histoLinearNuType; if(NuPDG==14) histoLinearNuType = "NuMuCC0pi"; else if(NuPDG==-14) histoLinearNuType = "AntiNuMuCC0pi"; // Now Convert into 1D list fDataHist = new TH1D(("LinarResult" + histoLinearNuType).c_str(),("LinarResult" + histoLinearNuType).c_str(),Nbins,0,Nbins); for (int bin = 0; bin < Nbins; bin++){ fDataHist->SetBinContent(bin+1, hLinearResult->GetBinContent(bin+1)); } // Make covariance matrix fFullCovar = new TMatrixDSym(Nbins); TMatrixDSym* tmpcovstat = (TMatrixDSym*) fInputFile->Get("JointNuMuAntiNuMuCC0piXsecCovMatrixStat"); TMatrixDSym* tmpcovsyst = (TMatrixDSym*) fInputFile->Get("JointNuMuAntiNuMuCC0piXsecCovMatrixSyst"); for(int ibin=0; ibinReset(); int bincount = 0; - for (int i = 0; i < nangbins; i++){ + for (size_t i = 0; i < nangbins; i++){ if(NuPDG==14){ // Make slices for data - fDataHistNuMu_Slices.push_back((TH1D*)fInputFile->Get(Form("hXsecNuMuCC0piDataSlice_%i",i))->Clone()); - fDataHistNuMu_Slices[i]->SetNameTitle(Form("T2K_NuMu_CC0pi_2DPcos_data_Slice%i",i), - (Form("T2K_NuMu_CC0pi_2DPcos_data_Slice%i",i))); + fDataHistNuMu_Slices.push_back((TH1D*)fInputFile->Get(Form("hXsecNuMuCC0piDataSlice_%zu",i))->Clone()); + fDataHistNuMu_Slices[i]->SetNameTitle(Form("T2K_NuMu_CC0pi_2DPcos_data_Slice%zu",i), + (Form("T2K_NuMu_CC0pi_2DPcos_data_Slice%zu",i))); // Loop over nbins and set errors from covar for (int j = 0; j < fDataHistNuMu_Slices[i]->GetNbinsX(); j++){ fDataHistNuMu_Slices[i]->SetBinError(j+1, sqrt((*fFullCovar)(bincount,bincount))*1E-38); fDataHist->SetBinContent(bincount+1, fDataHistNuMu_Slices[i]->GetBinContent(j+1)); fDataHist->SetBinError(bincount+1, fDataHistNuMu_Slices[i]->GetBinError(j+1)); bincount++; } // Save MC slices fMCHistNuMu_Slices.push_back((TH1D*) fDataHistNuMu_Slices[i]->Clone()); - fMCHistNuMu_Slices[i]->SetNameTitle(Form("T2K_NuMu_CC0pi_2DPcos_MC_Slice%i",i), (Form("T2K_NuMu_CC0pi_2DPcos_MC_Slice%i",i))); + fMCHistNuMu_Slices[i]->SetNameTitle(Form("T2K_NuMu_CC0pi_2DPcos_MC_Slice%zu",i), (Form("T2K_NuMu_CC0pi_2DPcos_MC_Slice%zu",i))); SetAutoProcessTH1(fDataHistNuMu_Slices[i],kCMD_Write); SetAutoProcessTH1(fMCHistNuMu_Slices[i]); } else if(NuPDG==-14) { // Make slices for data - fDataHistAntiNuMu_Slices.push_back((TH1D*)fInputFile->Get(Form("hXsecAntiNuMuCC0piDataSlice_%i",i))->Clone()); - fDataHistAntiNuMu_Slices[i]->SetNameTitle(Form("T2K_AntiNuMu_CC0pi_2DPcos_data_Slice%i",i), - (Form("T2K_AntiNuMu_CC0pi_2DPcos_data_Slice%i",i))); + fDataHistAntiNuMu_Slices.push_back((TH1D*)fInputFile->Get(Form("hXsecAntiNuMuCC0piDataSlice_%zu",i))->Clone()); + fDataHistAntiNuMu_Slices[i]->SetNameTitle(Form("T2K_AntiNuMu_CC0pi_2DPcos_data_Slice%zu",i), + (Form("T2K_AntiNuMu_CC0pi_2DPcos_data_Slice%zu",i))); //Loop over nbins and set errors from covar for (int j = 0; j < fDataHistAntiNuMu_Slices[i]->GetNbinsX(); j++){ fDataHistAntiNuMu_Slices[i]->SetBinError(j+1, sqrt((*fFullCovar)(bincount,bincount))*1E-38); fDataHist->SetBinContent(bincount+1, fDataHistAntiNuMu_Slices[i]->GetBinContent(j+1)); fDataHist->SetBinError(bincount+1, fDataHistAntiNuMu_Slices[i]->GetBinError(j+1)); bincount++; } // Save MC slices fMCHistAntiNuMu_Slices.push_back((TH1D*) fDataHistAntiNuMu_Slices[i]->Clone()); - fMCHistAntiNuMu_Slices[i]->SetNameTitle(Form("T2K_AntiNuMu_CC0pi_2DPcos_MC_Slice%i",i), (Form("T2K_AntiNuMu_CC0pi_2DPcos_MC_Slice%i",i))); + fMCHistAntiNuMu_Slices[i]->SetNameTitle(Form("T2K_AntiNuMu_CC0pi_2DPcos_MC_Slice%zu",i), (Form("T2K_AntiNuMu_CC0pi_2DPcos_MC_Slice%zu",i))); SetAutoProcessTH1(fDataHistAntiNuMu_Slices[i],kCMD_Write); SetAutoProcessTH1(fMCHistAntiNuMu_Slices[i]); } } return; }; diff --git a/src/T2K/T2K_NuMu_CC0pi_OC_XSec_2DPcos.cxx b/src/T2K/T2K_NuMu_CC0pi_OC_XSec_2DPcos.cxx index bec2fee..5a389f3 100644 --- a/src/T2K/T2K_NuMu_CC0pi_OC_XSec_2DPcos.cxx +++ b/src/T2K/T2K_NuMu_CC0pi_OC_XSec_2DPcos.cxx @@ -1,274 +1,274 @@ // 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 "T2K_NuMu_CC0pi_OC_XSec_2DPcos.h" static size_t nangbins = 6; static double angular_binning_costheta[] = {-1, 0., 0.6, 0.75, 0.86, 0.93, 1.}; //******************************************************************** T2K_NuMu_CC0pi_OC_XSec_2DPcos::T2K_NuMu_CC0pi_OC_XSec_2DPcos(nuiskey samplekey) { //******************************************************************** // Samples overview --------------------------------------------------- fSettings = LoadSampleSettings(samplekey); std::string name = fSettings.GetS("name"); std::string descrip = ""; // This has to deal with NuMu on O and on C if (!name.compare("T2K_NuMu_CC0pi_O_XSec_2DPcos")){ descrip = name +". \n" "Target: Oxygen \n" "Flux: T2K 2.5 degree off-axis (ND280) \n" "Signal: CC0pi\n" "DOI:10.1103/PhysRevD.101.112004"; fSettings.SetTitle("T2K_NuMu_CC0pi_O_XSec_2DPcos"); fSettings.DefineAllowedTargets("O"); Target = "O"; } else if (!name.compare("T2K_NuMu_CC0pi_C_XSec_2DPcos")){ descrip = name +". \n" "Target: Carbon \n" "Flux: T2K 2.5 degree off-axis (ND280) \n" "Signal: CC0pi\n" "DOI:10.1103/PhysRevD.101.112004"; fSettings.SetTitle("T2K_NuMu_CC0pi_C_XSec_2DPcos"); fSettings.DefineAllowedTargets("C"); Target = "C"; } // Setup common settings fSettings.SetDescription(descrip); fSettings.SetXTitle("p_{#mu}-cos#theta_{#mu}"); fSettings.SetYTitle("d^{2}#sigma/dP_{#mu}dcos#theta_{#mu} (cm^{2}/GeV)"); fSettings.SetAllowedTypes("DIAG,FULL/FREE,SHAPE,FIX/SYSTCOV/STATCOV","FIX"); fSettings.SetEnuRangeFromFlux(fFluxHist); fSettings.DefineAllowedSpecies("numu"); FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon fScaleFactor = ((GetEventHistogram()->Integral("width")/(fNEvents+0.)) * 1E-38 / (TotalIntegratedFlux())); // Setup Histograms SetHistograms(); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; bool T2K_NuMu_CC0pi_OC_XSec_2DPcos::isSignal(FitEvent *event){ return SignalDef::isCC0pi(event, 14, EnuMin, EnuMax); }; void T2K_NuMu_CC0pi_OC_XSec_2DPcos::FillEventVariables(FitEvent* event){ if (event->NumFSParticle(13) == 0) return; TLorentzVector Pnu = event->GetNeutrinoIn()->fP; TLorentzVector Pmu = event->GetHMFSParticle(13)->fP; double pmu = Pmu.Vect().Mag()/1000.; double CosThetaMu = cos(Pnu.Vect().Angle(Pmu.Vect())); fXVar = pmu; fYVar = CosThetaMu; return; }; void T2K_NuMu_CC0pi_OC_XSec_2DPcos::FillHistograms(){ Measurement1D::FillHistograms(); if (Signal){ FillMCSlice( fXVar, fYVar, Weight ); } } void T2K_NuMu_CC0pi_OC_XSec_2DPcos::ConvertEventRates(){ - for (int i = 0; i < nangbins; i++){ + for (size_t i = 0; i < nangbins; i++){ if(Target=="O") fMCHistNuMuO_Slices[i]->GetSumw2(); else if(Target=="C") fMCHistNuMuC_Slices[i]->GetSumw2(); } // Do standard conversion. Measurement1D::ConvertEventRates(); // Scale MC slices by their bin width for (size_t i = 0; i < nangbins; ++i) { if(Target=="O") fMCHistNuMuO_Slices[i]->Scale(1. / (angular_binning_costheta[i + 1] - angular_binning_costheta[i])); else if(Target=="C") fMCHistNuMuC_Slices[i]->Scale(1. / (angular_binning_costheta[i + 1] - angular_binning_costheta[i])); } // Now Convert into 1D histogram fMCHist->Reset(); int bincount = 0; - for (int i = 0; i < nangbins; i++){ + for (size_t i = 0; i < nangbins; i++){ if(Target=="O"){ for (int j = 0; j < fMCHistNuMuO_Slices[i]->GetNbinsX(); j++){ fMCHist->SetBinContent(bincount+1, fMCHistNuMuO_Slices[i]->GetBinContent(j+1)); bincount++; } } else if(Target=="C"){ for (int j = 0; j < fMCHistNuMuC_Slices[i]->GetNbinsX(); j++){ fMCHist->SetBinContent(bincount+1, fMCHistNuMuC_Slices[i]->GetBinContent(j+1)); bincount++; } } } return; } void T2K_NuMu_CC0pi_OC_XSec_2DPcos::FillMCSlice(double x, double y, double w){ for (size_t i = 0; i < nangbins; ++i) { if ((y > angular_binning_costheta[i]) && (y <= angular_binning_costheta[i + 1])) { if(Target=="O") fMCHistNuMuO_Slices[i]->Fill(x, w); else if(Target=="C") fMCHistNuMuC_Slices[i]->Fill(x, w); } } } void T2K_NuMu_CC0pi_OC_XSec_2DPcos::SetHistograms(){ // Read covariance matrix fInputFileCov = new TFile( (FitPar::GetDataBase() + "/T2K/CC0pi/JointO-C/covmatrix_noreg.root").c_str(),"READ"); TH1D* hLinearResult; int Nbins; if(Target=="O"){ fInputFile = new TFile( (FitPar::GetDataBase() + "/T2K/CC0pi/JointO-C/linear_unreg_results_O_nuisance.root").c_str(),"READ"); // Read 1D data histogram hLinearResult = (TH1D*) fInputFile->Get("LinResult"); Nbins = hLinearResult->GetNbinsX(); // Make covariance matrix fFullCovar = new TMatrixDSym(Nbins); TMatrixDSym* tempcov = (TMatrixDSym*) fInputFileCov->Get("covmatrixObin"); for(int ibin=0; ibinSetBinContent(bin+1, hLinearResult->GetBinContent(bin+1)); } fDataHist->Reset(); int bincount = 0; - for (int i = 0; i < nangbins; i++){ + for (size_t i = 0; i < nangbins; i++){ // Make slices for data - fDataHistNuMuO_Slices.push_back((TH1D*) fInputFile->Get(Form("dataslice_%i",i))->Clone()); - fDataHistNuMuO_Slices[i]->SetNameTitle(Form("T2K_NuMu_CC0pi_O_2DPcos_data_Slice%i",i), - (Form("T2K_NuMu_CC0pi_O_2DPcos_data_Slice%i",i))); + fDataHistNuMuO_Slices.push_back((TH1D*) fInputFile->Get(Form("dataslice_%zu",i))->Clone()); + fDataHistNuMuO_Slices[i]->SetNameTitle(Form("T2K_NuMu_CC0pi_O_2DPcos_data_Slice%zu",i), + (Form("T2K_NuMu_CC0pi_O_2DPcos_data_Slice%zu",i))); fDataHistNuMuO_Slices[i]->Scale(1E-39); // Loop over nbins and set errors from covariance for (int j = 0; j < fDataHistNuMuO_Slices[i]->GetNbinsX(); j++){ fDataHistNuMuO_Slices[i]->SetBinError(j+1, sqrt((*fFullCovar)(bincount,bincount))*1E-38); fDataHist->SetBinContent(bincount+1, fDataHistNuMuO_Slices[i]->GetBinContent(j+1)); fDataHist->SetBinError(bincount+1, fDataHistNuMuO_Slices[i]->GetBinError(j+1)); bincount++; } // Save MC slices fMCHistNuMuO_Slices.push_back((TH1D*) fDataHistNuMuO_Slices[i]->Clone()); - fMCHistNuMuO_Slices[i]->SetNameTitle(Form("T2K_NuMu_CC0pi_O_2DPcos_MC_Slice%i",i), (Form("T2K_NuMu_CC0pi_O_2DPcos_MC_Slice%i",i))); + fMCHistNuMuO_Slices[i]->SetNameTitle(Form("T2K_NuMu_CC0pi_O_2DPcos_MC_Slice%zu",i), (Form("T2K_NuMu_CC0pi_O_2DPcos_MC_Slice%zu",i))); SetAutoProcessTH1(fDataHistNuMuO_Slices[i],kCMD_Write); SetAutoProcessTH1(fMCHistNuMuO_Slices[i]); } } else if(Target=="C"){ fInputFile = new TFile( (FitPar::GetDataBase() + "/T2K/CC0pi/JointO-C/linear_unreg_results_C_nuisance.root").c_str(),"READ"); // Read 1D data histogram hLinearResult = (TH1D*) fInputFile->Get("LinResult"); Nbins = hLinearResult->GetNbinsX(); // Make the covariance matrix fFullCovar = new TMatrixDSym(Nbins); TMatrixDSym* tempcov = (TMatrixDSym*) fInputFileCov->Get("covmatrixCbin"); for(int ibin=0; ibinSetBinContent(bin+1, hLinearResult->GetBinContent(bin+1)); } fDataHist->Reset(); int bincount=0; - for (int i = 0; i < nangbins; i++){ + for (size_t i = 0; i < nangbins; i++){ // Make slices for data - fDataHistNuMuC_Slices.push_back((TH1D*) fInputFile->Get(Form("dataslice_%i",i))->Clone()); - fDataHistNuMuC_Slices[i]->SetNameTitle(Form("T2K_NuMu_CC0pi_C_2DPcos_data_Slice%i",i), - (Form("T2K_NuMu_CC0pi_C_2DPcos_data_Slice%i",i))); + fDataHistNuMuC_Slices.push_back((TH1D*) fInputFile->Get(Form("dataslice_%zu",i))->Clone()); + fDataHistNuMuC_Slices[i]->SetNameTitle(Form("T2K_NuMu_CC0pi_C_2DPcos_data_Slice%zu",i), + (Form("T2K_NuMu_CC0pi_C_2DPcos_data_Slice%zu",i))); fDataHistNuMuC_Slices[i]->Scale(1E-39); //Loop over nbins and set errors from covariance for (int j = 0; j < fDataHistNuMuC_Slices[i]->GetNbinsX(); j++){ fDataHistNuMuC_Slices[i]->SetBinError(j+1, sqrt((*fFullCovar)(bincount,bincount))*1E-38); fDataHist->SetBinContent(bincount+1, fDataHistNuMuC_Slices[i]->GetBinContent(j+1)); fDataHist->SetBinError(bincount+1, fDataHistNuMuC_Slices[i]->GetBinError(j+1)); bincount++; } //Save MC slices fMCHistNuMuC_Slices.push_back((TH1D*) fDataHistNuMuC_Slices[i]->Clone()); - fMCHistNuMuC_Slices[i]->SetNameTitle(Form("T2K_NuMu_CC0pi_C_2DPcos_MC_Slice%i",i), (Form("T2K_NuMu_CC0pi_C_2DPcos_MC_Slice%i",i))); + fMCHistNuMuC_Slices[i]->SetNameTitle(Form("T2K_NuMu_CC0pi_C_2DPcos_MC_Slice%zu",i), (Form("T2K_NuMu_CC0pi_C_2DPcos_MC_Slice%zu",i))); SetAutoProcessTH1(fDataHistNuMuC_Slices[i],kCMD_Write); SetAutoProcessTH1(fMCHistNuMuC_Slices[i]); } } return; }; diff --git a/src/Utils/BeamUtils.h b/src/Utils/BeamUtils.h index dde24c2..50d4efb 100644 --- a/src/Utils/BeamUtils.h +++ b/src/Utils/BeamUtils.h @@ -1,47 +1,47 @@ // 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 BEAM_UTILS_H #define BEAM_UTILS_H #include #include "FitLogger.h" #include "GeneralUtils.h" /*! * \addtogroup Utils * @{ */ /// Namespace for any global util functions related to beam simulation namespace BeamUtils{ - /// @brief Converts comma seperated string of beam ids into PDG vector + /// @brief Converts comma separated string of beam ids into PDG vector /// /// e.g. 'numu,nue,numub,e,16' = <14,12,-14,11,16> std::vector ParseSpeciesToIntVect(std::string spc); /// @brief Convert flux ID to a flux definition for use in gen_nuisance std::string ConvertFluxIDs (std::string); /// @brief Lists all possible flux ids, should be kept in sync with convert function. void ListFluxIDs (void); } /*! @} */ #endif diff --git a/src/Utils/PlotUtils.cxx b/src/Utils/PlotUtils.cxx index 61f5a1d..009ad71 100644 --- a/src/Utils/PlotUtils.cxx +++ b/src/Utils/PlotUtils.cxx @@ -1,1210 +1,1210 @@ // 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 "PlotUtils.h" #include "FitEvent.h" #include "StatUtils.h" // MOVE TO MB UTILS! // This function is intended to be modified to enforce a consistent masking for // all models. TH2D *PlotUtils::SetMaskHist(std::string type, TH2D *data) { TH2D *fMaskHist = (TH2D *)data->Clone("fMaskHist"); for (int xBin = 0; xBin < fMaskHist->GetNbinsX(); ++xBin) { for (int yBin = 0; yBin < fMaskHist->GetNbinsY(); ++yBin) { if (data->GetBinContent(xBin + 1, yBin + 1) == 0) fMaskHist->SetBinContent(xBin + 1, yBin + 1, 0); else fMaskHist->SetBinContent(xBin + 1, yBin + 1, 0.5); if (!type.compare("MB_numu_2D")) { if (yBin == 19 && xBin < 8) fMaskHist->SetBinContent(xBin + 1, yBin + 1, 1.0); } else { if (yBin == 19 && xBin < 11) fMaskHist->SetBinContent(xBin + 1, yBin + 1, 1.0); } if (yBin == 18 && xBin < 3) fMaskHist->SetBinContent(xBin + 1, yBin + 1, 1.0); if (yBin == 17 && xBin < 2) fMaskHist->SetBinContent(xBin + 1, yBin + 1, 1.0); if (yBin == 16 && xBin < 1) fMaskHist->SetBinContent(xBin + 1, yBin + 1, 1.0); } } return fMaskHist; }; // MOVE TO GENERAL UTILS? bool PlotUtils::CheckObjectWithName(TFile *inFile, std::string substring) { TIter nextkey(inFile->GetListOfKeys()); TKey *key; while ((key = (TKey *)nextkey())) { std::string test(key->GetName()); if (test.find(substring) != std::string::npos) return true; } return false; }; // MOVE TO GENERAL UTILS? std::string PlotUtils::GetObjectWithName(TFile *inFile, std::string substring) { TIter nextkey(inFile->GetListOfKeys()); TKey *key; std::string output = ""; while ((key = (TKey *)nextkey())) { std::string test(key->GetName()); if (test.find(substring) != std::string::npos) output = test; } return output; }; void PlotUtils::CreateNeutModeArray(TH1 *hist, TH1 *neutarray[]) { for (int i = 0; i < 60; i++) { neutarray[i] = (TH1 *)hist->Clone(Form("%s_NMODE_%i", hist->GetName(), i)); } return; }; void PlotUtils::DeleteNeutModeArray(TH1 *neutarray[]) { for (int i = 0; i < 60; i++) { delete neutarray[i]; } return; }; void PlotUtils::FillNeutModeArray(TH1D *hist[], int mode, double xval, double weight) { if (abs(mode) > 60) return; hist[abs(mode)]->Fill(xval, weight); return; }; void PlotUtils::FillNeutModeArray(TH2D *hist[], int mode, double xval, double yval, double weight) { if (abs(mode) > 60) return; hist[abs(mode)]->Fill(xval, yval, weight); return; }; THStack PlotUtils::GetNeutModeStack(std::string title, TH1 *ModeStack[], int option) { (void)option; THStack allmodes = THStack(title.c_str(), title.c_str()); for (int i = 0; i < 60; i++) { allmodes.Add(ModeStack[i]); } // Credit to Clarence for copying all this out. // CC ModeStack[1]->SetTitle("CCQE"); ModeStack[1]->SetFillColor(kBlue); // ModeStack[1]->SetFillStyle(3444); ModeStack[1]->SetLineColor(kBlue); ModeStack[2]->SetTitle("2p/2h Nieves"); ModeStack[2]->SetFillColor(kRed); // ModeStack[2]->SetFillStyle(3344); ModeStack[2]->SetLineColor(kRed); // ModeStack[11]->SetTitle("#it{#nu + p #rightarrow l^{-} + p + #pi^{+}}"); ModeStack[11]->SetTitle("CC1#pi^{+} on p"); ModeStack[11]->SetFillColor(kGreen); // ModeStack[11]->SetFillStyle(3004); ModeStack[11]->SetLineColor(kGreen); // ModeStack[12]->SetTitle("#it{#nu + n #rightarrow l^{-} + p + #pi^{0}}"); ModeStack[12]->SetTitle("CC1#pi^{0} on n"); ModeStack[12]->SetFillColor(kGreen + 3); // ModeStack[12]->SetFillStyle(3005); ModeStack[12]->SetLineColor(kGreen); // ModeStack[13]->SetTitle("#it{#nu + n #rightarrow l^{-} + n + #pi^{+}}"); ModeStack[13]->SetTitle("CC1#pi^{+} on n"); ModeStack[13]->SetFillColor(kGreen - 2); // ModeStack[13]->SetFillStyle(3004); ModeStack[13]->SetLineColor(kGreen); ModeStack[16]->SetTitle("CC coherent"); ModeStack[16]->SetFillColor(kBlue); // ModeStack[16]->SetFillStyle(3644); ModeStack[16]->SetLineColor(kBlue); // ModeStack[17]->SetTitle("#it{#nu + n #rightarrow l^{-} + p + #gamma}"); ModeStack[17]->SetTitle("CC1#gamma"); ModeStack[17]->SetFillColor(kMagenta); // ModeStack[17]->SetFillStyle(3001); ModeStack[17]->SetLineColor(kMagenta); ModeStack[21]->SetTitle("Multi #pi (1.3 < W < 2.0)"); ModeStack[21]->SetFillColor(kYellow); // ModeStack[21]->SetFillStyle(3005); ModeStack[21]->SetLineColor(kYellow); // ModeStack[22]->SetTitle("#it{#nu + n #rightarrow l^{-} + p + #eta^{0}}"); ModeStack[22]->SetTitle("CC1#eta^{0} on n"); ModeStack[22]->SetFillColor(kYellow - 2); // ModeStack[22]->SetFillStyle(3013); ModeStack[22]->SetLineColor(kYellow - 2); // ModeStack[23]->SetTitle("#it{#nu + n #rightarrow l^{-} + #Lambda + // K^{+}}"); ModeStack[23]->SetTitle("CC1#Labda1K^{+}"); ModeStack[23]->SetFillColor(kYellow - 6); // ModeStack[23]->SetFillStyle(3013); ModeStack[23]->SetLineColor(kYellow - 6); ModeStack[26]->SetTitle("DIS (W > 2.0)"); ModeStack[26]->SetFillColor(kRed); // ModeStack[26]->SetFillStyle(3006); ModeStack[26]->SetLineColor(kRed); // NC // ModeStack[31]->SetTitle("#it{#nu + n #rightarrow #nu + n + #pi^{0}}"); ModeStack[31]->SetTitle("NC1#pi^{0} on n"); ModeStack[31]->SetFillColor(kBlue); // ModeStack[31]->SetFillStyle(3004); ModeStack[31]->SetLineColor(kBlue); // ModeStack[32]->SetTitle("#it{#nu + p #rightarrow #nu + p + #pi^{0}}"); ModeStack[32]->SetTitle("NC1#pi^{0} on p"); ModeStack[32]->SetFillColor(kBlue + 3); // ModeStack[32]->SetFillStyle(3004); ModeStack[32]->SetLineColor(kBlue + 3); // ModeStack[33]->SetTitle("#it{#nu + n #rightarrow #nu + p + #pi^{-}}"); ModeStack[33]->SetTitle("NC1#pi^{-} on n"); ModeStack[33]->SetFillColor(kBlue - 2); // ModeStack[33]->SetFillStyle(3005); ModeStack[33]->SetLineColor(kBlue - 2); // ModeStack[34]->SetTitle("#it{#nu + p #rightarrow #nu + n + #pi^{+}}"); ModeStack[34]->SetTitle("NC1#pi^{+} on p"); ModeStack[34]->SetFillColor(kBlue - 8); // ModeStack[34]->SetFillStyle(3005); ModeStack[34]->SetLineColor(kBlue - 8); ModeStack[36]->SetTitle("NC Coherent"); ModeStack[36]->SetFillColor(kBlue + 8); // ModeStack[36]->SetFillStyle(3644); ModeStack[36]->SetLineColor(kBlue + 8); // ModeStack[38]->SetTitle("#it{#nu + n #rightarrow #nu + n + #gamma}"); ModeStack[38]->SetTitle("NC1#gamma on n"); ModeStack[38]->SetFillColor(kMagenta); // ModeStack[38]->SetFillStyle(3001); ModeStack[38]->SetLineColor(kMagenta); // ModeStack[39]->SetTitle("#it{#nu + p #rightarrow #nu + p + #gamma}"); ModeStack[39]->SetTitle("NC1#gamma on p"); ModeStack[39]->SetFillColor(kMagenta - 10); // ModeStack[39]->SetFillStyle(3001); ModeStack[39]->SetLineColor(kMagenta - 10); ModeStack[41]->SetTitle("Multi #pi (1.3 < W < 2.0)"); ModeStack[41]->SetFillColor(kBlue - 10); // ModeStack[41]->SetFillStyle(3005); ModeStack[41]->SetLineColor(kBlue - 10); // ModeStack[42]->SetTitle("#it{#nu + n #rightarrow #nu + n + #eta^{0}}"); ModeStack[42]->SetTitle("NC1#eta^{0} on n"); ModeStack[42]->SetFillColor(kYellow - 2); // ModeStack[42]->SetFillStyle(3013); ModeStack[42]->SetLineColor(kYellow - 2); // ModeStack[43]->SetTitle("#it{#nu + p #rightarrow #nu + p + #eta^{0}}"); ModeStack[43]->SetTitle("NC1#eta^{0} on p"); ModeStack[43]->SetFillColor(kYellow - 4); // ModeStack[43]->SetFillStyle(3013); ModeStack[43]->SetLineColor(kYellow - 4); // ModeStack[44]->SetTitle("#it{#nu + n #rightarrow #nu + #Lambda + K^{0}}"); ModeStack[44]->SetTitle("NC1#Lambda1K^{0} on n"); ModeStack[44]->SetFillColor(kYellow - 6); // ModeStack[44]->SetFillStyle(3014); ModeStack[44]->SetLineColor(kYellow - 6); // ModeStack[45]->SetTitle("#it{#nu + p #rightarrow #nu + #Lambda + K^{+}}"); ModeStack[45]->SetTitle("NC1#Lambda1K^{+}"); ModeStack[45]->SetFillColor(kYellow - 10); // ModeStack[45]->SetFillStyle(3014); ModeStack[45]->SetLineColor(kYellow - 10); ModeStack[46]->SetTitle("DIS (W > 2.0)"); ModeStack[46]->SetFillColor(kRed); // ModeStack[46]->SetFillStyle(3006); ModeStack[46]->SetLineColor(kRed); // ModeStack[51]->SetTitle("#it{#nu + p #rightarrow #nu + p}"); ModeStack[51]->SetTitle("NC on p"); ModeStack[51]->SetFillColor(kBlack); // ModeStack[51]->SetFillStyle(3444); ModeStack[51]->SetLineColor(kBlack); // ModeStack[52]->SetTitle("#it{#nu + n #rightarrow #nu + n}"); ModeStack[52]->SetTitle("NC on n"); ModeStack[52]->SetFillColor(kGray); // ModeStack[52]->SetFillStyle(3444); ModeStack[52]->SetLineColor(kGray); return allmodes; }; TLegend PlotUtils::GenerateStackLegend(THStack stack, int xlow, int ylow, int xhigh, int yhigh) { TLegend leg = TLegend(xlow, ylow, xhigh, yhigh); TObjArray *histarray = stack.GetStack(); int nhist = histarray->GetEntries(); for (int i = 0; i < nhist; i++) { TH1 *hist = (TH1 *)(histarray->At(i)); leg.AddEntry((hist), ((TH1 *)histarray->At(i))->GetTitle(), "fl"); } leg.SetName(Form("%s_LEG", stack.GetName())); return leg; }; void PlotUtils::ScaleNeutModeArray(TH1 *hist[], double factor, std::string option) { for (int i = 0; i < 60; i++) { if (hist[i]) hist[i]->Scale(factor, option.c_str()); } return; }; void PlotUtils::ResetNeutModeArray(TH1 *hist[]) { for (int i = 0; i < 60; i++) { if (hist[i]) hist[i]->Reset(); } return; }; //******************************************************************** // This assumes the Enu axis is the x axis, as is the case for MiniBooNE 2D // distributions void PlotUtils::FluxUnfoldedScaling(TH2D *fMCHist, TH1D *fhist, TH1D *ehist, double scalefactor) { //******************************************************************** // Make clones to avoid changing stuff TH1D *eventhist = (TH1D *)ehist->Clone(); TH1D *fFluxHist = (TH1D *)fhist->Clone(); // Undo width integral in SF fMCHist->Scale(scalefactor / eventhist->Integral(1, eventhist->GetNbinsX() + 1, "width")); // Standardise The Flux eventhist->Scale(1.0 / fFluxHist->Integral()); fFluxHist->Scale(1.0 / fFluxHist->Integral()); // Do interpolation for 2D plots? // fFluxHist = PlotUtils::InterpolateFineHistogram(fFluxHist,100,"width"); // eventhist = PlotUtils::InterpolateFineHistogram(eventhist,100,"width"); // eventhist->Scale(1.0/fFluxHist->Integral()); // fFluxHist->Scale(1.0/fFluxHist->Integral()); // Scale fMCHist by eventhist integral fMCHist->Scale(eventhist->Integral(1, eventhist->GetNbinsX() + 1)); // Find which axis is the Enu axis bool EnuOnXaxis = false; std::string xaxis = fMCHist->GetXaxis()->GetTitle(); if (xaxis.find("E") != std::string::npos && xaxis.find("nu") != std::string::npos) EnuOnXaxis = true; std::string yaxis = fMCHist->GetYaxis()->GetTitle(); if (yaxis.find("E") != std::string::npos && xaxis.find("nu") != std::string::npos) { // First check that xaxis didn't also find Enu if (EnuOnXaxis) { NUIS_ERR(FTL, fMCHist->GetTitle() << " error:"); NUIS_ERR(FTL, "Found Enu in xaxis title: " << xaxis); NUIS_ERR(FTL, "AND"); NUIS_ERR(FTL, "Found Enu in yaxis title: " << yaxis); NUIS_ABORT("Enu on x and Enu on y flux unfolded scaling isn't " "implemented, please modify " << __FILE__ << ":" << __LINE__); } EnuOnXaxis = false; } // Now Get a flux PDF assuming X axis is Enu TH1D *pdfflux = NULL; // If xaxis is Enu if (EnuOnXaxis) pdfflux = (TH1D *)fMCHist->ProjectionX()->Clone(); // If yaxis is Enu else pdfflux = (TH1D *)fMCHist->ProjectionY()->Clone(); // pdfflux->Write( (std::string(fMCHist->GetName()) + "_PROJX").c_str()); pdfflux->Reset(); // Awful MiniBooNE Check for the time being // Needed because the flux is in GeV whereas the measurement is in MeV bool ismb = std::string(fMCHist->GetName()).find("MiniBooNE") != std::string::npos; for (int i = 0; i < pdfflux->GetNbinsX(); i++) { double Ml = pdfflux->GetXaxis()->GetBinLowEdge(i + 1); double Mh = pdfflux->GetXaxis()->GetBinLowEdge(i + 2); // double Mc = pdfflux->GetXaxis()->GetBinCenter(i+1); // double Mw = pdfflux->GetBinWidth(i+1); double fluxint = 0.0; // Scaling to match flux for MB if (ismb) { Ml /= 1.E3; Mh /= 1.E3; // Mc /= 1.E3; // Mw /= 1.E3; } for (int j = 0; j < fFluxHist->GetNbinsX(); j++) { // double Fc = fFluxHist->GetXaxis()->GetBinCenter(j+1); double Fl = fFluxHist->GetXaxis()->GetBinLowEdge(j + 1); double Fh = fFluxHist->GetXaxis()->GetBinLowEdge(j + 2); double Fe = fFluxHist->GetBinContent(j + 1); double Fw = fFluxHist->GetXaxis()->GetBinWidth(j + 1); if (Fl >= Ml and Fh <= Mh) { fluxint += Fe; } else if (Fl < Ml and Fl < Mh and Fh > Ml and Fh < Mh) { fluxint += Fe * (Fh - Ml) / Fw; } else if (Fh > Mh and Fl < Mh and Fh > Ml and Fl > Ml) { fluxint += Fe * (Mh - Fl) / Fw; } else if (Ml >= Fl and Mh <= Fh) { fluxint += Fe * (Mh - Ml) / Fw; } else { continue; } } pdfflux->SetBinContent(i + 1, fluxint); } // Then finally divide by the bin-width in for (int i = 0; i < fMCHist->GetNbinsX(); i++) { for (int j = 0; j < fMCHist->GetNbinsY(); j++) { if (pdfflux->GetBinContent(i + 1) == 0.0) continue; // Different scaling depending on if Enu is on x or y axis double scaling = 1.0; // If Enu is on the x-axis, we want the ith entry of the flux // And to divide by the bin width of the jth bin if (EnuOnXaxis) { double binWidth = fMCHist->GetYaxis()->GetBinLowEdge(j + 2) - fMCHist->GetYaxis()->GetBinLowEdge(j + 1); scaling = pdfflux->GetBinContent(i + 1) * binWidth; } else { double binWidth = fMCHist->GetXaxis()->GetBinLowEdge(i + 2) - fMCHist->GetXaxis()->GetBinLowEdge(i + 1); scaling = pdfflux->GetBinContent(j + 1) * binWidth; } // fMCHist->SetBinContent(i + 1, j + 1, // fMCHist->GetBinContent(i + 1, j + 1) / // pdfflux->GetBinContent(i + 1) / binWidth); // fMCHist->SetBinError(i + 1, j + 1, fMCHist->GetBinError(i + 1, j + 1) / // pdfflux->GetBinContent(i + 1) / // binWidth); fMCHist->SetBinContent(i + 1, j + 1, fMCHist->GetBinContent(i + 1, j + 1) / scaling); fMCHist->SetBinError(i + 1, j + 1, fMCHist->GetBinError(i + 1, j + 1) / scaling); } } delete eventhist; delete fFluxHist; }; TH1D *PlotUtils::InterpolateFineHistogram(TH1D *hist, int res, std::string opt) { int nbins = hist->GetNbinsX(); double elow = hist->GetXaxis()->GetBinLowEdge(1); double ehigh = hist->GetXaxis()->GetBinLowEdge(nbins + 1); bool width = true; // opt.find("width") != std::string::npos; TH1D *fine = new TH1D("fine", "fine", nbins * res, elow, ehigh); TGraph *temp = new TGraph(); for (int i = 0; i < nbins; i++) { double E = hist->GetXaxis()->GetBinCenter(i + 1); double C = hist->GetBinContent(i + 1); double W = hist->GetXaxis()->GetBinWidth(i + 1); if (!width) W = 1.0; if (W != 0.0) temp->SetPoint(temp->GetN(), E, C / W); } for (int i = 0; i < fine->GetNbinsX(); i++) { double E = fine->GetXaxis()->GetBinCenter(i + 1); double W = fine->GetBinWidth(i + 1); if (!width) W = 1.0; fine->SetBinContent(i + 1, temp->Eval(E, 0, "S") * W); } fine->Scale(hist->Integral(1, hist->GetNbinsX() + 1) / fine->Integral(1, fine->GetNbinsX() + 1)); // std::cout << "Interpolation Difference = " //<< fine->Integral(1, fine->GetNbinsX() + 1) << "/" //<< hist->Integral(1, hist->GetNbinsX() + 1) << std::endl; return fine; } //******************************************************************** // This interpolates the flux by a TGraph instead of requiring the flux and MC // flux to have the same binning void PlotUtils::FluxUnfoldedScaling(TH1D *mcHist, TH1D *fhist, TH1D *ehist, double scalefactor, int nevents) { //******************************************************************** TH1D *eventhist = (TH1D *)ehist->Clone(); TH1D *fFluxHist = (TH1D *)fhist->Clone(); std::string name = std::string(mcHist->GetName()); if (FitPar::Config().GetParB("save_flux_debug")) { mcHist->Write((name + "_UNF_MC").c_str()); fFluxHist->Write((name + "_UNF_FLUX").c_str()); eventhist->Write((name + "_UNF_EVT").c_str()); TH1D *scalehist = new TH1D("scalehist", "scalehist", 1, 0.0, 1.0); scalehist->SetBinContent(1, scalefactor); scalehist->SetBinContent(2, nevents); scalehist->Write((name + "_UNF_SCALE").c_str()); } // Undo width integral in SF mcHist->Scale(scalefactor / eventhist->Integral(1, eventhist->GetNbinsX() + 1, "width")); // Standardise The Flux eventhist->Scale(1.0 / fFluxHist->Integral()); fFluxHist->Scale(1.0 / fFluxHist->Integral()); // Scale mcHist by eventhist integral mcHist->Scale(eventhist->Integral(1, eventhist->GetNbinsX() + 1)); // Now Get a flux PDF TH1D *pdfflux = (TH1D *)mcHist->Clone(); pdfflux->Reset(); for (int i = 0; i < mcHist->GetNbinsX(); i++) { double Ml = mcHist->GetXaxis()->GetBinLowEdge(i + 1); double Mh = mcHist->GetXaxis()->GetBinLowEdge(i + 2); // double Mc = mcHist->GetXaxis()->GetBinCenter(i+1); // double Me = mcHist->GetBinContent(i+1); // double Mw = mcHist->GetBinWidth(i+1); double fluxint = 0.0; for (int j = 0; j < fFluxHist->GetNbinsX(); j++) { // double Fc = fFluxHist->GetXaxis()->GetBinCenter(j+1); double Fl = fFluxHist->GetXaxis()->GetBinLowEdge(j + 1); double Fh = fFluxHist->GetXaxis()->GetBinLowEdge(j + 2); double Fe = fFluxHist->GetBinContent(j + 1); double Fw = fFluxHist->GetXaxis()->GetBinWidth(j + 1); if (Fl >= Ml and Fh <= Mh) { fluxint += Fe; } else if (Fl < Ml and Fl < Mh and Fh > Ml and Fh < Mh) { fluxint += Fe * (Fh - Ml) / Fw; } else if (Fh > Mh and Fl < Mh and Fh > Ml and Fl > Ml) { fluxint += Fe * (Mh - Fl) / Fw; } else if (Ml >= Fl and Mh <= Fh) { fluxint += Fe * (Mh - Ml) / Fw; } else { continue; } } pdfflux->SetBinContent(i + 1, fluxint); } if (FitPar::Config().GetParB("save_flux_debug")) { pdfflux->Write((name + "_UNF_SCALEHIST").c_str()); } // Scale MC hist by pdfflux for (int i = 0; i < mcHist->GetNbinsX(); i++) { if (pdfflux->GetBinContent(i + 1) == 0.0) continue; mcHist->SetBinContent(i + 1, mcHist->GetBinContent(i + 1) / pdfflux->GetBinContent(i + 1)); mcHist->SetBinError(i + 1, mcHist->GetBinError(i + 1) / pdfflux->GetBinContent(i + 1)); } delete eventhist; delete fFluxHist; }; // MOVE TO GENERAL UTILS //******************************************************************** void PlotUtils::Set2DHistFromText(std::string dataFile, TH2 *hist, double norm, bool skipbins) { //******************************************************************** std::string line; std::ifstream data(dataFile.c_str(), std::ifstream::in); int yBin = 0; while (std::getline(data >> std::ws, line, '\n')) { std::vector entries = GeneralUtils::ParseToDbl(line, " "); // Loop over entries and insert them into the histogram for (uint xBin = 0; xBin < entries.size(); xBin++) { if (!skipbins || entries[xBin] != -1.0) hist->SetBinContent(xBin + 1, yBin + 1, entries[xBin] * norm); } yBin++; } return; } // MOVE TO GENERAL UTILS TH1D *PlotUtils::GetTH1DFromFile(std::string dataFile, std::string title, std::string fPlotTitles, std::string alt_name) { TH1D *tempPlot; // If format is a root file if (dataFile.find(".root") != std::string::npos) { TFile *temp_infile = new TFile(dataFile.c_str(), "READ"); tempPlot = (TH1D *)temp_infile->Get(title.c_str()); tempPlot->SetDirectory(0); temp_infile->Close(); delete temp_infile; - // Else its a space seperated txt file + // Else its a space separated txt file } else { // Make a TGraph Errors TGraphErrors *gr = new TGraphErrors(dataFile.c_str(), "%lg %lg %lg"); if (gr->IsZombie()) { NUIS_ABORT( dataFile << " is a zombie and could not be read. Are you sure it exists?" << std::endl); } double *bins = gr->GetX(); double *values = gr->GetY(); double *errors = gr->GetEY(); int npoints = gr->GetN(); // Fill the histogram from it tempPlot = new TH1D(title.c_str(), title.c_str(), npoints - 1, bins); for (int i = 0; i < npoints; ++i) { tempPlot->SetBinContent(i + 1, values[i]); // If only two columns are present in the input file, use the sqrt(values) // as the error equivalent to assuming that the error is statistical. Also // check that we're looking at an event rate rather than a cross section if (!errors[i] && values[i] > 1E-30) { tempPlot->SetBinError(i + 1, sqrt(values[i])); } else { tempPlot->SetBinError(i + 1, errors[i]); } } delete gr; } // Allow alternate naming for root files if (!alt_name.empty()) { tempPlot->SetNameTitle(alt_name.c_str(), alt_name.c_str()); } // Allow alternate axis titles if (!fPlotTitles.empty()) { tempPlot->SetNameTitle( tempPlot->GetName(), (std::string(tempPlot->GetTitle()) + fPlotTitles).c_str()); } return tempPlot; }; TH1D *PlotUtils::GetRatioPlot(TH1D *hist1, TH1D *hist2) { // make copy of first hist TH1D *new_hist = (TH1D *)hist1->Clone(); // Do bins and errors ourselves as scales can go awkward for (int i = 0; i < new_hist->GetNbinsX(); i++) { if (hist2->GetBinContent(i + 1) == 0.0) { new_hist->SetBinContent(i + 1, 0.0); } new_hist->SetBinContent(i + 1, hist1->GetBinContent(i + 1) / hist2->GetBinContent(i + 1)); new_hist->SetBinError(i + 1, hist1->GetBinError(i + 1) / hist2->GetBinContent(i + 1)); } return new_hist; }; TH1D *PlotUtils::GetRenormalisedPlot(TH1D *hist1, TH1D *hist2) { // make copy of first hist TH1D *new_hist = (TH1D *)hist1->Clone(); if (hist1->Integral("width") == 0 or hist2->Integral("width") == 0) { new_hist->Reset(); return new_hist; } Double_t scaleF = hist2->Integral("width") / hist1->Integral("width"); new_hist->Scale(scaleF); return new_hist; }; TH1D *PlotUtils::GetShapePlot(TH1D *hist1) { // make copy of first hist TH1D *new_hist = (TH1D *)hist1->Clone(); if (hist1->Integral("width") == 0) { new_hist->Reset(); return new_hist; } Double_t scaleF1 = 1.0 / hist1->Integral("width"); new_hist->Scale(scaleF1); return new_hist; }; TH1D *PlotUtils::GetShapeRatio(TH1D *hist1, TH1D *hist2) { TH1D *new_hist1 = GetShapePlot(hist1); TH1D *new_hist2 = GetShapePlot(hist2); // Do bins and errors ourselves as scales can go awkward for (int i = 0; i < new_hist1->GetNbinsX(); i++) { if (hist2->GetBinContent(i + 1) == 0) { new_hist1->SetBinContent(i + 1, 0.0); } new_hist1->SetBinContent(i + 1, new_hist1->GetBinContent(i + 1) / new_hist2->GetBinContent(i + 1)); new_hist1->SetBinError(i + 1, new_hist1->GetBinError(i + 1) / new_hist2->GetBinContent(i + 1)); } delete new_hist2; return new_hist1; }; TH2D *PlotUtils::GetCovarPlot(TMatrixDSym *cov, std::string name, std::string title) { TH2D *CovarPlot; if (cov) CovarPlot = new TH2D((*cov)); else CovarPlot = new TH2D(name.c_str(), title.c_str(), 1, 0, 1, 1, 0, 1); CovarPlot->SetName(name.c_str()); CovarPlot->SetTitle(title.c_str()); return CovarPlot; } TH2D *PlotUtils::GetFullCovarPlot(TMatrixDSym *cov, std::string name) { return PlotUtils::GetCovarPlot( cov, name + "_COV", name + "_COV;Bins;Bins;Covariance (#times10^{-76})"); } TH2D *PlotUtils::GetInvCovarPlot(TMatrixDSym *cov, std::string name) { return PlotUtils::GetCovarPlot( cov, name + "_INVCOV", name + "_INVCOV;Bins;Bins;Inv. Covariance (#times10^{-76})"); } TH2D *PlotUtils::GetDecompCovarPlot(TMatrixDSym *cov, std::string name) { return PlotUtils::GetCovarPlot( cov, name + "_DECCOV", name + "_DECCOV;Bins;Bins;Decomp Covariance (#times10^{-76})"); } TH1D *PlotUtils::GetTH1DFromRootFile(std::string file, std::string name) { if (name.empty()) { std::vector tempfile = GeneralUtils::ParseToStr(file, ";"); file = tempfile[0]; name = tempfile[1]; } TFile *rootHistFile = new TFile(file.c_str(), "READ"); TH1D *tempHist = (TH1D *)rootHistFile->Get(name.c_str())->Clone(); if (tempHist == NULL) { NUIS_ABORT("Could not find distribution " << name << " in file " << file); } tempHist->SetDirectory(0); rootHistFile->Close(); return tempHist; } TH2D *PlotUtils::GetTH2DFromRootFile(std::string file, std::string name) { if (name.empty()) { std::vector tempfile = GeneralUtils::ParseToStr(file, ";"); file = tempfile[0]; name = tempfile[1]; } TFile *rootHistFile = new TFile(file.c_str(), "READ"); TH2D *tempHist = (TH2D *)rootHistFile->Get(name.c_str())->Clone(); tempHist->SetDirectory(0); rootHistFile->Close(); delete rootHistFile; return tempHist; } TH1 *PlotUtils::GetTH1FromRootFile(std::string file, std::string name) { if (name.empty()) { std::vector tempfile = GeneralUtils::ParseToStr(file, ";"); file = tempfile[0]; name = tempfile[1]; } TFile *rootHistFile = new TFile(file.c_str(), "READ"); if (!rootHistFile || rootHistFile->IsZombie()) { NUIS_ABORT("Couldn't open root file: \"" << file << "\"."); } TH1 *tempHist = dynamic_cast(rootHistFile->Get(name.c_str())->Clone()); if (!tempHist) { NUIS_ABORT("Couldn't retrieve: \"" << name << "\" from root file: \"" << file << "\"."); } tempHist->SetDirectory(0); rootHistFile->Close(); delete rootHistFile; return tempHist; } TGraph *PlotUtils::GetTGraphFromRootFile(std::string file, std::string name) { if (name.empty()) { std::vector tempfile = GeneralUtils::ParseToStr(file, ";"); file = tempfile[0]; name = tempfile[1]; } TDirectory *olddir = gDirectory; TFile *rootHistFile = new TFile(file.c_str(), "READ"); if (!rootHistFile || rootHistFile->IsZombie()) { NUIS_ABORT("Couldn't open root file: \"" << file << "\"."); } TDirectory *newdir = gDirectory; TGraph *temp = dynamic_cast(rootHistFile->Get(name.c_str())->Clone()); if (!temp) { NUIS_ABORT("Couldn't retrieve: \"" << name << "\" from root file: \"" << file << "\"."); } newdir->Remove(temp); olddir->Append(temp); rootHistFile->Close(); olddir->cd(); return temp; } /// Returns a vector of named TH1*s found in a single input file. /// /// Expects a descriptor like: file.root[hist1|hist2|...] std::vector PlotUtils::GetTH1sFromRootFile(std::string const &descriptor) { std::vector descriptors = GeneralUtils::ParseToStr(descriptor, ","); std::vector hists; for (size_t d_it = 0; d_it < descriptors.size(); ++d_it) { std::string &d = descriptors[d_it]; std::vector fname = GeneralUtils::ParseToStr(d, "["); if (!fname.size() || !fname[0].length()) { NUIS_ABORT("Couldn't find input file when attempting to parse : \"" << d << "\". Expected input.root[hist1|hist2|...]."); } if (fname[1][fname[1].length() - 1] == ']') { fname[1] = fname[1].substr(0, fname[1].length() - 1); } std::vector histnames = GeneralUtils::ParseToStr(fname[1], "|"); if (!histnames.size()) { NUIS_ABORT( "Couldn't find any histogram name specifiers when attempting to " "parse " ": \"" << fname[1] << "\". Expected hist1|hist2|..."); } TFile *rootHistFile = new TFile(fname[0].c_str(), "READ"); if (!rootHistFile || rootHistFile->IsZombie()) { NUIS_ABORT("Couldn't open root file: \"" << fname[0] << "\"."); } for (size_t i = 0; i < histnames.size(); ++i) { TH1 *tempHist = dynamic_cast(rootHistFile->Get(histnames[i].c_str())->Clone()); if (!tempHist) { NUIS_ABORT("Couldn't retrieve: \"" << histnames[i] << "\" from root file: \"" << fname[0] << "\"."); } tempHist->SetDirectory(0); hists.push_back(tempHist); } rootHistFile->Close(); } return hists; } // Create an array from an input file std::vector PlotUtils::GetArrayFromTextFile(std::string DataFile) { std::string line; std::ifstream data(DataFile.c_str(), std::ifstream::in); // Get first line std::getline(data >> std::ws, line, '\n'); // Convert from a string into a vector of double std::vector entries = GeneralUtils::ParseToDbl(line, " "); return entries; } // Get a 2D array from a text file std::vector > PlotUtils::Get2DArrayFromTextFile(std::string DataFile) { std::string line; std::vector > DataArray; std::ifstream data(DataFile.c_str(), std::ifstream::in); while (std::getline(data >> std::ws, line, '\n')) { std::vector entries = GeneralUtils::ParseToDbl(line, " "); DataArray.push_back(entries); } return DataArray; } TH2D *PlotUtils::GetTH2DFromTextFile(std::string data, std::string binx, std::string biny) { // First read in the binning // Array of x binning std::vector xbins = GetArrayFromTextFile(binx); // Array of y binning std::vector ybins = GetArrayFromTextFile(biny); // Read in the data std::vector > Data = Get2DArrayFromTextFile(data); // And finally fill the data TH2D *DataPlot = new TH2D("TempHist", "TempHist", xbins.size() - 1, &xbins[0], ybins.size() - 1, &ybins[0]); int nBinsX = 0; int nBinsY = 0; for (std::vector >::iterator it = Data.begin(); it != Data.end(); ++it) { nBinsX++; // Get the inner vector std::vector temp = *it; // Save the previous number[of bins to make sure it's uniform binning int oldBinsY = nBinsY; // Reset the counter nBinsY = 0; for (std::vector::iterator jt = temp.begin(); jt != temp.end(); ++jt) { nBinsY++; DataPlot->SetBinContent(nBinsX, nBinsY, *jt); DataPlot->SetBinError(nBinsX, nBinsY, 0.0); } if (oldBinsY > 0 && oldBinsY != nBinsY) { NUIS_ERR(FTL, "Found non-uniform y-binning in " << data); NUIS_ERR(FTL, "Previous slice: " << oldBinsY); NUIS_ERR(FTL, "Current slice: " << nBinsY); NUIS_ABORT("Non-uniform binning is not supported in " "PlotUtils::GetTH2DFromTextFile"); } } // Check x bins if (size_t(nBinsX + 1) != xbins.size()) { NUIS_ERR(FTL, "Number of x bins in data histogram does not match the binning " "histogram!"); NUIS_ERR( FTL, "Are they the wrong way around (i.e. xbinning should be ybinning)?"); NUIS_ERR(FTL, "Data: " << nBinsX); NUIS_ABORT("From " << binx << " binning: " << xbins.size()); } // Check y bins if (size_t(nBinsY + 1) != ybins.size()) { NUIS_ERR(FTL, "Number of y bins in data histogram does not match the binning " "histogram!"); NUIS_ERR( FTL, "Are they the wrong way around (i.e. xbinning should be ybinning)?"); NUIS_ERR(FTL, "Data: " << nBinsY); NUIS_ABORT("From " << biny << " binning: " << ybins.size()); } return DataPlot; } TH1D *PlotUtils::GetSliceY(TH2D *Hist, int SliceNo) { TH1D *Slice = Hist->ProjectionX(Form("%s_SLICEY%i", Hist->GetName(), SliceNo), SliceNo, SliceNo, "e"); Slice->SetTitle(Form("%s, %.2f-%.2f", Hist->GetYaxis()->GetTitle(), Hist->GetYaxis()->GetBinLowEdge(SliceNo), Hist->GetYaxis()->GetBinLowEdge(SliceNo + 1))); Slice->GetYaxis()->SetTitle(Hist->GetZaxis()->GetTitle()); return Slice; } TH1D *PlotUtils::GetSliceX(TH2D *Hist, int SliceNo) { TH1D *Slice = Hist->ProjectionY(Form("%s_SLICEX%i", Hist->GetName(), SliceNo), SliceNo, SliceNo, "e"); Slice->SetTitle(Form("%s, %.2f-%.2f", Hist->GetXaxis()->GetTitle(), Hist->GetXaxis()->GetBinLowEdge(SliceNo), Hist->GetXaxis()->GetBinLowEdge(SliceNo + 1))); Slice->GetYaxis()->SetTitle(Hist->GetZaxis()->GetTitle()); return Slice; } void PlotUtils::AddNeutModeArray(TH1D *hist1[], TH1D *hist2[], double scaling) { for (int i = 0; i < 60; i++) { if (!hist2[i]) continue; if (!hist1[i]) continue; hist1[i]->Add(hist2[i], scaling); } return; } void PlotUtils::ScaleToData(TH1D *data, TH1D *mc, TH1I *mask) { double scaleF = GetDataMCRatio(data, mc, mask); mc->Scale(scaleF); return; } void PlotUtils::MaskBins(TH1D *hist, TH1I *mask) { for (int i = 0; i < hist->GetNbinsX(); i++) { if (mask->GetBinContent(i + 1) <= 0.5) continue; hist->SetBinContent(i + 1, 0.0); hist->SetBinError(i + 1, 0.0); NUIS_LOG(DEB, "MaskBins: Set " << hist->GetName() << " Bin " << i + 1 << " to 0.0 +- 0.0"); } return; } void PlotUtils::MaskBins(TH2D *hist, TH2I *mask) { for (int i = 0; i < hist->GetNbinsX(); i++) { for (int j = 0; j < hist->GetNbinsY(); j++) { if (mask->GetBinContent(i + 1, j + 1) <= 0.5) continue; hist->SetBinContent(i + 1, j + 1, 0.0); hist->SetBinError(i + 1, j + 1, 0.0); NUIS_LOG(DEB, "MaskBins: Set " << hist->GetName() << " Bin " << i + 1 << " " << j + 1 << " to 0.0 +- 0.0"); } } return; } double PlotUtils::GetDataMCRatio(TH1D *data, TH1D *mc, TH1I *mask) { double rat = 1.0; TH1D *newmc = (TH1D *)mc->Clone(); TH1D *newdt = (TH1D *)data->Clone(); if (mask) { MaskBins(newmc, mask); MaskBins(newdt, mask); } rat = newdt->Integral() / newmc->Integral(); return rat; } TH2D *PlotUtils::GetCorrelationPlot(TH2D *cov, std::string name) { TH2D *cor = (TH2D *)cov->Clone(); cor->Reset(); for (int i = 0; i < cov->GetNbinsX(); i++) { for (int j = 0; j < cov->GetNbinsY(); j++) { if (cov->GetBinContent(i + 1, i + 1) != 0.0 and cov->GetBinContent(j + 1, j + 1) != 0.0) cor->SetBinContent(i + 1, j + 1, cov->GetBinContent(i + 1, j + 1) / (sqrt(cov->GetBinContent(i + 1, i + 1) * cov->GetBinContent(j + 1, j + 1)))); } } if (!name.empty()) { cor->SetNameTitle(name.c_str(), (name + ";;correlation").c_str()); } cor->SetMinimum(-1); cor->SetMaximum(1); return cor; } TH2D *PlotUtils::GetDecompPlot(TH2D *cov, std::string name) { TMatrixDSym *covarmat = new TMatrixDSym(cov->GetNbinsX()); for (int i = 0; i < cov->GetNbinsX(); i++) for (int j = 0; j < cov->GetNbinsY(); j++) (*covarmat)(i, j) = cov->GetBinContent(i + 1, j + 1); TMatrixDSym *decompmat = StatUtils::GetDecomp(covarmat); TH2D *dec = (TH2D *)cov->Clone(); for (int i = 0; i < cov->GetNbinsX(); i++) for (int j = 0; j < cov->GetNbinsY(); j++) dec->SetBinContent(i + 1, j + 1, (*decompmat)(i, j)); delete covarmat; delete decompmat; dec->SetNameTitle(name.c_str(), (name + ";;;decomposition").c_str()); return dec; } TH2D *PlotUtils::MergeIntoTH2D(TH1D *xhist, TH1D *yhist, std::string zname) { std::vector xedges, yedges; for (int i = 0; i < xhist->GetNbinsX() + 2; i++) { xedges.push_back(xhist->GetXaxis()->GetBinLowEdge(i + 1)); } for (int i = 0; i < yhist->GetNbinsX() + 2; i++) { yedges.push_back(yhist->GetXaxis()->GetBinLowEdge(i + 1)); } int nbinsx = xhist->GetNbinsX(); int nbinsy = yhist->GetNbinsX(); std::string name = std::string(xhist->GetName()) + "_vs_" + std::string(yhist->GetName()); std::string titles = ";" + std::string(xhist->GetXaxis()->GetTitle()) + ";" + std::string(yhist->GetXaxis()->GetTitle()) + ";" + zname; TH2D *newplot = new TH2D(name.c_str(), (name + titles).c_str(), nbinsx, &xedges[0], nbinsy, &yedges[0]); return newplot; } //*************************************************** void PlotUtils::MatchEmptyBins(TH1D *data, TH1D *mc) { //************************************************** for (int i = 0; i < data->GetNbinsX(); i++) { if (data->GetBinContent(i + 1) == 0.0 or data->GetBinError(i + 1) == 0.0) mc->SetBinContent(i + 1, 0.0); } return; } //*************************************************** void PlotUtils::MatchEmptyBins(TH2D *data, TH2D *mc) { //************************************************** for (int i = 0; i < data->GetNbinsX(); i++) { for (int j = 0; j < data->GetNbinsY(); j++) { if (data->GetBinContent(i + 1, j + 1) == 0.0 or data->GetBinError(i + 1, j + 1) == 0.0) mc->SetBinContent(i + 1, j + 1, 0.0); } } return; } //*************************************************** TH1D *PlotUtils::GetProjectionX(TH2D *hist, TH2I *mask) { //*************************************************** TH2D *maskedhist = StatUtils::ApplyHistogramMasking(hist, mask); // This includes the underflow/overflow TH1D *hist_X = maskedhist->ProjectionX("_px", 1, maskedhist->GetXaxis()->GetNbins()); hist_X->SetTitle(Form("%s x no under/overflow", hist_X->GetTitle())); delete maskedhist; return hist_X; } //*************************************************** TH1D *PlotUtils::GetProjectionY(TH2D *hist, TH2I *mask) { //*************************************************** TH2D *maskedhist = StatUtils::ApplyHistogramMasking(hist, mask); // This includes the underflow/overflow TH1D *hist_Y = maskedhist->ProjectionY("_py", 1, maskedhist->GetYaxis()->GetNbins()); hist_Y->SetTitle(Form("%s y no under/overflow", hist_Y->GetTitle())); delete maskedhist; return hist_Y; } diff --git a/src/Utils/TargetUtils.h b/src/Utils/TargetUtils.h index edf9a34..13cd20e 100644 --- a/src/Utils/TargetUtils.h +++ b/src/Utils/TargetUtils.h @@ -1,55 +1,55 @@ // 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 TARGET_UTILS_H #define TARGET_UTILS_H #include "FitLogger.h" #include "GeneralUtils.h" /// Namespace for utils parsing target pdgs namespace TargetUtils { - /// Convert comma seperated string of targets to vector of PDG codes + /// Convert comma separated string of targets to vector of PDG codes /// /// e.g. "C,H,10000100010" = "100000600120,10000100010,100000100010" std::vector ParseTargetsToIntVect(std::string targets); /// Convert a target string to pdg code int GetTargetPDGFromString(std::string target); /// Get Nuclear PDG code from Z and A int GetTargetPDGFromZA(int Z, int A); /// Get TargetZ code from the full PDG int GetTargetZFromPDG(int PDG); /// Get TargetA code from the full PDG int GetTargetAFromPDG(int PDG); /// Convert target ids to target that can be used by gen_nuisance std::string ConvertTargetIDs (std::string); /// Lists all possible target IDS, should be kept in sync with convert function void ListTargetIDs(void); } #endif