// @(#)root/roostats:$Id$
// Author: Kyle Cranmer, Lorenzo Moneta, Gregory Schott, Wouter Verkerke, Sven Kreiss
/*************************************************************************
 * Copyright (C) 1995-2008, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "RooStats/ModelConfig.h"

#include "TROOT.h"

#ifndef ROO_MSG_SERVICE
#include "RooMsgService.h"
#endif

#ifndef RooStats_RooStatsUtils
#include "RooStats/RooStatsUtils.h"
#endif

#include <sstream>


ClassImp(RooStats::ModelConfig)

using namespace std;

namespace RooStats {

void ModelConfig::GuessObsAndNuisance(const RooAbsData& data) {
   // Makes sensible guesses of observables, parameters of interest
   // and nuisance parameters.
   //
   // Defaults:
   //  observables: determined from data,
   //  global observables = explicit obs  -  obs from data
   //  parameters of interest: empty,
   //  nuisance parameters: all parameters except parameters of interest
  //
  // We use NULL to mean not set, so we don't want to fill
  // with empty RooArgSets

   // observables
  if (!GetObservables()) {
     const RooArgSet * obs = GetPdf()->getObservables(data);
     SetObservables(*obs);
     delete obs; 
   }
  // global observables 
   if (!GetGlobalObservables()) {
      RooArgSet co(*GetObservables());
      const RooArgSet * obs = GetPdf()->getObservables(data);     
      co.remove(*obs);
      RemoveConstantParameters(&co);
      if(co.getSize()>0)
	SetGlobalObservables(co);

      // TODO BUG This does not work as observables with the same name are already in the workspace.
      /*
      RooArgSet o(*GetObservables());
      o.remove(co);
      SetObservables(o);
      */
      delete obs; 
   }

   // parameters
   //   if (!GetParametersOfInterest()) {
   //      SetParametersOfInterest(RooArgSet());
   //   }
   if (!GetNuisanceParameters()) {
      const RooArgSet * params = GetPdf()->getParameters(data);
      RooArgSet p(*params);
      p.remove(*GetParametersOfInterest());
      RemoveConstantParameters(&p);
      if(p.getSize()>0)
	SetNuisanceParameters(p);
      delete params;
   }
   
   // print Modelconfig as an info message

   std::ostream& oldstream = RooPrintable::defaultPrintStream(&ccoutI(InputArguments));
   Print();
   RooPrintable::defaultPrintStream(&oldstream);
}

void ModelConfig::Print(Option_t*) const {
   // print contents of Model on the default print stream 
   // It can be changed using RooPrintable
   ostream& os = RooPrintable::defaultPrintStream();

   os << endl << "=== Using the following for " << GetName() << " ===" << endl;

 
   // args
   if(GetObservables()){
      os << "Observables:             ";
      GetObservables()->Print("");
   }
   if(GetParametersOfInterest()) {
      os << "Parameters of Interest:  ";
      GetParametersOfInterest()->Print("");
   }
   if(GetNuisanceParameters()){
      os << "Nuisance Parameters:     ";
      GetNuisanceParameters()->Print("");
   }
   if(GetGlobalObservables()){
      os << "Global Observables:      ";
      GetGlobalObservables()->Print("");
   }
   if(GetConstraintParameters()){
      os << "Constraint Parameters:   ";
      GetConstraintParameters()->Print("");
   }
   if(GetConditionalObservables()){
      os << "Conditional Observables: ";
      GetConditionalObservables()->Print("");
   }
   if(GetProtoData()){
      os << "Proto Data:              ";
      GetProtoData()->Print("");
   }

   // pdfs
   if(GetPdf()) {
      os << "PDF:                     ";
      GetPdf()->Print("");
   }
   if(GetPriorPdf()) {
      os << "Prior PDF:               ";
      GetPriorPdf()->Print("");
   }

   // snapshot
   const RooArgSet * snapshot = GetSnapshot();
   if(snapshot) {
      os << "Snapshot:                " << endl;
      snapshot->Print("v");
      delete snapshot;
   }

   os << endl;
}


void ModelConfig::SetWS(RooWorkspace & ws) {
   // set a workspace that owns all the necessary components for the analysis
   if( !fRefWS.GetObject() ) {
      fRefWS = &ws; 
      fWSName = ws.GetName();
   }   
   else{
      RooFit::MsgLevel level = RooMsgService::instance().globalKillBelow();
      RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR) ;
      GetWS()->merge(ws);
      RooMsgService::instance().setGlobalKillBelow(level) ;
   }
}

RooWorkspace * ModelConfig::GetWS() const {
   // get from TRef
   RooWorkspace *ws = dynamic_cast<RooWorkspace *>(fRefWS.GetObject() );
   if(!ws) {
      coutE(ObjectHandling) << "workspace not set" << endl;
      return NULL;
   }
   return ws;
}

void ModelConfig::SetSnapshot(const RooArgSet& set) {
   // save snaphot in the workspace 
   // and use values passed with the set
   if ( !GetWS() ) return;

   fSnapshotName = GetName();
   if (fSnapshotName.size()  > 0) fSnapshotName += "_";
   fSnapshotName += set.GetName();
   if (fSnapshotName.size()  > 0) fSnapshotName += "_";
   fSnapshotName += "snapshot";
   GetWS()->saveSnapshot(fSnapshotName.c_str(), set, true);  // import also the given parameter values
   DefineSetInWS(fSnapshotName.c_str(), set);
}    

const RooArgSet * ModelConfig::GetSnapshot() const{
   // Load the snapshot from ws and return the corresponding set with the snapshot values.
   // User must delete returned RooArgSet.
   if ( !GetWS() ) return 0;
   if (!fSnapshotName.length()) return 0;
   // calling loadSnapshot will also copy the current parameter values in the workspaces
   // since we do not want to change the model parameters - we restore the previous ones 
   if (! GetWS()->set(fSnapshotName.c_str() ) )return 0;
   RooArgSet snapshotVars(*GetWS()->set(fSnapshotName.c_str() ) );
   if (snapshotVars.getSize() == 0) return 0;
   // make my snapshot which will contain a copy of the snapshot variables 
   RooArgSet tempSnapshot; 
   snapshotVars.snapshot(tempSnapshot);  
   // load snapshot value from the workspace 
   if (!(GetWS()->loadSnapshot(fSnapshotName.c_str())) ) return 0;
   // by doing this snapshotVars will have the snapshot values - make the snapshot to return
   const RooArgSet * modelSnapshot = dynamic_cast<const RooArgSet*>( snapshotVars.snapshot());
   // restore now the variables of snapshot in ws to their original values
   // need to const cast since assign is not const (but in reality in just assign values and does not change the set)
   // and anyway the set is const 
   snapshotVars.assignFast(tempSnapshot);
   return modelSnapshot;  
}

void ModelConfig::LoadSnapshot() const{
   // load the snapshot from ws if it exists
   if ( !GetWS() ) return;
   GetWS()->loadSnapshot(fSnapshotName.c_str());
}

void ModelConfig::DefineSetInWS(const char* name, const RooArgSet& set) {
   // helper functions to avoid code duplication
   if ( !GetWS() ) return;

   const RooArgSet * prevSet = GetWS()->set(name); 
   if (  prevSet ) {
      //be careful not to remove passed set in case it is the same updated
      if (prevSet != &set) 
         GetWS()->removeSet(name);
   }
   
   // suppress warning when we re-define a previously defined set (when set == prevSet )
   // and set is not removed in that case
   RooFit::MsgLevel level = RooMsgService::instance().globalKillBelow();
   RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR) ;


   GetWS()->defineSet(name, set,true);

   RooMsgService::instance().setGlobalKillBelow(level) ;
  
}
   
void ModelConfig::ImportPdfInWS(const RooAbsPdf & pdf) { 
   // internal function to import Pdf in WS 
   if ( !GetWS() ) return;

   if (! GetWS()->pdf( pdf.GetName() ) ){
      RooFit::MsgLevel level = RooMsgService::instance().globalKillBelow();
      RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR) ;
      GetWS()->import(pdf, RooFit::RecycleConflictNodes());
      RooMsgService::instance().setGlobalKillBelow(level) ;
   }
}
   
void ModelConfig::ImportDataInWS(RooAbsData & data) { 
   // internal function to import data in WS
   if ( !GetWS() ) return;

   if (! GetWS()->data( data.GetName() ) ){
      RooFit::MsgLevel level = RooMsgService::instance().globalKillBelow();
      RooMsgService::instance().setGlobalKillBelow(RooFit::ERROR) ;
      GetWS()->import(data);
      RooMsgService::instance().setGlobalKillBelow(level) ;
   }
}


  Bool_t ModelConfig::SetHasOnlyParameters(const RooArgSet& set, const char* errorMsgPrefix) {

    RooArgSet nonparams ;
    RooFIter iter = set.fwdIterator() ;
    RooAbsArg* arg ;
    while ((arg=iter.next())) {
      if (!arg->isFundamental()) {
	nonparams.add(*arg) ;
      }
    }
    
    if (errorMsgPrefix && nonparams.getSize()>0) {
      cout << errorMsgPrefix << " ERROR: specified set contains non-parameters: " << nonparams << endl ;
    }
    return (nonparams.getSize()==0) ;
  }

} // end namespace RooStats
 ModelConfig.cxx:1
 ModelConfig.cxx:2
 ModelConfig.cxx:3
 ModelConfig.cxx:4
 ModelConfig.cxx:5
 ModelConfig.cxx:6
 ModelConfig.cxx:7
 ModelConfig.cxx:8
 ModelConfig.cxx:9
 ModelConfig.cxx:10
 ModelConfig.cxx:11
 ModelConfig.cxx:12
 ModelConfig.cxx:13
 ModelConfig.cxx:14
 ModelConfig.cxx:15
 ModelConfig.cxx:16
 ModelConfig.cxx:17
 ModelConfig.cxx:18
 ModelConfig.cxx:19
 ModelConfig.cxx:20
 ModelConfig.cxx:21
 ModelConfig.cxx:22
 ModelConfig.cxx:23
 ModelConfig.cxx:24
 ModelConfig.cxx:25
 ModelConfig.cxx:26
 ModelConfig.cxx:27
 ModelConfig.cxx:28
 ModelConfig.cxx:29
 ModelConfig.cxx:30
 ModelConfig.cxx:31
 ModelConfig.cxx:32
 ModelConfig.cxx:33
 ModelConfig.cxx:34
 ModelConfig.cxx:35
 ModelConfig.cxx:36
 ModelConfig.cxx:37
 ModelConfig.cxx:38
 ModelConfig.cxx:39
 ModelConfig.cxx:40
 ModelConfig.cxx:41
 ModelConfig.cxx:42
 ModelConfig.cxx:43
 ModelConfig.cxx:44
 ModelConfig.cxx:45
 ModelConfig.cxx:46
 ModelConfig.cxx:47
 ModelConfig.cxx:48
 ModelConfig.cxx:49
 ModelConfig.cxx:50
 ModelConfig.cxx:51
 ModelConfig.cxx:52
 ModelConfig.cxx:53
 ModelConfig.cxx:54
 ModelConfig.cxx:55
 ModelConfig.cxx:56
 ModelConfig.cxx:57
 ModelConfig.cxx:58
 ModelConfig.cxx:59
 ModelConfig.cxx:60
 ModelConfig.cxx:61
 ModelConfig.cxx:62
 ModelConfig.cxx:63
 ModelConfig.cxx:64
 ModelConfig.cxx:65
 ModelConfig.cxx:66
 ModelConfig.cxx:67
 ModelConfig.cxx:68
 ModelConfig.cxx:69
 ModelConfig.cxx:70
 ModelConfig.cxx:71
 ModelConfig.cxx:72
 ModelConfig.cxx:73
 ModelConfig.cxx:74
 ModelConfig.cxx:75
 ModelConfig.cxx:76
 ModelConfig.cxx:77
 ModelConfig.cxx:78
 ModelConfig.cxx:79
 ModelConfig.cxx:80
 ModelConfig.cxx:81
 ModelConfig.cxx:82
 ModelConfig.cxx:83
 ModelConfig.cxx:84
 ModelConfig.cxx:85
 ModelConfig.cxx:86
 ModelConfig.cxx:87
 ModelConfig.cxx:88
 ModelConfig.cxx:89
 ModelConfig.cxx:90
 ModelConfig.cxx:91
 ModelConfig.cxx:92
 ModelConfig.cxx:93
 ModelConfig.cxx:94
 ModelConfig.cxx:95
 ModelConfig.cxx:96
 ModelConfig.cxx:97
 ModelConfig.cxx:98
 ModelConfig.cxx:99
 ModelConfig.cxx:100
 ModelConfig.cxx:101
 ModelConfig.cxx:102
 ModelConfig.cxx:103
 ModelConfig.cxx:104
 ModelConfig.cxx:105
 ModelConfig.cxx:106
 ModelConfig.cxx:107
 ModelConfig.cxx:108
 ModelConfig.cxx:109
 ModelConfig.cxx:110
 ModelConfig.cxx:111
 ModelConfig.cxx:112
 ModelConfig.cxx:113
 ModelConfig.cxx:114
 ModelConfig.cxx:115
 ModelConfig.cxx:116
 ModelConfig.cxx:117
 ModelConfig.cxx:118
 ModelConfig.cxx:119
 ModelConfig.cxx:120
 ModelConfig.cxx:121
 ModelConfig.cxx:122
 ModelConfig.cxx:123
 ModelConfig.cxx:124
 ModelConfig.cxx:125
 ModelConfig.cxx:126
 ModelConfig.cxx:127
 ModelConfig.cxx:128
 ModelConfig.cxx:129
 ModelConfig.cxx:130
 ModelConfig.cxx:131
 ModelConfig.cxx:132
 ModelConfig.cxx:133
 ModelConfig.cxx:134
 ModelConfig.cxx:135
 ModelConfig.cxx:136
 ModelConfig.cxx:137
 ModelConfig.cxx:138
 ModelConfig.cxx:139
 ModelConfig.cxx:140
 ModelConfig.cxx:141
 ModelConfig.cxx:142
 ModelConfig.cxx:143
 ModelConfig.cxx:144
 ModelConfig.cxx:145
 ModelConfig.cxx:146
 ModelConfig.cxx:147
 ModelConfig.cxx:148
 ModelConfig.cxx:149
 ModelConfig.cxx:150
 ModelConfig.cxx:151
 ModelConfig.cxx:152
 ModelConfig.cxx:153
 ModelConfig.cxx:154
 ModelConfig.cxx:155
 ModelConfig.cxx:156
 ModelConfig.cxx:157
 ModelConfig.cxx:158
 ModelConfig.cxx:159
 ModelConfig.cxx:160
 ModelConfig.cxx:161
 ModelConfig.cxx:162
 ModelConfig.cxx:163
 ModelConfig.cxx:164
 ModelConfig.cxx:165
 ModelConfig.cxx:166
 ModelConfig.cxx:167
 ModelConfig.cxx:168
 ModelConfig.cxx:169
 ModelConfig.cxx:170
 ModelConfig.cxx:171
 ModelConfig.cxx:172
 ModelConfig.cxx:173
 ModelConfig.cxx:174
 ModelConfig.cxx:175
 ModelConfig.cxx:176
 ModelConfig.cxx:177
 ModelConfig.cxx:178
 ModelConfig.cxx:179
 ModelConfig.cxx:180
 ModelConfig.cxx:181
 ModelConfig.cxx:182
 ModelConfig.cxx:183
 ModelConfig.cxx:184
 ModelConfig.cxx:185
 ModelConfig.cxx:186
 ModelConfig.cxx:187
 ModelConfig.cxx:188
 ModelConfig.cxx:189
 ModelConfig.cxx:190
 ModelConfig.cxx:191
 ModelConfig.cxx:192
 ModelConfig.cxx:193
 ModelConfig.cxx:194
 ModelConfig.cxx:195
 ModelConfig.cxx:196
 ModelConfig.cxx:197
 ModelConfig.cxx:198
 ModelConfig.cxx:199
 ModelConfig.cxx:200
 ModelConfig.cxx:201
 ModelConfig.cxx:202
 ModelConfig.cxx:203
 ModelConfig.cxx:204
 ModelConfig.cxx:205
 ModelConfig.cxx:206
 ModelConfig.cxx:207
 ModelConfig.cxx:208
 ModelConfig.cxx:209
 ModelConfig.cxx:210
 ModelConfig.cxx:211
 ModelConfig.cxx:212
 ModelConfig.cxx:213
 ModelConfig.cxx:214
 ModelConfig.cxx:215
 ModelConfig.cxx:216
 ModelConfig.cxx:217
 ModelConfig.cxx:218
 ModelConfig.cxx:219
 ModelConfig.cxx:220
 ModelConfig.cxx:221
 ModelConfig.cxx:222
 ModelConfig.cxx:223
 ModelConfig.cxx:224
 ModelConfig.cxx:225
 ModelConfig.cxx:226
 ModelConfig.cxx:227
 ModelConfig.cxx:228
 ModelConfig.cxx:229
 ModelConfig.cxx:230
 ModelConfig.cxx:231
 ModelConfig.cxx:232
 ModelConfig.cxx:233
 ModelConfig.cxx:234
 ModelConfig.cxx:235
 ModelConfig.cxx:236
 ModelConfig.cxx:237
 ModelConfig.cxx:238
 ModelConfig.cxx:239
 ModelConfig.cxx:240
 ModelConfig.cxx:241
 ModelConfig.cxx:242
 ModelConfig.cxx:243
 ModelConfig.cxx:244
 ModelConfig.cxx:245
 ModelConfig.cxx:246
 ModelConfig.cxx:247
 ModelConfig.cxx:248
 ModelConfig.cxx:249
 ModelConfig.cxx:250
 ModelConfig.cxx:251
 ModelConfig.cxx:252
 ModelConfig.cxx:253
 ModelConfig.cxx:254
 ModelConfig.cxx:255
 ModelConfig.cxx:256
 ModelConfig.cxx:257
 ModelConfig.cxx:258
 ModelConfig.cxx:259
 ModelConfig.cxx:260
 ModelConfig.cxx:261
 ModelConfig.cxx:262
 ModelConfig.cxx:263
 ModelConfig.cxx:264
 ModelConfig.cxx:265
 ModelConfig.cxx:266
 ModelConfig.cxx:267
 ModelConfig.cxx:268
 ModelConfig.cxx:269
 ModelConfig.cxx:270
 ModelConfig.cxx:271
 ModelConfig.cxx:272
 ModelConfig.cxx:273
 ModelConfig.cxx:274
 ModelConfig.cxx:275
 ModelConfig.cxx:276
 ModelConfig.cxx:277
 ModelConfig.cxx:278
 ModelConfig.cxx:279
 ModelConfig.cxx:280
 ModelConfig.cxx:281
 ModelConfig.cxx:282
 ModelConfig.cxx:283