diff --git a/CMakeLists.txt b/CMakeLists.txt index 590b423..0154ce4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,228 +1,232 @@ # 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 . ################################################################################ -cmake_minimum_required (VERSION 2.6 FATAL_ERROR) +cmake_minimum_required (VERSION 2.8 FATAL_ERROR) + +#Use the compilers found in the path +find_program(CMAKE_C_COMPILER NAMES $ENV{CC} gcc PATHS ENV PATH NO_DEFAULT_PATH) +find_program(CMAKE_CXX_COMPILER NAMES $ENV{CXX} g++ PATHS ENV PATH NO_DEFAULT_PATH) project(NUISANCE) include(ExternalProject) enable_language(Fortran) set (NUISANCE_VERSION_MAJOR 2) set (NUISANCE_VERSION_MINOR 7) set (NUISANCE_VERSION_REVISION 0) set (NUISANCE_VERSION_STRING "v${NUISANCE_VERSION_MAJOR}r${NUISANCE_VERSION_MINOR}") if(${NUISANCE_VERSION_REVISION} STRGREATER "0") set (NUISANCE_VERSION_STRING "${NUISANCE_VERSION_STRING}p${NUISANCE_VERSION_REVISION}") endif() #Set this to TRUE to enable build debugging messages set(BUILD_DEBUG_MSGS TRUE) include(${CMAKE_SOURCE_DIR}/cmake/cmessage.cmake) include(${CMAKE_SOURCE_DIR}/cmake/cacheVariables.cmake) cmessage(STATUS "CMAKE_INSTALL_PREFIX: \"${CMAKE_INSTALL_PREFIX}\"") cmessage(STATUS "CMAKE_BUILD_TYPE: \"${CMAKE_BUILD_TYPE}\"") ################################################################################ # Check Dependencies ################################################################################ ################################## ROOT ###################################### include(${CMAKE_SOURCE_DIR}/cmake/ROOTSetup.cmake) ################################# HEPMC ###################################### include(${CMAKE_SOURCE_DIR}/cmake/HepMC.cmake) ############################ Reweight Engines ################################ include(${CMAKE_SOURCE_DIR}/cmake/ReweightEnginesSetup.cmake) ############################ Other Generators ################################ include(${CMAKE_SOURCE_DIR}/cmake/GiBUUSetup.cmake) if(USE_NUANCE) LIST(APPEND EXTRA_CXX_FLAGS -D__NUANCE_ENABLED__) endif() ################################# Pythia6/8 #################################### include(${CMAKE_SOURCE_DIR}/cmake/pythia6Setup.cmake) include(${CMAKE_SOURCE_DIR}/cmake/pythia8Setup.cmake) ################################# gperftools ################################### include(${CMAKE_SOURCE_DIR}/cmake/gperfSetup.cmake) if(NOT NOTEST) enable_testing() endif() SET(GENERATOR_SUPPORT) foreach(gen NEUT;NuWro;GENIE;GiBUU;NUANCE) if(USE_${gen}) SET(GENERATOR_SUPPORT "${GENERATOR_SUPPORT}${gen} ") endif() endforeach(gen) cmessage(STATUS "Generator Input Support: ${GENERATOR_SUPPORT}") set(MINCODE Routines FCN) set(CORE MCStudies Genie FitBase Config Logger InputHandler Splines Reweight Utils Statistical #Devel Smearceptance ) LIST(APPEND ALLEXPERIMENTS ANL ArgoNeuT BEBC BNL Electron FNAL GGM K2K MINERvA MiniBooNE SciBooNE T2K) foreach(exp ${ALLEXPERIMENTS}) if(NOT NO_${exp}) LIST(APPEND EXPERIMENTS_TO_BUILD ${exp}) else() LIST(REVERSE EXTRA_CXX_FLAGS) LIST(APPEND EXTRA_CXX_FLAGS -D__NO_${exp}__) LIST(REVERSE EXTRA_CXX_FLAGS) endif() endforeach() ################################## COMPILER #################################### include(${CMAKE_SOURCE_DIR}/cmake/c++CompilerSetup.cmake) ################################### doxygen ################################### include(${CMAKE_SOURCE_DIR}/cmake/docsSetup.cmake) ################################################################################ set(MINIMUM_INCLUDE_DIRECTORIES) LIST(APPEND MINIMUM_INCLUDE_DIRECTORIES ${RWENGINE_INCLUDE_DIRECTORIES} ${CMAKE_SOURCE_DIR}/src/FitBase ${CMAKE_SOURCE_DIR}/src/Reweight ${CMAKE_SOURCE_DIR}/src/InputHandler ${CMAKE_SOURCE_DIR}/src/Config ${CMAKE_SOURCE_DIR}/src/Logger ${CMAKE_SOURCE_DIR}/src/Statistical ${CMAKE_SOURCE_DIR}/src/Splines ${CMAKE_SOURCE_DIR}/src/Utils ${CMAKE_SOURCE_DIR}/src/Genie) cmessage(DEBUG "Base include directories: ${MINIMUM_INCLUDE_DIRECTORIES}") set(EXP_INCLUDE_DIRECTORIES) foreach(edir ${EXPERIMENTS_TO_BUILD}) LIST(APPEND EXP_INCLUDE_DIRECTORIES ${CMAKE_SOURCE_DIR}/src/${edir}) endforeach() cmessage(DEBUG "Included experiments: ${EXP_INCLUDE_DIRECTORIES}") foreach(mdir ${MINCODE}) cmessage (DEBUG "Configuring directory: src/${mdir}") add_subdirectory(src/${mdir}) endforeach() foreach(edir ${EXPERIMENTS_TO_BUILD}) cmessage (DEBUG "Configuring directory: src/${edir}") add_subdirectory(src/${edir}) endforeach() foreach(cdir ${CORE}) cmessage (DEBUG "Configuring directory: src/${cdir}") add_subdirectory(src/${cdir}) endforeach() cmessage(DEBUG "Module targets: ${MODULETargets}") add_subdirectory(app) add_subdirectory(src/Tests) configure_file(cmake/setup.sh.in "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/setup.sh" @ONLY) install(FILES "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/setup.sh" DESTINATION ${CMAKE_INSTALL_PREFIX}) configure_file(cmake/MakeBinaryBlob.in "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/MakeBinaryBlob" @ONLY) install(PROGRAMS "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/MakeBinaryBlob" DESTINATION bin) if(USE_DYNSAMPLES) SET(ALL_INCLUDES ${MINIMUM_INCLUDE_DIRECTORIES}) LIST(APPEND ALL_INCLUDES ${CMAKE_SOURCE_DIR}/src/Smearceptance) LIST(APPEND ALL_INCLUDES ${EXP_INCLUDE_DIRECTORIES}) string(REPLACE ";" " -I" ALL_INCLUDES_STR "${ALL_INCLUDES}") cmessage(DEBUG ${CMAKE_DEPENDLIB_FLAGS}) string(REPLACE "-levent " "" CMAKE_DEPENDLIB_FLAGS_NEW ${CMAKE_DEPENDLIB_FLAGS}) set(CMAKE_DEPENDLIB_FLAGS ${CMAKE_DEPENDLIB_FLAGS_NEW}) cmessage(DEBUG ${CMAKE_DEPENDLIB_FLAGS}) string(REPLACE ";" " -l" ALL_MODULETARGETS_STR "${MODULETargets}") configure_file(cmake/BuildDynamicSample.in "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/BuildDynamicSample" @ONLY) install(PROGRAMS "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/BuildDynamicSample" DESTINATION bin) configure_file(cmake/BuildDynamicSmearcepter.in "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/BuildDynamicSmearcepter" @ONLY) install(PROGRAMS "${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/BuildDynamicSmearcepter" DESTINATION bin) endif() install(PROGRAMS "${PROJECT_SOURCE_DIR}/scripts/nuiscardgen" DESTINATION bin) install(PROGRAMS "${PROJECT_SOURCE_DIR}/scripts/nuissamples" DESTINATION bin) diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 1d488e3..1afec7d 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -1,217 +1,225 @@ # Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret ################################################################################ # This file is part of NUISANCE. # # NUISANCE is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # NUISANCE is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with NUISANCE. If not, see . ################################################################################ set(TARGETS_TO_BUILD) if(USE_MINIMIZER) add_executable(nuismin nuismin.cxx) set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};nuismin) target_link_libraries(nuismin ${MODULETargets}) target_link_libraries(nuismin ${CMAKE_DEPENDLIB_FLAGS}) # target_link_libraries(nuismin ${ROOT_LIBS}) if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "") set_target_properties(nuismin PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS}) endif() add_executable(nuissplines nuissplines.cxx) set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};nuissplines) target_link_libraries(nuissplines ${MODULETargets}) target_link_libraries(nuissplines ${CMAKE_DEPENDLIB_FLAGS}) # target_link_libraries(nuissplines ${ROOT_LIBS}) if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "") set_target_properties(nuissplines PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS}) endif() endif() include_directories(${RWENGINE_INCLUDE_DIRECTORIES}) include_directories(${CMAKE_SOURCE_DIR}/src/Routines) include_directories(${CMAKE_SOURCE_DIR}/src/InputHandler) include_directories(${CMAKE_SOURCE_DIR}/src/Genie) include_directories(${CMAKE_SOURCE_DIR}/src/FitBase) include_directories(${CMAKE_SOURCE_DIR}/src/Statistical) include_directories(${CMAKE_SOURCE_DIR}/src/Utils) include_directories(${CMAKE_SOURCE_DIR}/src/Config) include_directories(${CMAKE_SOURCE_DIR}/src/Logger) include_directories(${CMAKE_SOURCE_DIR}/src/Splines) include_directories(${CMAKE_SOURCE_DIR}/src/Reweight) include_directories(${CMAKE_SOURCE_DIR}/src/FCN) include_directories(${CMAKE_SOURCE_DIR}/src/MCStudies) include_directories(${CMAKE_SOURCE_DIR}/src/Smearceptance) include_directories(${EXP_INCLUDE_DIRECTORIES}) if (USE_NuWro AND NOT NUWRO_BUILT_FROM_FILE) add_executable(nuwro_nuisance nuwro_NUISANCE.cxx) set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};nuwro_nuisance) target_link_libraries(nuwro_nuisance ${MODULETargets}) target_link_libraries(nuwro_nuisance ${CMAKE_DEPENDLIB_FLAGS}) # target_link_libraries(nuwro_nuisance ${ROOT_LIBS}) include_directories(${CMAKE_SOURCE_DIR}/src/FitBase) if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "") set_target_properties(nuwro_nuisance PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS}) endif() endif() if (USE_NEUT) add_executable(neut_nuisance neut_NUISANCE.cxx) set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};neut_nuisance) target_link_libraries(neut_nuisance ${MODULETargets}) target_link_libraries(neut_nuisance ${CMAKE_DEPENDLIB_FLAGS}) target_link_libraries(neut_nuisance ${ROOT_LIBS}) include_directories(${CMAKE_SOURCE_DIR}/src/FitBase) if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "") set_target_properties(neut_nuisance PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS}) endif() endif() if (BUILD_GEVGEN) add_executable(gevgen_nuisance gEvGen_NUISANCE.cxx) set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};gevgen_nuisance) target_link_libraries(gevgen_nuisance ${MODULETargets}) target_link_libraries(gevgen_nuisance ${CMAKE_DEPENDLIB_FLAGS}) # target_link_libraries(gevgen_nuisance ${ROOT_LIBS}) include_directories(${CMAKE_SOURCE_DIR}/src/FitBase) include_directories(${GENIE_INCLUDES}/Apps) include_directories(${GENIE_INCLUDES}/FluxDrivers) include_directories(${GENIE_INCLUDES}/EVGDrivers) if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "") set_target_properties(gevgen_nuisance PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS}) endif() add_executable(gevgen_nuisance_mixed gEvGen_NUISANCE_MIXED.cxx) set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};gevgen_nuisance_mixed) target_link_libraries(gevgen_nuisance_mixed ${MODULETargets}) target_link_libraries(gevgen_nuisance_mixed ${CMAKE_DEPENDLIB_FLAGS}) # target_link_libraries(gevgen_nuisance_mixed ${ROOT_LIBS}) include_directories(${CMAKE_SOURCE_DIR}/src/FitBase) include_directories(${GENIE_INCLUDES}/Apps) include_directories(${GENIE_INCLUDES}/FluxDrivers) include_directories(${GENIE_INCLUDES}/EVGDrivers) if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "") set_target_properties(gevgen_nuisance_mixed PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS}) endif() endif() if (USE_GiBUU) add_executable(DumpGiBUUEvents DumpGiBUUEvents.cxx) set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};DumpGiBUUEvents) target_link_libraries(DumpGiBUUEvents ${MODULETargets}) target_link_libraries(DumpGiBUUEvents ${CMAKE_DEPENDLIB_FLAGS}) # target_link_libraries(DumpGiBUUEvents ${ROOT_LIBS}) include_directories(${CMAKE_SOURCE_DIR}/src/FitBase) if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "") set_target_properties(DumpGiBUUEvents PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS}) endif() endif() add_executable(nuiscomp nuiscomp.cxx) set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};nuiscomp) target_link_libraries(nuiscomp ${MODULETargets}) target_link_libraries(nuiscomp ${CMAKE_DEPENDLIB_FLAGS}) # target_link_libraries(nuiscomp ${ROOT_LIBS}) if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "") set_target_properties(nuiscomp PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS}) endif() add_executable(nuisflat nuisflat.cxx) set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};nuisflat) target_link_libraries(nuisflat ${MODULETargets}) target_link_libraries(nuisflat ${CMAKE_DEPENDLIB_FLAGS}) # target_link_libraries(nuisflat ${ROOT_LIBS}) if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "") set_target_properties(nuisflat PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS}) endif() add_executable(nuissmear nuissmear.cxx) set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};nuissmear) target_link_libraries(nuissmear ${MODULETargets}) target_link_libraries(nuissmear ${CMAKE_DEPENDLIB_FLAGS}) # target_link_libraries(nuissmear ${ROOT_LIBS}) if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "") set_target_properties(nuissmear PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS}) endif() add_executable(nuissyst nuissyst.cxx) set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};nuissyst) target_link_libraries(nuissyst ${MODULETargets}) target_link_libraries(nuissyst ${CMAKE_DEPENDLIB_FLAGS}) # target_link_libraries(nuissyst ${ROOT_LIBS}) if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "") set_target_properties(nuissyst PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS}) endif() add_executable(nuisbayes nuisbayes.cxx) set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};nuisbayes) target_link_libraries(nuisbayes ${MODULETargets}) target_link_libraries(nuisbayes ${CMAKE_DEPENDLIB_FLAGS}) # target_link_libraries(nuisbayes ${ROOT_LIBS}) if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "") set_target_properties(nuisbayes PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS}) endif() if(USE_GENIE) add_executable(PrepareGENIE PrepareGENIE.cxx) set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};PrepareGENIE) target_link_libraries(PrepareGENIE ${MODULETargets}) target_link_libraries(PrepareGENIE ${CMAKE_DEPENDLIB_FLAGS}) # target_link_libraries(PrepareGENIE ${ROOT_LIBS}) if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "") set_target_properties(PrepareGENIE PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS}) endif() endif() if(USE_NEUT) add_executable(PrepareNEUT PrepareNEUT.cxx) set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};PrepareNEUT) target_link_libraries(PrepareNEUT ${MODULETargets}) target_link_libraries(PrepareNEUT ${CMAKE_DEPENDLIB_FLAGS}) # target_link_libraries(PrepareNEUT ${ROOT_LIBS}) if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "") set_target_properties(PrepareNEUT PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS}) endif() endif() # PREPARE NUWRO # Commented out for the time being until it is finished.. if(USE_NuWro) add_executable(PrepareNuwro PrepareNuwroEvents.cxx) set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};PrepareNuwro) target_link_libraries(PrepareNuwro ${MODULETargets}) target_link_libraries(PrepareNuwro ${CMAKE_DEPENDLIB_FLAGS}) # target_link_libraries(PrepareNuwro ${ROOT_LIBS}) if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "") set_target_properties(PrepareNuwro PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS}) endif() endif() +add_executable(nuisbac nuisbac.cxx) +set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};nuisbac) +target_link_libraries(nuisbac ${MODULETargets}) +target_link_libraries(nuisbac ${CMAKE_DEPENDLIB_FLAGS}) +if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "") + set_target_properties(nuisbac PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS}) +endif() + install(TARGETS ${TARGETS_TO_BUILD} DESTINATION bin) #add_executable(DumpROOTClassesFromVector DumpROOTClassesFromVector.cxx) # #Strip out -lNuWro_event1 # string(REPLACE "-lNuWro_event1" "" NWEVSTRIPPED_CDF ${CMAKE_DEPENDLIB_FLAGS}) # cmessage(DEBUG "Attempted to strip out nuwro library: \"${CMAKE_DEPENDLIB_FLAGS}\" -> \"${NWEVSTRIPPED_CDF}\"") # add_executable(PrepareNEUT PrepareNEUT.cxx) # target_link_libraries(DumpROOTClassesFromVector ${MODULETargets}) # target_link_libraries(DumpROOTClassesFromVector ${NWEVSTRIPPED_CDF}) # if(NOT CMAKE_LINK_FLAGS STREQUAL "") # set_target_properties(DumpROOTClassesFromVector PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS}) # endif() #install(TARGETS DumpROOTClassesFromVector DESTINATION bin) diff --git a/app/PrepareGENIE.cxx b/app/PrepareGENIE.cxx index 9c4c895..745beb3 100644 --- a/app/PrepareGENIE.cxx +++ b/app/PrepareGENIE.cxx @@ -1,798 +1,775 @@ #include #include #include "FitLogger.h" #include "PlotUtils.h" #include "TFile.h" #include "TH1D.h" #include "TTree.h" #ifdef __GENIE_ENABLED__ #include "Conventions/Units.h" #include "GHEP/GHepParticle.h" #include "PDG/PDGUtils.h" #endif std::string gInputFiles = ""; std::string gOutputFile = ""; std::string gFluxFile = ""; std::string gTarget = ""; double MonoEnergy; int gNEvents = -999; bool IsMonoE = 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); int main(int argc, char* argv[]) { ParseOptions(argc, argv); if (IsMonoE) { RunGENIEPrepareMono(gInputFiles, gTarget, gOutputFile); } else { RunGENIEPrepare(gInputFiles, gFluxFile, gTarget, gOutputFile); } } void RunGENIEPrepareMono(std::string input, std::string target, std::string output) { LOG(FIT) << "Running GENIE Prepare in mono energetic with E = " << MonoEnergy << " GeV" << std::endl; // Setup TTree TChain* tn = new TChain("gtree"); tn->AddFile(input.c_str()); int nevt = tn->GetEntries(); if (gNEvents != -999) { LOG(FIT) << "Overriding number of events by user from " << nevt << " to " << gNEvents << std::endl; nevt = gNEvents; } NtpMCEventRecord* genientpl = NULL; tn->SetBranchAddress("gmcrec", &genientpl); // 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()); - if (i % (nevt / 20) == 0) { + // Clear Event + genientpl->Clear(); + + size_t freq = nevt / 20; + if (freq && !(i % freq)) { LOG(FIT) << "Processed " << i << "/" << nevt << " GENIE events (E: " << neu->E() << " GeV, xsec: " << xsec << " E-38 cm^2/nucleon)" << std::endl; } - - // Clear Event - genientpl->Clear(); } LOG(FIT) << "Processed all events" << std::endl; TFile* outputfile; // If no output is specified just append to the file if (!gOutputFile.length()) { tn->GetEntry(0); outputfile = tn->GetFile(); outputfile->cd(); } else { outputfile = new TFile(gOutputFile.c_str(), "RECREATE"); outputfile->cd(); QLOG(FIT, "Cloning input vector to output file: " << gOutputFile); TTree* cloneTree = tn->CloneTree(); cloneTree->SetDirectory(outputfile); cloneTree->Write(); QLOG(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) { QLOG(FIT, "Could not find nova_wgts tree in " << gOutputFile); } else { QLOG(FIT, "Found nova_wgts tree in " << gOutputFile); } if (nova_tree) { nova_tree->SetDirectory(outputfile); nova_tree->Write(); } QLOG(FIT, "Done cloning tree."); } LOG(FIT) << "Getting splines in mono-energetic..." << std::endl; // Save each of the reconstructed splines to file std::map modeavg; TDirectory* inddir = (TDirectory*)outputfile->Get("IndividualGENIESplines"); if (!inddir) inddir = (TDirectory*)outputfile->mkdir("IndividualGENIESplines"); inddir->cd(); // Loop over GENIE ID's and get MEC count int MECcount = 0; bool MECcorrect = FitPar::Config().GetParB("CorrectGENIEMECNorm"); for (UInt_t i = 0; i < genieids.size(); i++) { if (genieids[i].find("MEC") != std::string::npos) { MECcount++; } } LOG(FIT) << "Found " << MECcount << " repeated MEC instances." << std::endl; 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)) { 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(); LOG(FIT) << "Getting Target Splines" << std::endl; // For each target save a total spline std::map targetsplines; for (uint i = 0; i < targetids.size(); i++) { std::string targ = targetids[i]; LOG(FIT) << "Getting target " << i << ": " << targ << std::endl; targetsplines[targ] = (TH1D*)xsechist->Clone(); targetsplines[targ]->GetYaxis()->SetTitle("#sigma (E_{#nu}) #times 10^{-38} (cm^{2}/target)"); LOG(FIT) << "Created target spline for " << targ << std::endl; for (uint j = 0; j < genieids.size(); j++) { std::string mode = genieids[j]; if (mode.find(targ) != std::string::npos) { LOG(FIT) << " Mode " << mode << " contains " << targ << " target" << std::endl; targetsplines[targ]->Add(modeavg[mode]); + LOG(FIT) << "Finished with Mode " << mode << " " << modeavg[mode]->Integral() << std::endl; } } LOG(FIT) << "Saving target spline:" << targ << std::endl; targetsplines[targ]->Write(("Total_" + targ).c_str(), TObject::kOverwrite); } LOG(FIT) << "Getting total splines" << std::endl; // 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 std::vector targprs = GeneralUtils::ParseToStr(target, ","); 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; if (targstr.find(targpdg) != std::string::npos) { FoundTarget = true; LOG(FIT) << "Adding target spline " << targstr << " Integral = " << xsec->Integral("width") << std::endl; totalxsec->Add(xsec); int nucl = atoi(targpdg.c_str()); totalnucl += int((nucl % 10000) / 10); } } // Check that targets were all found if (!FoundTarget) { ERR(WRN) << "Didn't find target " << targpdg << " in the list of targets recorded by GENIE" << std::endl; ERR(WRN) << " The list of targets you requested is: " << std::endl; for (uint i = 0; i < targprs.size(); ++i) ERR(WRN) << " " << targprs[i] << std::endl; ERR(WRN) << " The list of targets found in GENIE is: " << std::endl; for (std::map::iterator iter = targetsplines.begin(); iter != targetsplines.end(); iter++) ERR(WRN) << " " << iter->first<< std::endl; } } 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()); LOG(FIT) << "Dividing by Total Nucl = " << totalnucl << std::endl; eventhist->Scale(1.0 / double(totalnucl)); eventhist->Write("nuisance_events", TObject::kOverwrite); fluxhist->Write("nuisance_flux", TObject::kOverwrite); LOG(FIT) << "Inclusive XSec Per Nucleon = " << eventhist->Integral("width") * 1E-38 / fluxhist->Integral("width") << std::endl; LOG(FIT) << "XSec Hist Integral = " << totalxsec->Integral("width") << std::endl; outputfile->Close(); return; } void RunGENIEPrepare(std::string input, std::string flux, std::string target, std::string output) { LOG(FIT) << "Running GENIE Prepare with flux..." << std::endl; // Get Flux Hist std::vector fluxvect = GeneralUtils::ParseToStr(flux, ","); - TH1D* fluxhist = NULL; + 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; QLOG(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 = (TH1D*)(fluxfile->Get(fluxvect[1].c_str())); + fluxhist = dynamic_cast(fluxfile->Get(fluxvect[1].c_str())); if (!fluxhist) { ERR(FTL) << "Couldn't find histogram named: \"" << fluxvect[1] << "\" in file: \"" << fluxvect[0] << std::endl; throw; } fluxhist->SetDirectory(0); } } else if (fluxvect.size() == 1) { MonoEnergy = GeneralUtils::StrToDbl(fluxvect[0]); RunGENIEPrepareMono(input, target, output); return; } else { LOG(FTL) << "Bad flux specification: \"" << flux << "\"." << std::endl; throw; } // Setup TTree TChain* tn = new TChain("gtree"); 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()); QLOG(FIT, "Added input file: " << inputvect[iv_it]); } } else { // The Add form can accept wildcards. tn->Add(input.c_str()); } int nevt = tn->GetEntries(); if (gNEvents != -999) { LOG(FIT) << "Overriding number of events by user from " << nevt << " to " << gNEvents << std::endl; nevt = gNEvents; } if (!nevt) { THROW("Couldn't load any events from input specification: \"" << input.c_str() << "\""); } else { QLOG(FIT, "Found " << nevt << " input entries in " << input); } - StopTalking(); NtpMCEventRecord* genientpl = NULL; - StartTalking(); tn->SetBranchAddress("gmcrec", &genientpl); // Make Event and xsec 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); // 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]->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) { LOG(FIT) << "Processed " << i << "/" << nevt << " GENIE events (E: " << neu->E() << " GeV, xsec: " << xsec << " E-38 cm^2/nucleon)" << std::endl; } // Clear Event genientpl->Clear(); } LOG(FIT) << "Processed all events" << std::endl; // Once event loop is done we can start saving stuff into the file TFile* outputfile; if (!gOutputFile.length()) { tn->GetEntry(0); outputfile = tn->GetFile(); outputfile->cd(); } else { outputfile = new TFile(gOutputFile.c_str(), "RECREATE"); outputfile->cd(); QLOG(FIT, "Cloning input vector to output file: " << gOutputFile); TTree* cloneTree = tn->CloneTree(); cloneTree->SetDirectory(outputfile); cloneTree->Write(); + // ******************************** + // CLUDGE KLUDGE KLUDGE FOR NOVA QLOG(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(); if (!nova_tree) { QLOG(FIT, "Could not find nova_wgts tree in " << input); } else { QLOG(FIT, "Found nova_wgts tree in " << input); nova_tree->SetDirectory(outputfile); nova_tree->Write(); } QLOG(FIT, "Done cloning tree."); } LOG(FIT) << "Getting splines..." << std::endl; // Save each of the reconstructed splines to file std::map modeavg; TDirectory* inddir = (TDirectory*)outputfile->Get("IndividualGENIESplines"); if (!inddir) inddir = (TDirectory*)outputfile->mkdir("IndividualGENIESplines"); inddir->cd(); // Loop over GENIE ID's and get MEC count int MECcount = 0; bool MECcorrect = FitPar::Config().GetParB("CorrectGENIEMECNorm"); for (UInt_t i = 0; i < genieids.size(); i++) { if (genieids[i].find("MEC") != std::string::npos) { MECcount++; } } LOG(FIT) << "Found " << MECcount << " repeated MEC instances." << std::endl; 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)) { 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(); LOG(FIT) << "Getting Target Splines" << std::endl; - // For each target save a total spline std::map targetsplines; for (uint i = 0; i < targetids.size(); i++) { std::string targ = targetids[i]; LOG(FIT) << "Getting target " << i << ": " << targ << std::endl; targetsplines[targ] = (TH1D*)xsechist->Clone(); targetsplines[targ]->GetYaxis()->SetTitle("#sigma (E_{#nu}) #times 10^{-38} (cm^{2}/target)"); LOG(FIT) << "Created target spline for " << targ << std::endl; 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) { LOG(FIT) << " Mode " << mode << " contains " << targ << " target" << std::endl; targetsplines[targ]->Add(modeavg[mode]); + LOG(FIT) << "Finished with Mode " << mode << " " << modeavg[mode]->Integral() << std::endl; } } LOG(FIT) << "Saving target spline: " << targ << std::endl; targetsplines[targ]->Write(("Total_" + targ).c_str(), TObject::kOverwrite); } LOG(FIT) << "Getting total splines" << std::endl; // 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] std::cout << "Targets: " << std::endl; // 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, "["); std::cout << " " << *it << std::endl; // 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("]")); //*jt = "hello"; frac_list.push_back(*jt); // Won't find bracket for target } else { targ_list.push_back(*jt); } - std::cout << " " << *jt << std::endl; } } targprs = targ_list; - std::cout << "Target list: " << std::endl; - for (std::vector::iterator it = targ_list.begin(); it != targ_list.end(); it++) { - std::cout << " " << *it << std::endl; - } - - std::cout << "Fraction list: " << std::endl; std::vector targ_fractions; double minimum = 1.0; for (std::vector::iterator it = frac_list.begin(); it != frac_list.end(); it++) { std::cout << " " << *it << std::endl; double frac = std::atof((*it).c_str()); targ_fractions.push_back(frac); if (frac < minimum) minimum = frac; } - std::cout << "minimum target ratio: " << minimum << std::endl; - std::cout << "Fraction list rescaled: " << std::endl; 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; - std::cout << " " << "scaled by smallest: " << *it << std::endl; - std::cout << " " << "scaling: " << tempscaling << std::endl; } - std::cout << "scaling: " << int(scaling+0.5) << std::endl; it = targ_fractions.begin(); for (; it != targ_fractions.end(); it++) { - std::cout << "before scaling and rounding: " << *it << std::endl; // Round the scaling to nearest integer and multiply *it *= int(scaling+0.5); // Round to nearest integer *it = int(*it+0.5); - std::cout << "after scaling and rounding: " << *it << std::endl; totalnucl += *it; } - std::cout << "total number of nucleons in one target: " << totalnucl << std::endl; - - it = targ_fractions.begin(); - jt = targ_list.begin(); - for (; it != targ_fractions.end(); it++, jt++) { - int nucl = atoi((*jt).c_str()); - nucl = (nucl%10000)/10; - std::cout << "final fraction: " << *jt << ": " << *it << "/" << totalnucl << "=" << *it / totalnucl << " or " << *it / nucl << " copies of element " << *jt << std::endl; - } - - // Now count the total number of nucleons - 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; LOG(FIT) << "Adding target spline " << targstr << " Integral = " << xsec->Integral("width") << std::endl; 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) { ERR(WRN) << "Didn't find target " << targpdg << " in the list of targets recorded by GENIE" << std::endl; ERR(WRN) << " The list of targets you requested is: " << std::endl; for (uint i = 0; i < targprs.size(); ++i) ERR(WRN) << " " << targprs[i] << std::endl; ERR(WRN) << " The list of targets found in GENIE is: " << std::endl; for (std::map::iterator iter = targetsplines.begin(); iter != targetsplines.end(); iter++) ERR(WRN) << " " << iter->first<< std::endl; } } 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()); LOG(FIT) << "Dividing by Total Nucl = " << totalnucl << std::endl; eventhist->Scale(1.0 / double(totalnucl)); eventhist->Write("nuisance_events", TObject::kOverwrite); fluxhist->Write("nuisance_flux", TObject::kOverwrite); LOG(FIT) << "Inclusive XSec Per Nucleon = " << eventhist->Integral("width") * 1E-38 / fluxhist->Integral("width") << std::endl; LOG(FIT) << "XSec Hist Integral = " << totalxsec->Integral() << std::endl; outputfile->Close(); return; }; void PrintOptions() { - std::cout << "PrepareGENIEEvents 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. E.g. for CH2 " "target=1000060120,1000010010,1000010010" << 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; // 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 { ERR(FTL) << "ERROR: unknown command line option given! - '" << argv[i] << " " << argv[i + 1] << "'" << std::endl; PrintOptions(); break; } } } if (gInputFiles == "" && !flagopt) { ERR(FTL) << "No input file(s) specified!" << std::endl; flagopt = true; } if (gFluxFile == "" && !flagopt && !IsMonoE) { ERR(FTL) << "No flux input specified for Prepare Mode" << std::endl; flagopt = true; } if (gTarget == "" && !flagopt) { ERR(FTL) << "No target specified for Prepare Mode" << std::endl; flagopt = true; } if (argc < 1 || flagopt) { PrintOptions(); exit(-1); } return; } diff --git a/app/PrepareNEUT.cxx b/app/PrepareNEUT.cxx index 8a0c67e..d177a46 100644 --- a/app/PrepareNEUT.cxx +++ b/app/PrepareNEUT.cxx @@ -1,422 +1,424 @@ -#include -#include #include "FitLogger.h" #include "PlotUtils.h" #include "StatUtils.h" #include "TFile.h" #include "TH1D.h" #include "TTree.h" +#include +#include // If you don't have NEUT enabled, you shouldn't compile this... #include "neutpart.h" #include "neutvect.h" std::string fInputFiles = ""; std::string fOutputFile = ""; std::string fFluxFile = ""; bool fFluxInGeV = false; bool fIsMonoEFlux = false; double fMonoEEnergy = 0xdeadbeef; void PrintOptions(); -void ParseOptions(int argc, char* argv[]); +void ParseOptions(int argc, char *argv[]); void AddMonoRateHistogram(std::string inputList, double MonoE, std::string output); void CreateRateHistogram(std::string inputList, std::string flux, std::string output); //******************************* -int main(int argc, char* argv[]) { +int main(int argc, char *argv[]) { //******************************* LOG_VERB(FitPar::Config().GetParI("VERBOSITY")); ERR_VERB(FitPar::Config().GetParI("ERROR")); ParseOptions(argc, argv); LOG(FIT) << "Running PrepareNEUT" << std::endl; if (fIsMonoEFlux) { AddMonoRateHistogram(fInputFiles, fMonoEEnergy, fOutputFile); } else { CreateRateHistogram(fInputFiles, fFluxFile, fOutputFile); } }; void AddMonoRateHistogram(std::string inputList, double MonoE, std::string output) { // Need to allow for more than one file... will do soon - TChain* tn = new TChain("neuttree"); + TChain *tn = new TChain("neuttree"); std::vector inputs = GeneralUtils::ParseToStr(inputList, ","); for (std::vector::iterator it = inputs.begin(); it != inputs.end(); ++it) { LOG(FIT) << "Adding " << *it << " to the output" << std::endl; tn->AddFile((*it).c_str()); } if (inputs.size() > 1 && output.empty()) { ERR(FTL) << "You must provide a new output file name if you want to have " "more than 1 input file!" << std::endl; throw; } int nevts = tn->GetEntries(); if (!nevts) { ERR(FTL) << "Either the input file is not from NEUT, or it's empty..." << std::endl; throw; } - NeutVect* fNeutVect = NULL; + NeutVect *fNeutVect = NULL; tn->SetBranchAddress("vectorbranch", &fNeutVect); - TH1D* fluxHist = new TH1D("flux", "flux", 1000, 0, fFluxInGeV ? 10 : 10000); + TH1D *fluxHist = new TH1D("flux", "flux", 1000, 0, fFluxInGeV ? 10 : 10000); fluxHist->Fill(MonoE); fluxHist->Scale(1, "width"); // Make Event Hist - TH1D* xsecHist = (TH1D*)fluxHist->Clone(); + TH1D *xsecHist = (TH1D *)fluxHist->Clone(); xsecHist->Reset(); // Make a total cross section hist for shits and giggles - TH1D* entryHist = (TH1D*)xsecHist->Clone(); + TH1D *entryHist = (TH1D *)xsecHist->Clone(); double MeanE = 0; for (int i = 0; i < nevts; ++i) { tn->GetEntry(i); - NeutPart* part = fNeutVect->PartInfo(0); + NeutPart *part = fNeutVect->PartInfo(0); double E = part->fP.E(); double xsec = fNeutVect->Totcrs; // Unit conversion - if (fFluxInGeV) E *= 1E-3; + if (fFluxInGeV) + E *= 1E-3; xsecHist->Fill(E, xsec); entryHist->Fill(E); MeanE += E; if (i % (nevts / 20) == 0) { LOG(FIT) << "Processed " << i << "/" << nevts << " NEUT events." << std::endl; } } MeanE /= double(nevts); LOG(FIT) << "Processed all events" << std::endl; xsecHist->Divide(entryHist); // This will be the evtrt histogram - TH1D* evtHist = (TH1D*)xsecHist->Clone(); + TH1D *evtHist = (TH1D *)xsecHist->Clone(); evtHist->Multiply(fluxHist); // Check whether the overflow is empty. If not, advise that either the wrong // flux histogram or units were used... // If the events were generated with a limited range of the flux histogram, // this may be benign if (evtHist->Integral(0, -1) != evtHist->Integral() || evtHist->Integral(0, -1) == 0) { - ERR(WRN) << "The input file and flux histogram provided do not match... " - << std::endl; + ERR(WRN) << "The input file(" << evtHist->Integral(0, -1) + << ") and flux histogram provided do not match... " << std::endl; ERR(WRN) << "Are the units correct (MeanE = " << MeanE << ", FluxHistoUpperLim: " << fluxHist->GetXaxis()->GetBinUpEdge(1000) << ")? Did you provide the correct flux file?" << std::endl; ERR(WRN) << "Use output with caution..." << std::endl; } // Pick where the output should go - TFile* outFile = NULL; + TFile *outFile = NULL; if (!output.empty()) { LOG(FIT) << "Saving histograms in " << output << std::endl; outFile = new TFile(output.c_str(), "RECREATE"); } else { LOG(FIT) << "Saving histograms in " << inputs[0] << std::endl; outFile = new TFile(inputs[0].c_str(), "UPDATE"); } outFile->cd(); std::string xsec_name = "xsec_PrepareNeut"; std::string flux_name = "flux_PrepareNeut"; std::string rate_name = "evtrt_PrepareNeut"; if (output.empty()) { // Check whether we should overwrite existing histograms std::string input_xsec = PlotUtils::GetObjectWithName(outFile, "xsec"); std::string input_flux = PlotUtils::GetObjectWithName(outFile, "flux"); std::string input_rate = PlotUtils::GetObjectWithName(outFile, "evtrt"); if (!input_xsec.empty()) { LOG(FIT) << "Updating histogram: " << input_xsec << std::endl; xsec_name = input_xsec; } if (!input_flux.empty()) { LOG(FIT) << "Updating histogram: " << input_flux << std::endl; flux_name = input_flux; } if (!input_rate.empty()) { LOG(FIT) << "Updating histogram: " << input_rate << std::endl; rate_name = input_rate; } } else { LOG(FIT) << "Cloning neuttree into output file." << std::endl; StopTalking(); - TTree* newtree = (TTree*)tn->CloneTree(-1, "fast"); + TTree *newtree = (TTree *)tn->CloneTree(-1, "fast"); StartTalking(); newtree->Write(); } xsecHist->Write(xsec_name.c_str(), TObject::kOverwrite); fluxHist->Write(flux_name.c_str(), TObject::kOverwrite); evtHist->Write(rate_name.c_str(), TObject::kOverwrite); outFile->Close(); } //******************************* void CreateRateHistogram(std::string inputList, std::string flux, std::string output) { //******************************* // Need to allow for more than one file... will do soon - TChain* tn = new TChain("neuttree"); + TChain *tn = new TChain("neuttree"); std::vector inputs = GeneralUtils::ParseToStr(inputList, ","); for (std::vector::iterator it = inputs.begin(); it != inputs.end(); ++it) { LOG(FIT) << "Adding " << *it << " to the output" << std::endl; tn->AddFile((*it).c_str()); } if (inputs.size() > 1 && output.empty()) { ERR(FTL) << "You must provide a new output file name if you want to have " "more than 1 input file!" << std::endl; throw; } int nevts = tn->GetEntries(); if (!nevts) { ERR(FTL) << "Either the input file is not from NEUT, or it's empty..." << std::endl; throw; } - NeutVect* fNeutVect = NULL; + NeutVect *fNeutVect = NULL; tn->SetBranchAddress("vectorbranch", &fNeutVect); // Get Flux Hist std::vector fluxvect = GeneralUtils::ParseToStr(flux, ","); - TH1D* fluxHist = NULL; + TH1D *fluxHist = NULL; if (fluxvect.size() > 1) { - TFile* fluxfile = new TFile(fluxvect[0].c_str(), "READ"); - fluxHist = (TH1D*)fluxfile->Get(fluxvect[1].c_str()); + TFile *fluxfile = new TFile(fluxvect[0].c_str(), "READ"); + fluxHist = (TH1D *)fluxfile->Get(fluxvect[1].c_str()); fluxHist->SetDirectory(0); } else { ERR(FTL) << "NO FLUX SPECIFIED" << std::endl; throw; } // Decide what type of flux was given if (fFluxInGeV) LOG(FIT) << "Assuming flux histogram is in GeV" << std::endl; else LOG(FIT) << "Assuming flux histogram is in MeV" << std::endl; // Make Event Hist - TH1D* xsecHist = (TH1D*)fluxHist->Clone(); + TH1D *xsecHist = (TH1D *)fluxHist->Clone(); xsecHist->Reset(); // Make a total cross section hist for shits and giggles - TH1D* entryHist = (TH1D*)xsecHist->Clone(); + TH1D *entryHist = (TH1D *)xsecHist->Clone(); for (int i = 0; i < nevts; ++i) { tn->GetEntry(i); - NeutPart* part = fNeutVect->PartInfo(0); + NeutPart *part = fNeutVect->PartInfo(0); double E = part->fP.E(); double xsec = fNeutVect->Totcrs; // Unit conversion - if (fFluxInGeV) E *= 1E-3; + if (fFluxInGeV) + E *= 1E-3; xsecHist->Fill(E, xsec); entryHist->Fill(E); if (i % (nevts / 20) == 0) { LOG(FIT) << "Processed " << i << "/" << nevts << " NEUT events." - << std::endl; + << "(Enu = " << E << ", xsec = " << xsec << ") " << std::endl; } } LOG(FIT) << "Processed all events" << std::endl; xsecHist->Divide(entryHist); // This will be the evtrt histogram - TH1D* evtHist = NULL; + TH1D *evtHist = NULL; // If the integral of xsecHist is 0 the input file used a really old version // of NEUT without Totcrs if (!xsecHist->Integral(0, -1)) { ERR(WRN) << "Old NEUT input file: events will not be correctly normalized" << std::endl; - evtHist = (TH1D*)entryHist->Clone(); + evtHist = (TH1D *)entryHist->Clone(); if (evtHist->Integral() != 0) evtHist->Scale(fluxHist->Integral() / float(evtHist->Integral())); } else { - evtHist = (TH1D*)xsecHist->Clone(); + evtHist = (TH1D *)xsecHist->Clone(); evtHist->Multiply(fluxHist); } // Check whether the overflow is empty. If not, advise that either the wrong // flux histogram or units were used... // If the events were generated with a limited range of the flux histogram, // this may be benign if (evtHist->Integral(0, -1) != evtHist->Integral() || evtHist->Integral(0, -1) == 0) { - ERR(WRN) << "The input file and flux histogram provided do not match... " - << std::endl; + ERR(WRN) << "The input file(" << evtHist->Integral(0, -1) + << ") and flux histogram provided do not match... " << std::endl; ERR(WRN) << "Are the units correct? Did you provide the correct flux file?" << std::endl; ERR(WRN) << "Use output with caution..." << std::endl; } // Pick where the output should go - TFile* outFile = NULL; + TFile *outFile = NULL; if (!output.empty()) { LOG(FIT) << "Saving histograms in " << output << std::endl; outFile = new TFile(output.c_str(), "RECREATE"); } else { LOG(FIT) << "Saving histograms in " << inputs[0] << std::endl; outFile = new TFile(inputs[0].c_str(), "UPDATE"); } outFile->cd(); std::string xsec_name = "xsec_PrepareNeut"; std::string flux_name = "flux_PrepareNeut"; std::string rate_name = "evtrt_PrepareNeut"; if (output.empty()) { // Check whether we should overwrite existing histograms std::string input_xsec = PlotUtils::GetObjectWithName(outFile, "xsec"); std::string input_flux = PlotUtils::GetObjectWithName(outFile, "flux"); std::string input_rate = PlotUtils::GetObjectWithName(outFile, "evtrt"); if (!input_xsec.empty()) { LOG(FIT) << "Updating histogram: " << input_xsec << std::endl; xsec_name = input_xsec; } if (!input_flux.empty()) { LOG(FIT) << "Updating histogram: " << input_flux << std::endl; flux_name = input_flux; } if (!input_rate.empty()) { LOG(FIT) << "Updating histogram: " << input_rate << std::endl; rate_name = input_rate; } } else { LOG(FIT) << "Cloning neuttree into output file." << std::endl; StopTalking(); - TTree* newtree = (TTree*)tn->CloneTree(-1, "fast"); + TTree *newtree = (TTree *)tn->CloneTree(-1, "fast"); StartTalking(); newtree->Write(); } xsecHist->Write(xsec_name.c_str(), TObject::kOverwrite); fluxHist->Write(flux_name.c_str(), TObject::kOverwrite); evtHist->Write(rate_name.c_str(), TObject::kOverwrite); outFile->Close(); return; } void PrintOptions() { std::cout << "PrepareNEUT NUISANCE app. " << std::endl << "Produces or recalculates evtrt and flux histograms necessary " "for NUISANCE normalization." << std::endl; std::cout << "PrepareNEUT: " << std::endl; std::cout << " [-h,-help,--h,--help]" << std::endl; std::cout << " -i inputfile1.root,inputfile2.root,inputfile3.root,..." << std::endl; std::cout << " Takes any number of files, but assumes all are " "produced with a single flux" << std::endl; std::cout << " -f flux_root_file.root,flux_hist_name" << std::endl; std::cout << " Path to root file containing the flux histogram used " "when generating the NEUT files" << std::endl; std::cout << " [-o outputfile.root] " << std::endl; std::cout << " If an output file is not given, the input file will be used" << std::endl; std::cout << " If more than one input file is given, an output file " "must be given" << std::endl; std::cout << " [-G]" << std::endl; std::cout << " Flux is assumed to be in MeV. This switch indicates " "the input flux is in GeV" << std::endl; std::cout << " [-m E_nu]" << std::endl; std::cout << " Used to add dummy flux and evt rate histograms to " "mono-energetic vectors. Adheres to the -G flag." << std::endl; } -void ParseOptions(int argc, char* argv[]) { +void ParseOptions(int argc, char *argv[]) { bool flagopt = false; // If No Arguments print commands for (int i = 1; i < argc; ++i) { if (!std::strcmp(argv[i], "-h")) { flagopt = true; break; } else if (!std::strcmp(argv[i], "-G")) { fFluxInGeV = true; continue; } if (i + 1 != argc) { // Cardfile if (!std::strcmp(argv[i], "-h")) { flagopt = true; break; } else if (!std::strcmp(argv[i], "-i")) { fInputFiles = argv[i + 1]; ++i; } else if (!std::strcmp(argv[i], "-o")) { fOutputFile = argv[i + 1]; ++i; } else if (!std::strcmp(argv[i], "-f")) { fFluxFile = argv[i + 1]; ++i; } else if (!std::strcmp(argv[i], "-m")) { fIsMonoEFlux = true; fMonoEEnergy = GeneralUtils::StrToDbl(argv[i + 1]); ++i; } else { ERR(FTL) << "ERROR: unknown command line option given! - '" << argv[i] << " " << argv[i + 1] << "'" << std::endl; PrintOptions(); break; } } } if (fInputFiles == "" && !flagopt) { ERR(FTL) << "No input file(s) specified!" << std::endl; flagopt = true; } if (fFluxFile == "" && (!flagopt) && (!fIsMonoEFlux)) { ERR(FTL) << "No flux input specified!" << std::endl; flagopt = true; } if (argc < 1 || flagopt) { PrintOptions(); exit(-1); } return; } diff --git a/app/nuisbac.cxx b/app/nuisbac.cxx new file mode 100644 index 0000000..0b6df2f --- /dev/null +++ b/app/nuisbac.cxx @@ -0,0 +1,9 @@ +#include "Initialiser.h" + +int main(){ + + for(size_t i = 0; i < 100; ++i){ + nuisance_init(); + } + +} diff --git a/cmake/GENIESetup.cmake b/cmake/GENIESetup.cmake index 7c0b2c5..11c64b3 100644 --- a/cmake/GENIESetup.cmake +++ b/cmake/GENIESetup.cmake @@ -1,157 +1,168 @@ # 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 . ################################################################################ # TODO # check system for libxml2 # check whether we need the includes # check if we can use a subset of the GENIE libraries ################################################################################ # Check Dependencies ################################################################################ ################################# GENIE ###################################### if(GENIE STREQUAL "") cmessage(FATAL_ERROR "Variable GENIE is not defined. " "The location of a pre-built GENIE install must be defined either as" " $ cmake -DGENIE=/path/to/GENIE or as and environment vairable" " $ export GENIE=/path/to/GENIE") endif() if (BUILD_GEVGEN) cmessage(STATUS "Building custom gevgen") LIST(APPEND EXTRA_CXX_FLAGS -D__GEVGEN_ENABLED__) endif() # Extract GENIE VERSION if (GENIE_VERSION STREQUAL "AUTO") execute_process (COMMAND ${CMAKE_SOURCE_DIR}/cmake/getgenieversion.sh ${GENIE} OUTPUT_VARIABLE GENIE_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE) endif() execute_process (COMMAND genie-config --libs OUTPUT_VARIABLE GENIE_LD_FLAGS_STR OUTPUT_STRIP_TRAILING_WHITESPACE) execute_process (COMMAND genie-config --topsrcdir OUTPUT_VARIABLE GENIE_INCLUDES_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) string(REGEX MATCH "-L\([^ ]+\) \(.*\)$" PARSE_GENIE_LIBS_MATCH ${GENIE_LD_FLAGS_STR}) cmessage(DEBUG "genie-config --libs: ${GENIE_LD_FLAGS_STR}") if(NOT PARSE_GENIE_LIBS_MATCH) cmessage(FATAL_ERROR "Expected to be able to parse the result of genie-config --libs to a lib directory and a list of libraries to include, but got: \"${GENIE_LD_FLAGS_STR}\"") endif() set(GENIE_LIB_DIR ${CMAKE_MATCH_1}) set(GENIE_LIBS_RAW ${CMAKE_MATCH_2}) string(REPLACE "-l" "" GENIE_LIBS_STRIPED "${GENIE_LIBS_RAW}") cmessage(STATUS "GENIE version : ${GENIE_VERSION}") cmessage(STATUS "GENIE libdir : ${GENIE_LIB_DIR}") cmessage(STATUS "GENIE libs : ${GENIE_LIBS_STRIPED}") string(REGEX MATCH "ReinSeghal" WASMATCHED ${GENIE_LIBS_STRIPED}) if(WASMATCHED AND GENIE_VERSION STREQUAL "210") set(GENIE_SEHGAL ${GENIE_LIBS_STRIPED}) STRING(REPLACE "ReinSeghal" "ReinSehgal" GENIE_LIBS_STRIPED ${GENIE_SEHGAL}) cmessage(DEBUG "Fixed inconsistency in library naming: ${GENIE_LIBS_STRIPED}") endif() string(REGEX MATCH "ReWeight" WASMATCHED ${GENIE_LIBS_STRIPED}) if(NOT WASMATCHED) set(GENIE_LIBS_STRIPED "GReWeight ${GENIE_LIBS_STRIPED}") cmessage(DEBUG "Force added ReWeight library: ${GENIE_LIBS_STRIPED}") endif() -string(REPLACE " " ";" GENIE_LIBS_LIST "${GENIE_LIBS_STRIPED}") +string(REPLACE " " ";" GENIE_LIBS_LIST "-Wl,--start-group ${GENIE_LIBS_STRIPED} -Wl,--end-group") cmessage(DEBUG "genie-config --libs -- MATCH1: ${CMAKE_MATCH_1}") cmessage(DEBUG "genie-config --libs -- MATCH2: ${CMAKE_MATCH_2}") cmessage(DEBUG "genie-config --libs -- libs stripped: ${GENIE_LIBS_STRIPED}") cmessage(DEBUG "genie-config --libs -- libs list: ${GENIE_LIBS_LIST}") ################################ LHAPDF ###################################### if(LHAPDF_LIB STREQUAL "") cmessage(FATAL_ERROR "Variable LHAPDF_LIB is not defined. The location of a pre-built lhapdf install must be defined either as $ cmake -DLHAPDF_LIB=/path/to/LHAPDF_libraries or as and environment vairable $ export LHAPDF_LIB=/path/to/LHAPDF_libraries") endif() if(LHAPDF_INC STREQUAL "") cmessage(FATAL_ERROR "Variable LHAPDF_INC is not defined. The location of a pre-built lhapdf install must be defined either as $ cmake -DLHAPDF_INC=/path/to/LHAPDF_includes or as and environment vairable $ export LHAPDF_INC=/path/to/LHAPDF_includes") endif() if(LHAPATH STREQUAL "") cmessage(FATAL_ERROR "Variable LHAPATH is not defined. The location of a the LHAPATH directory must be defined either as $ cmake -DLHAPATH=/path/to/LHAPATH or as and environment variable $ export LHAPATH=/path/to/LHAPATH") endif() ################################ LIBXML ###################################### if(LIBXML2_LIB STREQUAL "") cmessage(FATAL_ERROR "Variable LIBXML2_LIB is not defined. The location of a pre-built libxml2 install must be defined either as $ cmake -DLIBXML2_LIB=/path/to/LIBXML2_libraries or as and environment vairable $ export LIBXML2_LIB=/path/to/LIBXML2_libraries") endif() if(LIBXML2_INC STREQUAL "") cmessage(FATAL_ERROR "Variable LIBXML2_INC is not defined. The location of a pre-built libxml2 install must be defined either as $ cmake -DLIBXML2_INC=/path/to/LIBXML2_includes or as and environment vairable $ export LIBXML2_INC=/path/to/LIBXML2_includes") endif() ############################### log4cpp ###################################### if(LOG4CPP_LIB STREQUAL "") - cmessage(FATAL_ERROR "Variable LOG4CPP_LIB is not defined. The location of a pre-built log4cpp install must be defined either as $ cmake -DLOG4CPP_LIB=/path/to/LOG4CPP_libraries or as and environment vairable $ export LOG4CPP_LIB=/path/to/LOG4CPP_libraries") + find_program(LOG4CPPCFG log4cpp-config) + if(NOT LOG4CPPCFG STREQUAL "LOG4CPPCFG-NOTFOUND") + execute_process (COMMAND ${LOG4CPPCFG} + --pkglibdir OUTPUT_VARIABLE LOG4CPP_LIB OUTPUT_STRIP_TRAILING_WHITESPACE) + else() + message(FATAL_ERROR "Variable LOG4CPP_LIB is not defined. The location of a pre-built log4cpp install must be defined either as $ cmake -DLOG4CPP_LIB=/path/to/LOG4CPP_libraries or as and environment vairable $ export LOG4CPP_LIB=/path/to/LOG4CPP_libraries") + endif() endif() if(LOG4CPP_INC STREQUAL "") - cmessage(FATAL_ERROR "Variable LOG4CPP_INC is not defined. The location of a pre-built log4cpp install must be defined either as $ cmake -DGENIE_LOG4CPP_INC=/path/to/LOG4CPP_includes or as and environment vairable $ export LOG4CPP_INC=/path/to/LOG4CPP_includes") + find_program(LOG4CPPCFG log4cpp-config) + if(NOT LOG4CPPCFG STREQUAL "LOG4CPPCFG-NOTFOUND") + execute_process (COMMAND ${LOG4CPPCFG} + --pkgincludedir OUTPUT_VARIABLE LOG4CPP_INC OUTPUT_STRIP_TRAILING_WHITESPACE) + else() + message(FATAL_ERROR "Variable LOG4CPP_INC is not defined. The location of a pre-built log4cpp install must be defined either as $ cmake -DGENIE_LOG4CPP_INC=/path/to/LOG4CPP_includes or as and environment vairable $ export LOG4CPP_INC=/path/to/LOG4CPP_includes") + endif() endif() ################################################################################ LIST(APPEND EXTRA_CXX_FLAGS -D__GENIE_ENABLED__ -D__GENIE_VERSION__=${GENIE_VERSION}) LIST(APPEND RWENGINE_INCLUDE_DIRECTORIES ${GENIE_INCLUDES_DIR} ${GENIE_INCLUDES_DIR}/GHEP ${GENIE_INCLUDES_DIR}/Ntuple ${GENIE_INCLUDES_DIR}/ReWeight ${GENIE_INCLUDES_DIR}/Apps ${GENIE_INCLUDES_DIR}/FluxDrivers ${GENIE_INCLUDES_DIR}/EVGDrivers ${LHAPDF_INC} ${LIBXML2_INC} ${LOG4CPP_INC}) SAYVARS() LIST(APPEND EXTRA_LINK_DIRS ${GENIE_LIB_DIR} ${LHAPDF_LIB} ${LIBXML2_LIB} ${LOG4CPP_LIB}) -#LIST(REVERSE EXTRA_LIBS) -#LIST(REVERSE GENIE_LIBS_LIST) +LIST(APPEND EXTRA_LIBS -Wl,--start-group) LIST(APPEND EXTRA_LIBS ${GENIE_LIBS_LIST}) -#LIST(REVERSE EXTRA_LIBS) +LIST(APPEND EXTRA_LIBS -Wl,--end-group) LIST(APPEND EXTRA_LIBS LHAPDF xml2 log4cpp) if(USE_PYTHIA8) set(NEED_PYTHIA8 TRUE) set(NEED_ROOTPYTHIA8 TRUE) else() set(NEED_PYTHIA6 TRUE) set(NEED_ROOTPYTHIA6 TRUE) endif() set(NEED_ROOTEVEGEN TRUE) SET(USE_GENIE TRUE CACHE BOOL "Whether to enable GENIE (reweight) support. Requires external libraries. " FORCE) diff --git a/cmake/NEUTSetup.cmake b/cmake/NEUTSetup.cmake index 85788d5..c4665af 100644 --- a/cmake/NEUTSetup.cmake +++ b/cmake/NEUTSetup.cmake @@ -1,83 +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 . ################################################################################ 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() -set(NEUT_LIB_DIR ${NEUT_ROOT}/lib/Linux_pc) +if(NOT IS_NEUT_54) + 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__ ) LIST(APPEND RWENGINE_INCLUDE_DIRECTORIES ${NEUT_ROOT}/include ${NEUT_ROOT}/src/neutclass ${NEUT_ROOT}/src/reweight) - LIST(APPEND EXTRA_LINK_DIRS - ${NEUT_ROOT}/lib/Linux_pc + ${NEUT_LIB_DIR} ${CERN}/${CERN_LEVEL}/lib ${NEUT_ROOT}/src/reweight) -LIST(APPEND EXTRA_LIBS - NReWeight - neutcore - nuccorrspl - nuceff - partnuck - skmcsvc - tauola - jetset74 - pdflib804 - mathlib - packlib - pawlib) - -LIST(APPEND EXTRA_SHAREDOBJS +if(NOT IS_NEUT_54) + LIST(APPEND EXTRA_LIBS + NReWeight + neutcore + nuccorrspl + nuceff + partnuck + skmcsvc + tauola + jetset74 + pdflib804 + mathlib + packlib + pawlib) +else() + LIST(APPEND EXTRA_LIBS + NReWeight + 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 + 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 -D__NEUT_NUCFSI_ENABLED__ ) - LIST(APPEND EXTRA_SHAREDOBJS + LIST(APPEND NEUT_ROOT_LIBS ${NEUT_CLASS}/neutnucfsistep.so ${NEUT_CLASS}/neutnucfsivert.so ) endif() -LIST(APPEND EXTRA_SHAREDOBJS - ${NEUT_CLASS}/neutrootTreeSingleton.so +if(NOT IS_NEUT_54) + 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() diff --git a/cmake/ROOTSetup.cmake b/cmake/ROOTSetup.cmake index ebf9dee..f6597a3 100644 --- a/cmake/ROOTSetup.cmake +++ b/cmake/ROOTSetup.cmake @@ -1,162 +1,170 @@ # 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 . ################################################################################ if ( NOT DEFINED ENV{ROOTSYS} ) cmessage (FATAL_ERROR "$ROOTSYS is not defined, please set up ROOT first.") else() cmessage(STATUS "Using ROOT installed at $ENV{ROOTSYS}") set(CMAKE_ROOTSYS $ENV{ROOTSYS}) endif() # Get cflags from ROOT execute_process (COMMAND root-config --cflags OUTPUT_VARIABLE ROOT_CXX_FLAGS_RAW OUTPUT_STRIP_TRAILING_WHITESPACE) string(REPLACE " " ";" ROOT_CXX_FLAGS "${ROOT_CXX_FLAGS_RAW}") # Get libdir from ROOT execute_process (COMMAND root-config --libdir OUTPUT_VARIABLE ROOT_LIBDIR OUTPUT_STRIP_TRAILING_WHITESPACE) # Get version from ROOT execute_process (COMMAND root-config --version OUTPUT_VARIABLE ROOT_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE) # Get features from ROOT execute_process (COMMAND root-config --features OUTPUT_VARIABLE ROOT_FEATURES OUTPUT_STRIP_TRAILING_WHITESPACE) LIST(APPEND EXTRA_LINK_DIRS ${ROOT_LIBDIR}) LIST(APPEND ROOT_LIBS Core Cint RIO XMLIO Net Hist Graf Graf3d Gpad Tree Rint Postscript Matrix Physics MathCore Thread EG Geom GenVector) if(USE_MINIMIZER) if("${ROOT_FEATURES}" MATCHES "minuit2") cmessage(STATUS "ROOT built with MINUIT2 support") LIST(APPEND EXTRA_CXX_FLAGS -D__MINUIT2_ENABLED__) else() cmessage(FATAL_ERROR "ROOT built without MINUIT2 support but minimizer functionality requested. Either configure with -DUSE_MINIMIZER=FALSE or use a version of ROOT with MINUIT2 support.") endif() - string(REGEX MATCH "5.34/([0-9]+)" ROOTVERSMATCH ${ROOT_VERSION}) - if(NOT ROOTVERSMATCH OR ${CMAKE_MATCH_1} LESS "19") - cmessage(FATAL_ERROR "ROOT Version: ${ROOT_VERSION} has out of date minimizer interface, but minimizer functionality requested. Please configure with -DUSE_MINIMIZER=FALSE or update to 5.34/19 or greater to enable minimization features.") + string(REGEX MATCH "6.*" ROOTVERSIXMATCH ${ROOT_VERSION}) + if(ROOTVERSIXMATCH) + cmessage(STATUS "Using ROOT6, We are essentially flying blind here.") + LIST(REMOVE_ITEM ROOT_LIBS Cint) + LIST(APPEND EXTRA_CXX_FLAGS -DROOT6_USE_FIT_FITTER_INTERFACE) + set(USE_ROOT6 True) + else() + string(REGEX MATCH "5.34/([0-9]+)" ROOTVERSMATCH ${ROOT_VERSION}) + if(NOT ROOTVERSMATCH OR ${CMAKE_MATCH_1} LESS "19") + cmessage(FATAL_ERROR "ROOT Version: ${ROOT_VERSION} has out of date minimizer interface, but minimizer functionality requested. Please configure with -DUSE_MINIMIZER=FALSE or update to 5.34/19 or greater to enable minimization features.") + endif() endif() endif() if("${ROOT_FEATURES}" MATCHES "opengl") cmessage(STATUS "ROOT built with OpenGL support") LIST(APPEND ROOT_LIBS RGL) endif() if(DEFINED NEED_ROOTPYTHIA6 AND NEED_ROOTPYTHIA6) LIST(APPEND ROOT_LIBS EGPythia6 Pythia6) endif() cmessage ( STATUS "[ROOT]: root-config --version: ${ROOT_VERSION} ") cmessage ( STATUS "[ROOT]: root-config --cflags : ${ROOT_CXX_FLAGS} ") cmessage ( STATUS "[ROOT]: root-config --libs : ${ROOT_LD_FLAGS} ") LIST(APPEND EXTRA_CXX_FLAGS ${ROOT_CXX_FLAGS}) #Helper functions for building dictionaries function(GenROOTDictionary OutputDictName Header LinkDef) get_directory_property(incdirs INCLUDE_DIRECTORIES) string(REPLACE ";" ";-I" LISTDIRINCLUDES "-I${incdirs}") string(REPLACE " " ";" LISTCPPFLAGS "${EXTRA_CXX_FLAGS}") #ROOT5 CINT cannot handle it. list(REMOVE_ITEM LISTCPPFLAGS "-std=c++11") message(STATUS "LISTCPPFLAGS: ${LISTCPPFLAGS}") message(STATUS "LISTINCLUDES: ${LISTDIRINCLUDES}") #Learn how to generate the Dict.cxx and Dict.hxx add_custom_command( OUTPUT "${OutputDictName}.cxx" "${OutputDictName}.h" COMMAND rootcint ARGS -f ${OutputDictName}.cxx -c -p ${LISTDIRINCLUDES} ${LISTCPPFLAGS} ${Header} ${LinkDef} DEPENDS ${Header};${LinkDef}) endfunction() function(BuildROOTProject ProjectName InputFile CommaSeparatedClassesToDump LIBLINKMODE) string(REPLACE "," ";" HeadersToDump ${CommaSeparatedClassesToDump}) set(OUTPUTFILES ${CMAKE_BINARY_DIR}/${ProjectName}/${ProjectName}ProjectSource.cxx ${CMAKE_BINARY_DIR}/${ProjectName}/${ProjectName}LinkDef.h ${CMAKE_BINARY_DIR}/${ProjectName}/${ProjectName}ProjectHeaders.h ${CMAKE_BINARY_DIR}/${ProjectName}/${ProjectName}ProjectInstances.h) cmessage(STATUS "As part of ROOT project: ${ProjectName}") foreach (header ${HeadersToDump}) LIST(APPEND OUTPUTFILES "${CMAKE_BINARY_DIR}/${ProjectName}/${header}.h") cmessage(STATUS "Will generate: ${CMAKE_BINARY_DIR}/${ProjectName}/${header}.h") endforeach() add_custom_command( OUTPUT ${OUTPUTFILES} COMMAND ${CMAKE_BINARY_DIR}/src/Utils/DumpROOTClassesFromVector ARGS ${InputFile} ${CMAKE_BINARY_DIR}/${ProjectName} ${CommaSeparatedClassesToDump} VERBATIM DEPENDS DumpROOTClassesFromVector) add_custom_target(${ProjectName}_sources DEPENDS ${OUTPUTFILES}) GenROOTDictionary( ${CMAKE_BINARY_DIR}/${ProjectName}/${ProjectName}ProjectDict ${CMAKE_BINARY_DIR}/${ProjectName}/${ProjectName}ProjectHeaders.h ${CMAKE_BINARY_DIR}/${ProjectName}/${ProjectName}LinkDef.h ) add_custom_target(${ProjectName}ProjectDict DEPENDS ${CMAKE_BINARY_DIR}/${ProjectName}/${ProjectName}ProjectDict.cxx ${CMAKE_BINARY_DIR}/${ProjectName}/${ProjectName}ProjectDict.h ) # add_dependencies(${ProjectName}ProjectDict ${ProjectName}_sources) #ProjectSource.cxx includes ProjectDict.cxx, so no need to add to compilation. set(ROAA_SOURCEFILES ${CMAKE_BINARY_DIR}/${ProjectName}/${ProjectName}ProjectSource.cxx) add_library(${ProjectName} ${LIBLINKMODE} ${ROAA_SOURCEFILES}) add_dependencies(${ProjectName} ${ProjectName}ProjectDict) endfunction() diff --git a/cmake/c++CompilerSetup.cmake b/cmake/c++CompilerSetup.cmake index 266b708..bd9adcb 100644 --- a/cmake/c++CompilerSetup.cmake +++ b/cmake/c++CompilerSetup.cmake @@ -1,109 +1,130 @@ # 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 . ################################################################################ if(USE_OMP) LIST(APPEND EXTRA_CXX_FLAGS -fopenmp) endif() if(USE_DYNSAMPLES) LIST(APPEND EXTRA_LIBS dl) LIST(APPEND EXTRA_CXX_FLAGS -D__USE_DYNSAMPLES__) endif() set(CXX_WARNINGS -Wall ) cmessage(DEBUG "EXTRA_CXX_FLAGS: ${EXTRA_CXX_FLAGS}") string(REPLACE ";" " " STR_EXTRA_CXX_FLAGS "${EXTRA_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${STR_EXTRA_CXX_FLAGS} ${CXX_WARNINGS}") set(CMAKE_Fortran_FLAGS_RELEASE "-fPIC") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0") if(USE_DYNSAMPLES) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fPIC") set(CMAKE_Fortran_FLAGS_DEBUG "-fPIC") endif() set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fPIC -O3") if(CMAKE_BUILD_TYPE MATCHES DEBUG) set(CURRENT_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS_DEBUG}) elseif(CMAKE_BUILD_TYPE MATCHES RELEASE) set(CURRENT_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS_RELEASE}) else() cmessage(FATAL_ERROR "[ERROR]: Unknown CMAKE_BUILD_TYPE (\"${CMAKE_BUILD_TYPE}\"): Should be \"DEBUG\" or \"RELEASE\".") endif() SET(STR_EXTRA_LINK_DIRS) if(NOT EXTRA_LINK_DIRS STREQUAL "") string(REPLACE ";" " -L" STR_EXTRA_LINK_DIRS "-L${EXTRA_LINK_DIRS}") endif() + SET(STR_EXTRA_LIBS) if(NOT EXTRA_LIBS STREQUAL "") - string(REPLACE ";" " -l" STR_EXTRA_LIBS "-l${EXTRA_LIBS}") + SET(STR_EXTRA_LIBS_NO_SCRUB_LINKOPTS) + string(REPLACE ";" " -l" STR_EXTRA_LIBS_NO_SCRUB_LINKOPTS "-l${EXTRA_LIBS}") + string(REPLACE "-l-" "-" STR_EXTRA_LIBS ${STR_EXTRA_LIBS_NO_SCRUB_LINKOPTS}) endif() + SET(STR_EXTRA_SHAREDOBJS) if(NOT EXTRA_SHAREDOBJS STREQUAL "") string(REPLACE ";" " " STR_EXTRA_SHAREDOBJS "${EXTRA_SHAREDOBJS}") endif() SET(STR_EXTRA_LINK_FLAGS) if(NOT EXTRA_LINK_FLAGS STREQUAL "") string(REPLACE ";" " " STR_EXTRA_LINK_FLAGS "${EXTRA_LINK_FLAGS}") endif() cmessage(DEBUG "EXTRA_LINK_DIRS: ${STR_EXTRA_LINK_DIRS}") cmessage(DEBUG "EXTRA_LIBS: ${STR_EXTRA_LIBS}") cmessage(DEBUG "EXTRA_SHAREDOBJS: ${STR_EXTRA_SHAREDOBJS}") cmessage(DEBUG "EXTRA_LINK_FLAGS: ${STR_EXTRA_LINK_FLAGS}") if(NOT STR_EXTRA_LINK_DIRS STREQUAL "" AND NOT STR_EXTRA_LIBS STREQUAL "") SET(CMAKE_DEPENDLIB_FLAGS "${STR_EXTRA_LINK_DIRS} ${STR_EXTRA_LIBS}") endif() +if(USE_NEUT) + foreach(OBJ ${NEUT_ROOT_LIBS}) + if(NOT CMAKE_DEPENDLIB_FLAGS STREQUAL "") + SET(CMAKE_DEPENDLIB_FLAGS "${CMAKE_DEPENDLIB_FLAGS} ${OBJ}") + else() + SET(CMAKE_DEPENDLIB_FLAGS "${OBJ}") + endif() + endforeach() + foreach(OBJ ${NEUT_ROOT_LIBS}) + if(NOT CMAKE_DEPENDLIB_FLAGS STREQUAL "") + SET(CMAKE_DEPENDLIB_FLAGS "${CMAKE_DEPENDLIB_FLAGS} ${OBJ}") + else() + SET(CMAKE_DEPENDLIB_FLAGS "${OBJ}") + endif() + endforeach() +endif() + if(NOT EXTRA_SHAREDOBJS STREQUAL "") if(NOT STR_EXTRA_LINK_FLAGS STREQUAL "") SET(STR_EXTRA_LINK_FLAGS "${STR_EXTRA_SHAREDOBJS} ${STR_EXTRA_LINK_FLAGS}") else() SET(STR_EXTRA_LINK_FLAGS "${STR_EXTRA_SHAREDOBJS}") endif() endif() if(NOT EXTRA_LINK_FLAGS STREQUAL "") if(NOT CMAKE_LINK_FLAGS STREQUAL "") SET(CMAKE_LINK_FLAGS "${CMAKE_LINK_FLAGS} ${STR_EXTRA_LINK_FLAGS}") else() SET(CMAKE_LINK_FLAGS "${STR_EXTRA_LINK_FLAGS}") endif() endif() if(USE_OMP) cmessage(FATAL_ERROR "No OMP features currently enabled so this is a FATAL_ERROR to let you know that you don't gain anything with this declaration.") endif() if (VERBOSE) cmessage (STATUS "C++ Compiler : ${CXX_COMPILER_NAME}") cmessage (STATUS " flags : ${CMAKE_CXX_FLAGS}") cmessage (STATUS " Release flags : ${CMAKE_CXX_FLAGS_RELEASE}") cmessage (STATUS " Debug flags : ${CMAKE_CXX_FLAGS_DEBUG}") cmessage (STATUS " Link Flags : ${CMAKE_LINK_FLAGS}") cmessage (STATUS " Lib Flags : ${CMAKE_DEPENDLIB_FLAGS}") endif() diff --git a/cmake/cacheVariables.cmake b/cmake/cacheVariables.cmake index 94d4019..3d52cee 100644 --- a/cmake/cacheVariables.cmake +++ b/cmake/cacheVariables.cmake @@ -1,213 +1,216 @@ # 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 . ################################################################################ function(CheckAndSetDefaultEnv VARNAME DEFAULT CACHETYPE DOCSTRING ENVNAME) #cmessage(DEBUG "Trying to assign variable ${VARNAME} into the cache.") if(NOT DEFINED ${VARNAME}) if(DEFINED ENV{${ENVNAME}} AND NOT $ENV{${ENVNAME}} STREQUAL "") set(${VARNAME} $ENV{${ENVNAME}} CACHE ${CACHETYPE} ${DOCSTRING}) cmessage(DEBUG " Read ${VARNAME} from ENVVAR ${ENVNAME} as $ENV{${ENVNAME}}.") else() set(${VARNAME} ${DEFAULT} CACHE ${CACHETYPE} ${DOCSTRING}) endif() else() set(${VARNAME} ${${VARNAME}} CACHE ${CACHETYPE} ${DOCSTRING}) unset(${VARNAME}) endif() cmessage(CACHE "--Set cache variable: \"${VARNAME}\" to \"${${VARNAME}}\", in cache ${CACHETYPE}.") endfunction() function(CheckAndSetDefaultCache VARNAME DEFAULT CACHETYPE DOCSTRING) # cmessage(DEBUG "Trying to assign variable ${VARNAME} into the cache.") if(NOT DEFINED ${VARNAME}) set(${VARNAME} ${DEFAULT} CACHE ${CACHETYPE} ${DOCSTRING}) else() set(${VARNAME} ${${VARNAME}} CACHE ${CACHETYPE} ${DOCSTRING}) unset(${VARNAME}) endif() cmessage(CACHE "--Set cache variable: \"${VARNAME}\" to \"${${VARNAME}}\", in cache ${CACHETYPE}.") endfunction() function(CheckAndSetDefault VARNAME DEFAULT) # cmessage(DEBUG "Trying to assign variable ${VARNAME}.") if(NOT DEFINED ${VARNAME}) set(${VARNAME} ${DEFAULT} PARENT_SCOPE) set(${VARNAME} ${DEFAULT}) endif() cmessage(CACHE "--Set variable: \"${VARNAME}\" to \"${${VARNAME}}\".") endfunction() CheckAndSetDefaultCache(VERBOSE TRUE BOOL "Whether to configure loudly.") set (CMAKE_SKIP_BUILD_RPATH TRUE) #Changes default install path to be a subdirectory of the build dir. #Can set build dir at configure time with -DCMAKE_INSTALL_PREFIX=/install/path if(CMAKE_INSTALL_PREFIX STREQUAL "" OR CMAKE_INSTALL_PREFIX STREQUAL "/usr/local") set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/${CMAKE_SYSTEM_NAME}") elseif(NOT DEFINED CMAKE_INSTALL_PREFIX) set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/${CMAKE_SYSTEM_NAME}") endif() if(CMAKE_BUILD_TYPE STREQUAL "") set(CMAKE_BUILD_TYPE DEBUG) elseif(NOT DEFINED CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE DEBUG) endif() CheckAndSetDefaultCache(EXTRA_SETUP_SCRIPT "" PATH "The path to an extra script to inject into the NUISANCE setup script. <>") CheckAndSetDefaultCache(USE_MINIMIZER TRUE INTERNAL "Whether we are using the ROOT minimization libraries. ") +CheckAndSetDefaultCache(USE_ROOT6 FALSE INTERNAL "Whether we are using the ROOT 6. ") + CheckAndSetDefaultCache(USE_HEPMC FALSE BOOL "Whether to enable HepMC input support. ") CheckAndSetDefaultEnv(HEPMC "" PATH "Path to HepMC source tree root directory. Overrides environment variable \$HEPMC <>" HEPMC) CheckAndSetDefaultCache(HEPMC_MOMUNIT "GEV" STRING "HepMC momentum units [MEV|GEV]. ") CheckAndSetDefaultCache(HEPMC_LENUNIT "CM" STRING "HepMC momentum units [MM|CM]. ") CheckAndSetDefaultCache(HEPMC_USED_EP FALSE INTERNAL "Whether we built HepMC or not. ") CheckAndSetDefaultCache(USE_NEUT FALSE BOOL "Whether to enable NEUT (reweight) support. Requires external libraries. ") +CheckAndSetDefaultCache(IS_NEUT_54 FALSE BOOL "Whether to enabled NEUT is version 5.4 or greater. ") CheckAndSetDefaultEnv(NEUT_ROOT "" PATH "Path to NEUT source tree root directory. Overrides environment variable \$NEUT_ROOT <>" NEUT_ROOT) CheckAndSetDefaultEnv(CERN "" PATH "Path to CERNLIB source tree root directory that NEUT was built against. Overrides environment variable \$CERN <>" CERN) CheckAndSetDefaultEnv(CERN_LEVEL "" STRING "CERNLIB Library version. Overrides environment variable \$CERN_LEVEL <>" CERN_LEVEL) CheckAndSetDefaultCache(USE_NuWro FALSE BOOL "Whether to enable NuWro support. ") CheckAndSetDefaultEnv(NUWRO "" PATH "Path to NuWro source tree root directory. Overrides environment variable \$NUWRO <>" NUWRO) CheckAndSetDefaultEnv(NUWRO_INC "" PATH "Path to NuWro installed includes directory, needs to contain \"params_all.h\". Overrides environment variable \$NUWRO_INC <>" NUWRO_INC) CheckAndSetDefaultCache(NUWRO_INPUT_FILE "" FILEPATH "Path to an input NuWro event vector, which can be used to build NuWro i/o libraries. <>") CheckAndSetDefaultCache(NUWRO_BUILT_FROM_FILE FALSE INTERNAL "Whether the NuWro libraries were built by NUISANCE. ") CheckAndSetDefaultCache(USE_NuWro_RW FALSE BOOL "Whether to try and build support for NuWro reweighting. ") CheckAndSetDefaultCache(USE_NuWro_SRW_Event FALSE BOOL "Whether to use cut down NuWro reweight event format. Requires NuWro reweight. ") CheckAndSetDefaultCache(USE_GENIE FALSE BOOL "Whether to enable GENIE (reweight) support. Requires external libraries. ") CheckAndSetDefaultCache(GENIE_VERSION "AUTO" STRING "GENIE Version ") CheckAndSetDefaultEnv(GENIE "" PATH "Path to GENIE source tree root directory. Overrides environment variable \$GENIE <>" GENIE) CheckAndSetDefaultEnv(LHAPDF_LIB "" PATH "Path to pre-built LHAPDF libraries. Overrides environment variable \$LHAPDF_LIB. <>" LHAPDF_LIB) CheckAndSetDefaultEnv(LHAPDF_INC "" PATH "Path to installed LHAPDF headers. Overrides environment variable \$LHAPDF_INC. <>" LHAPDF_INC) CheckAndSetDefaultEnv(LHAPATH "" PATH "Path to LHA PDF inputs. Overrides environment variable \$LHAPATH. <>" LHAPATH) CheckAndSetDefaultEnv(LIBXML2_LIB "" PATH "Path to pre-built LIBXML2 libraries. Overrides environment variable \$LIBXML2_LIB. <>" LIBXML2_LIB) CheckAndSetDefaultEnv(LIBXML2_INC "" PATH "Path to installed LIBXML2 headers. Overrides environment variable \$LIBXML2_INC. <>" LIBXML2_INC) CheckAndSetDefaultEnv(LOG4CPP_LIB "" PATH "Path to pre-built LOG4CPP libraries. Overrides environment variable \$LOG4CPP_LIB. <>" LOG4CPP_LIB) CheckAndSetDefaultEnv(LOG4CPP_INC "" PATH "Path to installed LOG4CPP headers. Overrides environment variable \$LOG4CPP_INC. <>" LOG4CPP_INC) CheckAndSetDefaultCache(BUILD_GEVGEN FALSE BOOL "Whether to build nuisance_gevgen app.") CheckAndSetDefaultCache(USE_T2K FALSE BOOL "Whether to enable T2KReWeight support. Requires external libraries. ") CheckAndSetDefaultEnv(T2KREWEIGHT "" PATH "Path to installed T2KREWEIGHTReWeight. Overrides environment variable \$T2KREWEIGHT. <>" T2KREWEIGHT) CheckAndSetDefaultCache(USE_NIWG FALSE BOOL "Whether to enable (T2K) NIWG ReWeight support. Requires external libraries. ") CheckAndSetDefaultEnv(NIWG_ROOT "" PATH "Path to installed NIWGReWeight. Overrides environment variable \$NIWG. <>" NIWG) CheckAndSetDefaultCache(USE_MINERvA_RW FALSE BOOL "Whether to enable MINERvA ReWeight support. ") CheckAndSetDefaultEnv(PYTHIA6 "" PATH "Path to directory containing libPythia6.so. Overrides environment variable \$PYTHIA6 <>" PYTHIA6) CheckAndSetDefaultEnv(PYTHIA8 "" PATH "Path to directory containing libPythia8.so. Overrides environment variable \$PYTHIA8 <>" PYTHIA8) CheckAndSetDefaultCache(USE_PYTHIA8 FALSE BOOL "Whether to enable PYTHIA8 event support. ") CheckAndSetDefaultCache(USE_GiBUU TRUE BOOL "Whether to enable GiBUU event support. ") CheckAndSetDefaultCache(BUILD_GiBUU FALSE BOOL "Whether to build supporting GiBUU event tools along with a patched version of GiBUU. ") CheckAndSetDefaultCache(USE_NUANCE TRUE BOOL "Whether to enable NUANCE event support. ") CheckAndSetDefaultCache(USE_PROB3PP FALSE BOOL "Whether to download and compile in Prob3++ support. ") -CheckAndSetDefaultCache(NO_EXTERNAL_UPDATE TRUE BOOL "Whether to perform the update target for external dependencies. ") +CheckAndSetDefaultCache(NO_EXTERNAL_UPDATE FALSE BOOL "Whether to perform the update target for external dependencies. Note this may produce errors for CMake < 3.8 where a bug was fixed for the feature that this option invokes. ") -CheckAndSetDefaultCache(USE_GPERFTOOLS FALSE BOOL "Whether to compile in google performance tools. ") +CheckAndSetDefaultCache(USE_GPERFTOOLS FALSE BOOL "Whether to compile in google performance tools. ") CheckAndSetDefault(NEED_PYTHIA6 FALSE) CheckAndSetDefault(NEED_PYTHIA8 FALSE) CheckAndSetDefault(NEED_ROOTEVEGEN FALSE) CheckAndSetDefault(NEED_ROOTPYTHIA6 FALSE) CheckAndSetDefaultCache(USE_OMP FALSE BOOL "Whether to enable multicore features (there currently are none...). ") -CheckAndSetDefaultCache(USE_DYNSAMPLES FALSE BOOL "Whether to enable the dynamic sample loader. ") +CheckAndSetDefaultCache(USE_DYNSAMPLES TRUE BOOL "Whether to enable the dynamic sample loader. ") CheckAndSetDefault(NO_EXPERIMENTS FALSE) cmessage(STATUS "NO_EXPERIMENTS: ${NO_EXPERIMENTS}") CheckAndSetDefaultCache(NO_ANL ${NO_EXPERIMENTS} BOOL "Whether to *NOT* build ANL samples. <-DNO_EXPERIMENTS=FALSE>") CheckAndSetDefaultCache(NO_ArgoNeuT ${NO_EXPERIMENTS} BOOL "Whether to *NOT* build ArgoNeuT samples. <-DNO_EXPERIMENTS=FALSE>") CheckAndSetDefaultCache(NO_BEBC ${NO_EXPERIMENTS} BOOL "Whether to *NOT* build BEBC samples. <-DNO_EXPERIMENTS=FALSE>") CheckAndSetDefaultCache(NO_BNL ${NO_EXPERIMENTS} BOOL "Whether to *NOT* build BNL samples. <-DNO_EXPERIMENTS=FALSE>") CheckAndSetDefaultCache(NO_FNAL ${NO_EXPERIMENTS} BOOL "Whether to *NOT* build FNAL samples. <-DNO_EXPERIMENTS=FALSE>") CheckAndSetDefaultCache(NO_GGM ${NO_EXPERIMENTS} BOOL "Whether to *NOT* build GGM samples. <-DNO_EXPERIMENTS=FALSE>") CheckAndSetDefaultCache(NO_K2K ${NO_EXPERIMENTS} BOOL "Whether to *NOT* build K2K samples. <-DNO_EXPERIMENTS=FALSE>") CheckAndSetDefaultCache(NO_MINERvA ${NO_EXPERIMENTS} BOOL "Whether to *NOT* build MINERvA samples. <-DNO_EXPERIMENTS=FALSE>") CheckAndSetDefaultCache(NO_MiniBooNE ${NO_EXPERIMENTS} BOOL "Whether to *NOT* build MiniBooNE samples. <-DNO_EXPERIMENTS=FALSE>") CheckAndSetDefaultCache(NO_T2K ${NO_EXPERIMENTS} BOOL "Whether to *NOT* build T2K samples. <-DNO_EXPERIMENTS=FALSE>") CheckAndSetDefaultCache(NO_SciBooNE ${NO_EXPERIMENTS} BOOL "Whether to *NOT* build SciBooNE samples. <-DNO_EXPERIMENTS=FALSE>") function(SAYVARS) LIST(APPEND VARS USE_HEPMC HEPMC HEPMC_MOMUNIT HEPMC_LENUNIT HEPMC_USED_EP USE_NEUT NEUT_ROOT CERN CERN_LEVEL USE_NuWro NUWRO NUWRO_INC NUWRO_INPUT_FILE NUWRO_BUILT_FROM_FILE USE_GENIE GENIE LHAPDF_LIB LHAPDF_INC LIBXML2_LIB LIBXML2_INC LOG4CPP_LIB GENIE_LOG4CPP_INC BUILD_GEVGEN USE_T2K USE_NIWG USE_GiBUU BUILD_GiBUU USE_NUANCE NO_EXTERNAL_UPDATE USE_GPERFTOOLS NO_ANL NO_ArgoNeuT NO_BEBC NO_BNL NO_FNAL NO_GGM NO_K2K NO_MINERvA NO_MiniBooNE NO_T2K NO_SciBooNE) foreach(v ${VARS}) if(DEFINED ${v}) cmessage(DEBUG "VARIABLE: \"${v}\" = \"${${v}}\"") endif() endforeach(v) endfunction() diff --git a/cmake/setup.sh.in b/cmake/setup.sh.in index 2fbbe90..123aaef 100644 --- a/cmake/setup.sh.in +++ b/cmake/setup.sh.in @@ -1,155 +1,155 @@ # 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 . ################################################################################ #!/bin/sh ### Adapted from https://unix.stackexchange.com/questions/4965/keep-duplicates-out-of-path-on-source function add_to_PATH () { for d; do d=$(cd -- "$d" && { pwd -P || pwd; }) 2>/dev/null # canonicalize symbolic links if [ -z "$d" ]; then continue; fi # skip nonexistent directory if [ "$d" == "/usr/bin" ] || [ "$d" == "/usr/bin64" ] || [ "$d" == "/usr/local/bin" ] || [ "$d" == "/usr/local/bin64" ]; then case ":$PATH:" in *":$d:"*) :;; *) export PATH=$PATH:$d;; esac else case ":$PATH:" in *":$d:"*) :;; *) export PATH=$d:$PATH;; esac fi done } function add_to_LD_LIBRARY_PATH () { for d; do d=$(cd -- "$d" && { pwd -P || pwd; }) 2>/dev/null # canonicalize symbolic links if [ -z "$d" ]; then continue; fi # skip nonexistent directory if [ "$d" == "/usr/lib" ] || [ "$d" == "/usr/lib64" ] || [ "$d" == "/usr/local/lib" ] || [ "$d" == "/usr/local/lib64" ]; then case ":$LD_LIBRARY_PATH:" in *":$d:"*) :;; *) export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$d;; esac else case ":$LD_LIBRARY_PATH:" in *":$d:"*) :;; *) export LD_LIBRARY_PATH=$d:$LD_LIBRARY_PATH;; esac fi done } if [ "@EXTRA_SETUP_SCRIPT@" ]; then if [ ! -e @EXTRA_SETUP_SCRIPT@ ]; then echo "[WARN]: Extra setup script \"@EXTRA_SETUP_SCRIPT@\" requested, but could not be found. Skipping..." else echo "[INFO]: Sourcing extra setup from \"@EXTRA_SETUP_SCRIPT@\"." . @EXTRA_SETUP_SCRIPT@ fi fi add_to_PATH "@CMAKE_INSTALL_PREFIX@/bin" add_to_LD_LIBRARY_PATH "@CMAKE_INSTALL_PREFIX@/lib" if [ ! "${ROOTSYS}" ]; then echo "[INFO]: Sourcing ROOT from: @CMAKE_ROOTSYS@" source "@CMAKE_ROOTSYS@/bin/thisroot.sh" fi if [ "@USE_T2K@" != "FALSE" ]; then echo "[INFO]: Adding T2K paths to the environment." export T2KREWEIGHT=@T2KREWEIGHT@ add_to_LD_LIBRARY_PATH "@T2KREWEIGHT@/lib" fi if [ "@USE_NIWG@" != "FALSE" ]; then echo "[INFO]: Adding NIWG paths to the environment." export NIWG=@NIWG_ROOT@ export NIWGREWEIGHT_INPUTS=@NIWG_ROOT@/inputs add_to_LD_LIBRARY_PATH "@NIWG_ROOT@" fi if [ "@USE_NEUT@" != "FALSE" ]; then echo "[INFO]: Adding NEUT library paths to the environment." export NEUT_ROOT=@NEUT_ROOT@ export CERN=@CERN@ export CERN_LEVEL=@CERN_LEVEL@ - add_to_LD_LIBRARY_PATH "${NEUT_ROOT}/lib/Linux_pc" "${NEUT_ROOT}/src/reweight" + add_to_LD_LIBRARY_PATH "${NEUT_LIB_DIR}" "${NEUT_ROOT}/src/reweight" fi if [ "@USE_NuWro@" != "FALSE" ]; then if [ "@NUWRO_BUILT_FROM_FILE@" == "FALSE" ]; then echo "[INFO]: Adding NuWro library paths to the environment." export NUWRO="@NUWRO@" add_to_PATH "@NUWRO@/bin" add_to_LD_LIBRARY_PATH "@NUWRO@/build/@CMAKE_SYSTEM_NAME@/lib" if [ "@NUWRO_INC@" ]; then export NUWRO_INC=@NUWRO_INC@ fi else echo "[INFO]: NuWro support included from input event file." fi fi if [ "@NEED_PYTHIA6@" != "FALSE" ]; then echo "[INFO]: Adding PYTHIA6 library paths to the environment." export PYTHIA6="@PYTHIA6@" add_to_LD_LIBRARY_PATH "@PYTHIA6@" fi if [ "@USE_GENIE@" != "FALSE" ]; then echo "[INFO]: Adding GENIE paths to the environment." export GENIE="@GENIE@" export LHAPDF_LIB="@LHAPDF_LIB@" export LHAPDF_INC="@LHAPDF_INC@" export LIBXML2_LIB="@LIBXML2_LIB@" export LIBXML2_INC="@LIBXML2_INC@" export LOG4CPP_LIB="@LOG4CPP_LIB@" export LOG4CPP_INC="@LOG4CPP_INC@" if [ "@LHAPATH@" ]; then export LHAPATH="@LHAPATH@" fi add_to_PATH "@GENIE@/bin" add_to_LD_LIBRARY_PATH "@GENIE@/lib" "@LHAPDF_LIB@" "@LIBXML2_LIB@" "@LOG4CPP_LIB@" fi if [ "@BUILD_GiBUU@" != "FALSE" ]; then echo "[INFO]: Sourcing GiBUU tools." source @CMAKE_BINARY_DIR@/GiBUUTools/src/GiBUUTools-build/Linux/setup.sh fi export NUISANCE="@CMAKE_SOURCE_DIR@" diff --git a/parameters/dial_conversion.card b/parameters/dial_conversion.card index b34a7d9..0227a07 100644 --- a/parameters/dial_conversion.card +++ b/parameters/dial_conversion.card @@ -1,23 +1,38 @@ # par Name Units Nominal FracErr ConvFunc neut_parameter MaCCQE GeV 1.21*(1.0+x*0.16) +neut_parameter MaNFFRES GeV 0.95*(1.0+x*0.157894737) +neut_parameter CA5RES x 1.01*(1.0+x*0.247524752) +neut_parameter BgSclRES x 1.30*(1.0+x*0.153846154) + +neut_parameter FrAbs_pi x 1.1*(1.0+x*0.5) +neut_parameter FrInelLow_pi x 1*(1.0+x*0.5) +neut_parameter FrInelHigh_pi x 1.8*(1.0+x*0.3) +neut_parameter FrPiProd_pi x 1*(1.0+x*0.5) +neut_parameter FrCExLow_pi x 1*(1.0+x*0.5) +neut_parameter FrCExHigh_pi x 1.8*(1.0+x*0.3) + niwg_parameter NIWGMEC_Norm_C12 % 100.0*(1.0+x) niwg_parameter VecFFCCQE MDLQE x niwg_parameter CCQEFermiSurfMom MeV 217*(1.0+x*0.15) - t2k_parameter NIWG2014a_pF_C12 MeV 217*(1.0+x*0.073733) t2k_parameter NIWG2014a_pF_O16 MeV 225*(1.0+x*0.071111) t2k_parameter NIWGMEC_PDDWeight_C12 x 0.5*(1.0+x*1.0) t2k_parameter NIWGMEC_PDDWeight_O16 x 0.5*(1.0+x*1.0) t2k_parameter NXSec_MaCCQE GeV 1.21*(1.0+x*0.165289256) t2k_parameter NXSec_MaNFFRES GeV 0.95*(1.0+x*0.157894737) t2k_parameter NXSec_CA5RES x 1.01*(1.0+x*0.247524752) t2k_parameter NXSec_BgSclCCRES x 1.30*(1.0+x*0.153846154) t2k_parameter NIWG_Effective_rpaCCQE_A x 1.0*(1.0 + x*0.1) t2k_parameter NIWG_Effective_rpaCCQE_B x 1.0*(1.0 + x*0.1) t2k_parameter NIWG_Effective_rpaCCQE_C x 1.0*(1.0 + x*0.1) t2k_parameter NIWG_Effective_rpaCCQE_D x 1.0*(1.0 + x*0.1) t2k_parameter NIWG_Effective_rpaCCQE_U x 1.0*(1.0 + x*0.1) + +nuwro_parameter kNuwro_Ma_CCQE MeV 1200*(1.0+x*0.160) +nuwro_parameter kNuwro_MaRES GeV 0.940*(1.0+x*0.1) +nuwro_parameter kNuwro_CA5 x 1.19*(1.0+x*0.1) +nuwro_parameter kNuwro_SPPBkgScale x 1.0*(1.0+x*0.26) diff --git a/scripts/nuissamples b/scripts/nuissamples index 7721fe5..22d72ce 100755 --- a/scripts/nuissamples +++ b/scripts/nuissamples @@ -1,19 +1,27 @@ -#!/bin/sh +#!/bin/bash + +if [[ -z ${NUISANCE} ]]; then + echo "NUISANCE environment variable is not set" + echo "Getting the sample list depends on this" + echo "Please do:" + echo "export NUISANCE=YOUR_INSTALL && ./nuissamples" + exit +fi for line in $(grep compare $NUISANCE/src/FCN/SampleList.cxx); do - if [[ $line != *"compare"* ]]; then + if [[ "${line}" != *"compare"* ]]; then continue fi line=${line//\!name\.compare\(/} line=${line//\(/} line=${line//\)/} line=${line//\"/} line=${line//\{} if [[ $line != *"$1"* ]]; then continue fi echo ${2}${line}${3} done diff --git a/src/Electron/CLAS6-EG2_Accepter.cxx b/src/Electron/CLAS6-EG2_Accepter.cxx index d2c4307..5f766c9 100644 --- a/src/Electron/CLAS6-EG2_Accepter.cxx +++ b/src/Electron/CLAS6-EG2_Accepter.cxx @@ -1,177 +1,258 @@ #include "ISmearcepter.h" #include "TH3D.h" #include "TRandom3.h" #include -#define DEBUG_CLASACCEPT +// #define DEBUG_CLASACCEPT 1 + +struct EffMap { + TH3D *Generated; + TH3D *Accepted; + + void Build(TFile *inpF, std::string const &GenName, + std::string const &AccName) { + Generated = dynamic_cast(inpF->Get(GenName.c_str())); + Accepted = dynamic_cast(inpF->Get(AccName.c_str())); + + if (!Generated) { + std::cout << "[ERROR]: Could not retrieve \"accepted\" histogram: \"" + << AccName << "\" from file: \"" << inpF->GetName() << "\"." + << std::endl; + exit(1); + } + if (!Accepted) { + std::cout << "[ERROR]: Could not retrieve \"generated\" histogram: \"" + << GenName << "\" from file: \"" << inpF->GetName() << "\"." + << std::endl; + exit(1); + } + + Generated = static_cast(Generated->Clone()); + Generated->SetDirectory(NULL); + Accepted = static_cast(Accepted->Clone()); + Accepted->SetDirectory(NULL); + } + + double GetAccRatio(double p_GeV, double costheta, double phi_deg, + double defaultAccRatio = 0) const { + // For a bin in phase space defined by p, cost, phi: + // Find number of generated events + Int_t pbin = Generated->GetXaxis()->FindBin(p_GeV); + + Int_t tbin = Generated->GetYaxis()->FindBin(costheta); + Int_t phibin = Generated->GetZaxis()->FindBin(phi_deg); + + if (((pbin == 0) || (pbin == (Generated->GetXaxis()->GetNbins() + 1))) || + ((tbin == 0) || (tbin == (Generated->GetYaxis()->GetNbins() + 1))) || + ((phibin == 0) || + (phibin == (Generated->GetZaxis()->GetNbins() + 1)))) { + return 0; + } + + double num_gen = Generated->GetBinContent(pbin, tbin, phibin); + if (num_gen == 0) { + return defaultAccRatio; + } + // Find number of accepted events + pbin = Accepted->GetXaxis()->FindBin(p_GeV); + tbin = Accepted->GetYaxis()->FindBin(costheta); + phibin = Accepted->GetZaxis()->FindBin(phi_deg); + double num_acc = Accepted->GetBinContent(pbin, tbin, phibin); + double acc_ratio = double(num_acc) / double(num_gen); + + if (((pbin == 0) || (pbin == (Accepted->GetXaxis()->GetNbins() + 1))) || + ((tbin == 0) || (tbin == (Accepted->GetYaxis()->GetNbins() + 1))) || + ((phibin == 0) || (phibin == (Accepted->GetZaxis()->GetNbins() + 1)))) { + return 0; + } + + if ((acc_ratio != 0 && !std::isnormal(acc_ratio)) || (acc_ratio > 1)) { + std::cout << "[BINS]: p " << Generated->GetXaxis()->GetBinLowEdge(1) + << " -- " + << Generated->GetXaxis()->GetBinUpEdge( + Generated->GetXaxis()->GetNbins()) + << ", cost " << Generated->GetYaxis()->GetBinLowEdge(1) + << " -- " + << Generated->GetYaxis()->GetBinUpEdge( + Generated->GetYaxis()->GetNbins()) + << ", phi " << Generated->GetZaxis()->GetBinLowEdge(1) << " -- " + << Generated->GetZaxis()->GetBinUpEdge( + Generated->GetZaxis()->GetNbins()) + << ". " << std::endl + << "[ERROR]: Bad acceptance ratio: " << acc_ratio << " = " + << num_acc << " / " << num_gen << ". (" << p_GeV << ", " + << costheta << ", " << phi_deg << ")." << std::endl; + exit(1); + } + return acc_ratio; + } +}; class CLASAccepter : public ISmearcepter { TRandom3 rand; // Maps a particle PDG to the relevant generated and accepted histograms from // the input map. - std::map > Acceptance; + std::map Acceptance; + double DefaultAccRatio; - public: - CLASAccepter() { ElementName = "CLASAccepter"; } +public: + CLASAccepter() : DefaultAccRatio(0) { ElementName = "CLASAccepter"; } void SpecifcSetup(nuiskey &nk) { rand.~TRandom3(); new (&rand) TRandom3(); InstanceName = nk.GetS("name"); + DefaultAccRatio = nk.GetD("DefaultAccRatio"); std::string const &mapfile = nk.GetS("map"); if (!mapfile.length()) { std::cout << "[ERROR]: No input file specified by \"map\" attribute." << std::endl; exit(1); } TFile *f = new TFile(mapfile.c_str()); if (!f || !f->IsOpen()) { std::cout << "[ERROR]: Could not open root file specified by \"map\" " "attribute: \"" << mapfile << "\"" << std::endl; exit(1); } std::vector accepts = nk.GetListOfChildNodes("accept"); for (auto &acc : accepts) { std::string const &genStr = acc.GetS("generated"); std::string const &accStr = acc.GetS("accepted"); if (!genStr.length() || !accStr.length()) { std::cout << "[ERROR]: expected accept node to contain both " "\"generated\" and \"accepted\" attributes." << std::endl; exit(1); } std::string const &pdgs_s = acc.GetS("PDG"); std::vector pdgs_i = GeneralUtils::ParseToInt(pdgs_s, ","); if (!pdgs_i.size()) { std::cout << "[ERROR]: Could not find any applicable particle PDG codes." << std::endl; exit(1); } - std::pair genacc; + EffMap ef; - genacc.first = dynamic_cast(f->Get(accStr.c_str())); - genacc.second = dynamic_cast(f->Get(genStr.c_str())); - - if (!genacc.first) { - std::cout << "[ERROR]: Could not retrieve \"accepted\" histogram: \"" - << accStr << "\" from file: \"" << mapfile << "\"." - << std::endl; - exit(1); - } - if (!genacc.second) { - std::cout << "[ERROR]: Could not retrieve \"accepted\" histogram: \"" - << genStr << "\" from file: \"" << mapfile << "\"." - << std::endl; - exit(1); - } - - genacc.first = static_cast(genacc.first->Clone()); - genacc.first->SetDirectory(NULL); - genacc.second = static_cast(genacc.second->Clone()); - genacc.second->SetDirectory(NULL); + ef.Build(f, genStr, accStr); for (size_t pdg_it = 0; pdg_it < pdgs_i.size(); ++pdg_it) { if (Acceptance.count(pdgs_i[pdg_it])) { std::cout << "[WARN]: Acceptance map already contains acceptance for PDG: " << pdgs_i[pdg_it] << ". Overwriting..." << std::endl; } - Acceptance[pdgs_i[pdg_it]] = genacc; + Acceptance[pdgs_i[pdg_it]] = ef; } } std::cout << "Loaded " << Acceptance.size() << " particle acceptance definitions." << std::endl; f->Close(); delete f; } RecoInfo *Smearcept(FitEvent *fe) { RecoInfo *ri = new RecoInfo(); for (size_t p_it = 0; p_it < fe->NParticles(); ++p_it) { FitParticle *fp = fe->GetParticle(p_it); int PDG = fp->PDG(); - double p = fp->P3().Mag(); + double p = fp->P3().Mag() * 1E-3; double cost = fp->P3().CosTheta(); - double phi = fp->P3().Phi(); + double phi = fp->P3().Phi() * (180.0 / TMath::Pi()) + 150.0; -#ifdef DEBUG_CLASACCEPT +#if DEBUG_CLASACCEPT > 1 std::cout << std::endl; std::cout << "[" << p_it << "]: " << PDG << ", " << fp->Status() << ", " << fp->E() << " -- KE:" << fp->KE() << " Mom: " << p << std::flush; #endif if (fp->Status() != kFinalState) { -#ifdef DEBUG_CLASACCEPT +#if DEBUG_CLASACCEPT > 1 std::cout << " -- Not final state." << std::flush; #endif continue; } if (!Acceptance.count(PDG)) { -#ifdef DEBUG_CLASACCEPT +#if DEBUG_CLASACCEPT > 1 std::cout << " -- Unknown acceptance." << std::flush; #endif continue; } - std::pair acc = Acceptance[PDG]; - - // For a bin in phase space defined by p, cost, phi: - // Find number of generated events - Int_t pbin = acc.second->GetXaxis()->FindBin(p); - Int_t tbin = acc.second->GetYaxis()->FindBin(cost); - Int_t phibin = acc.second->GetZaxis()->FindBin(phi); - double num_gen = acc.second->GetBinContent(pbin, tbin, phibin); - // Find number of accepted events - pbin = acc.first->GetXaxis()->FindBin(p); - tbin = acc.first->GetYaxis()->FindBin(cost); - phibin = acc.first->GetZaxis()->FindBin(phi); - double num_acc = acc.first->GetBinContent(pbin, tbin, phibin); - double acc_ratio = double(num_acc) / double(num_gen); + EffMap const &eff = Acceptance[PDG]; + + double acc_ratio = eff.GetAccRatio(p, cost, phi, DefaultAccRatio); bool accepted = (rand.Uniform() < acc_ratio); if (accepted) { #ifdef DEBUG_CLASACCEPT + std::cout << "(" << p << ", " << cost << ", " << phi << ")." + << std::endl; std::cout << " -- Reconstructed with probability: " << acc_ratio << std::flush; #endif ri->RecObjMom.push_back(fp->P3()); ri->RecObjClass.push_back(fp->PDG()); continue; } #ifdef DEBUG_CLASACCEPT + std::cout << "(" << p << ", " << cost << ", " << phi << ")." << std::endl; std::cout << " -- Rejected with probability: " << acc_ratio << std::flush; #endif -#ifdef DEBUG_CLASACCEPT - std::cout << std::endl; -#endif } #ifdef DEBUG_CLASACCEPT - std::cout << "Reconstructed " << ri->RecObjMom.size() << " particles. " - << std::endl; + std::cout << std::endl; + + if (ri->RecObjMom.size()) { + std::cout << "Reconstructed " << ri->RecObjMom.size() << " particles. " + << std::endl; + } #endif return ri; } + + double GetEfficiency(FitEvent *fe) { + double effweight = 1; + for (size_t p_it = 0; p_it < fe->NParticles(); ++p_it) { + FitParticle *fp = fe->GetParticle(p_it); + + int PDG = fp->PDG(); + double p = fp->P3().Mag() * 1E-3; + double cost = fp->P3().CosTheta(); + double phi = fp->P3().Phi() * (180.0 / TMath::Pi()) + 150.0; + if (fp->Status() != kFinalState) { + continue; + } + if (!Acceptance.count(PDG)) { + continue; + } + EffMap eff = Acceptance[PDG]; + + effweight *= eff.GetAccRatio(p, cost, phi); + } + return effweight; + } }; diff --git a/src/Electron/ElectronScattering_DurhamData.cxx b/src/Electron/ElectronScattering_DurhamData.cxx index c171df5..7e7b616 100644 --- a/src/Electron/ElectronScattering_DurhamData.cxx +++ b/src/Electron/ElectronScattering_DurhamData.cxx @@ -1,486 +1,486 @@ // 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 "ElectronScattering_DurhamData.h" //******************************************************************** ElectronScattering_DurhamData::ElectronScattering_DurhamData( nuiskey samplekey) { //******************************************************************** // Sample overview --------------------------------------------------- std::string descrip = "Electron Scattering Durham Data sample. \n" "Target: Multiple \n" "Flux: Energy should match data being handled \n" "Signal: Any event with an electron in the final state \n"; fSettings = LoadSampleSettings(samplekey); fSettings.SetDescription(descrip); fSettings.DefineAllowedSpecies("electron"); fSettings.SetTitle("Electron"); fSettings.SetAllowedTypes("FIX/DIAG", "FIX,FREE,SHAPE/DIAG/NORM/MASK"); fSettings.SetXTitle("q0"); fSettings.SetYTitle("#sigma"); fIsNoWidth = true; FinaliseSampleSettings(); // Plot Setup ------------------------------------------------------- SetDataFromName(fSettings.GetS("originalname")); SetCovarFromDiagonal(); // Scaling Setup --------------------------------------------------- // ScaleFactor automatically setup for DiffXSec/cm2/Nucleon // fScaleFactor = ((GetEventHistogram()->Integral("width") * 1E-38 / (fNEvents // + 0.)) / TotalIntegratedFlux()); EnuMin = fZLowLim; EnuMax = fZHighLim; double sigscale = GetEventHistogram()->Integral() * 1E-38 / double(fNEvents) / TotalIntegratedFlux(); // double dangle = 2 * M_PI * fabs((1. - cos(fYLowLim * M_PI / 180.)) - (1. - // cos(fYHighLim * M_PI / 180.))); // fScaleFactor = sigscale / dangle / fZCenter; fScaleFactor = sigscale; std::cout << "Event Integral = " << GetEventHistogram()->Integral() << std::endl; std::cout << "Flux Integral = " << TotalIntegratedFlux() << std::endl; std::cout << "FNEvents = " << fNEvents << std::endl; std::cout << "Z Limits = " << fZLowLim << " " << fZHighLim << std::endl; std::cout << "sigscale = " << sigscale << std::endl; std::cout << "fZCenter = " << fZCenter << std::endl; std::cout << "ScaleFactor = " << fScaleFactor << std::endl; // Finish up FinaliseMeasurement(); }; //******************************************************************** void ElectronScattering_DurhamData::SetDataFromName(std::string name) { //******************************************************************** // Data Should be given in the format // Electron_Z_A_Energy_Theta_Source std::vector splitstring = GeneralUtils::ParseToStr(name, "_"); std::string zstring = splitstring[1]; std::string astring = splitstring[2]; std::string estring = splitstring[3]; std::string tstring = splitstring[4]; std::string sstring = splitstring[5]; fYCenter = GeneralUtils::StrToDbl(tstring); fZCenter = GeneralUtils::StrToDbl(estring); // Create effective E and Theta bin Edges std::vector thetabinedges; std::vector ebinedges; int nthetabins = FitPar::Config().GetParI("Electron_NThetaBins"); int nebins = FitPar::Config().GetParI("Electron_NEnergyBins"); double thetawidth = FitPar::Config().GetParD("Electron_ThetaWidth"); double ewidth = FitPar::Config().GetParD("Electron_EnergyWidth"); for (int i = -nthetabins; i <= nthetabins; i++) { thetabinedges.push_back(fYCenter + thetawidth * (double(i))); } for (int i = -nebins; i <= nebins; i++) { double newval = fZCenter + ewidth * (double(i)); if (newval < 0.0) newval = 0.0; if (newval < GetEventHistogram()->GetXaxis()->GetXmin()) newval = GetEventHistogram()->GetXaxis()->GetXmin(); if (newval > GetEventHistogram()->GetXaxis()->GetXmax()) newval = GetEventHistogram()->GetXaxis()->GetXmax(); if (std::find(ebinedges.begin(), ebinedges.end(), newval) != ebinedges.end()) continue; ebinedges.push_back(newval); } // Determine target std::string target = ""; if (!zstring.compare("6") && !astring.compare("12")) target = "12C.dat"; else if (!zstring.compare("8") && !astring.compare("16")) target = "16O.dat"; else { ERR(FTL) << "Target not supported in electron scattering module!" << std::endl; throw; } // Fill Data Points std::string line; std::ifstream mask((FitPar::GetDataBase() + "/Electron/" + target).c_str(), - ifstream::in); + std::ifstream::in); if (!mask.good()) { ERR(FTL) << "Failed to open e-scattering database file: " << (FitPar::GetDataBase() + "/Electron/" + target) << std::endl; throw; } int i = 0; std::vector pointx; std::vector errorx; std::vector pointy; std::vector errory; double scalef = 1.E-38 * 1.E5; while (std::getline(mask >> std::ws, line, '\n')) { // std::cout << "Line = " << line << std::endl; if (line.empty()) continue; std::vector lineentries = GeneralUtils::ParseToStr(line, " "); // std::cout << "Checking : " << line << std::endl; if (zstring.compare(lineentries[0])) continue; if (astring.compare(lineentries[1])) continue; if (estring.compare(lineentries[2])) continue; if (tstring.compare(lineentries[3])) continue; if (sstring.compare(lineentries[7])) continue; // std::cout << "Registering data point : " << line << std::endl; // std::cout << "Adding Graph Point : " << // GeneralUtils::StrToDbl(lineentries[4]) << " " << // GeneralUtils::StrToDbl(lineentries[5]) << std::endl; // Loop through x and y points and find a place to insert if (pointx.empty()) { pointx.push_back(GeneralUtils::StrToDbl(lineentries[4])); errorx.push_back(0.0); pointy.push_back(GeneralUtils::StrToDbl(lineentries[5]) * scalef); errory.push_back(GeneralUtils::StrToDbl(lineentries[6]) * scalef); } else { for (size_t j = 0; j < pointx.size(); j++) { if (GeneralUtils::StrToDbl(lineentries[4]) < pointx[j] && j == 0) { // std::cout << "Inserting at start point iterator " << std::endl; pointx.insert(pointx.begin() + j, GeneralUtils::StrToDbl(lineentries[4])); errorx.insert(errorx.begin() + j, 0.0); pointy.insert(pointy.begin() + j, GeneralUtils::StrToDbl(lineentries[5]) * scalef); errory.insert(errory.begin() + j, GeneralUtils::StrToDbl(lineentries[6]) * scalef); break; } else if (GeneralUtils::StrToDbl(lineentries[4]) > pointx[j] && j == pointx.size() - 1) { // std::cout << "Pushing back data point " << std::endl; pointx.push_back(GeneralUtils::StrToDbl(lineentries[4])); errorx.push_back(0.0); pointy.push_back(GeneralUtils::StrToDbl(lineentries[5]) * scalef); errory.push_back(GeneralUtils::StrToDbl(lineentries[6]) * scalef); break; } else if (GeneralUtils::StrToDbl(lineentries[4]) > pointx[j - 1] && GeneralUtils::StrToDbl(lineentries[4]) < pointx[j]) { // std::cout << "Inserting at point iterator = " << j << std::endl; pointx.insert(pointx.begin() + j, GeneralUtils::StrToDbl(lineentries[4])); errorx.insert(errorx.begin() + j, 0.0); pointy.insert(pointy.begin() + j, GeneralUtils::StrToDbl(lineentries[5]) * scalef); errory.insert(errory.begin() + j, GeneralUtils::StrToDbl(lineentries[6]) * scalef); break; } } } // pointx.push_back(GeneralUtils::StrToDbl(lineentries[4])); // errorx.push_back(0.0); // pointy.push_back(GeneralUtils::StrToDbl(lineentries[5])); // errory.push_back(GeneralUtils::StrToDbl(lineentries[6])); i++; } if (!pointx.size() || (pointx.size() != errorx.size()) || !pointy.size() || (pointy.size() != errory.size())) { ERR(FTL) << "Failed to find dataset: " << name << "{" << "Z: " << zstring << ", A: " << astring << ", E: " << estring << ", CTheta: " << tstring << ", PubID: " << sstring << " } in file: " << (FitPar::GetDataBase() + "/Electron/" + target) << std::endl; throw; } // for (uint i = 0; i < pointx.size(); i++) { // std::cout << "Q0 Point " << i << " = " << pointx[i] << std::endl; // } fDataGraph = new TGraphErrors(pointx.size(), &pointx[0], &pointy[0], &errorx[0], &errory[0]); fDataGraph->SetNameTitle((fName + "_data_GRAPH").c_str(), (fName + "_data_GRAPH").c_str()); // Now form an effective data and mc histogram std::vector q0binedges; const double* x = fDataGraph->GetX(); // Loop over graph and get mid way point between each data point. for (int i = 0; i < fDataGraph->GetN(); i++) { // std::cout << "X Point = " << x[i] << std::endl; if (i == 0) { // First point set lower width as half distance to point above q0binedges.push_back(x[0] - ((x[1] - x[0]) / 2.0)); } else if (i == fDataGraph->GetN() - 1) { // Last point set upper width as half distance to point above. q0binedges.push_back(x[i] - ((x[i] - x[i - 1]) / 2.0)); q0binedges.push_back(x[i] + ((x[i] - x[i - 1]) / 2.0)); } else { // Set half distance to point below q0binedges.push_back(x[i] - ((x[i] - x[i - 1]) / 2.0)); } } // Bubble Sort // for (uint i = 0; i < q0binedges.size(); i++) { // std::cout << "Q0 Edge " << i << " = " << q0binedges[i] << std::endl; // } // for (uint i = 0; i < ebinedges.size(); i++) { // std::cout << "e Edge " << i << " = " << ebinedges[i] << std::endl; // } // for (uint i = 0; i < thetabinedges.size(); i++) { // std::cout << "theta Edge " << i << " = " << thetabinedges[i] << // std::endl; // } // Form the data hist, mchist, etc fDataHist = new TH1D((fName + "_data").c_str(), (fName + "_data").c_str(), q0binedges.size() - 1, &q0binedges[0]); fMCHist = (TH1D*)fDataHist->Clone("MC"); const double* y = fDataGraph->GetY(); const double* ey = fDataGraph->GetEY(); for (int i = 0; i < fDataGraph->GetN(); i++) { // std::cout << "Setting Data Bin " << i + 1 << " to " << y[i] << " +- " << // ey[i] << std::endl; fDataHist->SetBinContent(i + 1, y[i]); fDataHist->SetBinError(i + 1, ey[i]); fMCHist->SetBinContent(i + 1, 0.0); fMCHist->SetBinError(i + 1, 0.0); } fMCScan_Q0vsThetavsE = new TH3D((fName + "_MC_q0vsthetavse").c_str(), "MC_q0vsthetavse", q0binedges.size() - 1, &q0binedges[0], thetabinedges.size() - 1, &thetabinedges[0], ebinedges.size() - 1, &ebinedges[0]); fMCScan_Q0vsThetavsE->Reset(); fMCScan_Q0vsTheta = new TH2D( (fName + "_MC_q0vstheta").c_str(), "MC_q0vstheta", q0binedges.size() - 1, &q0binedges[0], thetabinedges.size() - 1, &thetabinedges[0]); fMCScan_Q0vsTheta->Reset(); fMCScan_Q0vsE = new TH2D((fName + "_MC_q0vse").c_str(), "MC_q0vse", q0binedges.size() - 1, &q0binedges[0], ebinedges.size() - 1, &ebinedges[0]); fMCScan_Q0vsE->Reset(); fXLowLim = fMCScan_Q0vsThetavsE->GetXaxis()->GetBinLowEdge(1); fXHighLim = fMCScan_Q0vsThetavsE->GetXaxis()->GetBinLowEdge( fMCScan_Q0vsThetavsE->GetNbinsX() + 2); fYLowLim = fMCScan_Q0vsThetavsE->GetYaxis()->GetBinLowEdge(1); fYHighLim = fMCScan_Q0vsThetavsE->GetYaxis()->GetBinLowEdge( fMCScan_Q0vsThetavsE->GetNbinsY() + 2); fZLowLim = fMCScan_Q0vsThetavsE->GetZaxis()->GetBinLowEdge(1); fZHighLim = fMCScan_Q0vsThetavsE->GetZaxis()->GetBinLowEdge( fMCScan_Q0vsThetavsE->GetNbinsZ() + 2); std::cout << "Sample " << name << "initialised: " << "{" << fXLowLim << "--" << fXHighLim << ", " << fYLowLim << "--" << fYHighLim << ", " << fZLowLim << "--" << fZHighLim << "}" << std::endl; } //******************************************************************** void ElectronScattering_DurhamData::FillEventVariables(FitEvent* event) { //******************************************************************** if (event->NumFSParticle(11) == 0) return; FitParticle* ein = event->PartInfo(0); FitParticle* eout = event->GetHMFSParticle(11); double q0 = fabs(ein->fP.E() - eout->fP.E()) / 1000.0; double E = ein->fP.E() / 1000.0; double theta = ein->fP.Vect().Angle(eout->fP.Vect()) * 180. / M_PI; fXVar = q0; fYVar = theta; fZVar = E; return; }; //******************************************************************** bool ElectronScattering_DurhamData::isSignal(FitEvent* event) { //******************************************************************** if (event->NumFSParticle(11) == 0) { std::cout << "Ev Cut due to no FS electron." << std::endl; return false; } // std::cout << "fXVar = " << fXVar << " " << fXLowLim << " " << fXHighLim << // std::endl; // std::cout << "fYVar = " << fYVar << " " << fYLowLim << " " << fYHighLim << // std::endl; // std::cout << "fZVar = " << fZVar << " " << fZLowLim << " " << fZHighLim << // std::endl; // std::cout << "iWeight: " << event->InputWeight << std::endl; if (fXVar < fXLowLim or fXVar > fXHighLim) { // std::cout << "Ev Cut due to X lims: " << fXLowLim << " -- " << fXHighLim // << " !<> " << fXVar << std::endl; return false; } if (fYVar < fYLowLim or fYVar > fYHighLim) { // std::cout << "Ev Cut due to Y lims: " << fYLowLim << " -- " << fYHighLim // << " !<> " << fXVar << std::endl; return false; } if (fZVar < fZLowLim or fZVar > fZHighLim) { // std::cout << "Ev Cut due to Z lims: " << fZLowLim << " -- " << fZHighLim // << " !<> " << fXVar << std::endl; return false; } return true; }; //******************************************************************** void ElectronScattering_DurhamData::FillHistograms() { //******************************************************************** Measurement1D::FillHistograms(); if (Signal) { fMCScan_Q0vsThetavsE->Fill(fXVar, fYVar, fZVar); fMCScan_Q0vsTheta->Fill(fXVar, fYVar); fMCScan_Q0vsE->Fill(fXVar, fZVar); } } // Weight = 1.0; // if (Signal) { // fMCHist->Fill(fXVar, Weight); // fMCFine->Fill(fXVar, Weight); // fMCStat->Fill(fXVar, 1.0); // if (fMCHist_Modes) fMCHist_Modes->Fill(Mode, fXVar, Weight); // } // } void ElectronScattering_DurhamData::ResetAll() { Measurement1D::ResetAll(); fMCScan_Q0vsThetavsE->Reset(); fMCScan_Q0vsTheta->Reset(); fMCScan_Q0vsE->Reset(); } void ElectronScattering_DurhamData::ApplyNormScale(double norm) { Measurement1D::ApplyNormScale(norm); fMCScan_Q0vsThetavsE->Scale(1.0 / norm); fMCScan_Q0vsTheta->Scale(1.0 / norm); fMCScan_Q0vsE->Scale(1.0 / norm); } //******************************************************************** void ElectronScattering_DurhamData::ScaleEvents() { //******************************************************************** Measurement1D::ScaleEvents(); /* fMCScan_Q0vsThetavsE->Scale(fScaleFactor, "width"); // Project into fMCScan_Q0vsTheta for (int x = 0; x < fMCScan_Q0vsThetavsE->GetNbinsX(); x++) { for (int y = 0; y < fMCScan_Q0vsThetavsE->GetNbinsY(); y++) { double total = 0.; for (int z = 0; z < fMCScan_Q0vsThetavsE->GetNbinsZ(); z++) { double zwidth = fMCScan_Q0vsThetavsE->GetZaxis()->GetBinWidth(z + 1); total += fMCScan_Q0vsThetavsE->GetBinContent(x + 1, y + 1, z + 1) * zwidth; } fMCScan_Q0vsTheta->SetBinContent(x + 1, y + 1, total); } } // Project into fMCScan_Q0vsE for (int x = 0; x < fMCScan_Q0vsThetavsE->GetNbinsX(); x++) { for (int z = 0; z < fMCScan_Q0vsThetavsE->GetNbinsZ(); z++) { double total = 0.; for (int y = 0; y < fMCScan_Q0vsThetavsE->GetNbinsY(); y++) { double ywidth = fMCScan_Q0vsThetavsE->GetYaxis()->GetBinWidth(y + 1); total += fMCScan_Q0vsThetavsE->GetBinContent(x + 1, y + 1, z + 1) * ywidth; } fMCScan_Q0vsE->SetBinContent(x + 1, z + 1, total); } } // Project fMCScan_Q0vsTheta into MC Hist for (int x = 0; x < fMCScan_Q0vsTheta->GetNbinsX(); x++) { double total = 0.; for (int y = 0; y < fMCScan_Q0vsTheta->GetNbinsY(); y++) { double ywidth = fMCScan_Q0vsTheta->GetYaxis()->GetBinWidth(y + 1); total += fMCScan_Q0vsTheta->GetBinContent(x + 1, y + 1); } double xwidth = fMCScan_Q0vsTheta->GetXaxis()->GetBinWidth(x + 1); fMCHist->SetBinContent(x + 1, total * xwidth); } fMCHist->Scale(fDataHist->Integral() / fMCHist->Integral()); */ } //******************************************************************** int ElectronScattering_DurhamData::GetNDOF() { //******************************************************************** return fDataGraph->GetN(); } void ElectronScattering_DurhamData::Write(std::string drawOpts) { Measurement1D::Write(drawOpts); fMCScan_Q0vsThetavsE->Write(); fMCScan_Q0vsTheta->Write(); fMCScan_Q0vsE->Write(); fDataGraph->Write(); } double ElectronScattering_DurhamData::GetLikelihood() { return 0.0; } void ElectronScattering_DurhamData::SetFitOptions(std::string opt) { return; } TH1D* ElectronScattering_DurhamData::GetMCHistogram(void) { return fMCHist; } TH1D* ElectronScattering_DurhamData::GetDataHistogram(void) { return fDataHist; } diff --git a/src/FCN/JointFCN.cxx b/src/FCN/JointFCN.cxx index 1c60f88..596d443 100755 --- a/src/FCN/JointFCN.cxx +++ b/src/FCN/JointFCN.cxx @@ -1,1139 +1,1122 @@ #include "JointFCN.h" #include #include "FitUtils.h" - //*************************************************** 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) { -//*************************************************** + //*************************************************** LOG(FIT) << " Creating new iteration container! " << std::endl; DestroyIterationTree(); fIterationTreeName = name; // Add sample likelihoods and ndof - for (MeasListConstIter iter = fSamples.begin(); - iter != fSamples.end(); + 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++) { - + 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(); + fSampleN = fSamples.size() + fPulls.size(); fSampleLikes = new double[fSampleN]; - fSampleNDOF = new int[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 ); + fNameValues.push_back(dials[i]); + fCurrentValues.push_back(0.0); } - fNDials = dials.size(); + 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() { -//*************************************************** + //*************************************************** LOG(FIT) << "Writing iteration tree" << std::endl; // Make a new TTree - TTree* itree = new TTree(fIterationTreeName.c_str(), - fIterationTreeName.c_str()); + 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 (int i = 0; i < fNameValues.size(); i++) { - itree->Branch( fNameValues[i].c_str(), - &vals[i], - (fNameValues[i] + "/D").c_str() ); + 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 ); + fIterationCount.push_back(fCurIter); fIterationValues.push_back(fCurrentValues); } //*************************************************** double JointFCN::DoEval(const double* x) { //*************************************************** // WEIGHT ENGINE fDialChanged = FitBase::GetRW()->HasRWDialChanged(x); FitBase::GetRW()->UpdateWeightEngine(x); 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(); + fNDOF = GetNDOF(); // PRINT PROGRESS LOG(FIT) << "Current Stat (iter. " << this->fCurIter << ") = " << fLikelihood << std::endl; // UPDATE TREE if (fIterationTree) FillIterationTree(FitBase::GetRW()); 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 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 if (fIterationTree) { fSampleNDOF[count] = dof; } // Add to total totaldof += dof; count++; } // Set Data Variable if (fIterationTree) { fSampleNDOF[count] = totaldof; } return totaldof; } //*************************************************** double JointFCN::GetLikelihood() { //*************************************************** LOG(MIN) << std::left << std::setw(43) << "Getting likelihoods..." << " : " << "-2logL" << std::endl; // 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 if (fIterationTree) { fSampleLikes[count] = newlike; } LOG(MIN) << "-> " << std::left << std::setw(40) << exp->GetName() << " : " << newlike << "/" << ndof << std::endl; // 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 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) { LOG(MIN) << "Loading Samples : " << samplekeys.size() << std::endl; 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 = ""; LOG(MIN) << "Loading Sample : " << samplename << std::endl; fOutputDir->cd(); MeasurementBase* NewLoadedSample = SampleUtils::CreateSample(key); if (!NewLoadedSample) { ERR(FTL) << "Could not load sample provided: " << samplename << std::endl; ERR(FTL) << "Check spelling with that in src/FCN/SampleList.cxx" << std::endl; 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); LOG(REC) << "Starting Reconfigure iter. " << this->fCurIter << std::endl; // std::cout << fUsingEventManager << " " << fullconfig << " " << fMCFilled << // std::endl; // Event Manager Reconf if (fUsingEventManager) { if (!fullconfig and 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; LOG(MIN) << "Finished Reconfigure iter. " << fCurIter << " in " << time(NULL) - starttime << "s" << std::endl; 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 LOG(REC) << "Event Manager Reconfigure" << std::endl; 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 / 5; // Start event loop iterating until we get a NULL pointer. while (curevent) { // Get Event Weight curevent->RWWeight = FitBase::GetRW()->CalcWeight(curevent); curevent->Weight = curevent->RWWeight * curevent->InputWeight; double rwweight = curevent->Weight; // std::cout << "RWWeight = " << curevent->RWWeight << " " << // curevent->InputWeight << std::endl; // Logging // std::cout << CHECKLOG(1) << std::endl; if (LOGGING(REC)) { - if (i % countwidth == 0) { + if (countwidth && (i % countwidth == 0)) { QLOG(REC, curinput->GetName() - << " : Processed " << i << " events. [M, W] = [" - << curevent->Mode << ", " << rwweight << "]"); + << " : Processed " << i << " events. [M, W] = [" + << curevent->Mode << ", " << rwweight << "]"); } } // 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(); + 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 and 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 and savesignal and 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. LOG(REC) << "Filled " << fillcount << " signal events." << std::endl; if (savesignal) { int mem = - ( // sizeof(fSignalEventBoxes) + - // fSignalEventBoxes.size() * sizeof(fSignalEventBoxes.at(0)) + - sizeof(MeasurementVariableBox1D) * fillcount) * - 1E-6; + ( // sizeof(fSignalEventBoxes) + + // fSignalEventBoxes.size() * sizeof(fSignalEventBoxes.at(0)) + + sizeof(MeasurementVariableBox1D) * fillcount) * + 1E-6; LOG(REC) << " -> Saved " << fillcount << " signal boxes for faster access. (~" << mem << " MB)" << std::endl; if (fIsAllSplines and !fSignalEventSplines.empty()) { int splmem = sizeof(float) * fSignalEventSplines.size() * fSignalEventSplines[0].size() * 1E-6; LOG(REC) << " -> Saved " << fillcount << " " << fSignalEventSplines.size() << " spline sets into memory. (~" << splmem << " MB)" << std::endl; } } LOG(REC) << "Time taken ReconfigureUsingManager() : " << time(NULL) - timestart << std::endl; // Check SignalReconfigures works for all samples if (savesignal) { double likefull = GetLikelihood(); ReconfigureFastUsingManager(); double likefast = GetLikelihood(); - if (fabs(likefull - likefast) > 0.0001) - { - ERROR(FTL, "Fast and Full Likelihoods DIFFER! : " << likefull << " : " << likefast); - ERROR(FTL, "This means some samples you are using are not setup to use SignalReconfigures=1"); + if (fabs(likefull - likefast) > 0.0001) { + ERROR(FTL, "Fast and Full Likelihoods DIFFER! : " << likefull << " : " + << likefast); + ERROR(FTL, + "This means some samples you are using are not setup to use " + "SignalReconfigures=1"); ERROR(FTL, "Please turn OFF signal reconfigures."); throw; } else { - LOG(FIT) << "Likelihoods for FULL and FAST match. Will use FAST next time." << std::endl; + LOG(FIT) + << "Likelihoods for FULL and FAST match. Will use FAST next time." + << std::endl; } } // End of reconfigure return; }; //*************************************************** void JointFCN::ReconfigureFastUsingManager() { -//*************************************************** + //*************************************************** LOG(FIT) << " -> Doing FAST using manager" << std::endl; // 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()) { ERR(WRN) << "Signal Flags Empty! Using normal manager." << std::endl; ReconfigureUsingManager(); return; } bool fFillNuisanceEvent = - FitPar::Config().GetParB("FullEventOnSignalReconfigure"); + FitPar::Config().GetParB("FullEventOnSignalReconfigure"); // Setup fast vector iterators. std::vector::iterator inpsig_iter = fSignalEventFlags.begin(); std::vector >::iterator box_iter = - fSignalEventBoxes.begin(); + fSignalEventBoxes.begin(); std::vector >::iterator spline_iter = - fSignalEventSplines.begin(); + fSignalEventSplines.begin(); std::vector >::iterator samsig_iter = - fSampleSignalFlags.begin(); + fSampleSignalFlags.begin(); int splinecount = 0; // Setup stuff for logging int fillcount = 0; int nevents = fSignalEventFlags.size(); int countwidth = nevents / 20; // If All Splines tell splines they need a reconfigure. std::vector::iterator inp_iter = fInputList.begin(); if (fIsAllSplines) { LOG(REC) << "All Spline Inputs so using fast spline loop." << std::endl; 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; splinecount = 0; // #pragma omp parallel for shared(splinecount,sigcount) for (uint iinput = 0; iinput < fInputList.size(); iinput++) { InputHandlerBase* curinput = fInputList[iinput]; BaseFitEvt* curevent = curinput->FirstBaseEvent(); for (int i = 0; i < curinput->GetNEvents(); i++) { double rwweight = 0.0; 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; rwweight = curevent->Weight; // Custom weights rwweight *= curevent->CustomWeight; coreeventweights[splinecount] = rwweight; if (countwidth && ((splinecount % countwidth) == 0)) { LOG(REC) << "Processed " << splinecount << " event weights. W = " << rwweight << std::endl; } // #pragma omp atomic splinecount++; } // #pragma omp atomic sigcount++; } } LOG(SAM) << "Processed event weights." << std::endl; // #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(); + (*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) { LOG(REC) << "Filled " << ispline << " sample weights." << std::endl; } // Iterate over the main signal event containers. samsig_iter++; box_iter++; spline_iter++; splinecount++; } // End of Fast Event Loop =================== LOG(SAM) << "Filled sample distributions." << std::endl; // Now loop over all Measurements // Convert Binned events iterSam = fSamples.begin(); for (; iterSam != fSamples.end(); iterSam++) { MeasurementBase* exp = (*iterSam); exp->ConvertEventRates(); } // Cleanup coreeventweights if (fIsAllSplines) { delete coreeventweights; } // Print some reconfigure profiling. LOG(REC) << "Filled " << fillcount << " signal events." << std::endl; LOG(REC) << "Time taken ReconfigureFastUsingManager() : " << time(NULL) - timestart << std::endl; } //*************************************************** void JointFCN::Write() { -//*************************************************** + //*************************************************** // Save a likelihood/ndof plot LOG(MIN) << "Writing likelihood plot.." << std::endl; 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); } - 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", 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())); for (size_t 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 LOG(MIN) << "Writing each of the data classes..." << std::endl; 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(); + 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) { -//*************************************************** + //*************************************************** LOG(MIN) << "Setting fake data from " << fakeinput << std::endl; 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(); + 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++) { + 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; LOG(MIN) << "Likelihoods : " << std::endl; // Loop over samples first - for (MeasListConstIter iter = fSamples.begin(); - iter != fSamples.end(); + 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 LOG(MIN) << "-> " << std::left << std::setw(40) << exp->GetName() << " : " << singlelike << std::endl; } - // Loop over pulls second - for (PullListConstIter iter = fPulls.begin(); - iter != fPulls.end(); - iter++) { + 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 LOG(MIN) << "-> " << std::left << std::setw(40) << pull->GetName() << " : " << singlelike << std::endl; - } // 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(); + 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++) { + 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/FitBase/JointMeas1D.cxx b/src/FitBase/JointMeas1D.cxx index 6700a10..6c3e699 100644 --- a/src/FitBase/JointMeas1D.cxx +++ b/src/FitBase/JointMeas1D.cxx @@ -1,2303 +1,2303 @@ // 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) { ERR(FTL) << "Joint measurement expected to recieve at least two semi-colon " "separated input files, but recieved: \"" << s.GetS("input") << "\"" << std::endl; throw; } std::vector first_file_descriptor = GeneralUtils::ParseToStr(entries.front(), ":"); if (first_file_descriptor.size() != 2) { ERR(FTL) << "Found Joint measurement where the input file had no type: \"" << s.GetS("input") << "\", expected \"INPUTTYPE:File.root;File2.root\"." << std::endl; throw; } 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 LOG(SAM) << "Finalising Sample Settings: " << fName << std::endl; if ((fSettings.GetS("originalname").find("Evt") != std::string::npos)) { fIsRawEvents = true; LOG(SAM) << "Found event rate measurement but using poisson likelihoods." << std::endl; } if (fSettings.GetS("originalname").find("XSec_1DEnu") != std::string::npos) { fIsEnu1D = true; LOG(SAM) << "::" << fName << "::" << std::endl; LOG(SAM) << "Found XSec Enu measurement, applying flux integrated scaling, " << "not flux averaged!" << std::endl; } if (fIsEnu1D && fIsRawEvents) { LOG(SAM) << "Found 1D Enu XSec distribution AND fIsRawEvents, is this " "really correct?!" << std::endl; LOG(SAM) << "Check experiment constructor for " << fName << " and correct this!" << std::endl; LOG(SAM) << "I live in " << __FILE__ << ":" << __LINE__ << std::endl; exit(-1); } // Parse Inputs fSubInFiles.clear(); std::vector entries = GeneralUtils::ParseToStr(fSettings.GetS("input"), ";"); if (entries.size() < 2) { ERR(FTL) << "Joint measurement expected to recieve at least two semi-colon " "separated input files, but recieved: \"" << fSettings.GetS("input") << "\"" << std::endl; throw; } std::vector first_file_descriptor = GeneralUtils::ParseToStr(entries.front(), ":"); if (first_file_descriptor.size() != 2) { ERR(FTL) << "Found Joint measurement where the input file had no type: \"" << fSettings.GetS("input") << "\", expected \"INPUTTYPE:File.root;File2.root\"." << std::endl; throw; } 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) { ERR(WRN) << "Norm error for class " << fName << " is 0.0!" << std::endl; ERR(WRN) << "If you want to use it please add fNormError=VAL" << std::endl; throw; } } if (!fRW) fRW = FitBase::GetRW(); LOG(SAM) << "Finalised Sample Settings" << std::endl; } //******************************************************************** void JointMeas1D::SetDataFromTextFile(std::string datafile) { //******************************************************************** LOG(SAM) << "Reading data from text file: " << datafile << std::endl; fDataHist = PlotUtils::GetTH1DFromFile(datafile, fSettings.GetName() + "_data", fSettings.GetFullTitles()); } //******************************************************************** void JointMeas1D::SetDataFromRootFile(std::string datafile, std::string histname) { //******************************************************************** LOG(SAM) << "Reading data from root file: " << datafile << ";" << histname << std::endl; fDataHist = PlotUtils::GetTH1DFromRootFile(datafile, histname); fDataHist->SetNameTitle((fSettings.GetName() + "_data").c_str(), (fSettings.GetFullTitles()).c_str()); return; }; //******************************************************************** void JointMeas1D::SetPoissonErrors() { //******************************************************************** if (!fDataHist) { ERR(FTL) << "Need a data hist to setup possion errors! " << std::endl; ERR(FTL) << "Setup Data First!" << std::endl; throw; } 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) { LOG(SAM) << "Setting diagonal covariance for: " << data->GetName() << std::endl; fFullCovar = StatUtils::MakeDiagonalCovarMatrix(data); covar = StatUtils::GetInvert(fFullCovar); fDecomp = StatUtils::GetDecomp(fFullCovar); } else { ERR(FTL) << "No data input provided to set diagonal covar from!" << std::endl; } if (!fIsDiag) { ERR(FTL) << "SetCovarMatrixFromDiag called for measurement " << "that is not set as diagonal." << std::endl; throw; } } //******************************************************************** void JointMeas1D::SetCovarFromTextFile(std::string covfile, int dim) { //******************************************************************** LOG(SAM) << "Reading covariance from text file: " << covfile << std::endl; fFullCovar = StatUtils::GetCovarFromTextFile(covfile, dim); - + covar = StatUtils::GetInvert(fFullCovar); 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){ LOG(SAM) << "Reading covariance from text file: " << covList[i] << std::endl; TMatrixDSym* temp_cov = StatUtils::GetCovarFromTextFile(covList[i], dim); (*fFullCovar) += (*temp_cov); delete temp_cov; } covar = StatUtils::GetInvert(fFullCovar); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void JointMeas1D::SetCovarFromRootFile(std::string covfile, std::string histname) { //******************************************************************** LOG(SAM) << "Reading covariance from text file: " << covfile << ";" << histname << std::endl; fFullCovar = StatUtils::GetCovarFromRootFile(covfile, histname); covar = StatUtils::GetInvert(fFullCovar); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void JointMeas1D::SetCovarInvertFromTextFile(std::string covfile, int dim) { //******************************************************************** LOG(SAM) << "Reading inverted covariance from text file: " << covfile << std::endl; covar = StatUtils::GetCovarFromTextFile(covfile, dim); fFullCovar = StatUtils::GetInvert(covar); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void JointMeas1D::SetCovarInvertFromRootFile(std::string covfile, std::string histname) { //******************************************************************** LOG(SAM) << "Reading inverted covariance from text file: " << covfile << ";" << histname << std::endl; covar = StatUtils::GetCovarFromRootFile(covfile, histname); fFullCovar = StatUtils::GetInvert(covar); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void JointMeas1D::SetCorrelationFromTextFile(std::string covfile, int dim) { //******************************************************************** if (dim == -1) dim = fDataHist->GetNbinsX(); LOG(SAM) << "Reading data correlations from text file: " << covfile << ";" << dim << std::endl; TMatrixDSym* correlation = StatUtils::GetCovarFromTextFile(covfile, dim); if (!fDataHist) { ERR(FTL) << "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" << std::endl; throw; } // 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); 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){ LOG(SAM) << "Reading covariance from text file: " << corrList[i] << std::endl; 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); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void JointMeas1D::SetCorrelationFromRootFile(std::string covfile, std::string histname) { //******************************************************************** LOG(SAM) << "Reading data correlations from text file: " << covfile << ";" << histname << std::endl; TMatrixDSym* correlation = StatUtils::GetCovarFromRootFile(covfile, histname); if (!fDataHist) { ERR(FTL) << "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" << std::endl; throw; } // 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); 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) { //******************************************************************** LOG(SAM) << "Reading cholesky from text file: " << covfile << std::endl; 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); fDecomp = StatUtils::GetDecomp(fFullCovar); delete temp; delete trans; } //******************************************************************** void JointMeas1D::SetCholDecompFromRootFile(std::string covfile, std::string histname) { //******************************************************************** LOG(SAM) << "Reading cholesky decomp from root file: " << covfile << ";" << histname << std::endl; 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); 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; LOG(SAM) << "Reading bin mask from file: " << maskfile << std::endl; // 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(), ifstream::in); + std::ifstream mask(maskfile.c_str(), std::ifstream::in); if (!mask.is_open()) { LOG(FTL) << " Cannot find mask file." << std::endl; 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) { LOG(WRN) << "JointMeas1D::SetBinMask(), couldn't parse line: " << line << std::endl; 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() { //******************************************************************** LOG(SAM) << "Finalising Measurement: " << fName << std::endl; // Make sure data is setup if (!fDataHist) { ERR(FTL) << "No data has been setup inside " << fName << " constructor!" << std::endl; throw; } // Make sure covariances are setup if (!fFullCovar) { fIsDiag = true; SetCovarFromDiagonal(fDataHist); } if (!covar) { covar = StatUtils::GetInvert(fFullCovar); } 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) { ERR(FTL) << "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." << std::endl; throw; } } } // 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) { ERR(FTL) << "ERROR: Fit Option '" << fit_options_input.at(i) << "' Provided is not allowed for this measurement." << std::endl; ERR(FTL) << "Fit Options should be provided as a '/' seperated list " "(e.g. FREE/DIAG/NORM)" << std::endl; ERR(FTL) << "Available options for " << fName << " are '" << fAllowedTypes << "'" << std::endl; 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; ERR(FTL) << "No other LIKELIHOODS properly supported!" << std::endl; ERR(FTL) << "Try to use a chi2!" << std::endl; 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(), ifstream::in); + 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()) LOG(SAM) << "Reading smearing matrix from file: " << smearfile << std::endl; else ERR(FTL) << "Smearing matrix provided is incorrect: " << smearfile << std::endl; 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) { ERR(WRN) << fName << ": attempted to apply smearing matrix, but none was set" << std::endl; 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() { //******************************************************************** LOG(FIT) << "Scaling JointMeas1D" << std::endl; // 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; LOG(SAM) << "Setting fake data from : " << fFakeDataInput << std::endl; // 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); if (fDecomp) delete fDecomp; fDecomp = StatUtils::GetInvert(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 << 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()); } if (drawOpt.find("INVCOV") != std::string::npos && covar) { PlotUtils::GetInvCovarPlot(covar, fSettings.GetName()); } if (drawOpt.find("DECOMP") != std::string::npos && fDecomp) { PlotUtils::GetDecompCovarPlot(fDecomp, fSettings.GetName()); } // // 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 LOG(SAM) << "Written Histograms: " << fName << std::endl; 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 << 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; } // 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 "JointMeas1D.h" /* Constructor/Deconstuctor */ /* 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. // Parse this list and save it for later, and set up the types etc. if (FitPar::Config().GetParB("EventManager")) { ERR(FTL) << "Event Manager does not yet work with JointMeas1D Samples" << std::endl; ERR(FTL) << "If you want good predictions for " << fName << " then run with it turned off! (-q EventManager=0)" << std::endl; } fSubInFiles.clear(); std::vector entries = GeneralUtils::ParseToStr(input, ";"); if (entries.size() < 2) { ERR(FTL) << "Joint measurement expected to recieve at least two semi-colon " "separated input files, but recieved: \"" << input << "\"" << std::endl; throw; } std::vector first_file_descriptor = GeneralUtils::ParseToStr(entries.front(), ":"); if (first_file_descriptor.size() != 2) { ERR(FTL) << "Found Joint measurement where the input file had no type: \"" << input << "\", expected \"INPUTTYPE:File.root;File2.root\"." << std::endl; throw; } 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){ ERR(FTL) << "No combined flux setup in JointMeas1D" << std::endl; } 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){ ERR(FTL) << "No combined event rate setup in JointMeas1D" << std::endl; } 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 LOG(SAM) << "Reading data from: " << dataFile.c_str() << std::endl; 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) { //******************************************************************** LOG(SAM) << "Filling histogram from " << inhistfile << "->" << histname << std::endl; 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) { //******************************************************************** LOG(SAM) << "Filling histogram from " << inhistfile << "->" << histname << std::endl; 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* decmpPlot = new TH2D(); TH2D* covarInvPlot = 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()); covarInvPlot = (TH2D*)tempFile->Get((covName + "covinv").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 ERR(WRN) << "Incorrect thrown_covariance option in parameters." << std::endl; 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(), ifstream::in); + std::ifstream covarread(covarFile.c_str(), std::ifstream::in); this->covar = new TMatrixDSym(dim); fFullCovar = new TMatrixDSym(dim); if (covarread.is_open()) LOG(SAM) << "Reading covariance matrix from file: " << covarFile << std::endl; else ERR(FTL) << "Covariance matrix provided is incorrect: " << covarFile << std::endl; // 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) { ERR(WRN) << "SetCovarMatrixFromText -> Covariance matrix only has <= 1 " "entries on this line: " << row << std::endl; } 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(), ifstream::in); + std::ifstream corr(corrFile.c_str(), std::ifstream::in); this->covar = new TMatrixDSym(dim); this->fFullCovar = new TMatrixDSym(dim); if (corr.is_open()) LOG(SAM) << "Reading and converting correlation matrix from file: " << corrFile << std::endl; else { ERR(FTL) << "Correlation matrix provided is incorrect: " << corrFile << std::endl; 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) { ERR(FTL) << "Found a zero value in the covariance matrix, assuming " "this is an error!" << std::endl; 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) { //******************************************************************** LOG(SAM) << "Getting covariance from " << covarFile << "->" << covName << std::endl; 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/Measurement1D.cxx b/src/FitBase/Measurement1D.cxx index cb2cdd3..3306167 100644 --- a/src/FitBase/Measurement1D.cxx +++ b/src/FitBase/Measurement1D.cxx @@ -1,1903 +1,1905 @@ // 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; // 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; // 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; } //******************************************************************** 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 LOG(SAM) << "Finalising Sample Settings: " << fName << std::endl; if ((fSettings.GetS("originalname").find("Evt") != std::string::npos)) { fIsRawEvents = true; LOG(SAM) << "Found event rate measurement but using poisson likelihoods." << std::endl; } if (fSettings.GetS("originalname").find("XSec_1DEnu") != std::string::npos) { fIsEnu1D = true; LOG(SAM) << "::" << fName << "::" << std::endl; LOG(SAM) << "Found XSec Enu measurement, applying flux integrated scaling, " << "not flux averaged!" << std::endl; } if (fIsEnu1D && fIsRawEvents) { LOG(SAM) << "Found 1D Enu XSec distribution AND fIsRawEvents, is this " "really correct?!" << std::endl; LOG(SAM) << "Check experiment constructor for " << fName << " and correct this!" << std::endl; LOG(SAM) << "I live in " << __FILE__ << ":" << __LINE__ << std::endl; exit(-1); } 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")); if (fAddNormPen) { if (fNormError <= 0.0) { ERR(WRN) << "Norm error for class " << fName << " is 0.0!" << std::endl; ERR(WRN) << "If you want to use it please add fNormError=VAL" << std::endl; throw; } } } //******************************************************************** 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) { //******************************************************************** LOG(SAM) << "Reading data from text file: " << datafile << std::endl; fDataHist = PlotUtils::GetTH1DFromFile(datafile, fSettings.GetName() + "_data", fSettings.GetFullTitles()); } //******************************************************************** void Measurement1D::SetDataFromRootFile(std::string datafile, std::string histname) { //******************************************************************** LOG(SAM) << "Reading data from root file: " << datafile << ";" << histname << std::endl; 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) { ERR(FTL) << "Need a data hist to setup possion errors! " << std::endl; ERR(FTL) << "Setup Data First!" << std::endl; 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) { LOG(SAM) << "Setting diagonal covariance for: " << data->GetName() << std::endl; fFullCovar = StatUtils::MakeDiagonalCovarMatrix(data); covar = StatUtils::GetInvert(fFullCovar); fDecomp = StatUtils::GetDecomp(fFullCovar); } else { ERR(FTL) << "No data input provided to set diagonal covar from!" << std::endl; } // if (!fIsDiag) { // ERR(FTL) << "SetCovarMatrixFromDiag called for measurement " // << "that is not set as diagonal." << std::endl; // throw; // } } //******************************************************************** void Measurement1D::SetCovarFromTextFile(std::string covfile, int dim) { //******************************************************************** if (dim == -1) { dim = fDataHist->GetNbinsX(); } LOG(SAM) << "Reading covariance from text file: " << covfile << std::endl; fFullCovar = StatUtils::GetCovarFromTextFile(covfile, dim); covar = StatUtils::GetInvert(fFullCovar); 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){ LOG(SAM) << "Reading covariance from text file: " << covList[i] << std::endl; TMatrixDSym* temp_cov = StatUtils::GetCovarFromTextFile(covList[i], dim); (*fFullCovar) += (*temp_cov); delete temp_cov; } covar = StatUtils::GetInvert(fFullCovar); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void Measurement1D::SetCovarFromRootFile(std::string covfile, std::string histname) { //******************************************************************** LOG(SAM) << "Reading covariance from text file: " << covfile << ";" << histname << std::endl; fFullCovar = StatUtils::GetCovarFromRootFile(covfile, histname); covar = StatUtils::GetInvert(fFullCovar); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void Measurement1D::SetCovarInvertFromTextFile(std::string covfile, int dim) { //******************************************************************** if (dim == -1) { dim = fDataHist->GetNbinsX(); } LOG(SAM) << "Reading inverted covariance from text file: " << covfile << std::endl; covar = StatUtils::GetCovarFromTextFile(covfile, dim); fFullCovar = StatUtils::GetInvert(covar); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void Measurement1D::SetCovarInvertFromRootFile(std::string covfile, std::string histname) { //******************************************************************** LOG(SAM) << "Reading inverted covariance from text file: " << covfile << ";" << histname << std::endl; covar = StatUtils::GetCovarFromRootFile(covfile, histname); fFullCovar = StatUtils::GetInvert(covar); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void Measurement1D::SetCorrelationFromTextFile(std::string covfile, int dim) { //******************************************************************** if (dim == -1) dim = fDataHist->GetNbinsX(); LOG(SAM) << "Reading data correlations from text file: " << covfile << ";" << dim << std::endl; TMatrixDSym* correlation = StatUtils::GetCovarFromTextFile(covfile, dim); if (!fDataHist) { ERR(FTL) << "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" << std::endl; throw; } // 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); 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){ LOG(SAM) << "Reading covariance from text file: " << corrList[i] << std::endl; 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); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void Measurement1D::SetCorrelationFromRootFile(std::string covfile, std::string histname) { //******************************************************************** LOG(SAM) << "Reading data correlations from text file: " << covfile << ";" << histname << std::endl; TMatrixDSym* correlation = StatUtils::GetCovarFromRootFile(covfile, histname); if (!fDataHist) { ERR(FTL) << "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" << std::endl; throw; } // 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); fDecomp = StatUtils::GetDecomp(fFullCovar); delete correlation; } //******************************************************************** void Measurement1D::SetCholDecompFromTextFile(std::string covfile, int dim) { //******************************************************************** if (dim == -1) { dim = fDataHist->GetNbinsX(); } LOG(SAM) << "Reading cholesky from text file: " << covfile << std::endl; 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); fDecomp = StatUtils::GetDecomp(fFullCovar); delete temp; delete trans; } //******************************************************************** void Measurement1D::SetCholDecompFromRootFile(std::string covfile, std::string histname) { //******************************************************************** LOG(SAM) << "Reading cholesky decomp from root file: " << covfile << ";" << histname << std::endl; 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); 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; LOG(SAM) << "Reading bin mask from file: " << maskfile << std::endl; // 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(), ifstream::in); + std::ifstream mask(maskfile.c_str(), std::ifstream::in); if (!mask.is_open()) { LOG(FTL) << " Cannot find mask file." << std::endl; 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) { 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. 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() { //******************************************************************** LOG(SAM) << "Finalising Measurement: " << fName << std::endl; 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) { ERR(FTL) << "No data has been setup inside " << fName << " constructor!" << std::endl; throw; } // Make sure covariances are setup if (!fFullCovar) { fIsDiag = true; SetCovarFromDiagonal(fDataHist); } if (!covar) { covar = StatUtils::GetInvert(fFullCovar); } 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 and FitPar::Config().GetParB("UseShapeCovar")){ if (covar) delete covar; covar = StatUtils::GetInvert(fShapeCovar); if (fDecomp) delete fDecomp; fDecomp = StatUtils::GetDecomp(fFullCovar); } // 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); SetAutoProcessTH1(fMCHist_Modes, kCMD_Reset, kCMD_Norm, kCMD_Write); } // 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 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) { ERR(FTL) << "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." << std::endl; throw; } } } // 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) { ERR(FTL) << "ERROR: Fit Option '" << fit_options_input.at(i) << "' Provided is not allowed for this measurement." << std::endl; ERR(FTL) << "Fit Options should be provided as a '/' seperated list " "(e.g. FREE/DIAG/NORM)" << std::endl; ERR(FTL) << "Available options for " << fName << " are '" << fAllowedTypes << "'" << std::endl; 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; ERR(FTL) << "No other LIKELIHOODS properly supported!" << std::endl; ERR(FTL) << "Try to use a chi2!" << std::endl; 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(), ifstream::in); + 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()) LOG(SAM) << "Reading smearing matrix from file: " << smearfile << std::endl; else ERR(FTL) << "Smearing matrix provided is incorrect: " << smearfile << std::endl; 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) { ERR(WRN) << fName << ": attempted to apply smearing matrix, but none was set" << std::endl; 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) { + QLOG(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) { // 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) { 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 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; LOG(SAM) << "Setting fake data from : " << fFakeDataInput << std::endl; // 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); if (fDecomp) delete fDecomp; fDecomp = StatUtils::GetInvert(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 GetDataList().at(0)->Write(); 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()); } if (drawOpt.find("INVCOV") != std::string::npos && covar) { PlotUtils::GetInvCovarPlot(covar, fSettings.GetName()); } if (drawOpt.find("DECOMP") != std::string::npos && fDecomp) { PlotUtils::GetDecompCovarPlot(fDecomp, fSettings.GetName()); } // // 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(); // Returning LOG(SAM) << "Written Histograms: " << fName << std::endl; 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()); if (fShapeCovar) StatUtils::SetDataErrorFromCov(dataShape, fShapeCovar, 1E-38); 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; LOG(SAM) << "Found event rate measurement but fIsRawEvents == false!" << std::endl; LOG(SAM) << "Overriding this and setting fIsRawEvents == true!" << std::endl; } fIsEnu1D = false; if (fName.find("XSec_1DEnu") != std::string::npos) { fIsEnu1D = true; LOG(SAM) << "::" << fName << "::" << std::endl; LOG(SAM) << "Found XSec Enu measurement, applying flux integrated scaling, " "not flux averaged!" << std::endl; } if (fIsEnu1D && fIsRawEvents) { LOG(SAM) << "Found 1D Enu XSec distribution AND fIsRawEvents, is this " "really correct?!" << std::endl; LOG(SAM) << "Check experiment constructor for " << fName << " and correct this!" << std::endl; LOG(SAM) << "I live in " << __FILE__ << ":" << __LINE__ << std::endl; exit(-1); } 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 LOG(SAM) << "Reading data from: " << dataFile.c_str() << std::endl; 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) { //******************************************************************** LOG(SAM) << "Filling histogram from " << inhistfile << "->" << histname << std::endl; 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) { //******************************************************************** LOG(SAM) << "Filling histogram from " << inhistfile << "->" << histname << std::endl; 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* decmpPlot = new TH2D(); TH2D* covarInvPlot = 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()); covarInvPlot = (TH2D*)tempFile->Get((covName + "covinv").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 ERR(WRN) << "Incorrect thrown_covariance option in parameters." << std::endl; 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(), ifstream::in); + std::ifstream covarread(covarFile.c_str(), std::ifstream::in); this->covar = new TMatrixDSym(dim); fFullCovar = new TMatrixDSym(dim); if (covarread.is_open()) LOG(SAM) << "Reading covariance matrix from file: " << covarFile << std::endl; else ERR(FTL) << "Covariance matrix provided is incorrect: " << covarFile << std::endl; // 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) { ERR(WRN) << "SetCovarMatrixFromText -> Covariance matrix only has <= 1 " "entries on this line: " << row << std::endl; } 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(), ifstream::in); + std::ifstream corr(corrFile.c_str(), std::ifstream::in); this->covar = new TMatrixDSym(dim); this->fFullCovar = new TMatrixDSym(dim); if (corr.is_open()) LOG(SAM) << "Reading and converting correlation matrix from file: " << corrFile << std::endl; else { ERR(FTL) << "Correlation matrix provided is incorrect: " << corrFile << std::endl; 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) { ERR(FTL) << "Found a zero value in the covariance matrix, assuming " "this is an error!" << std::endl; 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 Measurement1D::SetCovarFromDataFile(std::string covarFile, std::string covName, bool FullUnits) { //******************************************************************** LOG(SAM) << "Getting covariance from " << covarFile << "->" << covName << std::endl; 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(), ifstream::in); +// 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/Measurement2D.cxx b/src/FitBase/Measurement2D.cxx index 87f361f..77424bc 100644 --- a/src/FitBase/Measurement2D.cxx +++ b/src/FitBase/Measurement2D.cxx @@ -1,1961 +1,1961 @@ // 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; 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; // 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; } //******************************************************************** 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 LOG(SAM) << "Finalising Sample Settings: " << fName << std::endl; if ((fSettings.GetS("originalname").find("Evt") != std::string::npos)) { fIsRawEvents = true; LOG(SAM) << "Found event rate measurement but using poisson likelihoods." << std::endl; } if (fSettings.GetS("originalname").find("XSec_1DEnu") != std::string::npos) { fIsEnu1D = true; LOG(SAM) << "::" << fName << "::" << std::endl; LOG(SAM) << "Found XSec Enu measurement, applying flux integrated scaling, " << "not flux averaged!" << std::endl; } if (fIsEnu1D && fIsRawEvents) { LOG(SAM) << "Found 1D Enu XSec distribution AND fIsRawEvents, is this " "really correct?!" << std::endl; LOG(SAM) << "Check experiment constructor for " << fName << " and correct this!" << std::endl; LOG(SAM) << "I live in " << __FILE__ << ":" << __LINE__ << std::endl; exit(-1); } 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")); if (fAddNormPen) { fNormError = fSettings.GetNormError(); if (fNormError <= 0.0) { ERR(WRN) << "Norm error for class " << fName << " is 0.0!" << std::endl; ERR(WRN) << "If you want to use it please add fNormError=VAL" << std::endl; throw; } } } void Measurement2D::CreateDataHistogram(int dimx, double* binx, int dimy, double* biny) { if (fDataHist) delete fDataHist; LOG(SAM) << "Creating Data Histogram dim : " << dimx << " " << dimy << std::endl; fDataHist = new TH2D( (fSettings.GetName() + "_data").c_str(), (fSettings.GetFullTitles()).c_str(), dimx - 1, binx, dimy - 1, biny ); } void Measurement2D::SetDataFromTextFile(std::string datfile) { // fDataHist = PlotUtils::GetTH2DFromTextFile(datfile,""); } void Measurement2D::SetDataFromRootFile(std::string datfile, std::string histname) { fDataHist = PlotUtils::GetTH2DFromRootFile(datfile, histname); } void Measurement2D::SetDataValuesFromTextFile(std::string datfile, TH2D* hist) { LOG(SAM) << "Setting data values from text file" << std::endl; if (!hist) hist = fDataHist; // Read TH2D From textfile TH2D* valhist = (TH2D*) hist->Clone(); valhist->Reset(); PlotUtils::Set2DHistFromText(datfile, valhist, 1.0, true); LOG(SAM) << " -> Filling values from read hist." << std::endl; 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)); } } LOG(SAM) << " --> Done" << std::endl; } void Measurement2D::SetDataErrorsFromTextFile(std::string datfile, TH2D* hist) { LOG(SAM) << "Setting data errors from text file" << std::endl; if (!hist) hist = fDataHist; // Read TH2D From textfile TH2D* valhist = (TH2D*) hist->Clone(); valhist->Reset(); PlotUtils::Set2DHistFromText(datfile, valhist, 1.0); // Fill Errors LOG(SAM) << " -> Filling errors from read hist." << std::endl; 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)); } } LOG(SAM) << " --> Done" << std::endl; } 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]); LOG(SAM) << "Reading map from: " << dataFile << std::endl; PlotUtils::Set2DHistFromText(dataFile, fMapHist, 1.0); } //******************************************************************** void Measurement2D::SetPoissonErrors() { //******************************************************************** if (!fDataHist) { ERR(FTL) << "Need a data hist to setup possion errors! " << std::endl; ERR(FTL) << "Setup Data First!" << std::endl; throw; } 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) { LOG(SAM) << "Setting diagonal covariance for: " << data->GetName() << std::endl; fFullCovar = StatUtils::MakeDiagonalCovarMatrix(data); covar = StatUtils::GetInvert(fFullCovar); fDecomp = StatUtils::GetDecomp(fFullCovar); } else { ERR(FTL) << "No data input provided to set diagonal covar from!" << std::endl; } // 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(); } LOG(SAM) << "Reading covariance from text file: " << covfile << " " << dim << std::endl; fFullCovar = StatUtils::GetCovarFromTextFile(covfile, dim); covar = StatUtils::GetInvert(fFullCovar); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void Measurement2D::SetCovarFromRootFile(std::string covfile, std::string histname) { //******************************************************************** LOG(SAM) << "Reading covariance from text file: " << covfile << ";" << histname << std::endl; fFullCovar = StatUtils::GetCovarFromRootFile(covfile, histname); covar = StatUtils::GetInvert(fFullCovar); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void Measurement2D::SetCovarInvertFromTextFile(std::string covfile, int dim) { //******************************************************************** if (dim == -1) { dim = this->GetNDOF(); } LOG(SAM) << "Reading inverted covariance from text file: " << covfile << std::endl; covar = StatUtils::GetCovarFromTextFile(covfile, dim); fFullCovar = StatUtils::GetInvert(covar); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void Measurement2D::SetCovarInvertFromRootFile(std::string covfile, std::string histname) { //******************************************************************** LOG(SAM) << "Reading inverted covariance from text file: " << covfile << ";" << histname << std::endl; covar = StatUtils::GetCovarFromRootFile(covfile, histname); fFullCovar = StatUtils::GetInvert(covar); fDecomp = StatUtils::GetDecomp(fFullCovar); } //******************************************************************** void Measurement2D::SetCorrelationFromTextFile(std::string covfile, int dim) { //******************************************************************** if (dim == -1) dim = this->GetNDOF(); LOG(SAM) << "Reading data correlations from text file: " << covfile << ";" << dim << std::endl; TMatrixDSym* correlation = StatUtils::GetCovarFromTextFile(covfile, dim); if (!fDataHist) { ERR(FTL) << "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" << std::endl; throw; } // 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); fDecomp = StatUtils::GetDecomp(fFullCovar); delete correlation; } //******************************************************************** void Measurement2D::SetCorrelationFromRootFile(std::string covfile, std::string histname) { //******************************************************************** LOG(SAM) << "Reading data correlations from text file: " << covfile << ";" << histname << std::endl; TMatrixDSym* correlation = StatUtils::GetCovarFromRootFile(covfile, histname); if (!fDataHist) { ERR(FTL) << "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" << std::endl; throw; } // 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); fDecomp = StatUtils::GetDecomp(fFullCovar); delete correlation; } //******************************************************************** void Measurement2D::SetCholDecompFromTextFile(std::string covfile, int dim) { //******************************************************************** if (dim == -1) { dim = this->GetNDOF(); } LOG(SAM) << "Reading cholesky from text file: " << covfile << " " << dim << std::endl; 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); fDecomp = StatUtils::GetDecomp(fFullCovar); delete temp; delete trans; } //******************************************************************** void Measurement2D::SetCholDecompFromRootFile(std::string covfile, std::string histname) { //******************************************************************** LOG(SAM) << "Reading cholesky decomp from root file: " << covfile << ";" << histname << std::endl; 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); fDecomp = StatUtils::GetDecomp(fFullCovar); delete temp; delete trans; } //******************************************************************** 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; LOG(SAM) << "Reading bin mask from file: " << maskfile << std::endl; // 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(), ifstream::in); + std::ifstream mask(maskfile.c_str(), std::ifstream::in); if (!mask.is_open()) { LOG(FTL) << " Cannot find mask file." << std::endl; 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) { LOG(WRN) << "Measurement2D::SetBinMask(), couldn't parse line: " << line << std::endl; 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() { //******************************************************************** LOG(SAM) << "Finalising Measurement: " << fName << std::endl; 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) { ERR(FTL) << "No data has been setup inside " << fName << " constructor!" << std::endl; throw; } // Make sure covariances are setup if (!fFullCovar) { fIsDiag = true; SetCovarFromDiagonal(fDataHist); } if (!covar) { covar = StatUtils::GetInvert(fFullCovar); } if (!fDecomp) { fDecomp = StatUtils::GetDecomp(fFullCovar); } // 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); 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 = (TH2D*)fMCHist->Clone(); fMCWeighted->SetNameTitle((fName + "_MCWGHTS").c_str(), (fName + "_MCWGHTS" + fPlotTitles).c_str()); fMCWeighted->GetYaxis()->SetTitle("Weighted Events"); } } //******************************************************************** 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) { ERR(FTL) << "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." << std::endl; throw; } } } // 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) { ERR(FTL) << "ERROR: Fit Option '" << fit_options_input.at(i) << "' Provided is not allowed for this measurement." << std::endl; ERR(FTL) << "Fit Options should be provided as a '/' seperated list " "(e.g. FREE/DIAG/NORM)" << std::endl; ERR(FTL) << "Available options for " << fName << " are '" << fAllowedTypes << "'" << std::endl; 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; ERR(FTL) << "No other LIKELIHOODS properly supported!" << std::endl; ERR(FTL) << "Try to use a chi2!" << std::endl; 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; // 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() + 1; ++xBin) { for (int yBin = 0; yBin < fDataHist->GetNbinsY() + 1; ++yBin) { if (fDataHist->GetBinError(xBin, yBin) != 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); } } // Add a normal penalty term if (fAddNormPen) { chi2 += (1 - (fCurrentNorm)) * (1 - (fCurrentNorm)) / (fNormError * fNormError); LOG(REC) << "Norm penalty = " << (1 - (fCurrentNorm)) * (1 - (fCurrentNorm)) / (fNormError * fNormError) << std::endl; } // 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; LOG(SAM) << "Setting fake data from : " << fFakeDataInput << std::endl; // 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); if (fDecomp) delete fDecomp; fDecomp = StatUtils::GetInvert(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(); } // Write Data/MC GetDataList().at(0)->Write(); GetMCList().at(0)->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()); } if (drawOpt.find("INVCOV") != std::string::npos && covar) { PlotUtils::GetInvCovarPlot(covar, fSettings.GetName()); } if (drawOpt.find("DECOMP") != std::string::npos && fDecomp) { PlotUtils::GetDecompCovarPlot(fDecomp, fSettings.GetName()); } // // 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; // } // Write Extra Histograms AutoWriteExtraTH1(); WriteExtraHistograms(); /// 2D VERSION // If null pointer return if (!fMCHist and !fDataHist) { LOG(SAM) << fName << "Incomplete histogram set!" << std::endl; 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 drawXSec = (drawOpt.find("XSEC") != 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 drawSliceCanvYMC = (drawOpt.find("CANVYMC") != std::string::npos); bool drawWeighted = (drawOpt.find("WGHT") != std::string::npos); if (FitPar::Config().GetParB("EventManager")) { drawFlux = false; drawXSec = false; drawEvents = false; } if (fMaskHist) fMaskHist->Write(); // Save standard plots if (drawData) this->GetDataList().at(0)->Write(); if (drawNormal) this->GetMCList().at(0)->Write(); if (drawCov) { TH2D(*fFullCovar).Write((fName + "_COV").c_str()); } if (drawOpt.find("INVCOV") != std::string::npos) { TH2D(*covar).Write((fName + "_INVCOV").c_str()); } // Generate a simple map if (!fMapHist) fMapHist = StatUtils::GenerateMap(fDataHist); // Convert to 1D Lists TH1D* data_1D = StatUtils::MapToTH1D(fDataHist, fMapHist); TH1D* mc_1D = StatUtils::MapToTH1D(fMCHist, fMapHist); TH1I* mask_1D = StatUtils::MapToMask(fMaskHist, fMapHist); data_1D->Write(); mc_1D->Write(); if (mask_1D) { mask_1D->Write(); TMatrixDSym* calc_cov = StatUtils::ApplyInvertedMatrixMasking(covar, mask_1D); 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; // 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 } 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 or fIsProjFitY or 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); 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 (drawSliceCanvYMC or true) { TCanvas* c1 = new TCanvas((fName + "_MC_CANV_Y").c_str(), (fName + "_MC_CANV_Y").c_str(), 800, 600); c1->Divide(int(sqrt(fDataHist->GetNbinsY() + 1)), int(sqrt(fDataHist->GetNbinsY() + 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.6, 0.6, 0.9, 0.9); leg->AddEntry(fDataHist, (fName + " Data").c_str(), "ep"); leg->AddEntry(fMCHist, (fName + " MC").c_str(), "l"); leg->AddEntry(mcShape, (fName + " Shape").c_str(), "l"); leg->Draw("SAME"); /* // Make Y slices for (int i = 0; i < fDataHist->GetNbinY(); i++){ c1->cd(i+2); TH1D* fDataHist_SliceY = PlotUtils::GetSliceY(fDataHist, i); fDataHist_SliceY->Draw("E1"); TH1D* fMCHist_SliceY = PlotUtils::GetSliceY(fMCHist, i); fMCHist_SliceY->Draw("SAME HIST C"); TH1D* mcShape_SliceY = PlotUtils::GetSliceY(mcShape, i); mcShape_SliceY->Draw("SAME HIST C"); } */ c1->Write(); } if (drawWeighted) { fMCWeighted->Write(); } // Returning LOG(SAM) << "Written Histograms: " << fName << std::endl; return; // Returning LOG(SAM) << "Written Histograms: " << fName << std::endl; 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; LOG(SAM) << "Found event rate measurement but fIsRawEvents == false!" << std::endl; LOG(SAM) << "Overriding this and setting fIsRawEvents == true!" << std::endl; } fIsEnu = false; if ((fName.find("XSec") != std::string::npos) && (fName.find("Enu") != std::string::npos)) { fIsEnu = true; LOG(SAM) << "::" << fName << "::" << std::endl; LOG(SAM) << "Found XSec Enu measurement, applying flux integrated scaling, " "not flux averaged!" << std::endl; if (FitPar::Config().GetParB("EventManager")) { ERR(FTL) << "Enu Measurements do not yet work with the Event Manager!" << std::endl; ERR(FTL) << "If you want decent flux unfolded results please run in " "series mode (-q EventManager=0)" << std::endl; sleep(2); } } if (fIsEnu && fIsRawEvents) { LOG(SAM) << "Found 1D Enu XSec distribution AND fIsRawEvents, is this " "really correct?!" << std::endl; LOG(SAM) << "Check experiment constructor for " << fName << " and correct this!" << std::endl; LOG(SAM) << "I live in " << __FILE__ << ":" << __LINE__ << std::endl; exit(-1); } // 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) { ERR(FTL) << "Error! " << dataFile << " is not a .root file" << std::endl; ERR(FTL) << "Currently only .root file reading is supported (MiniBooNE " "CC1pi+ 2D), but implementing .txt should be dirt easy" << std::endl; ERR(FTL) << "See me at " << __FILE__ << ":" << __LINE__ << std::endl; exit(-1); } 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(), ifstream::in); + 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()) LOG(SAM) << "Reading data from: " << dataFile.c_str() << std::endl; 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(), ifstream::in); + std::ifstream error(errorFile.c_str(), std::ifstream::in); if (error.is_open()) LOG(SAM) << "Reading errors from: " << errorFile.c_str() << std::endl; 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); LOG(SAM) << "Reading data from: " << dataFile << std::endl; 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* decmpPlot = new TH2D(); TH2D* covarInvPlot = 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()); covarInvPlot = (TH2D*)tempFile->Get((covName + "covinv").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 ERR(WRN) << " Incorrect thrown_covariance option in parameters." << std::endl; // 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(), ifstream::in); + std::ifstream covar(covarFile.c_str(), std::ifstream::in); this->covar = new TMatrixDSym(dim); fFullCovar = new TMatrixDSym(dim); if (covar.is_open()) LOG(SAM) << "Reading covariance matrix from file: " << covarFile << std::endl; 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(), ifstream::in); + std::ifstream covarread(covarFile.c_str(), std::ifstream::in); TMatrixD* newcov = new TMatrixD(dim, dim); if (covarread.is_open()) LOG(SAM) << "Reading covariance matrix from file: " << covarFile << std::endl; 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/InputHandler/FitEvent.cxx b/src/InputHandler/FitEvent.cxx index 61751f8..50ef1bc 100644 --- a/src/InputHandler/FitEvent.cxx +++ b/src/InputHandler/FitEvent.cxx @@ -1,429 +1,429 @@ // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret /******************************************************************************* * This file is pddrt 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 "FitEvent.h" #include #include "TObjArray.h" FitEvent::FitEvent() { fGenInfo = NULL; kRemoveFSIParticles = true; kRemoveUndefParticles = true; AllocateParticleStack(400); }; void FitEvent::AddGeneratorInfo(GeneratorInfoBase* gen) { fGenInfo = gen; gen->AllocateParticleStack(kMaxParticles); } void FitEvent::AllocateParticleStack(int stacksize) { LOG(DEB) << "Allocating particle stack of size: " << stacksize << std::endl; kMaxParticles = stacksize; fParticleList = new FitParticle*[kMaxParticles]; fParticleMom = new double*[kMaxParticles]; fParticleState = new UInt_t[kMaxParticles]; fParticlePDG = new int[kMaxParticles]; fOrigParticleMom = new double*[kMaxParticles]; fOrigParticleState = new UInt_t[kMaxParticles]; fOrigParticlePDG = new int[kMaxParticles]; for (size_t i = 0; i < kMaxParticles; i++) { fParticleList[i] = NULL; fParticleMom[i] = new double[4]; fOrigParticleMom[i] = new double[4]; } if (fGenInfo) fGenInfo->AllocateParticleStack(kMaxParticles); } void FitEvent::ExpandParticleStack(int stacksize) { DeallocateParticleStack(); AllocateParticleStack(stacksize); } void FitEvent::DeallocateParticleStack() { for (size_t i = 0; i < kMaxParticles; i++) { if (fParticleList[i]) delete fParticleList[i]; delete fParticleMom[i]; delete fOrigParticleMom[i]; } delete fParticleMom; delete fOrigParticleMom; delete fParticleList; delete fParticleState; delete fParticlePDG; delete fOrigParticleState; delete fOrigParticlePDG; if (fGenInfo) fGenInfo->DeallocateParticleStack(); kMaxParticles = 0; } void FitEvent::ClearFitParticles() { for (size_t i = 0; i < kMaxParticles; i++) { fParticleList[i] = NULL; } } void FitEvent::FreeFitParticles() { for (size_t i = 0; i < kMaxParticles; i++) { FitParticle* fp = fParticleList[i]; if (fp) delete fp; fParticleList[i] = NULL; } } void FitEvent::ResetParticleList() { for (unsigned int i = 0; i < kMaxParticles; i++) { FitParticle* fp = fParticleList[i]; if (fp) delete fp; fParticleList[i] = NULL; } } void FitEvent::HardReset() { for (unsigned int i = 0; i < kMaxParticles; i++) { fParticleList[i] = NULL; } } void FitEvent::ResetEvent() { Mode = 9999; fEventNo = -1; fTotCrs = -1.0; fTargetA = -1; fTargetZ = -1; fTargetH = -1; fBound = false; fNParticles = 0; if (fGenInfo) fGenInfo->Reset(); for (unsigned int i = 0; i < kMaxParticles; i++) { if (fParticleList[i]) delete fParticleList[i]; fParticleList[i] = NULL; continue; fParticlePDG[i] = 0; fParticleState[i] = kUndefinedState; fParticleMom[i][0] = 0.0; fParticleMom[i][1] = 0.0; fParticleMom[i][2] = 0.0; fParticleMom[i][3] = 0.0; fOrigParticlePDG[i] = 0; fOrigParticleState[i] = kUndefinedState; fOrigParticleMom[i][0] = 0.0; fOrigParticleMom[i][1] = 0.0; fOrigParticleMom[i][2] = 0.0; fOrigParticleMom[i][3] = 0.0; } } void FitEvent::OrderStack() { // Copy current stack int npart = fNParticles; for (int i = 0; i < npart; i++) { fOrigParticlePDG[i] = fParticlePDG[i]; fOrigParticleState[i] = fParticleState[i]; fOrigParticleMom[i][0] = fParticleMom[i][0]; fOrigParticleMom[i][1] = fParticleMom[i][1]; fOrigParticleMom[i][2] = fParticleMom[i][2]; fOrigParticleMom[i][3] = fParticleMom[i][3]; } // Now run loops for each particle fNParticles = 0; int stateorder[6] = {kInitialState, kFinalState, kFSIState, kNuclearInitial, kNuclearRemnant, kUndefinedState}; for (int s = 0; s < 6; s++) { for (int i = 0; i < npart; i++) { if ((UInt_t)fOrigParticleState[i] != (UInt_t)stateorder[s]) continue; fParticlePDG[fNParticles] = fOrigParticlePDG[i]; fParticleState[fNParticles] = fOrigParticleState[i]; fParticleMom[fNParticles][0] = fOrigParticleMom[i][0]; fParticleMom[fNParticles][1] = fOrigParticleMom[i][1]; fParticleMom[fNParticles][2] = fOrigParticleMom[i][2]; fParticleMom[fNParticles][3] = fOrigParticleMom[i][3]; fNParticles++; } } if (LOG_LEVEL(DEB)) { LOG(DEB) << "Ordered stack" << std::endl; for (int i = 0; i < fNParticles; i++) { LOG(DEB) << "Particle " << i << ". " << fParticlePDG[i] << " " << fParticleMom[i][0] << " " << fParticleMom[i][1] << " " << fParticleMom[i][2] << " " << fParticleMom[i][3] << " " << fParticleState[i] << std::endl; } } if (fNParticles != npart) { ERR(FTL) << "Dropped some particles when ordering the stack!" << std::endl; } return; } void FitEvent::Print() { if (LOG_LEVEL(FIT)) { LOG(FIT) << "FITEvent print" << std::endl; - LOG(FIT) << "Mode: " << Mode << std::endl; + LOG(FIT) << "Mode: " << Mode << ", Weight: " << InputWeight << std::endl; LOG(FIT) << "Particles: " << fNParticles << std::endl; LOG(FIT) << " -> Particle Stack " << std::endl; for (int i = 0; i < fNParticles; i++) { LOG(FIT) << " -> -> " << i << ". " << fParticlePDG[i] << " " << fParticleState[i] << " " << " Mom(" << fParticleMom[i][0] << ", " << fParticleMom[i][1] << ", " << fParticleMom[i][2] << ", " << fParticleMom[i][3] << ")." << std::endl; } } return; } /* Read/Write own event class */ void FitEvent::SetBranchAddress(TChain* tn) { tn->SetBranchAddress("Mode", &Mode); tn->SetBranchAddress("EventNo", &fEventNo); tn->SetBranchAddress("TotCrs", &fTotCrs); tn->SetBranchAddress("TargetA", &fTargetA); tn->SetBranchAddress("TargetH", &fTargetH); tn->SetBranchAddress("Bound", &fBound); tn->SetBranchAddress("RWWeight", &SavedRWWeight); tn->SetBranchAddress("InputWeight", &InputWeight); } void FitEvent::AddBranchesToTree(TTree* tn) { tn->Branch("Mode", &Mode, "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("RWWeight", &RWWeight, "RWWeight/D"); tn->Branch("InputWeight", &InputWeight, "InputWeight/D"); tn->Branch("NParticles", &fNParticles, "NParticles/I"); tn->Branch("ParticleState", fOrigParticleState, "ParticleState[NParticles]/i"); tn->Branch("ParticlePDG", fOrigParticlePDG, "ParticlePDG[NParticles]/I"); tn->Branch("ParticleMom", fOrigParticleMom, "ParticleMom[NParticles][4]/D"); } // ------- EVENT ACCESS FUNCTION --------- // TLorentzVector FitEvent::GetParticleP4(int index) const { if (index == -1 or index >= fNParticles) return TLorentzVector(); return TLorentzVector(fParticleMom[index][0], fParticleMom[index][1], fParticleMom[index][2], fParticleMom[index][3]); } TVector3 FitEvent::GetParticleP3(int index) const { if (index == -1 or index >= fNParticles) return TVector3(); return TVector3(fParticleMom[index][0], fParticleMom[index][1], fParticleMom[index][2]); } double FitEvent::GetParticleMom(int index) const { if (index == -1 or index >= fNParticles) return 0.0; return sqrt(fParticleMom[index][0] * fParticleMom[index][0] + fParticleMom[index][1] * fParticleMom[index][1] + fParticleMom[index][2] * fParticleMom[index][2]); } double FitEvent::GetParticleMom2(int index) const { if (index == -1 or index >= fNParticles) return 0.0; return fabs((fParticleMom[index][0] * fParticleMom[index][0] + fParticleMom[index][1] * fParticleMom[index][1] + fParticleMom[index][2] * fParticleMom[index][2])); } double FitEvent::GetParticleE(int index) const { if (index == -1 or index >= fNParticles) return 0.0; return fParticleMom[index][3]; } int FitEvent::GetParticleState(int index) const { if (index == -1 or index >= fNParticles) return kUndefinedState; return (fParticleState[index]); } int FitEvent::GetParticlePDG(int index) const { if (index == -1 or index >= fNParticles) return 0; return (fParticlePDG[index]); } FitParticle* FitEvent::GetParticle(int const i) { // Check Valid Index if (i == -1) { return NULL; } // Check Valid if (i > fNParticles) { ERR(FTL) << "Requesting particle beyond stack!" << std::endl << "i = " << i << " N = " << fNParticles << std::endl << "Mode = " << Mode << std::endl; throw; } if (!fParticleList[i]) { /* std::cout << "Creating particle with values i " << i << " "; std::cout << fParticleMom[i][0] << " " << fParticleMom[i][1] << " " << fParticleMom[i][2] << " " << fParticleMom[i][3] << " "; std::cout << fParticlePDG[i] << " " << fParticleState[i] << std::endl; */ fParticleList[i] = new FitParticle(fParticleMom[i][0], fParticleMom[i][1], fParticleMom[i][2], fParticleMom[i][3], fParticlePDG[i], fParticleState[i]); } else { /* std::cout << "Filling particle with values i " << i << " "; std::cout << fParticleMom[i][0] << " " << fParticleMom[i][1] << " " << fParticleMom[i][2] << " " << fParticleMom[i][3] << " "; std::cout << fParticlePDG[i] << " "<< fParticleState[i] <SetValues(fParticleMom[i][0], fParticleMom[i][1], fParticleMom[i][2], fParticleMom[i][3], fParticlePDG[i], fParticleState[i]); } return fParticleList[i]; } bool FitEvent::HasParticle(int const pdg, int const state) const { bool found = false; for (int i = 0; i < fNParticles; i++) { if (state != -1 && fParticleState[i] != (uint)state) continue; if (fParticlePDG[i] == pdg) found = true; } return found; } int FitEvent::NumParticle(int const pdg, int const state) const { int nfound = 0; for (int i = 0; i < fNParticles; i++) { if (state != -1 and fParticleState[i] != (uint)state) continue; if (pdg == 0 or fParticlePDG[i] == pdg) nfound += 1; } return nfound; } std::vector FitEvent::GetAllParticleIndices(int const pdg, int const state) const { std::vector indexlist; for (int i = 0; i < fNParticles; i++) { if (state != -1 and fParticleState[i] != (uint)state) continue; if (pdg == 0 or fParticlePDG[i] == pdg) { indexlist.push_back(i); } } return indexlist; } std::vector FitEvent::GetAllParticle(int const pdg, int const state) { std::vector indexlist = GetAllParticleIndices(pdg, state); std::vector plist; for (std::vector::iterator iter = indexlist.begin(); iter != indexlist.end(); iter++) { plist.push_back(GetParticle((*iter))); } return plist; } int FitEvent::GetHMParticleIndex(int const pdg, int const state) const { double maxmom2 = -9999999.9; int maxind = -1; for (int i = 0; i < fNParticles; i++) { if (state != -1 and fParticleState[i] != (uint)state) continue; if (pdg == 0 or fParticlePDG[i] == pdg) { double newmom2 = GetParticleMom2(i); if (newmom2 > maxmom2) { maxind = i; maxmom2 = newmom2; } } } return maxind; } int FitEvent::GetBeamNeutrinoIndex(void) const { for (int i = 0; i < fNParticles; i++) { if (fParticleState[i] != kInitialState) continue; int pdg = abs(fParticlePDG[i]); if (pdg == 12 or pdg == 14 or pdg == 16) { return i; } } return 0; } int FitEvent::GetBeamElectronIndex(void) const { return GetHMISParticleIndex(11); } int FitEvent::GetBeamPionIndex(void) const { return GetHMISParticleIndex(PhysConst::pdg_pions); } int FitEvent::NumFSMesons() { int nMesons = 0; for (int i = 0; i < fNParticles; i++) { if (fParticleState[i] != kFinalState) continue; if (abs(fParticlePDG[i]) >= 111 && abs(fParticlePDG[i]) <= 557) nMesons += 1; } return nMesons; } int FitEvent::NumFSLeptons(void) const { int nLeptons = 0; for (int i = 0; i < fNParticles; i++) { if (fParticleState[i] != kFinalState) continue; if (abs(fParticlePDG[i]) == 11 || abs(fParticlePDG[i]) == 13 || abs(fParticlePDG[i]) == 15) nLeptons += 1; } return nLeptons; } diff --git a/src/InputHandler/GIBUUInputHandler.cxx b/src/InputHandler/GIBUUInputHandler.cxx index c0e8724..f61559f 100644 --- a/src/InputHandler/GIBUUInputHandler.cxx +++ b/src/InputHandler/GIBUUInputHandler.cxx @@ -1,301 +1,302 @@ #ifdef __GiBUU_ENABLED__ #include "GIBUUInputHandler.h" #include "InputUtils.h" GIBUUGeneratorInfo::~GIBUUGeneratorInfo() { DeallocateParticleStack(); } void GIBUUGeneratorInfo::AddBranchesToTree(TTree* tn) { // tn->Branch("NEUTParticleN", fNEUTParticleN, "NEUTParticleN/I"); // tn->Branch("NEUTParticleStatusCode", fNEUTParticleStatusCode, // "NEUTParticleStatusCode[NEUTParticleN]/I"); // tn->Branch("NEUTParticleAliveCode", fNEUTParticleAliveCode, // "NEUTParticleAliveCode[NEUTParticleN]/I"); } void GIBUUGeneratorInfo::SetBranchesFromTree(TTree* tn) { // tn->SetBranchAddress("NEUTParticleN", &fNEUTParticleN ); // tn->SetBranchAddress("NEUTParticleStatusCode", &fNEUTParticleStatusCode ); // tn->SetBranchAddress("NEUTParticleAliveCode", &fNEUTParticleAliveCode ); } void GIBUUGeneratorInfo::AllocateParticleStack(int stacksize) { // fNEUTParticleN = 0; // fNEUTParticleStatusCode = new int[stacksize]; // fNEUTParticleStatusCode = new int[stacksize]; } void GIBUUGeneratorInfo::DeallocateParticleStack() { // delete fNEUTParticleStatusCode; // delete fNEUTParticleAliveCode; } void GIBUUGeneratorInfo::FillGeneratorInfo(GiBUUStdHepReader* nevent) { Reset(); // for (int i = 0; i < nevent->Npart(); i++) { // fNEUTParticleStatusCode[i] = nevent->PartInfo(i)->fStatus; // fNEUTParticleAliveCode[i] = nevent->PartInfo(i)->fIsAlive; // fNEUTParticleN++; // } } void GIBUUGeneratorInfo::Reset() { // for (int i = 0; i < fNEUTParticleN; i++) { // fNEUTParticleStatusCode[i] = -1; // fNEUTParticleAliveCode[i] = 9; // } // fNEUTParticleN = 0; } GIBUUInputHandler::GIBUUInputHandler(std::string const& handle, std::string const& rawinputs) { LOG(SAM) << "Creating GiBUUInputHandler : " << handle << std::endl; // Run a joint input handling fName = handle; fEventType = kGiBUU; fGIBUUTree = new TChain("giRooTracker"); // Loop over all inputs and grab flux, eventhist, and nevents std::vector inputs = InputUtils::ParseInputFileList(rawinputs); for (size_t inp_it = 0; inp_it < inputs.size(); ++inp_it) { // Open File for histogram access LOG(SAM) << "Opening event file " << inputs[inp_it] << std::endl; TFile* inp_file = new TFile(inputs[inp_it].c_str(), "READ"); if ((!inp_file) || (!inp_file->IsOpen())) { THROW("GiBUU file !IsOpen() at : '" << inputs[inp_it] << "'" << std::endl << "Check that your file paths are correct and the file exists!"); } int NFluxes = bool(dynamic_cast(inp_file->Get("numu_flux"))) + bool(dynamic_cast(inp_file->Get("numub_flux"))) + bool(dynamic_cast(inp_file->Get("nue_flux"))) + bool(dynamic_cast(inp_file->Get("nueb_flux"))) + bool(dynamic_cast(inp_file->Get("e_flux"))); if (NFluxes != 1) { THROW("Found " << NFluxes << " input fluxes in " << inputs[inp_it] << ". The NUISANCE GiBUU interface expects to be " "passed multiple species vectors as separate " "input files like: " "\"GiBUU:(MINERVA_FHC_numu_evts.root,MINERVA_FHC_" "numubar_evts.root,[...])\""); } // Get Flux/Event hist TH1D* fluxhist = dynamic_cast(inp_file->Get("flux")); TH1D* eventhist = dynamic_cast(inp_file->Get("evt")); if (!fluxhist || !eventhist) { ERROR(FTL, "Input File Contents: " << inputs[inp_it]); inp_file->ls(); THROW( "GiBUU FILE doesn't contain flux/xsec info. You may have to " "regenerate your MC!"); } // Get N Events TTree* giRooTracker = dynamic_cast(inp_file->Get("giRooTracker")); if (!giRooTracker) { ERROR(FTL, "giRooTracker Tree not located in NEUT file: " << inputs[inp_it]); THROW("Check your inputs, they may need to be completely regenerated!"); throw; } int nevents = giRooTracker->GetEntries(); if (nevents <= 0) { THROW("Trying to a TTree with " << nevents << " to TChain from : " << inputs[inp_it]); } // Register input to form flux/event rate hists RegisterJointInput(inputs[inp_it], nevents, fluxhist, eventhist); // Add To TChain fGIBUUTree->AddFile(inputs[inp_it].c_str()); } // Registor all our file inputs SetupJointInputs(); // Create Fit Event fNUISANCEEvent = new FitEvent(); fGiReader = new GiBUUStdHepReader(); fGiReader->SetBranchAddresses(fGIBUUTree); fNUISANCEEvent->HardReset(); }; FitEvent* GIBUUInputHandler::GetNuisanceEvent(const UInt_t entry, const bool lightweight) { // Check out of bounds if (entry >= (UInt_t)fNEvents) return NULL; // Read Entry from TTree to fill NEUT Vect in BaseFitEvt; fGIBUUTree->GetEntry(entry); // Run NUISANCE Vector Filler if (!lightweight) { CalcNUISANCEKinematics(); } #ifdef __PROB3PP_ENABLED__ else { for (int i = 0; i < fGiReader->StdHepN; i++) { int state = GetGIBUUParticleStatus(fGiReader->StdHepStatus[i], fGiReader->StdHepPdg[i]); if (state != kInitialState) { continue; } if (std::count(PhysConst::pdg_neutrinos, PhysConst::pdg_neutrinos + 4, fGiReader->StdHepPdg[i])) { fNUISANCEEvent->probe_E = fGiReader->StdHepP4[i][3] * 1.E3; fNUISANCEEvent->probe_pdg = fGiReader->StdHepPdg[i]; break; } } } #endif fNUISANCEEvent->InputWeight *= GetInputWeight(entry); + fNUISANCEEvent->GiRead = fGiReader; return fNUISANCEEvent; } int GetGIBUUParticleStatus(int status, int pdg) { int state = kUndefinedState; switch (status) { case 0: // Incoming case 11: // Struck nucleon state = kInitialState; break; case 1: // Good Final State state = kFinalState; break; default: // Other break; } // Set Nuclear States Flag if (pdg > 1000000) { if (state == kInitialState) state = kNuclearInitial; else if (state == kFinalState) state = kNuclearRemnant; else state = kUndefinedState; } return state; } void GIBUUInputHandler::CalcNUISANCEKinematics() { // Reset all variables fNUISANCEEvent->ResetEvent(); FitEvent* evt = fNUISANCEEvent; evt->Mode = fGiReader->GiBUU2NeutCode; evt->fEventNo = 0.0; evt->fTotCrs = 0; evt->fTargetA = 0.0; // Change to get these from nuclear remnant. evt->fTargetZ = 0.0; evt->fTargetH = 0; evt->fBound = 0.0; // Extra GiBUU Input Weight evt->InputWeight = fGiReader->EvtWght; // Check Stack N int npart = fGiReader->StdHepN; int kmax = evt->kMaxParticles; if ((UInt_t)npart > (UInt_t)kmax) { ERROR(WRN, "GiBUU has too many particles. Expanding Stack."); fNUISANCEEvent->ExpandParticleStack(npart); } // Create Stack evt->fNParticles = 0; for (int i = 0; i < npart; i++) { // State int state = GetGIBUUParticleStatus(fGiReader->StdHepStatus[i], fGiReader->StdHepPdg[i]); int curpart = evt->fNParticles; // Set State evt->fParticleState[evt->fNParticles] = state; // Mom evt->fParticleMom[curpart][0] = fGiReader->StdHepP4[i][0] * 1.E3; evt->fParticleMom[curpart][1] = fGiReader->StdHepP4[i][1] * 1.E3; evt->fParticleMom[curpart][2] = fGiReader->StdHepP4[i][2] * 1.E3; evt->fParticleMom[curpart][3] = fGiReader->StdHepP4[i][3] * 1.E3; // PDG evt->fParticlePDG[curpart] = fGiReader->StdHepPdg[i]; // Add to total particles evt->fNParticles++; } // Run Initial, FSI, Final, Other ordering. fNUISANCEEvent->OrderStack(); FitParticle* ISNeutralLepton = fNUISANCEEvent->GetHMISParticle(PhysConst::pdg_neutrinos); if (ISNeutralLepton) { fNUISANCEEvent->probe_E = ISNeutralLepton->E(); fNUISANCEEvent->probe_pdg = ISNeutralLepton->PDG(); } return; } void GIBUUInputHandler::Print() {} void GIBUUInputHandler::SetupJointInputs() { if (jointeventinputs.size() <= 1) { jointinput = false; } else if (jointeventinputs.size() > 1) { jointinput = true; jointindexswitch = 0; } fMaxEvents = FitPar::Config().GetParI("MAXEVENTS"); if (fMaxEvents != -1 and jointeventinputs.size() > 1) { THROW("Can only handle joint inputs when config MAXEVENTS = -1!"); } for (size_t i = 0; i < jointeventinputs.size(); i++) { double scale = double(fNEvents) / fEventHist->Integral("width"); scale *= jointfluxinputs.at(i)->Integral("width"); jointindexscale.push_back(scale); } fEventHist->SetNameTitle((fName + "_EVT").c_str(), (fName + "_EVT").c_str()); fFluxHist->SetNameTitle((fName + "_FLUX").c_str(), (fName + "_FLUX").c_str()); // Setup Max Events if (fMaxEvents > 1 && fMaxEvents < fNEvents) { if (LOG_LEVEL(SAM)) { std::cout << "\t\t|-> Read Max Entries : " << fMaxEvents << std::endl; } fNEvents = fMaxEvents; } // Print out Status if (LOG_LEVEL(SAM)) { std::cout << "\t\t|-> Total Entries : " << fNEvents << std::endl << "\t\t|-> Event Integral : " << fEventHist->Integral("width") * 1.E-38 << " events/nucleon" << std::endl << "\t\t|-> Flux Integral : " << fFluxHist->Integral("width") << " /cm2" << std::endl << "\t\t|-> Event/Flux : " << fEventHist->Integral("width") * 1.E-38 / fFluxHist->Integral("width") << " cm2/nucleon" << std::endl; } } #endif diff --git a/src/InputHandler/InputHandler.cxx b/src/InputHandler/InputHandler.cxx index b400590..80e9f65 100644 --- a/src/InputHandler/InputHandler.cxx +++ b/src/InputHandler/InputHandler.cxx @@ -1,267 +1,301 @@ // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret /******************************************************************************* * This file is part of NUISANCE. * * NUISANCE is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * NUISANCE is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with NUISANCE. If not, see . *******************************************************************************/ #include "InputHandler.h" #include "InputUtils.h" InputHandlerBase::InputHandlerBase() { fName = ""; fFluxHist = NULL; fEventHist = NULL; fNEvents = 0; fNUISANCEEvent = NULL; fBaseEvent = NULL; kRemoveUndefParticles = FitPar::Config().GetParB("RemoveUndefParticles"); kRemoveFSIParticles = FitPar::Config().GetParB("RemoveFSIParticles"); kRemoveNuclearParticles = FitPar::Config().GetParB("RemoveNuclearParticles"); fMaxEvents = FitPar::Config().GetParI("MAXEVENTS"); fTTreePerformance = NULL; }; InputHandlerBase::~InputHandlerBase() { if (fFluxHist) delete fFluxHist; if (fEventHist) delete fEventHist; // if (fXSecHist) delete fXSecHist; // if (fNUISANCEEvent) delete fNUISANCEEvent; jointfluxinputs.clear(); jointeventinputs.clear(); jointindexlow.clear(); jointindexhigh.clear(); jointindexallowed.clear(); jointindexscale.clear(); // if (fTTreePerformance) { // fTTreePerformance->SaveAs(("ttreeperfstats_" + fName + // ".root").c_str()); // } } void InputHandlerBase::Print(){}; TH1D* InputHandlerBase::GetXSecHistogram(void) { fXSecHist = (TH1D*)fFluxHist->Clone(); fXSecHist->Divide(fEventHist); return fXSecHist; }; double InputHandlerBase::PredictedEventRate(double low, double high, std::string intOpt) { - int minBin = fFluxHist->GetXaxis()->FindBin(low); - int maxBin = fFluxHist->GetXaxis()->FindBin(high); + Int_t minBin = fEventHist->GetXaxis()->FindFixBin(low); + Int_t maxBin = fEventHist->GetXaxis()->FindFixBin(high); - return fEventHist->Integral(minBin, maxBin + 1, intOpt.c_str()); + 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() + 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; - // return fFluxHist->Integral(minBin + 1, maxBin - 1, intOpt.c_str()); } std::vector InputHandlerBase::GetFluxList(void) { return std::vector(1, fFluxHist); }; std::vector InputHandlerBase::GetEventList(void) { return std::vector(1, fEventHist); }; std::vector InputHandlerBase::GetXSecList(void) { return std::vector(1, GetXSecHistogram()); }; FitEvent* InputHandlerBase::FirstNuisanceEvent() { fCurrentIndex = 0; return GetNuisanceEvent(fCurrentIndex); }; FitEvent* InputHandlerBase::NextNuisanceEvent() { fCurrentIndex++; if ((fMaxEvents != -1) && (fCurrentIndex > fMaxEvents)) { 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) { THROW("Can only handle joint inputs when config MAXEVENTS = -1!"); } if (jointeventinputs.size() > 1) { ERROR(WRN, "GiBUU sample contains multiple inputs. This will only work for " "samples that expect multi-species inputs. If this sample does, you " "can ignore this warning."); } for (size_t i = 0; i < jointeventinputs.size(); i++) { double scale = double(fNEvents) / fEventHist->Integral("width"); scale *= 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) { 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/InputHandler.h b/src/InputHandler/InputHandler.h index 3377403..1110091 100644 --- a/src/InputHandler/InputHandler.h +++ b/src/InputHandler/InputHandler.h @@ -1,145 +1,145 @@ // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret /******************************************************************************* * This file is part of NUISANCE. * * NUISANCE is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * NUISANCE is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with NUISANCE. If not, see . *******************************************************************************/ #ifndef INPUTHANDLER2_H #define INPUTHANDLER2_H /*! * \addtogroup InputHandler * @{ */ #include "TH1D.h" #include "FitEvent.h" #include "BaseFitEvt.h" #include "TTreePerfStats.h" /// Base InputHandler class defining how events are requested and setup. class InputHandlerBase { public: /// Base constructor resets everything to default InputHandlerBase(); /// Removes flux/event rate histograms virtual ~InputHandlerBase(); /// Return NUISANCE FitEvent Class from given event entry. /// Must be overriden by GeneratorInputHandler. Lightweight allows a faster option /// to be given where only RW information is needed. virtual FitEvent* GetNuisanceEvent(const UInt_t entry, const bool lightweight=false) = 0; /// Calls GetNuisanceEvent(entry, TRUE); virtual BaseFitEvt* GetBaseEvent(const UInt_t entry); /// Print current event information virtual void Print(); /// Return handler ID inline std::string GetName (void) {return fName; }; /// Return Handler Event Type Index inline int GetType (void) {return fEventType;}; /// Get Total Number of Events being Handled inline virtual int GetNEvents (void) {return fNEvents; }; /// Get the Total Flux Histogram these events were generated with inline virtual TH1D* GetFluxHistogram (void) {return fFluxHist; }; /// Get the Total Event Histogram these events were generated with inline virtual TH1D* GetEventHistogram (void) {return fEventHist;}; /// Get the Total Cross-section Histogram (EventHist/FluxHist) virtual TH1D* GetXSecHistogram(void); /// Return all Flux Histograms for all InputFiles. virtual std::vector GetFluxList(void); /// Return all Event Histograms for all InputFiles virtual std::vector GetEventList(void); /// Return all Xsec Histograms for all InputFiles virtual std::vector GetXSecList(void); /// Placeholder to create a cache to speed up reads in GeneratorInputHandler inline virtual void CreateCache(){}; /// Placeholder to remove optional cache to free up memory inline virtual void RemoveCache(){}; /// Return starting NUISANCE event pointer (entry=0) FitEvent* FirstNuisanceEvent(); /// Iterate to next NUISANCE event. Returns NULL when entry > fNEvents. FitEvent* NextNuisanceEvent(); /// Returns starting Base Event Pointer (entry=0) BaseFitEvt* FirstBaseEvent(); /// Iterate to next NUISANCE Base Event. Returns NULL when entry > fNEvents. BaseFitEvt* NextBaseEvent(); /// Register an input file and update event/flux information virtual void RegisterJointInput(std::string input, int n, TH1D* f, TH1D* e); /// Finalise setup of Input event/flux information and calculate /// joint input weights if joint input is provided. virtual void SetupJointInputs(); /// Calculate a weight for the event given the joint input information. /// Used to scale the relative proportion of multiple inputs correctly /// with respect to one another. virtual double GetInputWeight(int entry); /// Returns the total predicted event rate for this input given the /// low and high energy ranges. intOpt specifies the option the ROOT /// TH1D integral should use. e.g. "" or "width" - double PredictedEventRate(double low, double high, - std::string intOpt); + double PredictedEventRate(double low = -9999.9, double high = -9999.9, + std::string intOpt = ""); /// Returns the total generated flux for this input given the /// low and high energy ranges. intOpt specifies the option the ROOT /// TH1D integral should use. e.g. "" or "width" double TotalIntegratedFlux(double low = -9999.9, double high = -9999.9, std::string intOpt = ""); /// Actual data members. std::vector jointfluxinputs; std::vector jointeventinputs; std::vector jointindexlow; std::vector jointindexhigh; std::vector jointindexallowed; size_t jointindexswitch; bool jointinput; std::vector jointindexscale; std::string fName; TH1D* fFluxHist; TH1D* fEventHist; TH1D* fXSecHist; int fNEvents; int fMaxEvents; FitEvent* fNUISANCEEvent; BaseFitEvt* fBaseEvent; int fEventType; int fCurrentIndex; int fCacheSize; bool kRemoveUndefParticles; bool kRemoveFSIParticles; bool kRemoveNuclearParticles; TTreePerfStats* fTTreePerformance; }; /*! @} */ #endif diff --git a/src/InputHandler/InteractionModes.h b/src/InputHandler/InteractionModes.h index f381f30..22d6adf 100644 --- a/src/InputHandler/InteractionModes.h +++ b/src/InputHandler/InteractionModes.h @@ -1,91 +1,121 @@ // 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 . -*******************************************************************************/ + * 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 INTERACTION_MODES_H #define INTERACTION_MODES_H +#include + namespace InputHandler { enum InteractionModes { - kCCQE = 1, - kCC2p2h = 2, - kCC1piponp = 11, - kCC1pi0onn = 12, - kCC1piponn = 13, - kCCCoherent = 16, - kCC1gamma = 17, - kCCmultipi = 21, - kCC1etaonn = 22, - kCC1kaonp = 23, - kCCDIS = 26, - kNC1pi0onn = 31, - kNC1pi0onp = 32, - kNC1pimonn = 33, - kNC1piponp = 34, - kNCCoherent = 36, - kNC1gamman = 38, - kNC1gammap = 39, - kNCmultipi = 41, - kNC1etaonn = 42, - kNC1etaonp = 43, - kNC1kaon0 = 44, - kNC1kaonp = 45, - kNCDIS = 46, - kNCELonp = 51, - kNCELonn = 52, - kNC2p2h = 53 -} + kCCQE = 1, + kCC2p2h = 2, + kCC1piponp = 11, + kCC1pi0onn = 12, + kCC1piponn = 13, + kCCCoherent = 16, + kCC1gamma = 17, + kCCmultipi = 21, + kCC1etaonn = 22, + kCC1kaonp = 23, + kCCDIS = 26, + kNC1pi0onn = 31, + kNC1pi0onp = 32, + kNC1pimonn = 33, + kNC1piponp = 34, + kNCCoherent = 36, + kNC1gamman = 38, + kNC1gammap = 39, + kNCmultipi = 41, + kNC1etaonn = 42, + kNC1etaonp = 43, + kNC1kaon0 = 44, + kNC1kaonp = 45, + kNCDIS = 46, + kNCELonp = 51, + kNCELonn = 52, + kNC2p2h = 53 +}; } -inline std::ostream &operator<<(std::ostream &os, InputHandler::InteractionModes it) { - - switch(it){ - case InputHandler::kCCQE: return os << "CCQE"; - case InputHandler::kCC2p2h: return os << "CC2p2h"; - case InputHandler::kCC1piponp: return os << "CC1piponp"; - case InputHandler::kCC1pi0onn: return os << "CC1pi0onn"; - case InputHandler::kCC1piponn: return os << "CC1piponn"; - case InputHandler::kCCCoherent: return os << "CCCoherent"; - case InputHandler::kCC1gamma: return os << "CC1gamma"; - case InputHandler::kCCmultipi: return os << "CCmultipi"; - case InputHandler::kCC1etaonn: return os << "CC1etaonn"; - case InputHandler::kCC1kaonp: return os << "CC1kaonp"; - case InputHandler::kCCDIS: return os << "CCDIS"; - case InputHandler::kNC1pi0onn: return os << "NC1pi0onn"; - case InputHandler::kNC1pi0onp: return os << "NC1pi0onp"; - case InputHandler::kNC1pimonn: return os << "NC1pimonn"; - case InputHandler::kNC1piponp: return os << "NC1piponp"; - case InputHandler::kNCCoherent: return os << "NCCoherent"; - case InputHandler::kNC1gamman: return os << "NC1gamman"; - case InputHandler::kNC1gammap: return os << "NC1gammap"; - case InputHandler::kNCmultipi: return os << "NCmultipi"; - case InputHandler::kNC1etaonn: return os << "NC1etaonn"; - case InputHandler::kNC1etaonp: return os << "NC1etaonp"; - case InputHandler::kNC1kaon0: return os << "NC1kaon0"; - case InputHandler::kNC1kaonp: return os << "NC1kaonp"; - case InputHandler::kNCDIS: return os << "NCDIS"; - case InputHandler::kNCELonp: return os << "NCELonp"; - case InputHandler::kNCELonn: return os << "NCELonn"; - case InputHandler::kNC2p2h: return os << "NC2p2h"; - default: return os << "UNKNOWN"; - } - return os << "UNKNOWN"; +inline std::ostream &operator<<(std::ostream &os, + InputHandler::InteractionModes it) { + switch (it) { + case InputHandler::kCCQE: + return os << "CCQE"; + case InputHandler::kCC2p2h: + return os << "CC2p2h"; + case InputHandler::kCC1piponp: + return os << "CC1piponp"; + case InputHandler::kCC1pi0onn: + return os << "CC1pi0onn"; + case InputHandler::kCC1piponn: + return os << "CC1piponn"; + case InputHandler::kCCCoherent: + return os << "CCCoherent"; + case InputHandler::kCC1gamma: + return os << "CC1gamma"; + case InputHandler::kCCmultipi: + return os << "CCmultipi"; + case InputHandler::kCC1etaonn: + return os << "CC1etaonn"; + case InputHandler::kCC1kaonp: + return os << "CC1kaonp"; + case InputHandler::kCCDIS: + return os << "CCDIS"; + case InputHandler::kNC1pi0onn: + return os << "NC1pi0onn"; + case InputHandler::kNC1pi0onp: + return os << "NC1pi0onp"; + case InputHandler::kNC1pimonn: + return os << "NC1pimonn"; + case InputHandler::kNC1piponp: + return os << "NC1piponp"; + case InputHandler::kNCCoherent: + return os << "NCCoherent"; + case InputHandler::kNC1gamman: + return os << "NC1gamman"; + case InputHandler::kNC1gammap: + return os << "NC1gammap"; + case InputHandler::kNCmultipi: + return os << "NCmultipi"; + case InputHandler::kNC1etaonn: + return os << "NC1etaonn"; + case InputHandler::kNC1etaonp: + return os << "NC1etaonp"; + case InputHandler::kNC1kaon0: + return os << "NC1kaon0"; + case InputHandler::kNC1kaonp: + return os << "NC1kaonp"; + case InputHandler::kNCDIS: + return os << "NCDIS"; + case InputHandler::kNCELonp: + return os << "NCELonp"; + case InputHandler::kNCELonn: + return os << "NCELonn"; + case InputHandler::kNC2p2h: + return os << "NC2p2h"; + default: + return os << "UNKNOWN"; + } + return os << "UNKNOWN"; } #endif diff --git a/src/InputHandler/NuWroInputHandler.cxx b/src/InputHandler/NuWroInputHandler.cxx index f4c62ee..384a326 100644 --- a/src/InputHandler/NuWroInputHandler.cxx +++ b/src/InputHandler/NuWroInputHandler.cxx @@ -1,473 +1,479 @@ #ifdef __NUWRO_ENABLED__ #include "NuWroInputHandler.h" #include "InputUtils.h" NuWroGeneratorInfo::~NuWroGeneratorInfo() { delete fNuWroParticlePDGs; } void NuWroGeneratorInfo::AddBranchesToTree(TTree* tn) { tn->Branch("NuWroParticlePDGs", &fNuWroParticlePDGs, "NuWroParticlePDGs/I"); } void NuWroGeneratorInfo::SetBranchesFromTree(TTree* tn) { tn->SetBranchAddress("NuWroParticlePDGs", &fNuWroParticlePDGs); } void NuWroGeneratorInfo::AllocateParticleStack(int stacksize) { fNuWroParticlePDGs = new int[stacksize]; } void NuWroGeneratorInfo::DeallocateParticleStack() { delete fNuWroParticlePDGs; } void NuWroGeneratorInfo::FillGeneratorInfo(event* e) { Reset(); } void NuWroGeneratorInfo::Reset() { for (int i = 0; i < kMaxParticles; i++) { fNuWroParticlePDGs[i] = 0; } } int event1_nof(event* e, int pdg) { int c = 0; for (size_t i = 0; i < e->out.size(); i++) if (e->out[i].pdg == pdg) c++; return c; } NuWroInputHandler::NuWroInputHandler(std::string const& handle, std::string const& rawinputs) { LOG(SAM) << "Creating NuWroInputHandler : " << handle << std::endl; // Run a joint input handling fName = handle; fMaxEvents = FitPar::Config().GetParI("MAXEVENTS"); fSaveExtra = false; // FitPar::Config().GetParB("NuWroSaveExtra"); // Setup the TChain fNuWroTree = new TChain("treeout"); // Loop over all inputs and grab flux, eventhist, and nevents std::vector inputs = InputUtils::ParseInputFileList(rawinputs); for (size_t inp_it = 0; inp_it < inputs.size(); ++inp_it) { // Open File for histogram access TFile* inp_file = new TFile(inputs[inp_it].c_str(), "READ"); if (!inp_file or inp_file->IsZombie()) { ERR(FTL) << "nuwro File IsZombie() at " << inputs[inp_it] << std::endl; throw; } // Get Flux/Event hist TH1D* fluxhist = (TH1D*)inp_file->Get( (PlotUtils::GetObjectWithName(inp_file, "FluxHist")).c_str()); TH1D* eventhist = (TH1D*)inp_file->Get( (PlotUtils::GetObjectWithName(inp_file, "EvtHist")).c_str()); if (!fluxhist or !eventhist) { ERR(FTL) << "nuwro FILE doesn't contain flux/xsec info" << std::endl; if (FitPar::Config().GetParB("regennuwro")) { ERR(FTL) << "Regen NuWro has not been added yet. Email the developers!" << std::endl; // ProcessNuWroInputFlux(inputs[inp_it]); throw; } else { ERR(FTL) << "If you would like NUISANCE to generate these for you " << "please set parameter regennuwro=1 and re-run." << std::endl; throw; } } // Get N Events TTree* nuwrotree = (TTree*)inp_file->Get("treeout"); if (!nuwrotree) { ERR(FTL) << "treeout not located in nuwro file! " << inputs[inp_it] << std::endl; throw; } int nevents = nuwrotree->GetEntries(); // Register input to form flux/event rate hists RegisterJointInput(inputs[inp_it], nevents, fluxhist, eventhist); // Add to TChain fNuWroTree->Add(inputs[inp_it].c_str()); } // Registor all our file inputs SetupJointInputs(); // Setup Events fNuWroEvent = NULL; fNuWroTree->SetBranchAddress("e", &fNuWroEvent); fNuWroTree->GetEntry(0); fNUISANCEEvent = new FitEvent(); fNUISANCEEvent->fType = kNUWRO; fNUISANCEEvent->fNuwroEvent = fNuWroEvent; fNUISANCEEvent->HardReset(); if (fSaveExtra) { fNuWroInfo = new NuWroGeneratorInfo(); fNUISANCEEvent->AddGeneratorInfo(fNuWroInfo); } }; NuWroInputHandler::~NuWroInputHandler() { if (fNuWroTree) delete fNuWroTree; } void NuWroInputHandler::CreateCache() { // fNuWroTree->SetCacheEntryRange(0, fNEvents); // fNuWroTree->AddBranchToCache("*", 1); // fNuWroTree->SetCacheSize(fCacheSize); } void NuWroInputHandler::RemoveCache() { // fNuWroTree->SetCacheEntryRange(0, fNEvents); // fNuWroTree->AddBranchToCache("*", 0); // fNuWroTree->SetCacheSize(0); } void NuWroInputHandler::ProcessNuWroInputFlux(const std::string file) {} FitEvent* NuWroInputHandler::GetNuisanceEvent(const UInt_t entry, const bool lightweight) { // Catch too large entries if (entry >= (UInt_t)fNEvents) return NULL; // Read Entry from TTree to fill NEUT Vect in BaseFitEvt; fNuWroTree->GetEntry(entry); // Run NUISANCE Vector Filler if (!lightweight) { CalcNUISANCEKinematics(); } #ifdef __PROB3PP_ENABLED__ for (size_t i = 0; i < fNUISANCEEvent->fNuwroEvent->in.size(); i++) { if (std::count(PhysConst::pdg_neutrinos, PhysConst::pdg_neutrinos + 4, fNUISANCEEvent->fNuwroEvent->in[i].pdg)) { fNUISANCEEvent->probe_E = fNUISANCEEvent->fNuwroEvent->in[i].t; fNUISANCEEvent->probe_pdg = fNUISANCEEvent->fNuwroEvent->in[i].pdg; break; } } #endif // Setup Input scaling for joint inputs fNUISANCEEvent->InputWeight = GetInputWeight(entry); #ifdef __USE_NUWRO_SRW_EVENTS__ if (!rwEvs.size()) { fNuwroParams = fNuWroEvent->par; } - if (entry >= rwEvs.size()) { rwEvs.push_back(BaseFitEvt()); + rwEvs.back().fType = kNUWRO; + rwEvs.back().Mode = fNUISANCEEvent->Mode; rwEvs.back().fNuwroSRWEvent = SRW::SRWEvent(*fNuWroEvent); rwEvs.back().fNuwroEvent = NULL; rwEvs.back().fNuwroParams = &fNuwroParams; rwEvs.back().probe_E = rwEvs.back().fNuwroSRWEvent.NeutrinoEnergy; rwEvs.back().probe_pdg = rwEvs.back().fNuwroSRWEvent.NeutrinoPDG; } + + fNUISANCEEvent->fNuwroSRWEvent = SRW::SRWEvent(*fNuWroEvent); + fNUISANCEEvent->fNuwroParams = &fNuwroParams; + fNUISANCEEvent->probe_E = fNUISANCEEvent->fNuwroSRWEvent.NeutrinoEnergy; + fNUISANCEEvent->probe_pdg = fNUISANCEEvent->fNuwroSRWEvent.NeutrinoPDG; #endif return fNUISANCEEvent; } int NuWroInputHandler::ConvertNuwroMode(event* e) { Int_t proton_pdg, neutron_pdg, pion_pdg, pion_plus_pdg, pion_minus_pdg, lambda_pdg, eta_pdg, kaon_pdg, kaon_plus_pdg; proton_pdg = 2212; eta_pdg = 221; neutron_pdg = 2112; pion_pdg = 111; pion_plus_pdg = 211; pion_minus_pdg = -211; // O_16_pdg = 100069; // oznacznie z Neuta lambda_pdg = 3122; kaon_pdg = 311; kaon_plus_pdg = 321; if (e->flag.qel) // kwiazielastyczne oddziaływanie { if (e->flag.anty) // jeśli jest to oddziaływanie z antyneutrinem { if (e->flag.cc) return -1; else { if (event1_nof(e, proton_pdg)) return -51; else if (event1_nof(e, neutron_pdg)) return -52; // sprawdzam dodatkowo ? } } else // oddziaływanie z neutrinem { if (e->flag.cc) return 1; else { if (event1_nof(e, proton_pdg)) return 51; else if (event1_nof(e, neutron_pdg)) return 52; } } } if (e->flag.mec) { if (e->flag.anty) return -2; else return 2; } if (e->flag.res) // rezonansowa produkcja: pojedynczy pion, pojed.eta, kaon, // multipiony { Int_t liczba_pionow, liczba_kaonow; liczba_pionow = event1_nof(e, pion_pdg) + event1_nof(e, pion_plus_pdg) + event1_nof(e, pion_minus_pdg); liczba_kaonow = event1_nof(e, kaon_pdg) + event1_nof(e, kaon_pdg); if (liczba_pionow > 1 || liczba_pionow == 0) // multipiony { if (e->flag.anty) { if (e->flag.cc) return -21; else return -41; } else { if (e->flag.cc) return 21; else return 41; } } if (liczba_pionow == 1) { if (e->flag.anty) // jeśli jest to oddziaływanie z antyneutrinem { if (e->flag.cc) { if (event1_nof(e, neutron_pdg) && event1_nof(e, pion_minus_pdg)) return -11; if (event1_nof(e, neutron_pdg) && event1_nof(e, pion_pdg)) return -12; if (event1_nof(e, proton_pdg) && event1_nof(e, pion_minus_pdg)) return -13; } else { if (event1_nof(e, proton_pdg)) { if (event1_nof(e, pion_minus_pdg)) return -33; else if (event1_nof(e, pion_pdg)) return -32; } else if (event1_nof(e, neutron_pdg)) { if (event1_nof(e, pion_plus_pdg)) return -34; else if (event1_nof(e, pion_pdg)) return -31; } } } else // oddziaływanie z neutrinem { if (e->flag.cc) { if (event1_nof(e, proton_pdg) && event1_nof(e, pion_plus_pdg)) return 11; if (event1_nof(e, proton_pdg) && event1_nof(e, pion_pdg)) return 12; if (event1_nof(e, neutron_pdg) && event1_nof(e, pion_plus_pdg)) return 13; } else { if (event1_nof(e, proton_pdg)) { if (event1_nof(e, pion_minus_pdg)) return 33; else if (event1_nof(e, pion_pdg)) return 32; } else if (event1_nof(e, neutron_pdg)) { if (event1_nof(e, pion_plus_pdg)) return 34; else if (event1_nof(e, pion_pdg)) return 31; } } } } if (event1_nof(e, eta_pdg)) // produkcja rezonansowa ety { if (e->flag.anty) // jeśli jest to oddziaływanie z antyneutrinem { if (e->flag.cc) return -22; else { if (event1_nof(e, neutron_pdg)) return -42; else if (event1_nof(e, proton_pdg)) return -43; // sprawdzam dodatkowo ? } } else // oddziaływanie z neutrinem { if (e->flag.cc) return 22; else { if (event1_nof(e, neutron_pdg)) return 42; else if (event1_nof(e, proton_pdg)) return 43; } } } if (event1_nof(e, lambda_pdg) == 1 && liczba_kaonow == 1) // produkcja rezonansowa kaonu { if (e->flag.anty) // jeśli jest to oddziaływanie z antyneutrinem { if (e->flag.cc && event1_nof(e, kaon_pdg)) return -23; else { if (event1_nof(e, kaon_pdg)) return -44; else if (event1_nof(e, kaon_plus_pdg)) return -45; } } else // oddziaływanie z neutrinem { if (e->flag.cc && event1_nof(e, kaon_plus_pdg)) return 23; else { if (event1_nof(e, kaon_pdg)) return 44; else if (event1_nof(e, kaon_plus_pdg)) return 45; } } } } if (e->flag.coh) // koherentne oddziaływanie tylko na O(16) { Int_t _target; _target = e->par.nucleus_p + e->par.nucleus_n; // liczba masowa O(16) if (_target == 16) { if (e->flag.anty) // jeśli jest to oddziaływanie z antyneutrinem { if (e->flag.cc && event1_nof(e, pion_minus_pdg)) return -16; else if (event1_nof(e, pion_pdg)) return -36; } else // oddziaływanie z neutrinem { if (e->flag.cc && event1_nof(e, pion_plus_pdg)) return 16; else if (event1_nof(e, pion_pdg)) return 36; } } } // gleboko nieelastyczne rozpraszanie if (e->flag.dis) { if (e->flag.anty) { if (e->flag.cc) return -26; else return -46; } else { if (e->flag.cc) return 26; else return 46; } } return 9999; } void NuWroInputHandler::CalcNUISANCEKinematics() { // std::cout << "NuWro Event Address " << fNuWroEvent << std::endl; // Reset all variables fNUISANCEEvent->ResetEvent(); FitEvent* evt = fNUISANCEEvent; // Sort Event Info evt->Mode = ConvertNuwroMode(fNuWroEvent); if (abs(evt->Mode) > 60) { evt->Mode = 0; } evt->fEventNo = 0.0; evt->fTotCrs = 0.0; evt->fTargetA = fNuWroEvent->par.nucleus_p + fNuWroEvent->par.nucleus_n; evt->fTargetZ = fNuWroEvent->par.nucleus_p; evt->fTargetH = 0; evt->fBound = (evt->fTargetA) == 1; // Check Particle Stack UInt_t npart_in = fNuWroEvent->in.size(); UInt_t npart_out = fNuWroEvent->out.size(); UInt_t npart_post = fNuWroEvent->post.size(); UInt_t npart = npart_in + npart_out + npart_post; UInt_t kmax = evt->kMaxParticles; if (npart > kmax) { ERR(WRN) << "NUWRO has too many particles. Expanding stack." << std::endl; fNUISANCEEvent->ExpandParticleStack(npart); } // Sort Particles evt->fNParticles = 0; std::vector::iterator p_iter; // Initial State for (p_iter = fNuWroEvent->in.begin(); p_iter != fNuWroEvent->in.end(); p_iter++) { AddNuWroParticle(fNUISANCEEvent, (*p_iter), kInitialState); } // FSI State // for (size_t i = 0; i < npart_in; i++ ) { // AddNuWroParticle(fNUISANCEEvent, (*p_iter), kFSIState); // } // Final State for (p_iter = fNuWroEvent->post.begin(); p_iter != fNuWroEvent->post.end(); p_iter++) { AddNuWroParticle(fNUISANCEEvent, (*p_iter), kFinalState); } // Fill Generator Info if (fSaveExtra) fNuWroInfo->FillGeneratorInfo(fNuWroEvent); // Run Initial, FSI, Final, Other ordering. fNUISANCEEvent->OrderStack(); FitParticle* ISNeutralLepton = fNUISANCEEvent->GetHMISParticle(PhysConst::pdg_neutrinos); if (ISNeutralLepton) { fNUISANCEEvent->probe_E = ISNeutralLepton->E(); fNUISANCEEvent->probe_pdg = ISNeutralLepton->PDG(); } return; } void NuWroInputHandler::AddNuWroParticle(FitEvent* evt, particle& p, int state) { // Add Mom evt->fParticleMom[evt->fNParticles][0] = static_cast(p).x; evt->fParticleMom[evt->fNParticles][1] = static_cast(p).y; evt->fParticleMom[evt->fNParticles][2] = static_cast(p).z; evt->fParticleMom[evt->fNParticles][3] = static_cast(p).t; // Status/PDG evt->fParticleState[evt->fNParticles] = state; evt->fParticlePDG[evt->fNParticles] = p.pdg; // Add to particle count evt->fNParticles++; } void NuWroInputHandler::Print() {} #endif diff --git a/src/InputHandler/StdHepEvt.cxx b/src/InputHandler/StdHepEvt.cxx index dfa93f8..02e821a 100644 --- a/src/InputHandler/StdHepEvt.cxx +++ b/src/InputHandler/StdHepEvt.cxx @@ -1,135 +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 . *******************************************************************************/ #include #include #include #include "StdHepEvt.h" // Include logging #include "FitLogger.h" StdHepReader::StdHepReader(){}; bool StdHepReader::SetBranchAddresses(TChain *chain) { bool ok = true; int SBAStatus = 0; SBAStatus = chain->SetBranchAddress("StdHepN", &StdHepN); ok = ok && (SBAStatus || SBAStatus == 5); if (!(!SBAStatus || SBAStatus == 5)) { ERR(WRN) << "Failed to set branch address for \"StdHepN\": " << SBAStatus << std::endl; } SBAStatus = chain->SetBranchAddress("StdHepPdg", StdHepPdg); ok = ok && (SBAStatus || SBAStatus == 5); if (!(!SBAStatus || SBAStatus == 5)) { ERR(WRN) << "Failed to set branch address for \"StdHepPdg\": " << SBAStatus << std::endl; } SBAStatus = chain->SetBranchAddress("StdHepStatus", StdHepStatus); ok = ok && (SBAStatus || SBAStatus == 5); if (!(!SBAStatus || SBAStatus == 5)) { ERR(WRN) << "Failed to set branch address for \"StdHepStatus\": " << SBAStatus << std::endl; } SBAStatus = chain->SetBranchAddress("StdHepP4", StdHepP4); ok = ok && (SBAStatus || SBAStatus == 5); if (!(!SBAStatus || SBAStatus == 5)) { ERR(WRN) << "Failed to set branch address for \"StdHepP4\": " << SBAStatus << std::endl; } return ok; } bool GiBUUStdHepReader::SetBranchAddresses(TChain *chain) { bool ok = true; int SBAStatus = 0; ok = ok && StdHepReader::SetBranchAddresses(chain); SBAStatus = chain->SetBranchAddress("GiBUU2NeutCode", &GiBUU2NeutCode); ok = ok && (SBAStatus || SBAStatus == 5); if (!(!SBAStatus || SBAStatus == 5)) { ERR(WRN) << "Failed to set branch address for \"GiBUU2NeutCode\": " << SBAStatus << std::endl; } + SBAStatus = chain->SetBranchAddress("GiBUUReactionCode", &GiBUUReactionCode); + ok = ok && (SBAStatus || SBAStatus == 5); + if (!(!SBAStatus || SBAStatus == 5)) { + ERR(WRN) << "Failed to set branch address for \"GiBUUReactionCode\": " + << SBAStatus << std::endl; + } SBAStatus = chain->SetBranchAddress("EvtWght", &EvtWght); ok = ok && (SBAStatus || SBAStatus == 5); if (!(!SBAStatus || SBAStatus == 5)) { ERR(WRN) << "Failed to set branch address for \"EvtWght\": " << SBAStatus << std::endl; } return ok; } std::string NegSpacer(double const &num) { return (num >= 0) ? " " : ""; } std::ostream &operator<<(std::ostream &os, TLorentzVector const &tlv) { std::streamsize prec = os.precision(); std::ios_base::fmtflags flags = os.flags(); os.precision(2); os.flags(std::ios::scientific); os << "[" << NegSpacer(tlv[0]) << tlv[0] << "," << NegSpacer(tlv[1]) << tlv[1] << "," << NegSpacer(tlv[2]) << tlv[2] << "," << NegSpacer(tlv[3]) << tlv[3] << ":M(" << tlv.M() << ")]"; os.precision(prec); os.flags(flags); return os; } std::string WriteGiBUUEvent(GiBUUStdHepReader const &gi) { std::stringstream ss(""); ss << "[INFO]: contained " << gi.StdHepN << ", Event Weight: " << std::setprecision(3) << gi.EvtWght << ", NeutConventionReactionCode: " << gi.GiBUU2NeutCode << "\n\t[Lep In](" << std::setw(3) << gi.StdHepPdg[0] << ") " << TLorentzVector(gi.StdHepP4[0][StdHepReader::kStdHepIdxPx], gi.StdHepP4[0][StdHepReader::kStdHepIdxPy], gi.StdHepP4[0][StdHepReader::kStdHepIdxPz], gi.StdHepP4[0][StdHepReader::kStdHepIdxE]) << std::endl; ss << "\t[Target] : " << gi.StdHepPdg[1] << std::endl; ss << "\t[Nuc In] : " << TLorentzVector(gi.StdHepP4[3][StdHepReader::kStdHepIdxPx], gi.StdHepP4[3][StdHepReader::kStdHepIdxPy], gi.StdHepP4[3][StdHepReader::kStdHepIdxPz], gi.StdHepP4[3][StdHepReader::kStdHepIdxE]) << " (" << std::setw(4) << gi.StdHepPdg[3] << ")" << std::endl; for (Int_t stdHepInd = 4; stdHepInd < gi.StdHepN; ++stdHepInd) { ss << "\t[" << std::setw(2) << (stdHepInd - (4)) << "](" << std::setw(5) << gi.StdHepPdg[stdHepInd] << ") " << TLorentzVector(gi.StdHepP4[stdHepInd][StdHepReader::kStdHepIdxPx], gi.StdHepP4[stdHepInd][StdHepReader::kStdHepIdxPy], gi.StdHepP4[stdHepInd][StdHepReader::kStdHepIdxPz], gi.StdHepP4[stdHepInd][StdHepReader::kStdHepIdxE]) << std::endl; } ss << "\t[Lep Out](" << std::setw(3) << gi.StdHepPdg[2] << ") " << TLorentzVector(gi.StdHepP4[2][StdHepReader::kStdHepIdxPx], gi.StdHepP4[2][StdHepReader::kStdHepIdxPy], gi.StdHepP4[2][StdHepReader::kStdHepIdxPz], gi.StdHepP4[2][StdHepReader::kStdHepIdxE]) << std::endl; return ss.str(); } diff --git a/src/InputHandler/StdHepEvt.h b/src/InputHandler/StdHepEvt.h index 198279b..96f280c 100644 --- a/src/InputHandler/StdHepEvt.h +++ b/src/InputHandler/StdHepEvt.h @@ -1,111 +1,116 @@ #ifndef __STDHEPEVT_SEEN__ #define __STDHEPEVT_SEEN__ // 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 "TChain.h" #include "TLorentzVector.h" struct StdHepReader { public: const static int kStdHepIdxPx = 0; const static int kStdHepIdxPy = 1; const static int kStdHepIdxPz = 2; const static int kStdHepIdxE = 3; const static int kStdHepNPmax = 100; StdHepReader(); ///\brief The number of StdHep particles in this event. Int_t StdHepN; ///\brief The PDG codes of particles in this event. /// /// This is determined from the GiBUU particle number by /// GiBUUUtils::GiBUUToPDG. ///\warning This is not a one-to-one mapping, e.g. resonances are not uniquely /// determined by the GiBUU scheme. Int_t StdHepPdg[kStdHepNPmax]; //[StdHepN] ///\brief The StdHep Status of particles in this event. /// /// Status Codes in use: /// - -1: Initial state real particle. /// - 1: Final state real particle. Int_t StdHepStatus[kStdHepNPmax]; //[StdHepN] ///\brief Four momentum for particles in this event. Double_t StdHepP4[kStdHepNPmax][4]; bool SetBranchAddresses(TChain*); }; struct GiBUUStdHepReader : public StdHepReader { GiBUUStdHepReader() : StdHepReader(){}; + ///\brief GiBUU interaction code + /// + /// See https://gibuu.hepforge.org/trac/wiki/LesHouches for details + Int_t GiBUUReactionCode; + ///\brief NEUT equivalent reaction code. /// CC: /// * 1 : QE /// * 2 : 2p2h /// * 10 : Single pion background (non-resonant) /// * 11 : Delta++ ( -11 : Delta- for nubar) /// * 12 : Delta+ (-12 : Delta0 for nubar) /// * 21 : Multi pion production /// * 26 : DIS /// * 4 : Higher resonance, charge: -1 /// * 5 : Higher resonance, charge: 0 /// * 6 : Higher resonance, charge: +1 /// * 7 : Higher resonance, charge: +2 /// /// NC: /// * 30 : Single pion background (non-resonant) /// * 31 : Delta0 /// * 32 : Delta+ /// * 41 : Multi pion production /// * 42 : 2p2h /// * 46 : DIS /// * 47 : Higher resonance, charge: -1 /// * 48 : Higher resonance, charge: 0 /// * 49 : Higher resonance, charge: +1 /// * 50 : Higher resonance, charge: +2 /// * 51 : NCEL proton-target /// * 52 : NCEL neutron-target /// Int_t GiBUU2NeutCode; ///\brief The total XSec weighting that should be applied to this event. Double_t EvtWght; ///\brief Weighting which takes account of multiple input numu species. /// /// Defined such that W_numu + W_numubar = 1 Double_t SpeciesWght_numu; ///\brief Weighting which takes account of multiple input nue species. /// /// Defined such that W_nue + W_nuebar = 1 Double_t SpeciesWght_nue; ///\brief Weighting which takes account of multiple input neutrino species. /// /// Defined such that \Sum_species W_species = 1 Double_t SpeciesWght; bool SetBranchAddresses(TChain*); }; std::string WriteGiBUUEvent(GiBUUStdHepReader const& gi); #endif diff --git a/src/Logger/FitLogger.h b/src/Logger/FitLogger.h index ce46f6c..2fede17 100644 --- a/src/Logger/FitLogger.h +++ b/src/Logger/FitLogger.h @@ -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 . *******************************************************************************/ #ifndef FITLOGGER_HPP #define FITLOGGER_HPP /*! * \addtogroup FitBase * @{ */ #include #include #include #include #include "TRandom3.h" #include "Initialiser.h" #include "NuisConfig.h" #define RESET "\033[0m" #define BLACK "\033[30m" /* Black */ #define RED "\033[31m" /* Red */ #define GREEN "\033[32m" /* Green */ #define YELLOW "\033[33m" /* Yellow */ #define BLUE "\033[34m" /* Blue */ #define MAGENTA "\033[35m" /* Magenta */ #define CYAN "\033[36m" /* Cyan */ #define WHITE "\033[37m" /* White */ #define BOLDBLACK "\033[1m\033[30m" /* Bold Black */ #define BOLDRED "\033[1m\033[31m" /* Bold Red */ #define BOLDGREEN "\033[1m\033[32m" /* Bold Green */ #define BOLDYELLOW "\033[1m\033[33m" /* Bold Yellow */ #define BOLDBLUE "\033[1m\033[34m" /* Bold Blue */ #define BOLDMAGENTA "\033[1m\033[35m" /* Bold Magenta */ #define BOLDCYAN "\033[1m\033[36m" /* Bold Cyan */ #define BOLDWHITE "\033[1m\033[37m" /* Bold White */ namespace Logger { extern int log_verb; //!< Current VERBOSITY extern int err_verb; //!< Current ERROR VERBOSITY extern bool external_verb; extern bool use_colors; //!< Use BASH Terminal Colors Flag extern bool super_rainbow_mode; //!< For when fitting gets boring. extern unsigned int super_rainbow_mode_colour; extern bool showtrace; // Quick Tracing for debugging extern int nloggercalls; extern int timelastlog; extern std::streambuf* default_cout; //!< Where the STDOUT stream is currently directed extern std::streambuf* default_cerr; //!< Where the STDERR stream is currently directed extern std::ofstream redirect_stream; //!< Where should unwanted messages be thrown } /// Returns full path to file currently in #define __FILENAME__ \ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) // ------ LOGGER FUNCTIONS ------------ // namespace Logger { /// NULL Output Stream extern std::ofstream __LOG_nullstream; /// Logging Stream extern std::ostream* __LOG_outstream; } /// Fitter VERBOSITY Enumerations /// These go through the different depths of the fitter. /// /// 0 QUIET - Little output. /// 1 FIT - Top Level Minimizer Status /// 2 MIN - Output from the FCN Minimizer Functions /// 3 SAM - Output from each of the samples during setup etc /// 4 REC - Output during each reconfigure. Percentage progress etc. /// 5 SIG - Output during every signal event that is found. /// 6 EVT - Output during every event. /// -1 DEB - Will print only debugging info wherever a LOG(DEB) statement was /// made -enum __LOG_levels { DEB = -1, QUIET, FIT, MIN, SAM, REC, SIG, EVT }; +enum __LOG_levels { QUIET = 0, FIT, MIN, SAM, REC, SIG, EVT, DEB }; /// Returns log level for a given file/function int __GETLOG_LEVEL(int level, const char* filename, const char* funct); /// Actually runs the logger std::ostream& __OUTLOG(int level, const char* filename, const char* funct, int line); /// Global Logging Definitions #define QLOG(level, stream) \ { \ if (Logger::log_verb >= \ __GETLOG_LEVEL(level, __FILENAME__, __FUNCTION__)) { \ __OUTLOG(level, __FILENAME__, __FUNCTION__, __LINE__) << stream \ << std::endl; \ } \ }; #define BREAK(level) \ { \ \ if (Logger::log_verb >= \ __GETLOG_LEVEL(level, __FILENAME__, __FUNCTION__)) { \ __OUTLOG(level, __FILENAME__, __FUNCTION__, __LINE__) << std::endl; \ } \ }; /// Return whether logging level is valid bool LOGGING(int level); /// Set Global Verbosity void SETVERBOSITY(int level); /// Set Global Verbosity from String void SETVERBOSITY(std::string verb); /// Set Trace Option void SETTRACE(bool val); // ----------- ERROR FUNCTIONS ---------- // /// Error Stream extern std::ostream* __ERR_outstream; /// Fitter ERROR VERBOSITY Enumerations /// /// 0 QUIET - No Error Output /// 1 FTL - Show errors only if fatal /// 2 WRN - Show Warning messages enum __ERR_levels { ERRQUIET = 0, FTL, WRN }; /// Actually runs the error messager std::ostream& __OUTERR(int level, const char* filename, const char* funct, int line); /// Error Logging Function #define ERROR(level, stream) \ { \ __OUTERR(level, __FILENAME__, __FUNCTION__, __LINE__) << stream \ << std::endl; \ }; // ----------- ERROR HANDLING ------------- // /// Exit the program with given error message stream #define THROW(stream) \ { \ __OUTERR(FTL, __FILENAME__, __FUNCTION__, __LINE__) << stream \ << std::endl; \ __OUTERR(FTL, __FILENAME__, __FUNCTION__, __LINE__) \ << "Attempting to save output file." << std::endl; \ - if (Config::Get().out && Config::Get().out->IsOpen()) { \ - Config::Get().out->Write(); \ - Config::Get().out->Close(); \ + if (Config::Get().out && Config::Get().out->IsOpen()) { \ + Config::Get().out->Write(); \ + Config::Get().out->Close(); \ __OUTERR(FTL, __FILENAME__, __FUNCTION__, __LINE__) << "Done." \ << std::endl; \ } else { \ __OUTERR(FTL, __FILENAME__, __FUNCTION__, __LINE__) \ << "No output file set." << std::endl; \ } \ __OUTERR(FTL, __FILENAME__, __FUNCTION__, __LINE__) << "Exiting!" \ << std::endl; \ std::abort(); \ } // ----------- External Logging ----------- // void SETEXTERNALVERBOSITY(int level); void StopTalking(); void StartTalking(); extern "C" { void shhnuisancepythiaitokay_(void); void canihaznuisancepythia_(void); } // ---------- LEGACY FUNCTIONS -------------- // bool LOG_LEVEL(int level); //! Set LOG VERBOSITY from a string void LOG_VERB(std::string verb); inline void LOG_VERB(int verb) { Logger::log_verb = verb; }; void SET_TRACE(bool val); //! Set ERROR VERBOSITY from a string void ERR_VERB(std::string verb); inline void ERR_VERB(int verb) { Logger::err_verb = verb; }; /// Logging Function. Use as a string stream. e.g. LOG(SAM) << "This sample is /// dope." << std::endl; std::ostream& _LOG(int level, const char* filename, const char* funct, int line); #define LOG(level) _LOG(level, __FILENAME__, __FUNCTION__, __LINE__) //! Error Function. Use as a string stream. e.g. ERR(FTL) << "The fit is //! completely buggered." << std::endl; std::ostream& _ERR(int level, const char* filename, const char* funct, int line); #define ERR(level) _ERR(level, __FILENAME__, __FUNCTION__, __LINE__) /*! @} */ #endif diff --git a/src/Logger/Initialiser.cxx b/src/Logger/Initialiser.cxx index 923805a..8cb09f2 100644 --- a/src/Logger/Initialiser.cxx +++ b/src/Logger/Initialiser.cxx @@ -1,98 +1,101 @@ #include "Initialiser.h" -void RunNuisance(){ - std::cout << "Starting NUISANCE" << std::endl; -} +void RunNuisance() { std::cout << "Starting NUISANCE" << std::endl; } struct LetterBackronym { LetterBackronym(size_t n, std::string const &b, float p = 1.0, std::string const &t = "") { NUsed = n; Backkie = b; ProbAccept = p; TagLine = t; }; size_t NUsed; float ProbAccept; std::string Backkie; std::string TagLine; }; -__attribute__((constructor)) void nuisance_init(void) { +__attribute__((constructor)) void constructor(void) { nuisance_init(); } + +void nuisance_init(void) { std::vector > Letters; for (size_t i = 0; i < 8; ++i) { Letters.push_back(std::vector()); } Letters[0].push_back(LetterBackronym(2, "Neutrino")); Letters[0].push_back(LetterBackronym(3, "NUIsance", 0.2)); Letters[2].push_back(LetterBackronym(1, "Interaction")); Letters[3].push_back(LetterBackronym(1, "Systematics")); Letters[3].push_back(LetterBackronym( - 1, "Synthesiser", 0.2, "Playing on the comparisons you want to see")); + 1, "Synthesiser", 0.2, "Playing on the comparisons you want to see")); Letters[4].push_back(LetterBackronym(2, "ANalyser")); Letters[4].push_back(LetterBackronym(1, "Aggregating", 0.5)); Letters[4].push_back(LetterBackronym(3, "from A-Neutrino sCattering", 1, "You can always find a frame")); Letters[5].push_back( - LetterBackronym(1, "New", 1, "The freshest comparisons")); + LetterBackronym(1, "New", 1, "The freshest comparisons")); Letters[6].push_back(LetterBackronym(1, "by Comparing")); Letters[6].push_back(LetterBackronym(1, "Constraints from")); Letters[7].push_back(LetterBackronym(1, "Experiments")); std::vector TagLines; TagLines.push_back("Fit and compare."); std::stringstream back(""); TRandom3 tr; tr.SetSeed(); for (size_t i = 0; i < 8;) { LetterBackronym const &let = Letters[i][tr.Integer(Letters[i].size())]; if (tr.Uniform() > let.ProbAccept) { continue; } back << let.Backkie << " "; i += let.NUsed; if (let.TagLine.length()) { TagLines.push_back(let.TagLine); } } std::string Name = "Nuisance"; std::string TagL = TagLines[tr.Integer(TagLines.size())]; std::vector > > - OneBlob; + OneBlob; OneBlob.push_back( - std::make_pair("NUISANCE", std::make_pair("", "FiXing your Neutrinos"))); + std::make_pair("NUISANCE", std::make_pair("", "FiXing your Neutrinos"))); if (tr.Uniform() < 0.01) { std::pair > const &blob = - OneBlob[tr.Integer(OneBlob.size())]; + OneBlob[tr.Integer(OneBlob.size())]; Name = blob.first; back.str(""); back << blob.second.first; TagL = blob.second.second; } - std::cout << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" - "%%%%%%%%%%%%%%%" - "%%" - << std::endl - << "%% Welcome to " << Name << ": \033[5m" << back.str() - << "\033[0m-- " << TagL << std::endl - << "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" - "%%%%%%%%%%%%%%%" - "%%" - << std::endl; -} \ No newline at end of file + // std::cout << + // "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" + // "%%%%%%%%%%%%%%%" + // "%%" + // << std::endl + // << "%% Welcome to " << Name << ": \033[5m" << back.str() + // << "\033[0m-- " << TagL << std::endl + // << + // "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" + // "%%%%%%%%%%%%%%%" + // "%%" + // << std::endl; + std::cout << Name << ": " << back.str() << " -- " << TagL << std::endl; +} diff --git a/src/Logger/Initialiser.h b/src/Logger/Initialiser.h index 104ead9..4386235 100644 --- a/src/Logger/Initialiser.h +++ b/src/Logger/Initialiser.h @@ -1,20 +1,21 @@ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "TRandom3.h" void RunNuisance(); +void nuisance_init(void) ; diff --git a/src/MCStudies/GenericFlux_Tester.cxx b/src/MCStudies/GenericFlux_Tester.cxx index b32a54f..284b9a8 100644 --- a/src/MCStudies/GenericFlux_Tester.cxx +++ b/src/MCStudies/GenericFlux_Tester.cxx @@ -1,576 +1,591 @@ // 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 . -*******************************************************************************/ + * 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_Tester.h" //******************************************************************** /// @brief Class to perform MC Studies on a custom measurement GenericFlux_Tester::GenericFlux_Tester(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 // Set default fitter flags fIsDiag = true; fIsShape = false; fIsRawEvents = false; nu_4mom = new TLorentzVector(0, 0, 0, 0); pmu = new TLorentzVector(0, 0, 0, 0); ppip = new TLorentzVector(0, 0, 0, 0); ppim = new TLorentzVector(0, 0, 0, 0); ppi0 = new TLorentzVector(0, 0, 0, 0); pprot = new TLorentzVector(0, 0, 0, 0); pneut = new TLorentzVector(0, 0, 0, 0); // 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; - liteMode = FitPar::Config().GetParB("isLiteMode"); + liteMode = Config::Get().GetParB("isLiteMode"); + + if (Config::HasPar("EnuMin")) { + EnuMin = Config::GetParD("EnuMin"); + } + + if (Config::HasPar("EnuMax")) { + EnuMax = Config::GetParD("EnuMax"); + } // 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 = - (GetEventHistogram()->Integral("width") * 1E-38 / (fNEvents + 0.)) / + (this->PredictedEventRate("width", 0, 1000) / double(fNEvents)) / this->TotalIntegratedFlux(); if (fScaleFactor <= 0.0) { ERR(WRN) << "SCALE FACTOR TOO LOW " << std::endl; throw; } - std::cout << EnuMin << " = " << EnuMax << std::endl; LOG(SAM) << " Generic Flux Scaling Factor = " << fScaleFactor << " [= " << (GetEventHistogram()->Integral("width") * 1E-38) << "/(" << (fNEvents + 0.) << "*" << this->TotalIntegratedFlux() << ")]" << std::endl; // Setup our TTrees this->AddEventVariablesToTree(); this->AddSignalFlagsToTree(); } void GenericFlux_Tester::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()); } LOG(SAM) << "Adding Event Variables" << std::endl; eventVariables->Branch("Mode", &Mode, "Mode/I"); eventVariables->Branch("PDGnu", &PDGnu, "PDGnu/I"); eventVariables->Branch("Enu_true", &Enu_true, "Enu_true/F"); eventVariables->Branch("Nleptons", &Nleptons, "Nleptons/I"); -// all sensible + // all sensible eventVariables->Branch("MLep", &MLep, "MLep/F"); eventVariables->Branch("ELep", &ELep, "ELep/F"); -// negative -999 + // negative -999 eventVariables->Branch("TLep", &TLep, "TLep/F"); eventVariables->Branch("CosLep", &CosLep, "CosLep/F"); eventVariables->Branch("CosPmuPpip", &CosPmuPpip, "CosPmuPpip/F"); eventVariables->Branch("CosPmuPpim", &CosPmuPpim, "CosPmuPpim/F"); eventVariables->Branch("CosPmuPpi0", &CosPmuPpi0, "CosPmuPpi0/F"); eventVariables->Branch("CosPmuPprot", &CosPmuPprot, "CosPmuPprot/F"); eventVariables->Branch("CosPmuPneut", &CosPmuPneut, "CosPmuPneut/F"); eventVariables->Branch("Nprotons", &Nprotons, "Nprotons/I"); eventVariables->Branch("MPr", &MPr, "MPr/F"); eventVariables->Branch("EPr", &EPr, "EPr/F"); eventVariables->Branch("TPr", &TPr, "TPr/F"); eventVariables->Branch("CosPr", &CosPr, "CosPr/F"); eventVariables->Branch("CosPprotPneut", &CosPprotPneut, "CosPprotPneut/F"); eventVariables->Branch("Nneutrons", &Nneutrons, "Nneutrons/I"); eventVariables->Branch("MNe", &MNe, "MNe/F"); eventVariables->Branch("ENe", &ENe, "ENe/F"); eventVariables->Branch("TNe", &TNe, "TNe/F"); eventVariables->Branch("CosNe", &CosNe, "CosNe/F"); eventVariables->Branch("Npiplus", &Npiplus, "Npiplus/I"); eventVariables->Branch("MPiP", &MPiP, "MPiP/F"); eventVariables->Branch("EPiP", &EPiP, "EPiP/F"); eventVariables->Branch("TPiP", &TPiP, "TPiP/F"); eventVariables->Branch("CosPiP", &CosPiP, "CosPiP/F"); eventVariables->Branch("CosPpipPprot", &CosPpipPprot, "CosPpipProt/F"); eventVariables->Branch("CosPpipPneut", &CosPpipPneut, "CosPpipPneut/F"); eventVariables->Branch("CosPpipPpim", &CosPpipPpim, "CosPpipPpim/F"); eventVariables->Branch("CosPpipPpi0", &CosPpipPpi0, "CosPpipPpi0/F"); eventVariables->Branch("Npineg", &Npineg, "Npineg/I"); eventVariables->Branch("MPiN", &MPiN, "MPiN/F"); eventVariables->Branch("EPiN", &EPiN, "EPiN/F"); eventVariables->Branch("TPiN", &TPiN, "TPiN/F"); eventVariables->Branch("CosPiN", &CosPiN, "CosPiN/F"); eventVariables->Branch("CosPpimPprot", &CosPpimPprot, "CosPpimPprot/F"); eventVariables->Branch("CosPpimPneut", &CosPpimPneut, "CosPpimPneut/F"); eventVariables->Branch("CosPpimPpi0", &CosPpimPpi0, "CosPpimPpi0/F"); eventVariables->Branch("Npi0", &Npi0, "Npi0/I"); eventVariables->Branch("MPi0", &MPi0, "MPi0/F"); eventVariables->Branch("EPi0", &EPi0, "EPi0/F"); eventVariables->Branch("TPi0", &TPi0, "TPi0/F"); eventVariables->Branch("CosPi0", &CosPi0, "CosPi0/F"); eventVariables->Branch("CosPi0Pprot", &CosPi0Pprot, "CosPi0Pprot/F"); eventVariables->Branch("CosPi0Pneut", &CosPi0Pneut, "CosPi0Pneut/F"); eventVariables->Branch("Nother", &Nother, "Nother/I"); eventVariables->Branch("Q2_true", &Q2_true, "Q2_true/F"); eventVariables->Branch("q0_true", &q0_true, "q0_true/F"); eventVariables->Branch("q3_true", &q3_true, "q3_true/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("bjorken_x", &bjorken_x, "bjorken_x/F"); eventVariables->Branch("bjorken_y", &bjorken_y, "bjorken_y/F"); eventVariables->Branch("Erecoil_true", &Erecoil_true, "Erecoil_true/F"); eventVariables->Branch("Erecoil_charged", &Erecoil_charged, "Erecoil_charged/F"); eventVariables->Branch("Erecoil_minerva", &Erecoil_minerva, "Erecoil_minerva/F"); if (!liteMode) { eventVariables->Branch("nu_4mom", &nu_4mom); eventVariables->Branch("pmu_4mom", &pmu); eventVariables->Branch("hm_ppip_4mom", &ppip); eventVariables->Branch("hm_ppim_4mom", &ppim); eventVariables->Branch("hm_ppi0_4mom", &ppi0); eventVariables->Branch("hm_pprot_4mom", &pprot); eventVariables->Branch("hm_pneut_4mom", &pneut); } // Event Scaling Information eventVariables->Branch("Weight", &Weight, "Weight/F"); eventVariables->Branch("InputWeight", &InputWeight, "InputWeight/F"); eventVariables->Branch("RWWeight", &RWWeight, "RWWeight/F"); eventVariables->Branch("FluxWeight", &FluxWeight, "FluxWeight/F"); eventVariables->Branch("fScaleFactor", &fScaleFactor, "fScaleFactor/D"); return; } void GenericFlux_Tester::AddSignalFlagsToTree() { if (!eventVariables) { Config::Get().out->cd(); eventVariables = new TTree((this->fName + "_VARS").c_str(), (this->fName + "_VARS").c_str()); } LOG(SAM) << "Adding signal flags" << std::endl; // 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"); }; - //******************************************************************** void GenericFlux_Tester::ResetVariables() { -//******************************************************************** + //******************************************************************** // Reset neutrino PDG PDGnu = 0; // Reset energies Enu_true = Enu_QE = __BAD_FLOAT__; // Reset auxillaries - Q2_true = Q2_QE = W_nuc_rest = bjorken_x = bjorken_y = q0_true = q3_true = Erecoil_true = Erecoil_charged = Erecoil_minerva = __BAD_FLOAT__; + Q2_true = Q2_QE = W_nuc_rest = bjorken_x = bjorken_y = q0_true = q3_true = + Erecoil_true = Erecoil_charged = Erecoil_minerva = __BAD_FLOAT__; // Reset particle counters - Nparticles = Nleptons = Nother = Nprotons = Nneutrons = Npiplus = Npineg = Npi0 = 0; + Nparticles = Nleptons = Nother = Nprotons = Nneutrons = Npiplus = Npineg = + Npi0 = 0; // Reset Lepton PDG PDGLep = 0; // Reset Lepton variables - TLep = CosLep = ELep = PLep = MLep = __BAD_FLOAT__; + TLep = CosLep = ELep = PLep = MLep = __BAD_FLOAT__; // Rset proton variables - PPr = CosPr = EPr = TPr = MPr = __BAD_FLOAT__; + PPr = CosPr = EPr = TPr = MPr = __BAD_FLOAT__; // Reset neutron variables - PNe = CosNe = ENe = TNe = MNe = __BAD_FLOAT__; + PNe = CosNe = ENe = TNe = MNe = __BAD_FLOAT__; // Reset pi+ variables - PPiP = CosPiP = EPiP = TPiP = MPiP = __BAD_FLOAT__; + PPiP = CosPiP = EPiP = TPiP = MPiP = __BAD_FLOAT__; // Reset pi- variables - PPiN = CosPiN = EPiN = TPiN = MPiN = __BAD_FLOAT__; + PPiN = CosPiN = EPiN = TPiN = MPiN = __BAD_FLOAT__; // Reset pi0 variables - PPi0 = CosPi0 = EPi0 = TPi0 = MPi0 = __BAD_FLOAT__; + PPi0 = CosPi0 = EPi0 = TPi0 = MPi0 = __BAD_FLOAT__; // Reset the cos angles - CosPmuPpip = CosPmuPpim = CosPmuPpi0 = CosPmuPprot = CosPmuPneut = CosPpipPprot = CosPpipPneut = CosPpipPpim = CosPpipPpi0 = CosPpimPprot = CosPpimPneut = CosPpimPpi0 = CosPi0Pprot = CosPi0Pneut = CosPprotPneut = __BAD_FLOAT__; + CosPmuPpip = CosPmuPpim = CosPmuPpi0 = CosPmuPprot = CosPmuPneut = + CosPpipPprot = CosPpipPneut = CosPpipPpim = CosPpipPpi0 = CosPpimPprot = + CosPpimPneut = CosPpimPpi0 = CosPi0Pprot = CosPi0Pneut = + CosPprotPneut = __BAD_FLOAT__; } //******************************************************************** void GenericFlux_Tester::FillEventVariables(FitEvent *event) { //******************************************************************** // Fill Signal Variables FillSignalFlags(event); LOG(DEB) << "Filling signal" << std::endl; // Reset the private variables (see header) ResetVariables(); // Function used to extract any variables of interest to the event Mode = event->Mode; // Reset the highest momentum variables float proton_highmom = __BAD_FLOAT__; float neutron_highmom = __BAD_FLOAT__; float piplus_highmom = __BAD_FLOAT__; float pineg_highmom = __BAD_FLOAT__; float pi0_highmom = __BAD_FLOAT__; (*nu_4mom) = event->PartInfo(0)->fP; if (!liteMode) { (*pmu) = TLorentzVector(0, 0, 0, 0); (*ppip) = TLorentzVector(0, 0, 0, 0); (*ppim) = TLorentzVector(0, 0, 0, 0); (*ppi0) = TLorentzVector(0, 0, 0, 0); (*pprot) = TLorentzVector(0, 0, 0, 0); (*pneut) = TLorentzVector(0, 0, 0, 0); } Enu_true = nu_4mom->E(); PDGnu = event->PartInfo(0)->fPID; bool cc = (abs(event->Mode) < 30); (void)cc; // Add all pion distributions for the event. // Add classifier for CC0pi or CC1pi or CCOther // Save Modes Properly // Save low recoil measurements // Start Particle Loop UInt_t npart = event->Npart(); for (UInt_t i = 0; i < npart; i++) { // Skip particles that weren't in the final state bool part_alive = event->PartInfo(i)->fIsAlive and event->PartInfo(i)->Status() == kFinalState; if (!part_alive) continue; // PDG Particle int PDGpart = event->PartInfo(i)->fPID; TLorentzVector part_4mom = event->PartInfo(i)->fP; Nparticles++; // Get Charged Lepton if (abs(PDGpart) == abs(PDGnu) - 1) { Nleptons++; PDGLep = PDGpart; TLep = FitUtils::T(part_4mom) * 1000.0; PLep = (part_4mom.Vect().Mag()); ELep = (part_4mom.E()); MLep = (part_4mom.Mag()); CosLep = cos(part_4mom.Vect().Angle(nu_4mom->Vect())); (*pmu) = part_4mom; Q2_true = -1 * (part_4mom - (*nu_4mom)).Mag2(); float ThetaLep = (event->PartInfo(0)) ->fP.Vect() .Angle((event->PartInfo(i))->fP.Vect()); q0_true = (part_4mom - (*nu_4mom)).E(); q3_true = (part_4mom - (*nu_4mom)).Vect().Mag(); // Get W_true with assumption of initial state nucleon at rest float m_n = (float)PhysConst::mass_proton * 1000.; W_nuc_rest = sqrt(-Q2_true + 2 * m_n * (Enu_true - ELep) + m_n * m_n); // Get the Bjorken x and y variables // Assume that E_had = Enu - Emu as in MINERvA bjorken_x = Q2_true / (2 * m_n * (Enu_true - ELep)); bjorken_y = 1 - ELep / Enu_true; // Quasi-elastic ---------------------- // ------------------------------------ // Q2 QE Assuming Carbon Input. Should change this to be dynamic soon. Q2_QE = FitUtils::Q2QErec(part_4mom, cos(ThetaLep), 34., true) * 1000000.0; Enu_QE = FitUtils::EnuQErec(part_4mom, cos(ThetaLep), 34., true) * 1000.0; // Pion Production ---------------------- // -------------------------------------- } else if (PDGpart == 2212) { Nprotons++; if (part_4mom.Vect().Mag() > proton_highmom) { proton_highmom = part_4mom.Vect().Mag(); PPr = (part_4mom.Vect().Mag()); EPr = (part_4mom.E()); TPr = FitUtils::T(part_4mom) * 1000.; MPr = (part_4mom.Mag()); CosPr = cos(part_4mom.Vect().Angle(nu_4mom->Vect())); (*pprot) = part_4mom; } } else if (PDGpart == 2112) { Nneutrons++; if (part_4mom.Vect().Mag() > neutron_highmom) { neutron_highmom = part_4mom.Vect().Mag(); PNe = (part_4mom.Vect().Mag()); ENe = (part_4mom.E()); TNe = FitUtils::T(part_4mom) * 1000.; MNe = (part_4mom.Mag()); CosNe = cos(part_4mom.Vect().Angle(nu_4mom->Vect())); (*pneut) = part_4mom; } } else if (PDGpart == 211) { Npiplus++; if (part_4mom.Vect().Mag() > piplus_highmom) { piplus_highmom = part_4mom.Vect().Mag(); PPiP = (part_4mom.Vect().Mag()); EPiP = (part_4mom.E()); TPiP = FitUtils::T(part_4mom) * 1000.; MPiP = (part_4mom.Mag()); CosPiP = cos(part_4mom.Vect().Angle(nu_4mom->Vect())); (*ppip) = part_4mom; } } else if (PDGpart == -211) { Npineg++; if (part_4mom.Vect().Mag() > pineg_highmom) { pineg_highmom = part_4mom.Vect().Mag(); PPiN = (part_4mom.Vect().Mag()); EPiN = (part_4mom.E()); TPiN = FitUtils::T(part_4mom) * 1000.; MPiN = (part_4mom.Mag()); CosPiN = cos(part_4mom.Vect().Angle(nu_4mom->Vect())); (*ppim) = part_4mom; } } else if (PDGpart == 111) { Npi0++; if (part_4mom.Vect().Mag() > pi0_highmom) { pi0_highmom = part_4mom.Vect().Mag(); PPi0 = (part_4mom.Vect().Mag()); EPi0 = (part_4mom.E()); TPi0 = FitUtils::T(part_4mom) * 1000.; MPi0 = (part_4mom.Mag()); CosPi0 = cos(part_4mom.Vect().Angle(nu_4mom->Vect())); (*ppi0) = part_4mom; } } else { Nother++; } } // Get Recoil Definitions ------ // ----------------------------- Erecoil_true = FitUtils::GetErecoil_TRUE(event); Erecoil_charged = FitUtils::GetErecoil_CHARGED(event); Erecoil_minerva = FitUtils::GetErecoil_MINERvA_LowRecoil(event); // Do the angles between final state particles if (Nleptons > 0 && Npiplus > 0) CosPmuPpip = cos(pmu->Vect().Angle(ppip->Vect())); if (Nleptons > 0 && Npineg > 0) CosPmuPpim = cos(pmu->Vect().Angle(ppim->Vect())); if (Nleptons > 0 && Npi0 > 0) CosPmuPpi0 = cos(pmu->Vect().Angle(ppi0->Vect())); if (Nleptons > 0 && Nprotons > 0) CosPmuPprot = cos(pmu->Vect().Angle(pprot->Vect())); if (Nleptons > 0 && Nneutrons > 0) CosPmuPneut = cos(pmu->Vect().Angle(pneut->Vect())); if (Npiplus > 0 && Nprotons > 0) CosPpipPprot = cos(ppip->Vect().Angle(pprot->Vect())); if (Npiplus > 0 && Nneutrons > 0) CosPpipPneut = cos(ppip->Vect().Angle(pneut->Vect())); if (Npiplus > 0 && Npineg > 0) CosPpipPpim = cos(ppip->Vect().Angle(ppim->Vect())); if (Npiplus > 0 && Npi0 > 0) CosPpipPpi0 = cos(ppip->Vect().Angle(ppi0->Vect())); if (Npineg > 0 && Nprotons > 0) CosPpimPprot = cos(ppim->Vect().Angle(pprot->Vect())); if (Npineg > 0 && Nneutrons > 0) CosPpimPneut = cos(ppim->Vect().Angle(pneut->Vect())); if (Npineg > 0 && Npi0 > 0) CosPpimPpi0 = cos(ppim->Vect().Angle(ppi0->Vect())); if (Npi0 > 0 && Nprotons > 0) CosPi0Pprot = cos(ppi0->Vect().Angle(pprot->Vect())); if (Npi0 > 0 && Nneutrons > 0) CosPi0Pneut = cos(ppi0->Vect().Angle(pneut->Vect())); if (Nprotons > 0 && Nneutrons > 0) CosPprotPneut = cos(pprot->Vect().Angle(pneut->Vect())); // Event Weights ---- // ------------------ Weight = event->RWWeight * event->InputWeight; RWWeight = event->RWWeight; InputWeight = event->InputWeight; FluxWeight = GetFluxHistogram()->GetBinContent(GetFluxHistogram()->FindBin(Enu)) / GetFluxHistogram()->Integral(); // Fill the eventVariables Tree eventVariables->Fill(); return; }; //******************************************************************** void GenericFlux_Tester::Write(std::string drawOpt) { //******************************************************************** // First save the TTree eventVariables->Write(); // Save Flux and Event Histograms too GetInput()->GetFluxHistogram()->Write(); GetInput()->GetEventHistogram()->Write(); return; } //******************************************************************** void GenericFlux_Tester::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); } // ------------------------------------------------------------------- // Purely MC Plot // Following functions are just overrides to handle this // ------------------------------------------------------------------- //******************************************************************** /// Everything is classed as signal... bool GenericFlux_Tester::isSignal(FitEvent *event) { //******************************************************************** (void)event; return true; }; //******************************************************************** void GenericFlux_Tester::ScaleEvents() { //******************************************************************** // Saving everything to a TTree so no scaling required return; } //******************************************************************** void GenericFlux_Tester::ApplyNormScale(float norm) { //******************************************************************** // Saving everything to a TTree so no scaling required this->fCurrentNorm = norm; return; } //******************************************************************** void GenericFlux_Tester::FillHistograms() { //******************************************************************** // No Histograms need filling........ return; } //******************************************************************** void GenericFlux_Tester::ResetAll() { //******************************************************************** eventVariables->Reset(); return; } //******************************************************************** float GenericFlux_Tester::GetChi2() { //******************************************************************** // No Likelihood to test, purely MC return 0.0; } diff --git a/src/MCStudies/GenericFlux_Vectors.cxx b/src/MCStudies/GenericFlux_Vectors.cxx index 0197a73..da0a4ca 100644 --- a/src/MCStudies/GenericFlux_Vectors.cxx +++ b/src/MCStudies/GenericFlux_Vectors.cxx @@ -1,327 +1,334 @@ // 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 . -*******************************************************************************/ + * 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" -GenericFlux_Vectors::GenericFlux_Vectors(std::string name, std::string inputfile, - FitWeight *rw, std::string type, - std::string fakeDataFile) { +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"); + } + // 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. - fScaleFactor = - (GetEventHistogram()->Integral("width") * 1E-38 / (fNEvents + 0.)) / + // 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(); LOG(SAM) << " Generic Flux Scaling Factor = " << fScaleFactor << " [= " << (GetEventHistogram()->Integral("width") * 1E-38) << "/(" << (fNEvents + 0.) << "*" << this->TotalIntegratedFlux() << ")]" << std::endl; if (fScaleFactor <= 0.0) { ERR(WRN) << "SCALE FACTOR TOO LOW " << std::endl; throw; } // Setup our TTrees this->AddEventVariablesToTree(); 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()); } LOG(SAM) << "Adding Event Variables" << std::endl; - 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("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("PDGLep", &PDGLep, "PDGLep/I"); - eventVariables->Branch("ELep", &ELep, "ELep/F" ); + 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("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("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("x", &x, "x/F"); - eventVariables->Branch("y", &y, "y/F"); + eventVariables->Branch("W", &W, "W/F"); + eventVariables->Branch("x", &x, "x/F"); + eventVariables->Branch("y", &y, "y/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("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"); // 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); LOG(DEB) << "Filling signal" << std::endl; // Now fill the information Mode = event->Mode; cc = (abs(event->Mode) < 30); // Get the incoming neutrino and outgoing lepton - FitParticle *nu = event->GetNeutrinoIn(); + FitParticle *nu = event->GetNeutrinoIn(); FitParticle *lep = event->GetHMFSAnyLepton(); PDGnu = nu->fPID; - Enu_true = nu->fP.E()/1E3; + Enu_true = nu->fP.E() / 1E3; tgt = event->fTargetPDG; if (lep != NULL) { PDGLep = lep->fPID; - ELep = lep->fP.E()/1E3; + 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; + 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); + Q2_QE = FitUtils::Q2QErec(lep->fP, CosLep, 34., true); // 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); // True Q2 W = sqrt(-Q2 + 2 * m_n * q0 + m_n * m_n); - x = Q2/(2 * m_n * q0); - y = 1 - ELep/Enu_true; + x = Q2 / (2 * m_n * q0); + y = 1 - ELep / Enu_true; } // Loop over the particles and store all the final state particles in a vector for (UInt_t i = 0; i < event->Npart(); ++i) { - bool part_alive = event->PartInfo(i)->fIsAlive and event->PartInfo(i)->Status() == kFinalState; + bool part_alive = event->PartInfo(i)->fIsAlive && + event->PartInfo(i)->Status() == kFinalState; if (!part_alive) continue; - partList .push_back(event->PartInfo(i)); + partList.push_back(event->PartInfo(i)); } // Save outgoing particle vectors nfsp = (int)partList.size(); - 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; + 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; } // 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 = PDGLep = 0; Enu_true = ELep = CosLep = Q2 = q0 = q3 = Enu_QE = Q2_QE = W_nuc_rest = W = x = y = -999.9; nfsp = 0; for (int i = 0; i < kMAX; ++i){ px[i] = py[i] = pz[i] = E[i] = -999; pdg[i] = 0; } Weight = InputWeight = RWWeight = 0.0; CustomWeight = 0.0; for (int i = 0; i < 6; ++i) CustomWeightArray[i] = 0.0; partList.clear(); flagCCINC = flagNCINC = flagCCQE = flagCC0pi = flagCCQELike = flagNCEL = flagNC0pi = flagCCcoh = flagNCcoh = flagCC1pip = flagNC1pip = flagCC1pim = flagNC1pim = flagCC1pi0 = flagNC1pi0 = false; } //******************************************************************** 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); } void GenericFlux_Vectors::AddSignalFlagsToTree() { if (!eventVariables) { Config::Get().out->cd(); eventVariables = new TTree((this->fName + "_VARS").c_str(), (this->fName + "_VARS").c_str()); } LOG(SAM) << "Adding signal flags" << std::endl; // 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"); }; 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::ScaleEvents() { return; } void GenericFlux_Vectors::ApplyNormScale(float norm) { this->fCurrentNorm = norm; return; } -void GenericFlux_Vectors::FillHistograms() { - return; -} +void GenericFlux_Vectors::FillHistograms() { return; } void GenericFlux_Vectors::ResetAll() { eventVariables->Reset(); return; } -float GenericFlux_Vectors::GetChi2() { - return 0.0; -} +float GenericFlux_Vectors::GetChi2() { return 0.0; } diff --git a/src/MCStudies/GenericFlux_Vectors.h b/src/MCStudies/GenericFlux_Vectors.h index 9fc92c5..92a965c 100644 --- a/src/MCStudies/GenericFlux_Vectors.h +++ b/src/MCStudies/GenericFlux_Vectors.h @@ -1,125 +1,125 @@ // 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" 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; int Mode; bool cc; int PDGnu; int tgt; 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; - + // 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]; - + // 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; }; #endif diff --git a/src/MINERvA/MINERvA_CC1pi0_XSec_1D_nu.cxx b/src/MINERvA/MINERvA_CC1pi0_XSec_1D_nu.cxx index 39fa194..d3a797b 100644 --- a/src/MINERvA/MINERvA_CC1pi0_XSec_1D_nu.cxx +++ b/src/MINERvA/MINERvA_CC1pi0_XSec_1D_nu.cxx @@ -1,320 +1,320 @@ // 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_CC1pi0_XSec_1D_nu.h" // Implementation of 2017 MINERvA numu CC1pi0 // arxiv:1708.03723v1 hep-ex // c.wret14@imperial.ac.uk //******************************************************************** void MINERvA_CC1pi0_XSec_1D_nu::SetupDataSettings(){ //******************************************************************** // Set Distribution // See header file for enum and some descriptions std::string name = fSettings.GetS("name"); if (!name.compare("MINERvA_CC1pi0_XSec_1DTpi_nu")) fDist = kTpi; else if (!name.compare("MINERvA_CC1pi0_XSec_1Dth_nu")) fDist= kth; else if (!name.compare("MINERvA_CC1pi0_XSec_1Dpmu_nu")) fDist= kpmu; else if (!name.compare("MINERvA_CC1pi0_XSec_1Dthmu_nu")) fDist= kthmu; else if (!name.compare("MINERvA_CC1pi0_XSec_1DQ2_nu")) fDist= kQ2; else if (!name.compare("MINERvA_CC1pi0_XSec_1DEnu_nu")) fDist= kEnu; else if (!name.compare("MINERvA_CC1pi0_XSec_1DWexp_nu")) fDist= kWexp; else if (!name.compare("MINERvA_CC1pi0_XSec_1DPPi0Mass_nu")) fDist= kPPi0Mass; else if (!name.compare("MINERvA_CC1pi0_XSec_1DPPi0MassDelta_nu")) fDist= kPPi0MassDelta; else if (!name.compare("MINERvA_CC1pi0_XSec_1DCosAdler_nu")) fDist= kCosAdler; else if (!name.compare("MINERvA_CC1pi0_XSec_1DPhiAdler_nu")) fDist= kPhiAdler; // Define what files to use from the dist std::string datafile = ""; std::string corrfile = ""; std::string titles = ""; std::string distdescript = ""; // Set the default to essentially not be a cut on proton kinetic energy // The Adler angles and reconstructed p,pi0 invariant mass have cuts on these ProtonCut = 100; // W exp is 1.8 GeV or lower (dealt with below) WexpCut = 1.8; // Load up the data switch (fDist) { case (kTpi): datafile = "data/XSec_Table_pi0_KE_xsec.csv"; corrfile = "corr/Correlation_Table_pi0_KE_xsec.csv"; titles = "CC1#pi^{0};T_{#pi} (GeV);d#sigma/dT_{#pi} (cm^{2}/nucleon/GeV)"; break; case (kth): datafile = "data/XSec_Table_pi0_theta_xsec.csv"; corrfile = "corr/Correlation_Table_pi0_theta_xsec.csv"; titles = "CC1#pi^{0};#theta_{#pi} (degrees); d#sigma/d#theta_{#pi} (cm^{2}/nucleon/degree)"; break; case (kpmu): datafile = "data/XSec_Table_muon_P_xsec.csv"; corrfile = "corr/Correlation_Table_muon_P_xsec.csv"; titles = "CC1#pi^{0};p_{#mu} (GeV);d#sigma/dp_{#mu} (cm^{2}/nucleon/GeV)"; break; case (kthmu): datafile = "data/XSec_Table_muon_theta_xsec.csv"; corrfile = "corr/Correlation_Table_muon_theta_xsec.csv"; titles = "CC1#pi^{0};#theta_{#mu} (degrees);d#sigma/d#theta_{#mu} (cm^{2}/nucleon/degree)"; break; case (kQ2): datafile = "data/XSec_Table_QSq_xsec.csv"; corrfile = "corr/Correlation_Table_QSq_xsec.csv"; titles = "CC1#pi^{0};Q^{2} (GeV^{2});d#sigma/dQ^{2} (cm^{2}/nucleon/GeV^{2})"; break; case (kEnu): datafile = "data/XSec_Table_Enu_xsec.csv"; corrfile = "corr/Correlation_Table_Enu_xsec.csv"; titles = "CC1#pi^{0};E_{#nu} (GeV);#sigma(E_#nu) (cm^{2}/nucleon)"; break; case (kWexp): datafile = "data/XSec_Table_W_xsec.csv"; corrfile = "corr/Correlation_Table_W_xsec.csv"; titles = "CC1#pi^{0};W_{exp} (GeV);d#sigma/dW_{exp} (cm^{2}/nucleon/GeV)"; break; case (kPPi0Mass): datafile = "data/XSec_Table_deltaInvMass_xsec.csv"; corrfile = "corr/Correlation_Table_deltaInvMass_xsec.csv"; titles = "CC1#pi^{0}; M_{p#pi^{0}} (GeV); d#sigma/dM_{p#pi^{0}} (cm^{2}/nucleon/GeV)"; break; case (kPPi0MassDelta): datafile = "data/XSec_Table_deltaInvMass_xsec_DeltaRich.csv"; corrfile = "corr/Correlation_Table_deltaInvMass_xsec_DeltaRich.csv"; titles = "CC1#pi^{0}; M_{p#pi^{0}} W_{exp} < 1.4 (GeV); d#sigma/dM_{p#pi^{0}} (cm^{2}/nucleon/GeV)"; break; case (kCosAdler): datafile = "data/XSec_Table_Delta_pi_theta_xsec.csv"; corrfile = "corr/Correlation_Table_Delta_pi_theta_xsec.csv"; titles = "CC1#pi^{0}; cos#theta_{Adler}; d#sigma/dcos#theta_{Adler} (cm^{2}/nucleon/0.1)"; break; case (kPhiAdler): datafile = "data/XSec_Table_Delta_pi_phi_xsec.csv"; corrfile = "corr/Correlation_Table_Delta_pi_phi_xsec.csv"; titles = "CC1#pi^{0}; #phi_{Adler} (degrees); d#sigma/d#phi_{Adler} (cm^{2}/nucleon/degree)"; break; default: THROW("Unknown Analysis Distribution : " << fDist); } // Set the Wexp and proton kinetic energy cuts depending on sample // for Ppi0Mass distributions and Adler angles we require a proton of at least 100 MeV kinetic energy if (fDist >= kPPi0Mass) { ProtonCut = 0.1; // 0.1 GeV proton kinetic energy cut // Some distributions have a Wexp cut at 1.4 GeV which attempts to isolate delta production if (fDist >= kPPi0MassDelta) { WexpCut = 1.4; } } // Only have xsec covariance (not shape only) // Now setup each data distribution and description. std::string descrip = distdescript + \ "Target: CH \n" \ "Flux: MINERvA Forward Horn Current numu ONLY \n" \ "Signal: Any event with 1 muon, and 1pi0 in FS, no mesons, any nucleon(s). W < 1.8" \ "Alt Signal: Add in requirement of 1 proton with 100 MeV and sometimes W < 1.4"; fSettings.SetDescription(descrip); // Specify the data fSettings.SetDataInput( GeneralUtils::GetTopLevelDir()+"/data/MINERvA/CC1pi0/2017_nu/" + datafile); // And the correlations fSettings.SetCovarInput(GeneralUtils::GetTopLevelDir()+"/data/MINERvA/CC1pi0/2017_nu/" + corrfile); fSettings.SetTitle( GeneralUtils::ParseToStr(titles,";")[0] ); fSettings.SetXTitle( GeneralUtils::ParseToStr(titles,";")[1] ); fSettings.SetYTitle( GeneralUtils::ParseToStr(titles,";")[2] ); return; } //******************************************************************** MINERvA_CC1pi0_XSec_1D_nu::MINERvA_CC1pi0_XSec_1D_nu(nuiskey samplekey) { //******************************************************************** // Define Sample Settings common to all data distributions fSettings = LoadSampleSettings(samplekey); fSettings.SetAllowedTypes("FIX,FREE,SHAPE/DIAG,FULL/NORM/MASK", "FIX/FULL"); // From 1.5 to 20 GeV Enu fSettings.SetEnuRange(1.5, 20.0); fSettings.DefineAllowedTargets("C,H"); fSettings.DefineAllowedSpecies("numu"); SetupDataSettings(); FinaliseSampleSettings(); // Scaling Setup --------------------------------------------------- // If Enu setup scale factor for Enu Unfolded, otherwise use differential if (fDist == kEnu) fScaleFactor = GetEventHistogram()->Integral("width") * double(1E-38) / double(fNEvents); else fScaleFactor = GetEventHistogram()->Integral("width") * double(1E-38) / double(fNEvents) / TotalIntegratedFlux("width"); // Plot Setup ------------------------------------------------------- SetDataFromTextFile( fSettings.GetDataInput() ); // The errors come as a percent of the cross-section for this measurement so need rescaling // Have set the fDataHist above so just loop over and set new errors for (int i = 0; i < fDataHist->GetNbinsX(); ++i) { fDataHist->SetBinError(i+1, (fDataHist->GetBinError(i+1)/100.0)*fDataHist->GetBinContent(i+1)); } // And finally all the numbers are in units of 1E-40 so scale the histograms as such fDataHist->Scale(1.0E-40); // This measurement gives us a correlation matrix, so should set it up as such SetCorrelationFromTextFile( fSettings.GetCovarInput() ); // Final setup --------------------------------------------------- FinaliseMeasurement(); }; //******************************************************************** void MINERvA_CC1pi0_XSec_1D_nu::FillEventVariables(FitEvent *event) { //******************************************************************** fXVar = -999.9; // Need a neutral pion and a muon if (event->NumFSParticle(111) == 0 || event->NumFSParticle(13) == 0) { return; } // Get the TLorentzVectors from the event TLorentzVector Pnu = event->GetNeutrinoIn()->fP; TLorentzVector Ppi0 = event->GetHMFSParticle(111)->fP; TLorentzVector Pmu = event->GetHMFSParticle(13)->fP; // Pion kinetic energy double Tpi = (Ppi0.E() - Ppi0.Mag())/1.E3; // Pion-neutrino angle double th = (180./M_PI)*FitUtils::th(Pnu, Ppi0); // Muon momentum double pmu = Pmu.Vect().Mag()/1.E3; // Muon-neutrino angle double thmu = (180.0/M_PI)*FitUtils::th(Pnu, Pmu); // True Q2 double Q2 = fabs((Pmu - Pnu).Mag2()) / 1.E6; // True Enu double Enu = Pnu.E() / 1.E3; // Wexp (derived from "kinematic quantities" but uses EnuTrue) double Wexp = FitUtils::Wrec(Pnu, Pmu)/1.E3; // Wexp cut of 1.8 GeV in signal definition // N.B. the Adler angles and PPi0 mass requires this to be 1400 if (Wexp > WexpCut) return; // Some distributions require the final state proton: check that it exists if (fDist >= kPPi0Mass && event->NumFSParticle(2212) == 0) return; - + // Fill the variables depending on the enums switch (fDist) { case kTpi: fXVar = Tpi; break; case kth: fXVar = th; break; case kpmu: // Pmu has a theta_mu < 25degree cut if (thmu > 25) return; else fXVar = pmu; break; case kthmu: // thmu has a theta_mu < 25degree cut if (thmu > 25) return; else fXVar = pmu; fXVar = thmu; break; case kQ2: fXVar = Q2; break; case kEnu: fXVar = Enu; break; case kWexp: fXVar = Wexp; break; // p, pi0 invariant mass with Wexp < 1.8 or Wexp < 1.4: already checked these above case kPPi0Mass: case kPPi0MassDelta: { // Get the proton TLorentzVector Pprot = event->GetHMFSParticle(2212)->fP; double Ppi0Mass = (Ppi0+Pprot).Mag()/1.E3; fXVar = Ppi0Mass; break; } // Cos theta Adler angle case kCosAdler: { TLorentzVector Pprot = event->GetHMFSParticle(2212)->fP; double CosThAdler = FitUtils::CosThAdler(Pnu, Pmu, Ppi0, Pprot); fXVar = CosThAdler; break; } // Phi Adler angle case kPhiAdler: { TLorentzVector Pprot = event->GetHMFSParticle(2212)->fP; double PhiAdler = FitUtils::PhiAdler(Pnu, Pmu, Ppi0, Pprot); fXVar = PhiAdler; break; } default: THROW("DIST NOT FOUND : " << fDist); break; } }; //******************************************************************** bool MINERvA_CC1pi0_XSec_1D_nu::isSignal(FitEvent *event) { //******************************************************************** // Some of the distributions require a proton with at least 100 MeV KE if (fDist >= kPPi0Mass) { // First of needs a proton in the final state if (event->NumFSParticle(2212) == 0) return false; // Needs to pass CC1pi0 signal definition bool pass_cc1pi0 = SignalDef::isCC1pi0_MINERvA_nu(event, EnuMin, EnuMax); if (!pass_cc1pi0) return false; // And the proton needs at least 100 MeV kinetic energy TLorentzVector Pprot = event->GetHMFSParticle(2212)->fP; double ke = (Pprot.E() - Pprot.Mag())/1.E3; if (pass_cc1pi0 && ke > ProtonCut) { return true; } else { return false; } // The other distributions ahve a more generic "1mu, 1pi0, no mesons, any nucleon(s)" // The W cut is instead made in FillEventVariables } else { return SignalDef::isCC1pi0_MINERvA_nu(event, EnuMin, EnuMax); } } diff --git a/src/Reweight/NUISANCEWeightCalcs.cxx b/src/Reweight/NUISANCEWeightCalcs.cxx index 5f9020a..4e14b90 100644 --- a/src/Reweight/NUISANCEWeightCalcs.cxx +++ b/src/Reweight/NUISANCEWeightCalcs.cxx @@ -1,447 +1,443 @@ #include "NUISANCEWeightCalcs.h" #include "FitEvent.h" #include "GeneralUtils.h" #include "NUISANCESyst.h" #include "WeightUtils.h" using namespace Reweight; -ModeNormCalc::ModeNormCalc(){ - fNormRES = 1.0; -} +ModeNormCalc::ModeNormCalc() { fNormRES = 1.0; } double ModeNormCalc::CalcWeight(BaseFitEvt* evt) { int mode = abs(evt->Mode); double w = 1.0; if (mode == 11 or mode == 12 or mode == 13) { w *= fNormRES; } return w; } void ModeNormCalc::SetDialValue(std::string name, double val) { SetDialValue(Reweight::ConvDial(name, kCUSTOM), val); } void ModeNormCalc::SetDialValue(int rwenum, double val) { int curenum = rwenum % 1000; // Check Handled if (!IsHandled(curenum)) return; if (curenum == kModeNorm_NormRES) fNormRES = val; } bool ModeNormCalc::IsHandled(int rwenum) { - int curenum = rwenum % 1000; switch (curenum) { case kModeNorm_NormRES: return true; default: return false; } } SBLOscWeightCalc::SBLOscWeightCalc() { fDistance = 0.0; fMassSplitting = 0.0; fSin2Theta = 0.0; } double SBLOscWeightCalc::CalcWeight(BaseFitEvt* evt) { FitEvent* fevt = static_cast(evt); FitParticle* pnu = fevt->PartInfo(0); double E = pnu->fP.E() / 1.E3; // Extract energy return GetSBLOscWeight(E); } void SBLOscWeightCalc::SetDialValue(std::string name, double val) { SetDialValue(Reweight::ConvDial(name, kCUSTOM), val); } void SBLOscWeightCalc::SetDialValue(int rwenum, double val) { int curenum = rwenum % 1000; if (!IsHandled(curenum)) return; - if (curenum == kSBLOsc_Distance) fDistance = val; + if (curenum == kSBLOsc_Distance) fDistance = val; if (curenum == kSBLOsc_MassSplitting) fMassSplitting = val; - if (curenum == kSBLOsc_Sin2Theta) fSin2Theta = val; + if (curenum == kSBLOsc_Sin2Theta) fSin2Theta = val; } bool SBLOscWeightCalc::IsHandled(int rwenum) { - int curenum = rwenum % 1000; switch (curenum) { - case kSBLOsc_Distance: return true; - case kSBLOsc_MassSplitting: return true; - case kSBLOsc_Sin2Theta: return true; - default: return false; + case kSBLOsc_Distance: + return true; + case kSBLOsc_MassSplitting: + return true; + case kSBLOsc_Sin2Theta: + return true; + default: + return false; } } -double SBLOscWeightCalc::GetSBLOscWeight(double E){ +double SBLOscWeightCalc::GetSBLOscWeight(double E) { if (E <= 0.0) return 1.0 - 0.5 * fSin2Theta; - return 1.0 - fSin2Theta * pow( sin(1.267 * fMassSplitting * fDistance / E ), 2); + return 1.0 - fSin2Theta * pow(sin(1.267 * fMassSplitting * fDistance / E), 2); } - GaussianModeCorr::GaussianModeCorr() { // Apply the tilt-shift Gauss by Patrick // Alternatively set in config fMethod = true; // Init fApply_CCQE = false; fGausVal_CCQE[kPosNorm] = 0.0; fGausVal_CCQE[kPosTilt] = 0.0; fGausVal_CCQE[kPosPq0] = 1.0; fGausVal_CCQE[kPosWq0] = 1.0; fGausVal_CCQE[kPosPq3] = 1.0; fGausVal_CCQE[kPosWq3] = 1.0; fApply_2p2h = false; fGausVal_2p2h[kPosNorm] = 0.0; fGausVal_2p2h[kPosTilt] = 0.0; fGausVal_2p2h[kPosPq0] = 1.0; fGausVal_2p2h[kPosWq0] = 1.0; fGausVal_2p2h[kPosPq3] = 1.0; fGausVal_2p2h[kPosWq3] = 1.0; fApply_2p2h_PPandNN = false; fGausVal_2p2h_PPandNN[kPosNorm] = 0.0; fGausVal_2p2h_PPandNN[kPosTilt] = 0.0; fGausVal_2p2h_PPandNN[kPosPq0] = 1.0; fGausVal_2p2h_PPandNN[kPosWq0] = 1.0; fGausVal_2p2h_PPandNN[kPosPq3] = 1.0; fGausVal_2p2h_PPandNN[kPosWq3] = 1.0; fApply_2p2h_NP = false; fGausVal_2p2h_NP[kPosNorm] = 0.0; fGausVal_2p2h_NP[kPosTilt] = 0.0; fGausVal_2p2h_NP[kPosPq0] = 1.0; fGausVal_2p2h_NP[kPosWq0] = 1.0; fGausVal_2p2h_NP[kPosPq3] = 1.0; fGausVal_2p2h_NP[kPosWq3] = 1.0; fApply_CC1pi = false; fGausVal_CC1pi[kPosNorm] = 0.0; fGausVal_CC1pi[kPosTilt] = 0.0; fGausVal_CC1pi[kPosPq0] = 1.0; fGausVal_CC1pi[kPosWq0] = 1.0; fGausVal_CC1pi[kPosPq3] = 1.0; fGausVal_CC1pi[kPosWq3] = 1.0; fAllowSuppression = false; fDebugStatements = FitPar::Config().GetParB("GaussianModeCorr_DEBUG"); } double GaussianModeCorr::CalcWeight(BaseFitEvt* evt) { FitEvent* fevt = static_cast(evt); double rw_weight = 1.0; // Get Neutrino if (!fevt->Npart()) { THROW("NO particles found in stack!"); } FitParticle* pnu = fevt->GetHMISAnyLeptons(); if (!pnu) { THROW("NO Starting particle found in stack!"); } int pdgnu = pnu->fPID; int expect_fsleppdg = 0; if (pdgnu & 1) { expect_fsleppdg = pdgnu; } else { expect_fsleppdg = abs(pdgnu) - 1; } FitParticle* plep = fevt->GetHMFSParticle(expect_fsleppdg); if (!plep) return 1.0; TLorentzVector q = pnu->fP - plep->fP; // Extra q0,q3 double q0 = fabs(q.E()) / 1.E3; double q3 = fabs(q.Vect().Mag()) / 1.E3; int initialstate = -1; // Undef if (abs(fevt->Mode) == 2) { - int npr = 0; int nne = 0; for (UInt_t j = 0; j < fevt->Npart(); j++) { if ((fevt->PartInfo(j))->fIsAlive) continue; - if (fevt->PartInfo(j)->fPID == 2212) npr++; - else if (fevt->PartInfo(j)->fPID == 2112) nne++; + if (fevt->PartInfo(j)->fPID == 2212) + npr++; + else if (fevt->PartInfo(j)->fPID == 2112) + nne++; } - // std::cout << "PN State = " << npr << " " << nne << std::endl; - if (fevt->Mode == 2 and npr == 1 and nne == 1) { + if (fevt->Mode == 2 && npr == 1 && nne == 1) { initialstate = 2; - } else if (fevt->Mode == 2 and ((npr == 0 and nne == 2) or (npr == 2 and nne == 0))) { + } else if (fevt->Mode == 2 && ((npr == 0 && nne == 2) || (npr == 2 && nne == 0))) { initialstate = 1; } } - // std::cout << "Got q0 q3 = " << q0 << " " << q3 << std::endl; + if (fDebugStatements) std::cout << "Got q0 q3 = " << q0 << " " << q3 << std::endl; // Apply weighting - if (fApply_CCQE and abs(fevt->Mode) == 1) { + if (fApply_CCQE && abs(fevt->Mode) == 1) { if (fDebugStatements) std::cout << "Getting CCQE Weight" << std::endl; double g = GetGausWeight(q0, q3, fGausVal_CCQE); if (g < 1.0) g = 1.0; rw_weight *= g; } - if (fApply_2p2h and abs(fevt->Mode) == 2) { + if (fApply_2p2h && abs(fevt->Mode) == 2) { if (fDebugStatements) std::cout << "Getting 2p2h Weight" << std::endl; rw_weight *= GetGausWeight(q0, q3, fGausVal_2p2h); } - if (fApply_2p2h_PPandNN and abs(fevt->Mode) == 2 and initialstate == 1) { + if (fApply_2p2h_PPandNN && abs(fevt->Mode) == 2 && initialstate == 1) { if (fDebugStatements) std::cout << "Getting 2p2h PPandNN Weight" << std::endl; rw_weight *= GetGausWeight(q0, q3, fGausVal_2p2h_PPandNN); } - if (fApply_2p2h_NP and abs(fevt->Mode) == 2 and initialstate == 2) { + if (fApply_2p2h_NP && abs(fevt->Mode) == 2 && initialstate == 2) { if (fDebugStatements) std::cout << "Getting 2p2h NP Weight" << std::endl; rw_weight *= GetGausWeight(q0, q3, fGausVal_2p2h_NP); } - if (fApply_CC1pi and abs(fevt->Mode) >= 11 and abs(fevt->Mode) <= 13) { + if (fApply_CC1pi && abs(fevt->Mode) >= 11 && abs(fevt->Mode) <= 13) { if (fDebugStatements) std::cout << "Getting CC1pi Weight" << std::endl; rw_weight *= GetGausWeight(q0, q3, fGausVal_CC1pi); } - - - - // if (fDebugStatements) std::cout << "Returning Weight " << rw_weight << std::endl; + if (fDebugStatements) std::cout << "Returning Weight " << rw_weight << std::endl; return rw_weight; } void GaussianModeCorr::SetMethod(bool method) { fMethod = method; if (fMethod == true) { LOG(FIT) << " Using tilt-shift Gaussian parameters for Gaussian enhancement..." << std::endl; } else { LOG(FIT) << " Using Normal Gaussian parameters for Gaussian enhancement..." << std::endl; } }; double GaussianModeCorr::GetGausWeight(double q0, double q3, double vals[]) { // The weight double w = 1.0; // Use tilt-shift method by Patrick if (fMethod) { if (fDebugStatements) { std::cout << "Using Patrick gaussian" << std::endl; } // // CCQE Without Suppression // double Norm = 4.82788679036; // double Tilt = 2.3501416116; // double Pq0 = 0.363964889702; // double Wq0 = 0.133976806938; // double Pq3 = 0.431769740224; // double Wq3 = 0.207666663434; // // Also add for CCQE at the end // return (w > 1.0) ? w : 1.0; // // 2p2h with suppression // double Norm = 15.967; // double Tilt = -0.455655; // double Pq0 = 0.214598; // double Wq0 = 0.0291061; // double Pq3 = 0.480194; // double Wq3 = 0.134588; double Norm = vals[kPosNorm]; double Tilt = vals[kPosTilt]; double Pq0 = vals[kPosPq0]; double Wq0 = vals[kPosWq0]; double Pq3 = vals[kPosPq3]; double Wq3 = vals[kPosWq3]; double a = cos(Tilt) * cos(Tilt) / (2 * Wq0 * Wq0); a += sin(Tilt) * sin(Tilt) / (2 * Wq3 * Wq3); double b = -sin(2 * Tilt) / (4 * Wq0 * Wq0); b += sin(2 * Tilt) / (4 * Wq3 * Wq3); double c = sin(Tilt) * sin(Tilt) / (2 * Wq0 * Wq0); c += cos(Tilt) * cos(Tilt) / (2 * Wq3 * Wq3); w = Norm; w *= exp(-a * (q0 - Pq0) * (q0 - Pq0)); w *= exp(+2.0 * b * (q0 - Pq0) * (q3 - Pq3)); w *= exp(-c * (q3 - Pq3) * (q3 - Pq3)); if (fDebugStatements) { std::cout << "Applied Tilt " << Tilt << " " << cos(Tilt) << " " << sin(Tilt) << std::endl; std::cout << "abc = " << a << " " << b << " " << c << std::endl; std::cout << "Returning " << Norm << " " << Pq0 << " " << Wq0 << " " << Pq3 << " " << Wq3 << " " << w << std::endl; } if (w != w || std::isnan(w) || w < 0.0) { w = 0.0; } if (w < 1.0 and !fAllowSuppression) { w = 1.0; } // Use the MINERvA Gaussian method } else { /* * From MINERvA and Daniel Ruterbories: * Old notes here: * http://cdcvs.fnal.gov/cgi-bin/public-cvs/cvsweb-public.cgi/AnalysisFramework/Ana/CCQENu/ana_common/data/?cvsroot=mnvsoft * These parameters are slightly altered * * FRESH: * 10.5798 * 0.254032 * 0.50834 * 0.0571035 * 0.129051 * 0.875287 */ if (fDebugStatements) { std::cout << "Using MINERvA Gaussian" << std::endl; } double norm = vals[kPosNorm]; double meanq0 = vals[kPosTilt]; double meanq3 = vals[kPosPq0]; double sigmaq0 = vals[kPosWq0]; double sigmaq3 = vals[kPosPq3]; double corr = vals[kPosWq3]; double z = (q0 - meanq0)*(q0 - meanq0) /sigmaq0/sigmaq0 + (q3 - meanq3)*(q3 - meanq3) / sigmaq3/sigmaq3 - 2*corr*(q0-meanq0)*(q3-meanq3)/ (sigmaq0 * sigmaq3); double ret = norm*exp( -0.5 * z / (1 - corr*corr) ); //Need to add 1 to the results w = 1.0 + ret; } return w; } void GaussianModeCorr::SetDialValue(std::string name, double val) { SetDialValue(Reweight::ConvDial(name, kCUSTOM), val); } void GaussianModeCorr::SetDialValue(int rwenum, double val) { int curenum = rwenum % 1000; // Check Handled if (!IsHandled(curenum)) return; // CCQE Setting for (int i = kGaussianCorr_CCQE_norm; i <= kGaussianCorr_CCQE_Wq3; i++) { if (i == curenum) { int index = i - kGaussianCorr_CCQE_norm; fGausVal_CCQE[index] = val; fApply_CCQE = true; } } // 2p2h Setting for (int i = kGaussianCorr_2p2h_norm; i <= kGaussianCorr_2p2h_Wq3; i++) { if (i == curenum) { int index = i - kGaussianCorr_2p2h_norm; fGausVal_2p2h[index] = val; fApply_2p2h = true; } } // 2p2h_PPandNN Setting for (int i = kGaussianCorr_2p2h_PPandNN_norm; i <= kGaussianCorr_2p2h_PPandNN_Wq3; i++) { if (i == curenum) { int index = i - kGaussianCorr_2p2h_PPandNN_norm; fGausVal_2p2h_PPandNN[index] = val; fApply_2p2h_PPandNN = true; } } // 2p2h_NP Setting for (int i = kGaussianCorr_2p2h_NP_norm; i <= kGaussianCorr_2p2h_NP_Wq3; i++) { if (i == curenum) { int index = i - kGaussianCorr_2p2h_NP_norm; fGausVal_2p2h_NP[index] = val; fApply_2p2h_NP = true; } } // CC1pi Setting for (int i = kGaussianCorr_CC1pi_norm; i <= kGaussianCorr_CC1pi_Wq3; i++) { if (i == curenum) { int index = i - kGaussianCorr_CC1pi_norm; fGausVal_CC1pi[index] = val; fApply_CC1pi = true; } } if (curenum == kGaussianCorr_AllowSuppression) { fAllowSuppression = (val > 0.5); } } bool GaussianModeCorr::IsHandled(int rwenum) { int curenum = rwenum % 1000; switch (curenum) { case kGaussianCorr_CCQE_norm: case kGaussianCorr_CCQE_tilt: case kGaussianCorr_CCQE_Pq0: case kGaussianCorr_CCQE_Wq0: case kGaussianCorr_CCQE_Pq3: case kGaussianCorr_CCQE_Wq3: case kGaussianCorr_2p2h_norm: case kGaussianCorr_2p2h_tilt: case kGaussianCorr_2p2h_Pq0: case kGaussianCorr_2p2h_Wq0: case kGaussianCorr_2p2h_Pq3: case kGaussianCorr_2p2h_Wq3: case kGaussianCorr_2p2h_PPandNN_norm: case kGaussianCorr_2p2h_PPandNN_tilt: case kGaussianCorr_2p2h_PPandNN_Pq0: case kGaussianCorr_2p2h_PPandNN_Wq0: case kGaussianCorr_2p2h_PPandNN_Pq3: case kGaussianCorr_2p2h_PPandNN_Wq3: case kGaussianCorr_2p2h_NP_norm: case kGaussianCorr_2p2h_NP_tilt: case kGaussianCorr_2p2h_NP_Pq0: case kGaussianCorr_2p2h_NP_Wq0: case kGaussianCorr_2p2h_NP_Pq3: case kGaussianCorr_2p2h_NP_Wq3: case kGaussianCorr_CC1pi_norm: case kGaussianCorr_CC1pi_tilt: case kGaussianCorr_CC1pi_Pq0: case kGaussianCorr_CC1pi_Wq0: case kGaussianCorr_CC1pi_Pq3: case kGaussianCorr_CC1pi_Wq3: case kGaussianCorr_AllowSuppression: return true; default: return false; } } diff --git a/src/Reweight/OscWeightEngine.cxx b/src/Reweight/OscWeightEngine.cxx index bcb9292..1577175 100644 --- a/src/Reweight/OscWeightEngine.cxx +++ b/src/Reweight/OscWeightEngine.cxx @@ -1,329 +1,331 @@ // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret /******************************************************************************* * This file is part of NUISANCE. * * NUISANCE is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * NUISANCE is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with NUISANCE. If not, see . *******************************************************************************/ //#define DEBUG_OSC_WE #include "OscWeightEngine.h" #include enum nuTypes { kNuebarType = -1, kNumubarType = -2, kNutaubarType = -3, kNueType = 1, kNumuType = 2, kNutauType = 3, }; nuTypes GetNuType(int pdg) { switch (pdg) { case 16: return kNutauType; case 14: return kNumuType; case 12: return kNueType; case -16: return kNutaubarType; case -14: return kNumubarType; case -12: return kNuebarType; default: { THROW("Attempting to convert \"neutrino pdg\": " << pdg); } } } OscWeightEngine::OscWeightEngine() : #ifdef __PROB3PP_ENABLED__ bp(), #endif theta12(0.825), theta13(0.10), theta23(1.0), dm12(7.9e-5), dm23(2.5e-3), dcp(0.0), LengthParam(0xdeadbeef), TargetNuType(0), ForceFromNuPDG(0) { Config(); } void OscWeightEngine::Config() { std::vector OscParam = Config::QueryKeys("OscParam"); if (OscParam.size() < 1) { ERROR(WRN, "Oscillation parameters specified but no OscParam element " "configuring the experimental characteristics found.\nExpect at " "least . Pausing for " "10..."); sleep(10); return; } if (OscParam[0].Has("baseline_km")) { LengthParamIsZenith = false; LengthParam = OscParam[0].GetD("baseline_km"); constant_density = OscParam[0].Has("matter_density") ? OscParam[0].GetD("matter_density") : 0xdeadbeef; } else if (OscParam[0].Has("detection_zenith_deg")) { LengthParamIsZenith = true; static const double deg2rad = asin(1) / 90.0; LengthParam = cos(OscParam[0].GetD("detection_zenith_deg") * deg2rad); } else { ERROR(WRN, "It appeared that you wanted to set up an oscillation weight " "branch, but it was not correctly configured. You need to specify " "either: detection_zenith_deg or baseline_km attributes on the " "OscParam element, and if baseline_km is specified, you can " "optionally also set matter_density for oscillations through a " "constant matter density. Pausing for 10..."); sleep(10); return; } dm23 = OscParam[0].Has("dm23") ? OscParam[0].GetD("dm23") : dm23; theta23 = OscParam[0].Has("sinsq_theta23") ? OscParam[0].GetD("sinsq_theta23") : theta23; theta13 = OscParam[0].Has("sinsq_theta13") ? OscParam[0].GetD("sinsq_theta13") : theta13; dm12 = OscParam[0].Has("dm12") ? OscParam[0].GetD("dm12") : dm12; theta12 = OscParam[0].Has("sinsq_theta12") ? OscParam[0].GetD("sinsq_theta12") : theta12; dcp = OscParam[0].Has("dcp") ? OscParam[0].GetD("dcp") : dcp; TargetNuType = OscParam[0].Has("TargetNuPDG") ? GetNuType(OscParam[0].GetI("TargetNuPDG")) : 0; ForceFromNuPDG = OscParam[0].Has("ForceFromNuPDG") ? GetNuType(OscParam[0].GetI("ForceFromNuPDG")) : 0; QLOG(FIT, "Configured oscillation weighter:"); if (LengthParamIsZenith) { QLOG(FIT, "Earth density profile with detection cos(zenith) = " << LengthParam); } else { if (constant_density != 0xdeadbeef) { QLOG(FIT, "Constant density with experimental baseline = " << LengthParam); } else { QLOG(FIT, "Vacuum oscillations with experimental baseline = " << LengthParam); } } params[0] = dm23; params[1] = theta23; params[2] = theta13; params[3] = dm12; params[4] = theta12; params[5] = dcp; QLOG(FIT, "\tdm23 : " << params[0]); QLOG(FIT, "\tsinsq_theta23: " << params[1]); QLOG(FIT, "\tsinsq_theta13: " << params[2]); QLOG(FIT, "\tdm12 : " << params[3]); QLOG(FIT, "\tsinsq_theta12: " << params[4]); QLOG(FIT, "\tdcp : " << params[5]); if (TargetNuType) { QLOG(FIT, "\tTargetNuType: " << TargetNuType); } if (ForceFromNuPDG) { QLOG(FIT, "\tForceFromNuPDG: " << ForceFromNuPDG); } #ifdef __PROB3PP_ENABLED__ bp.SetMNS(params[theta12_idx], params[theta13_idx], params[theta23_idx], params[dm12_idx], params[dm23_idx], params[dcp_idx], 1, true, 2); bp.DefinePath(LengthParam, 0); - QLOG(FIT, "\tBaseline : " << (bp.GetBaseline() / 100.0) << " km."); + if (LengthParamIsZenith) { + QLOG(FIT, "\tBaseline : " << (bp.GetBaseline() / 100.0) << " km."); + } #endif } void OscWeightEngine::IncludeDial(std::string name, double startval) { #ifdef DEBUG_OSC_WE std::cout << "IncludeDial: " << name << " at " << startval << std::endl; #endif int dial = SystEnumFromString(name); if (!dial) { THROW("OscWeightEngine passed dial: " << name << " that it does not understand."); } params[dial - 1] = startval; } void OscWeightEngine::SetDialValue(int nuisenum, double val) { #ifdef DEBUG_OSC_WE std::cout << "SetDial: " << (nuisenum % 1000) << " at " << val << std::endl; #endif fHasChanged = (params[(nuisenum % 1000) - 1] - val) > std::numeric_limits::epsilon(); params[(nuisenum % 1000) - 1] = val; } void OscWeightEngine::SetDialValue(std::string name, double val) { #ifdef DEBUG_OSC_WE std::cout << "SetDial: " << name << " at " << val << std::endl; #endif int dial = SystEnumFromString(name); if (!dial) { THROW("OscWeightEngine passed dial: " << name << " that it does not understand."); } fHasChanged = (params[dial - 1] - val) > std::numeric_limits::epsilon(); params[dial - 1] = val; } bool OscWeightEngine::IsDialIncluded(std::string name) { return SystEnumFromString(name); } bool OscWeightEngine::IsDialIncluded(int nuisenum) { return ((nuisenum % 1000) > 0) && ((nuisenum % 1000) < 6); } double OscWeightEngine::GetDialValue(std::string name) { int dial = SystEnumFromString(name); if (!dial) { THROW("OscWeightEngine passed dial: " << name << " that it does not understand."); } return params[dial - 1]; } double OscWeightEngine::GetDialValue(int nuisenum) { if (!(nuisenum % 1000) || (nuisenum % 1000) > 6) { THROW("OscWeightEngine passed dial enum: " << (nuisenum % 1000) << " that it does not understand, expected [1,6]."); } return params[(nuisenum % 1000) - 1]; } void OscWeightEngine::Reconfigure(bool silent) { fHasChanged = false; }; bool OscWeightEngine::NeedsEventReWeight() { if (fHasChanged) { return true; } return false; } double OscWeightEngine::CalcWeight(BaseFitEvt* evt) { static bool Warned = false; if (evt->probe_E == 0xdeadbeef) { if (!Warned) { ERROR(WRN, "Oscillation weights asked for but using 'litemode' or " "unsupported generator input. Pasuing for 10..."); sleep(10); Warned = true; } return 1; } return CalcWeight(evt->probe_E * 1E-3, evt->probe_pdg); } double OscWeightEngine::CalcWeight(double ENu, int PDGNu, int TargetPDGNu) { if (LengthParam == 0xdeadbeef) { // not configured. return 1; } #ifdef __PROB3PP_ENABLED__ int NuType = (ForceFromNuPDG != 0) ? ForceFromNuPDG : GetNuType(PDGNu); bp.SetMNS(params[theta12_idx], params[theta13_idx], params[theta23_idx], params[dm12_idx], params[dm23_idx], params[dcp_idx], ENu, true, NuType); int pmt = 0; double prob_weight = 1; TargetPDGNu = (TargetPDGNu == -1) ? (TargetNuType ? TargetNuType : NuType) : GetNuType(TargetPDGNu); if (LengthParamIsZenith) { // Use earth density bp.DefinePath(LengthParam, 0); bp.propagate(NuType); pmt = 0; prob_weight = bp.GetProb(NuType, TargetPDGNu); } else { if (constant_density != 0xdeadbeef) { bp.propagateLinear(NuType, LengthParam, constant_density); pmt = 1; prob_weight = bp.GetProb(NuType, TargetPDGNu); } else { pmt = 2; prob_weight = bp.GetVacuumProb(NuType, TargetPDGNu, ENu * 1E-3, LengthParam); } } #ifdef DEBUG_OSC_WE if (prob_weight != prob_weight) { THROW("Calculated bad prob weight: " << prob_weight << "(Osc Type: " << pmt << " -- " << NuType << " -> " << TargetPDGNu << ")"); } if (prob_weight > 1) { THROW("Calculated bad prob weight: " << prob_weight << "(Osc Type: " << pmt << " -- " << NuType << " -> " << TargetPDGNu << ")"); } std::cout << NuType << " -> " << TargetPDGNu << ": " << ENu << " = " << prob_weight << "%%." << std::endl; #endif return prob_weight; #else return 1; #endif } int OscWeightEngine::SystEnumFromString(std::string const& name) { if (name == "dm23") { return 1; } else if (name == "sinsq_theta23") { return 2; } else if (name == "sinsq_theta13") { return 3; } else if (name == "dm12") { return 4; } else if (name == "sinsq_theta12") { return 5; } else if (name == "dcp") { return 6; } else { return 0; } } void OscWeightEngine::Print() { std::cout << "OscWeightEngine: " << std::endl; std::cout << "\t theta12: " << params[theta12_idx] << std::endl; std::cout << "\t theta13: " << params[theta13_idx] << std::endl; std::cout << "\t theta23: " << params[theta23_idx] << std::endl; std::cout << "\t dm12: " << params[dm12_idx] << std::endl; std::cout << "\t dm23: " << params[dm23_idx] << std::endl; std::cout << "\t dcp: " << params[dcp_idx] << std::endl; } diff --git a/src/Reweight/OscWeightEngine.h b/src/Reweight/OscWeightEngine.h index 8cacff7..774fb99 100644 --- a/src/Reweight/OscWeightEngine.h +++ b/src/Reweight/OscWeightEngine.h @@ -1,143 +1,144 @@ // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret /******************************************************************************* * This file is part of NUISANCE. * * NUISANCE is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * NUISANCE is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with NUISANCE. If not, see . *******************************************************************************/ #include "FitLogger.h" #include "FitEvent.h" #include "PhysConst.h" #include "WeightEngineBase.h" #ifdef __PROB3PP_ENABLED__ #include "BargerPropagator.h" #endif #include #ifdef __PROB3PP_ENABLED__ class BG : public BargerPropagator { public: BG() : BargerPropagator(){}; double GetBaseline() { return Earth->get_Pathlength(); } }; #endif class OscWeightEngine : public WeightEngineBase { enum params { dm23_idx = 0, theta23_idx, theta13_idx, dm12_idx, theta12_idx, dcp_idx, }; #ifdef __PROB3PP_ENABLED__ BG bp; #endif //******************************* Osc params ****************************** double theta12; double theta13; double theta23; /// The 1-2 mass squared splitting (small) [eV] double dm12; /// The 2-3 mass squared splitting (large) [eV] double dm23; /// The PMNS CP-violating phase double dcp; ///\brief The constant matter density used for simple given baseline /// oscillation [g/cm^3] double constant_density; /// Whether LengthParam corresponds to a Zenith or a baseline. /// /// If we just want to calculate the osc. prob. with a constant matter density /// then this should be false and constant_density should be set /// (or 0 for vacuum prob). bool LengthParamIsZenith; /// Either a path length or a post oscillation zenith angle /// /// N.B. For a beamline that has a dip angle of X degrees, the post /// oscillation zenith angle will be 90+X degrees. double LengthParam; /// Holds current value of oscillation parameters. double params[6]; /// The oscillation target type /// /// If unspecified in the element, it will default to /// disappearance probability. int TargetNuType; /// The initial neutrino species /// /// If unspecified in the element, it will be determined by /// the incoming events. int ForceFromNuPDG; public: OscWeightEngine(); /// Configures oscillation parameters from input xml file. /// /// Osc parameters configured from OscParam XML element as: /// /// /// /// If matter_density and baseline are present, then oscillation probability /// is calculated for a constant matter density. /// If detection_zenith_deg is present, then the baseline and density are /// calculated from the density profile and radius of the earth. /// If none are present, a vacuum oscillation is calculated. /// If TargetNuPDG is unspecified, oscillation will default to /// disappearance probability. void Config(); // Functions requiring Override void IncludeDial(std::string name, double startval); void SetDialValue(int nuisenum, double val); void SetDialValue(std::string name, double val); bool IsDialIncluded(std::string name); bool IsDialIncluded(int nuisenum); double GetDialValue(std::string name); double GetDialValue(int nuisenum); void Reconfigure(bool silent); bool NeedsEventReWeight(); double CalcWeight(BaseFitEvt* evt); + /// ENu [GeV] double CalcWeight(double ENu, int PDGNu, int TargetPDGNu = -1); static int SystEnumFromString(std::string const& name); void Print(); }; diff --git a/src/Routines/MinimizerRoutines.cxx b/src/Routines/MinimizerRoutines.cxx index 24cd30d..19acb7f 100755 --- a/src/Routines/MinimizerRoutines.cxx +++ b/src/Routines/MinimizerRoutines.cxx @@ -1,1506 +1,1517 @@ // 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 "MinimizerRoutines.h" #include "Simple_MH_Sampler.h" /* Constructor/Destructor */ //************************ void MinimizerRoutines::Init() { //************************ fInputFile = ""; fInputRootFile = NULL; fOutputFile = ""; fOutputRootFile = NULL; fCovar = NULL; fCovFree = NULL; fCorrel = NULL; fCorFree = NULL; fDecomp = NULL; fDecFree = NULL; fStrategy = "Migrad,FixAtLimBreak,Migrad"; fRoutines.clear(); fCardFile = ""; fFakeDataInput = ""; fSampleFCN = NULL; fMinimizer = NULL; fMinimizerFCN = NULL; fCallFunctor = NULL; fAllowedRoutines = ("Migrad,Simplex,Combined," "Brute,Fumili,ConjugateFR," "ConjugatePR,BFGS,BFGS2," "SteepDesc,GSLSimAn,FixAtLim,FixAtLimBreak," "Chi2Scan1D,Chi2Scan2D,Contours,ErrorBands," "DataToys,MCMC"); }; //************************************* MinimizerRoutines::~MinimizerRoutines(){ //************************************* }; /* Input Functions */ //************************************* +MinimizerRoutines::MinimizerRoutines() { +//************************************* + Init(); +} + +//************************************* MinimizerRoutines::MinimizerRoutines(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, "-d", fFakeDataInput, 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()) { ERR(FTL) << "No input supplied!" << std::endl; throw; } if (fOutputFile.empty() and !fCardFile.empty()) { fOutputFile = fCardFile + ".root"; ERR(WRN) << "No output supplied so saving it to: " << fOutputFile << std::endl; } else if (fOutputFile.empty()) { ERR(FTL) << "No output file or cardfile supplied!" << std::endl; throw; } // 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 (!fCardFile.empty()) fCompKey.Set("cardfile", fCardFile); if (!fOutputFile.empty()) fCompKey.Set("outputfile", fOutputFile); - if (!fStrategy.empty()) fCompKey.Set("strategy", fStrategy); + if (!fStrategy.empty()) fCompKey.Set("strategy", fStrategy); // Load XML Cardfile - configuration.LoadSettings( fCompKey.GetS("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; // FitPar::log_verb = verbocount; SETVERBOSITY(verbocount); // ERR_VERB(errorcount); // Minimizer Setup ======================================== fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE"); SetupMinimizerFromXML(); SetupCovariance(); SetupRWEngine(); SetupFCN(); return; }; //************************************* void MinimizerRoutines::SetupMinimizerFromXML() { //************************************* LOG(FIT) << "Setting up nuismin" << std::endl; // Setup Parameters ------------------------------------------ std::vector parkeys = Config::QueryKeys("parameter"); if (!parkeys.empty()) { LOG(FIT) << "Number of parameters : " << parkeys.size() << std::endl; } for (size_t i = 0; i < parkeys.size(); i++) { nuiskey key = parkeys.at(i); // Check for type,name,nom if (!key.Has("type")) { ERR(FTL) << "No type given for parameter " << i << std::endl; throw; } else if (!key.Has("name")) { ERR(FTL) << "No name given for parameter " << i << std::endl; throw; } else if (!key.Has("nominal")) { ERR(FTL) << "No nominal given for parameter " << i << std::endl; throw; } // 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 state if none 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"); LOG(FIT) << "Read " << partype << " : " << parname << " = " << parnom << " : " << parlow << " < p < " << parhigh << " : " << parstate << std::endl; } else { LOG(FIT) << "Read " << partype << " : " << parname << " = " << parnom << " : " << parstate << std::endl; } // Run Parameter Conversion if needed if (parstate.find("ABS") != std::string::npos) { + double opnom = parnom; + double oparstep = parstep; parnom = FitBase::RWAbsToSigma(partype, parname, parnom); parlow = FitBase::RWAbsToSigma(partype, parname, parlow); parhigh = FitBase::RWAbsToSigma(partype, parname, parhigh); - parstep = FitBase::RWAbsToSigma(partype, parname, parstep); + parstep = + FitBase::RWAbsToSigma(partype, parname, opnom + parstep) - parnom; + std::cout << "ParStep: " << parstep << " (" << oparstep << ")." + << std::endl; } 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()) { LOG(FIT) << "Number of samples : " << samplekeys.size() << std::endl; } 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 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 << std::endl; // 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; fStartVals[normname] = samplenorm; 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()) { LOG(FIT) << "Number of fake parameters : " << fakekeys.size() << std::endl; } for (size_t i = 0; i < fakekeys.size(); i++) { nuiskey key = fakekeys.at(i); // Check for type,name,nom if (!key.Has("name")) { ERR(FTL) << "No name given for fakeparameter " << i << std::endl; throw; } else if (!key.Has("nom")) { ERR(FTL) << "No nominal given for fakeparameter " << i << std::endl; throw; } // Get Inputs std::string parname = key.GetS("name"); double parnom = key.GetD("nom"); // Push into vectors fFakeVals[parname] = parnom; } } /* Setup Functions */ //************************************* void MinimizerRoutines::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 MinimizerRoutines::SetupFCN() { //************************************* LOG(FIT) << "Making the jointFCN" << std::endl; if (fSampleFCN) delete fSampleFCN; // fSampleFCN = new JointFCN(fCardFile, fOutputRootFile); fSampleFCN = new JointFCN(fOutputRootFile); SetFakeData(); fMinimizerFCN = new MinimizerFCN(fSampleFCN); fCallFunctor = new ROOT::Math::Functor(*fMinimizerFCN, fParams.size()); fSampleFCN->CreateIterationTree("fit_iterations", FitBase::GetRW()); return; } //****************************************** void MinimizerRoutines::SetupFitter(std::string routine) { //****************************************** // Make the fitter std::string fitclass = ""; std::string fittype = ""; bool UseMCMC = false; // Get correct types if (!routine.compare("Migrad")) { fitclass = "Minuit2"; fittype = "Migrad"; } else if (!routine.compare("Simplex")) { fitclass = "Minuit2"; fittype = "Simplex"; } else if (!routine.compare("Combined")) { fitclass = "Minuit2"; fittype = "Combined"; } else if (!routine.compare("Brute")) { fitclass = "Minuit2"; fittype = "Scan"; } else if (!routine.compare("Fumili")) { fitclass = "Minuit2"; fittype = "Fumili"; } else if (!routine.compare("ConjugateFR")) { fitclass = "GSLMultiMin"; fittype = "ConjugateFR"; } else if (!routine.compare("ConjugatePR")) { fitclass = "GSLMultiMin"; fittype = "ConjugatePR"; } else if (!routine.compare("BFGS")) { fitclass = "GSLMultiMin"; fittype = "BFGS"; } else if (!routine.compare("BFGS2")) { fitclass = "GSLMultiMin"; fittype = "BFGS2"; } else if (!routine.compare("SteepDesc")) { fitclass = "GSLMultiMin"; fittype = "SteepestDescent"; // } else if (!routine.compare("GSLMulti")) { fitclass = "GSLMultiFit"; // fittype = ""; // Doesn't work out of the box } else if (!routine.compare("GSLSimAn")) { fitclass = "GSLSimAn"; fittype = ""; } else if (!routine.compare("MCMC")) { UseMCMC = true; } // make minimizer if (fMinimizer) delete fMinimizer; if (UseMCMC) { fMinimizer = new Simple_MH_Sampler(); } else { fMinimizer = ROOT::Math::Factory::CreateMinimizer(fitclass, fittype); } fMinimizer->SetMaxFunctionCalls( FitPar::Config().GetParI("MAXCALLS")); if (!routine.compare("Brute")) { fMinimizer->SetMaxFunctionCalls(fParams.size() * fParams.size() * 4); fMinimizer->SetMaxIterations(fParams.size() * fParams.size() * 4); } fMinimizer->SetMaxIterations( FitPar::Config().GetParI("MAXITERATIONS")); fMinimizer->SetTolerance(FitPar::Config().GetParD("TOLERANCE")); fMinimizer->SetStrategy(FitPar::Config().GetParI("STRATEGY")); fMinimizer->SetFunction(*fCallFunctor); int ipar = 0; // Add Fit Parameters for (UInt_t i = 0; i < fParams.size(); i++) { std::string syst = fParams.at(i); bool fixed = true; double vstart, vstep, vlow, vhigh; vstart = vstep = vlow = vhigh = 0.0; if (fCurVals.find(syst) != fCurVals.end()) vstart = fCurVals.at(syst); if (fMinVals.find(syst) != fMinVals.end()) vlow = fMinVals.at(syst); if (fMaxVals.find(syst) != fMaxVals.end()) vhigh = fMaxVals.at(syst); if (fStepVals.find(syst) != fStepVals.end()) vstep = fStepVals.at(syst); if (fFixVals.find(syst) != fFixVals.end()) fixed = fFixVals.at(syst); // fix for errors if (vhigh == vlow) vhigh += 1.0; fMinimizer->SetVariable(ipar, syst, vstart, vstep); fMinimizer->SetVariableLimits(ipar, vlow, vhigh); if (fixed) { fMinimizer->FixVariable(ipar); LOG(FIT) << "Fixed Param: " << syst << std::endl; } else { LOG(FIT) << "Free Param: " << syst << " Start:" << vstart << " Range:" << vlow << " to " << vhigh << " Step:" << vstep << std::endl; } ipar++; } LOG(FIT) << "Setup Minimizer: " << fMinimizer->NDim() << "(NDim) " << fMinimizer->NFree() << "(NFree)" << std::endl; return; } //************************************* // Set fake data from user input void MinimizerRoutines::SetFakeData() { //************************************* // If the fake data input field (-d) isn't provided, return to caller if (fFakeDataInput.empty()) return; // If user specifies -d MC we set the data to the MC // User can also specify fake data parameters to reweight by doing // "fake_parameter" in input card file // "fake_parameter" gets read in ReadCard function (reads to fFakeVals) if (fFakeDataInput.compare("MC") == 0) { LOG(FIT) << "Setting fake data from MC starting prediction." << std::endl; // fFakeVals get read in in ReadCard UpdateRWEngine(fFakeVals); // Reconfigure the reweight engine FitBase::GetRW()->Reconfigure(); // Reconfigure all the samples to the new reweight fSampleFCN->ReconfigureAllEvents(); // Feed on and set the fake-data in each measurement class fSampleFCN->SetFakeData("MC"); // Changed the reweight engine values back to the current values // So we start the fit at a different value than what we set the fake-data // to UpdateRWEngine(fCurVals); LOG(FIT) << "Set all data to fake MC predictions." << std::endl; } else { fSampleFCN->SetFakeData(fFakeDataInput); } return; } /* Fitting Functions */ //************************************* void MinimizerRoutines::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 MinimizerRoutines::Run() { //************************************* LOG(FIT) << "Running MinimizerRoutines : " << fStrategy << std::endl; if (FitPar::Config().GetParB("save_nominal")) { SaveNominal(); } // Parse given routines fRoutines = GeneralUtils::ParseToStr(fStrategy, ","); if (fRoutines.empty()) { ERR(FTL) << "Trying to run MinimizerRoutines with no routines given!" << std::endl; throw; } for (UInt_t i = 0; i < fRoutines.size(); i++) { std::string routine = fRoutines.at(i); int fitstate = kFitUnfinished; LOG(FIT) << "Running Routine: " << routine << std::endl; // Try Routines if (routine.find("LowStat") != std::string::npos) LowStatRoutine(routine); else if (routine == "FixAtLim") FixAtLimit(); else if (routine == "FixAtLimBreak") fitstate = FixAtLimit(); else if (routine.find("ErrorBands") != std::string::npos) GenerateErrorBands(); else if (routine.find("DataToys") != std::string::npos) ThrowDataToys(); else if (!routine.compare("Chi2Scan1D")) Create1DScans(); else if (!routine.compare("Chi2Scan2D")) Chi2Scan2D(); else fitstate = RunFitRoutine(routine); // If ending early break here if (fitstate == kFitFinished || fitstate == kNoChange) { LOG(FIT) << "Ending fit routines loop." << std::endl; break; } } return; } //************************************* int MinimizerRoutines::RunFitRoutine(std::string routine) { //************************************* int endfits = kFitUnfinished; // set fitter at the current start values fOutputRootFile->cd(); SetupFitter(routine); // choose what to do with the minimizer depending on routine. if (!routine.compare("Migrad") or !routine.compare("Simplex") or !routine.compare("Combined") or !routine.compare("Brute") or !routine.compare("Fumili") or !routine.compare("ConjugateFR") or !routine.compare("ConjugatePR") or !routine.compare("BFGS") or !routine.compare("BFGS2") or !routine.compare("SteepDesc") or // !routine.compare("GSLMulti") or !routine.compare("GSLSimAn") or !routine.compare("MCMC")) { if (fMinimizer->NFree() > 0) { LOG(FIT) << fMinimizer->Minimize() << std::endl; GetMinimizerState(); } } // other otptions else if (!routine.compare("Contour")) { CreateContours(); } return endfits; } //************************************* void MinimizerRoutines::PrintState() { //************************************* LOG(FIT) << "------------" << std::endl; // Count max size int maxcount = 0; for (UInt_t i = 0; i < fParams.size(); i++) { maxcount = max(int(fParams[i].size()), maxcount); } // Header 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::endl; // 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; LOG(FIT) << curparstring.str() << std::endl; } LOG(FIT) << "------------" << std::endl; double like = fSampleFCN->GetLikelihood(); LOG(FIT) << std::left << std::setw(46) << "Likelihood for JointFCN: " << like << std::endl; LOG(FIT) << "------------" << std::endl; } //************************************* void MinimizerRoutines::GetMinimizerState() { //************************************* LOG(FIT) << "Minimizer State: " << std::endl; // Get X and Err const double* values = fMinimizer->X(); const double* errors = fMinimizer->Errors(); // int ipar = 0; for (UInt_t i = 0; i < fParams.size(); i++) { std::string syst = fParams.at(i); fCurVals[syst] = values[i]; fErrorVals[syst] = errors[i]; } PrintState(); // Covar SetupCovariance(); if (fMinimizer->CovMatrixStatus() > 0) { // Fill Full Covar std::cout << "Filling covariance" << std::endl; for (int i = 0; i < fCovar->GetNbinsX(); i++) { for (int j = 0; j < fCovar->GetNbinsY(); j++) { fCovar->SetBinContent(i + 1, j + 1, fMinimizer->CovMatrix(i, j)); } } int freex = 0; int freey = 0; for (int i = 0; i < fCovar->GetNbinsX(); i++) { if (fMinimizer->IsFixedVariable(i)) continue; freey = 0; for (int j = 0; j < fCovar->GetNbinsY(); j++) { if (fMinimizer->IsFixedVariable(j)) continue; fCovFree->SetBinContent(freex + 1, freey + 1, fMinimizer->CovMatrix(i, j)); freey++; } freex++; } fCorrel = PlotUtils::GetCorrelationPlot(fCovar, "correlation"); fDecomp = PlotUtils::GetDecompPlot(fCovar, "decomposition"); if (fMinimizer->NFree() > 0) { fCorFree = PlotUtils::GetCorrelationPlot(fCovFree, "correlation_free"); fDecFree = PlotUtils::GetDecompPlot(fCovFree, "decomposition_free"); } } std::cout << "Got STATE" << std::endl; return; }; //************************************* void MinimizerRoutines::LowStatRoutine(std::string routine) { //************************************* LOG(FIT) << "Running Low Statistics Routine: " << routine << std::endl; int lowstatsevents = FitPar::Config().GetParI("LOWSTATEVENTS"); int maxevents = FitPar::Config().GetParI("MAXEVENTS"); int verbosity = FitPar::Config().GetParI("VERBOSITY"); std::string trueroutine = routine; std::string substring = "LowStat"; trueroutine.erase(trueroutine.find(substring), substring.length()); // Set MAX EVENTS=1000 Config::SetPar("MAXEVENTS", lowstatsevents); Config::SetPar("VERBOSITY", 3); SetupFCN(); RunFitRoutine(trueroutine); Config::SetPar("MAXEVENTS", maxevents); SetupFCN(); Config::SetPar("VERBOSITY", verbosity); return; } //************************************* void MinimizerRoutines::Create1DScans() { //************************************* // 1D Scan Routine // Steps through all free parameters about nominal using the step size // Creates a graph for each free parameter // At the current point create a 1D Scan for all parametes (Uncorrelated) for (UInt_t i = 0; i < fParams.size(); i++) { if (fFixVals[fParams[i]]) continue; LOG(FIT) << "Running 1D Scan for " << fParams[i] << std::endl; fSampleFCN->CreateIterationTree(fParams[i] + "_scan1D_iterations", FitBase::GetRW()); double scanmiddlepoint = fCurVals[fParams[i]]; // Determine N points needed double limlow = fMinVals[fParams[i]]; double limhigh = fMaxVals[fParams[i]]; double step = fStepVals[fParams[i]]; int npoints = int(fabs(limhigh - limlow) / (step + 0.)); TH1D* contour = new TH1D(("Chi2Scan1D_" + fParams[i]).c_str(), ("Chi2Scan1D_" + fParams[i] + ";" + fParams[i]).c_str(), npoints, limlow, limhigh); // Fill bins for (int x = 0; x < contour->GetNbinsX(); x++) { // Set X Val fCurVals[fParams[i]] = contour->GetXaxis()->GetBinCenter(x + 1); // Run Eval double* vals = FitUtils::GetArrayFromMap(fParams, fCurVals); double chi2 = fSampleFCN->DoEval(vals); delete vals; // Fill Contour contour->SetBinContent(x + 1, chi2); } // Save contour contour->Write(); // Reset Parameter fCurVals[fParams[i]] = scanmiddlepoint; // Save TTree fSampleFCN->WriteIterationTree(); } return; } //************************************* void MinimizerRoutines::Chi2Scan2D() { //************************************* // Chi2 Scan 2D // Creates a 2D chi2 scan by stepping through all free parameters // Works for all pairwise combos of free parameters // Scan I for (UInt_t i = 0; i < fParams.size(); i++) { if (fFixVals[fParams[i]]) continue; // Scan J for (UInt_t j = 0; j < i; j++) { if (fFixVals[fParams[j]]) continue; fSampleFCN->CreateIterationTree( fParams[i] + "_" + fParams[j] + "_" + "scan2D_iterations", FitBase::GetRW()); double scanmid_i = fCurVals[fParams[i]]; double scanmid_j = fCurVals[fParams[j]]; double limlow_i = fMinVals[fParams[i]]; double limhigh_i = fMaxVals[fParams[i]]; double step_i = fStepVals[fParams[i]]; double limlow_j = fMinVals[fParams[j]]; double limhigh_j = fMaxVals[fParams[j]]; double step_j = fStepVals[fParams[j]]; int npoints_i = int(fabs(limhigh_i - limlow_i) / (step_i + 0.)) + 1; int npoints_j = int(fabs(limhigh_j - limlow_j) / (step_j + 0.)) + 1; TH2D* contour = new TH2D( ("Chi2Scan2D_" + fParams[i] + "_" + fParams[j]).c_str(), ("Chi2Scan2D_" + fParams[i] + "_" + fParams[j] + ";" + fParams[i] + ";" + fParams[j]) .c_str(), npoints_i, limlow_i, limhigh_i, npoints_j, limlow_j, limhigh_j); // Begin Scan LOG(FIT) << "Running scan for " << fParams[i] << " " << fParams[j] << std::endl; // Fill bins for (int x = 0; x < contour->GetNbinsX(); x++) { // Set X Val fCurVals[fParams[i]] = contour->GetXaxis()->GetBinCenter(x + 1); // Loop Y for (int y = 0; y < contour->GetNbinsY(); y++) { // Set Y Val fCurVals[fParams[j]] = contour->GetYaxis()->GetBinCenter(y + 1); // Run Eval double* vals = FitUtils::GetArrayFromMap(fParams, fCurVals); double chi2 = fSampleFCN->DoEval(vals); delete vals; // Fill Contour contour->SetBinContent(x + 1, y + 1, chi2); fCurVals[fParams[j]] = scanmid_j; } fCurVals[fParams[i]] = scanmid_i; fCurVals[fParams[j]] = scanmid_j; } // Save contour contour->Write(); // Save Iterations fSampleFCN->WriteIterationTree(); } } return; } //************************************* void MinimizerRoutines::CreateContours() { //************************************* // Use MINUIT for this if possible ERR(FTL) << " Contours not yet implemented as it is really slow!" << std::endl; throw; return; } //************************************* int MinimizerRoutines::FixAtLimit() { //************************************* bool fixedparam = false; for (UInt_t i = 0; i < fParams.size(); i++) { std::string syst = fParams.at(i); if (fFixVals[syst]) continue; double curVal = fCurVals.at(syst); double minVal = fMinVals.at(syst); double maxVal = fMinVals.at(syst); if (fabs(curVal - minVal) < 0.0001) { fCurVals[syst] = minVal; fFixVals[syst] = true; fixedparam = true; } if (fabs(maxVal - curVal) < 0.0001) { fCurVals[syst] = maxVal; fFixVals[syst] = true; fixedparam = true; } } if (!fixedparam) { LOG(FIT) << "No dials needed fixing!" << std::endl; return kNoChange; } else return kStateChange; } /* Write Functions */ //************************************* void MinimizerRoutines::SaveResults() { //************************************* fOutputRootFile->cd(); if (fMinimizer) { SetupCovariance(); SaveMinimizerState(); } SaveCurrentState(); } //************************************* void MinimizerRoutines::SaveMinimizerState() { //************************************* std::cout << "Saving Minimizer State" << std::endl; if (!fMinimizer) { ERR(FTL) << "Can't save minimizer state without min object" << std::endl; throw; } // Save main fit tree fSampleFCN->WriteIterationTree(); // Get Vals and Errors GetMinimizerState(); // Save tree with fit status std::vector nameVect; std::vector valVect; std::vector errVect; std::vector minVect; std::vector maxVect; std::vector startVect; std::vector endfixVect; std::vector startfixVect; // int NFREEPARS = fMinimizer->NFree(); int NPARS = fMinimizer->NDim(); int ipar = 0; // Dial Vals for (UInt_t i = 0; i < fParams.size(); i++) { std::string name = fParams.at(i); nameVect.push_back(name); valVect.push_back(fCurVals.at(name)); errVect.push_back(fErrorVals.at(name)); minVect.push_back(fMinVals.at(name)); maxVect.push_back(fMaxVals.at(name)); startVect.push_back(fStartVals.at(name)); endfixVect.push_back(fFixVals.at(name)); startfixVect.push_back(fStartFixVals.at(name)); ipar++; } int NFREE = fMinimizer->NFree(); int NDIM = fMinimizer->NDim(); double CHI2 = fSampleFCN->GetLikelihood(); int NBINS = fSampleFCN->GetNDOF(); int NDOF = NBINS - NFREE; // Write fit results TTree* fit_tree = new TTree("fit_result", "fit_result"); fit_tree->Branch("parameter_names", &nameVect); fit_tree->Branch("parameter_values", &valVect); fit_tree->Branch("parameter_errors", &errVect); fit_tree->Branch("parameter_min", &minVect); fit_tree->Branch("parameter_max", &maxVect); fit_tree->Branch("parameter_start", &startVect); fit_tree->Branch("parameter_fix", &endfixVect); fit_tree->Branch("parameter_startfix", &startfixVect); fit_tree->Branch("CHI2", &CHI2, "CHI2/D"); fit_tree->Branch("NDOF", &NDOF, "NDOF/I"); fit_tree->Branch("NBINS", &NBINS, "NBINS/I"); fit_tree->Branch("NDIM", &NDIM, "NDIM/I"); fit_tree->Branch("NFREE", &NFREE, "NFREE/I"); fit_tree->Fill(); fit_tree->Write(); // Make dial variables TH1D dialvar = TH1D("fit_dials", "fit_dials", NPARS, 0, NPARS); TH1D startvar = TH1D("start_dials", "start_dials", NPARS, 0, NPARS); TH1D minvar = TH1D("min_dials", "min_dials", NPARS, 0, NPARS); TH1D maxvar = TH1D("max_dials", "max_dials", NPARS, 0, NPARS); TH1D dialvarfree = TH1D("fit_dials_free", "fit_dials_free", NFREE, 0, NFREE); TH1D startvarfree = TH1D("start_dials_free", "start_dials_free", NFREE, 0, NFREE); TH1D minvarfree = TH1D("min_dials_free", "min_dials_free", NFREE, 0, NFREE); TH1D maxvarfree = TH1D("max_dials_free", "max_dials_free", NFREE, 0, NFREE); int freecount = 0; for (UInt_t i = 0; i < nameVect.size(); i++) { std::string name = nameVect.at(i); dialvar.SetBinContent(i + 1, valVect.at(i)); dialvar.SetBinError(i + 1, errVect.at(i)); dialvar.GetXaxis()->SetBinLabel(i + 1, name.c_str()); startvar.SetBinContent(i + 1, startVect.at(i)); startvar.GetXaxis()->SetBinLabel(i + 1, name.c_str()); minvar.SetBinContent(i + 1, minVect.at(i)); minvar.GetXaxis()->SetBinLabel(i + 1, name.c_str()); maxvar.SetBinContent(i + 1, maxVect.at(i)); maxvar.GetXaxis()->SetBinLabel(i + 1, name.c_str()); if (NFREE > 0) { if (!startfixVect.at(i)) { freecount++; dialvarfree.SetBinContent(freecount, valVect.at(i)); dialvarfree.SetBinError(freecount, errVect.at(i)); dialvarfree.GetXaxis()->SetBinLabel(freecount, name.c_str()); startvarfree.SetBinContent(freecount, startVect.at(i)); startvarfree.GetXaxis()->SetBinLabel(freecount, name.c_str()); minvarfree.SetBinContent(freecount, minVect.at(i)); minvarfree.GetXaxis()->SetBinLabel(freecount, name.c_str()); maxvarfree.SetBinContent(freecount, maxVect.at(i)); maxvarfree.GetXaxis()->SetBinLabel(freecount, name.c_str()); } } } // Save Dial Plots dialvar.Write(); startvar.Write(); minvar.Write(); maxvar.Write(); if (NFREE > 0) { dialvarfree.Write(); startvarfree.Write(); minvarfree.Write(); maxvarfree.Write(); } // Save fit_status plot TH1D statusplot = TH1D("fit_status", "fit_status", 8, 0, 8); std::string fit_labels[8] = {"status", "cov_status", "maxiter", "maxfunc", "iter", "func", "precision", "tolerance"}; double fit_vals[8]; fit_vals[0] = fMinimizer->Status() + 0.; fit_vals[1] = fMinimizer->CovMatrixStatus() + 0.; fit_vals[2] = fMinimizer->MaxIterations() + 0.; fit_vals[3] = fMinimizer->MaxFunctionCalls() + 0.; fit_vals[4] = fMinimizer->NIterations() + 0.; fit_vals[5] = fMinimizer->NCalls() + 0.; fit_vals[6] = fMinimizer->Precision() + 0.; fit_vals[7] = fMinimizer->Tolerance() + 0.; for (int i = 0; i < 8; i++) { statusplot.SetBinContent(i + 1, fit_vals[i]); statusplot.GetXaxis()->SetBinLabel(i + 1, fit_labels[i].c_str()); } statusplot.Write(); // Save Covars if (fCovar) fCovar->Write(); if (fCovFree) fCovFree->Write(); if (fCorrel) fCorrel->Write(); if (fCorFree) fCorFree->Write(); if (fDecomp) fDecomp->Write(); if (fDecFree) fDecFree->Write(); return; } //************************************* void MinimizerRoutines::SaveCurrentState(std::string subdir) { //************************************* LOG(FIT) << "Saving current full FCN predictions" << std::endl; // 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 MinimizerRoutines::SaveNominal() { //************************************* fOutputRootFile->cd(); LOG(FIT) << "Saving Nominal Predictions (be cautious with this)" << std::endl; FitBase::GetRW()->Reconfigure(); SaveCurrentState("nominal"); }; //************************************* void MinimizerRoutines::SavePrefit() { //************************************* fOutputRootFile->cd(); LOG(FIT) << "Saving Prefit Predictions" << std::endl; UpdateRWEngine(fStartVals); SaveCurrentState("prefit"); UpdateRWEngine(fCurVals); }; /* MISC Functions */ //************************************* int MinimizerRoutines::GetStatus() { //************************************* return 0; } //************************************* void MinimizerRoutines::SetupCovariance() { //************************************* // Remove covares if they exist if (fCovar) delete fCovar; if (fCovFree) delete fCovFree; if (fCorrel) delete fCorrel; if (fCorFree) delete fCorFree; if (fDecomp) delete fDecomp; if (fDecFree) delete fDecFree; LOG(FIT) << "Building covariance matrix.." << std::endl; int NFREE = 0; int NDIM = 0; // Get NFREE from min or from vals (for cases when doing throws) if (fMinimizer) { std::cout << "NFREE FROM MINIMIZER" << std::endl; NFREE = fMinimizer->NFree(); NDIM = fMinimizer->NDim(); } else { NDIM = fParams.size(); for (UInt_t i = 0; i < fParams.size(); i++) { std::cout << "Getting Param " << fParams[i] << std::endl; if (!fFixVals[fParams[i]]) NFREE++; } } if (NDIM == 0) return; LOG(FIT) << "NFREE == " << NFREE << std::endl; fCovar = new TH2D("covariance", "covariance", NDIM, 0, NDIM, NDIM, 0, NDIM); if (NFREE > 0) { fCovFree = new TH2D("covariance_free", "covariance_free", NFREE, 0, NFREE, NFREE, 0, NFREE); } else { fCovFree = NULL; } // Set Bin Labels int countall = 0; int countfree = 0; for (UInt_t i = 0; i < fParams.size(); i++) { std::cout << "Getting Param " << i << std::endl; std::cout << "ParamI = " << fParams[i] << std::endl; 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) { fCovFree->GetXaxis()->SetBinLabel(countfree + 1, fParams[i].c_str()); fCovFree->GetYaxis()->SetBinLabel(countfree + 1, fParams[i].c_str()); countfree++; } } std::cout << "Filling Matrices" << std::endl; fCorrel = PlotUtils::GetCorrelationPlot(fCovar, "correlation"); fDecomp = PlotUtils::GetDecompPlot(fCovar, "decomposition"); if (NFREE > 0) { fCorFree = PlotUtils::GetCorrelationPlot(fCovFree, "correlation_free"); fDecFree = PlotUtils::GetDecompPlot(fCovFree, "decomposition_free"); } else { fCorFree = NULL; fDecFree = NULL; } std::cout << " Set the covariance" << std::endl; return; }; //************************************* void MinimizerRoutines::ThrowCovariance(bool uniformly) { //************************************* std::vector rands; if (!fDecFree) { ERR(WRN) << "Trying to throw 0 free parameters" << std::endl; return; } // Generate Random Gaussians for (Int_t i = 0; i < fDecFree->GetNbinsX(); i++) { rands.push_back(gRandom->Gaus(0.0, 1.0)); } // Reset Thrown Values for (UInt_t i = 0; i < fParams.size(); i++) { fThrownVals[fParams[i]] = fCurVals[fParams[i]]; } // Loop and get decomp for (Int_t i = 0; i < fDecFree->GetNbinsX(); i++) { std::string parname = std::string(fDecFree->GetXaxis()->GetBinLabel(i + 1)); double mod = 0.0; if (!uniformly) { for (Int_t j = 0; j < fDecFree->GetNbinsY(); j++) { mod += rands[j] * fDecFree->GetBinContent(j + 1, i + 1); } } if (fCurVals.find(parname) != fCurVals.end()) { if (uniformly) fThrownVals[parname] = gRandom->Uniform(fMinVals[parname], fMaxVals[parname]); else { fThrownVals[parname] = fCurVals[parname] + mod; } } } // Check Limits for (UInt_t i = 0; i < fParams.size(); i++) { std::string syst = fParams[i]; if (fFixVals[syst]) continue; if (fThrownVals[syst] < fMinVals[syst]) fThrownVals[syst] = fMinVals[syst]; if (fThrownVals[syst] > fMaxVals[syst]) fThrownVals[syst] = fMaxVals[syst]; } return; }; //************************************* void MinimizerRoutines::GenerateErrorBands() { //************************************* TDirectory* errorDIR = (TDirectory*)fOutputRootFile->mkdir("error_bands"); errorDIR->cd(); // Make a second file to store throws std::string tempFileName = fOutputFile; if (tempFileName.find(".root") != std::string::npos) tempFileName.erase(tempFileName.find(".root"), 5); tempFileName += ".throws.root"; TFile* tempfile = new TFile(tempFileName.c_str(), "RECREATE"); tempfile->cd(); int nthrows = FitPar::Config().GetParI("error_throws"); UpdateRWEngine(fCurVals); fSampleFCN->ReconfigureAllEvents(); TDirectory* nominal = (TDirectory*)tempfile->mkdir("nominal"); nominal->cd(); fSampleFCN->Write(); TDirectory* outnominal = (TDirectory*)fOutputRootFile->mkdir("nominal_throw"); outnominal->cd(); fSampleFCN->Write(); errorDIR->cd(); TTree* parameterTree = new TTree("throws", "throws"); double chi2; for (UInt_t i = 0; i < fParams.size(); i++) parameterTree->Branch(fParams[i].c_str(), &fThrownVals[fParams[i]], (fParams[i] + "/D").c_str()); parameterTree->Branch("chi2", &chi2, "chi2/D"); bool uniformly = FitPar::Config().GetParB("error_uniform"); // Run Throws and save for (Int_t i = 0; i < nthrows; i++) { TDirectory* throwfolder = (TDirectory*)tempfile->mkdir(Form("throw_%i", i)); throwfolder->cd(); // Generate Random Parameter Throw ThrowCovariance(uniformly); // Run Eval double* vals = FitUtils::GetArrayFromMap(fParams, fThrownVals); chi2 = fSampleFCN->DoEval(vals); delete vals; // Save the FCN fSampleFCN->Write(); parameterTree->Fill(); } errorDIR->cd(); fDecFree->Write(); fCovFree->Write(); parameterTree->Write(); delete parameterTree; // 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; TH1D* baseplot = (TH1D*)key->ReadObj(); std::string plotname = std::string(baseplot->GetName()); int nbins = baseplot->GetNbinsX() * 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)); } for (Int_t i = 0; i < nthrows; i++) { TH1* newplot = (TH1*)tempfile->Get(Form(("throw_%i/" + plotname).c_str(), i)); 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(); delete newplot; } errorDIR->cd(); for (Int_t j = 0; j < nbins; j++) { if (!uniformly) { baseplot->SetBinError(j + 1, tprof->GetBinError(j + 1)); } else { baseplot->SetBinContent(j + 1, (binlowest[j] + binhighest[j]) / 2.0); baseplot->SetBinError(j + 1, (binhighest[j] - binlowest[j]) / 2.0); } } errorDIR->cd(); baseplot->Write(); tprof->Write(); bintree->Write(); delete baseplot; delete tprof; delete bintree; delete[] bincontents; } return; }; void MinimizerRoutines::ThrowDataToys() { LOG(FIT) << "Generating Toy Data Throws" << std::endl; int verb = Config::GetParI("VERBOSITY"); SETVERBOSITY(FIT); int nthrows = FitPar::Config().GetParI("NToyThrows"); double maxlike = -1.0; double minlike = -1.0; std::vector values; for (int i = 0; i < 1.E4; i++) { fSampleFCN->ThrowDataToy(); double like = fSampleFCN->GetLikelihood(); values.push_back(like); if (maxlike == -1.0 or like > maxlike) maxlike = like; if (minlike == -1.0 or like < minlike) minlike = like; } SETVERBOSITY(verb); // Fill Histogram TH1D* likes = new TH1D("toydatalikelihood", "toydatalikelihood", int(sqrt(nthrows)), minlike, maxlike); for (size_t i = 0; i < values.size(); i++) { likes->Fill(values[i]); } // Save to file LOG(FIT) << "Writing toy data throws" << std::endl; fOutputRootFile->cd(); likes->Write(); } diff --git a/src/Routines/MinimizerRoutines.h b/src/Routines/MinimizerRoutines.h index 0733601..3918e7a 100755 --- a/src/Routines/MinimizerRoutines.h +++ b/src/Routines/MinimizerRoutines.h @@ -1,270 +1,278 @@ // 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 void SaveNominal(); //! Save predictions before the fit is ran into a seperate 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; //! 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/Splines/SplineWriter.h b/src/Splines/SplineWriter.h index ffc0655..87d7cc6 100644 --- a/src/Splines/SplineWriter.h +++ b/src/Splines/SplineWriter.h @@ -1,92 +1,98 @@ #ifndef SPLINEWRITER_H #define SPLINEWRITER_H #include "FitWeight.h" #include "Spline.h" #include "SplineUtils.h" #ifdef __MINUIT2_ENABLED__ + +#ifdef ROOT6_USE_FIT_FITTER_INTERFACE +#include "Fit/Fitter.h" +#else #include "TFitterMinuit.h" #endif +#endif + class SplineFCN { public: SplineFCN(Spline* spl, std::vector > v, std::vector w) { fSpl = spl; fVal = v; fWeight = w; }; ~SplineFCN() {}; double operator()(const double* x) const; double DoEval(const double *x) const; void SaveAs(std::string name, const float* fx); void UpdateWeights(std::vector& w); void SetCorrelated(bool state = true); bool uncorrelated; std::vector< std::vector > fVal; std::vector< double > fWeight; Spline* fSpl; }; class SplineWriter : public SplineReader { public: SplineWriter(FitWeight* fw) { fRW = fw; fDrawSplines = FitPar::Config().GetParB("drawsplines"); }; ~SplineWriter() {}; void SetupSplineSet(); void Write(std::string name); void AddCoefficientsToTree(TTree* tree); void FitSplinesForEvent(TCanvas* fitcanvas = NULL, bool saveplot = false); void AddWeightsToTree(TTree* tr); void ReadWeightsFromTree(TTree* tr); void FitSplinesForEvent(double* weightvals, float* coeff); void GetWeightsForEvent(FitEvent* event, double* weights); void GetWeightsForEvent(FitEvent* event); void ReconfigureSet(int iset); double GetWeightForThisSet(FitEvent* event, int iset=-1); void SetWeights(double* weights); inline int GetNWeights(){return fParVect.size();}; inline int GetNPars(){ return fNCoEff;}; int fNCoEff; // double* fCoEffStorer; float* fCoEffStorer; std::vector< std::vector > fParVect; std::vector< int > fSetIndex; double* fWeightList; std::vector< std::vector > fValList; int fCurrentSet; FitWeight* fRW; bool fDrawSplines; std::vector fAllDrawnHists; std::vector fAllDrawnGraphs; #ifdef __MINUIT2_ENABLED__ std::map fSplineFCNs; std::map fSplineFunctors; std::map fSplineMinimizers; #endif // Spline* gSpline; // Available Fitting Functions void FitCoeff(Spline* spl, std::vector< std::vector >& v, std::vector& w, float* coeff, bool draw); void FitCoeff1DGraph(Spline* spl, int n, double* x, double* y, float* coeff, bool draw); void GetCoeff1DTSpline3(Spline* spl, int n, double* x, double* y, float* coeff, bool draw); // void FitCoeff2DGraph(Spline* spl, std::vector< std::vector >& v, std::vector& w, float* coeff, bool draw); void FitCoeffNDGraph(Spline* spl, std::vector< std::vector >& v, std::vector& w, float* coeff, bool draw); void FitCoeff2DGraph(Spline* spl, int n, double* x, double* y, double* w, float* coeff, bool draw); //double Func2DWrapper(double* x, double* p); }; #endif diff --git a/src/Statistical/StatUtils.cxx b/src/Statistical/StatUtils.cxx index 1af6e2e..e052685 100644 --- a/src/Statistical/StatUtils.cxx +++ b/src/Statistical/StatUtils.cxx @@ -1,1303 +1,1304 @@ // 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 "TH1D.h" #include "StatUtils.h" -#include "NuisConfig.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(); - TH1D* calc_mc = (TH1D*)mc->Clone(); + TH1D* calc_mc = (TH1D*)mc->Clone(); // 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_mc = ApplyHistogramMasking(mc, mask); + calc_mc = ApplyHistogramMasking(mc, mask); } // 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; + 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 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) { -//******************************************************************* +Double_t StatUtils::GetChi2FromDiag(TH2D* data, TH2D* mc, TH2I* map, + TH2I* mask) { + //******************************************************************* // Generate a simple map - if (!map) map = GenerateMap(data); + if (!map) map = GenerateMap(data); // Convert to 1D Histograms TH1D* data_1D = MapToTH1D(data, map); - TH1D* mc_1D = MapToTH1D(mc, 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); + Double_t Chi2 = StatUtils::GetChi2FromDiag(data_1D, mc_1D, mask_1D); // CleanUp delete data_1D; delete mc_1D; delete mask_1D; return Chi2; }; //******************************************************************* -Double_t StatUtils::GetChi2FromCov(TH1D* data, TH1D* mc, - TMatrixDSym* invcov, TH1I* mask, - double data_scale, double covar_scale) { -//******************************************************************* +Double_t StatUtils::GetChi2FromCov(TH1D* data, TH1D* mc, TMatrixDSym* invcov, + TH1I* mask, double data_scale, + double covar_scale) { + //******************************************************************* Double_t Chi2 = 0.0; - TMatrixDSym* calc_cov = (TMatrixDSym*) invcov->Clone(); - TH1D* calc_data = (TH1D*) data->Clone(); - TH1D* calc_mc = (TH1D*) mc->Clone(); + TMatrixDSym* calc_cov = (TMatrixDSym*)invcov->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 = ApplyInvertedMatrixMasking(invcov, mask); + calc_cov = ApplyInvertedMatrixMasking(invcov, mask); calc_data = ApplyHistogramMasking(data, mask); - calc_mc = ApplyHistogramMasking(mc, mask); + calc_mc = ApplyHistogramMasking(mc, mask); } // Add MC Error to data if required - if (FitPar::Config().GetParB("addmcerror")) { - + if (FitPar::Config().GetParB("statutils.addmcerror")) { // Make temp cov TMatrixDSym* newcov = StatUtils::GetInvert(calc_cov); // 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); - std::cout << "Adding cov stat " << mcerr*mcerr << " to " << (*newcov)(i,i) << std::endl; + std::cout << "Adding cov stat " << mcerr * mcerr << " to " + << (*newcov)(i, i) << std::endl; (*newcov)(i, i) = oldval + mcerr * mcerr; } // Reset the calc_cov to new invert delete calc_cov; calc_cov = GetInvert(newcov); // Delete the tempcov delete newcov; } calc_data->Scale(data_scale); - calc_mc ->Scale(data_scale); + calc_mc->Scale(data_scale); (*calc_cov) *= covar_scale; // iterate over bins in X (i,j) + QLOG(DEB, "START Chi2 Calculation================="); for (int i = 0; i < calc_data->GetNbinsX(); i++) { - + QLOG(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++) { - - if (calc_data->GetBinContent(i + 1) != 0 || calc_mc->GetBinContent(i + 1) != 0) { - - LOG(DEB) << "i j = " << i << " " << j << std::endl; - LOG(DEB) << "Calc_data mc i = " << calc_data->GetBinContent(i + 1) - << " " << calc_mc->GetBinContent(i + 1) - << " Dif = " - << ( calc_data->GetBinContent(i + 1) - calc_mc->GetBinContent(i + 1) ) - << std::endl; - - LOG(DEB) << "Calc_data mc i = " << calc_data->GetBinContent(j + 1) - << " " << calc_mc->GetBinContent(j + 1) - << " Dif = " - << ( calc_data->GetBinContent(j + 1) - calc_mc->GetBinContent(j + 1) ) - << std::endl; - - LOG(DEB) << "Covar = " << (*calc_cov)(i, j) << std::endl; - - LOG(DEB) << "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 << std::endl; - - 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) ) ); + QLOG(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)) { + QLOG(DEB, "[CHI2]\t\t Chi2 contribution (i,j) = (" << i << "," << j + << ")"); + QLOG(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))); + + QLOG(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))); + + QLOG(DEB, "[CHI2]\t\t Covar = " << (*calc_cov)(i, j)); + + QLOG(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); + + 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))); } else { - - LOG(DEB) << "Error on bin (i,j) = (" << i << "," << j << ")" << std::endl; - LOG(DEB) << "data->GetBinContent(i+1) = " << calc_data->GetBinContent(i + 1) << std::endl; - LOG(DEB) << "mc->GetBinContent(i+1) = " << calc_mc->GetBinContent(i + 1) << std::endl; - LOG(DEB) << "Adding zero to chi2 instead of dying horrifically " << std::endl; - + QLOG(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.; } } } // 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) { //******************************************************************* +Double_t StatUtils::GetChi2FromCov(TH2D* data, TH2D* mc, TMatrixDSym* invcov, + TH2I* map, TH2I* mask) { + //******************************************************************* // Generate a simple map if (!map) { map = StatUtils::GenerateMap(data); } // Convert to 1D Histograms TH1D* data_1D = MapToTH1D(data, map); - TH1D* mc_1D = MapToTH1D(mc, map); + TH1D* mc_1D = MapToTH1D(mc, map); TH1I* mask_1D = MapToMask(mask, map); // Calculate 1D chi2 from 1D Plots - Double_t Chi2 = StatUtils::GetChi2FromCov(data_1D, mc_1D, invcov, mask_1D); + Double_t Chi2 = StatUtils::GetChi2FromCov(data_1D, mc_1D, invcov, mask_1D); // CleanUp delete data_1D; delete mc_1D; delete mask_1D; return Chi2; } //******************************************************************* -Double_t StatUtils::GetChi2FromSVD( TH1D* data, TH1D* mc, - TMatrixDSym* cov, TH1I* mask) { -//******************************************************************* +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(); + 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_cov = StatUtils::ApplyMatrixMasking(cov, mask); calc_data = StatUtils::ApplyHistogramMasking(data, mask); - calc_mc = StatUtils::ApplyHistogramMasking(mc, 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() ); + 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) ; + 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) { //******************************************************************* +Double_t StatUtils::GetChi2FromSVD(TH2D* data, TH2D* mc, TMatrixDSym* cov, + TH2I* map, TH2I* mask) { + //******************************************************************* // Generate a simple map - if (!map) - map = StatUtils::GenerateMap(data); + if (!map) map = StatUtils::GenerateMap(data); // Convert to 1D Histograms TH1D* data_1D = MapToTH1D(data, map); - TH1D* mc_1D = MapToTH1D(mc, 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; 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 + // 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(); + TH1D* calc_mc = (TH1D*)mc->Clone(); // Apply masking if required if (mask) { calc_data = ApplyHistogramMasking(data, mask); - calc_mc = ApplyHistogramMasking(mc, 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))); + 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; if (!map) 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++; - } } return NDOF; }; - - -//******************************************************************* -TH1D* StatUtils::ThrowHistogram(TH1D* hist, TMatrixDSym* cov, bool throwdiag, TH1I* mask) { //******************************************************************* +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(); + 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_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; 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 + // 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) ; + correl_val += rand_val[j] * (*decomp_cov)(j, i); } - calc_hist->SetBinContent(i + 1, (calc_hist->GetBinContent(i + 1) + correl_val * 1E-38)); + 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) { -//******************************************************************* +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; + (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() ); + if (!mask) return ((TH1D*)hist->Clone()); - // This masking is only sufficient for chi2 calculations, and will have dodgy bin edges. + // 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); + 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)) { - LOG(REC) << "Applying mask to bin " << i + 1 << " " << hist->GetName() << std::endl; + LOG(REC) << "Applying mask to bin " << i + 1 << " " << hist->GetName() + << std::endl; 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(); + 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) { -//******************************************************************* +TMatrixDSym* StatUtils::ApplyMatrixMasking(TMatrixDSym* mat, TH2D* data, + TH2I* mask, TH2I* map) { + //******************************************************************* if (!map) map = StatUtils::GenerateMap(data); TH1I* mask_1D = StatUtils::MapToMask(mask, map); - TMatrixDSym* newmat = StatUtils::ApplyMatrixMasking(mat, mask_1D); + TMatrixDSym* newmat = StatUtils::ApplyMatrixMasking(mat, mask_1D); delete mask_1D; return newmat; } - - -//******************************************************************* -TMatrixDSym* StatUtils::ApplyInvertedMatrixMasking(TMatrixDSym* mat, TH1I* mask) { //******************************************************************* +TMatrixDSym* StatUtils::ApplyInvertedMatrixMasking(TMatrixDSym* mat, + TH1I* mask) { + //******************************************************************* TMatrixDSym* new_mat = GetInvert(mat); TMatrixDSym* masked_mat = ApplyMatrixMasking(new_mat, mask); TMatrixDSym* inverted_mat = GetInvert(masked_mat); delete masked_mat; delete new_mat; return inverted_mat; }; - - -//******************************************************************* -TMatrixDSym* StatUtils::ApplyInvertedMatrixMasking(TMatrixDSym* mat, TH2D* data, TH2I* mask, TH2I* map) { //******************************************************************* +TMatrixDSym* StatUtils::ApplyInvertedMatrixMasking(TMatrixDSym* mat, TH2D* data, + TH2I* mask, TH2I* map) { + //******************************************************************* if (!map) map = StatUtils::GenerateMap(data); TH1I* mask_1D = StatUtils::MapToMask(mask, map); TMatrixDSym* newmat = ApplyInvertedMatrixMasking(mat, mask_1D); delete mask_1D; return newmat; } - - - //******************************************************************* TMatrixDSym* StatUtils::GetInvert(TMatrixDSym* mat) { -//******************************************************************* + //******************************************************************* 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; } - // Invert full matrix TDecompSVD LU = TDecompSVD((*new_mat)); - new_mat = new TMatrixDSym(new_mat->GetNrows(), LU.Invert().GetMatrixArray(), ""); + new_mat = + new TMatrixDSym(new_mat->GetNrows(), LU.Invert().GetMatrixArray(), ""); 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 ) { -//******************************************************************* +void StatUtils::ForceNormIntoCovar(TMatrixDSym* mat, TH2D* data, double norm, + TH2I* map) { + //******************************************************************* if (!map) map = StatUtils::GenerateMap(data); TH1D* data_1D = MapToTH1D(data, map); StatUtils::ForceNormIntoCovar(mat, data_1D, norm); delete data_1D; 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; + (*newmat)(i, i) = + data->GetBinError(i + 1) * data->GetBinError(i + 1) * scaleF * scaleF; } return newmat; } - - -//******************************************************************* -TMatrixDSym* StatUtils::MakeDiagonalCovarMatrix(TH2D* data, TH2I* map, double scaleF) { //******************************************************************* +TMatrixDSym* StatUtils::MakeDiagonalCovarMatrix(TH2D* data, TH2I* map, + double scaleF) { + //******************************************************************* if (!map) map = StatUtils::GenerateMap(data); TH1D* data_1D = MapToTH1D(data, map); return StatUtils::MakeDiagonalCovarMatrix(data_1D, scaleF); }; - -//******************************************************************* -void StatUtils::SetDataErrorFromCov(TH1D* data, TMatrixDSym* cov, double scale) { //******************************************************************* +void StatUtils::SetDataErrorFromCov(TH1D* data, TMatrixDSym* cov, + double scale) { + //******************************************************************* // Check if (cov->GetNrows() != data->GetNbinsX()) { - ERR(WRN) << "Nrows in cov don't match nbins in data for SetDataErrorFromCov" << std::endl; + ERR(WRN) << "Nrows in cov don't match nbins in data for SetDataErrorFromCov" + << std::endl; } // Set bin errors form cov diag for (int i = 0; i < data->GetNbinsX(); i++) { - data->SetBinError(i + 1, sqrt((*cov)(i, i)) * scale ); + data->SetBinError(i + 1, sqrt((*cov)(i, i)) * scale); } return; } //******************************************************************* -void StatUtils::SetDataErrorFromCov(TH2D* data, TMatrixDSym* cov, TH2I* map, double scale) { -//******************************************************************* +void StatUtils::SetDataErrorFromCov(TH2D* data, TMatrixDSym* cov, TH2I* map, + double scale) { + //******************************************************************* // Create map if required if (!map) 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; count = map->GetBinContent(i + 1, j + 1) - 1; - data->SetBinError(i + 1, j + 1, sqrt((*cov)(count, count)) * scale ); - + data->SetBinError(i + 1, j + 1, sqrt((*cov)(count, count)) * scale); } } return; } - -TMatrixDSym* StatUtils::ExtractShapeOnlyCovar(TMatrixDSym* full_covar, TH1* data_hist, double data_scale){ - +TMatrixDSym* StatUtils::ExtractShapeOnlyCovar(TMatrixDSym* full_covar, + TH1* 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){ - ERR(WRN) << "Inconsistent matrix and data histogram passed to StatUtils::ExtractShapeOnlyCovar!" << std::endl; - ERR(WRN) << "data_hist has " << data_hist->GetNbinsX() << " matrix has " << nbins << std::endl; + if (data_hist->GetNbinsX() != nbins) { + ERR(WRN) << "Inconsistent matrix and data histogram passed to " + "StatUtils::ExtractShapeOnlyCovar!" + << std::endl; + ERR(WRN) << "data_hist has " << data_hist->GetNbinsX() << " matrix has " + << nbins << std::endl; int err_bins = data_hist->GetNbinsX(); if (nbins > err_bins) err_bins = nbins; - for (int i = 0; i < err_bins; ++i){ - ERR(WRN) << "Matrix diag. = " << (*full_covar)(i, i) << " data = " << data_hist->GetBinContent(i+1) << std::endl; + for (int i = 0; i < err_bins; ++i) { + ERR(WRN) << "Matrix diag. = " << (*full_covar)(i, i) + << " data = " << data_hist->GetBinContent(i + 1) << std::endl; } return NULL; } - double total_data = 0; + 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; + total_data += data_hist->GetBinContent(i + 1) * data_scale; for (int j = 0; j < nbins; ++j) { - total_covar += (*full_covar)(i,j); + total_covar += (*full_covar)(i, j); } } - - if (total_data == 0 || total_covar == 0){ - ERR(WRN) << "Stupid matrix or data histogram passed to StatUtils::ExtractShapeOnlyCovar! Ignoring..." << std::endl; + + if (total_data == 0 || total_covar == 0) { + ERR(WRN) << "Stupid matrix or data histogram passed to " + "StatUtils::ExtractShapeOnlyCovar! Ignoring..." + << std::endl; return NULL; } - LOG(SAM) << "Norm error = " << sqrt(total_covar)/total_data << std::endl; - + LOG(SAM) << "Norm error = " << sqrt(total_covar) / total_data << std::endl; + // 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; + 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 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); + + 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; + 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; } - //******************************************************************* 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()); + 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 && hist->GetBinError(i + 1, j + 1) > 0) { - + if (hist->GetBinContent(i + 1, j + 1) > 0 && + hist->GetBinError(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(); 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)); + 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; } - //******************************************************************* 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(); 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)); + 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); + (*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) { //******************************************************************* +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) { - ERR(WRN) << "StatUtils::GetMatrixFromTextFile, matrix only has <= 1 " - "entries on this line: " << row << std::endl; + ERR(WRN) << "StatUtils::GetMatrixFromTextFile, matrix only has <= 1 " + "entries on this line: " + << row << std::endl; } 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) { ERR(WRN) << "StatUtils::GetMatrixFromTextFile, matrix only has <= 1 " - "entries on this line: " << row << std::endl; + "entries on this line: " + << row << std::endl; } 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."); + // 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) { -//******************************************************************* +TMatrixD* StatUtils::GetMatrixFromRootFile(std::string covfile, + std::string histname) { + //******************************************************************* std::string inputfile = covfile + ";" + histname; std::vector splitfile = GeneralUtils::ParseToStr(inputfile, ";"); if (splitfile.size() < 2) { ERR(FTL) << "No object name given!" << std::endl; throw; } // Get file TFile* tempfile = new TFile(splitfile[0].c_str(), "READ"); // Get Object TObject* obj = tempfile->Get(splitfile[1].c_str()); if (!obj) { ERR(FTL) << "Object " << splitfile[1] << " doesn't exist!" << std::endl; throw; } // 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){ -//******************************************************************* +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); + 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){ -//******************************************************************* +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); + 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/Tests/CMakeLists.txt b/src/Tests/CMakeLists.txt index 6fe0313..f02aea6 100644 --- a/src/Tests/CMakeLists.txt +++ b/src/Tests/CMakeLists.txt @@ -1,40 +1,58 @@ # 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_directories(${MINIMUM_INCLUDE_DIRECTORIES}) include_directories(${CMAKE_SOURCE_DIR}/src/Routines) include_directories(${CMAKE_SOURCE_DIR}/src/FCN) include_directories(${CMAKE_SOURCE_DIR}/src/MCStudies) include_directories(${CMAKE_SOURCE_DIR}/src/Smearceptance) include_directories(${EXP_INCLUDE_DIRECTORIES}) SET(TESTAPPS SignalDefTests ParserTests SmearceptanceTests) +if(USE_MINIMIZER) + # LIST(APPEND TESTAPPS FitMechanicsTests) +endif() + foreach(appimpl ${TESTAPPS}) add_executable(${appimpl} ${appimpl}.cxx) set(TARGETS_TO_BUILD ${TARGETS_TO_BUILD};${appimpl}) target_link_libraries(${appimpl} ${MODULETargets}) target_link_libraries(${appimpl} ${CMAKE_DEPENDLIB_FLAGS}) target_link_libraries(${appimpl} ${ROOT_LIBS}) if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "") set_target_properties(${appimpl} PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS}) endif() install(TARGETS ${appimpl} DESTINATION tests) add_test(${appimpl} ${appimpl} 1) endforeach() + +list (FIND TESTAPPS FitMechanicsTests _index) +if (${_index} GREATER -1) + add_library(DummySample SHARED DummySample.cxx) + target_link_libraries(DummySample ${MODULETargets}) + target_link_libraries(DummySample ${CMAKE_DEPENDLIB_FLAGS}) + target_link_libraries(DummySample ${ROOT_LIBS}) + + if(NOT "${CMAKE_LINK_FLAGS}" STREQUAL "") + set_target_properties(DummySample PROPERTIES LINK_FLAGS ${CMAKE_LINK_FLAGS}) + endif() + + install(TARGETS DummySample DESTINATION tests) +endif() diff --git a/src/Tests/ConstructibleFitEvent.h b/src/Tests/ConstructibleFitEvent.h new file mode 100644 index 0000000..a8b8759 --- /dev/null +++ b/src/Tests/ConstructibleFitEvent.h @@ -0,0 +1,59 @@ +#include "TLorentzVector.h" +#include "TRandom3.h" +#include "FitEvent.h" + +struct ConstructibleFitEvent : public FitEvent { + ConstructibleFitEvent() : FitEvent() { fNParticles = 0; } + void AddPart(double Mom[4], size_t State, int PDG) { + fParticleMom[fNParticles][0] = Mom[0]; + fParticleMom[fNParticles][1] = Mom[1]; + fParticleMom[fNParticles][2] = Mom[2]; + fParticleMom[fNParticles][3] = Mom[3]; + fParticleState[fNParticles] = State; + fParticlePDG[fNParticles] = PDG; + fNParticles++; + } + void SetMode(int mode) { Mode = mode; } + std::string ToString() { + std::stringstream ss(""); + ss << "Mode: " << Mode << std::endl; + ss << "Particles: " << fNParticles << std::endl; + ss << " -> Particle Stack " << std::endl; + for (int i = 0; i < fNParticles; i++) { + ss << " -> -> " << i << ". " << fParticlePDG[i] << " " + << fParticleState[i] << " " + << " Mom(" << fParticleMom[i][0] << ", " << fParticleMom[i][1] << ", " + << fParticleMom[i][2] << ", " << fParticleMom[i][3] << ")." + << std::endl; + } + return ss.str(); + } +}; + +template +ConstructibleFitEvent MakePDGStackEvent(int (&ISpdgs)[N], int (&FSpdgs)[M], + int Mode = 1) { + ConstructibleFitEvent fe; + double MomHolder[4] = {0, 0, 1E3, 1E3}; + for (size_t p_it = 0; p_it < N; ++p_it) { + fe.AddPart(MomHolder, kInitialState, ISpdgs[p_it]); + } + + TRandom3 rnd; + TLorentzVector rnd4M; + TVector3 rn3M; + for (size_t p_it = 0; p_it < M; ++p_it) { + /// Could do better and actually get the correct masses... + rn3M.SetMagThetaPhi(fabs(rnd.Gaus(200, 50)), rnd.Uniform(M_PI), + 2 * rnd.Uniform(M_PI)); + rnd4M.SetVectM(rn3M, 105); + MomHolder[0] = rnd4M[0]; + MomHolder[1] = rnd4M[1]; + MomHolder[2] = rnd4M[2]; + MomHolder[3] = rnd4M[3]; + fe.AddPart(MomHolder, kFinalState, FSpdgs[p_it]); + } + fe.SetMode(Mode); + fe.OrderStack(); + return fe; +} diff --git a/src/Tests/ConstructibleInputHandler.h b/src/Tests/ConstructibleInputHandler.h new file mode 100644 index 0000000..3c8ee1f --- /dev/null +++ b/src/Tests/ConstructibleInputHandler.h @@ -0,0 +1,25 @@ +#include "InputHandler.h" + +struct ConstructibleInputHandler : public InputHandlerBase { + std::vector FitEvents; + + ConstructibleInputHandler( + std::string const& name) { + fName = name; + } + + void AddFitEvent(FitEvent *fe) { + FitEvents.push_back(fe); + + fNEvents = FitEvents.size(); + + std::cout << "[INFO]: Added event " << std::endl; + fe->Print(); + } + + FitEvent* GetNuisanceEvent( + const UInt_t entry, const bool lightweight) { + if (entry >= (UInt_t)fNEvents) return NULL; + return FitEvents[entry]; + } +}; diff --git a/src/Tests/DummyMinimizer.h b/src/Tests/DummyMinimizer.h new file mode 100644 index 0000000..5ef73b3 --- /dev/null +++ b/src/Tests/DummyMinimizer.h @@ -0,0 +1,61 @@ +#include "MinimizerRoutines.h" + +struct DummyMinimizer : public MinimizerRoutines { + DummyMinimizer() : MinimizerRoutines() { + nuiskey p_m1 = Config::CreateKey("parameter"); + + p_m1.SetS("type", "modenorm_parameter"); + p_m1.SetS("name", "mode_1"); + p_m1.SetD("nominal", 1); + p_m1.SetS("state", "FREE"); + p_m1.SetD("low", 0); + p_m1.SetD("high", 3); + p_m1.SetD("step", 0.1); + + nuiskey p_m2 = Config::CreateKey("parameter"); + + p_m2.SetS("type", "modenorm_parameter"); + p_m2.SetS("name", "mode_2"); + p_m2.SetD("nominal", 1); + p_m2.SetS("state", "FREE"); + p_m2.SetD("low", 0); + p_m2.SetD("high", 3); + p_m2.SetD("step", 0.1); + + nuiskey p_m3 = Config::CreateKey("parameter"); + + p_m3.SetS("type", "modenorm_parameter"); + p_m3.SetS("name", "mode_3"); + p_m3.SetD("nominal", 1); + p_m3.SetS("state", "FREE"); + p_m3.SetD("low", 0); + p_m3.SetD("high", 3); + p_m3.SetD("step", 0.1); + + nuiskey dummysample = Config::CreateKey("sample"); + dummysample.SetS("name", "DummySample"); + + Config::SetPar("dynamic_sample.path", + std::string(getenv("NUISANCE")) + "/build/Linux/tests"); + + Config::SetPar("EventManager", false); + // SETVERBOSITY(DEB); + + + + std::cout << "[INFO]: Parameter config:" << std::endl; + nuisconfig::GetConfig().PrintXML(NULL); + std::cout << "================" << std::endl; + + fOutputRootFile = new TFile("TestOutput.root", "RECREATE"); + + SetupMinimizerFromXML(); + SetupRWEngine(); + SetupFCN(); + } + + std::string GetParamName (int i) { return fParams[i]; } + double GetParamVal (int i) { return fCurVals[GetParamName(i)]; } + double GetParamError (int i) { return fErrorVals[GetParamName(i)]; } + +}; diff --git a/src/Tests/DummySample.cxx b/src/Tests/DummySample.cxx new file mode 100644 index 0000000..0734dc9 --- /dev/null +++ b/src/Tests/DummySample.cxx @@ -0,0 +1,89 @@ +#include "ConstructibleFitEvent.h" +#include "ConstructibleInputHandler.h" +#include "Measurement1D.h" + +struct DummySample : public Measurement1D { + + std::vector FitEvents; + DummySample(nuiskey samplekey) { + ConstructibleInputHandler *cih = new ConstructibleInputHandler("DummyIHandler"); + fInput = cih; + + fSettings = SampleSettings(samplekey); + fSettings.SetTitle("DummySample"); + FinaliseSampleSettings(); + + fDataHist = new TH1D("data", "", 3, 1, 4); + fMCHist = new TH1D("data", "", 3, 1, 4); + + double FakeDataError = Config::GetParD("FakeDataError"); + + fScaleFactor = 1; + + int IS[] = {14}; + int FS_CC0pi_1[] = {13, 2212}; + int FS_CC1pi_1[] = {13, 2212, 211}; + int FS_CC2pi_1[] = {13, 2212, 211, -211}; + FitEvents.push_back(new ConstructibleFitEvent(MakePDGStackEvent(IS, FS_CC0pi_1))); + FitEvents.back()->SetMode(1); + FitEvents.push_back(new ConstructibleFitEvent(MakePDGStackEvent(IS, FS_CC1pi_1))); + FitEvents.back()->SetMode(2); + FitEvents.push_back(new ConstructibleFitEvent(MakePDGStackEvent(IS, FS_CC2pi_1))); + FitEvents.back()->SetMode(3); + + for(size_t fe_it = 0; fe_it < FitEvents.size(); ++fe_it){ + cih->AddFitEvent(FitEvents[fe_it]); + fDataHist->SetBinContent(FitEvents[fe_it]->Mode, 1.0 + float(fe_it)*0.5); + fDataHist->SetBinError(FitEvents[fe_it]->Mode, FakeDataError); + } + + SetupDefaultHist(); + SetCovarFromDiagonal(); + FinaliseMeasurement(); + } + void FillEventVariables(FitEvent* nvect) { fXVar = nvect->Mode; } + + bool isSignal(FitEvent* nvect) { return true; } + + virtual ~DummySample(){ + for(size_t fe_it = 0; fe_it < FitEvents.size(); ++fe_it){ + delete FitEvents[fe_it]; + } + } +}; + +static char const* SampleNames[] = {"DummySample"}; +static int const NSamples = 1; + +extern "C" { +int DSF_NSamples() { return NSamples; } +char const* DSF_GetSampleName(int i) { + if (i < NSamples) { + return SampleNames[i]; + } + return 0; +} +MeasurementBase* DSF_GetSample(int i, void* samplekey) { + nuiskey* sk = reinterpret_cast(samplekey); + if (!sk) { + return 0; + } + + if (sk->GetS("name") != DSF_GetSampleName(i)) { + std::cout + << "[ERROR]: When instantiating dynamic sample. Samplekey named: " + << sk->GetS("name") + << ", but requested sample named: " << DSF_GetSampleName(i) + << ". It is possible that the nuiskey object is lost in translation. " + "Was NUISANCE and this dynamic sample manifest built with the same " + "environment and compiler?" + << std::endl; + } + + if (i == 0) { + return new DummySample(*sk); + } + return 0; +} +void DSF_DestroySample(MeasurementBase* mb) { delete mb; } +} diff --git a/src/Tests/FitMechanicsTest.cxx b/src/Tests/FitMechanicsTest.cxx new file mode 100644 index 0000000..9bb9531 --- /dev/null +++ b/src/Tests/FitMechanicsTest.cxx @@ -0,0 +1,41 @@ +#include "DummyMinimizer.h" + +int main() { + + double FakeDataError = 1E-4; + double FakeDataErrorTol = 1.01 * FakeDataError; + Config::SetPar("FakeDataError", FakeDataError); + + DummyMinimizer min; + + std::cout << "======Running simple minimizer test======" << std::endl; + + min.Run(); + + std::cout << "======Done minimizing, checking output======" << std::endl; + + std::vector pnames; + pnames.push_back("mode_1"); + pnames.push_back("mode_2"); + pnames.push_back("mode_3"); + + std::vector postfitvals; + postfitvals.push_back(1); + postfitvals.push_back(1.5); + postfitvals.push_back(2); + + for (size_t i = 0; i < 3; ++i) { + std::cout << "\tTest param name: " << pnames[i] + << " == " << min.GetParamName(i) << std::endl; + assert(pnames[i] == min.GetParamName(i)); + std::cout << "\tTest param post-fit value : fabs(" << postfitvals[i] + << " - " << min.GetParamVal(i) << ") < " << min.GetParamError(i) + << std::endl; + assert(fabs(postfitvals[i] - min.GetParamVal(i)) < min.GetParamError(i)); + std::cout << "\tTest post-fit error " << min.GetParamError(i) << " < " + << FakeDataErrorTol << std::endl; + assert(min.GetParamError(i) < FakeDataErrorTol); + } + + return 0; +} diff --git a/src/Tests/SignalDefTests.cxx b/src/Tests/SignalDefTests.cxx index 551f66b..031526f 100644 --- a/src/Tests/SignalDefTests.cxx +++ b/src/Tests/SignalDefTests.cxx @@ -1,447 +1,389 @@ #include #include -#include "TLorentzVector.h" -#include "TRandom3.h" - -#include "FitEvent.h" #include "SignalDef.h" +#include "ConstructibleFitEvent.h" -struct ConstructibleFitEvent : public FitEvent { - ConstructibleFitEvent() : FitEvent() { fNParticles = 0; } - void AddPart(double Mom[4], size_t State, int PDG) { - fParticleMom[fNParticles][0] = Mom[0]; - fParticleMom[fNParticles][1] = Mom[1]; - fParticleMom[fNParticles][2] = Mom[2]; - fParticleMom[fNParticles][3] = Mom[3]; - fParticleState[fNParticles] = State; - fParticlePDG[fNParticles] = PDG; - fNParticles++; - } - void SetMode(int mode) { Mode = mode; } - std::string ToString() { - std::stringstream ss(""); - ss << "Mode: " << Mode << std::endl; - ss << "Particles: " << fNParticles << std::endl; - ss << " -> Particle Stack " << std::endl; - for (int i = 0; i < fNParticles; i++) { - ss << " -> -> " << i << ". " << fParticlePDG[i] << " " - << fParticleState[i] << " " - << " Mom(" << fParticleMom[i][0] << ", " << fParticleMom[i][1] << ", " - << fParticleMom[i][2] << ", " << fParticleMom[i][3] << ")." - << std::endl; - } - return ss.str(); - } -}; - -template -ConstructibleFitEvent MakePDGStackEvent(int (&ISpdgs)[N], int (&FSpdgs)[M], - int Mode = 1) { - ConstructibleFitEvent fe; - double MomHolder[4] = {0, 0, 1E3, 1E3}; - for (size_t p_it = 0; p_it < N; ++p_it) { - fe.AddPart(MomHolder, kInitialState, ISpdgs[p_it]); - } - - TRandom3 rnd; - TLorentzVector rnd4M; - TVector3 rn3M; - for (size_t p_it = 0; p_it < M; ++p_it) { - /// Could do better and actually get the correct masses... - rn3M.SetMagThetaPhi(fabs(rnd.Gaus(200, 50)), rnd.Uniform(M_PI), - 2 * rnd.Uniform(M_PI)); - rnd4M.SetVectM(rn3M, 105); - MomHolder[0] = rnd4M[0]; - MomHolder[1] = rnd4M[1]; - MomHolder[2] = rnd4M[2]; - MomHolder[3] = rnd4M[3]; - fe.AddPart(MomHolder, kFinalState, FSpdgs[p_it]); - } - fe.SetMode(Mode); - fe.OrderStack(); - return fe; -} int main(int argc, char const *argv[]) { bool FailOnFail = (argc > 1); LOG_VERB(SAM); LOG(FIT) << "* Running SignalDef Tests" << std::endl; LOG(FIT) << "***************************************************" << std::endl; int IS[] = {14}; int FS_CC0pi_1[] = {13, 2112, 2212, 2112, 2212}; ConstructibleFitEvent fe_CC0pi_1 = MakePDGStackEvent(IS, FS_CC0pi_1); int FS_CC0pi_2[] = {13, 2112, 2212, 2112, 2212}; ConstructibleFitEvent fe_CC0pi_2 = MakePDGStackEvent(IS, FS_CC0pi_2, 2); int FS_CC0pi_3[] = {-13, 2112, 2212, 2112, 2212}; ConstructibleFitEvent fe_CC0pi_3 = MakePDGStackEvent(IS, FS_CC0pi_3); int FS_CC0pi_4[] = {13, 2112, 2212}; ConstructibleFitEvent fe_CC0pi_4 = MakePDGStackEvent(IS, FS_CC0pi_4, 12); int FS_CC1pip_1[] = {13, 2212, 2112, 211}; ConstructibleFitEvent fe_CC1pip_1 = MakePDGStackEvent(IS, FS_CC1pip_1, 2); int FS_CC1pim_1[] = {13, -211, 2212, 2112}; ConstructibleFitEvent fe_CC1pim_1 = MakePDGStackEvent(IS, FS_CC1pim_1, 11); int FS_CC1pi0_1[] = {13, 2212, 111, 2112}; ConstructibleFitEvent fe_CC1pi0_1 = MakePDGStackEvent(IS, FS_CC1pi0_1, 12); int FS_CC1pi0_2[] = {11, 2212, 111, 2112}; ConstructibleFitEvent fe_CC1pi0_2 = MakePDGStackEvent(IS, FS_CC1pi0_2, 12); int FS_CCNpi_1[] = {13, 2212, 111, 2112, 211}; ConstructibleFitEvent fe_CCNpi_1 = MakePDGStackEvent(IS, FS_CCNpi_1, 21); int FS_CCNpi_2[] = {13, -211, 211, 2112, 211}; ConstructibleFitEvent fe_CCNpi_2 = MakePDGStackEvent(IS, FS_CCNpi_2, 21); int FS_CCNpi_3[] = {13, 2212, 111, 211, -211}; ConstructibleFitEvent fe_CCNpi_3 = MakePDGStackEvent(IS, FS_CCNpi_3, 26); int FS_CCNpi_4[] = {13, 2212, 111, 111, 111}; ConstructibleFitEvent fe_CCNpi_4 = MakePDGStackEvent(IS, FS_CCNpi_4, 26); int FS_CCCOH_1[] = {13, 211}; ConstructibleFitEvent fe_CCCOH_1 = MakePDGStackEvent(IS, FS_CCCOH_1, 16); int FS_NCel_1[] = {14, 2112}; ConstructibleFitEvent fe_NCel_1 = MakePDGStackEvent(IS, FS_NCel_1, 52); int FS_NCel_2[] = {12, 2212}; ConstructibleFitEvent fe_NCel_2 = MakePDGStackEvent(IS, FS_NCel_2, 51); int FS_NC1pi_1[] = {14, 2112, -211}; ConstructibleFitEvent fe_NC1pi_1 = MakePDGStackEvent(IS, FS_NC1pi_1, 31); int FS_NCNpi_1[] = {14, 2212, 211}; ConstructibleFitEvent fe_NCNpi_1 = MakePDGStackEvent(IS, FS_NCNpi_1, 32); LOG(FIT) << "* Testing: SignalDef::isCCINC" << std::endl; std::map isCCINC_PassExpectations; isCCINC_PassExpectations[&fe_CC0pi_1] = true; // numu CC0pi isCCINC_PassExpectations[&fe_CC0pi_2] = true; // numu CC0pi (2p2h) isCCINC_PassExpectations[&fe_CC0pi_3] = false; // numub CC0pi isCCINC_PassExpectations[&fe_CC0pi_4] = true; // numu CC0pi (RES) isCCINC_PassExpectations[&fe_CC1pip_1] = true; // numu CC1pip (2p2h) isCCINC_PassExpectations[&fe_CC1pim_1] = true; // numu CC1pim isCCINC_PassExpectations[&fe_CC1pi0_1] = true; // numu CC1pi0 isCCINC_PassExpectations[&fe_CC1pi0_2] = false; // nue CC1pi0 isCCINC_PassExpectations[&fe_CCNpi_1] = true; // numu CC multi pi isCCINC_PassExpectations[&fe_CCNpi_2] = true; // numu CC multi pi isCCINC_PassExpectations[&fe_CCNpi_3] = true; // numu CC multi pi isCCINC_PassExpectations[&fe_CCNpi_4] = true; // numu CC multi pi isCCINC_PassExpectations[&fe_CCCOH_1] = true; // numu CC COH pi isCCINC_PassExpectations[&fe_NCel_1] = false; // numu NCEl isCCINC_PassExpectations[&fe_NCel_2] = false; // nue NCEl isCCINC_PassExpectations[&fe_NC1pi_1] = false; // numu NC1pi isCCINC_PassExpectations[&fe_NCNpi_1] = false; // numu NC multi pi size_t ctr = 0; for (std::map::iterator fe_it = isCCINC_PassExpectations.begin(); fe_it != isCCINC_PassExpectations.end(); ++fe_it, ++ctr) { bool res = SignalDef::isCCINC(fe_it->first, 14); if (res != fe_it->second) { ERR(FTL) << "Event: (" << ctr << ")\n" << fe_it->first->ToString() << std::endl; ERR(FTL) << (res ? "passed" : "failed") << " SignalDef::isCCINC unexpectedly." << std::endl; } else { LOG(SAM) << "Event: (" << ctr << ") " << (res ? "passed" : "failed") << " as expected." << std::endl; } if (FailOnFail) { assert(res == fe_it->second); } } LOG(FIT) << "* Testing: SignalDef::isNCINC" << std::endl; std::map isNCINC_PassExpectations; isNCINC_PassExpectations[&fe_CC0pi_1] = false; // numu CC0pi isNCINC_PassExpectations[&fe_CC0pi_2] = false; // numu CC0pi (2p2h) isNCINC_PassExpectations[&fe_CC0pi_3] = false; // numub CC0pi isNCINC_PassExpectations[&fe_CC0pi_4] = false; // numu CC0pi (RES) isNCINC_PassExpectations[&fe_CC1pip_1] = false; // numu CC1pip (2p2h) isNCINC_PassExpectations[&fe_CC1pim_1] = false; // numu CC1pim isNCINC_PassExpectations[&fe_CC1pi0_1] = false; // numu CC1pi0 isNCINC_PassExpectations[&fe_CC1pi0_2] = false; // nue CC1pi0 isNCINC_PassExpectations[&fe_CCNpi_1] = false; // numu CC multi pi isNCINC_PassExpectations[&fe_CCNpi_2] = false; // numu CC multi pi isNCINC_PassExpectations[&fe_CCNpi_3] = false; // numu CC multi pi isNCINC_PassExpectations[&fe_CCNpi_4] = false; // numu CC multi pi isNCINC_PassExpectations[&fe_CCCOH_1] = false; // numu CC COH pi isNCINC_PassExpectations[&fe_NCel_1] = true; // numu NCEl isNCINC_PassExpectations[&fe_NCel_2] = false; // nue NCEl isNCINC_PassExpectations[&fe_NC1pi_1] = true; // numu NC1pi isNCINC_PassExpectations[&fe_NCNpi_1] = true; // numu NC multi pi ctr = 0; for (std::map::iterator fe_it = isNCINC_PassExpectations.begin(); fe_it != isNCINC_PassExpectations.end(); ++fe_it, ++ctr) { bool res = SignalDef::isNCINC(fe_it->first, 14); if (res != fe_it->second) { ERR(FTL) << "Event: (" << ctr << ")\n" << fe_it->first->ToString() << std::endl; ERR(FTL) << (res ? "passed" : "failed") << " SignalDef::isNCINC unexpectedly." << std::endl; } else { LOG(SAM) << "Event: (" << ctr << ") " << (res ? "passed" : "failed") << " as expected." << std::endl; } if (FailOnFail) { assert(res == fe_it->second); } } LOG(FIT) << "* Testing: SignalDef::isCC0pi" << std::endl; std::map isCC0pi_PassExpectations; isCC0pi_PassExpectations[&fe_CC0pi_1] = true; // numu CC0pi isCC0pi_PassExpectations[&fe_CC0pi_2] = true; // numu CC0pi (2p2h) isCC0pi_PassExpectations[&fe_CC0pi_3] = false; // numub CC0pi isCC0pi_PassExpectations[&fe_CC0pi_4] = true; // numu CC0pi (RES) isCC0pi_PassExpectations[&fe_CC1pip_1] = false; // numu CC1pip (2p2h) isCC0pi_PassExpectations[&fe_CC1pim_1] = false; // numu CC1pim isCC0pi_PassExpectations[&fe_CC1pi0_1] = false; // numu CC1pi0 isCC0pi_PassExpectations[&fe_CC1pi0_2] = false; // nue CC1pi0 isCC0pi_PassExpectations[&fe_CCNpi_1] = false; // numu CC multi pi isCC0pi_PassExpectations[&fe_CCNpi_2] = false; // numu CC multi pi isCC0pi_PassExpectations[&fe_CCNpi_3] = false; // numu CC multi pi isCC0pi_PassExpectations[&fe_CCNpi_4] = false; // numu CC multi pi isCC0pi_PassExpectations[&fe_CCCOH_1] = false; // numu CC COH pi isCC0pi_PassExpectations[&fe_NCel_1] = false; // numu NCEl isCC0pi_PassExpectations[&fe_NCel_2] = false; // nue NCEl isCC0pi_PassExpectations[&fe_NC1pi_1] = false; // numu NC1pi isCC0pi_PassExpectations[&fe_NCNpi_1] = false; // numu NC multi pi ctr = 0; for (std::map::iterator fe_it = isCC0pi_PassExpectations.begin(); fe_it != isCC0pi_PassExpectations.end(); ++fe_it, ++ctr) { bool res = SignalDef::isCC0pi(fe_it->first, 14); if (res != fe_it->second) { ERR(FTL) << "Event: (" << ctr << ")\n" << fe_it->first->ToString() << " " << std::endl; ERR(FTL) << (res ? "passed" : "failed") << " SignalDef::isCC0pi unexpectedly." << std::endl; } else { LOG(SAM) << "Event: (" << ctr << ") " << (res ? "passed" : "failed") << " as expected." << std::endl; } if (FailOnFail) { assert(res == fe_it->second); } } LOG(FIT) << "* Testing: SignalDef::isCCQELike" << std::endl; std::map isCCQELike_PassExpectations; isCCQELike_PassExpectations[&fe_CC0pi_1] = true; // numu CC0pi isCCQELike_PassExpectations[&fe_CC0pi_2] = true; // numu CC0pi (2p2h) isCCQELike_PassExpectations[&fe_CC0pi_3] = false; // numub CC0pi isCCQELike_PassExpectations[&fe_CC0pi_4] = false; // numu CC0pi (RES) isCCQELike_PassExpectations[&fe_CC1pip_1] = true; // numu CC1pip (2p2h) isCCQELike_PassExpectations[&fe_CC1pim_1] = false; // numu CC1pim isCCQELike_PassExpectations[&fe_CC1pi0_1] = false; // numu CC1pi0 isCCQELike_PassExpectations[&fe_CC1pi0_2] = false; // nue CC1pi0 isCCQELike_PassExpectations[&fe_CCNpi_1] = false; // numu CC multi pi isCCQELike_PassExpectations[&fe_CCNpi_2] = false; // numu CC multi pi isCCQELike_PassExpectations[&fe_CCNpi_3] = false; // numu CC multi pi isCCQELike_PassExpectations[&fe_CCNpi_4] = false; // numu CC multi pi isCCQELike_PassExpectations[&fe_CCCOH_1] = false; // numu CC COH pi isCCQELike_PassExpectations[&fe_NCel_1] = false; // numu NCEl isCCQELike_PassExpectations[&fe_NCel_2] = false; // nue NCEl isCCQELike_PassExpectations[&fe_NC1pi_1] = false; // numu NC1pi isCCQELike_PassExpectations[&fe_NCNpi_1] = false; // numu NC multi pi ctr = 0; for (std::map::iterator fe_it = isCCQELike_PassExpectations.begin(); fe_it != isCCQELike_PassExpectations.end(); ++fe_it, ++ctr) { bool res = SignalDef::isCCQELike(fe_it->first, 14); if (res != fe_it->second) { ERR(FTL) << "Event: (" << ctr << ")\n" << fe_it->first->ToString() << std::endl; ERR(FTL) << (res ? "passed" : "failed") << " SignalDef::isCCQELike unexpectedly." << std::endl; } else { LOG(SAM) << "Event: (" << ctr << ") " << (res ? "passed" : "failed") << " as expected." << std::endl; } if (FailOnFail) { assert(res == fe_it->second); } } LOG(FIT) << "* Testing: SignalDef::isCCQE" << std::endl; std::map isCCQE_PassExpectations; isCCQE_PassExpectations[&fe_CC0pi_1] = true; // numu CC0pi isCCQE_PassExpectations[&fe_CC0pi_2] = false; // numu CC0pi (2p2h) isCCQE_PassExpectations[&fe_CC0pi_3] = false; // numub CC0pi isCCQE_PassExpectations[&fe_CC0pi_4] = false; // numu CC0pi (RES) isCCQE_PassExpectations[&fe_CC1pip_1] = false; // numu CC1pip (2p2h) isCCQE_PassExpectations[&fe_CC1pim_1] = false; // numu CC1pim isCCQE_PassExpectations[&fe_CC1pi0_1] = false; // numu CC1pi0 isCCQE_PassExpectations[&fe_CC1pi0_2] = false; // nue CC1pi0 isCCQE_PassExpectations[&fe_CCNpi_1] = false; // numu CC multi pi isCCQE_PassExpectations[&fe_CCNpi_2] = false; // numu CC multi pi isCCQE_PassExpectations[&fe_CCNpi_3] = false; // numu CC multi pi isCCQE_PassExpectations[&fe_CCNpi_4] = false; // numu CC multi pi isCCQE_PassExpectations[&fe_CCCOH_1] = false; // numu CC COH pi isCCQE_PassExpectations[&fe_NCel_1] = false; // numu NCEl isCCQE_PassExpectations[&fe_NCel_2] = false; // nue NCEl isCCQE_PassExpectations[&fe_NC1pi_1] = false; // numu NC1pi isCCQE_PassExpectations[&fe_NCNpi_1] = false; // numu NC multi pi ctr = 0; for (std::map::iterator fe_it = isCCQE_PassExpectations.begin(); fe_it != isCCQE_PassExpectations.end(); ++fe_it, ++ctr) { bool res = SignalDef::isCCQE(fe_it->first, 14); if (res != fe_it->second) { ERR(FTL) << "Event: (" << ctr << ")\n" << fe_it->first->ToString() << std::endl; ERR(FTL) << (res ? "passed" : "failed") << " SignalDef::isCCQE unexpectedly." << std::endl; } else { LOG(SAM) << "Event: (" << ctr << ") " << (res ? "passed" : "failed") << " as expected." << std::endl; } if (FailOnFail) { assert(res == fe_it->second); } } LOG(FIT) << "* Testing: SignalDef::isCCCOH" << std::endl; std::map isCCCOH_PassExpectations; isCCCOH_PassExpectations[&fe_CC0pi_1] = false; // numu CC0pi isCCCOH_PassExpectations[&fe_CC0pi_2] = false; // numu CC0pi (2p2h) isCCCOH_PassExpectations[&fe_CC0pi_3] = false; // numub CC0pi isCCCOH_PassExpectations[&fe_CC0pi_4] = false; // numu CC0pi (RES) isCCCOH_PassExpectations[&fe_CC1pip_1] = false; // numu CC1pip (2p2h) isCCCOH_PassExpectations[&fe_CC1pim_1] = false; // numu CC1pim isCCCOH_PassExpectations[&fe_CC1pi0_1] = false; // numu CC1pi0 isCCCOH_PassExpectations[&fe_CC1pi0_2] = false; // nue CC1pi0 isCCCOH_PassExpectations[&fe_CCNpi_1] = false; // numu CC multi pi isCCCOH_PassExpectations[&fe_CCNpi_2] = false; // numu CC multi pi isCCCOH_PassExpectations[&fe_CCNpi_3] = false; // numu CC multi pi isCCCOH_PassExpectations[&fe_CCNpi_4] = false; // numu CC multi pi isCCCOH_PassExpectations[&fe_CCCOH_1] = true; // numu CC COH pi isCCCOH_PassExpectations[&fe_NCel_1] = false; // numu NCEl isCCCOH_PassExpectations[&fe_NCel_2] = false; // nue NCEl isCCCOH_PassExpectations[&fe_NC1pi_1] = false; // numu NC1pi isCCCOH_PassExpectations[&fe_NCNpi_1] = false; // numu NC multi pi ctr = 0; for (std::map::iterator fe_it = isCCCOH_PassExpectations.begin(); fe_it != isCCCOH_PassExpectations.end(); ++fe_it, ++ctr) { bool res = SignalDef::isCCCOH(fe_it->first, 14, 211); if (res != fe_it->second) { ERR(FTL) << "Event: (" << ctr << ")\n" << fe_it->first->ToString() << std::endl; ERR(FTL) << (res ? "passed" : "failed") << " SignalDef::isCCCOH unexpectedly." << std::endl; } else { LOG(SAM) << "Event: (" << ctr << ") " << (res ? "passed" : "failed") << " as expected." << std::endl; } if (FailOnFail) { assert(res == fe_it->second); } } LOG(FIT) << "* Testing: SignalDef::isCC1pi" << std::endl; std::map isCC1pi_PassExpectations; isCC1pi_PassExpectations[&fe_CC0pi_1] = false; // numu CC0pi isCC1pi_PassExpectations[&fe_CC0pi_2] = false; // numu CC0pi (2p2h) isCC1pi_PassExpectations[&fe_CC0pi_3] = false; // numub CC0pi isCC1pi_PassExpectations[&fe_CC0pi_4] = false; // numu CC0pi (RES) isCC1pi_PassExpectations[&fe_CC1pip_1] = true; // numu CC1pip (2p2h) isCC1pi_PassExpectations[&fe_CC1pim_1] = false; // numu CC1pim isCC1pi_PassExpectations[&fe_CC1pi0_1] = false; // numu CC1pi0 isCC1pi_PassExpectations[&fe_CC1pi0_2] = false; // nue CC1pi0 isCC1pi_PassExpectations[&fe_CCNpi_1] = false; // numu CC multi pi isCC1pi_PassExpectations[&fe_CCNpi_2] = false; // numu CC multi pi isCC1pi_PassExpectations[&fe_CCNpi_3] = false; // numu CC multi pi isCC1pi_PassExpectations[&fe_CCNpi_4] = false; // numu CC multi pi isCC1pi_PassExpectations[&fe_CCCOH_1] = true; // numu CC COH pi isCC1pi_PassExpectations[&fe_NCel_1] = false; // numu NCEl isCC1pi_PassExpectations[&fe_NCel_2] = false; // nue NCEl isCC1pi_PassExpectations[&fe_NC1pi_1] = false; // numu NC1pi isCC1pi_PassExpectations[&fe_NCNpi_1] = false; // numu NC multi pi ctr = 0; for (std::map::iterator fe_it = isCC1pi_PassExpectations.begin(); fe_it != isCC1pi_PassExpectations.end(); ++fe_it, ++ctr) { bool res = SignalDef::isCC1pi(fe_it->first, 14, 211); if (res != fe_it->second) { ERR(FTL) << "Event: (" << ctr << ")\n" << fe_it->first->ToString() << std::endl; ERR(FTL) << (res ? "passed" : "failed") << " SignalDef::isCC1pi unexpectedly." << std::endl; } else { LOG(SAM) << "Event: (" << ctr << ") " << (res ? "passed" : "failed") << " as expected." << std::endl; } if (FailOnFail) { assert(res == fe_it->second); } } LOG(FIT) << "* Testing: SignalDef::isNC1pi" << std::endl; std::map isNC1pi_PassExpectations; isNC1pi_PassExpectations[&fe_CC0pi_1] = false; // numu CC0pi isNC1pi_PassExpectations[&fe_CC0pi_2] = false; // numu CC0pi (2p2h) isNC1pi_PassExpectations[&fe_CC0pi_3] = false; // numub CC0pi isCCINC_PassExpectations[&fe_CC0pi_4] = false; // numu CC0pi (RES) isNC1pi_PassExpectations[&fe_CC1pip_1] = false; // numu CC1pip (2p2h) isNC1pi_PassExpectations[&fe_CC1pim_1] = false; // numu CC1pim isNC1pi_PassExpectations[&fe_CC1pi0_1] = false; // numu CC1pi0 isNC1pi_PassExpectations[&fe_CC1pi0_2] = false; // nue CC1pi0 isNC1pi_PassExpectations[&fe_CCNpi_1] = false; // numu CC multi pi isNC1pi_PassExpectations[&fe_CCNpi_2] = false; // numu CC multi pi isNC1pi_PassExpectations[&fe_CCNpi_3] = false; // numu CC multi pi isNC1pi_PassExpectations[&fe_CCNpi_4] = false; // numu CC multi pi isCCINC_PassExpectations[&fe_CCCOH_1] = false; // numu CC COH pi isNC1pi_PassExpectations[&fe_NCel_1] = false; // numu NCEl isNC1pi_PassExpectations[&fe_NCel_2] = false; // nue NCEl isCCINC_PassExpectations[&fe_NC1pi_1] = true; // numu NC1pi isCCINC_PassExpectations[&fe_NCNpi_1] = false; // numu NC multi pi ctr = 0; for (std::map::iterator fe_it = isNC1pi_PassExpectations.begin(); fe_it != isNC1pi_PassExpectations.end(); ++fe_it, ++ctr) { bool res = SignalDef::isNC1pi(fe_it->first, 14, -211); if (res != fe_it->second) { ERR(FTL) << "Event: (" << ctr << ")\n" << fe_it->first->ToString() << std::endl; ERR(FTL) << (res ? "passed" : "failed") << " SignalDef::isNC1pi unexpectedly." << std::endl; } else { LOG(SAM) << "Event: (" << ctr << ") " << (res ? "passed" : "failed") << " as expected." << std::endl; } if (FailOnFail) { assert(res == fe_it->second); } } // SignalDef::isCCWithFS(&fe,14); } diff --git a/src/Utils/PlotUtils.cxx b/src/Utils/PlotUtils.cxx index 1c84777..40d2f13 100644 --- a/src/Utils/PlotUtils.cxx +++ b/src/Utils/PlotUtils.cxx @@ -1,1027 +1,1029 @@ // 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)); // Now Get a flux PDF assuming X axis is Enu TH1D* pdfflux = (TH1D*)fMCHist->ProjectionX()->Clone(); // pdfflux->Write( (std::string(fMCHist->GetName()) + "_PROJX").c_str()); pdfflux->Reset(); // Awful MiniBooNE Check for the time being 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); } for (int i = 0; i < fMCHist->GetNbinsX(); i++) { for (int j = 0; j < fMCHist->GetNbinsY(); j++) { if (pdfflux->GetBinContent(i + 1) == 0.0) continue; double binWidth = fMCHist->GetYaxis()->GetBinLowEdge(j + 2) - fMCHist->GetYaxis()->GetBinLowEdge(j + 1); 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); } } delete eventhist; delete fFluxHist; return; }; 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(); if (FitPar::Config().GetParB("save_flux_debug")) { std::string name = std::string(mcHist->GetName()); 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); } // 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; return; }; // 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(), ifstream::in); + 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 or 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 { // Make a TGraph Errors TGraphErrors* gr = new TGraphErrors(dataFile.c_str(), "%lg %lg %lg"); if (gr->IsZombie()) { exit(-1); } 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 if (!errors[i]) 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(); 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()) { THROW("Couldn't open root file: \"" << file << "\"."); } TH1* tempHist = dynamic_cast(rootHistFile->Get(name.c_str())->Clone()); if (!tempHist) { THROW("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()) { THROW("Couldn't open root file: \"" << file << "\"."); } TDirectory* newdir = gDirectory; TGraph* temp = dynamic_cast(rootHistFile->Get(name.c_str())->Clone()); if (!temp) { THROW("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()) { THROW("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()) { THROW( "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()) { THROW("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) { THROW("Couldn't retrieve: \"" << histnames[i] << "\" from root file: \"" << fname[0] << "\"."); } tempHist->SetDirectory(0); hists.push_back(tempHist); } rootHistFile->Close(); } return hists; } TH2D* PlotUtils::GetTH2DFromTextFile(std::string file) { /// Contents should be /// Low Edfe return NULL; } 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); LOG(REC) << "MaskBins: Set " << hist->GetName() << " Bin " << i + 1 << " to 0.0 +- 0.0" << std::endl; } 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); LOG(REC) << "MaskBins: Set " << hist->GetName() << " Bin " << i + 1 << " " << j + 1 << " to 0.0 +- 0.0" << std::endl; } } 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); TH1D* hist_X = maskedhist->ProjectionX(); delete maskedhist; return hist_X; } //*************************************************** TH1D* PlotUtils::GetProjectionY(TH2D* hist, TH2I* mask) { //*************************************************** TH2D* maskedhist = StatUtils::ApplyHistogramMasking(hist, mask); TH1D* hist_Y = maskedhist->ProjectionY(); delete maskedhist; return hist_Y; }