// @(#)root/roostats:$Id$
// Author: Sven Kreiss, Kyle Cranmer, Lorenzo Moneta  Nov 2010
/*************************************************************************
 * 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.             *
 *************************************************************************/

// implementation file of DetailedOutputAggregator

#include <limits>


#include "RooFitResult.h"
#include "RooPullVar.h"
#include "RooRealVar.h"
#include "RooDataSet.h"

#include "RooStats/DetailedOutputAggregator.h"

namespace RooStats {

   DetailedOutputAggregator::~DetailedOutputAggregator() {
      // destructor
      if (fResult != NULL) delete fResult;
      if (fBuiltSet != NULL) delete fBuiltSet;
   }


   RooArgSet * DetailedOutputAggregator::GetAsArgSet(RooFitResult *result, TString prefix, bool withErrorsAndPulls) {
      // static function to translate the given fit result to a RooArgSet in a generic way.
      // Prefix is prepended to all variable names.
      // LM: caller is responsible to delete the returned list and eventually also the content of the list
      //    Note that the returned list is not owning the returned content
      RooArgSet *detailedOutput = new RooArgSet;
      const RooArgList &detOut = result->floatParsFinal();
      const RooArgList &truthSet = result->floatParsInit();
      TIterator *it = detOut.createIterator();
      while(RooAbsArg* v = dynamic_cast<RooAbsArg*>(it->Next())) {
         RooAbsArg* clone = v->cloneTree(TString().Append(prefix).Append(v->GetName()));
         clone->SetTitle( TString().Append(prefix).Append(v->GetTitle()) );
         RooRealVar* var = dynamic_cast<RooRealVar*>(v);
         if (var) clone->setAttribute("StoreError");
         detailedOutput->add(*clone);
         
         if( withErrorsAndPulls && var ) {
            clone->setAttribute("StoreAsymError");

            TString pullname = TString().Append(prefix).Append(TString::Format("%s_pull", var->GetName()));
            //             TString pulldesc = TString::Format("%s pull for fit %u", var->GetTitle(), fitNumber);
            RooRealVar* truth = dynamic_cast<RooRealVar*>(truthSet.find(var->GetName()));
            RooPullVar pulltemp("temppull", "temppull", *var, *truth);
            RooRealVar* pull = new RooRealVar(pullname, pullname, pulltemp.getVal());
            detailedOutput->add(*pull);
         }
      }
      delete it;

      // monitor a few more variables
      detailedOutput->add( *new RooRealVar(TString().Append(prefix).Append("minNLL"), TString().Append(prefix).Append("minNLL"), result->minNll() ) );
      detailedOutput->add( *new RooRealVar(TString().Append(prefix).Append("fitStatus"), TString().Append(prefix).Append("fitStatus"), result->status() ) );
      detailedOutput->add( *new RooRealVar(TString().Append(prefix).Append("covQual"), TString().Append(prefix).Append("covQual"), result->covQual() ) );
      detailedOutput->add( *new RooRealVar(TString().Append(prefix).Append("numInvalidNLLEval"), TString().Append(prefix).Append("numInvalidNLLEval"), result->numInvalidNLL() ) );
      return detailedOutput;
   }

   void DetailedOutputAggregator::AppendArgSet(const RooAbsCollection *aset, TString prefix) {
      // For each variable in aset, prepend prefix to its name and add
      // to the internal store. Note this will not appear in the produced
      // dataset unless CommitSet is called.

      if (aset == NULL) {
         // silently ignore
         //std::cout << "Attempted to append NULL" << endl;
         return;
      }
      if (fBuiltSet == NULL) {
         fBuiltSet = new RooArgList();
      }
      TIterator* iter = aset->createIterator();
      while(RooAbsArg* v = dynamic_cast<RooAbsArg*>( iter->Next() ) ) {
         TString renamed(TString::Format("%s%s", prefix.Data(), v->GetName()));
         if (fResult == NULL) {
            // we never commited, so by default all columns are expected to not exist
            RooAbsArg* var = v->createFundamental();
            assert(var != NULL);
            (RooArgSet(*var)) = RooArgSet(*v);
            var->SetName(renamed);
            if (RooRealVar* rvar= dynamic_cast<RooRealVar*>(var)) {
               if (v->getAttribute("StoreError"))     var->setAttribute("StoreError");
               else rvar->removeError();
               if (v->getAttribute("StoreAsymError")) var->setAttribute("StoreAsymError");
               else rvar->removeAsymError();
            }
            if (fBuiltSet->addOwned(*var)) continue;  // OK - can skip past setting value
         }
         if (RooAbsArg* var = fBuiltSet->find(renamed)) {
            // we already commited an argset once, so we expect all columns to already be in the set
            var->SetName(v->GetName());
            (RooArgSet(*var)) = RooArgSet(*v); // copy values and errors
            var->SetName(renamed);
         }
      }
      delete iter;
   }

   // Commit to the result RooDataSet.
   void DetailedOutputAggregator::CommitSet(double weight) {
      if (fResult == NULL) {
         // Store dataset as a tree - problem with VectorStore and StoreError (bug #94908)
         RooRealVar wgt("weight","weight",1.0);
         fResult = new RooDataSet("", "", RooArgSet(*fBuiltSet,wgt), RooFit::WeightVar(wgt));
      }
      fResult->add(RooArgSet(*fBuiltSet), weight);
      TIterator* iter = fBuiltSet->createIterator();
      while(RooAbsArg* v = dynamic_cast<RooAbsArg*>( iter->Next() ) ) {
         if (RooRealVar* var= dynamic_cast<RooRealVar*>(v)) {
            // Invalidate values in case we don't set some of them next time round (eg. if fit not done)
            var->setVal(std::numeric_limits<Double_t>::quiet_NaN());
            var->removeError();
            var->removeAsymError();
         }
      }
      delete iter;
   }


   RooDataSet * DetailedOutputAggregator::GetAsDataSet(TString name, TString title) {
      // Returns all detailed output as a dataset.
      // Ownership of the dataset is transferred to the caller.
      RooDataSet* temp = NULL;
      if( fResult ) {
         temp = fResult;
         fResult = NULL;   // we no longer own the dataset
         temp->SetNameTitle( name.Data(), title.Data() );
      }else{
         RooRealVar wgt("weight","weight",1.0);
         temp = new RooDataSet(name.Data(), title.Data(), RooArgSet(wgt), RooFit::WeightVar(wgt));
      }
      delete fBuiltSet;
      fBuiltSet = NULL;

      return temp;
   }


}  // end namespace RooStats

 DetailedOutputAggregator.cxx:1
 DetailedOutputAggregator.cxx:2
 DetailedOutputAggregator.cxx:3
 DetailedOutputAggregator.cxx:4
 DetailedOutputAggregator.cxx:5
 DetailedOutputAggregator.cxx:6
 DetailedOutputAggregator.cxx:7
 DetailedOutputAggregator.cxx:8
 DetailedOutputAggregator.cxx:9
 DetailedOutputAggregator.cxx:10
 DetailedOutputAggregator.cxx:11
 DetailedOutputAggregator.cxx:12
 DetailedOutputAggregator.cxx:13
 DetailedOutputAggregator.cxx:14
 DetailedOutputAggregator.cxx:15
 DetailedOutputAggregator.cxx:16
 DetailedOutputAggregator.cxx:17
 DetailedOutputAggregator.cxx:18
 DetailedOutputAggregator.cxx:19
 DetailedOutputAggregator.cxx:20
 DetailedOutputAggregator.cxx:21
 DetailedOutputAggregator.cxx:22
 DetailedOutputAggregator.cxx:23
 DetailedOutputAggregator.cxx:24
 DetailedOutputAggregator.cxx:25
 DetailedOutputAggregator.cxx:26
 DetailedOutputAggregator.cxx:27
 DetailedOutputAggregator.cxx:28
 DetailedOutputAggregator.cxx:29
 DetailedOutputAggregator.cxx:30
 DetailedOutputAggregator.cxx:31
 DetailedOutputAggregator.cxx:32
 DetailedOutputAggregator.cxx:33
 DetailedOutputAggregator.cxx:34
 DetailedOutputAggregator.cxx:35
 DetailedOutputAggregator.cxx:36
 DetailedOutputAggregator.cxx:37
 DetailedOutputAggregator.cxx:38
 DetailedOutputAggregator.cxx:39
 DetailedOutputAggregator.cxx:40
 DetailedOutputAggregator.cxx:41
 DetailedOutputAggregator.cxx:42
 DetailedOutputAggregator.cxx:43
 DetailedOutputAggregator.cxx:44
 DetailedOutputAggregator.cxx:45
 DetailedOutputAggregator.cxx:46
 DetailedOutputAggregator.cxx:47
 DetailedOutputAggregator.cxx:48
 DetailedOutputAggregator.cxx:49
 DetailedOutputAggregator.cxx:50
 DetailedOutputAggregator.cxx:51
 DetailedOutputAggregator.cxx:52
 DetailedOutputAggregator.cxx:53
 DetailedOutputAggregator.cxx:54
 DetailedOutputAggregator.cxx:55
 DetailedOutputAggregator.cxx:56
 DetailedOutputAggregator.cxx:57
 DetailedOutputAggregator.cxx:58
 DetailedOutputAggregator.cxx:59
 DetailedOutputAggregator.cxx:60
 DetailedOutputAggregator.cxx:61
 DetailedOutputAggregator.cxx:62
 DetailedOutputAggregator.cxx:63
 DetailedOutputAggregator.cxx:64
 DetailedOutputAggregator.cxx:65
 DetailedOutputAggregator.cxx:66
 DetailedOutputAggregator.cxx:67
 DetailedOutputAggregator.cxx:68
 DetailedOutputAggregator.cxx:69
 DetailedOutputAggregator.cxx:70
 DetailedOutputAggregator.cxx:71
 DetailedOutputAggregator.cxx:72
 DetailedOutputAggregator.cxx:73
 DetailedOutputAggregator.cxx:74
 DetailedOutputAggregator.cxx:75
 DetailedOutputAggregator.cxx:76
 DetailedOutputAggregator.cxx:77
 DetailedOutputAggregator.cxx:78
 DetailedOutputAggregator.cxx:79
 DetailedOutputAggregator.cxx:80
 DetailedOutputAggregator.cxx:81
 DetailedOutputAggregator.cxx:82
 DetailedOutputAggregator.cxx:83
 DetailedOutputAggregator.cxx:84
 DetailedOutputAggregator.cxx:85
 DetailedOutputAggregator.cxx:86
 DetailedOutputAggregator.cxx:87
 DetailedOutputAggregator.cxx:88
 DetailedOutputAggregator.cxx:89
 DetailedOutputAggregator.cxx:90
 DetailedOutputAggregator.cxx:91
 DetailedOutputAggregator.cxx:92
 DetailedOutputAggregator.cxx:93
 DetailedOutputAggregator.cxx:94
 DetailedOutputAggregator.cxx:95
 DetailedOutputAggregator.cxx:96
 DetailedOutputAggregator.cxx:97
 DetailedOutputAggregator.cxx:98
 DetailedOutputAggregator.cxx:99
 DetailedOutputAggregator.cxx:100
 DetailedOutputAggregator.cxx:101
 DetailedOutputAggregator.cxx:102
 DetailedOutputAggregator.cxx:103
 DetailedOutputAggregator.cxx:104
 DetailedOutputAggregator.cxx:105
 DetailedOutputAggregator.cxx:106
 DetailedOutputAggregator.cxx:107
 DetailedOutputAggregator.cxx:108
 DetailedOutputAggregator.cxx:109
 DetailedOutputAggregator.cxx:110
 DetailedOutputAggregator.cxx:111
 DetailedOutputAggregator.cxx:112
 DetailedOutputAggregator.cxx:113
 DetailedOutputAggregator.cxx:114
 DetailedOutputAggregator.cxx:115
 DetailedOutputAggregator.cxx:116
 DetailedOutputAggregator.cxx:117
 DetailedOutputAggregator.cxx:118
 DetailedOutputAggregator.cxx:119
 DetailedOutputAggregator.cxx:120
 DetailedOutputAggregator.cxx:121
 DetailedOutputAggregator.cxx:122
 DetailedOutputAggregator.cxx:123
 DetailedOutputAggregator.cxx:124
 DetailedOutputAggregator.cxx:125
 DetailedOutputAggregator.cxx:126
 DetailedOutputAggregator.cxx:127
 DetailedOutputAggregator.cxx:128
 DetailedOutputAggregator.cxx:129
 DetailedOutputAggregator.cxx:130
 DetailedOutputAggregator.cxx:131
 DetailedOutputAggregator.cxx:132
 DetailedOutputAggregator.cxx:133
 DetailedOutputAggregator.cxx:134
 DetailedOutputAggregator.cxx:135
 DetailedOutputAggregator.cxx:136
 DetailedOutputAggregator.cxx:137
 DetailedOutputAggregator.cxx:138
 DetailedOutputAggregator.cxx:139
 DetailedOutputAggregator.cxx:140
 DetailedOutputAggregator.cxx:141
 DetailedOutputAggregator.cxx:142
 DetailedOutputAggregator.cxx:143
 DetailedOutputAggregator.cxx:144
 DetailedOutputAggregator.cxx:145
 DetailedOutputAggregator.cxx:146
 DetailedOutputAggregator.cxx:147
 DetailedOutputAggregator.cxx:148
 DetailedOutputAggregator.cxx:149
 DetailedOutputAggregator.cxx:150