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
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
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])
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
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