示例#1
0
def incorporate_recon(event_edges, cascade_edges, nuflux, angle_edges):
    """
    This takes in the results from `generate_singly_diff_fluxes` and incorporates reconstruction uncertainties

    Should take in a list or array of energies (true, deposited), in units of eV
    And also take in a list of true cos(zenith) edges 
    """
    e_min = min(cascade_edges)
    e_max = max(cascade_edges)

    z_min = min(angle_edges)
    z_max = max(angle_edges)

    # we need to get all the centers for these bins with the given edges. 
    # these will be associeed with each of the bins in nuflux 
    
    cascade_centers = bhist([cascade_edges]).centers
    true_e_centers = bhist([event_edges]).centers
    true_ang_centers = bhist([angle_edges]).centers
   
    # these are reconstruction objects 
    r_energy = bhist([ np.logspace(np.log10(e_min), np.log10(e_max), int(len(cascade_edges)/2)) ])
    r_angle  = bhist([ np.linspace( z_min, z_max, int(len(angle_edges)/2))])
    
    print("Reconstruction Parameters")
    print("    Energy: {} to {} GeV".format(sci(e_min), sci(e_max)))
    print("    cos(t): {} to {} ".format(z_min, z_max))

    r_energy_centers = r_energy.centers
    r_energy_widths = r_energy.widths
    r_angle_centers = r_angle.centers
    r_angle_widths = r_angle.widths

    #build the data object
    # this thing take in those edges and centers and correctly builds normalized probabilities for the given bins 
    dataobj = DataReco(r_energy.edges, r_angle.edges, cascade_edges, angle_edges)

    # may god have mercy on our souls 
    recoflux = {}
    for key in nuflux.keys():
        print("Reconstructing {} Flux".format(key))
        # energy x, angle y
        recoflux[key] = np.zeros(shape=(len(r_energy_centers),len(true_e_centers), len(r_angle_centers),len(true_ang_centers)))
        for i_e_reco in range(len(r_energy_centers)):
            for i_e_depo in range(len(cascade_centers)):
                depo_odds = dataobj.get_energy_reco_odds(i_e_depo, i_e_reco) #per 
                if depo_odds<=0.:
                    continue
                for i_a_true in range(len(true_ang_centers)):
                    for i_a_reco in range(len(r_angle_centers)):
                        ang_odds = dataobj.get_czenith_reco_odds(i_a_true, i_a_reco,0) #per sr
                        if ang_odds<=0.:
                            continue
                        for i_e_true in range(len(true_e_centers)):
                            amt = nuflux[key][i_e_depo][i_e_true][i_a_true]# *depo_odds*ang_odds #per angle per gev depo
                            if amt>=0:
                                recoflux[key][i_e_reco][i_e_true][i_a_reco][i_a_true] += amt

    _save_data(r_energy.edges, event_edges, r_angle.edges, angle_edges, recoflux)
def build_contours(obs_e, obs_angle):
    """
    Presuming we're given some observed angle and observed energy...

    We first figure out which event bin we want 
    """

    obs_energy = obs_e * (1e9)

    # these are bin edges
    e_reco, e_true, a_reco, a_true, probs = load_file()

    # let's get the centers we want
    e_true_centers = bhist([e_true]).centers
    a_true_centers = bhist([a_true]).centers
    e_reco_centers = bhist([e_reco]).centers
    a_reco_centers = bhist([a_reco]).centers

    e_left, e_right = get_loc(obs_energy, e_reco_centers)
    a_left, a_right = get_loc(obs_angle, a_reco_centers)

    # so this is a bit wild. The reco-space entries are coarse. So, we grab neighboring 2D reconstruction arrays and do a bilinear interpolation of 2D arrays around our given point in reco-space
    key = list(probs.keys())[6]
    p0 = (obs_energy, obs_angle)

    p1 = (e_reco_centers[e_left], a_reco_centers[a_left])
    p2 = (e_reco_centers[e_right], a_reco_centers[a_right])

    print(np.shape(probs[key]))
    #q11=probs[key][e_left,:,a_left,:]
    #q21=probs[key][e_right,:,a_left,:]
    #q12=probs[key][e_left,:,a_right,:]
    #q22=probs[key][e_right,:,a_right,:]
    q11 = slicer(probs[key], e_left, a_left)
    q21 = slicer(probs[key], e_right, a_left)
    q12 = slicer(probs[key], e_left, a_right)
    q22 = slicer(probs[key], e_right, a_right)

    focus_prob = bilinear_interp(p0, p1, p2, q11, q12, q21, q22)
    del probs  # clear this out of memory. It's really big...

    # pcolormesh
    focus_prob = np.ma.masked_where(focus_prob <= 0, focus_prob)

    plt.pcolormesh(
        np.array(e_true_centers) / (1e9), a_true_centers,
        np.transpose(focus_prob))
    plt.xlabel("True Energy [GeV]", size=14)
    plt.xscale('log')
    plt.ylabel("Cos Zenith", size=14)
    plt.title(r"Expected Truth for E={} GeV, $\cos\theta$={}".format(
        sci(obs_e), obs_angle))
    plt.savefig("contour.png", dpi=400)
    plt.show()
示例#3
0
    def __init__(self, reco_energy_edges, reco_czenith_edges,
                 depo_energy_edges, true_czenith_edges):
        """
        Expects the energies in eV, but works in GeV
        """

        self._ereco = bhist([np.array(reco_energy_edges) * (1e-9)])
        self._edepo = bhist([np.array(depo_energy_edges) * (1e-9)])
        self._zreco = bhist([reco_czenith_edges
                             ])  # these two are in cos(Zenith)
        self._ztrue = bhist([true_czenith_edges])

        # these are now filled with the values of the probability DENSITY functions for each angle/energy combo
        # TODO right now there is no assumed covariance ... this should be improved
        self._energy_odds_array = np.array([[
            get_odds_energy(deposited, reconstructed)
            for reconstructed in self.reco_energy_centers
        ] for deposited in self.depo_energy_centers])
        self._angle_odds_array = np.array([[
            get_odds_angle(true, reconstructed)
            for reconstructed in self.reco_czenith_centers
        ] for true in self.true_czenith_centers])

        # Avoid equating two floats. Look for a sufficiently small difference!
        max_diff = 1e-12

        # normalize these things!
        # so for each energy deposited... the sum of (PDF*width evaluated at each reco bin) should add up to 1.
        for depo in range(len(self._energy_odds_array)):
            self._energy_odds_array[depo] *= 1. / sum(
                self._energy_odds_array[depo] * self.reco_energy_widths)
            assert (abs(1 - sum(self._energy_odds_array[depo] *
                                self.reco_energy_widths)) <= max_diff)

        for depo in range(len(self._angle_odds_array)):
            self._angle_odds_array[depo] *= 1. / sum(
                self._angle_odds_array[depo] * self.reco_czenith_widths)
            assert (abs(1 - sum(self._angle_odds_array[depo] *
                                self.reco_czenith_widths)) <= max_diff)
示例#4
0
def _load_flux(filename):
    f = open(filename, 'rb')
    all_data = pickle.load(f)
    f.close()

    e_reco = all_data["e_reco"]
    a_reco = all_data["a_reco"]
    flux = all_data["flux"]

    return (e_reco, a_reco, flux)


if True:
    e_reco, a_reco, flux = _load_flux(filename)

    energies = np.array(bhist([e_reco]).centers)
    czeniths = np.array(bhist([a_reco]).centers)

    from_muon, from_not = sep_by_flavor(flux)

    cf = plt.pcolormesh(czeniths,
                        energies / (1e9),
                        np.log10(from_not),
                        cmap=cm.coolwarm)  #, locator=ticker.LogLocator())
    plt.yscale('log')
    plt.ylabel("Event Energy [GeV]", size=14)
    plt.xlabel(r"Reconstructed $\cos\theta$", size=14)
    plt.title("Not Muons", size=14)
    cbar = plt.colorbar()  #cf,ticks=ticker.LogLocator())
    cbar.set_label(r"$\log\Phi$ [GeV sr s cm$^{2}$]$^{-1}$")
    plt.savefig("reco_flux_not_muon.png", dpi=400)
示例#5
0
def do_for_key(event_edges, cascade_edges, key, angles=None):
    """
    This function takes the desired bin edges for the event energies and deposited energies along with the dictionary key corresponding to a specific combination of falvor, current, and neutrino type.

    It builds up the 2D flux array (singly differential), which it then returns 
    """
    evt = bhist([event_edges])
    cas = bhist([cascade_edges])
    reco = bhist([cascade_edges])

    event_energies = evt.centers
    event_widths = evt.widths
    cascade_energies = cas.centers
    cascade_widths = cas.widths
    reco_energies = reco.centers
    reco_widths = reco.widths

    flav = key.split("_")[0]
    curr = key.split("_")[2]

    if angles is None:
        ang_list = [None]
    else:
        ang_list = angles

    if angles is None:
        flux = bhist((cascade_edges, event_edges))
    else:
        flux = bhist((cascade_edges, event_edges, angles))

    for angle in ang_list:
        # need special Tau treatment
        if curr == "CC":
            # deposit all the energy. Hadronic and Leptonic (event) contribute
            # Since the energy always all gets deposited, we only need to do one loop!
            # So, for a given "deposited energy" (cascade_energy), we already know the total energy.
            # Therefore we just get the total cross section * flux there... the units end up as [s GeV in sr]^-1
            for cas_bin in range(len(cascade_energies)):
                deposited_energy = cascade_energies[
                    cas_bin]  # energy going to the leptonic component!

                if flav.lower() == 'tau':
                    # Etau is cascade_energies[cas_bin]
                    # How much energy is visible in the various tau decays though?
                    # going from zero->deposited energy
                    deposited_energy = 0.5 * (
                        tauData(deposited_energy / const.GeV, 1) +
                        tauData(deposited_energy / const.GeV, -1))

                amount = data.get_flux(deposited_energy, key, angle=angle)
                amount *= get_diff_xs(deposited_energy, get_flavor(key),
                                      get_neut(key), get_curr(key))
                try:
                    if angle is None:
                        flux.register(amount, cascade_energies[cas_bin],
                                      deposited_energy)  # add it in!
                    else:
                        flux.register(amount, cascade_energies[cas_bin],
                                      deposited_energy, angle)
                except ValueError:
                    if flav.lower() != 'tau':
                        raise Exception("It wasn't tau. Something's wrong")

        else:
            # in this case, knowing the cascade doesn't tell us anything about the event energy.
            # so we loop over both, get the flux*differential_xs at each bin combination, and multiply by the widths of deposited-energy-bin to get the same units as in the CC case
            for evt_bin in range(len(event_energies)):
                for cas_bin in range(len(cascade_energies)):
                    lepton_energy = event_energies[evt_bin] - cascade_energies[
                        cas_bin]

                    # we'll have nowhere to put these, so let's just skip this
                    if lepton_energy < min(cascade_energies):
                        continue
                    if lepton_energy > max(cascade_energies):
                        continue

                    amount = data.get_flux(event_energies[evt_bin],
                                           key,
                                           angle=angle)
                    amount *= get_diff_xs(event_energies[evt_bin],
                                          get_flavor(key), get_neut(key),
                                          get_curr(key), lepton_energy,
                                          0.0) * cascade_widths[cas_bin]
                    if angle is None:
                        flux.register(amount, cascade_energies[cas_bin],
                                      event_energies[evt_bin])
                    else:
                        flux.register(amount, cascade_energies[cas_bin],
                                      event_energies[evt_bin], angle)

    # build a new bhist in reconstruction space (Still with event energy too)
    # then scan through deposited-true angle space
    # and use the PDFS to smear the true values into reconstructed values, depositing them into the reconstruction bhist

    return (flux.fill)
示例#6
0
    plt.legend()
    print("saving 'wow.png'")
    plt.savefig("wow_{:.2f}.png".format(glob_angle),dpi=400)

savefile = ".analysis_level.dat"


if mode==8 or do_all:
    if load_stored and os.path.exists(savefile):
        event, cascade, nuflux, angle_edges = _load_data(glob_angle)
    else:
        event, cascade, nuflux, angle_edges = generate_singly_diff_fluxes(n_bins)

    from_muon, from_not = sep_by_flavor(nuflux)

    event_energies = np.array(bhist([event]).centers)
    cascade_energies = np.array(bhist([cascade]).centers)

    from_muon = np.ma.masked_where(from_muon<=0, from_muon)
    from_not  = np.ma.masked_where(from_not<=0, from_not)

    plt.figure()
    levels = np.logspace(-50,-33,10)
    print("Max of muon: {}".format(np.max(from_muon)))
    cf = plt.contourf(event_energies/const.GeV, cascade_energies/const.GeV, from_muon,cmap=cm.coolwarm, locator=ticker.LogLocator(), levels=levels)
    plt.xscale('log')
    plt.yscale('log')
    plt.xlabel('Parent Energy [GeV]', size=14)
    plt.ylabel('Cascade Energy [GeV]', size=14)
    plt.grid(which='major',alpha=0.7)
    cbar = plt.colorbar(cf,ticks=ticker.LogLocator())