diff --git a/CMakeLists.txt b/CMakeLists.txt index 342761b..eb7a6d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,82 +1,78 @@ # Copyright 2018 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.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) set (NUISANCE_VERSION_MAJOR 3) set (NUISANCE_VERSION_MINOR 0) 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) include(${CMAKE_SOURCE_DIR}/cmake/parseConfigApp.cmake) include(${CMAKE_SOURCE_DIR}/cmake/StringAndListUtils.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) ################################# InputHandler ################################# include(${CMAKE_SOURCE_DIR}/cmake/InputHandlerSetup.cmake) ################################# Pythia6/8 ################################### include(${CMAKE_SOURCE_DIR}/cmake/pythia6Setup.cmake) ################################## FHICLCPP #################################### include(${CMAKE_SOURCE_DIR}/cmake/fhiclcppSetup.cmake) #Want this after fhiclcpp which will add the install directory include_directories(${CMAKE_SOURCE_DIR}/src) ################################## COMPILER #################################### include(${CMAKE_SOURCE_DIR}/cmake/c++CompilerSetup.cmake) ################################################################################ add_subdirectory(src) -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}) +add_subdirectory(scripts) add_subdirectory(config) add_subdirectory(data) diff --git a/cmake/c++CompilerSetup.cmake b/cmake/c++CompilerSetup.cmake index 17399d9..5083311 100644 --- a/cmake/c++CompilerSetup.cmake +++ b/cmake/c++CompilerSetup.cmake @@ -1,57 +1,57 @@ # Copyright 2018 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(CXX_WARNINGS -Wall -Wextra) LIST(APPEND EXTRA_CXX_FLAGS ${CXX_WARNINGS} -Werror -Wno-delete-non-virtual-dtor -Wno-unused "-D__FILENAME__=\"$(subst ${CMAKE_SOURCE_DIR}/,,$(abspath $<))\"") BuildFlagString(NUISANCE_LINK_DIRS "-L" ${EXTRA_LINK_DIRS}) LIST(APPEND EXTRA_LIBS dl) BuildLibraryFlagString(STR_EXTRA_LIBS ${EXTRA_LIBS}) BuildFlagString(STR_EXTRA_SHAREDOBJS " " ${EXTRA_SHAREDOBJS}) #This ends up holding all of the libraries and search paths for extenal dependencies CatStringsIfNotEmpty(NUISANCE_DEPEND_LIBS ${STR_EXTRA_SHAREDOBJS} ${STR_EXTRA_LIBS}) BuildFlagString(STR_EXTRA_LINK_FLAGS " " ${EXTRA_LINK_FLAGS}) CatStringsIfNotEmpty(CMAKE_LINK_FLAGS ${CMAKE_LINK_FLAGS} ${STR_EXTRA_LINK_FLAGS}) get_directory_property(NUISANCE_INCLUDE_DIRS INCLUDE_DIRECTORIES) BuildFlagString(NUISANCE_CXX_FLAGS " " ${EXTRA_CXX_FLAGS}) CatStringsIfNotEmpty(NUISANCE_CXX_FLAGS ${CMAKE_CXX_FLAGS} ${NUISANCE_CXX_FLAGS} ) if (VERBOSE) cmessage (STATUS "C++ Compiler : ${CXX_COMPILER_NAME}") cmessage (STATUS " Flags : ${NUISANCE_CXX_FLAGS}") cmessage (STATUS " Release Flags : ${CMAKE_CXX_FLAGS_RELEASE}") cmessage (STATUS " Debug Flags : ${CMAKE_CXX_FLAGS_DEBUG}") - cmessage (STATUS " Include Dris : ${NUISANCE_INCLUDE_DIRS}") + cmessage (STATUS " Include Dirs : ${NUISANCE_INCLUDE_DIRS}") cmessage (STATUS " Linker Flags : ${CMAKE_LINK_FLAGS}") cmessage (STATUS " Link Dirs : ${NUISANCE_LINK_DIRS}") cmessage (STATUS " Lib Flags : ${NUISANCE_DEPEND_LIBS}") endif() add_compile_options(${EXTRA_CXX_FLAGS}) diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt new file mode 100644 index 0000000..d6ea15b --- /dev/null +++ b/scripts/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(to_configure) diff --git a/scripts/to_configure/CMakeLists.txt b/scripts/to_configure/CMakeLists.txt new file mode 100644 index 0000000..ab6657a --- /dev/null +++ b/scripts/to_configure/CMakeLists.txt @@ -0,0 +1,28 @@ +configure_file(setup.sh.in + ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/setup.sh @ONLY) +configure_file(nuisbuild.in + ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/nuisbuild @ONLY) +configure_file(nuiseventprocgen.in + ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/nuiseventprocgen @ONLY) + +install( + FILES + ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/setup.sh + DESTINATION + ${CMAKE_INSTALL_PREFIX} + ) + +install( + FILES + SimpleDataComparison.cxx.in SimpleMCStudy.cxx.in + DESTINATION + file_stubs + ) + +install( + PROGRAMS + ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/nuisbuild + ${PROJECT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/nuiseventprocgen + DESTINATION + bin + ) diff --git a/scripts/to_configure/SimpleDataComparison.cxx.in b/scripts/to_configure/SimpleDataComparison.cxx.in new file mode 100644 index 0000000..a82f398 --- /dev/null +++ b/scripts/to_configure/SimpleDataComparison.cxx.in @@ -0,0 +1,180 @@ +// Copyright 2018 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 "samples/SimpleDataComparison.hxx" + +#include "utility/EventTopologyUtility.hxx" +#include "utility/FullEventUtility.hxx" +#include "utility/KinematicUtility.hxx" +#include "utility/PDGCodeUtility.hxx" + +using namespace nuis::event; +using namespace nuis::utility; + +class __SAMPLE_NAME__ : public __SDC_TYPE__ { + + //! Add any extra plots that you want to fill as data members of the + //! comparisons class. + // std::unique_ptr Extra_plot; + +public: + __SAMPLE_NAME__() { ReadGlobalConfigDefaults(); } + + std::string GetDocumentation() { return ""; } + fhicl::ParameterSet GetExampleConfiguration() { + fhicl::ParameterSet exps = __SDC_TYPE__::GetExampleConfiguration(); + + return exps; + } + + void Initialize(fhicl::ParameterSet const &instance_sample_configuration) { + + //! Set the verbosity of the sample logging macros. + if (instance_sample_configuration.has_key("verbosity")) { + SetSampleVerbosity( + instance_sample_configuration.get("verbosity")); + + //! Use these macros within member functions to log to the terminal + //! See src/samples/IEventProcessor.hxx for more details. + IEventProcessor_INFO( + "Verbosity set: " + << instance_sample_configuration.get("verbosity")); + } + + // Get the global configuration for this sample, if it exists. + fhicl::ParameterSet const &global_sample_configuration = + nuis::config::GetDocument().get( + std::string("global.sample_configuration.") + Name(), + fhicl::ParameterSet()); + + //! This will automatically set the data histogram to be loaded. + // SetData( + // GetDataDir() + + // "path/to/data;histname"); + + //! Instantiate any extra plots that you want to fill + // Extra_plot = std::unique_ptr( + // new TH1D("Extra_plot", + // "title;xlabel;ylabel", + // nbinsx,xlow,xhigh)); + + // Perform any per-sample configuration in the base class + __SDC_TYPE__::Initialize(instance_sample_configuration); + + //! Define your event signal here. + IsSigFunc = [](FullEvent const &fev) -> bool { + //! See src/utility/EventTopologyUtility.hxx for more pre-defined + //! topological signals. + // if (!IsCC0Pi(fev)) { + // return false; + // } + + //! See src/event/FullEvent.hxx for the full event class definition. + //! See src/utility/FullEventUtility.hxx for more helper methods for + //! interacting with the event class. + + //! Get the initial state anti-muon neutrino + // Particle ISNumuBar = GetHMISParticle(fev, {pdgcodes::kNuMuBar}); + //! An nuis::event::Particle that return true for !part is invalid and + //! does not exist on the particle stack. i.e. here, the selection fails + //! if the event didn't have an initial state numubar. + // if (!ISNumuBar) { + // return false; + // } + + //! Get the final state anti-muon + // Particle FSMuPlus = GetHMFSParticle(fev, {pdgcodes::kMuPlus}); + // if (!FSMuPlus) { + // return false; + // } + + //! Cut on kinematic properties of the true final state. + // if (FSMuPlus.CosTheta() < 0.84) { + // return false; + // } + + //! Select the event! + return true; + }; + + //! 1D Projection function + //! This function takes selected events and returns an array of size, the + //! dimensionality of the comparisons (__SDC_TYPE__::NDim) + CompProjFunc = + [](FullEvent const &fev) -> std::array { + // Particle FSMuPlus = GetHMFSParticle(fev, {pdgcodes::kMuPlus}); + // return {FSMuPlus.P()}; + return { + 1, + }; + }; + + //! Here you fill any custom histograms or TTrees that your sample handles. + //! Note the [&] means that the generated closure object will take a + //! reference to any in scope variables that are used within the lambda + //! body. As this method is then called outside of the scope of this + //! Initialize method, you should not use any method-locals within the + //! ProcessExtraFunc body. Class members are fine as this will only be + //! called when the same instance of this class is alive. + ProcessExtraFunc = [&](FullEvent const &fev, bool isSel, + double weight) -> void { + //! Whether this event passed the selection function. (Saves you manually + //! reselecting events with the IsSigFunc) + if (isSel) { + // Particle FSMuPlus = GetHMFSParticle(fev, {pdgcodes::kMuPlus}); + //! The TH_Helper class provides some templated helper methods for + //! filling histogram types that are decided at compile time, these are + //! used by the SimpleDataComparison base class to provide a dimension + //! and precision agnostic interface, but they can also be used by user + //! classes if you see fit. See src/utility/HistogramUtility.hxx for + //! more details. + // TH_Helper::Fill(Extra_plot, {FSMuPlus.CosTheta()}, weight); + } + }; + } + + std::string Name() { return "__SAMPLE_NAME__"; } + + //! Here you can write any custom histograms to TTrees that your sample has + //! been handling. + void Write() { + //! The base class writes the default MC and data histograms to the output + //! directory automatically, so you only have to include logic to write any + //! custom histograms or TTrees out here. + __SDC_TYPE__::Write(); + + //! The nuis::persistency helper methods will help write your objects to the + //! correct place and in a TFile that will be closed before the program + //! exits. + //! They will write a copy of the TObject that is passed, so you do not need + //! to release/worry about double freeing any histograms passed. + //! write_directory is set up by the baseclass and is configurable in the + //! instance configuration. + // nuis::persistency::WriteToOutputFile(Extra_plot, + // Extra_plot->GetName(), + // write_directory); + //! It probably isn't a good idea to write a TTree with the above method, instead, try using nuis::persistency::GetOutputFile() to get the TFile and then manually writing/giving ownership of your TTree to the output file. + } +}; + +//! These declarations allow your class to be loaded dynamically by NUISANCE +DECLARE_PLUGIN(IDataComparison, __SAMPLE_NAME__); +DECLARE_PLUGIN(IEventProcessor, __SAMPLE_NAME__); diff --git a/scripts/to_configure/SimpleMCStudy.cxx.in b/scripts/to_configure/SimpleMCStudy.cxx.in new file mode 100644 index 0000000..e52906a --- /dev/null +++ b/scripts/to_configure/SimpleMCStudy.cxx.in @@ -0,0 +1,117 @@ +// Copyright 2018 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 "samples/SimpleMCStudy.hxx" + +#include "utility/EventTopologyUtility.hxx" +#include "utility/FullEventUtility.hxx" +#include "utility/KinematicUtility.hxx" +#include "utility/PDGCodeUtility.hxx" + +using namespace nuis::event; +using namespace nuis::utility; + +class __SAMPLE_NAME__ : public SimpleMCStudy { + + //! Add any plots that you want to fill as data members of the + //! comparisons class. + // std::unique_ptr myPlot; + +public: + __SAMPLE_NAME__() { ReadGlobalConfigDefaults(); } + + void Initialize(fhicl::ParameterSet const &instance_sample_configuration) { + + //! Set the verbosity of the sample logging macros. + if (instance_sample_configuration.has_key("verbosity")) { + SetSampleVerbosity( + instance_sample_configuration.get("verbosity")); + + //! Use these macros within member functions to log to the terminal + //! See src/samples/IEventProcessor.hxx for more details. + IEventProcessor_INFO( + "Verbosity set: " + << instance_sample_configuration.get("verbosity")); + } + + // Get the global configuration for this sample, if it exists. + fhicl::ParameterSet const &global_sample_configuration = + nuis::config::GetDocument().get( + std::string("global.sample_configuration.") + Name(), + fhicl::ParameterSet()); + + //! Instantiate any plots that you want to fill + // myPlot = std::unique_ptr( + // new TH1D("myPlot", + // "title;xlabel;ylabel", + // nbinsx,xlow,xhigh)); + + // Perform any per-sample configuration in the base class + SimpleMCStudy::Initialize(instance_sample_configuration); + + //! Here you do whatever you want to do on a per-event basis. + //! This method will be run for every event given by the input handler, the + //! weight allows differential xsecs to be plotted easily and also contains + //! any requested reweightable parameter variations. + ProcessEventFunction = [&](nuis::event::FullEvent const &ev, + double weight) -> void { + //! Select events + //! See src/utility/EventTopologyUtility.hxx for more pre-defined + //! topological signals. + // if (!IsCC0Pi(fev)) { + // return false; + // } + + //! Build composite variables + //! See src/event/FullEvent.hxx for the full event class definition. + //! See src/utility/FullEventUtility.hxx for more helper methods for + //! interacting with the event class. + // Particle FSMuPlus = GetHMFSParticle(fev, {pdgcodes::kMuPlus}); + + //! Fill your histograms! + // myPlot->Fill(FSMuPlus.CosTheta(), weight); + }; + } + + std::string Name() { return "__SAMPLE_NAME__"; } + + //! Here you can write any custom histograms to TTrees that your sample has + //! been handling. + void Write() { + //! The nuis::persistency helper methods will help write your objects to the + //! correct place and in a TFile that will be closed before the program + //! exits. + //! They will write a copy of the TObject that is passed, so you do not need + //! to release/worry about double freeing any histograms passed. + //! write_directory is set up by the baseclass and is configurable in the + //! instance configuration. + // nuis::persistency::WriteToOutputFile(Extra_plot, + // Extra_plot->GetName(), + // write_directory); + //! It probably isn't a good idea to write a TTree with the above method, + //! instead, try using nuis::persistency::GetOutputFile() to get the TFile + //! and then manually writing/giving ownership of your TTree to the output + //! file. + } +}; + +//! These declarations allow your class to be loaded dynamically by NUISANCE +DECLARE_PLUGIN(IEventProcessor, __SAMPLE_NAME__); diff --git a/scripts/to_configure/nuisbuild.in b/scripts/to_configure/nuisbuild.in new file mode 100644 index 0000000..316b790 --- /dev/null +++ b/scripts/to_configure/nuisbuild.in @@ -0,0 +1,101 @@ +# 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/bash + +EXTRA_COMPILE_FLAGS="" +EXTRA_LINK_FLAGS="" +INPUT_FILE_NAME="" +OUTPUT_LIB_NAME="" + +SCRIPTNAME=${0} + +while [[ ${#} -gt 0 ]]; do + + key="$1" + case $key in + + -i|--implementation-file) + + if [[ ${#} -lt 2 ]]; then + echo "[ERROR]: ${1} expected a value." + exit 1 + fi + + INPUT_FILE_NAME="$2" + echo "[OPT]: Reading event processor implementation from: ${INPUT_FILE_NAME}" + shift # past argument + ;; + + --compile-flags) + + if [[ ${#} -lt 2 ]]; then + echo "[ERROR]: ${1} expected a value." + exit 1 + fi + + EXTRA_COMPILE_FLAGS="$2" + echo "[OPT]: Including extra compile flags: ${EXTRA_COMPILE_FLAGS}" + shift # past argument + ;; + + --link-flags) + + if [[ ${#} -lt 2 ]]; then + echo "[ERROR]: ${1} expected a value." + exit 1 + fi + + EXTRA_LINK_FLAGS="$2" + echo "[OPT]: Including extra linker flags: ${EXTRA_LINK_FLAGS}" + shift # past argument + ;; + + -?|--help) + + echo "[RUNLIKE] ${SCRIPTNAME}" + echo -e "\t-i|--implementation-file : Path to IEventProcessor subclass to build into dynamically loadable shared object." + echo -e "\t--compile-flags : Extra compile flags to pass to the compiler." + echo -e "\t--link-flags : Extra linker flags to pass to the linker." + echo -e "\t-?|--help : Print this message." + exit 0 + ;; + + *) + # unknown option + echo "Unknown option $1" + exit 1 + ;; + + esac + shift +done + +OUTPUT_LIB_NAME=${INPUT_FILE_NAME%.*}.so + +#Removes the NUISANCE filename descriptor that uses a gmake trick to insert the file name into the compiler options +NUISANCE_CXX_FLAGS_GMAKE_SCRUB=$(echo '@NUISANCE_CXX_FLAGS@' | sed s/-D__FILENAME__=\".*\"//g) + +echo "@CMAKE_CXX_COMPILER@ ${INPUT_FILE_NAME} -shared -fPIC -o ${OUTPUT_LIB_NAME} ${NUISANCE_CXX_FLAGS_GMAKE_SCRUB} ${EXTRA_COMPILE_FLAGS} -D__FILENAME__=\"${INPUT_FILE_NAME##*/}\" -I. -I@CMAKE_INSTALL_PREFIX@/include @CMAKE_LINK_FLAGS@ ${EXTRA_LINK_FLAGS} -L@CMAKE_INSTALL_PREFIX@/lib @NUISANCE_LINK_DIRS@ @NUISANCE_DEPEND_LIBS@" + +if ! @CMAKE_CXX_COMPILER@ ${INPUT_FILE_NAME} -shared -fPIC -o ${OUTPUT_LIB_NAME} ${NUISANCE_CXX_FLAGS_GMAKE_SCRUB} ${EXTRA_COMPILE_FLAGS} -D__FILENAME__=\"${INPUT_FILE_NAME##*/}\" -I. -I@CMAKE_INSTALL_PREFIX@/include @CMAKE_LINK_FLAGS@ ${EXTRA_LINK_FLAGS} -L@CMAKE_INSTALL_PREFIX@/lib @NUISANCE_LINK_DIRS@ @NUISANCE_DEPEND_LIBS@; then + echo "[ERROR]: Failed to compile ${INPUT_FILE_NAME} -> ${OUTPUT_LIB_NAME}" +else + echo "[INFO]: Successfully build: ${OUTPUT_LIB_NAME}." +fi diff --git a/scripts/to_configure/nuiseventprocgen.in b/scripts/to_configure/nuiseventprocgen.in new file mode 100644 index 0000000..fb60275 --- /dev/null +++ b/scripts/to_configure/nuiseventprocgen.in @@ -0,0 +1,131 @@ +# 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/bash + +CLASS_NAME="" +NDIMS="0" +INPUT_FILE_NAME="" +USE_POLY="0" +SDC_TYPE="" + +while [[ ${#} -gt 0 ]]; do + + key="$1" + case $key in + + -c|--class-name) + + if [[ ${#} -lt 2 ]]; then + echo "[ERROR]: ${1} expected a value." + exit 1 + fi + + CLASS_NAME="$2" + echo "[OPT]: Generating class named: ${CLASS_NAME} in implementation file: ${CLASS_NAME}.cxx" + shift # past argument + ;; + + --MC) + + INPUT_FILE_NAME="SimpleMCStudy.cxx.in" + echo "[OPT]: Generating simple MC study stub class." + ;; + + --data) + + INPUT_FILE_NAME="SimpleDataComparison.cxx.in" + echo "[OPT]: Generating data comparison stub class." + NDIMS="1" + ;; + + -n|--n-dimensions) + + if [[ ${#} -lt 2 ]]; then + echo "[ERROR]: ${1} expected a value." + exit 1 + fi + + NDIMS="${2}" + echo "[OPT]: Using a ${NDIMS} dimensional comparison" + shift # past argument + ;; + + --poly) + + USE_POLY="1" + echo "[OPT]: Using a TH2Poly comparion." + ;; + + -?|--help) + + echo "[RUNLIKE] ${SCRIPTNAME}" + echo -e "\t-c|--class-name : Name of generated event processor" + echo -e "\t class." + echo -e "\t--MC : Generate a simple MC study shell." + echo -e "\t--data : Generate a 'sample' shell." + echo -e "\t-n|--n-dimensions : Dimension of the data comparison" + echo -e "\t . Only valid for" + echo -e "\t --data (Currently can only be 1" + echo -e "\t or 2)." + echo -e "\t--poly : Build data comparison using" + echo -e "\t TH2Poly. Only valid for --data " + echo -e "\t -n 2" + echo -e "\t-?|--help : Print this message." + exit 0 + ;; + + *) + # unknown option + echo "Unknown option $1" + exit 1 + ;; + + esac + shift +done + +if [ ${INPUT_FILE_NAME} == "SimpleDataComparison.cxx.in" ]; then + if [ ${NDIMS} == "1" ]; then + SDC_TYPE=SimpleDataComparison_1D + elif [ ${NDIMS} == "2" ]; then + if [ ${USE_POLY} == "1" ]; then + SDC_TYPE=SimpleDataComparison_2DPoly + else + SDC_TYPE=SimpleDataComparison_2D + fi + else + echo "[ERROR]: Can only currently set dimensionality to 1 or 2 dimensions." + exit 1 + fi +fi + +if [ -e ${CLASS_NAME}.cxx ]; then + echo "[ERROR]: ${CLASS_NAME}.cxx already exists, not overwriting. Please use a different class name." + exit 2 +fi + +cp @CMAKE_INSTALL_PREFIX@/file_stubs/${INPUT_FILE_NAME} ${CLASS_NAME}.cxx + +sed -i "s/__SAMPLE_NAME__/${CLASS_NAME}/g" ${CLASS_NAME}.cxx +if [ ! -z ${SDC_TYPE} ]; then + sed -i "s/__SDC_TYPE__/${SDC_TYPE}/g" ${CLASS_NAME}.cxx +fi + +echo "[INFO]: Generated ${CLASS_NAME}.cxx" diff --git a/cmake/setup.sh.in b/scripts/to_configure/setup.sh.in similarity index 100% rename from cmake/setup.sh.in rename to scripts/to_configure/setup.sh.in diff --git a/scripts/dumpgenieconfig.py b/scripts_old/dumpgenieconfig.py similarity index 100% rename from scripts/dumpgenieconfig.py rename to scripts_old/dumpgenieconfig.py diff --git a/scripts/maketarball.sh b/scripts_old/maketarball.sh similarity index 100% rename from scripts/maketarball.sh rename to scripts_old/maketarball.sh diff --git a/scripts/nuiscardgen b/scripts_old/nuiscardgen similarity index 100% rename from scripts/nuiscardgen rename to scripts_old/nuiscardgen diff --git a/scripts/nuissamples b/scripts_old/nuissamples similarity index 100% rename from scripts/nuissamples rename to scripts_old/nuissamples diff --git a/scripts/plotlimitdist.py b/scripts_old/plotlimitdist.py similarity index 100% rename from scripts/plotlimitdist.py rename to scripts_old/plotlimitdist.py diff --git a/scripts/plotnuiscomp.py b/scripts_old/plotnuiscomp.py similarity index 100% rename from scripts/plotnuiscomp.py rename to scripts_old/plotnuiscomp.py diff --git a/scripts/plotnuismin.py b/scripts_old/plotnuismin.py similarity index 100% rename from scripts/plotnuismin.py rename to scripts_old/plotnuismin.py diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b615e75..d5b8f1d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,15 +1,16 @@ add_subdirectory(config) add_subdirectory(event) +add_subdirectory(exception) +add_subdirectory(generator) add_subdirectory(input) +add_subdirectory(parameters) +add_subdirectory(persistency) add_subdirectory(plugins) +add_subdirectory(samples) add_subdirectory(utility) -add_subdirectory(generator) -add_subdirectory(persistency) -add_subdirectory(parameters) add_subdirectory(variation) -add_subdirectory(samples) SET(INuADataComparisons_List ${INuADataComparisons_List} PARENT_SCOPE) SET(INuADataComparisons_FHiCL ${INuADataComparisons_FHiCL} PARENT_SCOPE) add_subdirectory(app) diff --git a/src/samples/CMakeLists.txt b/src/samples/CMakeLists.txt index a31710c..6313da0 100644 --- a/src/samples/CMakeLists.txt +++ b/src/samples/CMakeLists.txt @@ -1,23 +1,24 @@ set(samples_header_files IEventProcessor.hxx IDataComparison.hxx - SimpleDataComparison.hxx) + SimpleDataComparison.hxx + SimpleMCStudy.hxx) install(FILES ${samples_header_files} DESTINATION include/samples) add_subdirectory(MCTools) add_subdirectory(nuA) cmessage(DEBUG "INuADataComparisons: ${INuADataComparisons}") SET(INuADataComparisons_List) if(NOT IDataComparisons STREQUAL "") string(REPLACE ";" ", " INuADataComparisons_List "${INuADataComparisons}") endif() cmessage(DEBUG "INuADataComparisons_List: ${INuADataComparisons_List}") SET(INuADataComparisons_List ${INuADataComparisons_List} PARENT_SCOPE) SET(INuADataComparisons_FHiCL ${INuADataComparisons_FHiCL} PARENT_SCOPE) diff --git a/src/samples/SimpleDataComparison.hxx b/src/samples/SimpleDataComparison.hxx index 36f8e7a..a63e4df 100644 --- a/src/samples/SimpleDataComparison.hxx +++ b/src/samples/SimpleDataComparison.hxx @@ -1,424 +1,426 @@ // Copyright 2018 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 SAMPLES_SIMPLEDATACOMPARISON_HXX_SEEN -#define SAMPLES_SIMPLEDATACOMPARISON_HXX_SEEN +#pragma once #include "samples/IDataComparison.hxx" #include "event/FullEvent.hxx" #include "input/InputManager.hxx" #include "persistency/ROOTOutput.hxx" #include "utility/FileSystemUtility.hxx" #include "utility/HistogramUtility.hxx" #include "utility/KinematicUtility.hxx" #include "utility/ROOTUtility.hxx" #include "utility/StatsUtility.hxx" #include #include #include #include #include -template ::type> +template ::type> class SimpleDataComparison : public IDataComparison { NEW_NUIS_EXCEPT(invalid_SimpleDataComparison_initialization); NEW_NUIS_EXCEPT(SimpleDataComparison_already_finalized); protected: using HistType = HT; using TH_Help = typename nuis::utility::TH_Helper; + static size_t const NDim = nd; + nuis::input::InputManager::Input_id_t fIH_id; std::string write_directory; size_t NMaxSample_override; int fIsShapeOnly; int fIsFluxUnfolded; std::vector fSignalCache; std::vector> fProjectionCache; std::string fDataInputDescriptor; std::unique_ptr fData; std::string fMaskInputDescriptor; std::unique_ptr fMask; std::string fCovarianceInputDescriptor; std::unique_ptr fCovariance; std::unique_ptr fPrediction; std::unique_ptr fPrediction_xsec; std::unique_ptr fPrediction_shape; std::unique_ptr fPrediction_comparison; bool fComparisonFinalized; std::string fJournalReference; std::string fTargetMaterial; std::string fFluxDescription; std::string fSignalDescription; nuis::utility::ENuRange energy_cut; std::function IsSigFunc; std::function(nuis::event::FullEvent const &)> CompProjFunc; // If assigned by subclass will be called on for all events, bool signifies // whether the event was selected. std::function ProcessExtraFunc; public: SimpleDataComparison() { fIH_id = std::numeric_limits::max(); write_directory = ""; NMaxSample_override = std::numeric_limits::max(); fDataInputDescriptor = ""; fData = nullptr; fMaskInputDescriptor = ""; fMask = nullptr; fCovarianceInputDescriptor = ""; fCovariance = nullptr; fPrediction = nullptr; fPrediction_xsec = nullptr; fPrediction_shape = nullptr; fPrediction_comparison = nullptr; fComparisonFinalized = false; IsSigFunc = [](nuis::event::FullEvent const &) -> bool { return true; }; CompProjFunc = [](nuis::event::FullEvent const &) -> std::array { std::array arr; for (NumericT &el : arr) { el = 0; } return arr; }; ProcessExtraFunc = std::function(); fJournalReference = ""; fTargetMaterial = ""; fFluxDescription = ""; fSignalDescription = ""; fIsShapeOnly = -1; fIsFluxUnfolded = -1; energy_cut = nuis::utility::ENuRange{std::numeric_limits::max(), std::numeric_limits::max()}; } fhicl::ParameterSet fGlobalConfig; fhicl::ParameterSet fInstanceConfig; void ReadGlobalConfigDefaults() { fGlobalConfig = nuis::config::GetDocument().get( std::string("global.sample_configuration.") + Name(), fhicl::ParameterSet()); if (!fJournalReference.length()) { fJournalReference = fGlobalConfig.get("journal_reference", fJournalReference); } if (!fTargetMaterial.length()) { fTargetMaterial = fGlobalConfig.get("target_material", fTargetMaterial); } if (!fFluxDescription.length()) { fFluxDescription = fGlobalConfig.get("flux_description", fFluxDescription); } if (!fSignalDescription.length()) { fSignalDescription = fGlobalConfig.get("signal_description", fSignalDescription); } if (fIsShapeOnly == -1) { fIsShapeOnly = fGlobalConfig.get("shape_only", false); } if (fIsFluxUnfolded == -1) { fIsFluxUnfolded = fGlobalConfig.get("flux_unfolded", false); } if ((energy_cut.first == std::numeric_limits::max()) && (fGlobalConfig.has_key("enu_range"))) { energy_cut = fGlobalConfig.get>("enu_range"); } } virtual std::string GetJournalReference() { return fJournalReference; } virtual std::string GetTargetMaterial() { return fTargetMaterial; } virtual std::string GetFluxDescription() { return fFluxDescription; } virtual std::string GetSignalDescription() { return fSignalDescription; } void SetShapeOnly(bool iso) { fIsShapeOnly = iso; } void SetFluxUnfolded(bool ifo) { fIsFluxUnfolded = ifo; } void SetData(std::string const &data_descriptor) { fDataInputDescriptor = data_descriptor; } void SetMask(std::string const &mask_descriptor) { fMaskInputDescriptor = mask_descriptor; } void SetCovariance(std::string const &cov_descriptor) { fCovarianceInputDescriptor = cov_descriptor; } virtual void FillProjection(std::array const &proj, NumericT event_weight) { TH_Help::Fill(fPrediction, proj, event_weight); } virtual void FinalizeComparison() { if (fComparisonFinalized) { throw SimpleDataComparison_already_finalized() << "[ERROR]: Attempted to re-finalize a comparison for " "SimpleDataComparison: " << std::quoted(Name()); } fPrediction_xsec = nuis::utility::Clone(fPrediction, false, "Prediction_xsec"); IInputHandler const &IH = nuis::input::InputManager::Get().GetInputHandler(fIH_id); TH_Help::Scale(fPrediction_xsec, 1.0, "width"); // If we have a flux cut if (energy_cut.first != std::numeric_limits::max()) { TH_Help::Scale(fPrediction_xsec, IH.GetXSecScaleFactor(energy_cut)); } fPrediction_shape = nuis::utility::Clone(fPrediction_xsec, false, "Prediction_shape"); if (fData) { TH_Help::Scale(fPrediction_shape, TH_Help::Integral(fData, "width") / TH_Help::Integral(fPrediction_shape, "width")); } else { IEventProcessor_WARN( "When Finalizing comparison, no Data histogram available."); } if (fIsFluxUnfolded) { // fPrediction_comparison } else if (fIsShapeOnly) { fPrediction_comparison = nuis::utility::Clone(fPrediction_shape, false, "Prediction_comparison"); } else { fPrediction_comparison = nuis::utility::Clone(fPrediction_xsec, false, "Prediction_comparison"); } fComparisonFinalized = true; } void Initialize(fhicl::ParameterSet const &instance_sample_configuration) { fInstanceConfig = instance_sample_configuration; if (fInstanceConfig.has_key("verbosity")) { SetSampleVerbosity(fInstanceConfig.get("verbosity")); } else { SetSampleVerbosity("Reticent"); } ReadGlobalConfigDefaults(); if (fInstanceConfig.has_key("fake_data")) { fData = nuis::utility::GetHistogram( fInstanceConfig.get("fake_data_histogram")); } else if (!fGlobalConfig.get("has_data", true) || !fInstanceConfig.get("has_data", true)) { // Explicitly not expecting data } else { if (!fDataInputDescriptor.length()) { if (!fGlobalConfig.has_key("data_descriptor")) { throw invalid_SimpleDataComparison_initialization() << "[ERROR]: SimpleDataComparison::Initialize for " "IDataComparison: " << std::quoted(Name()) << " failed as no input data was set by a call to " "SimpleDataComparison::SetData and no data_descriptor for " "this SimpleDataComparison could be found in the global " "configuration."; } fDataInputDescriptor = fGlobalConfig.get("data_descriptor"); } fData = nuis::utility::GetHistogram(fDataInputDescriptor); } if (!fPrediction) { if (!fData) { throw invalid_SimpleDataComparison_initialization() << "[ERROR]: SimpleDataComparison::Initialize for " "IDataComparison: " << std::quoted(Name()) << " failed. As `has_data: false` was set in the configuration " "(global: " << (!fGlobalConfig.get("has_data", true)) << ", instance: " << !fInstanceConfig.get("has_data", true) << "), the instance constructor must supply the fPrediction " "binning, and it wasn't."; } fPrediction = nuis::utility::Clone(fData, true, "Prediction"); } if (fCovarianceInputDescriptor.length()) { fCovariance = nuis::utility::GetHistogram(fCovarianceInputDescriptor); } else if (fGlobalConfig.has_key("covariance_descriptor")) { fCovariance = nuis::utility::GetHistogram( fGlobalConfig.get("covariance_descriptor")); } if (fMaskInputDescriptor.length()) { fMask = nuis::utility::GetHistogram(fMaskInputDescriptor); } else if (fGlobalConfig.has_key("mask_descriptor")) { fMask = nuis::utility::GetHistogram( fGlobalConfig.get("mask_descriptor")); } if (fInstanceConfig.has_key("verbosity")) { SetSampleVerbosity(fInstanceConfig.get("verbosity")); } NMaxSample_override = fInstanceConfig.get("nmax", std::numeric_limits::max()); write_directory = fInstanceConfig.get("write_directory", Name()); fIH_id = nuis::input::InputManager::Get().EnsureInputLoaded(fInstanceConfig); } void ProcessSample(size_t nmax = std::numeric_limits::max()) { if (fIH_id == std::numeric_limits::max()) { throw uninitialized_IEventProcessor(); } IInputHandler const &IH = nuis::input::InputManager::Get().GetInputHandler(fIH_id); nmax = std::min(NMaxSample_override, nmax); size_t NEvsToProcess = std::min(nmax, IH.GetNEvents()); double nmax_scaling = double(IH.GetNEvents()) / double(NEvsToProcess); size_t NToShout = NEvsToProcess / 10; IEventProcessor_INFO("Sample " << std::quoted(Name()) << " processing " << NEvsToProcess << " events."); IInputHandler::ev_index_t ev_idx = 0; bool DetermineSignalEvents = !fSignalCache.size(); nuis::utility::Clear(*fPrediction); fComparisonFinalized = false; size_t cache_ctr = 0; while (ev_idx < NEvsToProcess) { if (DetermineSignalEvents) { nuis::event::FullEvent const &fev = IH.GetFullEvent(ev_idx); bool is_sig = IsSigFunc(fev); fSignalCache.push_back(is_sig); if (is_sig) { fProjectionCache.push_back(CompProjFunc(fev)); } if (ProcessExtraFunc) { ProcessExtraFunc(fev, is_sig, IH.GetEventWeight(ev_idx) * nmax_scaling); } } if (NToShout && !(ev_idx % NToShout)) { IEventProcessor_INFO("\tProcessed " << ev_idx << "/" << NEvsToProcess << " events."); } if (fSignalCache[ev_idx]) { FillProjection(fProjectionCache[cache_ctr++], IH.GetEventWeight(ev_idx) * nmax_scaling); } ev_idx++; } IEventProcessor_INFO("\t" << fProjectionCache.size() << "/" << NEvsToProcess << " events passed selection."); } void Write() { if (!fComparisonFinalized) { FinalizeComparison(); } nuis::persistency::WriteToOutputFile( fPrediction_comparison, "Prediction", write_directory); nuis::persistency::WriteToOutputFile( fPrediction_xsec, "Prediction_xsec", write_directory); if (fData) { nuis::persistency::WriteToOutputFile(fData, "Data", write_directory); nuis::persistency::WriteToOutputFile( fPrediction_shape, "Prediction_shape", write_directory); } } double GetGOF() { if (!fComparisonFinalized) { FinalizeComparison(); } if (fData && fPrediction_comparison) { return nuis::utility::GetChi2(fData, fPrediction_comparison); } else return std::numeric_limits::max(); } double GetNDOGuess() { if (fData) { return TH_Help::Nbins(fData); } return 0; } fhicl::ParameterSet GetExampleConfiguration() { fhicl::ParameterSet exps; exps.put("name", Name()); exps.put("input_type", "Generator"); exps.put("file", "Events.root"); exps.put("write_directory", Name()); exps.put("fake_data_histogram", "/path/to/file.root;h_name"); return exps; } }; -typedef SimpleDataComparison<1> SimpleDataComparison_1D; -typedef SimpleDataComparison<2> SimpleDataComparison_2D; - -#endif +typedef SimpleDataComparison<1, double, TH1D> SimpleDataComparison_1D; +typedef SimpleDataComparison<2, double, TH2D> SimpleDataComparison_2D; +typedef SimpleDataComparison<1, float, TH1F> SimpleDataComparison_1F; +typedef SimpleDataComparison<2, float, TH2F> SimpleDataComparison_2F; +typedef SimpleDataComparison<2, double, TH2Poly> SimpleDataComparison_2DPoly; diff --git a/src/samples/SimpleMCStudy.hxx b/src/samples/SimpleMCStudy.hxx new file mode 100644 index 0000000..c8a55d5 --- /dev/null +++ b/src/samples/SimpleMCStudy.hxx @@ -0,0 +1,108 @@ +// Copyright 2018 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 . + *******************************************************************************/ + +#pragma once + +#include "samples/IEventProcessor.hxx" + +#include "event/FullEvent.hxx" + +#include "input/InputManager.hxx" + +#include + +class SimpleMCStudy : public IEventProcessor { +protected: + nuis::input::InputManager::Input_id_t fIH_id; + std::string write_directory; + size_t NMaxSample_override; + + std::function + ProcessEventFunction; + +public: + SimpleMCStudy() { + fIH_id = std::numeric_limits::max(); + write_directory = ""; + NMaxSample_override = std::numeric_limits::max(); + + ProcessEventFunction = std::function(); + } + + fhicl::ParameterSet fGlobalConfig; + fhicl::ParameterSet fInstanceConfig; + + void ReadGlobalConfigDefaults() { + fGlobalConfig = nuis::config::GetDocument().get( + std::string("global.sample_configuration.") + Name(), + fhicl::ParameterSet()); + } + + void Initialize(fhicl::ParameterSet const &instance_sample_configuration) { + + fInstanceConfig = instance_sample_configuration; + + if (fInstanceConfig.has_key("verbosity")) { + SetSampleVerbosity(fInstanceConfig.get("verbosity")); + } else { + SetSampleVerbosity("Reticent"); + } + + ReadGlobalConfigDefaults(); + + NMaxSample_override = + fInstanceConfig.get("nmax", std::numeric_limits::max()); + + write_directory = + fInstanceConfig.get("write_directory", Name()); + + fIH_id = + nuis::input::InputManager::Get().EnsureInputLoaded(fInstanceConfig); + } + + void ProcessSample(size_t nmax = std::numeric_limits::max()) { + if (fIH_id == + std::numeric_limits::max()) { + throw uninitialized_IEventProcessor(); + } + IInputHandler const &IH = + nuis::input::InputManager::Get().GetInputHandler(fIH_id); + + nmax = std::min(NMaxSample_override, nmax); + + size_t NEvsToProcess = std::min(nmax, IH.GetNEvents()); + + double nmax_scaling = double(IH.GetNEvents()) / double(NEvsToProcess); + + size_t NToShout = NEvsToProcess / 10; + IEventProcessor_INFO("Sample " << std::quoted(Name()) << " processing " + << NEvsToProcess << " events."); + + IInputHandler::ev_index_t ev_idx = 0; + + while (ev_idx < NEvsToProcess) { + nuis::event::FullEvent const &fev = IH.GetFullEvent(ev_idx); + ProcessEventFunction(fev, IH.GetEventWeight(ev_idx) * nmax_scaling); + ev_idx++; + } + + IEventProcessor_INFO("Sample " << std::quoted(Name()) << " processed " + << NEvsToProcess << " events."); + } +};