@@ -1597,7 +1597,7 @@ void xRooNLLVar::xRooHypoPoint::Print(Option_t *) const
15971597 }
15981598 std::cout << " , pllType: " ;
15991599 switch (fPllType ) {
1600- case 0 : std::cout << " qmu " ; break ;
1600+ case 0 : std::cout << " tmu " ; break ;
16011601 case 1 : std::cout << " qmu or qmutilde" ; break ; // should check for 'physical' to decide if is latter
16021602 case 2 : std::cout << " q0" ; break ;
16031603 case 4 : std::cout << " u0" ; break ;
@@ -1775,6 +1775,14 @@ std::shared_ptr<xRooNLLVar::xRooHypoPoint> xRooNLLVar::xRooHypoPoint::asimov(boo
17751775 // dynamic_cast<RooRealVar *>(p)->removeRange("physical"); -- can't use this as will modify shared property
17761776 if (auto v = dynamic_cast <RooRealVar *>(p)) {
17771777 v->deleteSharedProperties (); // effectively removes all custom ranges
1778+ if (v->getVal () == 0 ) {
1779+ // for discovery tests, we generate asimov at mu!=0 and then evaluate the two sided
1780+ // at some value of mu. Normally we would use mu=0 but if we have a bin
1781+ // with only signal contribution (no bkg) will get asimov data in that bin
1782+ // and no prediction ... the cfit(mu=0) will never succeed on this
1783+ // so lets move to half the alt value instead (the value used to generate)
1784+ v->setVal (theFit->constPars ().getRealValue (v->GetName ()) * 0.5 );
1785+ }
17781786 }
17791787 }
17801788
@@ -1799,15 +1807,19 @@ xRooNLLVar::xValueWithError xRooNLLVar::xRooHypoPoint::pNull_asymp(double nSigma
17991807 auto first_poi = dynamic_cast <RooRealVar *>(poi ().first ());
18001808 if (!first_poi)
18011809 return std::pair<double , double >(std::numeric_limits<double >::quiet_NaN (), 0 );
1802- auto _sigma_mu = sigma_mu ();
1810+ double lowBound = first_poi->getMin (" physical" );
1811+ double hiBound = first_poi->getMax (" physical" );
1812+ // don't need to calculate sigma_mu if physical boundaries at infinity, PValue doesn't depend on it
1813+ auto _sigma_mu =
1814+ (lowBound == -std::numeric_limits<double >::infinity () && hiBound == std::numeric_limits<double >::infinity ())
1815+ ? std::pair<double , double >(0 , 0 )
1816+ : sigma_mu ();
18031817 double nom = xRooFit::Asymptotics::PValue (fPllType , ts_asymp (nSigma).first , fNullVal (), fNullVal (), _sigma_mu.first ,
1804- first_poi->getMin (" physical" ), first_poi->getMax (" physical" ));
1805- double up =
1806- xRooFit::Asymptotics::PValue (fPllType , ts_asymp (nSigma).first + ts_asymp (nSigma).second , fNullVal (), fNullVal (),
1807- _sigma_mu.first , first_poi->getMin (" physical" ), first_poi->getMax (" physical" ));
1808- double down =
1809- xRooFit::Asymptotics::PValue (fPllType , ts_asymp (nSigma).first - ts_asymp (nSigma).second , fNullVal (), fNullVal (),
1810- _sigma_mu.first , first_poi->getMin (" physical" ), first_poi->getMax (" physical" ));
1818+ lowBound, hiBound);
1819+ double up = xRooFit::Asymptotics::PValue (fPllType , ts_asymp (nSigma).first + ts_asymp (nSigma).second , fNullVal (),
1820+ fNullVal (), _sigma_mu.first , lowBound, hiBound);
1821+ double down = xRooFit::Asymptotics::PValue (fPllType , ts_asymp (nSigma).first - ts_asymp (nSigma).second , fNullVal (),
1822+ fNullVal (), _sigma_mu.first , lowBound, hiBound);
18111823 return std::pair (nom, std::max (std::abs (up - nom), std::abs (down - nom)));
18121824}
18131825
@@ -2248,8 +2260,8 @@ xRooNLLVar::xValueWithError xRooNLLVar::xRooHypoPoint::sigma_mu(bool readOnly)
22482260 }
22492261
22502262 auto out = asi->pll (readOnly);
2251- return std::pair<double , double >(std::abs (fNullVal () - fAltVal ()) / sqrt (out.first ),
2252- out.second * 0.5 * std::abs (fNullVal () - fAltVal ()) /
2263+ return std::pair<double , double >(std::abs (asi-> fNullVal () - fAltVal ()) / sqrt (out.first ),
2264+ out.second * 0.5 * std::abs (asi-> fNullVal () - fAltVal ()) /
22532265 (out.first * sqrt (out.first )));
22542266}
22552267
@@ -2615,6 +2627,10 @@ xRooNLLVar::hypoPoint(const char *poiValues, double alt_value, const xRooFit::As
26152627 AutoRestorer snap (*fFuncVars );
26162628
26172629 out.nllVar = std::make_shared<xRooNLLVar>(*this );
2630+ // clear the underlying RooAbsReal, so that we don't accidentally alter it (e.g. setAttribute readOnly)
2631+ // and therefore alter the xRooNLLVar object we are creating this hypoPoint from
2632+ // basically ensure the hypoPoint has an independent version of the function
2633+ out.nllVar ->reset ();
26182634 out.fData = getData ();
26192635
26202636 TStringToken pattern (poiValues, " ," );
@@ -3151,6 +3167,10 @@ xRooNLLVar::hypoSpace(const char *parName, const xRooFit::Asymptotics::PLLType &
31513167 throw std::runtime_error("You must specify at least one POI for the hypoSpace");
31523168 }*/
31533169 s.fNlls [s.fPdfs .begin ()->second ] = std::make_shared<xRooNLLVar>(*this );
3170+ // clear the underlying RooAbsReal, so that we don't accidentally alter it (e.g. setAttribute readOnly)
3171+ // and therefore alter the xRooNLLVar object we are creating this hypoPoint from
3172+ // basically ensure the hypoPoint has an independent version of the function
3173+ s.fNlls [s.fPdfs .begin ()->second ]->reset ();
31543174 s.fTestStatType = pllType;
31553175
31563176 for (auto poi : s.poi ()) {
0 commit comments