Beispiel #1
0
    def __init__(self, filename, col_altitude=0, col_thickness=2):
        """ 
        small class that calculates the height of the shower maximum
        given a parametrisation of the atmosphere 
        and certain parameters of the shower itself

        Parameters:
        -----------
        filename : string
            path to text file that contains a table of the 
            atmosphere parameters
        col_altitude : int
            column in the text file that contains the altitude/height
        col_thickness : int
            column in the text file that contains the thickness
        """

        altitude = []
        thickness = []
        atm_file = open(filename, "r")
        for line in atm_file:
            if line.startswith("#"):
                continue
            altitude.append(float(line.split()[col_altitude]))
            thickness.append(float(line.split()[col_thickness]))

        self.atmosphere = Histogram(axisNames=["altitude"])
        self.atmosphere.hist = thickness * u.g * u.cm ** -2
        self.atmosphere.bin_lower_edges = [np.array(altitude) * u.km]
def test_outliers():
    """
    Check that out-of-range values work as expected
    """
    H = Histogram(nbins=[5, 10], ranges=[[-2.5, 2.5], [-1, 1]])
    H.fill(np.array([[1, 1], ]))
    val1 = H.get_value((100, 100), outlier_value=-10000)
    val2 = H.get_value((-100, 0), outlier_value=None)
    assert val1 == -10000
    assert val2 == 0
Beispiel #3
0
def test_histogram_resample_inplace():
    hist = Histogram(nbins=[5, 11], ranges=[[-2.5, 2.5], [-1, 1]])
    hist.fill(np.array([[0, 0], [0, 0.5]]))

    for testpoint in [(0, 0), (0, 1), (1, 0), (3, 3)]:
        val0 = hist.get_value(testpoint)
        hist.resample_inplace((10, 22))
        hist.resample_inplace((5, 11))
        val2 = hist.get_value(testpoint)

        # at least check the resampling is undoable
        assert np.isclose(val0[0], val2[0])
Beispiel #4
0
def test_histogram_resample_inplace():
    hist = Histogram(nbins=[5, 11], ranges=[[-2.5, 2.5], [-1, 1]])
    hist.fill(np.array([[0, 0],
                     [0,0.5]]))

    for testpoint in [(0,0), (0,1), (1,0), (3,3)]:
        val0 = hist.get_value(testpoint)
        hist.resample_inplace((10, 22))
        val1 = hist.get_value(testpoint)
        hist.resample_inplace((5, 11))
        val2 = hist.get_value(testpoint)

        # at least check the resampling is undoable
        assert np.isclose(val0[0], val2[0])
Beispiel #5
0
def test_histogram_str():
    hist = Histogram(nbins=[5, 10],
                     ranges=[[-2.5, 2.5], [-1, 1]],
                     name="testhisto")
    expected = ("Histogram(name='testhisto', axes=['axis0', 'axis1'], "
                "nbins=[ 5 10], ranges=[[-2.5  2.5]\n [-1.   1. ]])")
    assert str(hist) == expected
Beispiel #6
0
def test_histogram_range_fill_and_read():
    """
    Check that the correct bin is read and written for multiple
    binnings and fill positions
    """

    num = 100

    for nxbins in np.arange(1, 50, 1):
        for xx in np.arange(-2.0, 2.0, 0.1):
            pp = (xx + 0.01829384, 0.1)
            coords = np.ones((num, 2)) * np.array(pp)
            hist = Histogram(nbins=[nxbins, 10], ranges=[[-2.5, 2.5], [-1, 1]])
            hist.fill(coords)
            val = hist.get_value(pp)[0]
            assert val == num
            del hist
Beispiel #7
0
def test_histogram_fill_and_read():

    hist = Histogram(nbins=[5, 10], ranges=[[-2.5, 2.5], [-1, 1]])

    pa = (0.1, 0.1)
    pb = (-0.55, 0.55)

    a = np.ones((100, 2)) * pa  # point at 0.1,0.1
    b = np.ones((10, 2)) * pb  # 10 points at -0.5,0.5

    hist.fill(a)
    hist.fill(b)

    va = hist.get_value(pa)[0]
    vb = hist.get_value(pb)[0]

    assert va == 100
    assert vb == 10
def test_histogram_range_fill_and_read():
    """
    Check that the correct bin is read and written for multiple
    binnings and fill positions
    """

    num = 100

    for nxbins in np.arange(1, 50, 1):
        for xx in np.arange(-2.0, 2.0, 0.1):
            pp = (xx + 0.01829384, 0.1)
            coords = np.ones((num, 2)) * np.array(pp)
            hist = Histogram(nbins=[nxbins, 10],
                             ranges=[[-2.5, 2.5], [-1, 1]])
            hist.fill(coords)
            val = hist.get_value(pp)[0]
            assert val == num
            del hist
def test_histogram_fill_and_read():

    hist = Histogram(nbins=[5, 10], ranges=[[-2.5, 2.5], [-1, 1]])

    pa = (0.1, 0.1)
    pb = (-0.55, 0.55)

    a = np.ones((100, 2)) * pa  # point at 0.1,0.1
    b = np.ones((10, 2)) * pb  # 10 points at -0.5,0.5

    hist.fill(a)
    hist.fill(b)

    va = hist.get_value(pa)[0]
    vb = hist.get_value(pb)[0]

    assert va == 100
    assert vb == 10
Beispiel #10
0
def test_histogram_fits(histogram_file):
    """
    Write to fits,read back, and check
    """

    hist = Histogram(nbins=[5, 11], ranges=[[-2.5, 2.5], [-1, 1]])
    hist.fill(np.array([[0, 0], [0, 0.5]]))

    hist.to_fits().writeto(histogram_file, overwrite=True)
    newhist = Histogram.from_fits(histogram_file)

    # check that the values are the same
    compare_histograms(hist, newhist)
Beispiel #11
0
def test_outliers():
    """
    Check that out-of-range values work as expected
    """
    H = Histogram(nbins=[5, 10], ranges=[[-2.5, 2.5], [-1, 1]])
    H.fill(np.array([
        [1, 1],
    ]))
    val1 = H.get_value((100, 100), outlier_value=-10000)
    val2 = H.get_value((-100, 0), outlier_value=None)
    assert val1 == -10000
    assert val2 == 0
Beispiel #12
0
def test_histogram_fits(histogram_file):
    """
    Write to fits,read back, and check
    """

    hist = Histogram(nbins=[5, 11], ranges=[[-2.5, 2.5], [-1, 1]])
    hist.fill(np.array([[0, 0],
                        [0, 0.5]]))

    hist.to_fits().writeto(histogram_file, overwrite=True)
    newhist = Histogram.from_fits(histogram_file)

    # check that the values are the same
    compare_histograms(hist, newhist)
Beispiel #13
0
def plot_muon_efficiency(outputpath):
    """
    Plot the muon efficiencies
    """
    fig, ax = plt.subplots(1, 1, figsize=(10, 10))
    figip, axip = plt.subplots(1, 1, figsize=(10, 10))
    figrw, axrw = plt.subplots(1, 1, figsize=(10, 10))

    nbins = 16
    t = Table.read(str(outputpath) + '_muontable.fits')
    print('Reading muon efficiency from table', outputpath, t['MuonEff'])

    if len(t['MuonEff']) < 1:
        print("No muon events to plot")
        return
    else:
        print("Found", len(t['MuonEff']), "muon events")

    (mu, sigma) = norm.fit(t['MuonEff'])

    print('Gaussian fit with mu=', mu, 'sigma=', sigma)

    conteff = ax.hist(t['MuonEff'], nbins)
    ax.set_xlim(0.2 * min(t['MuonEff']), 1.2 * max(t['MuonEff']))

    xtest = np.linspace(min(t['MuonEff']), max(t['MuonEff']), nbins)
    yg = mlab.normpdf(xtest, mu, sigma)
    print('mu', mu, 'sigma', sigma, 'yg', yg)
    ax.plot(xtest, yg, 'r', linewidth=2)

    ax.set_ylim(0., 1.2 * max(conteff[0]))
    ax.set_xlabel('Muon Efficiency')
    plt.draw()

    yimp = np.linspace(min(t['ImpactP']), max(t['ImpactP']), nbins)
    contimp = axip.hist(t['ImpactP'], nbins)
    axip.set_xlim(0.2 * min(t['ImpactP']), 1.2 * max(t['ImpactP']))
    axip.set_ylim(0., 1.2 * max(contimp[0]))
    axip.set_xlabel('Impact Parameter (m)')

    plt.draw()

    heffimp = Histogram(nbins=[16, 16],
                        ranges=[
                            (min(t['MuonEff']), max(t['MuonEff'])),
                            (min(t['ImpactP']), max(t['ImpactP']))
                        ])  # ,axisNames=["MuonEfficiency","ImpactParameter"])

    heffimp.fill([t['MuonEff'], t['ImpactP']])
    heffimp.draw_2d()

    yrw = np.linspace(min(t['RingWidth']), max(t['RingWidth']), nbins)
    contrw = axrw.hist(t['RingWidth'], nbins)
    axrw.set_xlim(0.2 * min(t['RingWidth']), 1.2 * max(t['RingWidth']))
    axrw.set_ylim(0., 1.2 * max(contrw[0]))
    axrw.set_xlabel('Ring Width ($^\circ$)')

    plt.draw()

    if outputpath is not None:
        print("saving figure at", outputpath)
        fig.savefig(str(outputpath) + '_MuonEff.png')
        figip.savefig(str(outputpath) + '_ImpactParameter.png')
        figrw.savefig(str(outputpath) + '_RingWidth.png')
    else:
        print("Not saving figure, no outputpath")
        plt.show()
def plot_muon_efficiency(outputpath):
    """
    Plot the muon efficiencies
    """
    fig, ax = plt.subplots(1, 1, figsize=(10, 10))
    figip, axip = plt.subplots(1, 1, figsize=(10, 10))
    figrw, axrw = plt.subplots(1, 1, figsize=(10, 10))

    nbins = 16
    t = Table.read(str(outputpath) + '_muontable.fits')
    print('Reading muon efficiency from table', outputpath, t['MuonEff'])

    if len(t['MuonEff']) < 1:
        print("No muon events to plot")
        return
    else:
        print("Found", len(t['MuonEff']), "muon events")

    (mu, sigma) = norm.fit(t['MuonEff'])

    print('Gaussian fit with mu=', mu, 'sigma=', sigma)

    #ax = figeff.add_subplot(1,3,1)
    conteff = ax.hist(t['MuonEff'], nbins)
    ax.set_xlim(0.2 * min(t['MuonEff']), 1.2 * max(t['MuonEff']))

    xtest = np.linspace(min(t['MuonEff']), max(t['MuonEff']), nbins)
    yg = mlab.normpdf(xtest, mu, sigma)
    print('mu', mu, 'sigma', sigma, 'yg', yg)
    ax.plot(xtest, yg, 'r', linewidth=2)

    ax.set_ylim(0., 1.2 * max(conteff[0]))
    ax.set_xlabel('Muon Efficiency')
    # plt.figure(fig.number)
    plt.draw()

    #axip = figeff.add_subplot(1,3,1)
    yimp = np.linspace(min(t['ImpactP']), max(t['ImpactP']), nbins)
    contimp = axip.hist(t['ImpactP'], nbins)
    axip.set_xlim(0.2 * min(t['ImpactP']), 1.2 * max(t['ImpactP']))
    axip.set_ylim(0., 1.2 * max(contimp[0]))
    axip.set_xlabel('Impact Parameter (m)')
    # plt.figure(figip.number)
    plt.draw()

    heffimp = Histogram(nbins=[16, 16],
                        ranges=[(min(t['MuonEff']), max(t['MuonEff'])),
                                (min(t['ImpactP']), max(t['ImpactP']))])  # ,axisNames=["MuonEfficiency","ImpactParameter"])
    # embed()
    # heffimp.bin_lower_edges([xtest,yimp])
    heffimp.fill([t['MuonEff'], t['ImpactP']])
    heffimp.draw_2d()

    #axrw = figeff.add_subplot(1,3,1)
    yrw = np.linspace(min(t['RingWidth']), max(t['RingWidth']), nbins)
    contrw = axrw.hist(t['RingWidth'], nbins)
    axrw.set_xlim(0.2 * min(t['RingWidth']), 1.2 * max(t['RingWidth']))
    axrw.set_ylim(0., 1.2 * max(contrw[0]))
    axrw.set_xlabel('Ring Width ($^\circ$)')
    # plt.figure(figrw.number)
    plt.draw()
    # plt.show()
    if outputpath is not None:
        print("saving figure at", outputpath)
        fig.savefig(str(outputpath) + '_MuonEff.png')
        figip.savefig(str(outputpath) + '_ImpactParameter.png')
        figrw.savefig(str(outputpath) + '_RingWidth.png')
    else:
        print("Not saving figure, no outputpath")
        plt.show()
def plot_muon_efficiency(outputpath):
    """
    Plot the muon efficiencies
    """
    fig, ax = plt.subplots(1, 1, figsize=(10, 10))
    figip, axip = plt.subplots(1, 1, figsize=(10, 10))
    figrw, axrw = plt.subplots(1, 1, figsize=(10, 10))

    nbins = 16
    t = Table.read(str(outputpath) + '_muontable.fits')
    logger.info('Reading muon efficiency from table "%s"', outputpath)

    if len(t['MuonEff']) < 1:
        logger.warning("No muon events to plot")
        return
    else:
        logger.info("Found %d muon events", len(t['MuonEff']))

    (mu, sigma) = norm.fit(t['MuonEff'])

    logger.debug('Gaussian fit with mu=%f, sigma=%f', mu, sigma)

    conteff = ax.hist(t['MuonEff'], nbins)
    ax.set_xlim(0.2 * min(t['MuonEff']), 1.2 * max(t['MuonEff']))

    xtest = np.linspace(min(t['MuonEff']), max(t['MuonEff']), nbins)
    yg = mlab.normpdf(xtest, mu, sigma)
    logger.debug('mu=%f sigma=%f yg=%f', mu, sigma, yg)
    ax.plot(xtest, yg, 'r', linewidth=2)

    ax.set_ylim(0., 1.2 * max(conteff[0]))
    ax.set_xlabel('Muon Efficiency')
    plt.draw()

    contimp = axip.hist(t['ImpactP'], nbins)
    axip.set_xlim(0.2 * min(t['ImpactP']), 1.2 * max(t['ImpactP']))
    axip.set_ylim(0., 1.2 * max(contimp[0]))
    axip.set_xlabel('Impact Parameter (m)')

    plt.draw()

    heffimp = Histogram(nbins=[16, 16],
                        ranges=[(min(t['MuonEff']), max(t['MuonEff'])),
                                (min(t['ImpactP']), max(t[
                                    'ImpactP']))])  #
    #  ,axisNames=["MuonEfficiency","ImpactParameter"])

    heffimp.fill([t['MuonEff'], t['ImpactP']])
    heffimp.draw_2d()

    contrw = axrw.hist(t['RingWidth'], nbins)
    axrw.set_xlim(0.2 * min(t['RingWidth']), 1.2 * max(t['RingWidth']))
    axrw.set_ylim(0., 1.2 * max(contrw[0]))
    axrw.set_xlabel('Ring Width ($^\circ$)')

    plt.draw()

    if outputpath is not None:
        logger.info("saving figure to '%s'", outputpath)
        fig.savefig(str(outputpath) + '_MuonEff.png')
        figip.savefig(str(outputpath) + '_ImpactParameter.png')
        figrw.savefig(str(outputpath) + '_RingWidth.png')
    else:
        logger.info("Not saving figure, no outputpath")
        plt.show()
Beispiel #16
0
class ShowerMaxEstimator:

    def __init__(self, filename, col_altitude=0, col_thickness=2):
        """ 
        small class that calculates the height of the shower maximum
        given a parametrisation of the atmosphere 
        and certain parameters of the shower itself

        Parameters:
        -----------
        filename : string
            path to text file that contains a table of the 
            atmosphere parameters
        col_altitude : int
            column in the text file that contains the altitude/height
        col_thickness : int
            column in the text file that contains the thickness
        """

        altitude = []
        thickness = []
        atm_file = open(filename, "r")
        for line in atm_file:
            if line.startswith("#"):
                continue
            altitude.append(float(line.split()[col_altitude]))
            thickness.append(float(line.split()[col_thickness]))

        self.atmosphere = Histogram(axisNames=["altitude"])
        self.atmosphere.hist = thickness * u.g * u.cm ** -2
        self.atmosphere.bin_lower_edges = [np.array(altitude) * u.km]

    def interpolate(self, arg, outlierValue=0., order=3):

        axis = self.atmosphere._binLowerEdges[0]
        bin_u = np.digitize(arg.to(axis.unit), axis)
        bin_l = bin_u - 1

        unit = arg.unit
        argv = arg.value

        bin_u_edge = axis[bin_u].to(unit).value
        bin_l_edge = axis[bin_l].to(unit).value
        coordinate = (argv - bin_u_edge) / (bin_u_edge - bin_l_edge) \
            * (bin_u - bin_l) + bin_u

        return ndimage.map_coordinates(self.atmosphere.hist,
                                       [[coordinate]],
                                       order=order,
                                       cval=outlierValue)[0]\
            * self.atmosphere.hist.unit

    def find_shower_max_height(self, energy, h_first_int, gamma_alt):
        """ 
        estimates the height of the shower maximum in the atmosphere
        according to equation (3) in [arXiv:0907.2610v3]

        Parameters:
        -----------
        energy : astropy.Quantity
            energy of the parent gamma photon
        h_first_int : astropy.Quantity
            hight of the first interaction
        gamma_alt : astropy.Quantity or float
            altitude / pi-minus-zenith (in radians in case of float) 
            of the parent gamma photon

        Returns:
        --------
        shower_max_height : astropy.Quantity
            height of the shower maximum
        """

        # offset of the shower-maximum in radiation lengths
        c = 0.97 * log(energy / (83 * u.MeV)) - 1.32
        # radiation length in dry air at 1 atm = 36,62 g / cm**2 [PDG]
        c *= 36.62 * u.g * u.cm ** -2
        # showers with a more horizontal direction spend more path
        # length in each atm. layer the "effective transverse
        # thickness" they have to pass is reduced
        c *= np.sin(gamma_alt)

        # find the thickness at the height of the first interaction
        t_first_int = self.interpolate(h_first_int)

        # total thickness at shower maximum = thickness at first
        # interaction + thickness traversed to shower maximum
        t_shower_max = t_first_int + c

        # now find the height with the wanted thickness
        for ii, thick1 in enumerate(self.atmosphere.hist):
            if t_shower_max > thick1:
                height1 = self.atmosphere.bin_lower_edges[0][ii]
                height2 = self.atmosphere.bin_lower_edges[0][ii - 1]
                val = [height2.to(
                    self.atmosphere._binLowerEdges[0].unit).value]
                thick2 = self.atmosphere.get_value(val)[0]

                return (height2 - height1) / (thick2 - thick1) \
                    * (t_shower_max - thick1) + height1