Page MenuHomeHEPForge

No OneTemporary

diff --git a/src/Routines/SystematicRoutines.cxx b/src/Routines/SystematicRoutines.cxx
index a89fe2f..cf53d85 100755
--- a/src/Routines/SystematicRoutines.cxx
+++ b/src/Routines/SystematicRoutines.cxx
@@ -1,1492 +1,1493 @@
// Copyright 2016-2021 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret
/*******************************************************************************
* This file is part of NUISANCE.
*
* NUISANCE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NUISANCE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NUISANCE. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
#include "SystematicRoutines.h"
void SystematicRoutines::Init() {
fInputFile = "";
fInputRootFile = NULL;
fOutputFile = "";
fOutputRootFile = NULL;
fCovar = fCovarFree = NULL;
fCorrel = fCorrelFree = NULL;
fDecomp = fDecompFree = NULL;
fStrategy = "ErrorBands";
fRoutines.clear();
fRoutines.push_back("ErrorBands");
fCardFile = "";
fFakeDataInput = "";
fSampleFCN = NULL;
fAllowedRoutines = ("ErrorBands,PlotLimits");
};
SystematicRoutines::~SystematicRoutines(){};
SystematicRoutines::SystematicRoutines(int argc, char *argv[]) {
// Initialise Defaults
Init();
nuisconfig configuration = Config::Get();
// Default containers
std::string cardfile = "";
std::string maxevents = "-1";
int errorcount = 0;
int verbocount = 0;
std::vector<std::string> xmlcmds;
std::vector<std::string> configargs;
fNThrows = 250;
fStartThrows = 0;
fThrowString = "";
// Make easier to handle arguments.
std::vector<std::string> args = GeneralUtils::LoadCharToVectStr(argc, argv);
ParserUtils::ParseArgument(args, "-c", fCardFile, true);
ParserUtils::ParseArgument(args, "-o", fOutputFile, false, false);
ParserUtils::ParseArgument(args, "-n", maxevents, false, false);
ParserUtils::ParseArgument(args, "-f", fStrategy, false, false);
ParserUtils::ParseArgument(args, "-d", fFakeDataInput, false, false);
ParserUtils::ParseArgument(args, "-s", fStartThrows, false, false);
ParserUtils::ParseArgument(args, "-t", fNThrows, false, false);
ParserUtils::ParseArgument(args, "-p", fThrowString, false, false);
ParserUtils::ParseArgument(args, "-i", xmlcmds);
ParserUtils::ParseArgument(args, "-q", configargs);
ParserUtils::ParseCounter(args, "e", errorcount);
ParserUtils::ParseCounter(args, "v", verbocount);
ParserUtils::CheckBadArguments(args);
// Add extra defaults if none given
if (fCardFile.empty() and xmlcmds.empty()) {
NUIS_ABORT("No input supplied!");
}
if (fOutputFile.empty() and !fCardFile.empty()) {
fOutputFile = fCardFile + ".root";
NUIS_ERR(WRN, "No output supplied so saving it to: " << fOutputFile);
} else if (fOutputFile.empty()) {
NUIS_ABORT("No output file or cardfile supplied!");
}
// Configuration Setup =============================
// Check no comp key is available
if (Config::Get().GetNodes("nuiscomp").empty()) {
fCompKey = Config::Get().CreateNode("nuiscomp");
} else {
fCompKey = Config::Get().GetNodes("nuiscomp")[0];
}
if (!fCardFile.empty())
fCompKey.Set("cardfile", fCardFile);
if (!fOutputFile.empty())
fCompKey.Set("outputfile", fOutputFile);
if (!fStrategy.empty())
fCompKey.Set("strategy", fStrategy);
// Load XML Cardfile
configuration.LoadSettings(fCompKey.GetS("cardfile"), "");
// Add Config Args
for (size_t i = 0; i < configargs.size(); i++) {
configuration.OverrideConfig(configargs[i]);
}
if (maxevents.compare("-1")) {
configuration.OverrideConfig("MAXEVENTS=" + maxevents);
}
// Finish configuration XML
configuration.FinaliseSettings(fCompKey.GetS("outputfile") + ".xml");
// Add Error Verbo Lines
verbocount += Config::GetParI("VERBOSITY");
errorcount += Config::GetParI("ERROR");
std::cout << "[ NUISANCE ]: Setting VERBOSITY=" << verbocount << std::endl;
std::cout << "[ NUISANCE ]: Setting ERROR=" << errorcount << std::endl;
SETVERBOSITY(verbocount);
// Proper Setup
if (fStrategy.find("ErrorBands") != std::string::npos ||
fStrategy.find("MergeErrors") != std::string::npos) {
fOutputRootFile =
new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE");
}
// fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(),
// "RECREATE");
SetupSystematicsFromXML();
SetupCovariance();
SetupRWEngine();
SetupFCN();
GetCovarFromFCN();
// Run();
return;
};
void SystematicRoutines::SetupSystematicsFromXML() {
NUIS_LOG(FIT, "Setting up nuismin");
// Setup Parameters ------------------------------------------
std::vector<nuiskey> parkeys = Config::QueryKeys("parameter");
if (!parkeys.empty()) {
NUIS_LOG(FIT, "Number of parameters : " << parkeys.size());
}
for (size_t i = 0; i < parkeys.size(); i++) {
nuiskey key = parkeys.at(i);
// Check for type,name,nom
if (!key.Has("type")) {
NUIS_ABORT("No type given for parameter " << i);
} else if (!key.Has("name")) {
NUIS_ABORT("No name given for parameter " << i);
} else if (!key.Has("nominal")) {
NUIS_ABORT("No nominal given for parameter " << i);
}
// Get Inputs
std::string partype = key.GetS("type");
std::string parname = key.GetS("name");
double parnom = key.GetD("nominal");
double parlow = parnom - 1;
double parhigh = parnom + 1;
double parstep = 1;
// Override if state not given
if (!key.Has("state")) {
key.SetS("state", "FIX");
}
std::string parstate = key.GetS("state");
// Extra limits
if (key.Has("low")) {
parlow = key.GetD("low");
parhigh = key.GetD("high");
parstep = key.GetD("step");
NUIS_LOG(FIT, "Read " << partype << " : " << parname << " = " << parnom
<< " : " << parlow << " < p < " << parhigh << " : "
<< parstate);
} else {
NUIS_LOG(FIT, "Read " << partype << " : " << parname << " = " << parnom
<< " : " << parstate);
}
// Run Parameter Conversion if needed
if (parstate.find("ABS") != std::string::npos) {
parnom = FitBase::RWAbsToSigma(partype, parname, parnom);
parlow = FitBase::RWAbsToSigma(partype, parname, parlow);
parhigh = FitBase::RWAbsToSigma(partype, parname, parhigh);
parstep = FitBase::RWAbsToSigma(partype, parname, parstep);
} else if (parstate.find("FRAC") != std::string::npos) {
parnom = FitBase::RWFracToSigma(partype, parname, parnom);
parlow = FitBase::RWFracToSigma(partype, parname, parlow);
parhigh = FitBase::RWFracToSigma(partype, parname, parhigh);
parstep = FitBase::RWFracToSigma(partype, parname, parstep);
}
// Push into vectors
fParams.push_back(parname);
fTypeVals[parname] = FitBase::ConvDialType(partype);
fStartVals[parname] = parnom;
fCurVals[parname] = parnom;
fErrorVals[parname] = 0.0;
fStateVals[parname] = parstate;
bool fixstate = parstate.find("FIX") != std::string::npos;
fFixVals[parname] = fixstate;
fStartFixVals[parname] = fFixVals[parname];
fMinVals[parname] = parlow;
fMaxVals[parname] = parhigh;
fStepVals[parname] = parstep;
}
// Setup Samples ----------------------------------------------
std::vector<nuiskey> samplekeys = Config::QueryKeys("sample");
if (!samplekeys.empty()) {
NUIS_LOG(FIT, "Number of samples : " << samplekeys.size());
}
for (size_t i = 0; i < samplekeys.size(); i++) {
nuiskey key = samplekeys.at(i);
// Get Sample Options
std::string samplename = key.GetS("name");
std::string samplefile = key.GetS("input");
std::string sampletype = key.Has("type") ? key.GetS("type") : "DEFAULT";
double samplenorm = key.Has("norm") ? key.GetD("norm") : 1.0;
// Print out
NUIS_LOG(FIT, "Read sample info " << i << " : " << samplename << std::endl
<< "\t\t input -> " << samplefile << std::endl
<< "\t\t state -> " << sampletype << std::endl
<< "\t\t norm -> " << samplenorm);
// If FREE add to parameters otherwise continue
if (sampletype.find("FREE") == std::string::npos) {
continue;
}
// Form norm dial from samplename + sampletype + "_norm";
std::string normname = samplename + "_norm";
// Check normname not already present
if (fTypeVals.find(normname) != fTypeVals.end()) {
continue;
}
// Add new norm dial to list if its passed above checks
fParams.push_back(normname);
fTypeVals[normname] = kNORM;
fStateVals[normname] = sampletype;
fCurVals[normname] = samplenorm;
fErrorVals[normname] = 0.0;
fMinVals[normname] = 0.1;
fMaxVals[normname] = 10.0;
fStepVals[normname] = 0.5;
bool state = sampletype.find("FREE") == std::string::npos;
fFixVals[normname] = state;
fStartFixVals[normname] = state;
}
// Setup Fake Parameters -----------------------------
std::vector<nuiskey> fakekeys = Config::QueryKeys("fakeparameter");
if (!fakekeys.empty()) {
NUIS_LOG(FIT, "Number of fake parameters : " << fakekeys.size());
}
for (size_t i = 0; i < fakekeys.size(); i++) {
nuiskey key = fakekeys.at(i);
// Check for type,name,nom
if (!key.Has("name")) {
NUIS_ABORT("No name given for fakeparameter " << i);
} else if (!key.Has("nom")) {
NUIS_ABORT("No nominal given for fakeparameter " << i);
}
// Get Inputs
std::string parname = key.GetS("name");
double parnom = key.GetD("nom");
// Push into vectors
fFakeVals[parname] = parnom;
}
}
/*
Setup Functions
*/
//*************************************
void SystematicRoutines::SetupRWEngine() {
//*************************************
for (UInt_t i = 0; i < fParams.size(); i++) {
std::string name = fParams[i];
FitBase::GetRW()->IncludeDial(name, fTypeVals.at(name));
}
UpdateRWEngine(fStartVals);
return;
}
//*************************************
void SystematicRoutines::SetupFCN() {
//*************************************
NUIS_LOG(FIT, "Making the jointFCN");
if (fSampleFCN)
delete fSampleFCN;
fSampleFCN = new JointFCN(fOutputRootFile);
+ fSampleFCN->SetNParams(int(fParams.size()));
SetFakeData();
return;
}
//*************************************
void SystematicRoutines::SetFakeData() {
//*************************************
if (fFakeDataInput.empty())
return;
if (fFakeDataInput.compare("MC") == 0) {
NUIS_LOG(FIT, "Setting fake data from MC starting prediction.");
UpdateRWEngine(fFakeVals);
FitBase::GetRW()->Reconfigure();
fSampleFCN->ReconfigureAllEvents();
fSampleFCN->SetFakeData("MC");
UpdateRWEngine(fCurVals);
NUIS_LOG(FIT, "Set all data to fake MC predictions.");
} else {
fSampleFCN->SetFakeData(fFakeDataInput);
}
return;
}
//*****************************************
// Setup the parameter covariances from the FCN
void SystematicRoutines::GetCovarFromFCN() {
//*****************************************
NUIS_LOG(FIT, "Loading ParamPull objects from FCN to build covariance...");
// Make helperstring
std::ostringstream helperstr;
// Keep track of what is being thrown
std::map<std::string, std::string> dialthrowhandle;
// Get Covariance Objects from FCN
std::list<ParamPull *> inputpulls = fSampleFCN->GetPullList();
for (PullListConstIter iter = inputpulls.begin(); iter != inputpulls.end();
iter++) {
ParamPull *pull = (*iter);
if (pull->GetType().find("THROW") != std::string::npos) {
fInputThrows.push_back(pull);
fInputCovar.push_back(pull->GetFullCovarMatrix());
fInputDials.push_back(pull->GetDataHist());
NUIS_LOG(FIT, "Read ParamPull: " << pull->GetName() << " " << pull->GetType());
}
TH1D dialhist = pull->GetDataHist();
TH1D minhist = pull->GetMinHist();
TH1D maxhist = pull->GetMaxHist();
TH1I typehist = pull->GetDialTypes();
for (int i = 0; i < dialhist.GetNbinsX(); i++) {
std::string name = std::string(dialhist.GetXaxis()->GetBinLabel(i + 1));
dialthrowhandle[name] = pull->GetName();
// Add to Containers
// Set the starting values etc to the postfit
fParams.push_back(name);
fCurVals[name] = dialhist.GetBinContent(i + 1);
// Set the starting values to be nominal MC
fStartVals[name] = 0.0;
fMinVals[name] = minhist.GetBinContent(i + 1);
fMaxVals[name] = maxhist.GetBinContent(i + 1);
fStepVals[name] = 1.0;
fFixVals[name] = false;
fStartFixVals[name] = false;
fTypeVals[name] = typehist.GetBinContent(i + 1);
fStateVals[name] = "FREE," + pull->GetType();
// If we find the string
if (fCurVals.find(name) == fCurVals.end()) {
// Maker Helper
helperstr << std::string(16, ' ')
<< FitBase::ConvDialType(fTypeVals[name]) << " " << name
<< " " << fMinVals[name] << " " << fMaxVals[name] << " "
<< fStepVals[name] << " " << fStateVals[name] << std::endl;
}
}
}
// Check if no throws given
if (fInputThrows.empty()) {
NUIS_ERR(WRN, "No covariances given to nuissyst");
NUIS_ERR(WRN, "Pushing back an uncorrelated gaussian throw error for each "
"free parameter using step size");
for (UInt_t i = 0; i < fParams.size(); i++) {
std::string syst = fParams[i];
if (fFixVals[syst])
continue;
// Make Terms
std::string name = syst + "_pull";
std::ostringstream pullterm;
pullterm << "DIAL:" << syst << ";" << fStartVals[syst] << ";"
<< fStepVals[syst];
std::string type = "GAUSTHROW/NEUT";
// Push Back Pulls
ParamPull *pull = new ParamPull(name, pullterm.str(), type);
fInputThrows.push_back(pull);
fInputCovar.push_back(pull->GetFullCovarMatrix());
fInputDials.push_back(pull->GetDataHist());
// Print Whats added
NUIS_LOG(FIT, "Added ParamPull : " << name << " " << pullterm.str() << " "
<< type);
// Add helper string for future fits
helperstr << std::string(16, ' ') << "covar " << name << " "
<< pullterm.str() << " " << type << std::endl;
// Keep Track of Throws
dialthrowhandle[syst] = pull->GetName();
}
}
// Print Helper String
if (!helperstr.str().empty()) {
NUIS_LOG(FIT, "To remove these statements in future studies, add the lines "
"below to your card:");
// Can't use the logger properly because this can be multi-line. Use cout
// and added spaces to look better!
std::cout << helperstr.str();
sleep(2);
}
// Print Throw State
for (UInt_t i = 0; i < fParams.size(); i++) {
std::string syst = fParams[i];
if (dialthrowhandle.find(syst) != dialthrowhandle.end()) {
NUIS_LOG(FIT, "Dial " << i << ". " << setw(20) << syst << " = THROWing with "
<< dialthrowhandle[syst]);
} else {
NUIS_LOG(FIT, "Dial " << i << ". " << setw(20) << syst << " = is FIXED");
}
}
}
/*
Fitting Functions
*/
//*************************************
void SystematicRoutines::UpdateRWEngine(
std::map<std::string, double> &updateVals) {
//*************************************
for (UInt_t i = 0; i < fParams.size(); i++) {
std::string name = fParams[i];
if (updateVals.find(name) == updateVals.end())
continue;
FitBase::GetRW()->SetDialValue(name, updateVals.at(name));
}
FitBase::GetRW()->Reconfigure();
}
//*************************************
void SystematicRoutines::PrintState() {
//*************************************
NUIS_LOG(FIT, "------------");
// Count max size
int maxcount = 0;
for (UInt_t i = 0; i < fParams.size(); i++) {
maxcount = max(int(fParams[i].size()), maxcount);
}
// Header
NUIS_LOG(FIT, " # " << left << setw(maxcount) << "Parameter "
<< " = " << setw(10) << "Value"
<< " +- " << setw(10) << "Error"
<< " " << setw(8) << "(Units)"
<< " " << setw(10) << "Conv. Val"
<< " +- " << setw(10) << "Conv. Err"
<< " " << setw(8) << "(Units)");
// Parameters
for (UInt_t i = 0; i < fParams.size(); i++) {
std::string syst = fParams.at(i);
std::string typestr = FitBase::ConvDialType(fTypeVals[syst]);
std::string curunits = "(sig.)";
double curval = fCurVals[syst];
double curerr = fErrorVals[syst];
if (fStateVals[syst].find("ABS") != std::string::npos) {
curval = FitBase::RWSigmaToAbs(typestr, syst, curval);
curerr = (FitBase::RWSigmaToAbs(typestr, syst, curerr) -
FitBase::RWSigmaToAbs(typestr, syst, 0.0));
curunits = "(Abs.)";
} else if (fStateVals[syst].find("FRAC") != std::string::npos) {
curval = FitBase::RWSigmaToFrac(typestr, syst, curval);
curerr = (FitBase::RWSigmaToFrac(typestr, syst, curerr) -
FitBase::RWSigmaToFrac(typestr, syst, 0.0));
curunits = "(Frac)";
}
std::string convunits = "(" + FitBase::GetRWUnits(typestr, syst) + ")";
double convval = FitBase::RWSigmaToAbs(typestr, syst, curval);
double converr = (FitBase::RWSigmaToAbs(typestr, syst, curerr) -
FitBase::RWSigmaToAbs(typestr, syst, 0.0));
std::ostringstream curparstring;
curparstring << " " << setw(3) << left << i << ". " << setw(maxcount)
<< syst << " = " << setw(10) << curval << " +- " << setw(10)
<< curerr << " " << setw(8) << curunits << " " << setw(10)
<< convval << " +- " << setw(10) << converr << " " << setw(8)
<< convunits;
NUIS_LOG(FIT, curparstring.str());
}
NUIS_LOG(FIT, "------------");
double like = fSampleFCN->GetLikelihood();
NUIS_LOG(FIT, std::left << std::setw(46) << "Likelihood for JointFCN: " << like);
NUIS_LOG(FIT, "------------");
}
/*
Write Functions
*/
//*************************************
void SystematicRoutines::SaveResults() {
//*************************************
if (!fOutputRootFile)
fOutputRootFile =
new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE");
fOutputRootFile->cd();
SaveCurrentState();
}
//*************************************
void SystematicRoutines::SaveCurrentState(std::string subdir) {
//*************************************
NUIS_LOG(FIT, "Saving current full FCN predictions");
// Setup DIRS
TDirectory *curdir = gDirectory;
if (!subdir.empty()) {
TDirectory *newdir = (TDirectory *)gDirectory->mkdir(subdir.c_str());
newdir->cd();
}
FitBase::GetRW()->Reconfigure();
fSampleFCN->ReconfigureAllEvents();
fSampleFCN->Write();
// Change back to current DIR
curdir->cd();
return;
}
//*************************************
void SystematicRoutines::SaveNominal() {
//*************************************
if (!fOutputRootFile)
fOutputRootFile =
new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE");
fOutputRootFile->cd();
NUIS_LOG(FIT, "Saving Nominal Predictions (be cautious with this)");
FitBase::GetRW()->Reconfigure();
SaveCurrentState("nominal");
};
//*************************************
void SystematicRoutines::SavePrefit() {
//*************************************
if (!fOutputRootFile)
fOutputRootFile =
new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE");
fOutputRootFile->cd();
NUIS_LOG(FIT, "Saving Prefit Predictions");
UpdateRWEngine(fStartVals);
SaveCurrentState("prefit");
UpdateRWEngine(fCurVals);
};
/*
MISC Functions
*/
//*************************************
int SystematicRoutines::GetStatus() {
//*************************************
return 0;
}
//*************************************
void SystematicRoutines::SetupCovariance() {
//*************************************
// Remove covares if they exist
if (fCovar)
delete fCovar;
if (fCovarFree)
delete fCovarFree;
if (fCorrel)
delete fCorrel;
if (fCorrelFree)
delete fCorrelFree;
if (fDecomp)
delete fDecomp;
if (fDecompFree)
delete fDecompFree;
int NFREE = 0;
int NDIM = 0;
// Get NFREE from min or from vals (for cases when doing throws)
NDIM = fParams.size();
for (UInt_t i = 0; i < fParams.size(); i++) {
if (!fFixVals[fParams[i]])
NFREE++;
}
if (NDIM == 0)
return;
fCovar = new TH2D("covariance", "covariance", NDIM, 0, NDIM, NDIM, 0, NDIM);
if (NFREE > 0) {
fCovarFree = new TH2D("covariance_free", "covariance_free", NFREE, 0, NFREE,
NFREE, 0, NFREE);
}
// Set Bin Labels
int countall = 0;
int countfree = 0;
for (UInt_t i = 0; i < fParams.size(); i++) {
fCovar->GetXaxis()->SetBinLabel(countall + 1, fParams[i].c_str());
fCovar->GetYaxis()->SetBinLabel(countall + 1, fParams[i].c_str());
countall++;
if (!fFixVals[fParams[i]] and NFREE > 0) {
fCovarFree->GetXaxis()->SetBinLabel(countfree + 1, fParams[i].c_str());
fCovarFree->GetYaxis()->SetBinLabel(countfree + 1, fParams[i].c_str());
countfree++;
}
}
fCorrel = PlotUtils::GetCorrelationPlot(fCovar, "correlation");
fDecomp = PlotUtils::GetDecompPlot(fCovar, "decomposition");
if (NFREE > 0)
fCorrelFree = PlotUtils::GetCorrelationPlot(fCovarFree, "correlation_free");
if (NFREE > 0)
fDecompFree = PlotUtils::GetDecompPlot(fCovarFree, "decomposition_free");
return;
};
//*************************************
void SystematicRoutines::ThrowCovariance(bool uniformly) {
//*************************************
// Set fThrownVals to all values in currentVals
for (UInt_t i = 0; i < fParams.size(); i++) {
std::string name = fParams.at(i);
fThrownVals[name] = fCurVals[name];
}
for (PullListConstIter iter = fInputThrows.begin();
iter != fInputThrows.end(); iter++) {
ParamPull *pull = *iter;
pull->ThrowCovariance();
TH1D dialhist = pull->GetDataHist();
for (int i = 0; i < dialhist.GetNbinsX(); i++) {
std::string name = std::string(dialhist.GetXaxis()->GetBinLabel(i + 1));
if (fCurVals.find(name) != fCurVals.end()) {
fThrownVals[name] = dialhist.GetBinContent(i + 1);
}
}
// Reset throw in case pulls are calculated.
pull->ResetToy();
}
};
//*************************************
void SystematicRoutines::PlotLimits() {
//*************************************
std::cout << "Plotting Limits" << std::endl;
if (!fOutputRootFile)
fOutputRootFile =
new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE");
TDirectory *limfolder = (TDirectory *)fOutputRootFile->mkdir("Limits");
limfolder->cd();
// Set all parameters at their starting values
for (UInt_t i = 0; i < fParams.size(); i++) {
fCurVals[fParams[i]] = fStartVals[fParams[i]];
}
TDirectory *nomfolder = (TDirectory *)limfolder->mkdir("nominal");
nomfolder->cd();
UpdateRWEngine(fCurVals);
fSampleFCN->ReconfigureAllEvents();
fSampleFCN->Write();
limfolder->cd();
std::vector<std::string> allfolders;
// Loop through each parameter
for (UInt_t i = 0; i < fParams.size(); i++) {
std::string syst = fParams[i];
std::cout << "Starting Param " << syst << std::endl;
if (fFixVals[syst])
continue;
// Loop Downwards
while (fCurVals[syst] > fMinVals[syst]) {
fCurVals[syst] = fCurVals[syst] - fStepVals[syst];
// Check Limit
if (fCurVals[syst] < fMinVals[syst])
fCurVals[syst] = fMinVals[syst];
// Check folder exists
std::string curvalstring =
std::string(Form((syst + "_%f").c_str(), fCurVals[syst]));
if (std::find(allfolders.begin(), allfolders.end(), curvalstring) !=
allfolders.end())
break;
// Make new folder for variation
TDirectory *minfolder = (TDirectory *)limfolder->mkdir(
Form((syst + "_%f").c_str(), fCurVals[syst]));
minfolder->cd();
allfolders.push_back(curvalstring);
// Update Iterations
double *vals = FitUtils::GetArrayFromMap(fParams, fCurVals);
fSampleFCN->DoEval(vals);
delete vals;
// Save to folder
fSampleFCN->Write();
}
// Reset before next loop
fCurVals[syst] = fStartVals[syst];
// Loop Upwards now
while (fCurVals[syst] < fMaxVals[syst]) {
fCurVals[syst] = fCurVals[syst] + fStepVals[syst];
// Check Limit
if (fCurVals[syst] > fMaxVals[syst])
fCurVals[syst] = fMaxVals[syst];
// Check folder exists
std::string curvalstring =
std::string(Form((syst + "_%f").c_str(), fCurVals[syst]));
if (std::find(allfolders.begin(), allfolders.end(), curvalstring) !=
allfolders.end())
break;
// Make new folder
TDirectory *maxfolder = (TDirectory *)limfolder->mkdir(
Form((syst + "_%f").c_str(), fCurVals[syst]));
maxfolder->cd();
allfolders.push_back(curvalstring);
// Update Iterations
double *vals = FitUtils::GetArrayFromMap(fParams, fCurVals);
fSampleFCN->DoEval(vals);
delete vals;
// Save to file
fSampleFCN->Write();
}
// Reset before leaving
fCurVals[syst] = fStartVals[syst];
UpdateRWEngine(fCurVals);
}
return;
}
//*************************************
void SystematicRoutines::Run() {
//*************************************
fRoutines = GeneralUtils::ParseToStr(fStrategy, ",");
for (UInt_t i = 0; i < fRoutines.size(); i++) {
std::string routine = fRoutines.at(i);
int fitstate = kFitUnfinished;
NUIS_LOG(FIT, "Running Routine: " << routine);
if (routine.compare("PlotLimits") == 0)
PlotLimits();
else if (routine.compare("ErrorBands") == 0)
GenerateErrorBands();
else if (routine.compare("ThrowErrors") == 0)
GenerateThrows();
else if (routine.compare("MergeErrors") == 0)
MergeThrows();
else if (routine.compare("EigenErrors") == 0)
EigenErrors();
else {
NUIS_ABORT("Unknown ROUTINE : " << routine);
}
// If ending early break here
if (fitstate == kFitFinished || fitstate == kNoChange) {
NUIS_LOG(FIT, "Ending fit routines loop.");
break;
}
}
}
void SystematicRoutines::GenerateErrorBands() {
GenerateThrows();
MergeThrows();
}
//*************************************
void SystematicRoutines::GenerateThrows() {
//*************************************
TFile *tempfile =
new TFile((fOutputFile + ".throws.root").c_str(), "RECREATE");
tempfile->cd();
// For generating throws we check with the config
int nthrows = Config::GetParI("error_throws");
int startthrows = fStartThrows;
int endthrows = startthrows + nthrows;
if (nthrows < 0)
nthrows = endthrows;
if (startthrows < 0)
startthrows = 0;
if (endthrows < 0)
endthrows = startthrows + nthrows;
// Setting Seed
// Matteo Mazzanti's Fix
struct timeval mytime;
gettimeofday(&mytime, NULL);
Double_t seed = time(NULL) + int(getpid()) + (mytime.tv_sec * 1000.) +
(mytime.tv_usec / 1000.);
gRandom->SetSeed(seed);
// int seed = (gRandom->Uniform(0.0,1.0)*100000 + 100000000*(startthrows +
// endthrows) + time(NULL) + int(getpid()) ); gRandom->SetSeed(seed);
NUIS_LOG(FIT, "Using Seed : " << seed);
NUIS_LOG(FIT, "nthrows = " << nthrows);
NUIS_LOG(FIT, "startthrows = " << startthrows);
NUIS_LOG(FIT, "endthrows = " << endthrows);
UpdateRWEngine(fStartVals);
fSampleFCN->ReconfigureAllEvents();
// Make the nominal
if (startthrows == 0) {
NUIS_LOG(FIT, "Making nominal ");
TDirectory *nominal = (TDirectory *)tempfile->mkdir("nominal");
nominal->cd();
fSampleFCN->Write();
// Make the postfit reading from the pull
NUIS_LOG(FIT, "Making postfit ");
TDirectory *postfit = (TDirectory *)tempfile->mkdir("postfit");
postfit->cd();
UpdateRWEngine(fCurVals);
fSampleFCN->ReconfigureSignal();
fSampleFCN->Write();
}
fSampleFCN->CreateIterationTree("error_iterations", FitBase::GetRW());
// Would anybody actually want to do uniform throws of any parameter??
bool uniformly = FitPar::Config().GetParB("error_uniform");
// Run Throws and save
for (Int_t i = 0; i < endthrows + 1; i++) {
// Generate Random Parameter Throw
ThrowCovariance(uniformly);
if (i < startthrows)
continue;
if (i == 0)
continue;
NUIS_LOG(FIT, "Throw " << i << "/" << endthrows
<< " ================================");
TDirectory *throwfolder =
(TDirectory *)tempfile->mkdir(Form("throw_%i", i));
throwfolder->cd();
// Run Eval
double *vals = FitUtils::GetArrayFromMap(fParams, fThrownVals);
fSampleFCN->DoEval(vals);
delete vals;
// Save the FCN
fSampleFCN->Write();
}
tempfile->cd();
fSampleFCN->WriteIterationTree();
tempfile->Close();
}
// Merge throws together into one summary
void SystematicRoutines::MergeThrows() {
fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE");
fOutputRootFile->cd();
// Make a container folder
TDirectory *errorDIR = (TDirectory *)fOutputRootFile->mkdir("error_bands");
errorDIR->cd();
TDirectory *outnominal =
(TDirectory *)fOutputRootFile->mkdir("nominal_throw");
outnominal->cd();
// Split Input Files
if (!fThrowString.empty())
fThrowList = GeneralUtils::ParseToStr(fThrowString, ",");
// Add default if no throwlist given
if (fThrowList.size() < 1)
fThrowList.push_back(fOutputFile + ".throws.root");
/// Save location of file containing nominal
std::string nominalfile;
bool nominalfound;
// Loop over files and check they exist.
for (uint i = 0; i < fThrowList.size(); i++) {
std::string file = fThrowList[i];
bool found = false;
// normal
std::string newfile = file;
TFile *throwfile = new TFile(file.c_str(), "READ");
if (throwfile and !throwfile->IsZombie()) {
found = true;
}
// normal.throws.root
if (!found) {
newfile = file + ".throws.root";
throwfile = new TFile((file + ".throws.root").c_str(), "READ");
if (throwfile and !throwfile->IsZombie()) {
found = true;
}
}
// If its found save to throwlist, else save empty.
// Also search for nominal
if (found) {
fThrowList[i] = newfile;
NUIS_LOG(FIT, "Throws File :" << newfile);
// Find input which contains nominal
if (throwfile->Get("nominal")) {
nominalfound = true;
nominalfile = newfile;
}
throwfile->Close();
} else {
fThrowList[i] = "";
}
delete throwfile;
}
// Make sure we have a nominal file
if (!nominalfound or nominalfile.empty()) {
NUIS_ABORT("No nominal found when merging! Exiting!");
}
// Get the nominal throws file
TFile *tempfile = new TFile((nominalfile).c_str(), "READ");
tempfile->cd();
TDirectory *nominal = (TDirectory *)tempfile->Get("nominal");
bool uniformly = FitPar::Config().GetParB("error_uniform");
// Check percentage of bad files is okay.
int badfilecount = 0;
for (uint i = 0; i < fThrowList.size(); i++) {
if (!fThrowList[i].empty()) {
NUIS_LOG(FIT, "Loading Throws From File " << i << " : " << fThrowList[i]);
} else {
badfilecount++;
}
}
// Check we have at least one good file
if ((uint)badfilecount == fThrowList.size()) {
NUIS_ABORT("Found no good throw files for MergeThrows");
throw;
} else if (badfilecount > (fThrowList.size() * 0.25)) {
NUIS_ERR(
WRN,
"Over 25% of your throw files are dodgy. Please check this is okay!");
NUIS_ERR(WRN, "Will continue for the time being...");
sleep(5);
}
// Now go through the keys in the temporary file and look for TH1D, and TH2D
// plots
TIter next(nominal->GetListOfKeys());
TKey *key;
while ((key = (TKey *)next())) {
TClass *cl = gROOT->GetClass(key->GetClassName());
if (!cl->InheritsFrom("TH1D") and !cl->InheritsFrom("TH2D"))
continue;
TH1 *baseplot = (TH1D *)key->ReadObj();
std::string plotname = std::string(baseplot->GetName());
NUIS_LOG(FIT, "Creating error bands for " << plotname);
if (LOG_LEVEL(FIT)) {
if (!uniformly) {
NUIS_LOG(FIT, " : Using COVARIANCE Throws! ");
} else {
NUIS_LOG(FIT, " : Using UNIFORM THROWS!!! ");
}
}
int nbins = 0;
if (cl->InheritsFrom("TH1D"))
nbins = ((TH1D *)baseplot)->GetNbinsX();
else
nbins = ((TH1D *)baseplot)->GetNbinsX() * ((TH1D *)baseplot)->GetNbinsY();
// Setup TProfile with RMS option
TProfile *tprof =
new TProfile((plotname + "_prof").c_str(), (plotname + "_prof").c_str(),
nbins, 0, nbins, "S");
// Setup The TTREE
double *bincontents;
bincontents = new double[nbins];
double *binlowest;
binlowest = new double[nbins];
double *binhighest;
binhighest = new double[nbins];
errorDIR->cd();
TTree *bintree =
new TTree((plotname + "_tree").c_str(), (plotname + "_tree").c_str());
for (Int_t i = 0; i < nbins; i++) {
bincontents[i] = 0.0;
binhighest[i] = 0.0;
binlowest[i] = 0.0;
bintree->Branch(Form("content_%i", i), &bincontents[i],
Form("content_%i/D", i));
}
// Make new throw plot
TH1 *newplot;
// Run Throw Merging.
for (UInt_t i = 0; i < fThrowList.size(); i++) {
TFile *throwfile = new TFile(fThrowList[i].c_str(), "READ");
// Loop over all throws in a folder
TIter nextthrow(throwfile->GetListOfKeys());
TKey *throwkey;
while ((throwkey = (TKey *)nextthrow())) {
// Skip non throw folders
if (std::string(throwkey->GetName()).find("throw_") ==
std::string::npos)
continue;
// Get Throw DIR
TDirectory *throwdir = (TDirectory *)throwkey->ReadObj();
// Get Plot From Throw
newplot = (TH1 *)throwdir->Get(plotname.c_str());
if (!newplot)
continue;
// Loop Over Plot
for (Int_t j = 0; j < nbins; j++) {
tprof->Fill(j + 0.5, newplot->GetBinContent(j + 1));
bincontents[j] = newplot->GetBinContent(j + 1);
if (bincontents[j] < binlowest[j] or i == 0)
binlowest[j] = bincontents[j];
if (bincontents[j] > binhighest[j] or i == 0)
binhighest[j] = bincontents[j];
}
errorDIR->cd();
bintree->Fill();
}
throwfile->Close();
delete throwfile;
}
errorDIR->cd();
if (uniformly) {
NUIS_LOG(FIT, "Uniformly Calculating Plot Errors!");
}
TH1 *statplot = (TH1 *)baseplot->Clone();
for (Int_t j = 0; j < nbins; j++) {
if (!uniformly) {
// if ((baseplot->GetBinError(j+1)/baseplot->GetBinContent(j+1))
//< 1.0) {
// baseplot->SetBinError(j+1,sqrt(pow(tprof->GetBinError(j+1),2)
//+ pow(baseplot->GetBinError(j+1),2))); } else {
baseplot->SetBinContent(j + 1, tprof->GetBinContent(j + 1));
baseplot->SetBinError(j + 1, tprof->GetBinError(j + 1));
// }
} else {
baseplot->SetBinContent(j + 1,
0.0); //(binlowest[j] + binhighest[j]) / 2.0);
baseplot->SetBinError(j + 1,
0.0); //(binhighest[j] - binlowest[j])/2.0);
}
}
baseplot->SetTitle("Profiled throws");
errorDIR->cd();
baseplot->Write();
tprof->Write();
bintree->Write();
outnominal->cd();
for (int i = 0; i < nbins; i++) {
baseplot->SetBinError(i + 1, sqrt(pow(statplot->GetBinError(i + 1), 2) +
pow(baseplot->GetBinError(i + 1), 2)));
}
baseplot->Write();
delete statplot;
delete baseplot;
delete tprof;
delete bintree;
delete[] bincontents;
}
fOutputRootFile->Write();
fOutputRootFile->Close();
};
void SystematicRoutines::EigenErrors() {
fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "RECREATE");
fOutputRootFile->cd();
// Make Covariance
TMatrixDSym *fullcovar = new TMatrixDSym(fParams.size());
// Extract covariance from all loaded ParamPulls
for (PullListConstIter iter = fInputThrows.begin();
iter != fInputThrows.end(); iter++) {
ParamPull *pull = *iter;
// Check pull is actualyl Gaussian
std::string pulltype = pull->GetType();
if (pulltype.find("GAUSTHROW") == std::string::npos) {
NUIS_ABORT("Can only calculate EigenErrors for Gaussian pulls!");
}
// Get data and covariances
TH1D dialhist = pull->GetDataHist();
TH2D covhist = pull->GetFullCovar();
// Loop over all dials and compare names
for (size_t pari = 0; pari < fParams.size(); pari++) {
for (size_t parj = 0; parj < fParams.size(); parj++) {
std::string name_pari = fParams[pari];
std::string name_parj = fParams[parj];
// Compare names to those in the pull
for (int pulli = 0; pulli < dialhist.GetNbinsX(); pulli++) {
for (int pullj = 0; pullj < dialhist.GetNbinsX(); pullj++) {
std::string name_pulli =
dialhist.GetXaxis()->GetBinLabel(pulli + 1);
std::string name_pullj =
dialhist.GetXaxis()->GetBinLabel(pullj + 1);
if (name_pulli == name_pari && name_pullj == name_parj) {
(*fullcovar)[pari][parj] =
covhist.GetBinContent(pulli + 1, pullj + 1);
fCurVals[name_pari] = dialhist.GetBinContent(pulli + 1);
fCurVals[name_parj] = dialhist.GetBinContent(pullj + 1);
}
}
}
}
}
}
/*
TFile* test = new TFile("testingcovar.root","RECREATE");
test->cd();
TH2D* joinedcov = new TH2D("COVAR","COVAR",
fullcovar->GetNrows(), 0.0, float(fullcovar->GetNrows()),
fullcovar->GetNrows(), 0.0, float(fullcovar->GetNrows()));
for (int i = 0; i < fullcovar->GetNrows(); i++){
for (int j = 0; j < fullcovar->GetNcols(); j++){
joinedcov->SetBinContent(i+1, j+1, (*fullcovar)[i][j]);
}
}
joinedcov->Write("COVAR");
test->Close();
*/
// Calculator all EigenVectors and EigenValues
TMatrixDSymEigen *eigen = new TMatrixDSymEigen(*fullcovar);
const TVectorD eigenVals = eigen->GetEigenValues();
const TMatrixD eigenVect = eigen->GetEigenVectors();
eigenVals.Print();
eigenVect.Print();
TDirectory *outnominal = (TDirectory *)fOutputRootFile->mkdir("nominal");
outnominal->cd();
// double *valst = FitUtils::GetArrayFromMap(fParams, fCurVals);
// double chi2 = fSampleFCN->DoEval( valst );
// delete valst;
fSampleFCN->Write();
// Loop over all throws
TDirectory *throwsdir = (TDirectory *)fOutputRootFile->mkdir("throws");
throwsdir->cd();
int count = 0;
// Produce all error throws.
for (int i = 0; i < eigenVect.GetNrows(); i++) {
TDirectory *throwfolder =
(TDirectory *)throwsdir->mkdir(Form("throw_%i", count));
throwfolder->cd();
// Get New Parameter Vector
NUIS_LOG(FIT, "Parameter Set " << count);
for (int j = 0; j < eigenVect.GetNrows(); j++) {
std::string param = fParams[j];
NUIS_LOG(FIT, " " << j << ". " << param << " : "
<< fCurVals[param] + sqrt(eigenVals[i]) * eigenVect[j][i]);
fThrownVals[param] =
fCurVals[param] + sqrt(eigenVals[i]) * eigenVect[j][i];
}
// Run Eval
double *vals = FitUtils::GetArrayFromMap(fParams, fThrownVals);
double chi2 = fSampleFCN->DoEval(vals);
NUIS_LOG(DEB, "Chi2 = " << chi2);
delete vals;
count++;
fSampleFCN->Write();
throwfolder = (TDirectory *)throwsdir->mkdir(Form("throw_%i", count));
throwfolder->cd();
// Get New Parameter Vector
NUIS_LOG(FIT, "Parameter Set " << count);
for (int j = 0; j < eigenVect.GetNrows(); j++) {
std::string param = fParams[j];
NUIS_LOG(FIT, " " << j << ". " << param << " : "
<< fCurVals[param] - sqrt(eigenVals[i]) * eigenVect[j][i]);
fThrownVals[param] =
fCurVals[param] - sqrt(eigenVals[i]) * eigenVect[j][i];
}
// Run Eval
double *vals2 = FitUtils::GetArrayFromMap(fParams, fThrownVals);
chi2 = fSampleFCN->DoEval(vals2);
NUIS_LOG(DEB, "Chi2 = " << chi2);
delete vals2;
count++;
// Save the FCN
fSampleFCN->Write();
}
fOutputRootFile->Close();
fOutputRootFile = new TFile(fCompKey.GetS("outputfile").c_str(), "UPDATE");
fOutputRootFile->cd();
throwsdir = (TDirectory *)fOutputRootFile->Get("throws");
outnominal = (TDirectory *)fOutputRootFile->Get("nominal");
// Loop through Error DIR
TDirectory *outerr = (TDirectory *)fOutputRootFile->mkdir("errors");
outerr->cd();
TIter next(outnominal->GetListOfKeys());
TKey *key;
while ((key = (TKey *)next())) {
TClass *cl = gROOT->GetClass(key->GetClassName());
if (!cl->InheritsFrom("TH1D") and !cl->InheritsFrom("TH2D"))
continue;
NUIS_LOG(FIT, "Creating error bands for " << key->GetName());
std::string plotname = std::string(key->GetName());
if (plotname.find("_EVT") != std::string::npos)
continue;
if (plotname.find("_FLUX") != std::string::npos)
continue;
if (plotname.find("_FLX") != std::string::npos)
continue;
TH1 *baseplot =
(TH1D *)key->ReadObj()->Clone(Form("%s_ORIGINAL", key->GetName()));
TH1 *errorplot_upper =
(TH1D *)baseplot->Clone(Form("%s_ERROR_UPPER", key->GetName()));
TH1 *errorplot_lower =
(TH1D *)baseplot->Clone(Form("%s_ERROR_LOWER", key->GetName()));
TH1 *meanplot =
(TH1D *)baseplot->Clone(Form("%s_SET_MEAN", key->GetName()));
TH1 *systplot = (TH1D *)baseplot->Clone(Form("%s_SYST", key->GetName()));
TH1 *statplot = (TH1D *)baseplot->Clone(Form("%s_STAT", key->GetName()));
TH1 *totlplot = (TH1D *)baseplot->Clone(Form("%s_TOTAL", key->GetName()));
int nbins = 0;
if (cl->InheritsFrom("TH1D"))
nbins = ((TH1D *)baseplot)->GetNbinsX();
else
nbins = ((TH1D *)baseplot)->GetNbinsX() * ((TH1D *)baseplot)->GetNbinsY();
meanplot->Reset();
errorplot_upper->Reset();
errorplot_lower->Reset();
for (int j = 0; j < nbins; j++) {
errorplot_upper->SetBinError(j + 1, 0.0);
errorplot_lower->SetBinError(j + 1, 0.0);
}
// Loop over throws and calculate mean and error for +- throws
int addcount = 0;
// Add baseplot first to slightly bias to central value
meanplot->Add(baseplot);
addcount++;
for (int i = 0; i < count; i++) {
TH1 *newplot =
(TH1D *)throwsdir->Get(Form("throw_%i/%s", i, plotname.c_str()));
if (!newplot) {
NUIS_ERR(WRN, "Cannot find new plot : " << Form("throw_%i/%s", i,
plotname.c_str()));
NUIS_ERR(WRN, "This plot will not have the correct errors!");
continue;
}
newplot->SetDirectory(0);
nbins = newplot->GetNbinsX();
for (int j = 0; j < nbins; j++) {
if (i % 2 == 0) {
errorplot_upper->SetBinContent(
j + 1, errorplot_upper->GetBinContent(j + 1) +
pow(baseplot->GetBinContent(j + 1) -
newplot->GetBinContent(j + 1),
2));
} else {
errorplot_lower->SetBinContent(
j + 1, errorplot_lower->GetBinContent(j + 1) +
pow(baseplot->GetBinContent(j + 1) -
newplot->GetBinContent(j + 1),
2));
}
meanplot->SetBinContent(j + 1, meanplot->GetBinContent(j + 1) +
baseplot->GetBinContent(j + 1));
}
delete newplot;
addcount++;
}
// Get mean Average
for (int j = 0; j < nbins; j++) {
meanplot->SetBinContent(j + 1, meanplot->GetBinContent(j + 1) /
double(addcount));
}
for (int j = 0; j < nbins; j++) {
errorplot_upper->SetBinContent(
j + 1, sqrt(errorplot_upper->GetBinContent(j + 1)));
errorplot_lower->SetBinContent(
j + 1, sqrt(errorplot_lower->GetBinContent(j + 1)));
statplot->SetBinError(j + 1, baseplot->GetBinError(j + 1));
systplot->SetBinError(j + 1, (errorplot_upper->GetBinContent(j + 1) +
errorplot_lower->GetBinContent(j + 1)) /
2.0);
totlplot->SetBinError(j + 1, sqrt(pow(statplot->GetBinError(j + 1), 2) +
pow(systplot->GetBinError(j + 1), 2)));
meanplot->SetBinError(j + 1, sqrt(pow(statplot->GetBinError(j + 1), 2) +
pow(systplot->GetBinError(j + 1), 2)));
}
outerr->cd();
errorplot_upper->Write();
errorplot_lower->Write();
baseplot->Write();
meanplot->Write();
statplot->Write();
systplot->Write();
totlplot->Write();
delete errorplot_upper;
delete errorplot_lower;
delete baseplot;
delete meanplot;
delete statplot;
delete systplot;
delete totlplot;
}
}

File Metadata

Mime Type
text/x-diff
Expires
Tue, Nov 19, 3:13 PM (1 d, 14 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3804922
Default Alt Text
(46 KB)

Event Timeline