ATLAS Offline Software
Loading...
Searching...
No Matches
CalibrationDataGlobalEigenVariations Class Reference

#include <CalibrationDataEigenVariations.h>

Inheritance diagram for CalibrationDataGlobalEigenVariations:
Collaboration diagram for CalibrationDataGlobalEigenVariations:

Public Types

typedef std::set< size_t > IndexSet
typedef std::set< IndexSetIndexSuperSet

Public Member Functions

 CalibrationDataGlobalEigenVariations (const std::string &cdipath, const std::string &tagger, const std::string &wp, const std::string &jetcollection, const std::vector< std::string > &flavours, CalibrationDataHistogramContainer *cnt, bool excludeRecommendedUncertaintySet=false)
 ~CalibrationDataGlobalEigenVariations ()
TMatrixDSym getEigenCovarianceMatrix ()
 also provide (some) access to the underlying information: covariance matrix corresponding to eigenvector variations
void initialize (double min_variance=1.0E-6)
 carry out the eigenvector computations.
TMatrixD getJacobianReductionMatrix (TMatrixDSym &cov)
void excludeNamedUncertainty (const std::string &name, const std::string &flavour)
std::vector< std::string > listNamedVariations (const std::string &flavour) const
unsigned int getNamedVariationIndex (const std::string &name, const std::string &flavour) const
bool getNamedVariation (const std::string &flavour, const std::string &name, TH1 *&up, TH1 *&down)
bool getNamedVariation (unsigned int nameIndex, const std::string &flavour, TH1 *&up, TH1 *&down)
bool getEigenvectorVariation (const std::string &flavour, unsigned int variation, TH1 *&up, TH1 *&down)
unsigned int getNumberOfEigenVariations (const std::string &flavour)
bool isExtrapolationVariation (unsigned int nameIndex, const std::string &flavour) const
void mergeVariationsFrom (const size_t &index, std::string &flav)
void mergeVariations (const IndexSet &set, std::string &flav)
void mergeVariations (const IndexSuperSet &set, std::string &flav)
void removeVariations (const IndexSet &set, std::string &flav)
void removeVariations (const IndexSuperSet &set, std::string &flav)
void excludeNamedUncertainty (const std::string &name, CalibrationDataContainer *cnt)
 exclude the source of uncertainty indicated by name from eigenvector calculations
void removeVariations (const IndexSet &set)
 remove all variations in the given set
void removeVariations (const IndexSuperSet &set)
 remove all variations in any of the given sets
void mergeVariationsFrom (const size_t &index)
 merge all variations starting from the given index
void mergeVariations (const IndexSet &set)
 merge all variations in the given set
void mergeVariations (const IndexSuperSet &set)
 merge all variations in any of the given sets
unsigned int getNumberOfNamedVariations () const
 retrieve the number of named variations
std::vector< std::string > listNamedVariations () const
 list the named variations
unsigned int getNamedVariationIndex (const std::string &name) const
 retrieve the integer index corresponding to the named variation.
unsigned int getNumberOfEigenVariations ()
 retrieve the number of eigenvector variations
bool getEigenvectorVariation (unsigned int variation, TH1 *&up, TH1 *&down)
 obtain the "up" and "down" variations for the given eigenvector number.
bool getNamedVariation (const std::string &name, TH1 *&up, TH1 *&down)
 obtain the "up" and "down" variations for the named uncertainty.
bool getNamedVariation (unsigned int nameIndex, TH1 *&up, TH1 *&down)
 obtain the "up" and "down" variations for the source uncertainty pointed to by the given index (which is assumed to correspond to the value retrieved using getNamedVariationIndex()).
bool isExtrapolationVariation (unsigned int nameIndex) const
 flag whether the given index corresponds to an extrapolation variation
TMatrixDSym getEigenCovarianceMatrixFromVariations ()
 covariance matrix corresponding to eigenvector variations constructed from the eigen-variation
TMatrixD getJacobianReductionMatrix ()
 matrix to remove unecessary rows and columns from covariance
bool EigenVectorRecomposition (const std::string &label, std::map< std::string, std::map< std::string, float > > &coefficientMap)
 Eigenvector recomposition method.
void setVerbose (bool)

Protected Attributes

bool m_initialized
 flag whether the initialization has been carried out
bool m_validate
std::map< std::string, unsigned int > m_namedIndices
 named variations
std::vector< std::pair< TH1 *, TH1 * > > m_named
int m_namedExtrapolation
 named variation index for the special case of extrapolation uncertainties
std::vector< std::pair< TH1 *, TH1 * > > m_eigen
 eigenvector variations
bool m_statVariations
 indicate whether statistical uncertainties are stored as variations
std::string m_cdipath
 @ data members needed for eigenvector method
std::string m_taggername
std::string m_wp
std::string m_jetauthor
double m_totalvariance
double m_capturedvariance
bool m_verbose

Private Attributes

int m_blockmatrixsize
std::map< std::string, Analysis::CalibrationDataHistogramContainer * > m_histcontainers
std::set< std::string > m_all_shared_systematics
std::set< std::string > m_only_shared_systematics
std::map< std::string, std::vector< int > > m_flavour_combinations
std::map< std::string, std::map< std::string, unsigned int > > m_flav_namedIndices
std::map< std::string, std::vector< std::pair< TH1 *, TH1 * > > > m_flav_named
std::map< std::string, int > m_flav_namedExtrapolation
std::map< std::string, std::vector< std::pair< TH1 *, TH1 * > > > m_flav_eigen
std::vector< std::string > m_flavours
CalibrationDataHistogramContainerm_cnt
 container object containing the basic information

Detailed Description

Definition at line 145 of file CalibrationDataEigenVariations.h.

Member Typedef Documentation

◆ IndexSet

typedef std::set<size_t> Analysis::CalibrationDataEigenVariations::IndexSet
inherited

Definition at line 29 of file CalibrationDataEigenVariations.h.

◆ IndexSuperSet

Constructor & Destructor Documentation

◆ CalibrationDataGlobalEigenVariations()

CalibrationDataGlobalEigenVariations::CalibrationDataGlobalEigenVariations ( const std::string & cdipath,
const std::string & tagger,
const std::string & wp,
const std::string & jetcollection,
const std::vector< std::string > & flavours,
CalibrationDataHistogramContainer * cnt,
bool excludeRecommendedUncertaintySet = false )

Definition at line 1290 of file CalibrationDataEigenVariations.cxx.

1290 :
1291CalibrationDataEigenVariations(cdipath, tagger, wp, jetcollection, cnt, excludeRecommendedUncertaintySet, false), m_flav_eigen(), m_flavours(flavours)
1292//m_blockmatrixsize(1200)
1293{
1294 m_blockmatrixsize = 0; // <------- This needs to be computed based off of the dimensions of the result vectors (currently 4x1x5 for continuous WP, 1x300x1 for fixed cut WP, circa 2022)
1295 m_initialized = false;
1297 m_statVariations = false;
1298 // We want to retrieve all the containers that belong in the tagger/jetcollection/wp group
1299 // These are then stored, with all uncertainties extracted and stored as well, for later use in EV decomposition
1300
1301 // For now we will open up the CDI file from within the constructor, to get at the data we need
1302 TString fileName(cdipath);
1303 TFile* f = TFile::Open(fileName.Data(), "READ");
1304 f->cd();
1305
1306 // This loop extracts all the "flavour containers", i.e. all CalibrationDataHistogramContainers pertaining to the same path, but with different flavours
1307 // It also puts all the uncertainties for all containers into a set, which we can then later loop over, to construct the total covariance matrix
1308 for (const auto& flavour : m_flavours){
1309 std::string dir = m_taggername + "/" + m_jetauthor + "/" + m_wp + "/" + flavour + "/" + "default_SF" ;
1310 TString contName(dir);
1311 Analysis::CalibrationDataHistogramContainer* c;
1312 f->GetObject(contName.Data(), c);
1313 if (c) {
1314 if (m_verbose) std::cout << "Found " << contName.Data() << std::endl;
1315 m_histcontainers.insert({flavour, c}); // Build the mapping between flavour and the corresponding "flavour container", i.e. the CalibrationDataHistogramContainer
1316 std::vector<std::string> uncs = c->listUncertainties();
1317 TH1* result = dynamic_cast<TH1*>(c->GetValue("result")); // let's get the size of this for later
1318 if (not result){
1319 if (m_verbose) std::cout << "Dynamic cast failed at "<<__LINE__<<"\n";
1320 continue;
1321 }
1322 m_blockmatrixsize+=result->GetNbinsX()*result->GetNbinsY()*result->GetNbinsZ(); // should be ~300 for fixed cut, something else for continuous
1323 if (m_verbose) std::cout << "m_blockmatrixsize is now " << m_blockmatrixsize << std::endl;
1324 for (const std::string& unc : uncs){
1325 if (unc.find("stat_np") != string::npos) m_statVariations = true;
1326 if ((unc=="result")||(unc=="comment")||(unc=="ReducedSets")||(unc=="systematics")||(unc=="statistics")||(unc=="extrapolation")||(unc=="MChadronisation")||(unc=="combined")||(unc=="extrapolation from charm")) {
1327 continue;
1328 } else {
1329 m_all_shared_systematics.insert(unc); // Construct the set of uncertainties to get a full tally of everything in the container group
1330 }
1331 }
1332 // If specified, add items recommended for exclusion from EV decomposition by the calibration group to the 'named uncertainties' list
1333 // This used to work on only one container, but now we do it on all four containers
1334 if (excludeRecommendedUncertaintySet) {
1335 std::vector<std::string> to_exclude = split(c->getExcludedUncertainties());
1336 if (to_exclude.size() == 0) {
1337 std::cerr << "CalibrationDataEigenVariations warning: exclusion of pre-set uncertainties list requested but no (or empty) list found" << std::endl;
1338 }
1339 for (const auto& name : to_exclude) {
1340 if (name == "") continue;
1341 excludeNamedUncertainty(name, flavour);
1342 }
1343 }
1344 }
1345 }
1346
1347 if (m_verbose) std::cout << "\n number of shared uncertainties is " << m_all_shared_systematics.size() << std::endl;
1348
1349 std::set<std::string>::iterator it = m_all_shared_systematics.begin();
1350 if (it != m_all_shared_systematics.end()){
1351 if (m_verbose) std::cout << "Printing out all shared uncertainties for " << tagger << "/" << jetcollection << "/" << wp << std::endl;
1352 if (m_verbose) std::cout << "| " << std::endl;
1353 while (it != m_all_shared_systematics.end()){
1354 if (m_verbose) std::cout << "|-- " << (*it) << std::endl;
1355 ++it;
1356 }
1357 } else {
1358 if (m_verbose) std::cout << "| no shared systematics between ";
1359 for (const auto& f : m_flavours){
1360 if (m_verbose) std::cout << f << ", ";
1361 } if (m_verbose) std::cout << std::endl;
1362 }
1363 // End of constructor
1364}
bool m_initialized
flag whether the initialization has been carried out
int m_namedExtrapolation
named variation index for the special case of extrapolation uncertainties
bool m_statVariations
indicate whether statistical uncertainties are stored as variations
CalibrationDataEigenVariations(const std::string &cdipath, const std::string &tagger, const std::string &wp, const std::string &jetcollection, CalibrationDataHistogramContainer *cnt, bool excludeRecommendedUncertaintySet=false, bool base=true)
normal constructor.
void excludeNamedUncertainty(const std::string &name, const std::string &flavour)
std::map< std::string, std::vector< std::pair< TH1 *, TH1 * > > > m_flav_eigen
std::map< std::string, Analysis::CalibrationDataHistogramContainer * > m_histcontainers
std::vector< std::string > split(const std::string &s, const std::string &t=":")
Definition hcg.cxx:179
const std::string tagger

◆ ~CalibrationDataGlobalEigenVariations()

Definition at line 1367 of file CalibrationDataEigenVariations.cxx.

1368{
1369 // delete all variation histograms owned by us
1370 for (const auto& flavour : m_flavours){
1371 for (vector<pair<TH1*, TH1*> >::iterator it = m_flav_eigen[flavour].begin(); it != m_flav_eigen[flavour].end(); ++it) {
1372 delete it->first;
1373 delete it->second;
1374 }
1375
1376 for (vector<pair<TH1*, TH1*> >::iterator it = m_flav_named[flavour].begin(); it != m_flav_named[flavour].end(); ++it) {
1377 delete it->first;
1378 delete it->second;
1379 }
1380 }
1381}
std::map< std::string, std::vector< std::pair< TH1 *, TH1 * > > > m_flav_named
std::map< std::string, std::vector< std::pair< TH1 *, TH1 * > > > m_flav_eigen

Member Function Documentation

◆ EigenVectorRecomposition()

bool CalibrationDataEigenVariations::EigenVectorRecomposition ( const std::string & label,
std::map< std::string, std::map< std::string, float > > & coefficientMap )
inherited

Eigenvector recomposition method.

Definition at line 1113 of file CalibrationDataEigenVariations.cxx.

1115{
1116 // Calculating eigen vector recomposition coefficient map and pass to
1117 // user by reference. Return true if method success. Return false and
1118 // will not modify coefficientMap if function failed.
1119 //
1120 // label: flavour label
1121 // coefficientMap: (reference to) coefficentMap which will be used as return value.
1122
1123 if (! m_initialized) initialize();
1124
1125 std::vector<TH1*> originSF_hvec;
1126 std::vector<std::unique_ptr<TH1>> eigenSF_hvec;
1127
1128 // Retrieving information for calculation
1129 std::vector<string>fullUncList = m_cnt->listUncertainties();
1130 std::vector<string> uncList;
1131 for (unsigned int t = 0; t < fullUncList.size(); ++t) {
1132 // entries that should never be included
1133 if (fullUncList[t] == "comment" || fullUncList[t] == "result" || fullUncList[t] == "combined" ||
1134 fullUncList[t] == "statistics" || fullUncList[t] == "systematics" || fullUncList[t] == "MCreference" ||
1135 fullUncList[t] == "MChadronisation" || fullUncList[t] == "extrapolation" || fullUncList[t] == "ReducedSets" ||
1136 fullUncList[t] == "excluded_set") continue;
1137
1138 // entries that can be excluded if desired
1139 if (m_namedIndices.find(fullUncList[t]) != m_namedIndices.end()) continue;
1140
1141 TH1* hunc = dynamic_cast<TH1*>(m_cnt->GetValue(fullUncList[t].c_str()));
1142 if (not hunc){
1143 std::cerr<<"CalibrationDataEigenVariations::EigenVectorRecomposition: dynamic cast failed\n";
1144 continue;
1145 }
1146
1147 Int_t nx = hunc->GetNbinsX();
1148 Int_t ny = hunc->GetNbinsY();
1149 Int_t nz = hunc->GetNbinsZ();
1150 Int_t bin = 0;
1151 bool retain = false; // Retain the histogram?
1152
1153 // discard empty histograms
1154 // Read all bins without underflow&overflow
1155 for(Int_t binx = 1; binx <= nx; binx++)
1156 for(Int_t biny = 1; biny <= ny; biny++)
1157 for(Int_t binz = 1; binz <= nz; binz++){
1158 bin = hunc->GetBin(binx, biny, binz);
1159 if (fabs(hunc->GetBinContent(bin)) > 1E-20){
1160 retain = true;
1161 break;
1162 }
1163 }// end hist bin for-loop
1164 if (!retain){
1165 if (m_verbose) std::cout<<"Eigenvector Recomposition: Empty uncertainty "<<fullUncList.at(t)<<" is discarded."<<std::endl;
1166 continue; // discard the vector
1167 }
1168
1169 uncList.push_back(fullUncList.at(t));
1170 originSF_hvec.push_back(hunc);
1171 }
1172
1173 TH1* nom = dynamic_cast<TH1*>(m_cnt->GetValue("result")); // Nominal SF hist
1174 if (not nom){
1175 if (m_verbose) std::cout<<"Eigenvector Recomposition: dynamic cast failed\n";
1176 return false;
1177 }
1178 int dim = nom->GetDimension();
1179 Int_t nx = nom->GetNbinsX();
1180 Int_t ny = nom->GetNbinsY();
1181 Int_t nz = nom->GetNbinsZ();
1182 Int_t nbins = nx;
1183 if(dim > 1) nbins *= ny;
1184 if(dim > 2) nbins *= nz;
1185 TMatrixD matSF(uncList.size(), nbins);
1186 Int_t col = 0; // mark the column number
1187 // Fill the Delta SF Matrix
1188 for(unsigned int i = 0; i < uncList.size(); i++){
1189 col = 0;
1190 // Loop all bins except underflow&overflow bin
1191 for(int binz = 1; binz <= nz; binz++)
1192 for(int biny = 1; biny <= ny; biny++)
1193 for(int binx = 1; binx <= nx; binx++){
1194 Int_t bin = originSF_hvec.at(i)->GetBin(binx, biny, binz);
1195 TMatrixDRow(matSF,i)[col] = originSF_hvec[i]->GetBinContent(bin);
1196 col++;
1197 }
1198 }
1199
1200 // get eigen vectors of scale factors. Note that this is not the original eigen-vector.
1201 int nEigen = getNumberOfEigenVariations();
1202 TH1* up = nullptr;
1203 TH1* down = nullptr;
1204 for (int i = 0; i < nEigen; i++){
1205 if (!getEigenvectorVariation(i, up, down)){
1206 std::cerr<<"EigenVectorRecomposition: Error on retrieving eigenvector "<<i<<std::endl;
1207 return false;
1208 }
1209 // Clone first: up is owned by m_eigen, so subtracting nom in place would corrupt the cache.
1210 std::unique_ptr<TH1> pure(static_cast<TH1*>(up->Clone()));
1211 pure->SetDirectory(nullptr);
1212 pure->Add(nom, -1);
1213 eigenSF_hvec.push_back(std::move(pure));
1214 }
1215 TMatrixD matEigen(nEigen, nbins);
1216
1217 // Fill the Eigen Matrix
1218 for(int i = 0; i < nEigen; i++){
1219 col = 0;
1220 // Read 300 bins without underflow&overflow
1221 for(int binz = 1; binz <= nz; binz++)
1222 for(int biny = 1; biny <= ny; biny++)
1223 for(int binx = 1; binx <= nx; binx++){
1224 Int_t bin = eigenSF_hvec.at(i)->GetBin(binx, biny, binz);
1225 TMatrixDRow(matEigen,i)[col] = eigenSF_hvec[i]->GetBinContent(bin);
1226 col++;
1227 }
1228 }
1229
1230 eigenSF_hvec.clear();
1231
1232 // Sanity check:
1233 TMatrixD matEigenOriginal = matEigen;
1234 TMatrixD matEigenTranspose = matEigen;
1235 matEigenTranspose = matEigenTranspose.T();
1236 TMatrixD matOriginalTimesTranspose = matEigenOriginal*matEigenTranspose;
1237 TMatrixD matEigenInvert = matEigenTranspose*matOriginalTimesTranspose.Invert();
1238 //(matEigenOriginal*matEigenInvert).DrawClone("colz"); // This should give us an identity matrix
1239
1240 TMatrixD matCoeff = matSF*matEigenInvert;
1241 int nRows = matCoeff.GetNrows();
1242 int nCols = matCoeff.GetNcols();
1243 std::map<std::string, float> temp_map;
1244 for (int col = 0; col < nCols; col++){
1245 temp_map.clear();
1246 for(int row = 0; row < nRows; row++){
1247 temp_map[uncList[row]] = TMatrixDRow(matCoeff, row)[col];
1248 }
1249 coefficientMap["Eigen_"+label+"_"+std::to_string(col)] = temp_map;
1250 }
1251
1252 return true;
1253}
CalibrationDataHistogramContainer * m_cnt
container object containing the basic information
std::map< std::string, unsigned int > m_namedIndices
named variations
bool getEigenvectorVariation(unsigned int variation, TH1 *&up, TH1 *&down)
obtain the "up" and "down" variations for the given eigenvector number.
unsigned int getNumberOfEigenVariations()
retrieve the number of eigenvector variations
std::string label(const std::string &format, int i)
Definition label.h:19
row
Appending html table to final .html summary file.
unsigned int constexpr nRows
Definition RPDUtils.h:24
unsigned int constexpr nCols
Definition RPDUtils.h:25
void initialize()

◆ excludeNamedUncertainty() [1/2]

void CalibrationDataEigenVariations::excludeNamedUncertainty ( const std::string & name,
CalibrationDataContainer * cnt )
inherited

exclude the source of uncertainty indicated by name from eigenvector calculations

Definition at line 371 of file CalibrationDataEigenVariations.cxx.

372{
373 // Exclude the source of uncertainty identified by the given name from being used
374 // in the construction of the covariance matrix to be diagonalised.
375 // Notes:
376 // - Some names returned by CalibrationDataContainer::listUncertainties() are not
377 // meaningful in this context, and specifying them is not allowed.
378 // - Once the eigenvector diagonalisation has been carried out, this method may
379 // not be used anymore.
380
381 if (m_initialized) {
382 std::cerr << "CalibrationDataEigenVariations::excludeNamedUncertainty error:" << " initialization already done" << std::endl;
383 } else if (name == "comment" || name == "result" || name == "systematics" ||
384 name == "statistics" || name == "combined" || name == "extrapolation" ||
385 name == "MCreference" || name == "MChadronisation" || name == "ReducedSets" ||
386 name == "excluded_set" || name == "" || name == " ") // <--- these last two handle some cases that may turn up
387 {
388 std::cerr << "CalibrationDataEigenVariations::excludeNamedUncertainty error:" << " name " << name << " not allowed" << std::endl;
389 }
390 // in case multiple uncertainties should be discarded
391 else if (name.back() == '*'){
392 std::string temp_name = name.substr(0, name.size()-1); //remove "*"
393 std::vector<std::string> uncs = m_cnt->listUncertainties();
394 std::vector<std::string> unc_subgroup;
395 std::copy_if(uncs.begin(), uncs.end(), back_inserter(unc_subgroup),
396 [&temp_name](const std::string& el) {
397 return el.compare(0, temp_name.size(), temp_name) == 0;
398 });
399 if (m_verbose) std::cout <<"Found a group of uncertainties to exclude: " <<name <<" found " <<unc_subgroup.size() <<" uncertainties corresponding to the query" <<std::endl;
400 for (const auto& single_name : unc_subgroup){
401 // only really add if the entry is not yet in the list
402 if (m_namedIndices.find(single_name) == m_namedIndices.end()) {
403 if (m_verbose) std::cout << "Name : " << single_name << std::endl;
404 m_named.push_back(std::pair<TH1*, TH1*>(0, 0));
405 m_namedIndices[single_name] = m_named.size()-1;
406 }
407 }
408 }
409 else if (! cnt->GetValue(name.c_str())){
410 std::cerr << "CalibrationDataEigenVariations::excludeNamedUncertainty error:" << " uncertainty named " << name << " not found" << std::endl;
411 }
412}
std::vector< std::pair< TH1 *, TH1 * > > m_named

◆ excludeNamedUncertainty() [2/2]

void CalibrationDataGlobalEigenVariations::excludeNamedUncertainty ( const std::string & name,
const std::string & flavour )

Definition at line 1523 of file CalibrationDataEigenVariations.cxx.

1524{
1525 // Exclude the source of uncertainty identified by the given name from being used
1526 // in the construction of the covariance matrix to be diagonalised.
1527 // Notes:
1528 // - Some names returned by CalibrationDataContainer::listUncertainties() are not
1529 // meaningful in this context, and specifying them is not allowed.
1530 // - Once the eigenvector diagonalisation has been carried out, this method may
1531 // not be used anymore.
1532
1533 if (m_initialized) std::cerr << "CalibrationDataGlobalEigenVariations::excludeNamedUncertainty error:" << " initialization already done" << std::endl;
1534
1535 else if (name == "comment" || name == "result" || name == "systematics" ||
1536 name == "statistics" || name == "combined" || name == "extrapolation" ||
1537 name == "MCreference" || name == "MChadronisation" || name == "ReducedSets" ||
1538 name == "excluded_set" || name == "" || name == " ")
1539 std::cerr << "CalibrationDataGlobalEigenVariations::excludeNamedUncertainty error:" << " name [" << name << "] not allowed" << std::endl;
1540
1541 // Note: we WANT to exclude named uncertainties FROM ALL FLAVOURS, even if they don't contain the uncertainty (just fill with zeros). So I won't do this check here.
1542 // only really add if the entry is not yet in the list
1543 else if (m_flav_namedIndices[flavour].find(name) == m_flav_namedIndices[flavour].end()) {
1544 m_flav_named[flavour].push_back(std::pair<TH1*, TH1*>(0, 0));
1545 m_flav_namedIndices[flavour][name] = m_flav_named[flavour].size()-1; // store the index that the name variation pair is stored with in m_named
1546 }
1547}
std::map< std::string, std::map< std::string, unsigned int > > m_flav_namedIndices
std::string find(const std::string &s)
return a remapped string
Definition hcg.cxx:140

◆ getEigenCovarianceMatrix()

also provide (some) access to the underlying information: covariance matrix corresponding to eigenvector variations

Reimplemented from Analysis::CalibrationDataEigenVariations.

Definition at line 1385 of file CalibrationDataEigenVariations.cxx.

1386{
1387 // Construct the block (global) covariance matrix that is to be diagonalised.
1388 // Note that extrapolation uncertainties (identified by the keyword "extrapolation,
1389 // this will pertain mostly to the extrapolation to high jet pt) are always excluded
1390 // since by definition they will not apply to the normal calibration bins. Instead
1391 // this uncertainty has to be dealt with as a named variation. In addition there are
1392 // other items ("combined", "systematics") that will not be dealt with correctly
1393 // either and hence are excluded as well).
1394 //
1395 // Note that if an explicit covariance matrix is supplied (at present this may be
1396 // the case only for statistical uncertainties: in the case of "continuous tagging",
1397 // multinomial statistics applies so bin-to-bin correlations exist) this will be
1398 // used instead of constructing the statistical uncertainties' covariance matrix on
1399 // the fly.
1400
1401 std::map<std::string, TMatrixDSym> cov_matrices; // temporary store, just to aid in printing out the individual systematic covariance matrices
1402 TMatrixDSym global_covariance(m_blockmatrixsize);
1403 // Then loop through the list of (other) uncertainties
1404 for (const std::string& unc : m_all_shared_systematics){
1405 std::vector<int> flavs_in_common;
1406 TString tunc(unc);
1407 std::vector<double> comb_syst; // this vector combines the TH1 uncertainty bins for each flavour into one object -> stored in comb_systematics for now, but meant for covariance matrix method
1408 // For the fixed cut case, we want to bin by groups of flavour > pT (i.e. "blocks" of flavour)
1409 // For the continuous case, we want to bin by groups of flavour > tagweight > pT (i.e. "blocks" of flavour, containing tagweight blocks... more complicated, but works on same principle)
1410 for (const auto& flavour : m_flavours){
1411 Analysis::CalibrationDataHistogramContainer* c = m_histcontainers[flavour]; // pointer to the flavour container
1412 int flavour_size = 0; // Store the length of the uncertainty in the flavour, initialize to zero
1413 if (c) {
1414 // Now we want to get the histogram for this systematic, for this flavour
1415 TH1* hunc = dynamic_cast<TH1*>(c->GetValue(tunc.Data()));
1416 TH1* ref = dynamic_cast<TH1*>(c->GetValue("result")); // retrieving this just in case the uncertainty doesn't exist for this flavour, just need it to get dimensions right
1417 if (not ref){
1418 if (m_verbose) std::cout << " There was no uncertainty OR SF/EFF results... Are you sure you have the right CDIContainer path?" << std::endl;
1419 continue;
1420 }
1421 int tagweightax = c->getTagWeightAxis(); // for handling the continuous case(s)
1422 if (hunc){
1423 flavs_in_common.push_back(1); // report that we have this uncertainty in this flavour
1424 Int_t nbinx = hunc->GetNbinsX(), nbiny = hunc->GetNbinsY(), nbinz = hunc->GetNbinsZ();
1425 Int_t rows = nbinx;
1426 if (hunc->GetDimension() > 1) rows *= nbiny;
1427 if (hunc->GetDimension() > 2) rows *= nbinz;
1428 flavour_size = rows; // Record the number of bins in the uncertainty TH1
1429 } else {
1430 flavs_in_common.push_back(0); // If the uncertainty doesn't exist for that flavour, just report, we'll set to zero in the combined vector
1431 // Because the uncertainty doesn't exist for this flavour, we just get the dimensions we need
1432 Int_t nbinx = ref->GetNbinsX(), nbiny = ref->GetNbinsY(), nbinz = ref->GetNbinsZ();
1433 Int_t rows = nbinx;
1434 if (ref->GetDimension() > 1) rows *= nbiny;
1435 if (ref->GetDimension() > 2) rows *= nbinz;
1436 flavour_size = rows;
1437 }
1438
1439 // Now we can loop through the bins of the flavour uncertainty, adding them onto the combined systematic
1440 if (tagweightax == -1){ //<--- i.e. NOT continuous, but is a fixed cut WP
1441 for (int i = 1 ; i <= flavour_size ; i++){
1442 if (hunc){
1443 Int_t bin = hunc->GetBin(1,i,1);
1444 double unc_val = hunc->GetBinContent(bin);
1445 comb_syst.push_back(unc_val); // if uncertainty, push uncertainty bin content to combined systematic vector
1446 } else {
1447 comb_syst.push_back(0.0); // if no uncertainty, push 0's
1448 }
1449 }
1450 } else if (tagweightax == 0){
1451 // X axis is the tagweight axis, meaning Y is pt, Z is abs(eta)
1452 for (Int_t xbins = 1 ; xbins <= ref->GetNbinsX() ; xbins++){
1453 for (Int_t zbins = 1 ; zbins <= ref->GetNbinsZ() ; zbins++){
1454 for (Int_t ybins = 1 ; ybins <= ref->GetNbinsY() ; ybins++){
1455 if (hunc){
1456 Int_t bin = hunc->GetBin(xbins,ybins,zbins);
1457 double unc_val = hunc->GetBinContent(bin);
1458 comb_syst.push_back(unc_val); // if uncertainty, push uncertainty bin content to combined systematic vector
1459 } else {
1460 comb_syst.push_back(0.0); // if no uncertainty, push 0's
1461 }
1462 // And now we should be constructing the initial covariance matrix for block continuous correctly
1463 }
1464 }
1465 }
1466 } else if (tagweightax == 1){
1467 // Y axis is the tagweight axis, meaning X is pt, Z is abs(eta)
1468 for (Int_t ybins = 1 ; ybins <= ref->GetNbinsY() ; ybins++){
1469 for (Int_t zbins = 1 ; zbins <= ref->GetNbinsZ() ; zbins++){
1470 for (Int_t xbins = 1 ; xbins <= ref->GetNbinsX() ; xbins++){
1471 if (hunc){
1472 Int_t bin = hunc->GetBin(xbins,ybins,zbins);
1473 double unc_val = hunc->GetBinContent(bin);
1474 comb_syst.push_back(unc_val); // if uncertainty, push uncertainty bin content to combined systematic vector
1475 } else {
1476 comb_syst.push_back(0.0); // if no uncertainty, push 0's
1477 }
1478 // And now we should be constructing the initial covariance matrix for block continuous correctly
1479 }
1480 }
1481 }
1482 } else if (tagweightax == 2){
1483 // Z axis is the tagweight axis, meaning X is pt, Y is abs(eta)
1484 for (Int_t zbins = 1 ; zbins <= ref->GetNbinsZ() ; zbins++){
1485 for (Int_t ybins = 1 ; ybins <= ref->GetNbinsY() ; ybins++){
1486 for (Int_t xbins = 1 ; xbins <= ref->GetNbinsX() ; xbins++){
1487 if (hunc){
1488 Int_t bin = hunc->GetBin(xbins,ybins,zbins);
1489 double unc_val = hunc->GetBinContent(bin);
1490 comb_syst.push_back(unc_val); // if uncertainty, push uncertainty bin content to combined systematic vector
1491 } else {
1492 comb_syst.push_back(0.0); // if no uncertainty, push 0's
1493 }
1494 // And now we should be constructing the initial covariance matrix for block continuous correctly
1495 }
1496 }
1497 }
1498 }
1499 }
1500 }
1501 //comb_systematics.insert({unc, comb_syst}); // after having looped through the bins for each flavour, the comb_syst vector should be completed and added (or rather, made into a covariance matrix)
1502 TMatrixDSym unc_cov(comb_syst.size());
1503 if (unc == "statistics"){
1504 unc_cov = getStatCovarianceMatrix(comb_syst, m_statVariations); // we want to handle the "statistics" uncertainty differently
1505 } else {
1506 unc_cov = getSystCovarianceMatrix(comb_syst);
1507 }
1508 cov_matrices.insert({unc, unc_cov}); // add the covariance matrix for the uncertainty to this map, this is temporary for testing/plotting purposes
1509
1510 // To look only at uncertainties that pertain to more than one flavour (2, 3 or all 4) we can store the covariances separately for later saving and plotting
1511 if (flavs_in_common[0]+flavs_in_common[1]+flavs_in_common[2]+flavs_in_common[3] > 1){
1512 m_only_shared_systematics.insert(unc) ; // mark the shared systematics...
1513 }
1514
1515 global_covariance += unc_cov;
1516 }
1517 return global_covariance;
1518}
const std::regex ref(r_ef)

◆ getEigenCovarianceMatrixFromVariations()

TMatrixDSym CalibrationDataEigenVariations::getEigenCovarianceMatrixFromVariations ( )
inherited

covariance matrix corresponding to eigenvector variations constructed from the eigen-variation

Definition at line 473 of file CalibrationDataEigenVariations.cxx.

474{
475 // Construct the (Eigen-variation part of the) covariance matrix from the individual variations.
476 // This must be called _after_ initialize()!
477
478 // retrieve the central calibration
479 TH1 *result = dynamic_cast<TH1*>(m_cnt->GetValue("result"));
480 if (!result){
481 std::cerr<<"CalibrationDataEigenVariations::getEigenCovarianceMatrixFromVariations(): dynamic cast failed\n";
482 return TMatrixDSym();
483 }
484 TMatrixD jac = getJacobianReductionMatrix();
485 int nbins = jac.GetNcols();
486 TMatrixDSym cov(nbins);
487 auto variation = std::make_unique<double[]>(nbins);
488
489 for (const std::pair<TH1*, TH1*>& it : m_eigen){ // m_eigen is vector of pairs of TH1* which point to TH1's representing the upVariation and downVariation respectively
490 TH1* resultVariedUp = it.first; // <--------------- This is the "result" but "varied" upwards - i.e. how the result would look like if the systematic "it" was imposed
491 for (unsigned int u = 0; u < (unsigned int) nbins; ++u) variation[u] = resultVariedUp->GetBinContent(u) - result->GetBinContent(u);
492 for (int u = 0; u < nbins; ++u){
493 for (int v = 0; v < nbins; ++v){
494 cov(u, v) += variation[u]*variation[v];
495 }
496 }
497 }
498
499 return cov;
500}
std::vector< std::pair< TH1 *, TH1 * > > m_eigen
eigenvector variations
TMatrixD getJacobianReductionMatrix()
matrix to remove unecessary rows and columns from covariance
@ u
Enums for curvilinear frames.
Definition ParamDefs.h:77

◆ getEigenvectorVariation() [1/2]

bool CalibrationDataEigenVariations::getEigenvectorVariation ( unsigned int variation,
TH1 *& up,
TH1 *& down )
inherited

obtain the "up" and "down" variations for the given eigenvector number.

The return value will be false if the eigenvector number is invalid.

Definition at line 1022 of file CalibrationDataEigenVariations.cxx.

1024{
1025 // Return the pointers to the up- and downward variation histogram for the specified
1026 // eigenvector variation. In case of an invalid variation number, null pointers will
1027 // be returned and the return value will be false.
1028 //
1029 // variation: eigenvector variation number
1030 // up: (reference to) pointer to upward variation histogram
1031 // down: (reference to) pointer to downward variation histogram
1032
1033 if (! m_initialized) initialize();
1034
1035 if (variation < m_eigen.size()) {
1036 up = m_eigen[variation].first;
1037 down = m_eigen[variation].second;
1038 return true;
1039 }
1040
1041 up = down = 0;
1042 return false;
1043}

◆ getEigenvectorVariation() [2/2]

bool CalibrationDataGlobalEigenVariations::getEigenvectorVariation ( const std::string & flavour,
unsigned int variation,
TH1 *& up,
TH1 *& down )

Definition at line 1961 of file CalibrationDataEigenVariations.cxx.

1962{
1963 // Return the pointers to the up- and downward variation histogram for the specified
1964 // eigenvector variation. In case of an invalid variation number, null pointers will
1965 // be returned and the return value will be false.
1966 //
1967 // variation: eigenvector variation number
1968 // up: (reference to) pointer to upward variation histogram
1969 // down: (reference to) pointer to downward variation histogram
1970
1971 if (! m_initialized) initialize();
1972 std::vector<std::pair<TH1*,TH1*>> flav_variations = m_flav_eigen.find(flavour)->second;
1973 if (variation < flav_variations.size()){
1974 up = flav_variations[variation].first;
1975 down = flav_variations[variation].second;
1976 return true;
1977 }
1978
1979 up = down = 0;
1980 return false;
1981}

◆ getJacobianReductionMatrix() [1/2]

TMatrixD CalibrationDataEigenVariations::getJacobianReductionMatrix ( )
inherited

matrix to remove unecessary rows and columns from covariance

Definition at line 504 of file CalibrationDataEigenVariations.cxx.

505{
506 // Construct the matrix that removes the rows and columns that fail to influence
507 // the eigen-variations. To reduce the covariance matrix, do the following:
508 //
509 // TMatrixDSym cov = getEigenCovarianceMatrix();
510 // TMatrixDSym jac = getJacobianReductionMatrix(); // <------------ This is an upper triangular matrix of 1's. Similarity transformation will do...
511 // TMatrixDSym redSystematicCovMatrix = cov.Similarity(jac);
512
513 // retrieve the central calibration
514 TH1* result = dynamic_cast<TH1*>(m_cnt->GetValue("result"));
515 if (not result){
516 std::cerr<<"CalibrationDataEigenVariations::getJacobianReductionMatrix(): dynamic cast failed\n";
517 return TMatrixD();
518 }
519
520 // loop over the uncertainties to construct the covariance matrix for all uncertainties
521 // to be addressed using the eigenvector method.
522
523 // Retrieve the un-compressed Eigenvector variation covariance matrix
524 // (only needed to check for unexpected singularities)
525 TMatrixDSym cov = getEigenCovarianceMatrix();
526
527 // Compute the original number of bins
528 int nbins = result->GetNbinsX()+2;
529 int ndim = result->GetDimension();
530 if (ndim > 1) nbins*= (result->GetNbinsY()+2);
531 if (ndim > 2) nbins*= (result->GetNbinsZ()+2);
532
533 // Start by "compressing" the covariance matrix (removing columns/rows containing zeros only)
534 int nZeros=0;
535 std::vector<int> zeroComponents;
536 if (cov.GetNrows() != nbins) {
537 std::cerr << " error: covariance matrix size (" << cov.GetNrows() << ") doesn't match histogram size (" << nbins << ")" << std::endl;
538 return TMatrixDSym();
539 }
540
541 // First flag all the zeros
542 for (int i = 0; i < nbins; ++i) {
543 // Directly identify the under- and overflow bins
544 Int_t binx, biny, binz;
545 result->GetBinXYZ(i, binx, biny, binz);
546 if ((binx == 0 || binx == result->GetNbinsX()+1) ||
547 (ndim > 1 && (biny == 0 || biny == result->GetNbinsY()+1)) ||
548 (ndim > 2 && (binz == 0 || binz == result->GetNbinsZ()+1)))
549 {
550 ++nZeros;
551 zeroComponents.push_back(i);
552 }
553 // Try a first (quick) identification of rows/columns of zeros by the first element in each row
554 // If "successful", check the whole row in more detail
555 else if (fabs(cov(i,0)) < 1e-10) {
556 bool isThereANonZero(false);
557 for (int j = 0; j < nbins; ++j) {
558 if (fabs(cov(i,j)) > 1e-10) {
559 isThereANonZero=true; break;
560 }
561 }
562 if (! isThereANonZero) {
563 ++nZeros;
564 zeroComponents.push_back(i);
565 }
566 }
567 }
568
569 // **** COMMENTED OUT FOR NOW.
570 // Leave it here in case the calibration method will change again in the future.
571 // No need to reweight the SF by the efficiency of that bin (MCreference always = 0)
572
573 // Determine whether the container is for "continuous" calibration.
574 // This is important since the number of independent scale factors (for each pt or eta bin)
575 // is reduced by 1 compared to the number of tag weight bins (related to the fact that the fractions
576 // of events in tag weight bins have to sum up to unity).
577 // int axis = m_cnt->getTagWeightAxis();
578 // bool doContinuous = false; unsigned int weightAxis = 0;
579
580 // if (axis >= 0) {
581 // doContinuous = true;
582 // // weightAxis = (unsigned int) axis;
583 // // In this case, verify that the special "uncertainty" entry that is in fact the reference MC tag
584 // // weight fractions is present. These tag weight fractions are needed in order to carry out the
585 // // diagonalisation successfully.
586 // if (! dynamic_cast<TH1*>(m_cnt->GetValue("MCreference"))) {
587 // std::cerr << " Problem: continuous calibration object found without MC reference tag weight histogram " << std::endl;
588 // return TMatrixDSym();
589 // }
590 // }
591
592 // Only relevant for continuous calibration containers, but in order to void re-computation we
593 // retrieve them here
594 // Int_t nbinx = result->GetNbinsX()+2, nbiny = result->GetNbinsY()+2, nbinz = result->GetNbinsZ()+2;
595
596 // // If we are indeed dealing with a "continuous" calibration container, ignore one tag weight row
597 // const int skipTagWeightBin = 1; // NB this follows the histogram's bin numbering
598 // if (doContinuous) {
599 // for (Int_t binx = 1; binx < nbinx-1; ++binx)
600 // for (Int_t biny = 1; biny < nbiny-1; ++biny)
601 // for (Int_t binz = 1; binz < nbinz-1; ++binz) {
602 // if ((weightAxis == 0 && binx == skipTagWeightBin) ||
603 // (weightAxis == 1 && biny == skipTagWeightBin) ||
604 // (weightAxis == 2 && binz == skipTagWeightBin)) {
605 // // At this point we simply add these to the 'null' elements
606 // ++nZeros;
607 // zeroComponents.push_back(result->GetBin(binx, biny, binz));
608 // }
609 // }
610 // }
611
612 if (nZeros >= nbins) {
613 std::cerr << " Problem. Found n. " << nZeros << " while size of matrix is " << nbins << std::endl;
614 return TMatrixDSym();
615 }
616
617 int size = nbins - nZeros; // <--- Tis the size of the matrix removing zeros from the covariance matrix
618
619 TMatrixT<double> matrixVariationJacobian(size,nbins);
620 int nMissed=0;
621 for (int i = 0; i < nbins; ++i) { //full size
622 bool missed=false;
623 for (unsigned int s = 0; s < zeroComponents.size(); ++s) { // <-------- Basically what this does is it flags "missed" for a given "i" of the full bin size
624 if (zeroComponents.at(s) == i) { // <-------- if "i" is in "zeroComponents". Breaks (because it found that it's to be missed)
625 missed = true;
626 break;
627 }
628 }
629 if (missed) { // <-------- Finally, if "i" is to be missed, increase "nMissed" by one, and....
630 ++nMissed;
631 continue;
632 }
633 matrixVariationJacobian(i-nMissed,i)=1; // <-------- ... this ALWAYS adds a one. If zero "nMissed", add to diagonal. otherwise off-diagonal
634 } // <-------- This matrix only add 1's on/off diagonal, upper triangular matrix
635
636 return matrixVariationJacobian;
637}
size_t size() const
Number of registered mappings.
virtual TMatrixDSym getEigenCovarianceMatrix()
also provide (some) access to the underlying information: covariance matrix corresponding to eigenvec...
float j(const xAOD::IParticle &, const xAOD::TrackMeasurementValidation &hit, const Eigen::Matrix3d &jab_inv)

◆ getJacobianReductionMatrix() [2/2]

Definition at line 1883 of file CalibrationDataEigenVariations.cxx.

1884{
1885 // Construct the matrix that removes the rows and columns that fail to influence
1886 // the eigen-variations. To reduce the covariance matrix, do the following:
1887 // Note: Previous version called "getEigenCovariance" whereas here we pass it in by reference to save on compute
1888 // This "cov" is the "uncompressed" eigenvariation covariance matrix for all uncertainties.
1889 // We will subsequently compress it (removing columns/rows containing zeros only)
1890 // and then construct the hopefully rectangular matrix that can remove these ones from the covariance matrix
1891
1892 int nZeros = 0;
1893 std::vector<int> zeroComponents;
1894
1895 // First flag all the zeros
1896 for (int i = 0 ; i < m_blockmatrixsize ; i++){
1897 if (fabs(cov(i,0)) < 1e-10){
1898 bool isThereANonZero = false;
1899 for (int j = 0 ; j < m_blockmatrixsize ; j++){
1900 // Try a first (quick) identification of rows/columns of zeros by the first element in each row
1901 // If "successful", check the whole row in more detail
1902 if (fabs(cov(i,j)) > 1e-10){
1903 isThereANonZero = true;
1904 break;
1905 }
1906 }
1907 if (! isThereANonZero){
1908 ++nZeros;
1909 zeroComponents.push_back(i) ;
1910 }
1911 }
1912 }
1913
1914 if (nZeros >= m_blockmatrixsize) {
1915 std::cerr << " Problem. Found n. " << nZeros << " while size of matrix is " << m_blockmatrixsize << std::endl;
1916 return TMatrixDSym();
1917 }
1918
1919 int size = m_blockmatrixsize - nZeros;
1920 TMatrixT<double> matrixVariationJacobian(size,m_blockmatrixsize);
1921 int nMissed = 0;
1922
1923 for (int i = 0; i < m_blockmatrixsize; ++i) { // full size
1924 bool missed = false;
1925 for (unsigned int s = 0 ; s < zeroComponents.size(); ++s) { // <--- Basically what this does is it flags "missed" for a given "i" of the full bin size
1926 if (zeroComponents.at(s) == i) { // <--- if "i" is in "zeroComponents". Breaks (because it found that it's to be missed)
1927 missed = true;
1928 break;
1929 }
1930 }
1931 if (missed) { // <-------- Finally, if "i" is to be missed, increase "nMissed" by one, and....
1932 ++nMissed;
1933 continue;
1934 }
1935
1936 matrixVariationJacobian(i-nMissed,i)=1; // <-------- ... this ALWAYS adds a one. If zero "nMissed", add to diagonal. otherwise off-diagonal
1937 }
1938
1939 return matrixVariationJacobian;
1940}

◆ getNamedVariation() [1/4]

bool CalibrationDataEigenVariations::getNamedVariation ( const std::string & name,
TH1 *& up,
TH1 *& down )
inherited

obtain the "up" and "down" variations for the named uncertainty.

The return value will be false if the given name is not listed as being excluded from the eigenvector calculations.

Definition at line 1047 of file CalibrationDataEigenVariations.cxx.

1049{
1050 // Return the pointers to the up- and downward variation histogram for the specified
1051 // named variation. In case of an invalid named variation, null pointers will
1052 // be returned and the return value will be false.
1053 //
1054 // name: named variation
1055 // up: (reference to) pointer to upward variation histogram
1056 // down: (reference to) pointer to downward variation histogram
1057
1058 map<string, unsigned int>::const_iterator it = m_namedIndices.find(name);
1059 if (it != m_namedIndices.end()) return getNamedVariation(it->second, up, down);
1060
1061 up = down = 0;
1062 return false;
1063}
bool getNamedVariation(const std::string &name, TH1 *&up, TH1 *&down)
obtain the "up" and "down" variations for the named uncertainty.

◆ getNamedVariation() [2/4]

bool CalibrationDataEigenVariations::getNamedVariation ( unsigned int nameIndex,
TH1 *& up,
TH1 *& down )
inherited

obtain the "up" and "down" variations for the source uncertainty pointed to by the given index (which is assumed to correspond to the value retrieved using getNamedVariationIndex()).

The return value will be false if the index is out of bounds.

Definition at line 1067 of file CalibrationDataEigenVariations.cxx.

1069{
1070 // Return the pointers to the up- and downward variation histogram for the specified
1071 // named variation. In case of an invalid named variation number, null pointers will
1072 // be returned and the return value will be false.
1073 //
1074 // nameIndex: named variation number
1075 // up: (reference to) pointer to upward variation histogram
1076 // down: (reference to) pointer to downward variation histogram
1077
1078 if (! m_initialized) initialize();
1079
1080 if (nameIndex < m_named.size()) {
1081 up = m_named[nameIndex].first;
1082 down = m_named[nameIndex].second;
1083 return true;
1084 }
1085
1086 up = down = 0;
1087 return false;
1088}

◆ getNamedVariation() [3/4]

bool CalibrationDataGlobalEigenVariations::getNamedVariation ( const std::string & flavour,
const std::string & name,
TH1 *& up,
TH1 *& down )

Definition at line 1985 of file CalibrationDataEigenVariations.cxx.

1986{
1987 // Return the pointers to the up- and downward variation histogram for the specified
1988 // named variation. In case of an invalid named variation, null pointers will
1989 // be returned and the return value will be false.
1990 //
1991 // name: named variation
1992 // up: (reference to) pointer to upward variation histogram
1993 // down: (reference to) pointer to downward variation histogram
1994
1995 // Find the named variation index (if it exists) and pass to "getNamedVariation"
1996 std::map<std::string, unsigned int>::const_iterator it = (m_flav_namedIndices.find(flavour)->second).find(name);
1997 if (it != (m_flav_namedIndices.find(flavour)->second).end()) return getNamedVariation(it->second, flavour, up, down);
1998
1999 up = down = 0;
2000 return false;
2001}
bool getNamedVariation(const std::string &flavour, const std::string &name, TH1 *&up, TH1 *&down)

◆ getNamedVariation() [4/4]

bool CalibrationDataGlobalEigenVariations::getNamedVariation ( unsigned int nameIndex,
const std::string & flavour,
TH1 *& up,
TH1 *& down )

Definition at line 2005 of file CalibrationDataEigenVariations.cxx.

2006{
2007 // Return the pointers to the up- and downward variation histogram for the specified
2008 // named variation. In case of an invalid named variation number, null pointers will
2009 // be returned and the return value will be false.
2010 //
2011 // nameIndex: named variation number
2012 // up: (reference to) pointer to upward variation histogram
2013 // down: (reference to) pointer to downward variation histogram
2014
2015 if (! m_initialized) initialize();
2016
2017 if (nameIndex < m_flav_named[flavour].size()) {
2018 up = m_flav_named[flavour][nameIndex].first;
2019 down = m_flav_named[flavour][nameIndex].second;
2020 return true;
2021 }
2022
2023 up = down = 0;
2024 return false;
2025}

◆ getNamedVariationIndex() [1/2]

unsigned int CalibrationDataEigenVariations::getNamedVariationIndex ( const std::string & name) const
inherited

retrieve the integer index corresponding to the named variation.

This can be used to speed up computations by avoiding string comparisons. Note that this function is not protected against passing an invalid name.

Definition at line 1092 of file CalibrationDataEigenVariations.cxx.

1093{
1094 // Return the integer index corresponding to the named variation.
1095 // Note that no checks are made on the validity of the name provided.
1096
1097 map<string, unsigned int>::const_iterator it = m_namedIndices.find(name);
1098 return it->second;
1099}

◆ getNamedVariationIndex() [2/2]

unsigned int CalibrationDataGlobalEigenVariations::getNamedVariationIndex ( const std::string & name,
const std::string & flavour ) const

Definition at line 2030 of file CalibrationDataEigenVariations.cxx.

2031{
2032 // Return the integer index corresponding to the named variation.
2033 // Note that no checks are made on the validity of the name provided.
2034 std::map<std::string, unsigned int>::const_iterator it = (m_flav_namedIndices.find(flavour)->second).find(name);
2035 return it->second;
2036}

◆ getNumberOfEigenVariations() [1/2]

unsigned int CalibrationDataEigenVariations::getNumberOfEigenVariations ( )
inherited

retrieve the number of eigenvector variations

Definition at line 1014 of file CalibrationDataEigenVariations.cxx.

1015{
1016 if (! m_initialized) initialize();
1017 return m_eigen.size();
1018}

◆ getNumberOfEigenVariations() [2/2]

Definition at line 1948 of file CalibrationDataEigenVariations.cxx.

1949{
1950 if (! m_initialized) initialize();
1951
1952 if (m_flav_eigen.find(flavour) == m_flav_eigen.end()){
1953 if (m_verbose) std::cout << "No m_flav_eigen for flavour " << flavour << std::endl;
1954 return 0;
1955 }
1956 return (m_flav_eigen.find(flavour)->second).size();
1957}

◆ getNumberOfNamedVariations()

unsigned int CalibrationDataEigenVariations::getNumberOfNamedVariations ( ) const
inherited

retrieve the number of named variations

Definition at line 992 of file CalibrationDataEigenVariations.cxx.

993{
994 // Returns the number of named variations
995
996 return m_namedIndices.size();
997}

◆ initialize()

void CalibrationDataGlobalEigenVariations::initialize ( double min_variance = 1.0E-6)
virtual

carry out the eigenvector computations.

Exclusion of any source of uncertainty has to be done before calling this method

Reimplemented from Analysis::CalibrationDataEigenVariations.

Definition at line 1566 of file CalibrationDataEigenVariations.cxx.

1567{
1568 // This is this class's most important method, in the sense that it does all the
1569 // math and constructs all "variation" histograms (for both eigenvector and named
1570 // named variations). This constitutes the full initialisation of the class.
1571 // This method is meant to be called only after all calls (if any) to the
1572 // CalibrationDataGlobalEigenVariations::excludeNamedUncertainty() method.
1573
1574
1575 // First step: construct the block covariance matrix
1576 TMatrixDSym cov = getEigenCovarianceMatrix();
1577
1578 TMatrixDSym corr(cov); // We want to construct the correlation matrix in order to compare the final eigenvariations correlation matrix to it
1579 for (int row = 0 ; row < cov.GetNrows() ; row++){
1580 for (int col = 0 ; col < cov.GetNcols() ; col++){
1581 double rowvar = sqrt(cov(row,row));
1582 double colvar = sqrt(cov(col,col));
1583 corr(row,col) = corr(row,col)/(rowvar * colvar); // divide each element by the variance
1584 }
1585 }
1586
1588
1589 // Second step: create the variations for the named sources of uncertainty (easy...)
1590 // News flash: This isn't so easy now, as it has to be done for all the flavours to which the uncertainty pertains
1591 // the following are temporary data structures
1592 std::vector<double> combined_result;
1593 std::map<std::string, int> flav_bins; // store the nbins of each flavour histogram for later use in "reporting"
1594 // and eventually, at the end, we will want to separate the flavour blocks out...
1595 for (const auto& flavour : m_flavours) {
1596 // for each flavour, we want to combine the results and uncertainty values across flavours into one "block" vector
1597 // retrieve the central calibration
1598 Analysis::CalibrationDataHistogramContainer* c = m_histcontainers[flavour]; // pointer to the flavour container
1599
1600 TH1* result = dynamic_cast<TH1*>(c->GetValue("result"));
1601 if (not result){
1602 std::cerr<<"CalibrationDataGlobalEigenVariations::initialize: dynamic cast failed\n ";
1603 continue;
1604 }
1605 //construct the combined_result and combined_named_variations (up and down)
1606 if (c->getTagWeightAxis() == -1){ // For fixed cut WP, the Y axis **should** be the pT axis (but can it can potentially be different in the future)
1607 flav_bins[flavour] = result->GetNbinsY(); // Add the number of bins of the result histogram with non-zero results...
1608 if (m_verbose) std::cout << "flav_bins["<<flavour<<"] = " << flav_bins[flavour] << std::endl;
1609 for(int i = 0 ; i < flav_bins[flavour] ; i++){
1610 // push bin content onto the combined_result vector
1611 Int_t bin = result->GetBin(1,i+1); // This will only pick up the CONTENTS, not of the underflow bin
1612 double res_value = result->GetBinContent(bin);
1613 combined_result.push_back(res_value);
1614 }
1615 } else if (c->getTagWeightAxis() == 0) { // for continuous WP, the taxweight axis determines which axis is pt and |eta|
1616 flav_bins[flavour] = result->GetNbinsX()*result->GetNbinsY();
1617 int tagbins = result->GetNbinsX();
1618 int ptbins = result->GetNbinsY();
1619 if (m_verbose) std::cout << "flav_bins["<<flavour<<"] = " << flav_bins[flavour] << std::endl;
1620 for(int i = 0 ; i < tagbins ; i++){
1621 for(int j = 0 ; j < ptbins ; j++){
1622 // push bin content onto the combined_result vector
1623 Int_t bin = result->GetBin(j+1,1,i+1); // This will only pick up the CONTENTS, not of the underflow bin
1624 double res_value = result->GetBinContent(bin);
1625 combined_result.push_back(res_value);
1626 }
1627 }
1628 } else if (c->getTagWeightAxis() == 1) {
1629 flav_bins[flavour] = result->GetNbinsX()*result->GetNbinsY();
1630 int tagbins = result->GetNbinsY();
1631 int ptbins = result->GetNbinsX();
1632 if (m_verbose) std::cout << "flav_bins["<<flavour<<"] = " << flav_bins[flavour] << std::endl;
1633 for(int i = 0 ; i < tagbins ; i++){
1634 for(int j = 0 ; j < ptbins ; j++){
1635 // push bin content onto the combined_result vector
1636 Int_t bin = result->GetBin(j+1,1,i+1); // This will only pick up the CONTENTS, not of the underflow bin
1637 double res_value = result->GetBinContent(bin);
1638 combined_result.push_back(res_value);
1639 }
1640 }
1641 } else if (c->getTagWeightAxis() == 2) {
1642 flav_bins[flavour] = result->GetNbinsX()*result->GetNbinsZ();
1643 int tagbins = result->GetNbinsZ();
1644 int ptbins = result->GetNbinsX();
1645 if (m_verbose) std::cout << "flav_bins["<<flavour<<"] = " << flav_bins[flavour] << std::endl;
1646 for(int i = 0 ; i < tagbins ; i++){
1647 for(int j = 0 ; j < ptbins ; j++){
1648 // push bin content onto the combined_result vector
1649 Int_t bin = result->GetBin(j+1,1,i+1); // This will only pick up the CONTENTS, not of the underflow bin
1650 double res_value = result->GetBinContent(bin);
1651 combined_result.push_back(res_value);
1652 }
1653 }
1654 }
1655
1656
1657 // loop over the excluded uncertainties for this flavour, and construct their actual variations...
1658 // the "m_flav_namedIndices" are constructed within "excludeNamedUncertainties", which is called in the constructor
1659 for (map<string, unsigned int>::iterator it = m_flav_namedIndices[flavour].begin(); it != m_flav_namedIndices[flavour].end(); ++it) {
1660 TH1* hunc = (TH1*) c->GetValue(it->first.c_str()); // this should store the name uncertainty, if it exists for this flavour
1661 // I need to test if this uncertainty actually exists, and if it doesn't just use a ZERO variation histogram explicitly
1662 // but even if it doesn't exist, we want to have it, so that the indices match between flavours
1663 pair<TH1*, TH1*>& p = m_flav_named[flavour][it->second];
1664 TString namedvar("namedVar");
1665 namedvar += it->first.c_str();
1666 TString namedvarUp(namedvar); namedvarUp += "_up";
1667 TString namedvarDown(namedvar); namedvarDown += "_down";
1668 TH1* resultVariedUp = (TH1*)result->Clone(namedvarUp);
1669 TH1* resultVariedDown = (TH1*)result->Clone(namedvarDown);
1670 if (hunc){
1671 resultVariedUp->Add(hunc, 1.0); resultVariedUp->SetDirectory(0);
1672 resultVariedDown->Add(hunc, -1.0); resultVariedDown->SetDirectory(0);
1673 } else {
1674 resultVariedUp->SetDirectory(0);
1675 resultVariedDown->SetDirectory(0);
1676 }
1677 p.first = resultVariedUp;
1678 p.second = resultVariedDown;
1679 } // End of uncertainty in flavour loop
1680
1681 // Now handle the extrapolation uncertainties per flavour...
1682 // Refinement: add the "extrapolation" uncertainty as a named uncertainty, if the histogram is provided
1683 // This is a bit special, since the extrapolation uncertainty histogram has a different size than other histograms
1684 if (TH1* hunc = (TH1*)c->GetValue("extrapolation")) { // this is just saying "if it exists"...
1685 TH1* resultVariedUp = (TH1*) hunc->Clone("extrapolation_up"); resultVariedUp->SetDirectory(0);
1686 TH1* resultVariedDown = (TH1*) hunc->Clone("extrapolation_down"); resultVariedDown->SetDirectory(0);
1687 Int_t nbinx = hunc->GetNbinsX()+2, nbiny = hunc->GetNbinsY()+2, nbinz = hunc->GetNbinsZ()+2;
1688 Int_t firstbinx = hunc->GetXaxis()->FindFixBin(result->GetXaxis()->GetBinCenter(1));
1689 Int_t firstbiny = result->GetDimension() > 1 ? hunc->GetYaxis()->FindFixBin(result->GetYaxis()->GetBinCenter(1)) : 1;
1690 Int_t firstbinz = result->GetDimension() > 2 ? hunc->GetZaxis()->FindFixBin(result->GetZaxis()->GetBinCenter(1)) : 1;
1691 for (Int_t binx = 1; binx < nbinx-1; ++binx) {
1692 Int_t binxResult = binx - firstbinx + 1;
1693 if (binxResult < 1) binxResult = 1;
1694 if (binxResult > result->GetNbinsX()) binxResult = result->GetNbinsX();
1695 for (Int_t biny = 1; biny < nbiny-1; ++biny) {
1696 Int_t binyResult = biny - firstbiny + 1;
1697 if (binyResult > result->GetNbinsY()) binyResult = result->GetNbinsY();
1698 for (Int_t binz = 1; binz < nbinz-1; ++binz) {
1699 Int_t binzResult = binz - firstbinz + 1;
1700 if (binzResult > result->GetNbinsZ()) binzResult = result->GetNbinsZ();
1701 Int_t bin = hunc->GetBin(binx, biny, binz);
1702 double contResult = result->GetBinContent(binxResult, binyResult, binzResult);
1703 resultVariedUp->SetBinContent(bin, contResult + hunc->GetBinContent(bin));
1704 resultVariedDown->SetBinContent(bin, contResult - hunc->GetBinError(bin));
1705 }
1706 }
1707 }
1708 m_flav_named[flavour].push_back(std::make_pair(resultVariedUp, resultVariedDown));
1709 m_flav_namedExtrapolation[flavour] = m_flav_namedIndices[flavour]["extrapolation"] = m_flav_named[flavour].size()-1;
1710 }
1711
1712
1713 } // End flavour loop
1714
1715
1716
1717 // Third step: compute the eigenvector variations corresponding to the remaining sources of uncertainty
1718 // First, build the combined_result vector into a TH1
1719 std::unique_ptr<TH1> comb_result(new TH1D("combined_result", "", combined_result.size(), 0., 1.));
1720 int nbins = comb_result->GetNbinsX()+2;
1721 int ndim = comb_result->GetDimension();
1722 if (ndim > 1) nbins*= (comb_result->GetNbinsY()+2);
1723 if (ndim > 2) nbins*= (comb_result->GetNbinsZ()+2);
1724
1725 // I want to take the contents of "combined_result" and fill in "comb_result" without the under/overflow
1726 for (unsigned int i=0 ; i<combined_result.size() ; i++){
1727 // assuming dimension == 1, which should be the case...
1728 comb_result->SetBinContent(i+1, combined_result[i]); // setting i+1 so we don't start with the underflow bin
1729 }
1730
1731 // Get the portions of the covariance matrix that aren't zero, this next step
1732 TMatrixT<double> matrixVariationJacobian = getJacobianReductionMatrix(cov); // we pass the covariance matrix in as a starting point
1733
1734 int size = matrixVariationJacobian.GetNrows();
1735
1736 // Reduce the matrix to one without the zeros, using a "similarity" transformation
1737 const TMatrixDSym matrixCovariance = cov.Similarity(matrixVariationJacobian); // <--- This step removes the zeros
1738
1739 // Carry out the Eigenvector decomposition on this matrix
1740 TMatrixDSymEigen eigenValueMaker (matrixCovariance);
1741 TVectorT<double> eigenValues = eigenValueMaker.GetEigenValues();
1742 TMatrixT<double> eigenVectors = eigenValueMaker.GetEigenVectors();
1743 TMatrixT<double> matrixVariations (size,size);
1744
1745 //compute the total variance by summing the eigenvalues
1746 m_totalvariance = eigenValues.Sum();
1747
1748 for (int i = 0; i < size; ++i) {
1749 for (int r = 0; r < size; ++r) {
1750 //first index is the variation number, second corresponds to the pT bin // The "eigenvariations" matrix is the "C" matrix which has CKC^T = I with "K" being the o.g. covariance matrix, and "I" is the identity.
1751 matrixVariations(i,r) = -1.0*eigenVectors[r][i]*sqrt(fabs(eigenValues[i])); // So the result is a matrix (eigenvariation) which is the eigenvector scaled by the sqrt(eigenvalue)
1752 }
1753 } // <------- matrixVariations: each row is one variation, each column is the pT bin.
1754
1755 TMatrixT<double> matrixVariationsWithZeros = matrixVariations * matrixVariationJacobian; // This step adds in the zero rows again
1756
1757 // Construct the initial set of variations from this
1758 for (int i = 0; i < matrixVariationsWithZeros.GetNrows(); ++i) {
1759 TString superstring("eigenVar");
1760 superstring+=i;
1761
1762 TString nameUp(superstring); nameUp += "_up"; // In the end you get something like "eigenVar5_up"
1763 TString nameDown(superstring); nameDown += "_down";
1764 // TString nameUnc(superstring); nameUnc+= "_unc";
1765
1766 TH1* resultVariedUp = (TH1*)comb_result->Clone(nameUp); resultVariedUp->SetDirectory(0);
1767 TH1* resultVariedDown = (TH1*)comb_result->Clone(nameDown); resultVariedDown->SetDirectory(0);
1768
1769 for (int u = 0; u < comb_result->GetNbinsX(); ++u) {
1770 resultVariedUp->SetBinContent(u,(comb_result->GetBinContent(u) + matrixVariationsWithZeros(i,u)));
1771 resultVariedDown->SetBinContent(u,(comb_result->GetBinContent(u) - matrixVariationsWithZeros(i,u)));
1772 }
1773
1774 m_eigen.push_back(std::make_pair(resultVariedUp, resultVariedDown)); //<--- This is currently storing the FULL/combined variations, which aren't binned with proper bin widths etc.
1775 // The "proper binning" isn't necessary for pruning purposes. Later on, after pruning, separate the flavour blocks of each eigenvariation and construct the variations for each flavour, storing results in m_flav_eigen
1776
1777 } //end eigenvector size
1778
1779
1781 // Without any changes, all eigenvariations are kept due to the variation being non-negligible for SOME flavour...
1783 // Step 4 : Time for PRUNING
1784 // > Check the variation bins to see if any exceed a given threshold value of "min_variance"
1785 // > Value of E-6 seems to work well for SFGlobalEigen (found through a scan of possible thresholds)
1786 // but this is not necessarily going to hold for future CDI's. This needs to be checked through the
1787 // "validate_reduction" function, which can be used to compare how well the reduction captures the total covariance.
1789
1790 // Remove variations that are below the given tolerance (effectively meaning that they don't have any effect)
1791 IndexSet final_set;
1792 size_t current_set = 0;
1793
1794 // We set the custom min_variance here
1795 min_variance = 1.0E-6;
1796 for (size_t index = 0; index < m_eigen.size(); ++index) {
1797 bool keep_variation = false; // guilty until proven innocent
1798 TH1* up = static_cast<TH1*>(m_eigen[index].first->Clone()); up->SetDirectory(0); // clone the up variation and check it out
1799 up->Add(comb_result.get(), -1.0); // now we're left with decimal values centered around 0, i.e. 0.02 or -0.02
1800
1801 for (int bin = 1; bin <= nbins; ++bin) {
1802 if (fabs(up->GetBinContent(bin)) > min_variance) { // If you find even ONE bin with big enough variance, we keep the whole systematic.
1803 keep_variation = true;
1804 break;
1805 }
1806 }
1807 if (!keep_variation){ // At this stage, if we find no bins in the systematic with large enough variation, we insert it to "final_set" for removal/pruning
1808 final_set.insert(current_set);
1809 } else {
1810 m_capturedvariance += eigenValues[index];
1811 }
1812 delete up;
1813 ++current_set;
1814 }
1815 if (final_set.size() > 0){ // at this point, a set of the indices of negligible variations should have been gathered, proceed to remove them...
1816 if (m_verbose) std::cout << "CalibrationDataEigenVariations: Removing " << final_set.size() << " eigenvector variations leading to sub-tolerance effects, retaining " << m_eigen.size()-final_set.size() << " variations" << std::endl;
1817 }
1818
1819 CalibrationDataEigenVariations::removeVariations(final_set); // This method actually performs the reduction. The above logic simply flags which variations to get rid of, inserting them into "final_set"
1820
1821 // AT THIS STAGE: Pruning has already occurred, leaving us with a set of combined eigenvariations in "m_eigen", which we can thence recombine and compute the correlation matrix
1822 // That correlation matrix can then be compared to the original correlation matrix "corr", simply subtracting one from the other. Better approximations will have close to zero deviation.
1823 // What follows is the construction of this comparison, and the reporting of the comparison (saving it to file)...
1824 std::streamsize ss = std::cout.precision();
1825 if (m_verbose) std::cout << " The total variance is " << m_totalvariance << " and the reduction captured " << std::setprecision(9) << 100.0*(m_capturedvariance/m_totalvariance) << "% of this." << std::endl;
1826 std::cout.precision(ss); //restore precision
1830 if (m_validate){ // <---- this flag can be set manually in a local checkout of this package (temporary fix)
1831 validate_reduction(m_blockmatrixsize, corr, m_eigen, comb_result.get(), "SFGlobalEigen", m_taggername, m_wp, m_jetauthor); // This method is simply here to report the matrix comparison, for reduction scheme validation
1832 }
1833
1834
1836 // Let's separate out the flavour histograms now, this should be far simpler to ensure the binning is correct for each flavour.
1837 // At this stage, we should have constructed a set of combined eigenvariations stored in m_eigen.
1838 // Below, we take them one by one, separate, and store the flavour variations in m_flav_eigen, with the proper flavour heading
1839 // <----- The "mergeVariations" code originally merged the variations in m_eigen. But now that wouldn't work, since m_eigen stores
1840 // the combined histograms. We should instead merge the "reported" flavour histograms, as they're properly binned (and physically meaningful)
1841 // So if we construct the flavour variations first, keeping the indices all the same, then merge them.
1843
1844
1845 for(const std::pair<TH1*,TH1*>& var : m_eigen){
1846 // now we make use of the same old flavour loop and impose the flavour variation to the flavour container
1847 TString eigenvarup = var.first->GetName();
1848 TString eigenvardown = var.second->GetName();
1849 int bin_baseline = 0; // increment this by flav_bins after getting each flavour block
1850 for (const std::string& flavour : m_flavours){
1851 Analysis::CalibrationDataHistogramContainer* c = m_histcontainers[flavour];
1852 TH1* result = dynamic_cast<TH1*>(c->GetValue("result"));
1853 if (not result){
1854 std::cerr<<"CalibrationDataGlobalEigenVariations::initialize: dynamic cast failed\n";
1855 continue;
1856 }
1857 TH1* resultVariedUp = (TH1*)result->Clone(eigenvarup); resultVariedUp->SetDirectory(0); // copy flavour result, want to set bin contents according to the combined eigenvartion flavour block
1858 TH1* resultVariedDown = (TH1*)result->Clone(eigenvardown); resultVariedDown->SetDirectory(0);
1859 int up_to_bin = flav_bins[flavour];
1860 int current_bin = 1; // starting from 1 for filling histograms
1861 for(int flav_bin = bin_baseline+1 ; flav_bin < up_to_bin+1 ; flav_bin++){ // the +1's here are to deal with bin numbering yet again...
1862 Int_t bin = result->GetBin(1,current_bin); // increment along smaller (result) flavour variation TH1
1863 resultVariedUp->SetBinContent(bin, var.first->GetBinContent(flav_bin)); // Sets the result TH1 bin content to the eigenvariation bin content
1864 resultVariedDown->SetBinContent(bin, var.second->GetBinContent(flav_bin)); // In this way, we achieve flavour variations with proper binning
1865 current_bin+=1;
1866 }
1867 bin_baseline+=up_to_bin;
1868 m_flav_eigen[flavour].push_back(std::make_pair(resultVariedUp, resultVariedDown)); // <-------- add the flavour EV to the storage (indexed the same as in m_eigen!)
1869 }
1870 }
1871
1872 for(const auto& f : m_flavours){
1873 if (m_verbose) std::cout << " " << f << " m_flav_eigen has " << m_flav_eigen[f].size() << std::endl;
1874 }
1875
1876 m_initialized = true;
1877}
static Double_t ss
void removeVariations(const IndexSet &set)
remove all variations in the given set
TMatrixDSym getEigenCovarianceMatrix()
also provide (some) access to the underlying information: covariance matrix corresponding to eigenvec...
int r
Definition globals.cxx:22
str index
Definition DeMoScan.py:362

◆ isExtrapolationVariation() [1/2]

bool CalibrationDataEigenVariations::isExtrapolationVariation ( unsigned int nameIndex) const
inherited

flag whether the given index corresponds to an extrapolation variation

Definition at line 1103 of file CalibrationDataEigenVariations.cxx.

1104{
1105 // Verifies whether the given named variation index corresponds to the extrapolation
1106 // uncertainty.
1107
1108 return (m_namedExtrapolation == int(nameIndex));
1109}

◆ isExtrapolationVariation() [2/2]

bool CalibrationDataGlobalEigenVariations::isExtrapolationVariation ( unsigned int nameIndex,
const std::string & flavour ) const

Definition at line 2041 of file CalibrationDataEigenVariations.cxx.

2042{
2043 // Verifies whether the given named variation index corresponds to the extrapolation
2044 // uncertainty.
2045 int extrapIndex = m_flav_namedExtrapolation.find(flavour)->second;
2046 return (extrapIndex == int(nameIndex));
2047}

◆ listNamedVariations() [1/2]

vector< string > CalibrationDataEigenVariations::listNamedVariations ( ) const
inherited

list the named variations

Definition at line 1001 of file CalibrationDataEigenVariations.cxx.

1002{
1003 // Provides the list of named variations
1004
1005 vector<string> names;
1006 for (map<string, unsigned int>::const_iterator it = m_namedIndices.begin(); it != m_namedIndices.end(); ++it){
1007 names.push_back(it->first);
1008 }
1009 return names;
1010}

◆ listNamedVariations() [2/2]

std::vector< std::string > CalibrationDataGlobalEigenVariations::listNamedVariations ( const std::string & flavour) const

Definition at line 1552 of file CalibrationDataEigenVariations.cxx.

1553{
1554 // Provides the list of named variations
1555
1556 std::vector<std::string> names;
1557 for(const auto& namedar : m_flav_namedIndices.find(flavour)->second){
1558 names.push_back(namedar.first);
1559 }
1560 return names;
1561}

◆ mergeVariations() [1/4]

void CalibrationDataEigenVariations::mergeVariations ( const IndexSet & set)
inherited

merge all variations in the given set

Definition at line 881 of file CalibrationDataEigenVariations.cxx.

882{
883 IndexSuperSet sset;
884 sset.insert(set);
885 mergeVariations(sset);
886}
void mergeVariations(const IndexSet &set)
merge all variations in the given set

◆ mergeVariations() [2/4]

void CalibrationDataEigenVariations::mergeVariations ( const IndexSuperSet & set)
inherited

merge all variations in any of the given sets

Definition at line 890 of file CalibrationDataEigenVariations.cxx.

891{
892 // check for overlap
894 for (IndexSuperSet::iterator set_it = set.begin(); set_it != set.end(); ++set_it) {
895 for (IndexSet::iterator subset_it = set_it->begin(); subset_it != set_it->end(); ++subset_it){
896 if (checker.count(*subset_it) == 0 && *subset_it <= m_eigen.size())
897 checker.insert(*subset_it);
898 else {
899 std::cerr << "Error in CalibrationDataEigenVariations::mergeVariations: \
900 IndexSets must not overlap and must lie between 1 and " << m_eigen.size() << ". Aborting!" << std::endl;
901 return;
902 }
903 }
904 }
905
906 // retrieve the central calibration
907 TH1 *result = static_cast<TH1*>(m_cnt->GetValue("result"));
908 IndexSet toDelete;
909 int nbins = result->GetNbinsX()+2;
910 int ndim = result->GetDimension();
911 if (ndim > 1) nbins *= (result->GetNbinsY()+2);
912 if (ndim > 2) nbins *= (result->GetNbinsZ()+2);
913
914 // TH1 *var_up_final = static_cast<TH1*>(result->Clone()),
915 // *var_down_final = static_cast<TH1*>(result->Clone());
916
917 // var_up_final->Reset();
918 // var_down_final->Reset();
919
920 // complex sum
921 for (IndexSuperSet::iterator set_it = set.begin(); set_it != set.end(); ++set_it) {
922 if (set_it->empty()) continue;
923
924 double sum_H_up = 0.0, sum_H_down = 0.0;
925 size_t lowest_index = *set_it->lower_bound(0);
926 TH1 *total_var_up = static_cast<TH1*>(m_eigen[lowest_index].first->Clone()),
927 *total_var_down = static_cast<TH1*>(m_eigen[lowest_index].second->Clone());
928 total_var_up->SetDirectory(0);
929 total_var_down->SetDirectory(0);
930
931 total_var_up->Reset();
932 total_var_down->Reset();
933
934 // sum all other variations
935 for (IndexSet::iterator subset_it = set_it->begin();
936 subset_it != set_it->end(); ++subset_it) {
937 size_t actual_index = *subset_it;
938
939 if (actual_index != lowest_index) toDelete.insert(*subset_it);
940
941 TH1 *partial_var_up = static_cast<TH1*>(m_eigen[actual_index].first->Clone()),
942 *partial_var_down = static_cast<TH1*>(m_eigen[actual_index].second->Clone());
943 partial_var_up->SetDirectory(0);
944 partial_var_down->SetDirectory(0);
945
946 partial_var_up->Add(result, -1.0); // <----- Is this correct? Should it be +1?
947 partial_var_down->Add(result, -1.0);
948 for (int i = 0; i < nbins; ++i) {
949 partial_var_down->SetBinContent(i, -1.0*partial_var_down->GetBinContent(i));
950 }
951
952 for (int u = 0; u < nbins; ++u) {
953 double sum_up = total_var_up->GetBinContent(u),
954 sum_down = total_var_down->GetBinContent(u);
955 for (int v = 0; v < nbins; ++v) {
956 sum_up += partial_var_up->GetBinContent(u)*partial_var_up->GetBinContent(v);
957 sum_H_up += partial_var_up->GetBinContent(u)*partial_var_up->GetBinContent(v);
958 sum_down += partial_var_down->GetBinContent(u)*partial_var_down->GetBinContent(v);
959 sum_H_down += partial_var_down->GetBinContent(u)*partial_var_down->GetBinContent(v);
960 }
961 total_var_up->SetBinContent(u, sum_up);
962 total_var_down->SetBinContent(u, sum_down);
963 }
964 delete partial_var_up;
965 delete partial_var_down;
966 }
967
968 // final part of complex summing
969 for (int i = 0; i < nbins; ++i) {
970 if (sum_H_up != 0.0)
971 total_var_up->SetBinContent(i, total_var_up->GetBinContent(i)/sqrt(sum_H_up));
972 else
973 total_var_up->SetBinContent(i, 0.0);
974 if (sum_H_down != 0.0)
975 total_var_down->SetBinContent(i, -1.0*total_var_down->GetBinContent(i)/sqrt(sum_H_down));
976 else
977 total_var_down->SetBinContent(i, 0.0);
978 }
979
980 total_var_up->Add(result);
981 total_var_down->Add(result);
982
983 m_eigen[lowest_index].first = total_var_up;
984 m_eigen[lowest_index].second = total_var_down;
985 }
986
987 removeVariations(toDelete);
988}
void set(const ELT &e, const element_type &x) const
Set the variable for one element.

◆ mergeVariations() [3/4]

Definition at line 2068 of file CalibrationDataEigenVariations.cxx.

2069{
2070 IndexSuperSet sset;
2071 sset.insert(set);
2072 mergeVariations(sset, flav);
2073}
void mergeVariations(const IndexSet &set, std::string &flav)

◆ mergeVariations() [4/4]

Definition at line 2078 of file CalibrationDataEigenVariations.cxx.

2079{
2081 // Merge the (flavour specific) eigenvariations, as stored in m_flav_eigen
2083
2084 // check for overlap
2086 for (IndexSuperSet::iterator set_it = set.begin(); set_it != set.end(); ++set_it) {
2087 for (IndexSet::iterator subset_it = set_it->begin(); subset_it != set_it->end(); ++subset_it){
2088 if (checker.count(*subset_it) == 0 && *subset_it <= m_flav_eigen[flav].size())
2089 checker.insert(*subset_it);
2090 else {
2091 std::cerr << "Error in CalibrationDataGlobalEigenVariations::mergeVariations: \
2092 IndexSets must not overlap and must lie between 1 and " << m_eigen.size() << ". Aborting!" << std::endl;
2093 return;
2094 }
2095 }
2096 }
2097
2098 std::string flavour = flav;
2099
2100 Analysis::CalibrationDataHistogramContainer* c = m_histcontainers[flavour];
2101
2102 TH1* result = dynamic_cast<TH1*>(c->GetValue("result"));
2103 if (not result){
2104 std::cerr << "Error in CalibrationDataGlobalEigenVariations::mergeVariations: failed dynamic cast\n";
2105 return;
2106 }
2107 // retrieve the central calibration
2108
2109 IndexSet toDelete;
2110 int nbins = result->GetNbinsX()+2;
2111 int ndim = result->GetDimension();
2112 if (ndim > 1) nbins *= (result->GetNbinsY()+2);
2113 if (ndim > 2) nbins *= (result->GetNbinsZ()+2);
2114
2115 // complex sum
2116 for (IndexSuperSet::iterator set_it = set.begin(); set_it != set.end(); ++set_it) {
2117 if (set_it->empty()) continue;
2118
2119 double sum_H_up = 0.0, sum_H_down = 0.0;
2120 size_t lowest_index = *set_it->lower_bound(0);
2121 TH1 *total_var_up = static_cast<TH1*>(m_flav_eigen[flavour][lowest_index].first->Clone());
2122 TH1 *total_var_down = static_cast<TH1*>(m_flav_eigen[flavour][lowest_index].second->Clone());
2123 total_var_up->SetDirectory(0);
2124 total_var_down->SetDirectory(0);
2125
2126 total_var_up->Reset();
2127 total_var_down->Reset();
2128
2129 // sum all other variations
2130 for (IndexSet::iterator subset_it = set_it->begin(); subset_it != set_it->end(); ++subset_it) {
2131 size_t actual_index = *subset_it;
2132
2133 if (actual_index != lowest_index) toDelete.insert(*subset_it); //
2134
2135 TH1 *partial_var_up = static_cast<TH1*>(m_flav_eigen[flavour][actual_index].first->Clone());
2136 TH1 *partial_var_down = static_cast<TH1*>(m_flav_eigen[flavour][actual_index].second->Clone());
2137 partial_var_up->SetDirectory(0);
2138 partial_var_down->SetDirectory(0);
2139
2140 partial_var_up->Add(result, -1.0);
2141 partial_var_down->Add(result, -1.0);
2142 for (int i = 0; i < nbins; ++i) {
2143 partial_var_down->SetBinContent(i, -1.0*partial_var_down->GetBinContent(i));
2144 }
2145
2146 for (int u = 0; u < nbins; ++u) {
2147 double sum_up = total_var_up->GetBinContent(u);
2148 double sum_down = total_var_down->GetBinContent(u);
2149 for (int v = 0; v < nbins; ++v) {
2150 sum_up += partial_var_up->GetBinContent(u)*partial_var_up->GetBinContent(v);
2151 sum_H_up += partial_var_up->GetBinContent(u)*partial_var_up->GetBinContent(v);
2152 sum_down += partial_var_down->GetBinContent(u)*partial_var_down->GetBinContent(v);
2153 sum_H_down += partial_var_down->GetBinContent(u)*partial_var_down->GetBinContent(v);
2154 }
2155 total_var_up->SetBinContent(u, sum_up);
2156 total_var_down->SetBinContent(u, sum_down);
2157 }
2158 delete partial_var_up;
2159 delete partial_var_down;
2160 }
2161
2162 // final part of complex summing
2163 for (int i = 0; i < nbins; ++i) {
2164 if (sum_H_up != 0.0)
2165 total_var_up->SetBinContent(i, total_var_up->GetBinContent(i)/sqrt(sum_H_up));
2166 else
2167 total_var_up->SetBinContent(i, 0.0);
2168 if (sum_H_down != 0.0)
2169 total_var_down->SetBinContent(i, -1.0*total_var_down->GetBinContent(i)/sqrt(sum_H_down));
2170 else
2171 total_var_down->SetBinContent(i, 0.0);
2172 }
2173
2174 total_var_up->Add(result);
2175 total_var_down->Add(result);
2176
2177 m_flav_eigen[flavour][lowest_index].first = total_var_up;
2178 m_flav_eigen[flavour][lowest_index].second = total_var_down;
2179 }
2180
2181 removeVariations(toDelete, flavour);
2182}
void removeVariations(const IndexSet &set, std::string &flav)

◆ mergeVariationsFrom() [1/2]

void CalibrationDataEigenVariations::mergeVariationsFrom ( const size_t & index)
inherited

merge all variations starting from the given index

Definition at line 867 of file CalibrationDataEigenVariations.cxx.

868{
869 // Merge all systematic variation starting from the given index.
870 // The resulting merged variation replaces the first entry in the list
871 // (i.e., the entry specified by the index).
872 IndexSet simple_set;
873
874 for (size_t it = index; it < m_eigen.size(); ++it)
875 simple_set.insert(it);
876 mergeVariations(simple_set);
877}

◆ mergeVariationsFrom() [2/2]

void CalibrationDataGlobalEigenVariations::mergeVariationsFrom ( const size_t & index,
std::string & flav )

Definition at line 2053 of file CalibrationDataEigenVariations.cxx.

2054{
2055 // Merge all systematic variation starting from the given index.
2056 // The resulting merged variation replaces the first entry in the list
2057 // (i.e., the entry specified by the index).
2058
2059 IndexSet simple_set;
2060
2061 for (size_t it = index; it < m_flav_eigen[flav].size(); ++it)
2062 simple_set.insert(it);
2063 mergeVariations(simple_set, flav);
2064}

◆ removeVariations() [1/4]

void CalibrationDataEigenVariations::removeVariations ( const IndexSet & set)
inherited

remove all variations in the given set

Definition at line 839 of file CalibrationDataEigenVariations.cxx.

840{
841 if (set.size() == 0) return;
842
843 std::vector<std::pair<TH1*, TH1*> > new_eigen;
844 for (size_t index = 0; index < m_eigen.size(); ++index){
845 if (set.count(index) == 0) new_eigen.push_back(m_eigen[index]);
846 else { delete m_eigen[index].first; delete m_eigen[index].second; }
847 }
848 m_eigen = std::move(new_eigen);
849}

◆ removeVariations() [2/4]

void CalibrationDataEigenVariations::removeVariations ( const IndexSuperSet & set)
inherited

remove all variations in any of the given sets

Definition at line 853 of file CalibrationDataEigenVariations.cxx.

854{
855 IndexSet simple_set;
856
857 for (IndexSuperSet::iterator set_it = set.begin(); set_it != set.end(); ++set_it) {
858 for (IndexSet::iterator subset_it = set_it->begin(); subset_it != set_it->end(); ++subset_it)
859 simple_set.insert(*subset_it);
860 }
861
862 removeVariations(simple_set);
863}

◆ removeVariations() [3/4]

Definition at line 2187 of file CalibrationDataEigenVariations.cxx.

2188{
2189 if (set.size() == 0) return;
2190 std::vector<std::pair<TH1*, TH1*> > new_eigen;
2191 std::vector<std::pair<TH1*, TH1*>> eigen = m_flav_eigen[flav];
2192 for (size_t index = 0; index < eigen.size(); ++index){
2193 if (set.count(index) == 0) {
2194 new_eigen.push_back(eigen[index]);
2195 } else {
2196 delete eigen[index].first; delete eigen[index].second;
2197 }
2198 }
2199
2200 m_flav_eigen[flav] = std::move(new_eigen);
2201
2202}

◆ removeVariations() [4/4]

Definition at line 2206 of file CalibrationDataEigenVariations.cxx.

2207{
2208 IndexSet simple_set;
2209
2210 for (IndexSuperSet::iterator set_it = set.begin(); set_it != set.end(); ++set_it) {
2211 for (IndexSet::iterator subset_it = set_it->begin(); subset_it != set_it->end(); ++subset_it)
2212 simple_set.insert(*subset_it);
2213 }
2214
2215 removeVariations(simple_set, flav);
2216}

◆ setVerbose()

void CalibrationDataEigenVariations::setVerbose ( bool verbose)
inherited

Definition at line 1255 of file CalibrationDataEigenVariations.cxx.

1255 {
1257}
bool verbose
Definition hcg.cxx:75

Member Data Documentation

◆ m_all_shared_systematics

◆ m_blockmatrixsize

◆ m_capturedvariance

double Analysis::CalibrationDataEigenVariations::m_capturedvariance
protectedinherited

Definition at line 137 of file CalibrationDataEigenVariations.h.

◆ m_cdipath

std::string Analysis::CalibrationDataEigenVariations::m_cdipath
protectedinherited

@ data members needed for eigenvector method

the map stores the int which is needed to access the other vector<> objects

Definition at line 129 of file CalibrationDataEigenVariations.h.

◆ m_cnt

CalibrationDataHistogramContainer* Analysis::CalibrationDataEigenVariations::m_cnt
privateinherited

container object containing the basic information

Definition at line 100 of file CalibrationDataEigenVariations.h.

◆ m_eigen

std::vector<std::pair<TH1*, TH1*> > Analysis::CalibrationDataEigenVariations::m_eigen
protectedinherited

eigenvector variations

Definition at line 116 of file CalibrationDataEigenVariations.h.

◆ m_flav_eigen

std::map<std::string, std::vector<std::pair<TH1*, TH1*> > > Analysis::CalibrationDataGlobalEigenVariations::m_flav_eigen
private

Definition at line 189 of file CalibrationDataEigenVariations.h.

◆ m_flav_named

std::map<std::string, std::vector<std::pair<TH1*,TH1*> > > Analysis::CalibrationDataGlobalEigenVariations::m_flav_named
private

Definition at line 187 of file CalibrationDataEigenVariations.h.

◆ m_flav_namedExtrapolation

◆ m_flav_namedIndices

std::map<std::string, std::map<std::string, unsigned int> > Analysis::CalibrationDataGlobalEigenVariations::m_flav_namedIndices
private

Definition at line 186 of file CalibrationDataEigenVariations.h.

◆ m_flavour_combinations

std::map<std::string, std::vector<int> > Analysis::CalibrationDataGlobalEigenVariations::m_flavour_combinations
private

Definition at line 183 of file CalibrationDataEigenVariations.h.

◆ m_flavours

Definition at line 190 of file CalibrationDataEigenVariations.h.

◆ m_histcontainers

◆ m_initialized

bool Analysis::CalibrationDataEigenVariations::m_initialized
protectedinherited

flag whether the initialization has been carried out

Definition at line 105 of file CalibrationDataEigenVariations.h.

◆ m_jetauthor

std::string Analysis::CalibrationDataEigenVariations::m_jetauthor
protectedinherited

Definition at line 132 of file CalibrationDataEigenVariations.h.

◆ m_named

std::vector<std::pair<TH1*, TH1*> > Analysis::CalibrationDataEigenVariations::m_named
protectedinherited

Definition at line 110 of file CalibrationDataEigenVariations.h.

◆ m_namedExtrapolation

int Analysis::CalibrationDataEigenVariations::m_namedExtrapolation
protectedinherited

named variation index for the special case of extrapolation uncertainties

Definition at line 113 of file CalibrationDataEigenVariations.h.

◆ m_namedIndices

std::map<std::string, unsigned int> Analysis::CalibrationDataEigenVariations::m_namedIndices
protectedinherited

named variations

Definition at line 109 of file CalibrationDataEigenVariations.h.

◆ m_only_shared_systematics

◆ m_statVariations

bool Analysis::CalibrationDataEigenVariations::m_statVariations
protectedinherited

indicate whether statistical uncertainties are stored as variations

Definition at line 119 of file CalibrationDataEigenVariations.h.

◆ m_taggername

std::string Analysis::CalibrationDataEigenVariations::m_taggername
protectedinherited

Definition at line 130 of file CalibrationDataEigenVariations.h.

◆ m_totalvariance

double Analysis::CalibrationDataEigenVariations::m_totalvariance
protectedinherited

Definition at line 136 of file CalibrationDataEigenVariations.h.

◆ m_validate

bool Analysis::CalibrationDataEigenVariations::m_validate
protectedinherited

Definition at line 106 of file CalibrationDataEigenVariations.h.

◆ m_verbose

bool Analysis::CalibrationDataEigenVariations::m_verbose
protectedinherited

Definition at line 139 of file CalibrationDataEigenVariations.h.

◆ m_wp

std::string Analysis::CalibrationDataEigenVariations::m_wp
protectedinherited

Definition at line 131 of file CalibrationDataEigenVariations.h.


The documentation for this class was generated from the following files: