Skip to content

Some questions about "AsymptoticLimits.cc" #1037

@desycms107

Description

@desycms107

Dear Combine experts,

I really appreciate the scripts that you provide that make limits for so many CMS analysis. But while I read through the codes, I have some questions that I hope can be clarified so that we might reduce misunderstanding from users:

  1. May I ask why we set rMin directly to 0 when we use $\widetilde{q}$? I wonder if MIGRAD will get the gradient calculation wrong if $r$ isn't allowed to get slightly toward negative values, causing biased minimisation. Could we follow the definition in eq. (16) of the Asymptotic formulae paper, re-define the NLL if $\widehat{r}$ is either less than 0 or larger than $r$?

    r->setMin(qtilde_ ? 0 : -r->getMax());

  2. I think it is good that rMax is set to be 3 times the uncertainty of r (rErr). So the while loop has much smaller chance to become an infinite loop (than the one mentioned in point 8). But I think we should put a warning whenever the rMax is doubled to let the user know the uncertainty of r increases fast with r, which could be due to incorrect model configuration or large systematics applying to signals.

    double rMin = std::max<double>(0, r->getVal()), rMax = rMin + 3 * rErr;

  3. I wonder why we do a logarithmic interpolation for the observed limit but bissection method for the expected limit as default? When a user creates an Asimov dataset using "-t -1", the user would expect the observed limit to match the 50% quantile expected limit. But one wouldn't because the limit-searching methods are not same.

    double rCross = rMin + (rMax-rMin)*log(clsMax/clsTarget)/log(clsMax/clsMin);

    I also wonder what is the mathematical basis that the r should be lienar to the natural log of CLs. According to equations like (69) in the Asymptotic formulae paper, the relation is an inverse CDF of the normal distribution, not natural log.

  4. May I ask the mathematical basis fo this 80-20 interpolation ?

    limit = 0.8*rCross + 0.2*rMax;

  5. Is it intentional to use the function "minimize" for unconstrained fit:

    minim.minimize(verbose-2);

    But then we use the function "improve" for the constrained fit"
    if (!minimD.improve(verbose-2) && picky_) return -999;

  6. I thought qmu can never become negative according to the definition of qmu in the Asymptotic formulae paper's eq (16).

    double qmu = 2*(nllD_->getVal() - minNllD_); if (qmu < 0) qmu = 0;

    Is this to prevent numerical errors? The setting of qmu to 0 when $\widehat{r}&gt;r$ is done here already:

  7. According to page 20 of Minuit documentation, the error level (the value to 1 $\sigma$) affects the precision of the minimiser: estimated distance to minimum (EDM) requirement is 0.001*[tolerance = 0.1]*[error-level]. The RooFit default value is 1. But in the following snippet, it changed it to 1.92

    minim.setErrorLevel(0.5*pow(ROOT::Math::normal_quantile(1-0.5*(1-cl),1.0), 2)); // the 0.5 is because qmu is -2*NLL

    So the precision becomes worse by this change. But in the following lines, it used this less precise fit to determine whether the Asimov dataset is well-behaved.
    CombineLogger::instance().log("AsymptoticLimits.cc",__LINE__,std::string(Form("[WARNING] Best fit of asimov dataset is at %s = %f (%f times %sMax), while it should be at zero",r->GetName(), r->getVal(), r->getVal()/r->getMax(), r->GetName())),__func__);

    What's stranger is that the reference is 0.001 times rMax, which is rather arbitrary. I suggested we turn off this warning as it might mislead careful users that turn up the verbose level, or we don't change the error-level for higher precision and could use the ratio $\widehat{r}$ over $\sigma_{\text{fit}}(r)$ as a indicator of the fit healthiness.

  8. The current default way of calculating expected limit is via the "bisection", which contains a while loop:

    while (rErr > std::max(rRelAccuracy_*rCross, rAbsAccuracy_)) {

    This implied that user might be stuck in an infinite loop if the rMax and rMin were set too narrow. In contrast, the method "stepping" has a warning when it couldn't find the required NLL shift and won't get stuck in an infinite loop:
    if (verbose > 1) CombineLogger::instance().log("AsymptoticLimits.cc",__LINE__,std::string(Form("reached hard bound at %s = %f\n", r->GetName(), rCross)),__func__);

Best regards,

Kuan
B2G Combine contact

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions