#include <ctime>
#include <iostream>
#include <algorithm>
#include <sys/stat.h>
#include "TSystem.h"
#include "TTimeStamp.h"
#include "RooStats/HistFactory/Measurement.h"
#include "RooStats/HistFactory/HistFactoryException.h"
using namespace std;
ClassImp(RooStats::HistFactory::Measurement) ;
RooStats::HistFactory::Measurement::Measurement() :
fPOI(), fLumi( 1.0 ), fLumiRelErr( .10 ),
fBinLow( 0 ), fBinHigh( 1 ), fExportOnly( false )
{
}
RooStats::HistFactory::Measurement::Measurement(const char* Name, const char* Title) :
TNamed( Name, Title ),
fPOI(), fLumi( 1.0 ), fLumiRelErr( .10 ),
fBinLow( 0 ), fBinHigh( 1 ), fExportOnly( false )
{
}
void RooStats::HistFactory::Measurement::AddConstantParam( const std::string& param )
{
if( std::find(fConstantParams.begin(), fConstantParams.end(), param) != fConstantParams.end() ) {
std::cout << "Warning: Setting parameter: " << param
<< " to constant, but it is already listed as constant. "
<< "You may ignore this warning."
<< std::endl;
return;
}
fConstantParams.push_back( param );
}
void RooStats::HistFactory::Measurement::SetParamValue( const std::string& param, double value )
{
if( fParamValues.find(param) != fParamValues.end() ) {
std::cout << "Warning: Chainging parameter: " << param
<< " value from: " << fParamValues[param]
<< " to: " << value
<< std::endl;
}
std::cout << "Setting parameter: " << param
<< " value to " << value
<< std::endl;
fParamValues[param] = value;
}
void RooStats::HistFactory::Measurement::AddPreprocessFunction( std::string name, std::string expression, std::string dependencies )
{
PreprocessFunction func(name, expression, dependencies);
AddFunctionObject(func);
}
std::vector<std::string> RooStats::HistFactory::Measurement::GetPreprocessFunctions()
{
std::vector<std::string> PreprocessFunctionExpressions;
for( unsigned int i = 0; i < fFunctionObjects.size(); ++i ) {
std::string expression = fFunctionObjects.at(i).GetCommand();
PreprocessFunctionExpressions.push_back( expression );
}
return PreprocessFunctionExpressions;
}
void RooStats::HistFactory::Measurement::AddGammaSyst(std::string syst, double uncert)
{
fGammaSyst[syst] = uncert;
}
void RooStats::HistFactory::Measurement::AddLogNormSyst(std::string syst, double uncert)
{
fLogNormSyst[syst] = uncert;
}
void RooStats::HistFactory::Measurement::AddUniformSyst(std::string syst)
{
fUniformSyst[syst] = 1.0;
}
void RooStats::HistFactory::Measurement::AddNoSyst(std::string syst)
{
fNoSyst[syst] = 1.0;
}
bool RooStats::HistFactory::Measurement::HasChannel( std::string ChanName )
{
for( unsigned int i = 0; i < fChannels.size(); ++i ) {
Channel& chan = fChannels.at(i);
if( chan.GetName() == ChanName ) {
return true;
}
}
return false;
}
RooStats::HistFactory::Channel& RooStats::HistFactory::Measurement::GetChannel( std::string ChanName )
{
for( unsigned int i = 0; i < fChannels.size(); ++i ) {
Channel& chan = fChannels.at(i);
if( chan.GetName() == ChanName ) {
return chan;
}
}
std::cout << "Error: Did not find channel: " << ChanName
<< " in measurement: " << GetName() << std::endl;
throw hf_exc();
}
void RooStats::HistFactory::Measurement::PrintTree( std::ostream& stream )
{
stream << "Measurement Name: " << GetName()
<< "\t OutputFilePrefix: " << fOutputFilePrefix
<< "\t POI: ";
for(unsigned int i = 0; i < fPOI.size(); ++i) {
stream << fPOI.at(i);
}
stream << "\t Lumi: " << fLumi
<< "\t LumiRelErr: " << fLumiRelErr
<< "\t BinLow: " << fBinLow
<< "\t BinHigh: " << fBinHigh
<< "\t ExportOnly: " << fExportOnly
<< std::endl;
if( fConstantParams.size() != 0 ) {
stream << "Constant Params: ";
for( unsigned int i = 0; i < fConstantParams.size(); ++i ) {
stream << " " << fConstantParams.at(i);
}
stream << std::endl;
}
if( fFunctionObjects.size() != 0 ) {
stream << "Preprocess Functions: ";
for( unsigned int i = 0; i < fFunctionObjects.size(); ++i ) {
stream << " " << fFunctionObjects.at(i).GetCommand();
}
stream << std::endl;
}
if( fChannels.size() != 0 ) {
stream << "Channels:" << std::endl;
for( unsigned int i = 0; i < fChannels.size(); ++i ) {
fChannels.at(i).Print( stream );
}
}
std::cout << "End Measurement: " << GetName() << std::endl;
}
void RooStats::HistFactory::Measurement::PrintXML( std::string directory, std::string newOutputPrefix )
{
if( directory != "" && gSystem->OpenDirectory( directory.c_str() ) == 0 ) {
int success = gSystem->MakeDirectory(directory.c_str() );
if( success != 0 ) {
std::cout << "Error: Failed to make directory: " << directory << std::endl;
throw hf_exc();
}
}
std::cout << "Printing XML Files for measurement: " << GetName() << std::endl;
std::string XMLName = std::string(GetName()) + ".xml";
if( directory != "" ) XMLName = directory + "/" + XMLName;
ofstream xml( XMLName.c_str() );
if( ! xml.is_open() ) {
std::cout << "Error opening xml file: " << XMLName << std::endl;
throw hf_exc();
}
xml << "<!--" << std::endl;
xml << "This xml file created automatically on: " << std::endl;
TTimeStamp t;
UInt_t year = 0;
UInt_t month = 0;
UInt_t day = 0;
t.GetDate(true, 0, &year, &month, &day);
xml << year << '-'
<< month << '-'
<< day
<< std::endl;
xml << "-->" << std::endl;
xml << "<!DOCTYPE Combination SYSTEM 'HistFactorySchema.dtd'>" << std::endl << std::endl;
if (newOutputPrefix.empty() ) newOutputPrefix = fOutputFilePrefix;
xml << "<Combination OutputFilePrefix=\"" << newOutputPrefix << "\" >" << std::endl << std::endl;
for( unsigned int i = 0; i < fFunctionObjects.size(); ++i ) {
RooStats::HistFactory::PreprocessFunction func = fFunctionObjects.at(i);
func.PrintXML(xml);
}
xml << std::endl;
for( unsigned int i = 0; i < fChannels.size(); ++i ) {
xml << " <Input>" << "./";
if (!directory.empty() ) xml << directory << "/";
xml << GetName() << "_" << fChannels.at(i).GetName() << ".xml" << "</Input>" << std::endl;
}
xml << std::endl;
xml << " <Measurement Name=\"" << GetName() << "\" "
<< "Lumi=\"" << fLumi << "\" "
<< "LumiRelErr=\"" << fLumiRelErr << "\" "
<< "ExportOnly=\"" << (fExportOnly ? std::string("True") : std::string("False")) << "\" "
<< " >" << std::endl;
xml << " <POI>" ;
for(unsigned int i = 0; i < fPOI.size(); ++i) {
if(i==0) xml << fPOI.at(i);
else xml << " " << fPOI.at(i);
}
xml << "</POI> " << std::endl;
if(fConstantParams.size()) {
xml << " <ParamSetting Const=\"True\">";
for( unsigned int i = 0; i < fConstantParams.size(); ++i ) {
if (i==0) xml << fConstantParams.at(i);
else xml << " " << fConstantParams.at(i);;
}
xml << "</ParamSetting>" << std::endl;
}
std::map<std::string, double>::iterator ConstrItr;
for( ConstrItr = fGammaSyst.begin(); ConstrItr != fGammaSyst.end(); ++ConstrItr ) {
xml << "<ConstraintTerm Type=\"Gamma\" RelativeUncertainty=\""
<< ConstrItr->second << "\">" << ConstrItr->first
<< "</ConstraintTerm>" << std::endl;
}
for( ConstrItr = fUniformSyst.begin(); ConstrItr != fUniformSyst.end(); ++ConstrItr ) {
xml << "<ConstraintTerm Type=\"Uniform\" RelativeUncertainty=\""
<< ConstrItr->second << "\">" << ConstrItr->first
<< "</ConstraintTerm>" << std::endl;
}
for( ConstrItr = fLogNormSyst.begin(); ConstrItr != fLogNormSyst.end(); ++ConstrItr ) {
xml << "<ConstraintTerm Type=\"LogNormal\" RelativeUncertainty=\""
<< ConstrItr->second << "\">" << ConstrItr->first
<< "</ConstraintTerm>" << std::endl;
}
for( ConstrItr = fNoSyst.begin(); ConstrItr != fNoSyst.end(); ++ConstrItr ) {
xml << "<ConstraintTerm Type=\"NoSyst\" RelativeUncertainty=\""
<< ConstrItr->second << "\">" << ConstrItr->first
<< "</ConstraintTerm>" << std::endl;
}
xml << " </Measurement> " << std::endl << std::endl;
xml << "</Combination>" << std::endl;
xml.close();
std::string prefix = std::string(GetName()) + "_";
for( unsigned int i = 0; i < fChannels.size(); ++i ) {
fChannels.at(i).PrintXML( directory, prefix );
}
std::cout << "Finished printing XML files" << std::endl;
}
void RooStats::HistFactory::Measurement::writeToFile( TFile* file )
{
RooStats::HistFactory::Measurement outMeas( *this );
std::string OutputFileName = file->GetName();
for( unsigned int chanItr = 0; chanItr < outMeas.fChannels.size(); ++chanItr ) {
file->cd();
file->Flush();
RooStats::HistFactory::Channel& channel = outMeas.fChannels.at( chanItr );
std::string chanName = channel.GetName();
if( ! channel.CheckHistograms() ) {
std::cout << "Measurement.writeToFile(): Channel: " << chanName
<< " has uninitialized histogram pointers" << std::endl;
throw hf_exc();
return;
}
TDirectory* chanDir = file->mkdir( (chanName + "_hists").c_str() );
if( chanDir == NULL ) {
std::cout << "Error: Cannot create channel " << (chanName + "_hists")
<< std::endl;
throw hf_exc();
}
chanDir->cd();
TDirectory* dataDir = chanDir->mkdir( "data" );
if( dataDir == NULL ) {
std::cout << "Error: Cannot make directory " << chanDir << std::endl;
throw hf_exc();
}
dataDir->cd();
channel.fData.writeToFile( OutputFileName, GetDirPath(dataDir) );
for( unsigned int sampItr = 0; sampItr < channel.GetSamples().size(); ++sampItr ) {
RooStats::HistFactory::Sample& sample = channel.GetSamples().at( sampItr );
std::string sampName = sample.GetName();
std::cout << "Writing sample: " << sampName << std::endl;
file->cd();
chanDir->cd();
TDirectory* sampleDir = chanDir->mkdir( sampName.c_str() );
if( sampleDir == NULL ) {
std::cout << "Error: Directory " << sampName << " not created properly" << std::endl;
throw hf_exc();
}
std::string sampleDirPath = GetDirPath( sampleDir );
if( ! sampleDir ) {
std::cout << "Error making directory: " << sampName
<< " in directory: " << chanName
<< std::endl;
throw hf_exc();
}
sampleDir->cd();
sample.writeToFile( OutputFileName, sampleDirPath );
}
}
std::cout << "Saved all histograms" << std::endl;
file->cd();
outMeas.Write();
std::cout << "Saved Measurement" << std::endl;
}
std::string RooStats::HistFactory::Measurement::GetDirPath( TDirectory* dir )
{
std::string path = dir->GetPath();
if( path.find(":") != std::string::npos ) {
size_t index = path.find(":");
path.replace( 0, index+1, "" );
}
path = path + "/";
return path;
}
void RooStats::HistFactory::Measurement::CollectHistograms()
{
for( unsigned int chanItr = 0; chanItr < fChannels.size(); ++chanItr) {
RooStats::HistFactory::Channel& chan = fChannels.at( chanItr );
chan.CollectHistograms();
}
}