Exemple #1
0
    def finish(self):
        livetime = rate.BinnedArray(self.counts.bins)
        for offsets in self.tisi_rows:
            self.seglists.offsets.update(offsets)
            livetime[offsets[self.x_instrument],
                     offsets[self.y_instrument]] += float(
                         abs(self.seglists.intersection(self.seglists.keys())))
        zvals = self.counts.at_centres() / livetime.at_centres()
        rate.filter_array(zvals, rate.gaussian_window(3, 3))
        xcoords, ycoords = self.counts.centres()
        self.axes.contour(xcoords, ycoords, numpy.transpose(numpy.log(zvals)))
        for offsets in self.tisi_rows:
            if any(offsets):
                # time slide vector is non-zero-lag
                self.axes.plot((offsets[self.x_instrument], ),
                               (offsets[self.y_instrument], ), "k+")
            else:
                # time slide vector is zero-lag
                self.axes.plot((offsets[self.x_instrument], ),
                               (offsets[self.y_instrument], ), "r+")

        self.axes.set_xlim(
            [self.counts.bins().min[0],
             self.counts.bins().max[0]])
        self.axes.set_ylim(
            [self.counts.bins().min[1],
             self.counts.bins().max[1]])
        self.axes.set_title(
            r"Coincident Event Rate vs. Instrument Time Offset (Logarithmic Rate Contours)"
        )
Exemple #2
0
    def density_estimate(lnpdf, name, kernel=rate.gaussian_window(4.)):
        """
		For internal use only.
		"""
        assert not numpy.isnan(lnpdf.array).any(
        ), "%s log likelihood ratio PDF contain NaNs" % name
        rate.filter_array(lnpdf.array, kernel)
Exemple #3
0
	def finish(self):
		self.axes.set_title("Trigger Rate vs. Peak Frequency\n(%d Triggers)" % self.nevents)
		# 21 bins per filter width
		rate.filter_array(self.rate.array, rate.gaussian_window(21))
		xvals = self.rate.centres()[0]
		self.axes.plot(xvals, self.rate.at_centres(), "k")
		self.axes.semilogy()
		self.axes.set_xlim((min(xvals), max(xvals)))
	def finish(self):
		self.axes.set_title("Trigger Rate vs. Peak Frequency\n(%d Triggers)" % self.nevents)
		# 21 bins per filter width
		rate.filter_array(self.rate.array, rate.gaussian_window(21))
		xvals = self.rate.centres()[0]
		self.axes.plot(xvals, self.rate.at_centres(), "k")
		self.axes.semilogy()
		self.axes.set_xlim((min(xvals), max(xvals)))
	def finish(self):
		self.axes.set_title("Trigger Peak Time - Injection Peak Time\n(%d Found Injections)" % self.found)
		# 21 bins per filter width
		filter = rate.gaussian_window(21)
		rate.filter_array(self.offsets.array, filter)
		rate.filter_array(self.coinc_offsets.array, filter)
		self.axes.plot(self.offsets.centres()[0], self.offsets.at_centres(), "k")
		self.axes.plot(self.coinc_offsets.centres()[0], self.coinc_offsets.at_centres(), "r")
		self.axes.legend(["%s residuals" % self.instrument, "SNR-weighted mean of residuals in all instruments"], loc = "lower right")
Exemple #6
0
	def finish(self):
		for instrument, data in sorted(self.data.items()):
			fig, axes = SnglBurstUtils.make_burst_plot(r"$t_{\mathrm{recovered}} - t_{\mathrm{injected}}$ (s)", "Triggers per Unit Offset")
			axes.semilogy()
			axes.set_title("Trigger Peak Time - Injection Peak Time in %s\n(%d Found Injections)" % (instrument, data.found))
			# 21 bins per filter width
			rate.filter_array(data.offsets.array, rate.gaussian_window(21))
			axes.plot(data.offsets.centres()[0], data.offsets.at_centres(), "k")
			#axes.legend(["%s residuals" % instrument, "SNR-weighted mean of residuals in all instruments"], loc = "lower right")
			yield fig
	def finish(self):
		self.axes.set_title("Time Between Triggers\n(%d Triggers)" % self.nevents)

		rate.filter_array(self.bins.array, rate.gaussian_window(21))
		xvals = self.bins.centres()[0]
		yvals = self.bins.at_centres()
		self.axes.plot(xvals, yvals, "k")

		self.axes.set_xlim((0, xvals[-1]))
		self.axes.set_ylim((1, 10.0**(int(math.log10(yvals.max())) + 1)))
Exemple #8
0
	def finish(self):
		self.axes.set_title("Time Between Triggers\n(%d Triggers)" % self.nevents)

		rate.filter_array(self.bins.array, rate.gaussian_window(21))
		xvals = self.bins.centres()[0]
		yvals = self.bins.at_centres()
		self.axes.plot(xvals, yvals, "k")

		self.axes.set_xlim((0, xvals[-1]))
		self.axes.set_ylim((1, 10.0**(int(math.log10(yvals.max())) + 1)))
	def finish(self):
		self.axes.set_title("Trigger Peak Frequency / Injection Centre Frequency\n(%d Found Injections)" % self.found)
		# 21 bins per filter width
		filter = rate.gaussian_window(21)
		rate.filter_array(self.offsets.array, filter)
		rate.filter_array(self.coinc_offsets.array, filter)
		self.axes.plot(10**self.offsets.centres()[0], self.offsets.at_centres(), "k")
		self.axes.plot(10**self.coinc_offsets.centres()[0], self.coinc_offsets.at_centres(), "r")
		self.axes.legend(["%s triggers" % self.instrument, "SNR-weighted mean of all matching triggers"], loc = "lower right")
		ymin, ymax = self.axes.get_ylim()
		if ymax / ymin > 1e6:
			ymin = ymax / 1e6
			self.axes.set_ylim((ymin, ymax))
Exemple #10
0
	def finish(self):
		for key, pdf in self.densities.items():
			if key.endswith("_snr2_chi2"):
				rate.filter_array(pdf.array, rate.gaussian_window(11, 11, sigma = 20))
			elif key.endswith("_dt") or key.endswith("_dA") or key.endswith("_df"):
				rate.filter_array(pdf.array, rate.gaussian_window(11, sigma = 20))
			elif key.startswith("instrumentgroup"):
				# instrument group filter is a no-op
				pass
			else:
				# shouldn't get here
				raise Exception
			pdf.normalize()
		self.mkinterps()
	def finish(self):
		self.axes.set_title(r"\begin{center}Distribution of Coincident Events (%d Foreground, %d Background Events, %d Injections Found in Coincidence, Logarithmic Density Contours)\end{center}" % (self.n_foreground, self.n_background, self.n_injections))
		xcoords, ycoords = self.background_bins.centres()

		# prepare the data
		rate.filter_array(self.foreground_bins.array, rate.gaussian_window(8, 8))
		rate.filter_array(self.background_bins.array, rate.gaussian_window(8, 8))
		rate.filter_array(self.coinc_injection_bins.array, rate.gaussian_window(8, 8))
		rate.filter_array(self.incomplete_coinc_injection_bins.array, rate.gaussian_window(8, 8))
		self.foreground_bins.logregularize()
		self.background_bins.logregularize()
		self.coinc_injection_bins.logregularize()
		self.incomplete_coinc_injection_bins.logregularize()

		# plot background contours
		max_density = math.log(self.background_bins.array.max())
		self.axes.contour(xcoords, ycoords, numpy.transpose(numpy.log(self.background_bins.array)), [max_density - n for n in xrange(0, 10, 1)], cmap = matplotlib.cm.Greys)

		# plot foreground (zero-lag) contours
		max_density = math.log(self.foreground_bins.array.max())
		self.axes.contour(xcoords, ycoords, numpy.transpose(numpy.log(self.foreground_bins.array)), [max_density - n for n in xrange(0, 10, 1)], cmap = matplotlib.cm.Reds)
		#self.axes.plot(self.foreground_x, self.foreground_y, "r+")

		# plot coincident injection contours
		max_density = math.log(self.coinc_injection_bins.array.max())
		self.axes.contour(xcoords, ycoords, numpy.transpose(numpy.log(self.coinc_injection_bins.array)), [max_density - n for n in xrange(0, 10, 1)], cmap = matplotlib.cm.Blues)

		# plot incomplete coincident injection contours
		max_density = math.log(self.incomplete_coinc_injection_bins.array.max())
		self.axes.contour(xcoords, ycoords, numpy.transpose(numpy.log(self.incomplete_coinc_injection_bins.array)), [max_density - n for n in xrange(0, 10, 1)], cmap = matplotlib.cm.Greens)

		# fix axes limits
		self.axes.set_xlim([self.background_bins.bins.min[0], self.background_bins.bins.max[0]])
		self.axes.set_ylim([self.background_bins.bins.min[1], self.background_bins.bins.max[1]])
Exemple #12
0
	def finish(self):
		for key, pdf in self.densities.items():
			if key.endswith("_snr2_chi2"):
				rate.filter_array(pdf.array, rate.gaussian_window(11, 11, sigma = 20))
			elif key.endswith("_dt") or key.endswith("_dA") or key.endswith("_df"):
				rate.filter_array(pdf.array, rate.gaussian_window(11, sigma = 20))
			elif key.startswith("instrumentgroup"):
				# instrument group filter is a no-op
				pass
			else:
				# shouldn't get here
				raise Exception
			pdf.normalize()
		self.mkinterps()
Exemple #13
0
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 finish(self):
     self.axes.set_title(
         "Trigger Peak Time - Injection Peak Time\n(%d Found Injections)" %
         self.found)
     # 21 bins per filter width
     filter = rate.gaussian_window(21)
     rate.filter_array(self.offsets.array, filter)
     rate.filter_array(self.coinc_offsets.array, filter)
     self.axes.plot(self.offsets.centres()[0], self.offsets.at_centres(),
                    "k")
     self.axes.plot(self.coinc_offsets.centres()[0],
                    self.coinc_offsets.at_centres(), "r")
     self.axes.legend([
         "%s residuals" % self.instrument,
         "SNR-weighted mean of residuals in all instruments"
     ],
                      loc="lower right")
	def finish(self):
		livetime = rate.BinnedArray(self.counts.bins)
		for offsets in self.tisi_rows:
			self.seglists.offsets.update(offsets)
			livetime[offsets[self.x_instrument], offsets[self.y_instrument]] += float(abs(self.seglists.intersection(self.seglists.keys())))
		zvals = self.counts.at_centres() / livetime.at_centres()
		rate.filter_array(zvals, rate.gaussian_window(3, 3))
		xcoords, ycoords = self.counts.centres()
		self.axes.contour(xcoords, ycoords, numpy.transpose(numpy.log(zvals)))
		for offsets in self.tisi_rows:
			if any(offsets):
				# time slide vector is non-zero-lag
				self.axes.plot((offsets[self.x_instrument],), (offsets[self.y_instrument],), "k+")
			else:
				# time slide vector is zero-lag
				self.axes.plot((offsets[self.x_instrument],), (offsets[self.y_instrument],), "r+")

		self.axes.set_xlim([self.counts.bins().min[0], self.counts.bins().max[0]])
		self.axes.set_ylim([self.counts.bins().min[1], self.counts.bins().max[1]])
		self.axes.set_title(r"Coincident Event Rate vs. Instrument Time Offset (Logarithmic Rate Contours)")
 def finish(self):
     self.axes.set_title(
         "Trigger Peak Frequency / Injection Centre Frequency\n(%d Found Injections)"
         % self.found)
     # 21 bins per filter width
     filter = rate.gaussian_window(21)
     rate.filter_array(self.offsets.array, filter)
     rate.filter_array(self.coinc_offsets.array, filter)
     self.axes.plot(10**self.offsets.centres()[0],
                    self.offsets.at_centres(), "k")
     self.axes.plot(10**self.coinc_offsets.centres()[0],
                    self.coinc_offsets.at_centres(), "r")
     self.axes.legend([
         "%s triggers" % self.instrument,
         "SNR-weighted mean of all matching triggers"
     ],
                      loc="lower right")
     ymin, ymax = self.axes.get_ylim()
     if ymax / ymin > 1e6:
         ymin = ymax / 1e6
         self.axes.set_ylim((ymin, ymax))
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
Exemple #18
0
    def finish(self):
        self.axes.set_title(
            r"\begin{center}Distribution of Coincident Events (%d Foreground, %d Background Events, %d Injections Found in Coincidence, Logarithmic Density Contours)\end{center}"
            % (self.n_foreground, self.n_background, self.n_injections))
        xcoords, ycoords = self.background_bins.centres()

        # prepare the data
        rate.filter_array(self.foreground_bins.array,
                          rate.gaussian_window(8, 8))
        rate.filter_array(self.background_bins.array,
                          rate.gaussian_window(8, 8))
        rate.filter_array(self.coinc_injection_bins.array,
                          rate.gaussian_window(8, 8))
        rate.filter_array(self.incomplete_coinc_injection_bins.array,
                          rate.gaussian_window(8, 8))
        self.foreground_bins.logregularize()
        self.background_bins.logregularize()
        self.coinc_injection_bins.logregularize()
        self.incomplete_coinc_injection_bins.logregularize()

        # plot background contours
        max_density = math.log(self.background_bins.array.max())
        self.axes.contour(xcoords,
                          ycoords,
                          numpy.transpose(numpy.log(
                              self.background_bins.array)),
                          [max_density - n for n in xrange(0, 10, 1)],
                          cmap=matplotlib.cm.Greys)

        # plot foreground (zero-lag) contours
        max_density = math.log(self.foreground_bins.array.max())
        self.axes.contour(xcoords,
                          ycoords,
                          numpy.transpose(numpy.log(
                              self.foreground_bins.array)),
                          [max_density - n for n in xrange(0, 10, 1)],
                          cmap=matplotlib.cm.Reds)
        #self.axes.plot(self.foreground_x, self.foreground_y, "r+")

        # plot coincident injection contours
        max_density = math.log(self.coinc_injection_bins.array.max())
        self.axes.contour(xcoords,
                          ycoords,
                          numpy.transpose(
                              numpy.log(self.coinc_injection_bins.array)),
                          [max_density - n for n in xrange(0, 10, 1)],
                          cmap=matplotlib.cm.Blues)

        # plot incomplete coincident injection contours
        max_density = math.log(
            self.incomplete_coinc_injection_bins.array.max())
        self.axes.contour(xcoords,
                          ycoords,
                          numpy.transpose(
                              numpy.log(
                                  self.incomplete_coinc_injection_bins.array)),
                          [max_density - n for n in xrange(0, 10, 1)],
                          cmap=matplotlib.cm.Greens)

        # fix axes limits
        self.axes.set_xlim([
            self.background_bins.bins.min[0], self.background_bins.bins.max[0]
        ])
        self.axes.set_ylim([
            self.background_bins.bins.min[1], self.background_bins.bins.max[1]
        ])
Exemple #19
0
 def finish(self):
     for key, pdf in self.densities.items():
         rate.filter_array(pdf.array, rate.gaussian_window(11, 5))
         pdf.normalize()
     self.mkinterps()
Exemple #20
0
    def integrate(self, func, *args, **kwargs):
        """
        Integrate func, by using n sample points. Right now, all params defined must be passed to args must be provided, but this will change soon.

        Limitations:
            func's signature must contain all parameters currently defined by the sampler, and with the same names. This is required so that the sample values can be passed consistently.

        kwargs:
        nmax -- total allowed number of sample points, will throw a warning if this number is reached before neff.
        nmin -- minimum number of samples to allow, by default will be set to the end of the 'burnin' at n_adapt * n
        neff -- Effective samples to collect before terminating. If not given, assume infinity
        n -- Number of samples to integrate in a 'chunk' -- default is 1000
        save_integrand -- Save the evaluated value of the integrand at the sample points with the sample point
        history_mult -- Number of chunks (of size n) to use in the adaptive histogramming: only useful if there are parameters with adaptation enabled
        tempering_exp -- Exponent to raise the weights of the 1-D marginalized histograms for adaptive sampling prior generation, by default it is 0 which will turn off adaptive sampling regardless of other settings
        n_adapt -- number of chunks over which to allow the pdf to adapt. Default is zero, which will turn off adaptive sampling regardless of other settings
        convergence_tests - dictionary of function pointers, each accepting self._rvs and self.params as arguments. CURRENTLY ONLY USED FOR REPORTING
        maxval - Guess at the maximum value of the integrand -- used as a seed for the maxval counter

        Pinning a value: By specifying a kwarg with the same of an existing parameter, it is possible to "pin" it. The sample draws will always be that value, and the sampling prior will use a delta function at that value.
        """

        #
        # Pin values
        #
        tempcdfdict, temppdfdict, temppriordict, temppdfnormdict = {}, {}, {}, {}
        temppdfnormdict = defaultdict(lambda: 1.0)
        for p, val in kwargs.iteritems():
            if p in self.params:
                # Store the previous pdf/cdf in case it's already defined
                tempcdfdict[p] = self.cdf_inv[p]
                temppdfdict[p] = self.pdf[p]
                temppdfnormdict[p] = self._pdf_norm[p]
                temppriordict[p] = self.prior_pdf[p]
                # Set a new one to always return the same value
                self.pdf[p] = functools.partial(delta_func_pdf_vector, val)
                self._pdf_norm[p] = 1.0
                self.prior_pdf[p] = functools.partial(delta_func_pdf_vector, val)
                self.cdf_inv[p] = functools.partial(delta_func_samp_vector, val)

        # This is a semi-hack to ensure that the integrand is called with
        # the arguments in the right order
        # FIXME: How dangerous is this?
        args = func.func_code.co_varnames[:func.func_code.co_argcount]
        if not MCSampler.match_params_from_args(args, self.params):
            raise ValueError("All integrand variables must be represented by integral parameters.")
        
        #
        # Determine stopping conditions
        #
        nmax = kwargs["nmax"] if kwargs.has_key("nmax") else float("inf")
        neff = kwargs["neff"] if kwargs.has_key("neff") else numpy.float128("inf")
        n = kwargs["n"] if kwargs.has_key("n") else min(1000, nmax)
        convergence_tests = kwargs["convergence_tests"] if kwargs.has_key("convergence_tests") else None

        #
        # Adaptive sampling parameters
        #
        n_history = int(kwargs["history_mult"]*n) if kwargs.has_key("history_mult") else None
        tempering_exp = kwargs["tempering_exp"] if kwargs.has_key("tempering_exp") else 1.0
        n_adapt = int(kwargs["n_adapt"]*n) if kwargs.has_key("n_adapt") else 0
        nmax = kwargs["nmax"] if kwargs.has_key("nmax") else n_adapt
        nmin = kwargs["nmin"] if kwargs.has_key("nmin") else n_adapt

        save_intg = kwargs["save_intg"] if kwargs.has_key("save_intg") else False
        nkeep = kwargs["save_intg"] if kwargs.has_key("save_intg") else None
        # Corner case: we want all the samples, and we don't want them messed
        # with, so everything is saved, but no sort is done
        if nkeep is True:
            nkeep = None

        # FIXME: The adaptive step relies on the _rvs cache, so this has to be
        # on in order to work
        if n_adapt > 0 and tempering_exp > 0.0:
            save_intg = True

        deltalnL = kwargs['igrand_threshold_deltalnL'] if kwargs.has_key('igrand_threshold_deltalnL') else None # default is to return all
        deltaP = kwargs["igrand_threshold_p"] if kwargs.has_key('igrand_threshold_p') else 0 # default is to omit 1e-7 of probability

        show_evaluation_log = kwargs['verbose'] if kwargs.has_key('verbose') else False
        if show_evaluation_log:
            print " .... mcsampler : providing verbose output ..... "

        int_val1 = numpy.float128(0)
        self.ntotal = 0
        maxval = kwargs["maxval"] if "maxval" in kwargs else -float("Inf")
        old_maxval = maxval
        maxlnL = -float("Inf")
        eff_samp = 0
        mean, var = None, None
        last_convergence_test = defaultdict(lambda: False)   # initialize record of tests

        if show_evaluation_log:
            print "walltime : iteration Neff  ln(maxweight) lnLmarg ln(Z/Lmax) int_var"

        socket = None
        while self.ntotal < nmin or (eff_samp < neff and self.ntotal < nmax):
            # Draw our sample points
            p_s, p_prior, rv = self.draw(n, *self.params)
                        
            # Calculate the overall p_s assuming each pdf is independent
            joint_p_s = numpy.prod(p_s, axis=0)
            joint_p_prior = numpy.prod(p_prior, axis=0)

            #
            # Prevent zeroes in the sampling prior
            #
            # FIXME: If we get too many of these, we should bail
            if (isinstance(joint_p_s, numpy.ndarray) and any(joint_p_s <= 0)) \
              or (not isinstance(joint_p_s, numpy.ndarray) and joint_p_s <= 0):
                for p in self.params:
                    self._rvs[p] = numpy.resize(self._rvs[p], len(self._rvs[p])-n)
                print >>sys.stderr, "Zero prior value detected, skipping."
                continue

            #
            # Unpack rvs and evaluate integrand
            #
            if len(rv[0].shape) != 1:
                rv = rv[0]

            params = []
            for item in self.params:
                if isinstance(item, tuple):
                    params.extend(item)
                else:
                    params.append(item)
            unpacked = numpy.hstack([r.flatten() for r in rv]).reshape(len(args), -1)
            unpacked = dict(zip(params, unpacked))
            fval = func(**unpacked)

            #
            # Check if there is any practical contribution to the integral
            #
            # FIXME: While not technically a fatal error, this will kill the 
            # adaptive sampling
            if fval.sum() == 0:
                for p in self.params:
                    self._rvs[p] = numpy.resize(self._rvs[p], len(self._rvs[p])-n)
                print >>sys.stderr, "No contribution to integral, skipping."
                continue

            sample_n = numpy.arange(self.ntotal, self.ntotal + len(fval))

            if save_intg:
                # FIXME: The joint_prior, if not specified is set to one and
                # will come out as a scalar here, hence the hack
                if not isinstance(joint_p_prior, numpy.ndarray):
                    joint_p_prior = numpy.ones(fval.shape)*joint_p_prior

                # FIXME: See warning at beginning of function. The prior values
                # need to be moved out of this, as they are not part of MC
                # integration
                if self._rvs.has_key("integrand"):
                    self._rvs["integrand"] = numpy.hstack( (self._rvs["integrand"], fval) )
                    self._rvs["joint_prior"] = numpy.hstack( (self._rvs["joint_prior"], joint_p_prior) )
                    self._rvs["joint_s_prior"] = numpy.hstack( (self._rvs["joint_s_prior"], joint_p_s) )
                    self._rvs["weights"] = numpy.hstack( (self._rvs["weights"], fval*joint_p_prior/joint_p_s) )
                    self._rvs["sample_n"] = numpy.hstack( (self._rvs["sample_n"], sample_n) )
                else:
                    self._rvs["integrand"] = fval
                    self._rvs["joint_prior"] = joint_p_prior
                    self._rvs["joint_s_prior"] = joint_p_s
                    self._rvs["weights"] = fval*joint_p_prior/joint_p_s
                    self._rvs["sample_n"] = sample_n

            # Calculate the integral over this chunk
            int_val = fval * joint_p_prior / joint_p_s

            # Calculate max L (a useful convergence feature) for debug 
            # reporting.  Not used for integration
            # Try to avoid nan's
            maxlnL = numpy.log(numpy.max([numpy.exp(maxlnL), numpy.max(fval),numpy.exp(-100)]))   # note if f<0, this will return nearly 0

            # Calculate the effective samples via max over the current 
            # evaluations
            maxval = [max(maxval, int_val[0]) if int_val[0] != 0 else maxval]
            for v in int_val[1:]:
                maxval.append( v if v > maxval[-1] and v != 0 else maxval[-1] )

            # running variance
            var = statutils.cumvar(int_val, mean, var, self.ntotal)[-1]
            # running integral
            int_val1 += int_val.sum()
            # running number of evaluations
            self.ntotal += n
            # FIXME: Likely redundant with int_val1
            mean = int_val1/self.ntotal
            maxval = maxval[-1]

            eff_samp = int_val1/maxval

            # Throw exception if we get infinity or nan
            if math.isnan(eff_samp):
                raise NanOrInf("Effective samples = nan")
            if maxlnL is float("Inf"):
                raise NanOrInf("maxlnL = inf")

            if show_evaluation_log:
                print int(time.time()), ": ", self.ntotal, eff_samp, math.log(maxval), numpy.log(int_val1/self.ntotal), numpy.log(int_val1/self.ntotal)-maxlnL, numpy.sqrt(var*self.ntotal)/int_val1

            if (not convergence_tests) and self.ntotal >= nmin and self.ntotal >= nmax and neff != float("inf"):
                print >>sys.stderr, "WARNING: User requested maximum number of samples reached... bailing."

            #
            # Convergence tests
            #
            if convergence_tests:
                converged = True
                for key in convergence_tests.keys():
                    last_convergence_test[key] = convergence_tests[key](self._rvs, self.params)
                    converged &= las_convergence_test[key]

            if convergence_tests and show_evaluation_log:  # Print status of each test
                for key in convergence_tests:
                    print "   -- Convergence test status : ", key, last_convergence_test[key]

            self._address, self._port = "pcdev2.nemo.phys.uwm.edu", 1890
            #if self._address is not None:
            if False:
                dims = ("distance", "inclination", "right_ascension",
                        "declination", "integrand", "joint_prior", "joint_s_prior")
                send_data = synchlib.prepare_data(self._rvs, dims, self.ntotal - n)
                self.socket = synchlib.send_samples(send_data, self._address, self._port, verbose=True, socket=self.socket)

            #
            # The total number of adaptive steps is reached
            #
            # FIXME: We need a better stopping condition here
            if self.ntotal >= n_adapt and maxval == old_maxval:
                # Downsample points
                if save_intg and nkeep is not None:
                    pt_sort = self._rvs["weights"].argsort()[-nkeep:]
                    for key in self._rvs:
                        if len(self._rvs[key].shape) > 1:
                            self._rvs[key] = self._rvs[key][:,pt_sort]
                        else:
                            self._rvs[key] = self._rvs[key][pt_sort]
                continue
            old_maxval = maxval

            #
            # Iterate through each of the parameters, updating the sampling
            # prior PDF according to the 1-D marginalization
            #
            for itr, p in enumerate(self.params):
                # FIXME: The second part of this condition should be made more
                # specific to pinned parameters
                if p not in self.adaptive or p in kwargs.keys():
                    continue
                points = self._rvs[p][-n_history:]
                weights = (self._rvs["integrand"][-n_history:]*self._rvs["joint_prior"][-n_history:])**tempering_exp

                self._hist[p] = statutils.get_adaptive_binning(points, (self.llim[p], self.rlim[p]))
                for pt, w in zip(points, weights):
                    self._hist[p][pt,] += w
                self._hist[p].array += self._hist[p].array.mean()
                rate.filter_array(self._hist[p].array, rate.tophat_window(3))
                norm = numpy.sum(self._hist[p].array * self._hist[p].bins.volumes())
                self._hist[p].array /= norm
                # FIXME: Stupid pet trick while numpy version is lacking
                self.pdf[p] = numpy.frompyfunc(rate.InterpBinnedArray(self._hist[p]), 1, 1)
                #with open("%s_%d_hist.txt" % (p, self.ntotal), "w") as fout:
                    #for c, pdf in zip(self._hist[p].centres()[0], self._hist[p].array):
                        #print >>fout, "%f %g" % (c, pdf)

                self.cdf[p] = self.cdf_function(p)
                self.cdf_inv[p] = self.cdf_inverse(p)

        # If we were pinning any values, undo the changes we did before
        self.cdf_inv.update(tempcdfdict)
        self.pdf.update(temppdfdict)
        self._pdf_norm.update(temppdfnormdict)
        self.prior_pdf.update(temppriordict)

        # Clean out the _rvs arrays for 'irrelevant' points
        #   - create the cumulative weights
        if "weights" in self._rvs and deltaP > 0:
            # Sort the weights with the deltaL masked applied
            sorted_weights = self._rvs["weights"].argsort()
            # Make the (unnormalized) CDF
            total_weight = self._rvs["weights"][sorted_weights].cumsum()
            # Find the deltaP cutoff index
            idx = numpy.searchsorted(total_weight, deltaP*total_weight[-1], 'left')
            sorted_weights = sorted_weights[idx:]
            # Remove all samples which contribute to smallest 1e-3 of cumulative
            # probability
            for key in self._rvs.keys():
                if isinstance(key, tuple):
                    self._rvs[key] = self._rvs[key][:,sorted_weights]
                else:
                    self._rvs[key] = self._rvs[key][sorted_weights]

        if "integrand" in self._rvs and deltalnL is not None:
            deltal_mask = numpy.log(self._rvs["integrand"]) > (maxlnL - deltalnL)
            # Remove all samples which do not have L > maxlnL - deltalnL
            for key in self._rvs.keys():
                if isinstance(key, tuple):
                    self._rvs[key] = self._rvs[key][:,deltal_mask]
                else:
                    self._rvs[key] = self._rvs[key][deltal_mask]

        # Create extra dictionary to return things
        dict_return ={}
        if convergence_tests is not None:
            dict_return["convergence_test_results"] = last_convergence_test

        return int_val1/self.ntotal, var/self.ntotal, eff_samp, dict_return
	def finish(self, threshold):
		# bin the injections

		self._bin_events()

		# use the same binning for the found injection density as
		# was constructed for the efficiency

		self.found_density = rate.BinnedArray(self.efficiency.denominator.bins)

		# construct the amplitude weighting function

		amplitude_weight = rate.BinnedArray(rate.NDBins((rate.LinearBins(threshold - 100, threshold + 100, 10001),)))

		# gaussian window's width is the number of bins
		# corresponding to 10 units of amplitude, which is computed
		# by dividing 10 by the "volume" of the bin corresponding
		# to threshold.  index is the index of the element in
		# amplitude_weight corresponding to the threshold.

		index, = amplitude_weight.bins[threshold,]
		window = rate.gaussian_window(10.0 / amplitude_weight.bins.volumes()[index])
		window /= 10 * window[(len(window) - 1) / 2]

		# set the window data into the BinnedArray object.  the
		# Gaussian peaks on the middle element of the window, which
		# we want to place at index in the amplitude_weight array.

		lo = index - (len(window) - 1) / 2
		hi = lo + len(window)
		if lo < 0 or hi > len(amplitude_weight.array):
			raise ValueError("amplitude weighting window too large")
		amplitude_weight.array[lo:hi] = window

		# store the recovered injections in the found density bins
		# weighted by amplitude

		for x, y, z in self.recovered_xyz:
			try:
				weight = amplitude_weight[z,]
			except IndexError:
				# beyond the edge of the window
				weight = 0.0
			self.found_density[x, y] += weight

		# the efficiency is only valid up to the highest energy
		# that has been injected.  this creates problems later on
		# so, instead, for each frequency, identify the highest
		# energy that has been measured and copy the values for
		# that bin's numerator and denominator into the bins for
		# all higher energies.  do the same for the counts in the
		# found injection density bins.
		#
		# numpy.indices() returns two arrays array, the first of
		# which has each element set equal to its x index, the
		# second has each element set equal to its y index, we keep
		# the latter.  meanwhile numpy.roll() cyclically permutes
		# the efficiency bins down one along the y (energy) axis.
		# from this, the conditional finds bins where the
		# efficiency is greater than 0.9 but <= 0.9 in the bin
		# immediately above it in energy.  we select the elements
		# from the y index array where the conditional is true, and
		# then use numpy.max() along the y direction to return the
		# highest such y index for each x index, which is a 1-D
		# array.  finally, enumerate() is used to iterate over x
		# index and corresponding y index, and if the y index is
		# not negative (was found) the value from that x-y bin is
		# copied to all higher bins.

		n = self.efficiency.numerator.array
		d = self.efficiency.denominator.array
		f = self.found_density.array
		bady = -1
		for x, y in enumerate(numpy.max(numpy.where((d > 0) & (numpy.roll(d, -1, axis = 1) <= 0), numpy.indices(d.shape)[1], bady), axis = 1)):
			if y != bady:
				n[x, y + 1:] = n[x, y]
				d[x, y + 1:] = d[x, y]
				f[x, y + 1:] = f[x, y]

		# now do the same for the bins at energies below those that
		# have been measured.

		bady = d.shape[1]
		for x, y in enumerate(numpy.min(numpy.where((d > 0) & (numpy.roll(d, 1, axis = 1) <= 0), numpy.indices(d.shape)[1], bady), axis = 1)):
			if y != bady:
				n[x, 0:y] = n[x, y]
				d[x, 0:y] = d[x, y]
				f[x, 0:y] = f[x, y]

		diagnostic_plot(self.efficiency.numerator.array, self.efficiency.denominator.bins, r"Efficiency Numerator (Before Averaging)", self.amplitude_lbl, "lalapps_excesspowerfinal_efficiency_numerator_before.png")
		diagnostic_plot(self.efficiency.denominator.array, self.efficiency.denominator.bins, r"Efficiency Denominator (Before Averaging)", self.amplitude_lbl, "lalapps_excesspowerfinal_efficiency_denominator_before.png")
		diagnostic_plot(self.found_density.array, self.efficiency.denominator.bins, r"Injections Lost / Unit of Threshold (Before Averaging)", self.amplitude_lbl, "lalapps_excesspowerfinal_found_density_before.png")

		# smooth the efficiency bins and the found injection
		# density bins using the same 2D window.

		window = rate.gaussian_window(self.window_size_x, self.window_size_y)
		window /= window[tuple((numpy.array(window.shape, dtype = "double") - 1) / 2)]
		rate.filter_binned_ratios(self.efficiency, window)
		rate.filter_array(self.found_density.array, window)

		diagnostic_plot(self.efficiency.numerator.array, self.efficiency.denominator.bins, r"Efficiency Numerator (After Averaging)", self.amplitude_lbl, "lalapps_excesspowerfinal_efficiency_numerator_after.png")
		diagnostic_plot(self.efficiency.denominator.array, self.efficiency.denominator.bins, r"Efficiency Denominator (After Averaging)", self.amplitude_lbl, "lalapps_excesspowerfinal_efficiency_denominator_after.png")
		diagnostic_plot(self.found_density.array, self.efficiency.denominator.bins, r"Injections Lost / Unit of Threshold (After Averaging)", self.amplitude_lbl, "lalapps_excesspowerfinal_found_density_after.png")

		# compute the uncertainties in the efficiency and its
		# derivative by assuming these to be the binomial counting
		# fluctuations in the numerators.

		p = self.efficiency.ratio()
		self.defficiency = numpy.sqrt(p * (1 - p) / self.efficiency.denominator.array)
		p = self.found_density.array / self.efficiency.denominator.array
		self.dfound_density = numpy.sqrt(p * (1 - p) / self.efficiency.denominator.array)
Exemple #22
0
  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
Exemple #23
0
	def finish(self, threshold):
		# bin the injections

		self._bin_events()

		# use the same binning for the found injection density as
		# was constructed for the efficiency

		self.found_density = rate.BinnedArray(self.efficiency.denominator.bins)

		# construct the amplitude weighting function

		amplitude_weight = rate.BinnedArray(rate.NDBins((rate.LinearBins(threshold - 100, threshold + 100, 10001),)))

		# gaussian window's width is the number of bins
		# corresponding to 10 units of amplitude, which is computed
		# by dividing 10 by the "volume" of the bin corresponding
		# to threshold.  index is the index of the element in
		# amplitude_weight corresponding to the threshold.

		index, = amplitude_weight.bins[threshold,]
		window = rate.gaussian_window(10.0 / amplitude_weight.bins.volumes()[index])
		window /= 10 * window[(len(window) - 1) / 2]

		# set the window data into the BinnedArray object.  the
		# Gaussian peaks on the middle element of the window, which
		# we want to place at index in the amplitude_weight array.

		lo = index - (len(window) - 1) / 2
		hi = lo + len(window)
		if lo < 0 or hi > len(amplitude_weight.array):
			raise ValueError("amplitude weighting window too large")
		amplitude_weight.array[lo:hi] = window

		# store the recovered injections in the found density bins
		# weighted by amplitude

		for x, y, z in self.recovered_xyz:
			try:
				weight = amplitude_weight[z,]
			except IndexError:
				# beyond the edge of the window
				weight = 0.0
			self.found_density[x, y] += weight

		# the efficiency is only valid up to the highest energy
		# that has been injected.  this creates problems later on
		# so, instead, for each frequency, identify the highest
		# energy that has been measured and copy the values for
		# that bin's numerator and denominator into the bins for
		# all higher energies.  do the same for the counts in the
		# found injection density bins.
		#
		# numpy.indices() returns two arrays array, the first of
		# which has each element set equal to its x index, the
		# second has each element set equal to its y index, we keep
		# the latter.  meanwhile numpy.roll() cyclically permutes
		# the efficiency bins down one along the y (energy) axis.
		# from this, the conditional finds bins where the
		# efficiency is greater than 0.9 but <= 0.9 in the bin
		# immediately above it in energy.  we select the elements
		# from the y index array where the conditional is true, and
		# then use numpy.max() along the y direction to return the
		# highest such y index for each x index, which is a 1-D
		# array.  finally, enumerate() is used to iterate over x
		# index and corresponding y index, and if the y index is
		# not negative (was found) the value from that x-y bin is
		# copied to all higher bins.

		n = self.efficiency.numerator.array
		d = self.efficiency.denominator.array
		f = self.found_density.array
		bady = -1
		for x, y in enumerate(numpy.max(numpy.where((d > 0) & (numpy.roll(d, -1, axis = 1) <= 0), numpy.indices(d.shape)[1], bady), axis = 1)):
			if y != bady:
				n[x, y + 1:] = n[x, y]
				d[x, y + 1:] = d[x, y]
				f[x, y + 1:] = f[x, y]

		# now do the same for the bins at energies below those that
		# have been measured.

		bady = d.shape[1]
		for x, y in enumerate(numpy.min(numpy.where((d > 0) & (numpy.roll(d, 1, axis = 1) <= 0), numpy.indices(d.shape)[1], bady), axis = 1)):
			if y != bady:
				n[x, 0:y] = n[x, y]
				d[x, 0:y] = d[x, y]
				f[x, 0:y] = f[x, y]

		diagnostic_plot(self.efficiency.numerator.array, self.efficiency.denominator.bins, r"Efficiency Numerator (Before Averaging)", self.amplitude_lbl, "lalapps_excesspowerfinal_efficiency_numerator_before.png")
		diagnostic_plot(self.efficiency.denominator.array, self.efficiency.denominator.bins, r"Efficiency Denominator (Before Averaging)", self.amplitude_lbl, "lalapps_excesspowerfinal_efficiency_denominator_before.png")
		diagnostic_plot(self.found_density.array, self.efficiency.denominator.bins, r"Injections Lost / Unit of Threshold (Before Averaging)", self.amplitude_lbl, "lalapps_excesspowerfinal_found_density_before.png")

		# smooth the efficiency bins and the found injection
		# density bins using the same 2D window.

		window = rate.gaussian_window(self.window_size_x, self.window_size_y)
		window /= window[tuple((numpy.array(window.shape, dtype = "double") - 1) / 2)]
		rate.filter_binned_ratios(self.efficiency, window)
		rate.filter_array(self.found_density.array, window)

		diagnostic_plot(self.efficiency.numerator.array, self.efficiency.denominator.bins, r"Efficiency Numerator (After Averaging)", self.amplitude_lbl, "lalapps_excesspowerfinal_efficiency_numerator_after.png")
		diagnostic_plot(self.efficiency.denominator.array, self.efficiency.denominator.bins, r"Efficiency Denominator (After Averaging)", self.amplitude_lbl, "lalapps_excesspowerfinal_efficiency_denominator_after.png")
		diagnostic_plot(self.found_density.array, self.efficiency.denominator.bins, r"Injections Lost / Unit of Threshold (After Averaging)", self.amplitude_lbl, "lalapps_excesspowerfinal_found_density_after.png")

		# compute the uncertainties in the efficiency and its
		# derivative by assuming these to be the binomial counting
		# fluctuations in the numerators.

		p = self.efficiency.ratio()
		self.defficiency = numpy.sqrt(p * (1 - p) / self.efficiency.denominator.array)
		p = self.found_density.array / self.efficiency.denominator.array
		self.dfound_density = numpy.sqrt(p * (1 - p) / self.efficiency.denominator.array)
	weeks = float(abs(segment)) / 86400.0 / 7.0	# FIXME: leep seconds?
	border = (0.5, 0.75, 0.125, 0.625)	# inches
	width = max(10.0, weeks * 3.0 + border[0] + border[2])	# inches
	height = 8.0	# inches
	fig = figure.Figure()
	canvas = FigureCanvas(fig)
	fig.set_size_inches(width, height)
	fig.gca().set_position([border[0] / width, border[1] / height, (width - border[0] - border[2]) / width, (height - border[1] - border[3]) / height])
	return fig


fig = newfig(options.segment)
axes = fig.gca()


rate.filter_array(trigger_rate.array, rate.gaussian_window(bins_per_filterwidth))


axes.plot(trigger_rate.centres()[0], trigger_rate.at_centres())


axes.set_xlim(list(options.segment))
axes.grid(True)


for seg in ~seglist & segments.segmentlist([options.segment]):
	axes.axvspan(seg[0], seg[1], facecolor = "k", alpha = 0.2)


axes.set_title("%s Excess Power Trigger Rate vs. Time\n(%d Triggers, %g s Moving Average)" % (options.instrument, num_triggers, options.window))
	def finish(self):
		fig, axes = SnglBurstUtils.make_burst_plot(r"Injection Amplitude (\(\mathrm{s}^{-\frac{1}{3}}\))", "Detection Efficiency", width = 108.0)
		axes.set_title(r"Detection Efficiency vs.\ Amplitude")
		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 self.all), max(sim.amplitude for sim in self.all), 400),))
		efficiency_num = rate.BinnedArray(bins)
		efficiency_den = rate.BinnedArray(bins)
		for sim in self.found:
			efficiency_num[sim.amplitude,] += 1
		for sim in self.all:
			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(self.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, self.cal_uncertainty, self.filter_width, colour = "k", linestyle = "-", erroralpha = 0.2)
		print("Pipeline's 50%% efficiency point for all detections = %g +/- %g%%\n" % (A50, A50_err * 100), file=sys.stderr)

		# add a legend to the axes
		axes.legend((line1,), (r"\noindent Injections recovered with $\log \Lambda > %.2f$" % self.detection_threshold,), loc = "lower right")

		# adjust limits
		axes.set_xlim([3e-22, 3e-19])
		axes.set_ylim([0.0, 1.0])

		#
		# dump some information about the highest-amplitude missed
		# and quietest-amplitude found injections
		#

		self.loudest_missed.sort(reverse = True)
		self.quietest_found.sort(reverse = True)

		f = file("string_loud_missed_injections.txt", "w")
		print("Highest Amplitude Missed Injections", file=f)
		print("===================================", file=f)
		for amplitude, sim, offsetvector, filename, ln_likelihood_ratio in self.loudest_missed:
			print(file=f)
			print("%s in %s:" % (str(sim.simulation_id), filename), file=f)
			if ln_likelihood_ratio is None:
				print("Not recovered", file=f)
			else:
				print("Recovered with \\log \\Lambda = %.16g, detection threshold was %.16g" % (ln_likelihood_ratio, self.detection_threshold), file=f)
			for instrument in self.seglists:
				print("In %s:" % instrument, file=f)
				print("\tInjected amplitude:\t%.16g" % SimBurstUtils.string_amplitude_in_instrument(sim, instrument, offsetvector), file=f)
				print("\tTime of injection:\t%s s" % sim.time_at_instrument(instrument, offsetvector), file=f)
			print("Amplitude in waveframe:\t%.16g" % sim.amplitude, file=f)
			t = sim.get_time_geocent()
			print("Time at geocentre:\t%s s" % t, file=f)
			print("Segments within 60 seconds:\t%s" % segmentsUtils.segmentlistdict_to_short_string(self.seglists & segments.segmentlistdict((instrument, segments.segmentlist([segments.segment(t-offsetvector[instrument]-60, t-offsetvector[instrument]+60)])) for instrument in self.seglists)), file=f)
			print("Vetoes within 60 seconds:\t%s" % segmentsUtils.segmentlistdict_to_short_string(self.vetoseglists & segments.segmentlistdict((instrument, segments.segmentlist([segments.segment(t-offsetvector[instrument]-60, t-offsetvector[instrument]+60)])) for instrument in self.vetoseglists)), file=f)

		f = file("string_quiet_found_injections.txt", "w")
		print("Lowest Amplitude Found Injections", file=f)
		print("=================================", file=f)
		for inv_amplitude, sim, offsetvector, filename, ln_likelihood_ratio in self.quietest_found:
			print(file=f)
			print("%s in %s:" % (str(sim.simulation_id), filename), file=f)
			if ln_likelihood_ratio is None:
				print("Not recovered", file=f)
			else:
				print("Recovered with \\log \\Lambda = %.16g, detection threshold was %.16g" % (ln_likelihood_ratio, self.detection_threshold), file=f)
			for instrument in self.seglists:
				print("In %s:" % instrument, file=f)
				print("\tInjected amplitude:\t%.16g" % SimBurstUtils.string_amplitude_in_instrument(sim, instrument, offsetvector), file=f)
				print("\tTime of injection:\t%s s" % sim.time_at_instrument(instrument, offsetvector), file=f)
			print("Amplitude in waveframe:\t%.16g" % sim.amplitude, file=f)
			t = sim.get_time_geocent()
			print("Time at geocentre:\t%s s" % t, file=f)
			print("Segments within 60 seconds:\t%s" % segmentsUtils.segmentlistdict_to_short_string(self.seglists & segments.segmentlistdict((instrument, segments.segmentlist([segments.segment(t-offsetvector[instrument]-60, t-offsetvector[instrument]+60)])) for instrument in self.seglists)), file=f)
			print("Vetoes within 60 seconds:\t%s" % segmentsUtils.segmentlistdict_to_short_string(self.vetoseglists & segments.segmentlistdict((instrument, segments.segmentlist([segments.segment(t-offsetvector[instrument]-60, t-offsetvector[instrument]+60)])) for instrument in self.vetoseglists)), file=f)

		#
		# done
		#

		return fig,
Exemple #26
0
def twoD_SearchVolume(found,
                      missed,
                      twodbin,
                      dbin,
                      wnfunc,
                      livetime,
                      bootnum=1,
                      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 wnfunc:
        wnfunc /= wnfunc[(wnfunc.shape[0] - 1) / 2, (wnfunc.shape[1] - 1) / 2]
    x = twodbin.shape[0]
    y = twodbin.shape[1]
    z = dbin.n
    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
        if bootnum > 1: sm, sf = scramble_pop(missed, found)
        else: sm, sf = missed, found
        for l in sf:  #found:
            tbin = rArrays[dbin[scramble_dist(l.distance, derr, dsys)]]
            tbin.incnumerator((l.mass1, l.mass2))
        for l in sm:  #missed:
            tbin = rArrays[dbin[scramble_dist(l.distance, derr, dsys)]]
            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
Exemple #27
0
	def finish(self):
		for key, pdf in self.densities.items():
			rate.filter_array(pdf.array, rate.gaussian_window(11, 5))
			pdf.normalize()
		self.mkinterps()
def SNRPDF(instruments,
           horizon_distances,
           snr_cutoff,
           n_samples=200000,
           bins=rate.ATanLogarithmicBins(3.6, 1e3, 150)):
    """
	Precomputed SNR PDF for each detector
	Returns a BinnedArray containing
	P(snr_{inst1}, snr_{inst2}, ... | signal seen in exactly
		{inst1, inst2, ...} in a network of instruments
		with a given set of horizon distances)
	
	i.e., the joint probability density of observing a set of
	SNRs conditional on them being the result of signal that
	has been recovered in a given subset of the instruments in
	a network of instruments with a given set of horizon
	distances.

	The axes of the PDF correspond to the instruments in
	alphabetical order.  The binning used for all axes is set
	with the bins parameter.

	The n_samples parameter sets the number of iterations for
	the internal Monte Carlo sampling loop.
	"""
    if n_samples < 1:
        raise ValueError("n_samples=%d must be >= 1" % n_samples)

    # get instrument names
    instruments = sorted(instruments)
    if len(instruments) < 1:
        raise ValueError(instruments)
    # get the horizon distances in the same order
    DH_times_8 = 8. * numpy.array(
        [horizon_distances[inst] for inst in instruments])
    # get detector responses in the same order
    resps = [
        lalsimulation.DetectorPrefixToLALDetector(str(inst)).response
        for inst in instruments
    ]

    # get horizon distances and responses of remaining
    # instruments (order doesn't matter as long as they're in
    # the same order)
    DH_times_8_other = 8. * numpy.array([
        dist
        for inst, dist in horizon_distances.items() if inst not in instruments
    ])
    resps_other = tuple(
        lalsimulation.DetectorPrefixToLALDetector(str(inst)).response
        for inst in horizon_distances if inst not in instruments)

    # initialize the PDF array, and pre-construct the sequence of
    # snr, d(snr) tuples. since the last SNR bin probably has
    # infinite size, we remove it from the sequence
    # (meaning the PDF will be left 0 in that bin)
    pdf = rate.BinnedArray(rate.NDBins([bins] * len(instruments)))
    snr_sequence = rate.ATanLogarithmicBins(3.6, 1e3, 500)
    snr_snrlo_snrhi_sequence = numpy.array(
        zip(snr_sequence.centres(), snr_sequence.lower(),
            snr_sequence.upper())[:-1])

    # compute the SNR at which to begin iterations over bins
    assert type(snr_cutoff) is float
    snr_min = snr_cutoff - 3.0
    assert snr_min > 0.0

    # we select random uniformly-distributed right assensions
    # so there's no point in also choosing random GMSTs and any
    # vlaue is as good as any other
    gmst = 0.0

    # run the sample the requested # of iterations. save some
    # symbols to avoid doing module attribute look-ups in the
    # loop
    acos = math.acos
    random_uniform = random.uniform
    twopi = 2. * math.pi
    pi_2 = math.pi / 2.
    xlal_am_resp = lal.ComputeDetAMResponse
    # FIXME:  scipy.stats.rice.rvs broken on reference OS.
    # switch to it when we can rely on a new-enough scipy
    #rice_rvs = stats.rice.rvs	# broken on reference OS
    # the .reshape is needed in the event that x is a 1x1
    # array:  numpy returns a scalar from sqrt(), but we must
    # have something that we can iterate over
    rice_rvs = lambda x: numpy.sqrt(stats.ncx2.rvs(2., x**2.)).reshape(x.shape)

    for i in xrange(n_samples):
        # select random sky location and source orbital
        # plane inclination
        # the signal is linearly polaraized, and h_cross = 0
        # is assumed, so we need only F+ (its absolute value).
        ra = random_uniform(0., twopi)
        dec = pi_2 - acos(random_uniform(-1., 1.))
        psi = random_uniform(0., twopi)
        fplus = tuple(
            abs(xlal_am_resp(resp, ra, dec, psi, gmst)[0]) for resp in resps)

        # 1/8 ratio of inverse SNR to distance for each instrument
        # (1/8 because horizon distance is defined for an SNR of 8,
        # and we've omitted that factor for performance)
        snr_times_D = DH_times_8 * fplus

        # snr * D in instrument whose SNR grows fastest
        # with decreasing D
        max_snr_times_D = snr_times_D.max()

        # snr_times_D.min() / snr_min = the furthest a
        # source can be and still be above snr_min in all
        # instruments involved.  max_snr_times_D / that
        # distance = the SNR that distance corresponds to
        # in the instrument whose SNR grows fastest with
        # decreasing distance --- the SNR the source has in
        # the most sensitive instrument when visible to all
        # instruments in the combo
        try:
            start_index = snr_sequence[max_snr_times_D /
                                       (snr_times_D.min() / snr_min)]
        except ZeroDivisionError:
            # one of the instruments that must be able
            # to see the event is blind to it
            continue

        # min_D_other is minimum distance at which source
        # becomes visible in an instrument that isn't
        # involved.  max_snr_times_D / min_D_other gives
        # the SNR in the most sensitive instrument at which
        # the source becomes visible to one of the
        # instruments not allowed to participate
        if len(DH_times_8_other):
            min_D_other = (DH_times_8_other * fplus).min() / snr_cutoff
            try:
                end_index = snr_sequence[max_snr_times_D / min_D_other] + 1
            except ZeroDivisionError:
                # all instruments that must not see
                # it are blind to it
                end_index = None
        else:
            # there are no other instruments
            end_index = None

        # if start_index >= end_index then in order for the
        # source to be close enough to be visible in all
        # the instruments that must see it it is already
        # visible to one or more instruments that must not.
        # don't need to check for this, the for loop that
        # comes next will simply not have any iterations.

        # iterate over the nominal SNRs (= noise-free SNR
        # in the most sensitive instrument) at which we
        # will add weight to the PDF.  from the SNR in
        # most sensitive instrument, the distance to the
        # source is:
        #
        #	D = max_snr_times_D / snr
        #
        # and the (noise-free) SNRs in all instruments are:
        #
        #	snr_times_D / D
        #
        # scipy's Rice-distributed RV code is used to
        # add the effect of background noise, converting
        # the noise-free SNRs into simulated observed SNRs
        #
        # number of sources b/w Dlo and Dhi:
        #
        #	d count \propto D^2 |dD|
        #	  count \propto Dhi^3 - Dlo**3
        D_Dhi_Dlo_sequence = max_snr_times_D / snr_snrlo_snrhi_sequence[
            start_index:end_index]
        for snr, weight in zip(
                rice_rvs(snr_times_D /
                         numpy.reshape(D_Dhi_Dlo_sequence[:, 0],
                                       (len(D_Dhi_Dlo_sequence), 1))),
                D_Dhi_Dlo_sequence[:, 1]**3. - D_Dhi_Dlo_sequence[:, 2]**3.):
            pdf[tuple(snr)] += weight

    # check for divide-by-zeros that weren't caught.  also
    # finds nans if they are there
    assert numpy.isfinite(pdf.array).all()

    # convolve samples with gaussian kernel
    rate.filter_array(pdf.array,
                      rate.gaussian_window(*(1.875, ) * len(pdf.array.shape)))
    # protect against round-off in FFT convolution leading to
    # negative valuesin the PDF
    numpy.clip(pdf.array, 0., PosInf, pdf.array)
    # zero counts in bins that are below the trigger threshold.
    # have to convert SNRs to indexes ourselves and adjust so
    # that we don't zero the bin in which the SNR threshold
    # falls
    range_all = slice(None, None)
    range_low = slice(None, pdf.bins[0][snr_cutoff])
    for i in xrange(len(instruments)):
        slices = [range_all] * len(instruments)
        slices[i] = range_low
    # convert bin counts to normalized PDF
    pdf.to_pdf()
    # one last sanity check
    assert numpy.isfinite(pdf.array).all()
    # done
    return pdf
Exemple #29
0
def twoD_SearchVolume(found, missed, twodbin, dbin, wnfunc, livetime, bootnum=1, 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 wnfunc: wnfunc /= wnfunc[(wnfunc.shape[0]-1) / 2, (wnfunc.shape[1]-1) / 2]
  x = twodbin.shape[0]
  y = twodbin.shape[1]
  z = dbin.n
  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
    if bootnum > 1: sm, sf = scramble_pop(missed, found)
    else: sm, sf = missed, found
    for l in sf:#found:
      tbin = rArrays[dbin[scramble_dist(l.distance,derr,dsys)]]
      tbin.incnumerator( (l.mass1, l.mass2) )
    for l in sm:#missed:
      tbin = rArrays[dbin[scramble_dist(l.distance,derr,dsys)]]
      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
Exemple #30
0
    def integrate(self, func, *args, **kwargs):
        """
        Integrate func, by using n sample points. Right now, all params defined must be passed to args must be provided, but this will change soon.

        Limitations:
            func's signature must contain all parameters currently defined by the sampler, and with the same names. This is required so that the sample values can be passed consistently.

        kwargs:
        nmax -- total allowed number of sample points, will throw a warning if this number is reached before neff.
        nmin -- minimum number of samples to allow, by default will be set to the end of the 'burnin' at n_adapt * n
        neff -- Effective samples to collect before terminating. If not given, assume infinity
        n -- Number of samples to integrate in a 'chunk' -- default is 1000
        save_integrand -- Save the evaluated value of the integrand at the sample points with the sample point
        history_mult -- Number of chunks (of size n) to use in the adaptive histogramming: only useful if there are parameters with adaptation enabled
        tempering_exp -- Exponent to raise the weights of the 1-D marginalized histograms for adaptive sampling prior generation, by default it is 0 which will turn off adaptive sampling regardless of other settings
        n_adapt -- number of chunks over which to allow the pdf to adapt. Default is zero, which will turn off adaptive sampling regardless of other settings
        convergence_tests - dictionary of function pointers, each accepting self._rvs and self.params as arguments. CURRENTLY ONLY USED FOR REPORTING
        maxval - Guess at the maximum value of the integrand -- used as a seed for the maxval counter

        Pinning a value: By specifying a kwarg with the same of an existing parameter, it is possible to "pin" it. The sample draws will always be that value, and the sampling prior will use a delta function at that value.
        """

        #
        # Pin values
        #
        tempcdfdict, temppdfdict, temppriordict, temppdfnormdict = {}, {}, {}, {}
        temppdfnormdict = defaultdict(lambda: 1.0)
        for p, val in kwargs.iteritems():
            if p in self.params:
                # Store the previous pdf/cdf in case it's already defined
                tempcdfdict[p] = self.cdf_inv[p]
                temppdfdict[p] = self.pdf[p]
                temppdfnormdict[p] = self._pdf_norm[p]
                temppriordict[p] = self.prior_pdf[p]
                # Set a new one to always return the same value
                self.pdf[p] = functools.partial(delta_func_pdf_vector, val)
                self._pdf_norm[p] = 1.0
                self.prior_pdf[p] = functools.partial(delta_func_pdf_vector, val)
                self.cdf_inv[p] = functools.partial(delta_func_samp_vector, val)

        # This is a semi-hack to ensure that the integrand is called with
        # the arguments in the right order
        # FIXME: How dangerous is this?
        args = func.func_code.co_varnames[:func.func_code.co_argcount]
        if not MCSampler.match_params_from_args(args, self.params):
            raise ValueError("All integrand variables must be represented by integral parameters.")
        
        #
        # Determine stopping conditions
        #
        nmax = kwargs["nmax"] if kwargs.has_key("nmax") else float("inf")
        neff = kwargs["neff"] if kwargs.has_key("neff") else numpy.float128("inf")
        n = kwargs["n"] if kwargs.has_key("n") else min(1000, nmax)
        convergence_tests = kwargs["convergence_tests"] if kwargs.has_key("convergence_tests") else None

        #
        # Adaptive sampling parameters
        #
        n_history = int(kwargs["history_mult"]*n) if kwargs.has_key("history_mult") else None
        tempering_exp = kwargs["tempering_exp"] if kwargs.has_key("tempering_exp") else 1.0
        n_adapt = int(kwargs["n_adapt"]*n) if kwargs.has_key("n_adapt") else 0
        nmax = kwargs["nmax"] if kwargs.has_key("nmax") else n_adapt
        nmin = kwargs["nmin"] if kwargs.has_key("nmin") else n_adapt

        save_intg = kwargs["save_intg"] if kwargs.has_key("save_intg") else False
        nkeep = kwargs["save_intg"] if kwargs.has_key("save_intg") else None
        # Corner case: we want all the samples, and we don't want them messed
        # with, so everything is saved, but no sort is done
        if nkeep is True:
            nkeep = None

        # FIXME: The adaptive step relies on the _rvs cache, so this has to be
        # on in order to work
        if n_adapt > 0 and tempering_exp > 0.0:
            save_intg = True

        deltalnL = kwargs['igrand_threshold_deltalnL'] if kwargs.has_key('igrand_threshold_deltalnL') else None # default is to return all
        deltaP = kwargs["igrand_threshold_p"] if kwargs.has_key('igrand_threshold_p') else 0 # default is to omit 1e-7 of probability

        show_evaluation_log = kwargs['verbose'] if kwargs.has_key('verbose') else False
        if show_evaluation_log:
            print(" .... mcsampler : providing verbose output ..... ")

        int_val1 = numpy.float128(0)
        self.ntotal = 0
        maxval = kwargs["maxval"] if "maxval" in kwargs else -float("Inf")
        old_maxval = maxval
        maxlnL = -float("Inf")
        eff_samp = 0
        mean, var = None, None
        last_convergence_test = defaultdict(lambda: False)   # initialize record of tests

        if show_evaluation_log:
            print("walltime : iteration Neff  ln(maxweight) lnLmarg ln(Z/Lmax) int_var")

        socket = None
        while self.ntotal < nmin or (eff_samp < neff and self.ntotal < nmax):
            # Draw our sample points
            p_s, p_prior, rv = self.draw(n, *self.params)
                        
            # Calculate the overall p_s assuming each pdf is independent
            joint_p_s = numpy.prod(p_s, axis=0)
            joint_p_prior = numpy.prod(p_prior, axis=0)

            #
            # Prevent zeroes in the sampling prior
            #
            # FIXME: If we get too many of these, we should bail
            if (isinstance(joint_p_s, numpy.ndarray) and any(joint_p_s <= 0)) \
              or (not isinstance(joint_p_s, numpy.ndarray) and joint_p_s <= 0):
                for p in self.params:
                    self._rvs[p] = numpy.resize(self._rvs[p], len(self._rvs[p])-n)
                print("Zero prior value detected, skipping.", file=sys.stderr)
                continue

            #
            # Unpack rvs and evaluate integrand
            #
            if len(rv[0].shape) != 1:
                rv = rv[0]

            params = []
            for item in self.params:
                if isinstance(item, tuple):
                    params.extend(item)
                else:
                    params.append(item)
            unpacked = numpy.hstack([r.flatten() for r in rv]).reshape(len(args), -1)
            unpacked = dict(zip(params, unpacked))
            fval = func(**unpacked)

            #
            # Check if there is any practical contribution to the integral
            #
            # FIXME: While not technically a fatal error, this will kill the 
            # adaptive sampling
            if fval.sum() == 0:
                for p in self.params:
                    self._rvs[p] = numpy.resize(self._rvs[p], len(self._rvs[p])-n)
                print("No contribution to integral, skipping.", file=sys.stderr)
                continue

            sample_n = numpy.arange(self.ntotal, self.ntotal + len(fval))

            if save_intg:
                # FIXME: The joint_prior, if not specified is set to one and
                # will come out as a scalar here, hence the hack
                if not isinstance(joint_p_prior, numpy.ndarray):
                    joint_p_prior = numpy.ones(fval.shape)*joint_p_prior

                # FIXME: See warning at beginning of function. The prior values
                # need to be moved out of this, as they are not part of MC
                # integration
                if self._rvs.has_key("integrand"):
                    self._rvs["integrand"] = numpy.hstack( (self._rvs["integrand"], fval) )
                    self._rvs["joint_prior"] = numpy.hstack( (self._rvs["joint_prior"], joint_p_prior) )
                    self._rvs["joint_s_prior"] = numpy.hstack( (self._rvs["joint_s_prior"], joint_p_s) )
                    self._rvs["weights"] = numpy.hstack( (self._rvs["weights"], fval*joint_p_prior/joint_p_s) )
                    self._rvs["sample_n"] = numpy.hstack( (self._rvs["sample_n"], sample_n) )
                else:
                    self._rvs["integrand"] = fval
                    self._rvs["joint_prior"] = joint_p_prior
                    self._rvs["joint_s_prior"] = joint_p_s
                    self._rvs["weights"] = fval*joint_p_prior/joint_p_s
                    self._rvs["sample_n"] = sample_n

            # Calculate the integral over this chunk
            int_val = fval * joint_p_prior / joint_p_s

            # Calculate max L (a useful convergence feature) for debug 
            # reporting.  Not used for integration
            # Try to avoid nan's
            maxlnL = numpy.log(numpy.max([numpy.exp(maxlnL), numpy.max(fval),numpy.exp(-100)]))   # note if f<0, this will return nearly 0

            # Calculate the effective samples via max over the current 
            # evaluations
            maxval = [max(maxval, int_val[0]) if int_val[0] != 0 else maxval]
            for v in int_val[1:]:
                maxval.append( v if v > maxval[-1] and v != 0 else maxval[-1] )

            # running variance
            var = statutils.cumvar(int_val, mean, var, self.ntotal)[-1]
            # running integral
            int_val1 += int_val.sum()
            # running number of evaluations
            self.ntotal += n
            # FIXME: Likely redundant with int_val1
            mean = int_val1/self.ntotal
            maxval = maxval[-1]

            eff_samp = int_val1/maxval

            # Throw exception if we get infinity or nan
            if math.isnan(eff_samp):
                raise NanOrInf("Effective samples = nan")
            if maxlnL is float("Inf"):
                raise NanOrInf("maxlnL = inf")

            if show_evaluation_log:
                print("{0:.3f} : {1:d} {2:.5f} {3:.2f} {4:.2f} {5:.2f} {6:.3f}".format(time.time(), self.ntotal, eff_samp, math.log(maxval), numpy.log(int_val1 / self.ntotal), numpy.log(int_val1 / self.ntotal) - maxlnL, numpy.sqrt(var * self.ntotal) / int_val1))

            if (not convergence_tests) and self.ntotal >= nmin and self.ntotal >= nmax and neff != float("inf"):
                print("WARNING: User requested maximum number of samples reached... bailing.", file=sys.stderr)

            #
            # Convergence tests
            #
            if convergence_tests:
                converged = True
                for key in convergence_tests.keys():
                    last_convergence_test[key] = convergence_tests[key](self._rvs, self.params)
                    converged &= las_convergence_test[key]

            if convergence_tests and show_evaluation_log:  # Print status of each test
                for key in convergence_tests:
                    print("   -- Convergence test status : ", key, last_convergence_test[key])

            self._address, self._port = "pcdev2.nemo.phys.uwm.edu", 1890
            #if self._address is not None:
            if False:
                dims = ("distance", "inclination", "right_ascension",
                        "declination", "integrand", "joint_prior", "joint_s_prior")
                send_data = synchlib.prepare_data(self._rvs, dims, self.ntotal - n)
                self.socket = synchlib.send_samples(send_data, self._address, self._port, verbose=True, socket=self.socket)

            #
            # The total number of adaptive steps is reached
            #
            # FIXME: We need a better stopping condition here
            if self.ntotal >= n_adapt and maxval == old_maxval:
                # Downsample points
                if save_intg and nkeep is not None:
                    pt_sort = self._rvs["weights"].argsort()[-nkeep:]
                    for key in self._rvs:
                        if len(self._rvs[key].shape) > 1:
                            self._rvs[key] = self._rvs[key][:,pt_sort]
                        else:
                            self._rvs[key] = self._rvs[key][pt_sort]
                continue
            old_maxval = maxval

            #
            # Iterate through each of the parameters, updating the sampling
            # prior PDF according to the 1-D marginalization
            #
            for itr, p in enumerate(self.params):
                # FIXME: The second part of this condition should be made more
                # specific to pinned parameters
                if p not in self.adaptive or p in kwargs.keys():
                    continue
                points = self._rvs[p][-n_history:]
                weights = (self._rvs["integrand"][-n_history:]*self._rvs["joint_prior"][-n_history:])**tempering_exp

                self._hist[p] = statutils.get_adaptive_binning(points, (self.llim[p], self.rlim[p]))
                for pt, w in zip(points, weights):
                    self._hist[p][pt,] += w
                self._hist[p].array += self._hist[p].array.mean()
                rate.filter_array(self._hist[p].array, rate.tophat_window(3))
                norm = numpy.sum(self._hist[p].array * self._hist[p].bins.volumes())
                self._hist[p].array /= norm
                # FIXME: Stupid pet trick while numpy version is lacking
                self.pdf[p] = numpy.frompyfunc(rate.InterpBinnedArray(self._hist[p]), 1, 1)
                #with open("%s_%d_hist.txt" % (p, self.ntotal), "w") as fout:
                    #for c, pdf in zip(self._hist[p].centres()[0], self._hist[p].array):
                        #print >>fout, "%f %g" % (c, pdf)

                self.cdf[p] = self.cdf_function(p)
                self.cdf_inv[p] = self.cdf_inverse(p)

        # If we were pinning any values, undo the changes we did before
        self.cdf_inv.update(tempcdfdict)
        self.pdf.update(temppdfdict)
        self._pdf_norm.update(temppdfnormdict)
        self.prior_pdf.update(temppriordict)

        # Clean out the _rvs arrays for 'irrelevant' points
        #   - create the cumulative weights
        if "weights" in self._rvs and deltaP > 0:
            # Sort the weights with the deltaL masked applied
            sorted_weights = self._rvs["weights"].argsort()
            # Make the (unnormalized) CDF
            total_weight = self._rvs["weights"][sorted_weights].cumsum()
            # Find the deltaP cutoff index
            idx = numpy.searchsorted(total_weight, deltaP*total_weight[-1], 'left')
            sorted_weights = sorted_weights[idx:]
            # Remove all samples which contribute to smallest 1e-3 of cumulative
            # probability
            for key in self._rvs.keys():
                if isinstance(key, tuple):
                    self._rvs[key] = self._rvs[key][:,sorted_weights]
                else:
                    self._rvs[key] = self._rvs[key][sorted_weights]

        if "integrand" in self._rvs and deltalnL is not None:
            deltal_mask = numpy.log(self._rvs["integrand"]) > (maxlnL - deltalnL)
            # Remove all samples which do not have L > maxlnL - deltalnL
            for key in self._rvs.keys():
                if isinstance(key, tuple):
                    self._rvs[key] = self._rvs[key][:,deltal_mask]
                else:
                    self._rvs[key] = self._rvs[key][deltal_mask]

        # Create extra dictionary to return things
        dict_return ={}
        if convergence_tests is not None:
            dict_return["convergence_test_results"] = last_convergence_test

        return int_val1/self.ntotal, var/self.ntotal, eff_samp, dict_return
    def finish(self):
        snrsq_kernel_width_at_64 = 16.,
        chisq_kernel_width = 0.02,
        sigma = 10.
        for key, lnpdf in self.densities.items():
            if key.endswith("_snr2_chi2"):
                numsamples = max(lnpdf.array.sum() / 10. + 1., 1e3)
                snrsq_bins, chisq_bins = lnpdf.bins
                snrsq_per_bin_at_64 = (snrsq_bins.upper() -
                                       snrsq_bins.lower())[snrsq_bins[64.]]
                chisq_per_bin_at_0_02 = (chisq_bins.upper() -
                                         chisq_bins.lower())[chisq_bins[0.02]]

                # apply Silverman's rule so that the width scales
                # with numsamples**(-1./6.) for a 2D PDF
                snrsq_kernel_bins = snrsq_kernel_width_at_64 / snrsq_per_bin_at_64 / numsamples**(
                    1. / 6.)
                chisq_kernel_bins = chisq_kernel_width / chisq_per_bin_at_0_02 / numsamples**(
                    1. / 6.)

                # check the size of the kernel. We don't ever let
                # it get smaller than the 2.5 times the bin size
                if snrsq_kernel_bins < 2.5:
                    snrsq_kernel_bins = 2.5
                    warnings.warn("Replacing snrsq kernel bins with 2.5")
                if chisq_kernel_bins < 2.5:
                    chisq_kernel_bins = 2.5
                    warnings.warn("Replacing chisq kernel bins with 2.5")

                # convolve bin count with density estimation kernel
                rate.filter_array(
                    lnpdf.array,
                    rate.gaussian_window(snrsq_kernel_bins,
                                         chisq_kernel_bins,
                                         sigma=sigma))

                # zero everything below the SNR cutoff. need to do the slicing
                # ourselves to avoid zero-ing the at-threshold bin
                lnpdf.array[:lnpdf.bins[0][self.snr_threshold], :] = 0.
            elif key.endswith("_snr2_duration"):
                # FIXME the duration filter kernel is left as a guess
                rate.filter_array(
                    lnpdf.array,
                    rate.gaussian_window(snrsq_kernel_bins, 11, sigma=sigma))
                # zero everything below the SNR cutoff. need to do the slicing
                # ourselves to avoid zero-ing the at-threshold bin
                lnpdf.array[:lnpdf.bins[0][self.snr_threshold], :] = 0.
            else:
                # shouldn't get here
                raise Exception
            lnpdf.normalize()
        self.mkinterps()

        #
        # never allow PDFs that have had the density estimation
        # transform applied to be written to disk:  on-disk files
        # must only ever provide raw counts.  also don't allow
        # density estimation to be applied twice
        #

        def to_xml(*args, **kwargs):
            raise NotImplementedError(
                "writing .finish()'ed LnLRDensity object to disk is forbidden")

        self.to_xml = to_xml

        def finish(*args, **kwargs):
            raise NotImplementedError(
                ".finish()ing a .finish()ed LnLRDensity object is forbidden")

        self.finish = finish
    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
    height = 8.0  # inches
    fig = figure.Figure()
    canvas = FigureCanvas(fig)
    fig.set_size_inches(width, height)
    fig.gca().set_position([
        border[0] / width, border[1] / height,
        (width - border[0] - border[2]) / width,
        (height - border[1] - border[3]) / height
    ])
    return fig


fig = newfig(options.segment)
axes = fig.gca()

rate.filter_array(trigger_rate.array,
                  rate.gaussian_window(bins_per_filterwidth))

axes.plot(trigger_rate.centres()[0], trigger_rate.at_centres())

axes.set_xlim(list(options.segment))
axes.grid(True)

for seg in ~seglist & segments.segmentlist([options.segment]):
    axes.axvspan(seg[0], seg[1], facecolor="k", alpha=0.2)

axes.set_title(
    "%s Excess Power Trigger Rate vs. Time\n(%d Triggers, %g s Moving Average)"
    % (options.instrument, num_triggers, options.window))

ticks = make_xticks(options.segment)
axes.set_xticks(ticks[0])