def test_volume_lambda(self): ''' Check the dependence of upper limits on volume and lambda. ''' # volumes to test: these range over 5 orders of magnitude volumes = numpy.logspace(-3,2,50) for vol in volumes: # take a large, fixed set of mu samples to bracket the 1/vol values mu = numpy.logspace(-5,5,1e5) # lambda = 0 likely = upper_limit_utils.margLikelihood([vol], [0], mu) post = likely # uniform prior; NB compute_upper_limit works for unnormalized posteriors muhi = upper_limit_utils.compute_upper_limit(mu, post, alpha = 0.90) self.assertTrue( 2.30/vol < muhi < 2.31/vol ) # lambda = 1 likely = upper_limit_utils.margLikelihood([vol], [1], mu) post = likely # uniform prior muhi = upper_limit_utils.compute_upper_limit(mu, post, alpha = 0.90) self.assertTrue( 3.27/vol < muhi < 3.28/vol ) # lambda = infinity likely = upper_limit_utils.margLikelihood([vol], [1e6], mu) post = likely # uniform prior muhi = upper_limit_utils.compute_upper_limit(mu, post, alpha = 0.90) self.assertTrue( 3.885/vol < muhi < 3.895/vol )
def test_logspacing_rate_upper_limit(self): ''' Give the upper_limit function some known distributions with known 95% upper limits. ''' # Exponential mu = numpy.logspace(-5,2,1e6) post = numpy.exp(-mu) muhi = upper_limit_utils.compute_upper_limit(mu, post, alpha = 0.95) self.assertTrue( abs( muhi - numpy.log(20) ) < 0.0001 ) # get upper limit to 4 decimal places # Gaussian over positive mu post = numpy.exp(-(mu**2)/2) muhi = upper_limit_utils.compute_upper_limit(mu, post, alpha = 0.95) self.assertTrue( abs(muhi - 1.95996) < 0.0001 ) # get upper limit to 4 decimal places
def test_compute_many_posterior(self): # for 0 lambda's, volumes add mu = numpy.linspace(0,100,1e4) post1 = upper_limit_utils.margLikelihood([5,10,4,6],[0,0,0,0],mu) post2 = upper_limit_utils.margLikelihood([15,10],[0,0],mu) post3 = upper_limit_utils.margLikelihood([25],[0],mu) mu_90_1 = upper_limit_utils.compute_upper_limit(mu,post1/post1.sum(),0.90) mu_90_2 = upper_limit_utils.compute_upper_limit(mu,post2/post2.sum(),0.90) mu_90_3 = upper_limit_utils.compute_upper_limit(mu,post3/post3.sum(),0.90) self.assertTrue( (mu_90_2-mu_90_1) < 0.05 ) self.assertTrue( (mu_90_3-mu_90_1) < 0.05 ) self.assertTrue( (mu_90_3-mu_90_2) < 0.05 )
def test_zero_volume_search(self): ''' Check that running a search with zero volume has no effect on upper limits. ''' # no prior specified, unit volume mu = numpy.linspace(0,100,1e4) likely = upper_limit_utils.margLikelihood([1], [0], mu) post = likely/likely.sum() #uniform prior muhi_np = upper_limit_utils.compute_upper_limit(mu, post, alpha = 0.90) # posterior for prior, zero volume likely = upper_limit_utils.margLikelihood([0],[0], mu) post *= likely #uniform post for prior post /= post.sum() muhi_zv = upper_limit_utils.compute_upper_limit(mu, post, alpha = 0.90) self.assertTrue( abs(muhi_zv - muhi_np) < 0.01 )
def test_zero_padded_uniform(self): # Uniform posterior mumax = 15 mu = numpy.linspace(0,2*mumax,2*1e6) post = numpy.concatenate((numpy.ones(len(mu)/2),numpy.zeros(len(mu)/2))) a = 1 muhi = upper_limit_utils.compute_upper_limit(mu, post, alpha = 1) self.assertTrue( a*mumax - 0.0001 < muhi < a*mumax + 0.0001) # get upper limit to 4 sig figs
def test_uniform_upper_limit(self): # Uniform posterior mumax = 15 mu = numpy.linspace(0,mumax,1e6) post = numpy.ones(len(mu)) alphas = numpy.arange(0.1,1,0.1) for a in alphas: muhi = upper_limit_utils.compute_upper_limit(mu, post, alpha = a) self.assertTrue( a*mumax - 0.0001 < muhi < a*mumax + 0.0001) # get upper limit to 4 decimal places
def test_gaussian_upper_limit(self): ''' Give the upper_limit function some known distributions with known 95% upper limits. ''' # Gaussian over *positive* mu: 95% limit is equal to sqrt(2)*erfc^-1(0.05) mu = numpy.linspace(0,5,1e6) post = numpy.exp(-(mu**2)/2) muhi = upper_limit_utils.compute_upper_limit(mu, post, alpha = 0.95) self.assertTrue( abs(muhi - 1.95996) < 0.0001 ) # get upper limit to 4 decimal places
def test_volume_additivity(self): ''' For a series of independent searches with 0 lambda, the search volumes add. Check that upper limits computed by summing volumes is same as upper limit obtained by iteratively applying the individual searches. ''' # volume additivity check mu = numpy.linspace(0,100,1e4) likely = upper_limit_utils.margLikelihood([1], [0], mu) post = likely/likely.sum() #uniform prior post *= upper_limit_utils.margLikelihood([9], [0], mu) # use post for prior post /= post.sum() muhi_1p9 = upper_limit_utils.compute_upper_limit(mu, post, alpha = 0.90) likely = upper_limit_utils.margLikelihood([10], [0], mu) post = likely/likely.sum() #uniform prior muhi_10 = upper_limit_utils.compute_upper_limit(mu, post, alpha = 0.90) self.assertTrue( abs( muhi_1p9 - muhi_10 ) < 0.01 )
def test_confidence_interval(self): ''' The confidence interval function computes a minimal width interval. For a symmetric distribution, this interval is the same as computing upper and lower limits at half-confidences. For a monotonically decreasing distribution, this interval is the same as the upper limit at the same confidence level. ''' exes = numpy.arange(-10,10,0.01) post = numpy.exp(-exes**2/2) lo, hi = upper_limit_utils.confidence_interval_min_width(exes, post, 0.9) lo2 = upper_limit_utils.compute_lower_limit(exes, post, 0.95) hi2 = upper_limit_utils.compute_upper_limit(exes, post, 0.95) self.assertTrue( abs(lo - lo2) < 0.001 ) self.assertTrue( abs(hi - hi2) < 0.001 )
def test_exponential_upper_limit(self): # Exponential mu = numpy.linspace(0,15,1e6) post = numpy.exp(-mu) muhi = upper_limit_utils.compute_upper_limit(mu, post, alpha = 0.95) self.assertTrue( abs( muhi - numpy.log(20) ) < 0.0001 ) # get upper limit to 4 decimal places