Skip to content

Commit

Permalink
[RF] Add log-value error checking to batch interface.
Browse files Browse the repository at this point in the history
Further, remove unused statics in RooAbsPdf.
  • Loading branch information
hageboeck committed Aug 15, 2019
1 parent f6de5db commit 9f739cc
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 132 deletions.
11 changes: 2 additions & 9 deletions roofit/roofitcore/inc/RooAbsPdf.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ class RooAbsPdf : public RooAbsReal {

virtual RooSpan<const double> getValBatch(std::size_t begin, std::size_t batchSize,
const RooArgSet* normSet = nullptr) const;
RooSpan<double> getLogValBatch(std::size_t begin, std::size_t batchSize,
RooSpan<const double> getLogValBatch(std::size_t begin, std::size_t batchSize,
const RooArgSet* normSet = nullptr) const;

Double_t getNorm(const RooArgSet& nset) const {
Expand Down Expand Up @@ -258,9 +258,6 @@ class RooAbsPdf : public RooAbsReal {

virtual Double_t extendedTerm(Double_t observedEvents, const RooArgSet* nset=0) const ;

static void clearEvalError() ;
static Bool_t evalError() ;

void setNormRange(const char* rangeName) ;
const char* normRange() const {
return _normRange.Length()>0 ? _normRange.Data() : 0 ;
Expand Down Expand Up @@ -293,7 +290,7 @@ class RooAbsPdf : public RooAbsReal {
const char *label= "", Int_t sigDigits = 2, Option_t *options = "NELU", Double_t xmin=0.65,
Double_t xmax= 0.99,Double_t ymax=0.95, const RooCmdArg* formatCmd=0) ;

void fixOutputsAndLogErrors(RooSpan<double>& outputs, std::size_t begin) const;
void logBatchComputationErrors(RooSpan<const double>& outputs, std::size_t begin) const;

protected:
virtual RooPlot *plotOn(RooPlot *frame, PlotOpt o) const;
Expand Down Expand Up @@ -354,10 +351,6 @@ class RooAbsPdf : public RooAbsReal {

Bool_t _selectComp ; // Component selection flag for RooAbsPdf::plotCompOn

static void raiseEvalError() ;

static Bool_t _evalError ;

RooNumGenConfig* _specGeneratorConfig ; //! MC generator configuration specific for this object

TString _normRange ; // Normalization range
Expand Down
175 changes: 63 additions & 112 deletions roofit/roofitcore/src/RooAbsPdf.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,6 @@ ClassImp(RooAbsPdf::GenSpec);
;

Int_t RooAbsPdf::_verboseEval = 0;
Bool_t RooAbsPdf::_evalError = kFALSE ;
TString RooAbsPdf::_normRangeOverride ;

////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -335,49 +334,6 @@ Double_t RooAbsPdf::getValV(const RooArgSet* nset) const
return _value ;
}

////////////////////////////////////////////////////////////////////////////////
/// Check for infinity or NaN.
/// \param[in] inputs Array to check
/// \return True if either infinity or NaN were found.
namespace {
template<class T>
bool checkInfNaN(const T& inputs)
{
// check for a math error or negative value
bool nan = false;
bool neg = false;

for (double val : inputs) { //CHECK_VECTORISE
nan |= std::isnan(val);
neg |= val < 0;
}

return nan || neg;
}
}


////////////////////////////////////////////////////////////////////////////////
/// Scan through outputs and fix+log all nans and negative values.
/// \param[in/out] outputs Array to be scanned & fixed.
/// \param[in] begin Begin of event range. Only needed to print the correct event number
/// where the error occurred.
void RooAbsPdf::fixOutputsAndLogErrors(RooSpan<double>& outputs, std::size_t begin) const {
for (unsigned int i=0; i<outputs.size(); ++i) {
const double value = outputs[i];
if (std::isnan(outputs[i])) {
logEvalError(Form("p.d.f value of (%s) is Not-a-Number (%f), forcing value to zero for entry %zu",
GetName(), value, begin+i));
outputs[i] = 0;
}
if (outputs[i] < 0.) {
logEvalError(Form("p.d.f value of (%s) is less than zero (%f), forcing value to zero for entry %zu",
GetName(), value, begin+i));
outputs[i] = 0;
}
}
}


////////////////////////////////////////////////////////////////////////////////
/// Compute batch of values for given range, and normalise by integrating over
Expand Down Expand Up @@ -409,10 +365,6 @@ RooSpan<const double> RooAbsPdf::getValBatch(std::size_t begin, std::size_t maxS
maxSize = outputs.size();
_normSet = tmp;

if (checkInfNaN(outputs)) {
fixOutputsAndLogErrors(outputs, begin);
}

_batchData.setStatus(begin, maxSize, BatchHelpers::BatchData::kReady);

return outputs;
Expand All @@ -431,9 +383,6 @@ RooSpan<const double> RooAbsPdf::getValBatch(std::size_t begin, std::size_t maxS

auto outputs = evaluateBatch(begin, maxSize);
maxSize = outputs.size();
if (checkInfNaN(outputs)) {
fixOutputsAndLogErrors(outputs, begin);
}

// Evaluate denominator
const double normVal = _norm->getVal();
Expand Down Expand Up @@ -781,54 +730,86 @@ Double_t RooAbsPdf::getLogVal(const RooArgSet* nset) const


////////////////////////////////////////////////////////////////////////////////
/// Compute the log-likelihoods for all events in the requested batch.
/// The arguments are passed over to getValBatch().
/// \param[in] begin Start of the batch.
/// \param[in] size Maximum size of the batch.
/// \return Returns a batch of doubles that contains the log probabilities.
RooSpan<double> RooAbsPdf::getLogValBatch(std::size_t begin, std::size_t batchSize,
const RooArgSet* normSet) const
{
auto pdfValues = getValBatch(begin, batchSize, normSet);

//TODO avoid allocate&destroy?
std::vector<double> outputs(pdfValues.size());
/// Check for infinity or NaN.
/// \param[in] inputs Array to check
/// \return True if either infinity or NaN were found.
namespace {
template<class T>
bool checkInfNaNNeg(const T& inputs) {
// check for a math error or negative value
bool inf = false;
bool nan = false;
bool neg = false;

/* TODO
if (fabs(prob)>1e6) {
coutW(Eval) << "RooAbsPdf::getLogVal(" << GetName() << ") WARNING: large likelihood value: " << prob << endl ;
for (double val : inputs) { //CHECK_VECTORISE
inf |= !std::isfinite(val);
nan |= TMath::IsNaN(val); // Works also during fast math
neg |= val < 0;
}

if(prob < 0) {
return inf || nan || neg;
}
}

logEvalError("getLogVal() top-level p.d.f evaluates to a negative number") ;

return 0;
////////////////////////////////////////////////////////////////////////////////
/// Scan through outputs and fix+log all nans and negative values.
/// \param[in/out] outputs Array to be scanned & fixed.
/// \param[in] begin Begin of event range. Only needed to print the correct event number
/// where the error occurred.
void RooAbsPdf::logBatchComputationErrors(RooSpan<const double>& outputs, std::size_t begin) const {
for (unsigned int i=0; i<outputs.size(); ++i) {
const double value = outputs[i];
if (TMath::IsNaN(outputs[i])) {
logEvalError(Form("p.d.f value of (%s) is Not-a-Number (%f) for entry %zu",
GetName(), value, begin+i));
} else if (!std::isfinite(outputs[i])){
logEvalError(Form("p.d.f value of (%s) is (%f) for entry %zu",
GetName(), value, begin+i));
} else if (outputs[i] < 0.) {
logEvalError(Form("p.d.f value of (%s) is less than zero (%f) for entry %zu",
GetName(), value, begin+i));
}
}
if(prob == 0) {
}

logEvalError("getLogVal() top-level p.d.f evaluates to zero") ;
////////////////////////////////////////////////////////////////////////////////
/// Compute the log-likelihoods for all events in the requested batch.
/// The arguments are passed over to getValBatch().
/// \param[in] begin Start of the batch.
/// \param[in] size Maximum size of the batch. Depending on data layout and memory, the batch
/// may come back smaller.
/// \return Returns a batch of doubles that contains the log probabilities.
RooSpan<const double> RooAbsPdf::getLogValBatch(std::size_t begin, std::size_t maxSize,
const RooArgSet* normSet) const
{
auto pdfValues = getValBatch(begin, maxSize, normSet);

return log((double)0);
if (checkInfNaNNeg(pdfValues)) {
logBatchComputationErrors(pdfValues, begin);
}

if (TMath::IsNaN(prob)) {
logEvalError("getLogVal() top-level p.d.f evaluates to NaN") ;
return log((double)0);
auto output = _batchData.makeWritableBatchUnInit(begin, pdfValues.size());

}
*/
for (std::size_t i = 0; i < pdfValues.size(); ++i) { //CHECK_VECTORISE
const double prob = pdfValues[i];

for (unsigned int i = 0; i < pdfValues.size(); ++i) { //CHECK_VECTORISE
#ifdef USE_VDT
outputs[i] = vdt::fast_log(pdfValues[i]);
double theLog = vdt::fast_log(prob);
#else
outputs[i] = log(pdfValues[i]);
double theLog = log(prob);
#endif

if (prob < 0) {
theLog = prob;
} else if (prob == 0 || TMath::IsNaN(prob)) {
theLog = -std::numeric_limits<double>::infinity();
}

output[i] = theLog;
}

return RooSpan<double>(std::move(outputs));
return output;
}

////////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -3412,36 +3393,6 @@ RooArgSet* RooAbsPdf::getAllConstraints(const RooArgSet& observables, RooArgSet&
}


////////////////////////////////////////////////////////////////////////////////
/// Clear the evaluation error flag

void RooAbsPdf::clearEvalError()
{
_evalError = kFALSE ;
}



////////////////////////////////////////////////////////////////////////////////
/// Return the evaluation error flag

Bool_t RooAbsPdf::evalError()
{
return _evalError ;
}



////////////////////////////////////////////////////////////////////////////////
/// Raise the evaluation error flag

void RooAbsPdf::raiseEvalError()
{
_evalError = kTRUE ;
}



////////////////////////////////////////////////////////////////////////////////
/// Returns the default numeric MC generator configuration for all RooAbsReals

Expand Down
15 changes: 6 additions & 9 deletions roofit/roofitcore/src/RooMinimizerFcn.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ double RooMinimizerFcn::DoEval(const double *x) const
double fvalue = _funct->getVal();
RooAbsReal::setHideOffset(kTRUE) ;

if (RooAbsPdf::evalError() || RooAbsReal::numEvalErrors()>0 || fvalue>1e30) {
if (RooAbsReal::numEvalErrors()>0 || fvalue > 1e30) {

if (_printEvalErrors>=0) {

Expand All @@ -542,30 +542,27 @@ double RooMinimizerFcn::DoEval(const double *x) const
oocoutW(_context,Minimization) << "RooMinimizerFcn: Minimized function has error status but is ignored" << endl ;
}

TIterator* iter = _floatParamList->createIterator() ;
RooRealVar* var ;
Bool_t first(kTRUE) ;
ooccoutW(_context,Minimization) << "Parameter values: " ;
while((var=(RooRealVar*)iter->Next())) {
for (const auto par : *_floatParamList) {
auto var = static_cast<const RooRealVar*>(par);
if (first) { first = kFALSE ; } else ooccoutW(_context,Minimization) << ", " ;
ooccoutW(_context,Minimization) << var->GetName() << "=" << var->getVal() ;
}
delete iter ;
ooccoutW(_context,Minimization) << endl ;

RooAbsReal::printEvalErrors(ooccoutW(_context,Minimization),_printEvalErrors) ;
ooccoutW(_context,Minimization) << endl ;
}

if (_doEvalErrorWall) {
fvalue = _maxFCN+1 ;
fvalue = _maxFCN+1;
}

RooAbsPdf::clearEvalError() ;
RooAbsReal::clearEvalErrorLog() ;
_numBadNLL++ ;
} else if (fvalue>_maxFCN) {
_maxFCN = fvalue ;
} else {
_maxFCN = std::max(fvalue, _maxFCN);
}

// Optional logging
Expand Down
3 changes: 1 addition & 2 deletions roofit/roofitcore/src/RooMinuit.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -1222,7 +1222,7 @@ void RooMinuitGlue(Int_t& /*np*/, Double_t* /*gin*/,
f= context->_func->getVal() ;
RooAbsReal::setHideOffset(kTRUE) ;
context->_evalCounter++ ;
if ( RooAbsPdf::evalError() || RooAbsReal::numEvalErrors()>0 || f>1e30) {
if (RooAbsReal::numEvalErrors()>0 || f>1e30) {

if (context->_printEvalErrors>=0) {

Expand Down Expand Up @@ -1253,7 +1253,6 @@ void RooMinuitGlue(Int_t& /*np*/, Double_t* /*gin*/,
f = maxFCN+1 ;
}

RooAbsPdf::clearEvalError() ;
RooAbsReal::clearEvalErrorLog() ;
context->_numBadNLL++ ;
} else if (f>maxFCN) {
Expand Down

0 comments on commit 9f739cc

Please sign in to comment.