Exemplo n.º 1
0
    def signal_spatial(source, cut_data):
        """Calculates the angular distance between the source and the
        coincident dataset. Uses a Gaussian PDF function, centered on the
        source. Returns the value of the Gaussian at the given distances.

        :param source: Single Source
        :param cut_data: Subset of Dataset with coincident events
        :return: Array of Spatial PDF values
        """
        distance = angular_distance(cut_data["ra"], cut_data["dec"],
                                    source["ra_rad"], source["dec_rad"])
        space_term = (1.0 / (2.0 * np.pi * cut_data["sigma"]**2.0) *
                      np.exp(-0.5 * (distance / cut_data["sigma"])**2.0))

        return space_term
Exemplo n.º 2
0
        floors = []
        floor2s = []
        floor_corrected = []
        floor2_corrected = []
        ceilings = []
        x_vals = []

        for j, lower_e in enumerate(log_e_bins[:-1]):
            upper_e = log_e_bins[j + 1]
            e_mask = np.logical_and(cut_mc["logE"] >= lower_e,
                                    cut_mc["logE"] < upper_e)

            bin_mc = cut_mc[e_mask]

            x = np.degrees(
                angular_distance(bin_mc["ra"], bin_mc["dec"], bin_mc["trueRa"],
                                 bin_mc["trueDec"]))
            y = np.degrees(bin_mc["sigma"]) * 1.177

            if np.sum(e_mask) > 0:

                [floor, floor2,
                 ceiling] = weighted_quantile(x, [0.1, 0.25, 0.9],
                                              weights[e_mask])
                pull = x / y
                median_pull = weighted_quantile(pull, 0.5, weights[e_mask])

                meds += [median_pull for _ in range(2)]
                floors += [floor for _ in range(2)]
                floor2s += [floor2 for _ in range(2)]
                floor_corrected += [floor * median_pull for _ in range(2)]
                floor2_corrected += [floor2 * median_pull for _ in range(2)]
Exemplo n.º 3
0
def estimate_discovery_potential(seasons,
                                 inj_dict,
                                 sources,
                                 llh_dict,
                                 raw_scale=1.0):
    """Function to estimate discovery potential given an injection model. It
    assumes an optimal LLH construction, i.e aligned time windows and correct
    energy weighting etc. Takes injectors and seasons.

    :param injectors: Injectors to be used
    :param sources: Sources to be evaluated
    :return: An estimate for the discovery potential
    """
    logging.info("Trying to guess scale using AsimovEstimator.")

    season_bkg = []
    season_sig = []

    def weight_f(n_s, n_bkg):
        metric = np.array(n_s)  #/np.sqrt(np.array(n_bkg))
        return 1.  #metric #/ np.mean(metric)#/ max(metric)

    def ts_weight(n_s):
        return 1.
        # return n_s / np.sum(n_s)

    # def weight_ts(ts, n_s)

    weight_scale = calculate_source_weight(sources)

    livetime = 0.

    n_s_tot = 0.
    n_tot = 0.
    n_tot_coincident = 0.

    all_ns = []
    all_nbkg = []

    all_ts = []
    all_bkg_ts = []

    final_ts = []

    new_n_s = 0.
    new_n_bkg = 0.

    for season in seasons.values():

        new_llh_dict = dict(llh_dict)
        new_llh_dict["llh_name"] = "fixed_energy"
        new_llh_dict["llh_energy_pdf"] = inj_dict["injection_energy_pdf"]
        llh = LLH.create(season, sources, new_llh_dict)

        data = season.get_background_model()
        n_tot += np.sum(data["weight"])
        livetime += llh.bkg_time_pdf.livetime * 60 * 60 * 24

        def signalness(sig_over_background):
            """Converts a signal over background ratio into a signal
            probability. This is ratio/(1 + ratio)

            :param sig_over_background: Ratio of signal to background
            probability
            :return: Percentage probability of signal
            """

            return sig_over_background / (1. + sig_over_background)

        n_sigs = []
        n_bkgs = []

        ts_vals = []
        bkg_vals = []
        n_s_season = 0.

        # n_exp = np.sum(inj.n_exp["n_exp"]) * raw_scale

        sig_times = np.array(
            [llh.sig_time_pdf.effective_injection_time(x) for x in sources])
        source_weights = np.array(
            [calculate_source_weight(x) for x in sources])
        mean_time = np.sum(sig_times * source_weights) / weight_scale

        # print(source_weights)

        fluences = np.array(
            [x * sig_times[i]
             for i, x in enumerate(source_weights)]) / weight_scale
        # print(sources.dtype.names)
        # print(sources["dec_rad"], np.sin(sources["dec_rad"]))
        # print(fluences)
        # input("?")
        res = np.histogram(np.sin(sources["dec_rad"]),
                           bins=season.sin_dec_bins,
                           weights=fluences)

        dummy_sources = []
        bounds = []
        n_eff_sources = []

        for i, w in enumerate(res[0]):
            if w > 0:
                lower = res[1][i]
                upper = res[1][i + 1]
                mid = np.mean([upper, lower])

                mask = np.logical_and(
                    np.sin(sources["dec_rad"]) > lower,
                    np.sin(sources["dec_rad"]) < upper)

                n_eff_sources.append(
                    (np.sum(fluences[mask])**2. / np.sum(fluences[mask]**2)))

                # print(n_eff_sources)
                # print(fluences[mask])
                #
                # tester = np.array([1.5, 1.5, 1.5])
                #
                #
                # print(np.sum(tester**2)/(np.mean(tester)**2.))
                # input("?")

                dummy_sources.append((np.arcsin(mid), res[0][i], 1., 1.,
                                      "dummy_{0}".format(mid)))
                bounds.append((lower, upper))

        dummy_sources = np.array(dummy_sources,
                                 dtype=np.dtype([("dec_rad", np.float),
                                                 ("base_weight", np.float),
                                                 ("distance_mpc", np.float),
                                                 ("injection_weight_modifier",
                                                  np.float),
                                                 ("source_name", np.str)]))
        inj = season.make_injector(dummy_sources, **inj_dict)

        for j, dummy_source in enumerate(dummy_sources):

            lower, upper = bounds[j]

            n_eff = n_eff_sources[j]

            source_mc = inj.calculate_single_source(dummy_source,
                                                    scale=raw_scale)

            if len(source_mc) == 0:
                logging.warning(
                    "Warning, no MC found for dummy source at declinbation ".
                    format(np.arcsin(lower), np.arcsin(upper)))
                ts_vals.append(0.0)
                n_sigs.append(0.0)
                n_bkgs.append(0.0)
            else:
                # Gives the solid angle coverage of the sky for the band
                omega = 2. * np.pi * (upper - lower)

                data_mask = np.logical_and(
                    np.greater(data["dec"], np.arcsin(lower)),
                    np.less(data["dec"], np.arcsin(upper)))
                local_data = data[data_mask]

                data_weights = signalness(
                    llh.energy_weight_f(local_data)) * local_data["weight"]

                # print("source_mc", source_mc)

                mc_weights = signalness(llh.energy_weight_f(source_mc))

                true_errors = angular_distance(source_mc["ra"],
                                               source_mc["dec"],
                                               source_mc["trueRa"],
                                               source_mc["trueDec"])

                # median_sigma = weighted_quantile(
                #             true_errors, 0.5, source_mc["ow"] * mc_weights)

                median_sigma = np.mean(local_data["sigma"])

                area = np.pi * (2.0 * median_sigma)**2 / np.cos(
                    dummy_source["dec_rad"])

                local_rate = np.sum(data_weights)

                # n_bkg = local_rate * area  # * source_weight
                n_bkg = np.sum(local_data["weight"])

                n_tot_coincident += n_bkg

                ratio_time = livetime / mean_time

                sig_spatial = signalness((1. / (2. * np.pi * source_mc["sigma"] ** 2.) *
                                          np.exp(-0.5 * (
                                                  (true_errors / source_mc["sigma"]) ** 2.))) \
                                         / llh.spatial_pdf.background_spatial(source_mc))

                ra_steps = np.linspace(-np.pi, np.pi, 100)
                dec_steps = np.linspace(lower, upper, 10)

                mean_dec = np.mean(
                    signalness(
                        norm.pdf(dec_steps,
                                 scale=median_sigma /
                                 np.cos(dummy_source["dec_rad"]),
                                 loc=np.mean([lower, upper])) *
                        (upper - lower)))

                mean_ra = np.mean(
                    signalness(
                        norm.pdf(ra_steps, scale=median_sigma, loc=0.) * 2. *
                        np.pi))

                bkg_spatial = mean_dec * mean_ra  # * n_eff

                n_s_tot += np.sum(source_mc["ow"])
                n_s_season += np.sum(source_mc["ow"])

                med_sig = np.mean(sig_spatial * mc_weights) * signalness(
                    ratio_time) * np.sum(source_mc["ow"])
                med_bkg = np.mean(bkg_spatial * data_weights) * (
                    1. - signalness(ratio_time)) * n_bkg

                new_n_s += med_sig
                new_n_bkg += med_bkg

    scaler_ratio = new_n_s / n_s_tot

    scaler_ratio = new_n_bkg / n_tot_coincident

    print("Scaler Ratio", scaler_ratio)

    disc_count = norm.ppf(norm.cdf(5.0), loc=0.,
                          scale=np.sqrt(new_n_bkg))  # * scaler_ratio

    simple = 5. * np.sqrt(new_n_bkg)  # * scaler_ratio
    #
    # disc_count = simple

    # print(disc_count, simple, simple/disc_count, n_s_tot)
    #
    # print("testerer", new_n_s, new_n_bkg)
    #
    print("Disc count", disc_count, disc_count / scaler_ratio)
    scale = disc_count / new_n_s
    print(scale)

    # Convert from scale factor to flux units

    scale = k_to_flux(scale) * raw_scale

    logging.info(
        "Estimated Discovery Potential is: {:.3g} GeV sr^-1 s^-1 cm^-2".format(
            scale))

    return scale
Exemplo n.º 4
0
def get_pulls(mc):
    x = np.degrees(
        angular_distance(mc["ra"], mc["dec"], mc["trueRa"], mc["trueDec"]))
    y = np.degrees(mc["sigma"]) * 1.177
    return x / y
Exemplo n.º 5
0
def get_data(season):
    mc = data_loader(season["mc_path"], floor=True)
    x = np.degrees(angular_distance(
        mc["ra"], mc["dec"], mc["trueRa"], mc["trueDec"]))
    y = np.degrees(mc["sigma"]) * 1.177
    return mc, x, y