Пример #1
0
	def __init__(self, instruments):
		self.densities = {}
		for instrument in instruments:
			self.densities["%s_snr2_chi2" % instrument] = rate.BinnedLnPDF(rate.NDBins((rate.ATanLogarithmicBins(10, 1e7, 801), rate.ATanLogarithmicBins(.1, 1e4, 801))))
		for pair in itertools.combinations(sorted(instruments), 2):
			dt = 0.005 + snglcoinc.light_travel_time(instrument1, instrument2)	# seconds
			self.densities["%s_%s_dt" % pair] = rate.BinnedLnPDF(rate.NDBins((rate.ATanBins(-dt, +dt, 801),)))
			self.densities["%s_%s_dA" % pair] = rate.BinnedLnPDF(rate.NDBins((rate.ATanBins(-0.5, +0.5, 801),)))
			self.densities["%s_%s_df" % pair] = rate.BinnedLnPDF(rate.NDBins((rate.ATanBins(-0.2, +0.2, 501),)))
		# only non-negative rss timing residual bins will be used
		# but we want a binning that's linear at the origin so
		# instead of inventing a new one we just use atan bins that
		# are symmetric about 0
		self.densities["instrumentgroup,rss_timing_residual"] = rate.BinnedLnPDF(rate.NDBins((snglcoinc.InstrumentBins(names = instruments), rate.ATanBins(-0.02, +0.02, 1001))))
def dt_binning(instrument1, instrument2):
    # FIXME:  hard-coded for directional search
    #dt = 0.02 + inject.light_travel_time(instrument1, instrument2)
    dt = 0.02
    return rate.NDBins(
        (rate.ATanBins(-dt, +dt, 12001), rate.LinearBins(0.0, 2 * math.pi,
                                                         61)))
Пример #3
0
 def __init__(self, instruments):
     self.densities = {}
     for pair in intertools.combinations(sorted(instruments), 2):
         # FIXME:  hard-coded for directional search
         #dt = 0.02 + snglcoinc.light_travel_time(*pair)
         dt = 0.02
         self.densities["%s_%s_dt" % pair] = rate.BinnedLnDPF(
             rate.NDBins((rate.ATanBins(-dt, +dt, 12001),
                          rate.LinearBins(0.0, 2 * math.pi, 61))))
         self.densities["%s_%s_dband" % pair] = rate.BinnedLnDPF(
             rate.NDBins((rate.LinearBins(-2.0, +2.0, 12001),
                          rate.LinearBins(0.0, 2 * math.pi, 61))))
         self.densities["%s_%s_ddur" % pair] = rate.BinnedLnDPF(
             rate.NDBins((rate.LinearBins(-2.0, +2.0, 12001),
                          rate.LinearBins(0.0, 2 * math.pi, 61))))
         self.densities["%s_%s_df" % pair] = rate.BinnedLnDPF(
             rate.NDBins((rate.LinearBins(-2.0, +2.0, 12001),
                          rate.LinearBins(0.0, 2 * math.pi, 61))))
         self.densities["%s_%s_dh" % pair] = rate.BinnedLnDPF(
             rate.NDBins((rate.LinearBins(-2.0, +2.0, 12001),
                          rate.LinearBins(0.0, 2 * math.pi, 61))))
Пример #4
0
def dt_binning(instrument1, instrument2):
    dt = 0.005 + snglcoinc.light_travel_time(instrument1,
                                             instrument2)  # seconds
    return rate.NDBins((rate.ATanBins(-dt, +dt, 801), ))
Пример #5
0
class StringCoincParamsDistributions(snglcoinc.CoincParamsDistributions):
    ligo_lw_name_suffix = u"stringcusp_coincparamsdistributions"

    binnings = {
        "H1_snr2_chi2":
        rate.NDBins((rate.ATanLogarithmicBins(10, 1e7, 801),
                     rate.ATanLogarithmicBins(.1, 1e4, 801))),
        "H2_snr2_chi2":
        rate.NDBins((rate.ATanLogarithmicBins(10, 1e7, 801),
                     rate.ATanLogarithmicBins(.1, 1e4, 801))),
        "L1_snr2_chi2":
        rate.NDBins((rate.ATanLogarithmicBins(10, 1e7, 801),
                     rate.ATanLogarithmicBins(.1, 1e4, 801))),
        "V1_snr2_chi2":
        rate.NDBins((rate.ATanLogarithmicBins(10, 1e7, 801),
                     rate.ATanLogarithmicBins(.1, 1e4, 801))),
        "H1_H2_dt":
        dt_binning("H1", "H2"),
        "H1_L1_dt":
        dt_binning("H1", "L1"),
        "H1_V1_dt":
        dt_binning("H1", "V1"),
        "H2_L1_dt":
        dt_binning("H2", "L1"),
        "H2_V1_dt":
        dt_binning("H2", "V1"),
        "L1_V1_dt":
        dt_binning("L1", "V1"),
        "H1_H2_dA":
        rate.NDBins((rate.ATanBins(-0.5, +0.5, 801), )),
        "H1_L1_dA":
        rate.NDBins((rate.ATanBins(-0.5, +0.5, 801), )),
        "H1_V1_dA":
        rate.NDBins((rate.ATanBins(-0.5, +0.5, 801), )),
        "H2_L1_dA":
        rate.NDBins((rate.ATanBins(-0.5, +0.5, 801), )),
        "H2_V1_dA":
        rate.NDBins((rate.ATanBins(-0.5, +0.5, 801), )),
        "L1_V1_dA":
        rate.NDBins((rate.ATanBins(-0.5, +0.5, 801), )),
        "H1_H2_df":
        rate.NDBins((rate.ATanBins(-0.2, +0.2, 501), )),
        "H1_L1_df":
        rate.NDBins((rate.ATanBins(-0.2, +0.2, 501), )),
        "H1_V1_df":
        rate.NDBins((rate.ATanBins(-0.2, +0.2, 501), )),
        "H2_L1_df":
        rate.NDBins((rate.ATanBins(-0.2, +0.2, 501), )),
        "H2_V1_df":
        rate.NDBins((rate.ATanBins(-0.2, +0.2, 501), )),
        "L1_V1_df":
        rate.NDBins((rate.ATanBins(-0.2, +0.2, 501), )),
        # only non-negative rss timing residual bins will be used
        # but we want a binning that's linear at the origin so
        # instead of inventing a new one we just use atan bins that
        # are symmetric about 0
        "instrumentgroup,rss_timing_residual":
        rate.NDBins((snglcoinc.InstrumentBins(names=("H1", "H2", "L1", "V1")),
                     rate.ATanBins(-0.02, +0.02, 1001)))
    }

    filters = {
        "H1_snr2_chi2":
        rate.gaussian_window(11, 11, sigma=20),
        "H2_snr2_chi2":
        rate.gaussian_window(11, 11, sigma=20),
        "L1_snr2_chi2":
        rate.gaussian_window(11, 11, sigma=20),
        "V1_snr2_chi2":
        rate.gaussian_window(11, 11, sigma=20),
        "H1_H2_dt":
        rate.gaussian_window(11, sigma=20),
        "H1_L1_dt":
        rate.gaussian_window(11, sigma=20),
        "H1_V1_dt":
        rate.gaussian_window(11, sigma=20),
        "H2_L1_dt":
        rate.gaussian_window(11, sigma=20),
        "H2_V1_dt":
        rate.gaussian_window(11, sigma=20),
        "L1_V1_dt":
        rate.gaussian_window(11, sigma=20),
        "H1_H2_dA":
        rate.gaussian_window(11, sigma=20),
        "H1_L1_dA":
        rate.gaussian_window(11, sigma=20),
        "H1_V1_dA":
        rate.gaussian_window(11, sigma=20),
        "H2_L1_dA":
        rate.gaussian_window(11, sigma=20),
        "H2_V1_dA":
        rate.gaussian_window(11, sigma=20),
        "L1_V1_dA":
        rate.gaussian_window(11, sigma=20),
        "H1_H2_df":
        rate.gaussian_window(11, sigma=20),
        "H1_L1_df":
        rate.gaussian_window(11, sigma=20),
        "H1_V1_df":
        rate.gaussian_window(11, sigma=20),
        "H2_L1_df":
        rate.gaussian_window(11, sigma=20),
        "H2_V1_df":
        rate.gaussian_window(11, sigma=20),
        "L1_V1_df":
        rate.gaussian_window(11, sigma=20),
        # instrument group filter is a no-op, should produce a
        # 1-bin top-hat window.
        "instrumentgroup,rss_timing_residual":
        rate.gaussian_window(1e-100, 11, sigma=20)
    }

    @staticmethod
    def coinc_params(events, offsetvector, triangulators):
        #
        # check for coincs that have been vetoed entirely
        #

        if len(events) < 2:
            return None

        #
        # Initialize the parameter dictionary, sort the events by
        # instrument name (the multi-instrument parameters are defined for
        # the instruments in this order and the triangulators are
        # constructed this way too), and retrieve the sorted instrument
        # names
        #

        params = {}
        events = tuple(sorted(events, key=lambda event: event.ifo))
        instruments = tuple(event.ifo for event in events)

        #
        # zero-instrument parameters
        #

        ignored, ignored, ignored, rss_timing_residual = triangulators[
            instruments](tuple(event.peak + offsetvector[event.ifo]
                               for event in events))
        # FIXME:  rss_timing_residual is forced to 0 to disable this
        # feature.  all the code to compute it properly is still here and
        # given suitable initializations, the distribution data is still
        # two-dimensional and has a suitable filter applied to it, but all
        # events are forced into the RSS_{\Delta t} = 0 bin, in effect
        # removing that dimension from the data.  We can look at this again
        # sometime in the future if we're curious why it didn't help.  Just
        # delete the next line and you're back in business.
        rss_timing_residual = 0.0
        params["instrumentgroup,rss_timing_residual"] = (
            frozenset(instruments), rss_timing_residual)

        #
        # one-instrument parameters
        #

        for event in events:
            prefix = "%s_" % event.ifo

            params["%ssnr2_chi2" % prefix] = (event.snr**2.0,
                                              event.chisq / event.chisq_dof)

        #
        # two-instrument parameters.  note that events are sorted by
        # instrument
        #

        for event1, event2 in iterutils.choices(events, 2):
            assert event1.ifo != event2.ifo

            prefix = "%s_%s_" % (event1.ifo, event2.ifo)

            dt = float((event1.peak + offsetvector[event1.ifo]) -
                       (event2.peak + offsetvector[event2.ifo]))
            params["%sdt" % prefix] = (dt, )

            dA = math.log10(abs(event1.amplitude / event2.amplitude))
            params["%sdA" % prefix] = (dA, )

            # f_cut = central_freq + bandwidth/2
            f_cut1 = event1.central_freq + event1.bandwidth / 2
            f_cut2 = event2.central_freq + event2.bandwidth / 2
            df = float((math.log10(f_cut1) - math.log10(f_cut2)) /
                       (math.log10(f_cut1) + math.log10(f_cut2)))
            params["%sdf" % prefix] = (df, )

        #
        # done
        #

        return params

    def add_slidelessbackground(self,
                                database,
                                experiments,
                                param_func_args=()):
        # FIXME:  this needs to be taught how to not slide H1 and
        # H2 with respect to each other

        # segment lists
        seglists = database.seglists - database.vetoseglists

        # construct the event list dictionary.  remove vetoed
        # events from the lists and save event peak times so they
        # can be restored later
        eventlists = {}
        orig_peak_times = {}
        for event in database.sngl_burst_table:
            if event.peak in seglists[event.ifo]:
                try:
                    eventlists[event.ifo].append(event)
                except KeyError:
                    eventlists[event.ifo] = [event]
                orig_peak_times[event] = event.peak

        # parse the --thresholds H1,L1=... command-line options from burca
        delta_t = [
            float(threshold.split("=")[-1])
            for threshold in ligolw_process.get_process_params(
                database.xmldoc, "ligolw_burca", "--thresholds")
        ]
        if not all(delta_t[0] == threshold for threshold in delta_t[1:]):
            raise ValueError(
                "\Delta t is not unique in ligolw_burca arguments")
        delta_t = delta_t.pop()

        # construct the coinc generator.  note that H1+H2-only
        # coincs are forbidden, which is affected here by removing
        # that instrument combination from the object's internal
        # .rates dictionary
        coinc_generator = snglcoinc.CoincSynthesizer(eventlists, seglists,
                                                     delta_t)
        if frozenset(("H1", "H2")) in coinc_generator.rates:
            del coinc_generator.rates[frozenset(("H1", "H2"))]

        # build a dictionary of time-of-arrival generators
        toa_generator = dict(
            (instruments, coinc_generator.plausible_toas(instruments))
            for instruments in coinc_generator.rates.keys())

        # how many coincs?  the expected number is obtained by
        # multiplying the total zero-lag time for which at least
        # two instruments were on by the sum of the rates for all
        # coincs to get the mean number of coincs per zero-lag
        # observation time, and multiplying that by the number of
        # experiments the background should simulate to get the
        # mean number of background events to simulate.  the actual
        # number simulated is a Poisson-distributed RV with that
        # mean.
        n_coincs, = scipy.stats.poisson.rvs(
            float(abs(segmentsUtils.vote(seglists.values(), 2))) *
            sum(coinc_generator.rates.values()) * experiments)

        # generate synthetic background coincs
        zero_lag_offset_vector = offsetvector(
            (instrument, 0.0) for instrument in seglists)
        for n, events in enumerate(
                coinc_generator.coincs(lsctables.SnglBurst.get_peak)):
            # n = 1 on 2nd iteration, so placing this condition
            # where it is in the loop causes the correct number
            # of events to be added to the background
            if n >= n_coincs:
                break
            # assign fake peak times
            toas = toa_generator[frozenset(event.ifo
                                           for event in events)].next()
            for event in events:
                event.peak = toas[event.ifo]
            # compute coincidence parameters
            self.add_background(
                self.coinc_params(events, zero_lag_offset_vector,
                                  *param_func_args))

        # restore original peak times
        for event, peak_time in orig_peak_times.iteritems():
            event.peak = peak_time