def get_volume_derivative(self, instruments): injfnames = self.inj_fnames FAR = self.far[instruments] zero_lag_segments = self.zero_lag_segments[instruments] gw = self.gw twoDMassBins = self.twoDMassBins #determine binning up front for infinite FAR found, missed = self.get_injections(instruments, FAR=float("inf")) dbin = rate.LogarithmicBins(min([l.distance for l in found]), max([l.distance for l in found]), int(self.opts.dist_bins)) livetime = float(abs(zero_lag_segments)) FARh = FAR * 100000 FARl = FAR * 0.001 nbins = 5 FARS = rate.LogarithmicBins(FARl, FARh, nbins) vA = [] vA2 = [] for far in FARS.centres(): print("computing volume at FAR " + str(far), file=sys.stderr) vAt, vA2t = self.twoD_SearchVolume(instruments, dbin=dbin, FAR=far, bootnum=1) # we need to compute derivitive of log according to ul paper vAt.array = scipy.log10(vAt.array + 0.001) vA.append(vAt) # the derivitive is calcuated with respect to FAR * t FARTS = rate.LogarithmicBins(FARl * livetime, FARh * livetime, nbins) return self._derivitave_fit(FARTS, FAR * livetime, vA, twoDMassBins)
def get_volume_derivative(injfnames, twoDMassBins, dBin, FAR, zero_lag_segments, gw): if (FAR == 0): print("\n\nFAR = 0\n \n") # FIXME lambda = ~inf if loudest event is above loudest timeslide? output = rate.BinnedArray(twoDMassBins) output.array = 10**6 * numpy.ones(output.array.shape) return output livetime = float(abs(zero_lag_segments)) FARh = FAR * 100000 FARl = FAR * 0.001 nbins = 5 FARS = rate.LogarithmicBins(FARl, FARh, nbins) vA = [] vA2 = [] for far in FARS.centres(): m, f = get_injections(injfnames, far, zero_lag_segments) print("computing volume at FAR " + str(far), file=sys.stderr) vAt, vA2t = twoD_SearchVolume(f, m, twoDMassBins, dBin, gw, livetime, 1) # we need to compute derivitive of log according to ul paper vAt.array = scipy.log10(vAt.array + 0.001) vA.append(vAt) # the derivitive is calcuated with respect to FAR * t FARS = rate.LogarithmicBins(FARl * livetime, FARh * livetime, nbins) return derivitave_fit(FARS, FAR * livetime, vA, twoDMassBins)
def __init__(self, x_instrument, y_instrument, magnitude, desc, min_magnitude, max_magnitude): self.fig, self.axes = SnglBurstUtils.make_burst_plot( "%s %s" % (x_instrument, desc), "%s %s" % (y_instrument, desc)) self.fig.set_size_inches(6, 6) self.axes.loglog() self.x_instrument = x_instrument self.y_instrument = y_instrument self.magnitude = magnitude self.foreground_x = [] self.foreground_y = [] self.n_foreground = 0 self.n_background = 0 self.n_injections = 0 self.foreground_bins = rate.BinnedArray( rate.NDBins( (rate.LogarithmicBins(min_magnitude, max_magnitude, 1024), rate.LogarithmicBins(min_magnitude, max_magnitude, 1024)))) self.background_bins = rate.BinnedArray( rate.NDBins( (rate.LogarithmicBins(min_magnitude, max_magnitude, 1024), rate.LogarithmicBins(min_magnitude, max_magnitude, 1024)))) self.coinc_injection_bins = rate.BinnedArray( rate.NDBins( (rate.LogarithmicBins(min_magnitude, max_magnitude, 1024), rate.LogarithmicBins(min_magnitude, max_magnitude, 1024)))) self.incomplete_coinc_injection_bins = rate.BinnedArray( rate.NDBins( (rate.LogarithmicBins(min_magnitude, max_magnitude, 1024), rate.LogarithmicBins(min_magnitude, max_magnitude, 1024))))
def make_binning(plots): plots = [ plot for instrument in plots.keys() for plot in plots[instrument] if isinstance(plot, SimBurstUtils.Efficiency_hrss_vs_freq) ] if not plots: return None minx = min([min(plot.injected_x) for plot in plots]) maxx = max([max(plot.injected_x) for plot in plots]) miny = min([min(plot.injected_y) for plot in plots]) maxy = max([max(plot.injected_y) for plot in plots]) return rate.NDBins( (rate.LogarithmicBins(minx, maxx, 512), rate.LogarithmicBins(miny, maxy, 512)))
def _bin_events(self, binning=None): # called internally by finish() if binning is None: minx, maxx = min(self.injected_x), max(self.injected_x) miny, maxy = min(self.injected_y), max(self.injected_y) binning = rate.NDBins((rate.LogarithmicBins(minx, maxx, 256), rate.LogarithmicBins(miny, maxy, 256))) self.efficiency = rate.BinnedRatios(binning) for xy in zip(self.injected_x, self.injected_y): self.efficiency.incdenominator(xy) for xy in zip(self.found_x, self.found_y): self.efficiency.incnumerator(xy) # 1 / error^2 is the number of injections that need to be # within the window in order for the fractional uncertainty # in that number to be = error. multiplying by # bins_per_inj tells us how many bins the window needs to # cover, and taking the square root translates that into # the window's length on a side in bins. because the # contours tend to run parallel to the x axis, the window # is dilated in that direction to improve resolution. bins_per_inj = self.efficiency.used() / float(len(self.injected_x)) self.window_size_x = self.window_size_y = math.sqrt(bins_per_inj / self.error**2) self.window_size_x *= math.sqrt(2) self.window_size_y /= math.sqrt(2) if self.window_size_x > 100 or self.window_size_y > 100: # program will take too long to run raise ValueError( "smoothing filter too large (not enough injections)") print("The smoothing window for %s is %g x %g bins" % ("+".join( self.instruments), self.window_size_x, self.window_size_y), end=' ', file=sys.stderr) print("which is %g%% x %g%% of the binning" % (100.0 * self.window_size_x / binning[0].n, 100.0 * self.window_size_y / binning[1].n), file=sys.stderr)
def get_distance_bins(self, instruments, found=None, missed=None): if not found and not missed: found, missed = self.get_injections(instruments) if not found: print("Found no injections cannot compute distance bins ABORTING", file=sys.stderr) sys.exit(1) #Give the bins some padding based on the errors maxdist = max([s.distance for s in found]) mindist = min([s.distance for s in found]) if (maxdist < 0) or (mindist < 0) or (mindist > maxdist): print("minimum and maximum distances are screwy, maybe the distance errors given in the options don't make sense? ABORTING", file=sys.stderr) sys.exit(1) self.dBin[instruments] = rate.LogarithmicBins(mindist,maxdist,self.opts.dist_bins)
def create_efficiency_plot(axes, all_injections, found_injections, detection_threshold, cal_uncertainty): filter_width = 16.7 # formats axes.semilogx() axes.set_position([0.10, 0.150, 0.86, 0.77]) # set desired yticks axes.set_yticks((0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0)) axes.set_yticklabels((r"\(0\)", r"\(0.1\)", r"\(0.2\)", r"\(0.3\)", r"\(0.4\)", r"\(0.5\)", r"\(0.6\)", r"\(0.7\)", r"\(0.8\)", r"\(0.9\)", r"\(1.0\)")) axes.xaxis.grid(True, which = "major,minor") axes.yaxis.grid(True, which = "major,minor") # put made and found injections in the denominators and # numerators of the efficiency bins bins = rate.NDBins((rate.LogarithmicBins(min(sim.amplitude for sim in all_injections), max(sim.amplitude for sim in all_injections), 400),)) efficiency_num = rate.BinnedArray(bins) efficiency_den = rate.BinnedArray(bins) for sim in found_injections: efficiency_num[sim.amplitude,] += 1 for sim in all_injections: efficiency_den[sim.amplitude,] += 1 # generate and plot trend curves. adjust window function # normalization so that denominator array correctly # represents the number of injections contributing to each # bin: make w(0) = 1.0. note that this factor has no # effect on the efficiency because it is common to the # numerator and denominator arrays. we do this for the # purpose of computing the Poisson error bars, which # requires us to know the counts for the bins windowfunc = rate.gaussian_window(filter_width) windowfunc /= windowfunc[len(windowfunc) / 2 + 1] rate.filter_array(efficiency_num.array, windowfunc) rate.filter_array(efficiency_den.array, windowfunc) # regularize: adjust unused bins so that the efficiency is # 0, not NaN assert (efficiency_num.array <= efficiency_den.array).all() efficiency_den.array[(efficiency_num.array == 0) & (efficiency_den.array == 0)] = 1 line1, A50, A50_err = render_data_from_bins(file("string_efficiency.dat", "w"), axes, efficiency_num, efficiency_den, cal_uncertainty, filter_width, colour = "k", linestyle = "-", erroralpha = 0.2) # add a legend to the axes axes.legend((line1,), (r"\noindent Injections recovered with $\log \Lambda > %.2f$" % detection_threshold,), loc = "lower right") # adjust limits axes.set_xlim([3e-22, 3e-19]) axes.set_ylim([0.0, 1.0])
def rate_posterior_from_samples(samples): """ Construct and return a BinnedArray containing a histogram of a sequence of samples. If limits is None (default) then the limits of the binning will be determined automatically from the sequence, otherwise limits is expected to be a tuple or other two-element sequence providing the (low, high) limits, and in that case the sequence can be a generator. """ nbins = int(math.sqrt(len(samples)) / 40.) assert nbins >= 1, "too few samples to construct histogram" lo = samples.min() * (1. - nbins / len(samples)) hi = samples.max() * (1. + nbins / len(samples)) ln_pdf = rate.BinnedLnPDF( rate.NDBins((rate.LogarithmicBins(lo, hi, nbins), ))) count = ln_pdf.count # avoid attribute look-up in loop for sample in samples: count[sample, ] += 1. rate.filter_array(ln_pdf.array, rate.gaussian_window(5), use_fft=False) ln_pdf.normalize() return ln_pdf
def twoD_SearchVolume(self, instruments, dbin=None, FAR=None, bootnum=None, derr=0.197, dsys=0.074): """ Compute the search volume in the mass/mass plane, bootstrap and measure the first and second moment (assumes the underlying distribution can be characterized by those two parameters) This is gonna be brutally slow derr = (0.134**2+.103**2+.102**2)**.5 = 0.197 which is the 3 detector calibration uncertainty in quadrature. This is conservative since some injections will be H1L1 and have a lower error of .17 the dsys is the DC offset which is the max offset of .074. """ if not FAR: FAR = self.far[instruments] found, missed = self.get_injections(instruments, FAR) twodbin = self.twoDMassBins wnfunc = self.gw livetime = self.livetime[instruments] if not bootnum: bootnum = self.bootnum if wnfunc: wnfunc /= wnfunc[(wnfunc.shape[0] - 1) / 2, (wnfunc.shape[1] - 1) / 2] x = twodbin.shape[0] y = twodbin.shape[1] z = int(self.opts.dist_bins) rArrays = [] volArray = rate.BinnedArray(twodbin) volArray2 = rate.BinnedArray(twodbin) #set up ratio arrays for each distance bin for k in range(z): rArrays.append(rate.BinnedRatios(twodbin)) # Bootstrap to account for errors for n in range(bootnum): #initialize by setting these to zero for k in range(z): rArrays[k].numerator.array = numpy.zeros( rArrays[k].numerator.bins.shape) rArrays[k].denominator.array = numpy.zeros( rArrays[k].numerator.bins.shape) #Scramble the inj population and distances if bootnum > 1: sm, sf = self._scramble_pop(missed, found) # I make a separate array of distances to speed up this calculation f_dist = self._scramble_dist(sf, derr, dsys) else: sm, sf = missed, found f_dist = numpy.array([l.distance for l in found]) # compute the distance bins if not dbin: dbin = rate.LogarithmicBins(min(f_dist), max(f_dist), z) #else: print dbin.centres() # get rid of all missed injections outside the distance bins # to prevent binning errors sm, m_dist = self.cut_distance(sm, dbin) sf, f_dist = self.cut_distance(sf, dbin) for i, l in enumerate(sf): #found: tbin = rArrays[dbin[f_dist[i]]] tbin.incnumerator((l.mass1, l.mass2)) for i, l in enumerate(sm): #missed: tbin = rArrays[dbin[m_dist[i]]] tbin.incdenominator((l.mass1, l.mass2)) tmpArray2 = rate.BinnedArray( twodbin) #start with a zero array to compute the mean square for k in range(z): tbins = rArrays[k] tbins.denominator.array += tbins.numerator.array if wnfunc: rate.filter_array(tbins.denominator.array, wnfunc) if wnfunc: rate.filter_array(tbins.numerator.array, wnfunc) tbins.regularize() # logarithmic(d) integrand = 4.0 * pi * tbins.ratio() * dbin.centres( )[k]**3 * dbin.delta volArray.array += integrand tmpArray2.array += integrand #4.0 * pi * tbins.ratio() * dbin.centres()[k]**3 * dbin.delta print( "bootstrapping:\t%.1f%% and Calculating smoothed volume:\t%.1f%%\r" % ((100.0 * n / bootnum), (100.0 * k / z)), end=' ', file=sys.stderr) tmpArray2.array *= tmpArray2.array volArray2.array += tmpArray2.array print("", file=sys.stderr) #Mean and variance volArray.array /= bootnum volArray2.array /= bootnum volArray2.array -= volArray.array**2 # Variance volArray.array *= livetime volArray2.array *= livetime * livetime # this gets two powers of live time return volArray, volArray2
zero_lag_segments, verbose=opts.verbose) else: Found = get_burst_injections(opts.burst_found) Missed = get_burst_injections(opts.burst_missed) # restrict the sims to a distance range Found = cut_distance(Found, 1, max_dist) Missed = cut_distance(Missed, 1, max_dist) # get a 2D mass binning twoDMassBins = get_2d_mass_bins(min_mass, max_mass, mass_bins) # get log distance bins dBin = rate.LogarithmicBins(0.1, max_dist * 1.25, dist_bins) # Someday we could try a Gaussian smoothing function #gw = rate.gaussian_window2d(2,2,8) gw = None #Get derivative of volume with respect to FAR #dvA = get_volume_derivative(opts.injfnames, twoDMassBins, dBin, FAR, zero_lag_segments, gw) vA, vA2 = twoD_SearchVolume(Found, Missed, twoDMassBins, dBin, gw, 1.0, bootnum=int(opts.bootstrap_iterations))