Newer
Older
#include "QFramework/TQFolder.h"
#include "QFramework/TQIterator.h"
#include "QFramework/TQUtils.h"
#include "QFramework/TQStringUtils.h"
#include "TString.h"
#include "SFramework/TSStatisticsManager.h"
namespace TSBaseActions {
class TransferSystematics : public TSStatisticsManager::Action {
bool matchesAny(TQFolder* f,const std::vector<TString>& filters, const TString&prefix = "") const {
bool matched = false;
for(const auto& x:filters){
if(TQStringUtils::matches(f->GetName(),prefix+x)){
matched = true;
return matched;
}
bool execute(TQFolder * config) const override {
TQFolder* model = models()->getFolder(config->GetName());
if(!model){
manager->error(TString::Format("no such model available: '%s'",config->GetName()));
}
TQFolderIterator transfers = config->getListOfFolders("?");
int nOK = 0;
while(transfers.hasNext()){
TQFolder* transfer = transfers.readNext();
if(!transfer) continue;
nOK += performTransfer(transfer,model);
}
return nOK;
}
bool performTransfer(TQFolder * config,TQFolder* model) const {
TString mode = config->getTagStringDefault("mode","sample");
TString componentFilter = config->getTagStringDefault("componentFilter","OverallSysHistoSys");
TQFolder* histograms = model->getFolder(".Histograms");
bool verbose = config->getTagBoolDefault("~verbose",false);
std::vector<TString> exceptRegions = config->getTagVString("except.Channels");
std::vector<TString> exceptSamples = config->getTagVString("except.Samples");
std::vector<TString> exceptSystematics = config->getTagVString("except.OverallSys");
manager->info(TString::Format("performing transfer '%s'",config->GetName()));
std::vector<TString> targetSamples = config->getTagVString("select.Samples");
if(targetSamples.empty()){
targetSamples.push_back("*");
}
std::vector<TString> targetChannels = config->getTagVString("select.Channels");
if(targetChannels.empty()){
targetChannels.push_back("*");
}
std::vector<TString> targetSystematics = config->getTagVString("select.Systematics");
if(targetSystematics.empty()){
targetSystematics.push_back("*");
}
TString mark;
bool marked = config->getTagString("selectTag.OverallSys",mark);
if (mode.Contains("sample",TString::kIgnoreCase)) {
TString sourceSample;
if(!config->getTagString("source",sourceSample)){
manager->error(TString::Format("missing required 'source' information on transfer '%s'",config->GetName()));
return false;
}
int i=0;
for(const auto& channelExp:targetChannels){
TQFolderIterator regions(model->getListOfFolders("Channel."+channelExp),true);
while(regions.hasNext()){
TQFolder* region = regions.readNext();
if(!region) continue;
if(matchesAny(region,exceptRegions,"Channel.")) continue;
if(verbose) manager->info(TString::Format("transferring in region '%s'",region->GetName()));
TQFolder* source = region->getFolder("Sample."+sourceSample);
if(!source){
manager->warn(TString::Format("unable to find source '%s' in channel '%s', skipping!",sourceSample.Data(),region->GetName()));
continue;
}
for(const auto& sampleExp:targetSamples){
TQFolderIterator samples(region->getListOfFolders("Sample."+sampleExp),true);
while(samples.hasNext()){
TQFolder* sample = samples.readNext();
if(!sample) continue;
if(matchesAny(sample,exceptSamples,"Sample.")) continue;
if(TQStringUtils::matches(sample->GetName(),"Sample."+sourceSample)) continue;
if(verbose) manager->info(TString::Format("\tfor sample '%s'",sample->GetName()));
sample->deleteObject(".Dropped!");
for (const auto& systType : {TString("OverallSys."),TString("HistoSys.")}) {
if (componentFilter=="OverallSys" and systType=="HistoSys.") continue;
if (componentFilter=="HistoSys" and systType=="OverallSys.") continue;
std::vector<TQFolder*> remove;
{
TQFolderIterator oldsystematics(sample->getListOfFolders(systType+"*"),true);
while(oldsystematics.hasNext()){
TQFolder* systematic = oldsystematics.readNext();
if(!systematic) continue;
if(matchesAny(systematic,exceptSystematics,systType) || !matchesAny(systematic,targetSystematics,systType)) continue;
if(marked && !systematic->getTagBoolDefault(mark,false)) continue;
if(verbose) manager->info(TString::Format("\t\tremoving '%s'",systematic->GetName()));
remove.push_back(systematic);
}
}
for(auto systematic:remove){
systematic->detachFromBase();
delete systematic;
}
{
TQFolderIterator newsystematics(source->getListOfFolders(systType+"*"),true);
while(newsystematics.hasNext()){
TQFolder* systematic = newsystematics.readNext();
if(!systematic) continue;
if(matchesAny(systematic,exceptSystematics,systType) || !matchesAny(systematic,targetSystematics,systType)) continue;
if(marked && !systematic->getTagBoolDefault(mark,false)) continue;
if(verbose) manager->info(TString::Format("\t\tcopying '%s'",systematic->GetName()));
TQFolder* copy = systematic->copy();
copy->setTagString("transferred",source->GetName());
if(systematic->hasTagString("HistoLow") && systematic->hasTagString("HistoHigh")){
TH1* nomHist = dynamic_cast<TH1*>(histograms->getObject(sample->getTagStringDefault("Histo","")));
TH1* lowHist = dynamic_cast<TH1*>(histograms->getObject(systematic->getTagStringDefault("HistoLow","")));
TH1* highHist = dynamic_cast<TH1*>(histograms->getObject(systematic->getTagStringDefault("HistoHigh","")));
if(!TQHistogramUtils::checkConsistency(nomHist,lowHist) || !TQHistogramUtils::checkConsistency(nomHist,highHist)){
manager->error(TString::Format("transferred histograms are inconsistent, skipping!\n\tnom\t%s\n\tlow\t%s\n\thigh\t%s",TQStringUtils::getDetails(nomHist).Data(),TQStringUtils::getDetails(lowHist).Data(),TQStringUtils::getDetails(highHist).Data()));
delete copy;
continue;
}
}
++j;
sample->addFolder(copy);
}
if(verbose && j==0){
manager->warn(TString::Format("\tno systematics of type %s found in '%s' matching '%s' except '%s'!",systType.Data(),source->GetName(),TQStringUtils::concat(targetSystematics,",").Data(),TQStringUtils::concat(exceptSystematics,",").Data()));
}
}
}
}
if(i>0) return true;
manager->error("no targets found for sample transfer!");
return false;
} else if (mode.Contains("channel",TString::kIgnoreCase)) {
TString sourceChannel;
if(!config->getTagString("source",sourceChannel)){
manager->error(TString::Format("missing required 'source' information on transfer '%s'",config->GetName()));
return false;
}
int i=0;
for(const auto& channelExp:targetChannels){
TQFolderIterator regions(model->getListOfFolders("Channel."+channelExp),true);
while(regions.hasNext()){
TQFolder* region = regions.readNext();
if(!region) continue;
if(region->GetName() == sourceChannel) continue; //there is no point in transfering from A to A (it would even delete some stuff!)
if(matchesAny(region,exceptRegions,"Channel.")) continue;
if(verbose) manager->info(TString::Format("transferring in region '%s'",region->GetName()));
for(const auto& sampleExp:targetSamples){
TQFolderIterator samples(region->getListOfFolders("Sample."+sampleExp),true);
while(samples.hasNext()){
TQFolder* sample = samples.readNext();
if(matchesAny(sample,exceptSamples,"Sample.")) continue;
TQFolder* sourceRegion = model->getFolder("Channel."+sourceChannel);
TQFolder* source = sourceRegion ? sourceRegion->getFolder(sample->GetName()) : NULL;
if(!source){
manager->warn(TString::Format("unable to find source '%s'/'%s' in model '%s', skipping!",sourceChannel.Data(),sample->GetName(),model->GetName()));
continue;
}
if(verbose) manager->info(TString::Format("\tfor sample '%s'",sample->GetName()));
sample->deleteObject(".Dropped!");
for (const auto& systType : {TString("OverallSys."),TString("HistoSys.")}) {
if (componentFilter=="OverallSys" and systType=="HistoSys.") continue;
if (componentFilter=="HistoSys" and systType=="OverallSys.") continue;
std::vector<TQFolder*> remove;
{
TQFolderIterator oldsystematics(sample->getListOfFolders(systType+"*"),true);
while(oldsystematics.hasNext()){
TQFolder* systematic = oldsystematics.readNext();
if(!systematic) continue;
if(matchesAny(systematic,exceptSystematics,systType) || !matchesAny(systematic,targetSystematics,systType)) continue;
if(marked && !systematic->getTagBoolDefault(mark,false)) continue;
if(verbose) manager->info(TString::Format("\t\tremoving '%s'",systematic->GetName()));
remove.push_back(systematic);
}
}
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
for(auto systematic:remove){
systematic->detachFromBase();
delete systematic;
}
{
TQFolderIterator newsystematics(source->getListOfFolders(systType+"*"),true);
int j = 0;
while(newsystematics.hasNext()){
TQFolder* systematic = newsystematics.readNext();
if(!systematic) continue;
if(matchesAny(systematic,exceptSystematics,systType) || !matchesAny(systematic,targetSystematics,systType)) continue;
if(marked && !systematic->getTagBoolDefault(mark,false)) continue;
if(verbose) manager->info(TString::Format("\t\tcopying '%s'",systematic->GetName()));
TQFolder* copy = systematic->copy();
copy->setTagString("transferred",source->GetName());
if(systematic->hasTagString("HistoLow") && systematic->hasTagString("HistoHigh")){
TH1* sourceNomHist = dynamic_cast<TH1*>(histograms->getObject(sample->getTagStringDefault("Histo","")));
TH1* targetNomHist = dynamic_cast<TH1*>(histograms->getObject(systematic->getTagStringDefault("Histo","")));
TH1* targetLowHist = dynamic_cast<TH1*>(histograms->getObject(systematic->getTagStringDefault("HistoHigh","")));
TH1* targetHighHist = dynamic_cast<TH1*>(histograms->getObject(systematic->getTagStringDefault("HistoLow","")));
TQHistogramUtils::normalize(sourceLowHist,sourceNomHist);
TQHistogramUtils::divideHistogramWithoutError(sourceLowHist,sourceNomHist);
TQHistogramUtils::normalize(sourceHighHist,sourceNomHist);
TH1* targetNomHistClone1= dynamic_cast<TH1*>(sourceNomHist->Clone());
TQHistogramUtils::divideHistogramWithoutError(targetNomHistClone1,sourceLowHist);
targetLowHist = targetNomHistClone1;
TH1* targetNomHistClone2= dynamic_cast<TH1*>(sourceNomHist->Clone());
TQHistogramUtils::divideHistogramWithoutError(targetNomHistClone2,sourceHighHist);
targetHighHist = targetNomHistClone2;
TQHistogramUtils::normalize(targetLowHist,targetNomHist);
TQHistogramUtils::normalize(targetHighHist,targetNomHist);
TString histoPathLow=systematic->getTagStringDefault("HistoLow","");
TString histoPathHigh=systematic->getTagStringDefault("HistoHigh","");
TQFolder::getPathTail(histoPathLow);
TQFolder::getPathTail(histoPathHigh);
TQStringUtils::ensureTrailingText(histoPathLow,"/");
TQStringUtils::ensureTrailingText(histoPathHigh,"/");
}
++j;
}
if(verbose && j==0){
manager->warn(TString::Format("\tno systematics of type %s found in '%s' matching '%s' except '%s'!",systType.Data(),source->GetName(),TQStringUtils::concat(targetSystematics,",").Data(),TQStringUtils::concat(exceptSystematics,",").Data()));
}
i += j;
}
if(i>0) return true;
manager->error("no targets found for channel transfer!");
return false;
//no valid mode was selected
manager->error("Failed to perform, no valid mode was selected!");
return false;