diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b1afae4198..6256045654f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,9 @@ cmake_minimum_required( VERSION 3.11 FATAL_ERROR ) set(CMAKE_CXX_STANDARD 17) -project(CMSCombine VERSION 0.0.1) +project(HiggsAnalysisCombinedLimit VERSION 0.0.1) option( MODIFY_ROOTMAP "Modify generated Rootmap to take out classes already bundled in StatAnalysis" FALSE ) +option( INSTALL_PYTHON "Install the Python library and scripts" TRUE ) # Can build with CMake after e.g. setting up StatAnalysis release like this: # export ATLAS_LOCAL_ROOT_BASE=/cvmfs/atlas.cern.ch/repo/ATLASLocalRootBase @@ -25,7 +26,7 @@ include_directories(${ROOT_INCLUDE_DIRS}) include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR}) add_definitions(${ROOT_CXX_FLAGS}) -set(LIBNAME CMSCombine) +set(LIBNAME HiggsAnalysisCombinedLimit) file(GLOB HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} interface/*.h*) file(GLOB SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} src/*.c*) @@ -103,9 +104,6 @@ install(FILES ${CMAKE_CURRENT_BINARY_DIR}/HiggsAnalysis/CombinedLimit/src/classe # Install the "combine" executable in the bin directory. install(TARGETS combine DESTINATION bin) -# Install the scripts like "text2workspace" to the bin directory. -install(DIRECTORY scripts/ DESTINATION bin) - # This block is commented out for now, while using the less sophisticated location below # Check if the Python library installation directory is outside the install # prefix. If it is, we error out because CMake should not install files outside @@ -123,16 +121,20 @@ install(DIRECTORY scripts/ DESTINATION bin) ## The the Python library installation directory relative to the install prefix. #file(RELATIVE_PATH Python_SITELIB_IN_PREFIX ${CMAKE_INSTALL_PREFIX} ${Python_SITELIB}) -set(Python_SITELIB_IN_PREFIX "python") +if(INSTALL_PYTHON) + # Install the scripts like "text2workspace" to the bin directory. + install(DIRECTORY scripts/ DESTINATION bin) + set(Python_SITELIB_IN_PREFIX "python") -message (STATUS "Using Python install location:" ${Python_SITELIB_IN_PREFIX}) -# The python package will be installed in such a way that the original -# CMSSW-style directory structure is kept, for maximal compatibility. -install(DIRECTORY python/ DESTINATION ${Python_SITELIB_IN_PREFIX}/HiggsAnalysis/CombinedLimit) + message (STATUS "Using Python install location:" ${Python_SITELIB_IN_PREFIX}) + # The python package will be installed in such a way that the original + # CMSSW-style directory structure is kept, for maximal compatibility. + install(DIRECTORY python/ DESTINATION ${Python_SITELIB_IN_PREFIX}/HiggsAnalysis/CombinedLimit) -# Create empty __init__.py files in the Python package subdirectories such that -# the Python imports work. -file(TOUCH ${empty_init_py}) -INSTALL(FILES ${empty_init_py} DESTINATION ${Python_SITELIB_IN_PREFIX}/HiggsAnalysis) -INSTALL(FILES ${empty_init_py} DESTINATION ${Python_SITELIB_IN_PREFIX}/HiggsAnalysis/CombinedLimit) + # Create empty __init__.py files in the Python package subdirectories such that + # the Python imports work. + file(TOUCH ${empty_init_py}) + INSTALL(FILES ${empty_init_py} DESTINATION ${Python_SITELIB_IN_PREFIX}/HiggsAnalysis) + INSTALL(FILES ${empty_init_py} DESTINATION ${Python_SITELIB_IN_PREFIX}/HiggsAnalysis/CombinedLimit) +endif() diff --git a/demo_lcg.sh b/demo_lcg.sh new file mode 100755 index 00000000000..11c3d99db93 --- /dev/null +++ b/demo_lcg.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +# Need to run with "./demo_lcg.sh" on lxplus9 + +# Setup LGC release and paths +source ./env_lcg.sh + +# For the python part, it is recommended to install it as a python package +# into your virtual environment (see setup.py). Do this AFTER the LCG +# environment setup to use a consistent Python version. + +mkdir -p .python/HiggsAnalysis +ln -s $PWD/python $PWD/.python/HiggsAnalysis/CombinedLimit +touch $PWD/.python/HiggsAnalysis/__init__.py +touch $PWD/.python/HiggsAnalysis/CombinedLimit/__init__.py + +python3 -m venv virtualenv +source virtualenv/bin/activate + +python3 -m pip install -e . + +# Now, build the C++ part of combine +mkdir build +cd build +cmake -DCMAKE_INSTALL_PREFIX=../install -DINSTALL_PYTHON=FALSE .. +make install -j4 +cd .. + +# Run the following combine "hello world" example +text2workspace.py data/tutorials/CAT23001/datacard-3-parametric-analysis.txt +combine -M MultiDimFit -m 125.38 data/tutorials/CAT23001/datacard-3-parametric-analysis.root diff --git a/env_lcg.sh b/env_lcg.sh index 039dd93e7f0..335ccacdda8 100644 --- a/env_lcg.sh +++ b/env_lcg.sh @@ -1,4 +1,8 @@ -. /cvmfs/sft.cern.ch/lcg/views/LCG_102/x86_64-centos7-gcc11-opt/setup.sh -export PATH=${PATH}:${PWD}/build/bin -export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${PWD}/build/lib -export PYTHONPATH=${PYTHONPATH}:${PWD}/build/lib/python +LCG_RELEASE=dev4 # or dev3 for ROOT master (dev4 is the latest ROOT stable branch) +LCG_PATH=/cvmfs/sft.cern.ch/lcg/views/$LCG_RELEASE/latest/x86_64-el9-gcc13-opt + +source $LCG_PATH/setup.sh +source $LCG_PATH/bin/thisroot.sh + +export PATH=$PWD/install/bin:$PATH +export LD_LIBRARY_PATH=$PWD/install/lib:$LD_LIBRARY_PATH diff --git a/env_standalone_root_master.sh b/env_standalone_root_master.sh deleted file mode 100644 index da071e918dd..00000000000 --- a/env_standalone_root_master.sh +++ /dev/null @@ -1,10 +0,0 @@ - . /cvmfs/cms.cern.ch/slc7_amd64_gcc700/external/gcc/7.0.0-omkpbe2/etc/profile.d/init.sh - . /afs/cern.ch/work/a/agilbert/public/root_master/bin/thisroot.sh - . /cvmfs/cms.cern.ch/slc7_amd64_gcc700/external/gsl/2.2.1-omkpbe2/etc/profile.d/init.sh - . /cvmfs/cms.cern.ch/slc7_amd64_gcc700/external/tbb/2018_U1-omkpbe2/etc/profile.d/init.sh - . /cvmfs/cms.cern.ch/slc7_amd64_gcc700/cms/vdt/0.4.0-gnimlf/etc/profile.d/init.sh - . /cvmfs/cms.cern.ch/slc7_amd64_gcc700/external/boost/1.63.0-gnimlf/etc/profile.d/init.sh - . /cvmfs/cms.cern.ch/slc7_amd64_gcc700/external/pcre/8.37-omkpbe2/etc/profile.d/init.sh - export PATH=${PATH}:${PWD}/exe:${PWD}/scripts - export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${PWD}/lib - export PYTHONPATH=${PYTHONPATH}:${PWD}/lib/python:${PWD}/lib diff --git a/setup.py b/setup.py new file mode 100644 index 00000000000..e9c75a13c29 --- /dev/null +++ b/setup.py @@ -0,0 +1,51 @@ +import setuptools + +# This setup script lets you install the Python part of combine like a standard +# Python package. The big advantage of it is you can make an in-place +# installation into your virtual environment, which means you can change the +# Python files in this repo, and the changes will be effective immediately +# without any recompilation or reinstallation. + +# Before installing the package, run in this repo: +# mkdir -p .python/HiggsAnalysis +# ln -s $PWD/python $PWD/.python/HiggsAnalysis/CombinedLimit +# touch $PWD/.python/HiggsAnalysis/__init__.py +# touch $PWD/.python/HiggsAnalysis/CombinedLimit/__init__.py + +# To do an in-place installation, it's best to create and activate a virtual +# environment, if you don't have done so already: +# python3 -m venv +# source /bin/activate + +# Finally, the in-place installation (for regular installation, drop the "-e"): +# python3 -m pip install -e . + +with open("README.md", "r", encoding="utf-8") as fh: + long_description = fh.read() + +scripts = [ + "combineCards.py", + "plotGof.py", + "pruneUncerts.py", + "combineTool.py", + "plotImpacts.py", + "text2workspace.py", + "commentUncerts.py", + "plot1DScan.py", + "plotLimitGrid.py", + "plotBSMxsBRLimit.py", + "plotLimits.py", +] + +setuptools.setup( + name="HiggsAnalysisCombinedLimit", + version="1.0", + description="CMS Combine", + author="The CMS Collaboration", + long_description=long_description, + long_description_content_type="text/markdown", + package_dir={"": ".python"}, + packages=setuptools.find_packages(where=".python"), + python_requires=">=3.8", + scripts=["scripts/" + filename for filename in scripts], +) diff --git a/test/compile-standalone.sh b/test/compile-standalone.sh deleted file mode 100755 index 79bdd82f39d..00000000000 --- a/test/compile-standalone.sh +++ /dev/null @@ -1,82 +0,0 @@ -#!/bin/bash - -## This script allows to compile the program as standalone, taking ROOT and BOOST from CERN AFS -## It also takes python 2.6 from /usr/bin/python2.6 in case your default python is 2.4 like in SLC5 -## It is meant only for DEBUGGING and TESTING, and it is NOT supported. -## -## Usage: -## - if necessary, fix the paths to BOOST, GCC, ROOT -## - go under HiggsAnalysis/CombinedLimit, and -## - if necessary, clean up a previous build with -## ./test/compile-standalone.sh clean -## - if necessary, compile the program -## ./test/compile-standalone.sh make -## - setup your environment -## eval $(./test/compile-standalone.sh env) -## - now you can run the program - -if [[ "$1" == "" ]]; then echo "$0 (clean | make |env)"; exit 1; fi; - -BASEDIR="$( cd "$( dirname "$0" )"/../../.. && pwd )" -BOOST=/afs/cern.ch/cms/slc5_amd64_gcc434/external/boost/1.42.0-cms -MYGCC=/afs/cern.ch/sw/lcg/external/gcc/4.3.2/x86_64-slc5/setup.sh -MYROOT=/afs/cern.ch/sw/lcg/app/releases/ROOT/5.28.00/x86_64-slc5-gcc43-opt/root/bin/thisroot.sh -cd $BASEDIR/HiggsAnalysis/CombinedLimit; - -if [[ "$1" == "env" ]]; then - echo "source $MYGCC '' ;"; - echo "source $MYROOT;"; - echo "export LD_LIBRARY_PATH=\"\${LD_LIBRARY_PATH}:${BOOST}/lib\";"; - echo "export PATH=\"${BASEDIR}/HiggsAnalysis/CombinedLimit/tmp/bin:${PATH}\";"; - echo "export PYTHONPATH=\"${BASEDIR}/HiggsAnalysis/CombinedLimit/tmp/python:${PYTHONPATH}\";"; -elif [[ "$1" == "clean" ]]; then - test -f src/tmp_LinkDef.cc && rm src/tmp_LinkDef.cc - test -f src/tmp_LinkDef.h && rm src/tmp_LinkDef.h - rm -r src/*.o tmp/ 2> /dev/null || /bin/true; -elif [[ "$1" == "make" ]]; then - echo ">>> Setup " - source $MYGCC '' - source $MYROOT - INC="-I${ROOTSYS}/include -I${BASEDIR} -I${BOOST}/include" - - echo ">>> Dictionaries " - test -f src/tmp_LinkDef.cc && rm src/tmp_LinkDef.cc - test -f src/tmp_LinkDef.h && rm src/tmp_LinkDef.h - echo rootcint -f src/tmp_LinkDef.cc -c -p ${INC} -fPIC src/LinkDef.h && \ - rootcint -f src/tmp_LinkDef.cc -c -p ${INC} -fPIC src/LinkDef.h || exit 1 - perl -i -npe 'print qq{#include "LinkDef.h"\n} if 1 .. 1' src/tmp_LinkDef.cc - - echo ">>> Compile " - CXXFLAGS="$(root-config --cflags) -O2 -I${BASEDIR} -I${BOOST}/include -fPIC ${CXXFLAGS}" - CXXFLAGS=" -g ${CXXFLAGS}" - for f in src/*.cc; do - test -f ${f/.cc/.o} && rm ${f/.cc/.o} - echo gcc ${CXXFLAGS} -c $f -o ${f/.cc/.o} && \ - gcc ${CXXFLAGS} -c $f -o ${f/.cc/.o} ; - done - test -f src/tmp_LinkDef.cc && rm src/tmp_LinkDef.cc - test -f src/tmp_LinkDef.h && rm src/tmp_LinkDef.h - - echo ">>> Link " - mkdir -p tmp/bin - LDFLAGS="-L${BOOST}/lib -lboost_program_options -lboost_system -lboost_filesystem ${LDFLAGS}" - LDFLAGS="$(root-config --ldflags --libs) -lRooFitCore -lRooStats -lRooFit -lFoam -lMinuit ${LDFLAGS}" - LDFLAGS="-lstdc++ -fPIC ${LDFLAGS}" - echo gcc ${CXXFLAGS} src/*.o bin/combine.cpp ${LDFLAGS} -o tmp/bin/combine && - gcc ${CXXFLAGS} src/*.o bin/combine.cpp ${LDFLAGS} -o tmp/bin/combine || exit 3; - - echo ">>> Python" - test -d tmp/bin || mkdir -p tmp/bin; - test -d tmp/python/HiggsAnalysis || mkdir -p tmp/python/HiggsAnalysis; - ln -sd $BASEDIR/HiggsAnalysis/CombinedLimit/python tmp/python/HiggsAnalysis/CombinedLimit - touch tmp/python/HiggsAnalysis/__init__.py - touch tmp/python/HiggsAnalysis/CombinedLimit/__init__.py - - # hack to get python 2.6 - if python -V 2>&1 | grep -q "Python 2.4"; then - cp -s /usr/bin/python2.6 ${BASEDIR}/HiggsAnalysis/CombinedLimit/tmp/bin/python - fi; -else - echo "$0 (clean | make |env)"; - exit 1; -fi;