Skip to content

Commit

Permalink
Merge pull request #625 from ajgilbert/ch-april
Browse files Browse the repository at this point in the history
Planned developments for CombineHarvester (April)
  • Loading branch information
ajgilbert committed Apr 10, 2015
2 parents a7e0452 + 995b5fc commit 64e1075
Show file tree
Hide file tree
Showing 28 changed files with 729 additions and 169 deletions.
2 changes: 1 addition & 1 deletion CombineHarvester/CombinePdfs/Rules.mk
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
SUBDIRS :=
LIB_DEPS := CombineTools
LIB_EXTRA := -lHiggsAnalysisCombinedLimit
LIB_EXTRA := -L$(CMSSW_BASE)/lib/$(SCRAM_ARCH) -lHiggsAnalysisCombinedLimit
DICTIONARY :=
2 changes: 1 addition & 1 deletion CombineHarvester/CombinePdfs/src/MorphFunctions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ void BuildRooMorphing(RooWorkspace& ws, CombineHarvester& cb,
CombineHarvester cb_bp =
std::move(cb.cp().bin({bin}).process({process}));

vector<string> masses_all = Set2Vec(cb_bp.GenerateSetFromProcs<string>(
vector<string> masses_all = Set2Vec(cb_bp.SetFromProcs(
std::mem_fn(&ch::Process::mass)));

std::sort(masses_all.begin(), masses_all.end(),
Expand Down
9 changes: 2 additions & 7 deletions CombineHarvester/CombinePdfs/test/ParametricMSSM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,7 @@ int main() {
std::cout << " done\n";

// cb.era({"8TeV"}).bin_id({8});
set<string> lm_bins =
cb.GenerateSetFromObs<string>(mem_fn(&ch::Observation::bin));
set<string> lm_bins = cb.SetFromObs(mem_fn(&ch::Observation::bin));

if (create_asimov) {
for (auto const& b : lm_bins) {
Expand Down Expand Up @@ -140,11 +139,7 @@ int main() {
in->set_bin(in->bin() + "_hm");
});

set<string> hm_bins =
cb_hm.GenerateSetFromObs<string>(mem_fn(&ch::Observation::bin));



set<string> hm_bins = cb_hm.SetFromObs(mem_fn(&ch::Observation::bin));

cb.cp().bin_id({8}).VariableRebin(
{0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120,
Expand Down
11 changes: 11 additions & 0 deletions CombineHarvester/CombineTools/Rules.mk
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
SUBDIRS :=
LIB_DEPS :=
LIB_EXTRA := -lboost_python -L$(shell scramv1 tool tag python LIBDIR) -l$(shell scramv1 tool tag python LIB) -lPyROOT

$(d)/interface/GitVersion.h: $(TOP)/../.git/logs/HEAD
@echo -e "Updating $@"
@echo -e "namespace ch { inline std::string GitVersion() { return \""$(shell git describe --dirty)"\"; } }\n" > $@

clean_$(d)/interface/GitVersion.h :
rm -f $(subst clean_,,$@)

clean_$(d) : clean_$(d)/interface/GitVersion.h

dir_$(d) : | $(d)/interface/GitVersion.h
1 change: 1 addition & 0 deletions CombineHarvester/CombineTools/interface/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
GitVersion.h
80 changes: 80 additions & 0 deletions CombineHarvester/CombineTools/interface/CardWriter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#ifndef CombineTools_CardWriter_h
#define CombineTools_CardWriter_h
#include <string>
#include <map>
#include <vector>
#include <set>
#include "CombineTools/interface/CombineHarvester.h"
#include "CombineTools/interface/Object.h"

namespace ch {

/**
* Automates the writing of datacards into directory structures
*
* A CardWriter is constructed with two strings which give patterns for where
* the datacard text and ROOT files should be located and how they should be
* named. These patterns can contain placeholders for the object metadata,
* e.g.:
*
* ch::CardWriter writer(
* "$TAG/$MASS/$ANALYSIS_$CHANNEL_$BINID_$ERA.txt",
* "$TAG/common/$ANALYSIS_$CHANNEL.input_$ERA.root");
*
* All of the standard metadata placeholders are supported. Then, assuming a
* CombineHarvester instance `cb` has already been configured, the cards are
* written with:
*
* writer.WriteCards("LIMITS/cmb", cb);
*
* The CardWriter will determine the sets of root files and datacards to
* create given the metadata of the objects in `cb`. The first argument of
* `WriteCards` is substituted into the `$TAG` placeholder. In this way
* multiple calls to \ref WriteCards can produce output in different folders.
*
* By default CardWriter will create any directories that are needed, but this
* behaviour can be switched off with the `CreateDirectories` method. Also
* note that any existing files with the same name will be over-written.
*
* \note The $MASS variable is treated differently than the others when
* constructing the list of output files. It is anticipated that a mass value
* of `*` should not give rise to actual files containing the `*` character,
* but rather implies an Object that is valid for any mass-point. It is
* commonly used to denote background processes that do not depend on the
* signal mass hypothesis. Therefore this class ignores objects with a mass
* value of `*` when determining which files to create, and when creating the
* files treats this object as matching any mass value. It is possible to
* alter or remove this behaviour by supplying a new list of wildcard values
* with the \ref SetWildcardMasses method.
*/
class CardWriter {
public:
/// Must be constructed with text and ROOT file patterns
CardWriter(std::string const& text_pattern, std::string const& root_pattern);
/// Write datacards according to patterns, substituting `$TAG` for `tag`
void WriteCards(std::string const& tag, ch::CombineHarvester& cmb) const;
/// Set >= 1 for verbose output, otherwise silent
CardWriter& SetVerbosity(unsigned v);
/// Control whether directories can be created if missing
CardWriter& CreateDirectories(bool flag);
/// Redefine the mass values that should be treated as wildcards
CardWriter& SetWildcardMasses(std::vector<std::string> const& masses);

private:
typedef std::map<std::string, std::set<std::string>> PatternMap;
std::string text_pattern_;
std::string root_pattern_;
mutable std::string tag_;
std::vector<std::string> wildcard_masses_;
unsigned v_;
bool create_dirs_;

std::string Compile(std::string pattern, ch::Object const* obj,
bool skip_mass = false) const;
PatternMap BuildMap(std::string const& pattern,
ch::CombineHarvester& cmb) const;
void MakeDirs(PatternMap const& map) const;
};
}

#endif
105 changes: 68 additions & 37 deletions CombineHarvester/CombineTools/interface/CombineHarvester.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,18 +164,6 @@ class CombineHarvester {
*/
/**@{*/
// Set generation
template <typename T>
std::set<T> GenerateSetFromProcs(
std::function<T(ch::Process const*)> func);

template<typename T>
std::set<T> GenerateSetFromObs(
std::function<T(ch::Observation const*)> func);

template <typename T>
std::set<T> GenerateSetFromSysts(
std::function<T(ch::Systematic const*)> func);

std::set<std::string> bin_set();
std::set<int> bin_id_set();
std::set<std::string> process_set();
Expand All @@ -185,18 +173,55 @@ class CombineHarvester {
std::set<std::string> mass_set();
std::set<std::string> syst_name_set();
std::set<std::string> syst_type_set();
/**@}*/

// An alternative way to do the set generation
// template<typename T>
// T unwind(T const& x) { return x; }
/**
* Fill an std::set with the return values from an arbitrary function
*
* This method will loop through all ch::Observation, ch::Process and
* ch::Systematic entries and call the user-supplied function `func`. The
* return value is then inserted into the set.
*
* @tparam T A function (or other callable) that must have a single
* `ch::Object const*` argument.
* @tparam R The return type of the function, which is deduced by using
* `std::result_of`, then `std::decay`. The latter is needed to handle
* functions that return by reference, i.e. turning a type R& into a type R.
*/
template <typename T,
typename R = typename std::decay<
typename std::result_of<T(Object const*)>::type>::type>
std::set<R> SetFromAll(T func);

/**
* Fill an std::set using only the Observation entries
*
* \sa SetFromAll
*/
template <typename T,
typename R = typename std::decay<
typename std::result_of<T(Observation const*)>::type>::type>
std::set<R> SetFromObs(T func);

/**
* Fill an std::set using only the Process entries
*
* \sa SetFromAll
*/
template <typename T,
typename R = typename std::decay<
typename std::result_of<T(Process const*)>::type>::type>
std::set<R> SetFromProcs(T func);

// template<typename T>
// auto SetFromProcs(T func) -> std::set<decltype(unwind(func(nullptr)))> {
// std::set<decltype(unwind(func(nullptr)))> ret;
// for (auto const& item : procs_) ret.insert(func(item.get()));
// return ret;
// };
/**
* Fill an std::set using only the Systematic entries
*
* \sa SetFromAll
*/
template <typename T,
typename R = typename std::decay<
typename std::result_of<T(Systematic const*)>::type>::type>
std::set<R> SetFromSysts(T func);
/**@}*/

/**
* \name Modification
Expand Down Expand Up @@ -446,29 +471,35 @@ void FillHistMappings(std::vector<HistMapping> & mappings);
// ---------------------------------------------------------------
// Template method implementation
// ---------------------------------------------------------------
template<typename T>
std::set<T> CombineHarvester::GenerateSetFromProcs(
std::function<T (ch::Process const*)> func) {
std::set<T> ret;
template <typename T, typename R>
std::set<R> CombineHarvester::SetFromAll(T func) {
std::set<R> ret;
for (auto const& item : obs_) ret.insert(func(item.get()));
for (auto const& item : procs_) ret.insert(func(item.get()));
for (auto const& item : systs_) ret.insert(func(item.get()));
return ret;
}
};

template<typename T>
std::set<T> CombineHarvester::GenerateSetFromObs(
std::function<T (ch::Observation const*)> func) {
std::set<T> ret;
template <typename T, typename R>
std::set<R> CombineHarvester::SetFromObs(T func) {
std::set<R> ret;
for (auto const& item : obs_) ret.insert(func(item.get()));
return ret;
}
};

template <typename T, typename R>
std::set<R> CombineHarvester::SetFromProcs(T func) {
std::set<R> ret;
for (auto const& item : procs_) ret.insert(func(item.get()));
return ret;
};

template<typename T>
std::set<T> CombineHarvester::GenerateSetFromSysts(
std::function<T (ch::Systematic const*)> func) {
std::set<T> ret;
template <typename T, typename R>
std::set<R> CombineHarvester::SetFromSysts(T func) {
std::set<R> ret;
for (auto const& item : systs_) ret.insert(func(item.get()));
return ret;
}
};

template<typename Function>
void CombineHarvester::ForEachObj(Function func) {
Expand Down
60 changes: 59 additions & 1 deletion CombineHarvester/CombineTools/interface/Logging.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@
#define CombineTools_Logging_h
#include <string>
#include <iostream>
#include <chrono>

namespace ch {

#define FNERROR(x) FnError(x, __FILE__, __LINE__, __PRETTY_FUNCTION__)

#define LOGLINE(x, y) LogLine(x, __func__, y)

#define FNLOG(x) x << "[" << __func__ << "]"
#define FNLOGC(x, y) if (y) x << "[" << __func__ << "] "
/**
* \brief Writes a logging message to a given ostream
* \details Should be used with the macro LOGLINE which will call this function
Expand All @@ -33,7 +36,6 @@ void LogLine(std::ostream& stream, std::string const& func,
*/
std::string FnError(std::string const& message, std::string const& file,
unsigned line, std::string const& fn);
}

/**
* \brief Extracts the fully-qualified function name from a complete function
Expand All @@ -49,4 +51,60 @@ std::string FnError(std::string const& message, std::string const& file,
*/
std::string GetQualififedName(std::string const& str);

/**
* Conveniently initialise a ch::FnTimer instance
*
* This macro should be placed at the start of a function, e.g.:
*
* void MyFunction() {
* LAUNCH_FUNCTION_TIMER(__timer__, __token__)
* }
*
* The arguments are the names of two objects (a ch::FnTimer and a
* ch::FnTimer::Token) that will be created by this macro. Note that the
* ch::FnTimer will be assigned the current function name automatically.
*/
#define LAUNCH_FUNCTION_TIMER(x, y) \
static FnTimer x(ch::GetQualififedName(__PRETTY_FUNCTION__)); \
auto y = x.Inc();

/**
* Determine the total amount of time spent in a function
*
* An FnTimer instance should typically be declared as a static variable at
* the beginning of a function, follwed by a call to the Inc() method, which
* will increment the counter. The Inc() method also returns an FnTimer::Token
* object that records the time at which it is constructed and then destroyed,
* the latter occurring automatically at the end of the function. At the end
* of the program the FnTimer destructor will write a message to the screen
* summarising the number of calls and the time information.
*
* \note A simple way of using this class is via the LAUNCH_FUNCTION_TIMER(x,y)
* macro
*/
class FnTimer {
public:
class Token {
public:
explicit Token(FnTimer *src);
~Token();
private:
FnTimer *src_;
};

explicit FnTimer(std::string name);
~FnTimer();
Token Inc();
void StartTimer();
void StopTimer();

private:
std::string name_;
unsigned calls_;
std::chrono::time_point<std::chrono::system_clock> start_;
std::chrono::time_point<std::chrono::system_clock> end_;
double elapsed_;
};
}

#endif
3 changes: 3 additions & 0 deletions CombineHarvester/CombineTools/interface/TFileIO.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ T OpenFromTFile(TFile* file, std::string const& path);
// ------------------------------------------------------------------
template <class T>
void ch::WriteToTFile(T const* ptr, TFile* file, std::string const& path) {
#ifdef TIME_FUNCTIONS
LAUNCH_FUNCTION_TIMER(__timer__, __token__)
#endif
file->cd();
std::vector<std::string> as_vec;
boost::split(as_vec, path, boost::is_any_of("/"));
Expand Down
Loading

0 comments on commit 64e1075

Please sign in to comment.