def binomialLimits(nsuccess, ntotal, cl=None, sigma=False): """ NAME: binomialLimits AUTHOR: Tim Haines, [email protected] PURPOSE: This function computes the single-sided upper and lower confidence limits for the binomial distribution. CATEGORY: Statistics and probability CALLING SEQUENCE: (u,l) = binomialLimits(nsuccess, ntotal, [, cl [, sigma]]) INPUTS: nsuccess: A strictly nonnegative integer that specifies the number of successes in ntotal Bernoulli trials. Can be a list or a numpy array. ntotal: An integer strictly greater than nsuccess that specifies the number of Bernoulli trials. Can be a list or a numpy array. OPTIONAL INPUTS: cl: The confidence level in the interval [0, 1]. The default is 0.8413 (i.e., 1 sigma) OPTIONS: sigma: If this is true, then cl is assumed to be a multiple of sigma, and the actual confidence level is computed from the standard normal distribution with parameter cl. RETURNS: Two lists: the first containing the upper limits, and the second containing the lower limits. If the inputs are numpy arrays, then numpy arrays are returned instead of lists. If the inputs are scalars, then scalars are returned. REFERENCES: N. Gehrels. Confidence limits for small numbers of events in astrophysical data. The Astrophysical Journal, 303:336-346, April 1986. EXAMPLE: I have a mass bin with 100 galaxies (20 reds and 80 blues) and I am computing the fraction of reds to blues, then for this bin NSUCCESS = 20 and NTOTAL = 100. To compute the confidence limits at the 2.5 sigma level, use (u,l) = binomialLimits(20, 100, 2.5, sigma=True) u = 0.31756 l = 0.11056 Since these are the confidence limits, the fraction would be reported as 0.2 (+0.11756, -0.08944) """ if cl is None: cl = 1.0 sigma = True if sigma: cl = ndtr(cl) if not type(nsuccess) == type(ntotal): exit('nsuccess and ntotal must have the same type') # Since there isn't any syntactical advantage to using # numpy, just convert them to lists and carry on. isNumpy = False if isinstance(nsuccess,numpy.ndarray): nsuccess = nsuccess.tolist() ntotal = ntotal.tolist() isNumpy = True # Box single values into a list isScalar = False if not isinstance(nsuccess,list): nsuccess = [nsuccess] ntotal = [ntotal] isScalar = True # Must have the same length if not len(nsuccess) == len(ntotal): exit('nsuccess and total must have same length') upper = [] lower = [] for (s,t) in zip(nsuccess,ntotal): nfail = t - s # See Gehrels (1986) for details if nfail == 0: upper.append(1.0) else: upper.append(bdtri(s,t,1-cl)) # See Gehrels (1986) for details if s == 0: lower.append(0.0) else: lower.append(1 - bdtri(nfail,t,1-cl)) if isNumpy: upper = numpy.array(upper) lower = numpy.array(lower) # Scalar-in/scalar-out if isScalar: return (upper[0],lower[0]) return (upper,lower)
def test_domain(self, k, n, p): val = sc.bdtri(k, n, p) assert np.isnan(val)
def test_bdtr_bdtri_roundtrip(self): bdtr_vals = sc.bdtr([0, 1, 2], 2, 0.5) roundtrip_vals = sc.bdtri([0, 1, 2], 2, bdtr_vals) assert_allclose(roundtrip_vals, [0.5, 0.5, np.nan])
def test_inf(self, k, n, p): with suppress_warnings() as sup: sup.filter(DeprecationWarning) val = sc.bdtri(k, n, p) assert np.isnan(val)
def test_rounding(self): double_val = sc.bdtri([0.1, 1.1], 2, 0.5) int_val = sc.bdtri([0, 1], 2, 0.5) assert_allclose(double_val, int_val)
def test_sum_is_one(self): val = sc.bdtri([0, 1], 2, 0.5) actual = np.asarray([1 - 1 / np.sqrt(2), 1 / np.sqrt(2)]) assert_allclose(val, actual)
def test_value(self): val = sc.bdtri(0, 1, 0.5) assert_allclose(val, 0.5)
def binomialLimits(nsuccess, ntotal, cl=None, sigma=False): """ NAME: binomialLimits AUTHOR: Tim Haines, [email protected] PURPOSE: This function computes the single-sided upper and lower confidence limits for the binomial distribution. CATEGORY: Statistics and probability CALLING SEQUENCE: (u,l) = binomialLimits(nsuccess, ntotal, [, cl [, sigma]]) INPUTS: nsuccess: A strictly nonnegative integer that specifies the number of successes in ntotal Bernoulli trials. Can be a list or a numpy array. ntotal: An integer strictly greater than nsuccess that specifies the number of Bernoulli trials. Can be a list or a numpy array. OPTIONAL INPUTS: cl: The confidence level in the interval [0, 1]. The default is 0.8413 (i.e., 1 sigma) OPTIONS: sigma: If this is true, then cl is assumed to be a multiple of sigma, and the actual confidence level is computed from the standard normal distribution with parameter cl. RETURNS: Two lists: the first containing the upper limits, and the second containing the lower limits. If the inputs are numpy arrays, then numpy arrays are returned instead of lists. If the inputs are scalars, then scalars are returned. REFERENCES: N. Gehrels. Confidence limits for small numbers of events in astrophysical data. The Astrophysical Journal, 303:336-346, April 1986. EXAMPLE: I have a mass bin with 100 galaxies (20 reds and 80 blues) and I am computing the fraction of reds to blues, then for this bin NSUCCESS = 20 and NTOTAL = 100. To compute the confidence limits at the 2.5 sigma level, use (u,l) = binomialLimits(20, 100, 2.5, sigma=True) u = 0.31756 l = 0.11056 Since these are the confidence limits, the fraction would be reported as 0.2 (+0.11756, -0.08944) """ if cl is None: cl = 1.0 sigma = True if sigma: cl = ndtr(cl) if not type(nsuccess) == type(ntotal): exit('nsuccess and ntotal must have the same type') # Since there isn't any syntactical advantage to using # numpy, just convert them to lists and carry on. isNumpy = False if isinstance(nsuccess, numpy.ndarray): nsuccess = nsuccess.tolist() ntotal = ntotal.tolist() isNumpy = True # Box single values into a list isScalar = False if not isinstance(nsuccess, list): nsuccess = [nsuccess] ntotal = [ntotal] isScalar = True # Must have the same length if not len(nsuccess) == len(ntotal): exit('nsuccess and total must have same length') upper = [] lower = [] for (s, t) in zip(nsuccess, ntotal): nfail = t - s # See Gehrels (1986) for details if nfail == 0: upper.append(1.0) else: upper.append(bdtri(s, t, 1 - cl)) # See Gehrels (1986) for details if s == 0: lower.append(0.0) else: lower.append(1 - bdtri(nfail, t, 1 - cl)) if isNumpy: upper = numpy.array(upper) lower = numpy.array(lower) # Scalar-in/scalar-out if isScalar: return (upper[0], lower[0]) return (upper, lower)