Example #1
0
class AeffServiceMC:
    '''
    Takes the weighted effective area files, and creates a dictionary
    of the 2D effective area in terms of energy and coszen, for each
    flavor (nue,nue_bar,numu,...) and interaction type (CC, NC)
    '''
    def __init__(self, ebins, czbins, aeff_weight_file=None, **kwargs):
        self.ebins = ebins
        self.czbins = czbins
        logging.info('Initializing AeffServiceMC...')

        logging.info('Opening file: %s' % (aeff_weight_file))
        try:
            fh = h5py.File(find_resource(aeff_weight_file), 'r')
        except IOError, e:
            logging.error("Unable to open aeff_weight_file %s" %
                          aeff_weight_file)
            logging.error(e)
            sys.exit(1)

        self.aeff_dict = {}
        logging.info("Creating effective area dict...")
        for flavor in [
                'nue', 'nue_bar', 'numu', 'numu_bar', 'nutau', 'nutau_bar'
        ]:
            flavor_dict = {}
            logging.debug("Working on %s effective areas" % flavor)
            for int_type in ['cc', 'nc']:
                weighted_aeff = np.array(fh[flavor + '/' + int_type +
                                            '/weighted_aeff'])
                true_energy = np.array(fh[flavor + '/' + int_type +
                                          '/true_energy'])
                true_coszen = np.array(fh[flavor + '/' + int_type +
                                          '/true_coszen'])

                bins = (self.ebins, self.czbins)
                aeff_hist, _, _ = np.histogram2d(true_energy,
                                                 true_coszen,
                                                 weights=weighted_aeff,
                                                 bins=bins)
                # Divide by bin widths to convert to aeff:
                ebin_sizes = get_bin_sizes(ebins)
                czbin_sizes = 2.0 * np.pi * get_bin_sizes(czbins)
                bin_sizes = np.meshgrid(czbin_sizes, ebin_sizes)
                aeff_hist /= np.abs(bin_sizes[0] * bin_sizes[1])

                flavor_dict[int_type] = aeff_hist

            self.aeff_dict[flavor] = flavor_dict

        return
Example #2
0
def get_aeff1D(data,cuts_list,ebins,files_per_run,mcnu='MCNeutrino',
               nc=False,solid_angle=None):
    '''
    Return 1D Aeff directly from simulations (using OneWeight) as a
    histogram, including the error bars.

    \params:
      * data - data table from a hdf5 PyTables file.
      * cuts_list - np array of indices for events passing selection cuts
      * ebins - energy bin edges in GeV that the Aeff histogram
        will be formed from
      * files_per_run - file number normalization to correctly calculate
        simulation weight for Aeff. Should be number of simulation files
        per run for flavour.
      * mcnu - Monte Carlo neutrino field/key in hdf5 file to use for MC
        true information.
      * solid_angle - total solid angle to integrate over. Most of the
        time, we only calculate Aeff for upgoing events, so we do half
        the 4pi solid angle of the whole sky, which would be 2.0*np.pi
      * nc - set this flag to true if we are using NC files.
    '''

    #if not nc:
    nfiles = len(set(data.root.I3EventHeader.col('Run')))*files_per_run
    logging.info("runs: %s"%str(set(data.root.I3EventHeader.col('Run'))))
    logging.info("num runs: %d"%len(set(data.root.I3EventHeader.col('Run'))))
    total_events = data.root.I3MCWeightDict.col('NEvents')[cuts_list]*nfiles/2.0

    # NOTE: solid_angle should be coordinated with get_arb_cuts(cut_sim_down=bool)
    sim_wt_array = (data.root.I3MCWeightDict.col('OneWeight')[cuts_list]/
                    total_events/solid_angle)
    # Not sure why nu_<> cc needs __getattr__ and only NC combined
    # file needs __getattribute__??
    try:
        egy_array = data.root.__getattr__(mcnu).col('energy')[cuts_list]
    except:
        egy_array = data.root.__getattribute__(mcnu).col('energy')[cuts_list]
    aeff,xedges = np.histogram(egy_array,weights=sim_wt_array,bins=ebins)

    egy_bin_widths = get_bin_sizes(ebins)

    aeff /= egy_bin_widths
    aeff*=1.0e-4 # [cm^2] -> [m^2]

    unweighted_events,xedges = np.histogram(egy_array,bins=ebins)

    # So that the error calculation comes out right without divide by zeros...
    unweighted_events = [1. if val < 1.0 else val for val in unweighted_events]

    aeff_error = np.divide(aeff,np.sqrt(unweighted_events))

    logging.debug("percent error on aeff: %s"%str(np.nan_to_num(aeff/aeff_error)))

    return aeff,aeff_error,xedges
Example #3
0
 def get_flux(self, ebins, czbins, prim):
     '''Get the flux in units [m^-2 s^-1] for the given
        bin edges in energy and cos(zenith) and the primary.'''
     
     #Evaluate the flux at the bin centers
     evals = get_bin_centers(ebins)
     czvals = get_bin_centers(czbins)
 
     # Get the spline interpolation, which is in
     # log(flux) as function of log(E), cos(zenith)
     return_table = bisplev(np.log10(evals), czvals, self.spline_dict[prim])
     return_table = np.power(10., return_table).T
 
     #Flux is given per sr and GeV, so we need to multiply
     #by bin width in both dimensions
     #Get the bin size in both dimensions
     ebin_sizes = get_bin_sizes(ebins)
     czbin_sizes = 2.*np.pi*get_bin_sizes(czbins)
     bin_sizes = np.meshgrid(ebin_sizes, czbin_sizes)
 
     return_table *= np.abs(bin_sizes[0]*bin_sizes[1])
 
     return return_table.T
Example #4
0
    def get_flux(self, ebins, czbins, prim):
        """Get the flux in units [m^-2 s^-1] for the given
           bin edges in energy and cos(zenith) and the primary."""

        #Evaluate the flux at the bin centers
        evals = get_bin_centers(ebins)
        czvals = get_bin_centers(czbins)

        # Get the spline interpolation, which is in
        # log(flux) as function of log(E), cos(zenith)
        return_table = bisplev(np.log10(evals), czvals, self.spline_dict[prim])
        return_table = np.power(10., return_table).T

        #Flux is given per sr and GeV, so we need to multiply
        #by bin width in both dimensions
        #Get the bin size in both dimensions
        ebin_sizes = get_bin_sizes(ebins)
        czbin_sizes = 2. * np.pi * get_bin_sizes(czbins)
        bin_sizes = np.meshgrid(ebin_sizes, czbin_sizes)

        return_table *= np.abs(bin_sizes[0] * bin_sizes[1])

        return return_table.T
Example #5
0
    def _get_reco_kernels(self, flipback=True,
                          e_reco_scale=None, cz_reco_scale=None,
                          **kwargs):
        """
        Use the parametrization functions to calculate the actual reco
        kernels (i.e. 4D histograms). If flipback==True, the zenith angle
        part that goes below the zenith will be mirrored back in.
        """
        if all([hasattr(self, 'kernels'), e_reco_scale==1., cz_reco_scale==1.]):
            logging.info('Using existing kernels for reconstruction')
            return self.kernels

        logging.info('Creating parametrized reconstruction kernels')

        # get binning information
        evals, esizes = get_bin_centers(self.ebins), get_bin_sizes(self.ebins)
        czvals, czsizes = get_bin_centers(self.czbins), get_bin_sizes(self.czbins)
        czbins = self.czbins 
        n_e, n_cz = len(evals), len(czvals)

        # prepare for folding back at lower edge
        if not is_linear(self.czbins):
            logging.warn("cos(zenith) bins have different "
                         "sizes! Unable to fold around edge "
                         "of histogram, will not do that.")
            flipback = False

        if flipback:
            czvals = np.append(czvals-(self.czbins[-1]-self.czbins[0]),
                               czvals)
            czbins = np.append(czbins[:-1]-(self.czbins[-1]-self.czbins[0]),
                               czbins)
            czsizes = np.append(czsizes, czsizes)

        # get properly scaled parametrization, initialize kernels
        parametrization = self.apply_reco_scales(e_reco_scale, cz_reco_scale)
        kernel_dict = {}

        for flavour in parametrization:
          kernel_dict[flavour] = {}
          for int_type in ['cc', 'nc']:
            logging.debug('Calculating parametrized reconstruction kernel for %s %s'
                          %(flavour, int_type))

            # create empty kernel
            kernel = np.zeros((n_e, n_cz, n_e, n_cz))

            # quick handle to parametrization
            e_pars = parametrization[flavour][int_type]['energy']
            cz_pars = parametrization[flavour][int_type]['coszen']

            # loop over every bin in true (energy, coszen)
            for (i, j) in itertools.product(range(n_e), range(n_cz)):

                e_kern_cdf = double_gauss(self.ebins,
                                          loc1=e_pars['loc1'][i,j]+evals[i],
                                          width1=e_pars['width1'][i,j],
                                          loc2=e_pars['loc2'][i,j]+evals[i],
                                          width2=e_pars['width2'][i,j],
                                          fraction=e_pars['fraction'][i,j])
		e_kern_int = np.sum(e_kern_cdf)

                offset = n_cz if flipback else 0

                cz_kern_cdf = double_gauss(czbins,
                                           loc1=cz_pars['loc1'][i,j]+czvals[j+offset],
                                           width1=cz_pars['width1'][i,j],
                                           loc2=cz_pars['loc2'][i,j]+czvals[j+offset],
                                           width2=cz_pars['width2'][i,j],
                                           fraction=cz_pars['fraction'][i,j])
                cz_kern_int = np.sum(cz_kern_cdf)

                if flipback:
                    # fold back
                    cz_kern_cdf = cz_kern_cdf[:len(czbins)/2][::-1] + cz_kern_cdf[len(czbins)/2:]

                kernel[i,j] = np.outer(e_kern_cdf, cz_kern_cdf)

            kernel_dict[flavour][int_type] = copy(kernel)

        kernel_dict['ebins'] = self.ebins
        kernel_dict['czbins'] = self.czbins

        return kernel_dict
Example #6
0
    def _get_reco_kernels(self,
                          flipback=True,
                          e_reco_scale=None,
                          cz_reco_scale=None,
                          **kwargs):
        """
        Use the parametrization functions to calculate the actual reco
        kernels (i.e. 4D histograms). If flipback==True, the zenith angle
        part that goes below the zenith will be mirrored back in.
        """
        if all([
                hasattr(self, 'kernels'), e_reco_scale == 1.,
                cz_reco_scale == 1.
        ]):
            logging.info('Using existing kernels for reconstruction')
            return self.kernels

        logging.info('Creating parametrized reconstruction kernels')

        # get binning information
        evals, esizes = get_bin_centers(self.ebins), get_bin_sizes(self.ebins)
        czvals, czsizes = get_bin_centers(self.czbins), get_bin_sizes(
            self.czbins)
        czbins = self.czbins
        n_e, n_cz = len(evals), len(czvals)

        # prepare for folding back at lower edge
        if not is_linear(self.czbins):
            logging.warn("cos(zenith) bins have different "
                         "sizes! Unable to fold around edge "
                         "of histogram, will not do that.")
            flipback = False

        if flipback:
            czvals = np.append(czvals - (self.czbins[-1] - self.czbins[0]),
                               czvals)
            czbins = np.append(
                czbins[:-1] - (self.czbins[-1] - self.czbins[0]), czbins)
            czsizes = np.append(czsizes, czsizes)

        # get properly scaled parametrization, initialize kernels
        parametrization = self.apply_reco_scales(e_reco_scale, cz_reco_scale)
        kernel_dict = {}

        for flavour in parametrization:
            kernel_dict[flavour] = {}
            for int_type in ['cc', 'nc']:
                logging.debug(
                    'Calculating parametrized reconstruction kernel for %s %s'
                    % (flavour, int_type))

                # create empty kernel
                kernel = np.zeros((n_e, n_cz, n_e, n_cz))

                # quick handle to parametrization
                e_pars = parametrization[flavour][int_type]['energy']
                cz_pars = parametrization[flavour][int_type]['coszen']

                # loop over every bin in true (energy, coszen)
                for (i, j) in itertools.product(range(n_e), range(n_cz)):

                    e_kern_cdf = double_gauss(
                        self.ebins,
                        loc1=e_pars['loc1'][i, j] + evals[i],
                        width1=e_pars['width1'][i, j],
                        loc2=e_pars['loc2'][i, j] + evals[i],
                        width2=e_pars['width2'][i, j],
                        fraction=e_pars['fraction'][i, j])
                    e_kern_int = np.sum(e_kern_cdf)

                    offset = n_cz if flipback else 0

                    cz_kern_cdf = double_gauss(
                        czbins,
                        loc1=cz_pars['loc1'][i, j] + czvals[j + offset],
                        width1=cz_pars['width1'][i, j],
                        loc2=cz_pars['loc2'][i, j] + czvals[j + offset],
                        width2=cz_pars['width2'][i, j],
                        fraction=cz_pars['fraction'][i, j])
                    cz_kern_int = np.sum(cz_kern_cdf)

                    if flipback:
                        # fold back
                        cz_kern_cdf = cz_kern_cdf[:len(czbins) /
                                                  2][::-1] + cz_kern_cdf[
                                                      len(czbins) / 2:]

                    kernel[i, j] = np.outer(e_kern_cdf, cz_kern_cdf)

                kernel_dict[flavour][int_type] = copy(kernel)

        kernel_dict['ebins'] = self.ebins
        kernel_dict['czbins'] = self.czbins

        return kernel_dict