def plot_delta_histogram(ids, **kwargs): """ Plot a histogram of the deltas """ if type(ids) is int: ids = [ids] # Bin width bin_size = 1 # 2.5*n # Begin Figure plot = Plot() for id in ids: ext_timestamps, deltas = get(id) low = floor(min(deltas)) high = ceil(max(deltas)) bins = np.arange(low - .5 * bin_size, high + bin_size, bin_size) n, bins = np.histogram(deltas, bins) bin_centers = (bins[:-1] + bins[1:]) / 2 popt, pcov = curve_fit(gauss, bin_centers, n, p0=[.15, np.mean(deltas), np.std(deltas)]) plot.histogram(n, bins) plot.plot(bin_centers, gauss(bin_centers, *popt), mark=None, linestyle='gray') if kwargs.keys(): plot.set_title('Tijdtest ' + kwargs[kwargs.keys()[0]]) plot.set_label(r'$\mu={1:.1f}$, $\sigma={2:.1f}$'.format(*popt)) plot.set_xlabel(r'Time difference [ns]') plot.set_ylabel(r'Counts') plot.set_xlimits(low, high) plot.set_ylimits(min=0.) # Save Figure if len(ids) == 1: name = 'delta_histogram/tt_delta_hist_%03d' % ids[0] elif kwargs.keys(): name = 'delta_histogram/tt_delta_hist_' + kwargs[kwargs.keys()[0]] plot.save_as_pdf(PLOT_PATH + name) print 'tt_analyse: Plotted histogram'
def plot_slice(self, n): densities = [1, 3, 8, 15, 30] bins = linspace(0, 15, 150) plot = Plot() for density in densities: padding = round(sqrt(density) / 2.) counts, bins = histogram( n.compress(abs(self.src_k - density) < padding), bins=bins, density=True) plot.histogram(counts, bins) plot.add_pin( r'\SI[multi-part-units=single, separate-uncertainty]{%d\pm%d}{\per\meter\squared}' % (density, padding), 'above', bins[counts.argmax()]) plot.set_ylimits(min=0) plot.set_xlimits(min=bins[0], max=bins[-1]) plot.set_xlabel(r'HiSPARC detected density [\si{\per\meter\squared}]') plot.set_ylabel(r'Counts') return plot
def plot_detector_dt(path='/'): with tables.open_file(RESULT_DATA, 'r') as data: sims = data.get_node(path + 'cluster_simulations') ud_dt = sims.station_0.events.col('t1') - sims.station_0.events.col( 't2') lr_dt = sims.station_1.events.col('t1') - sims.station_1.events.col( 't2') bins = np.linspace(-61.25, 61.25, 50) ud_counts, _ = np.histogram(ud_dt, bins) lr_counts, _ = np.histogram(lr_dt, bins) plot = Plot() plot.histogram(ud_counts, bins, linestyle='black') plot.histogram(lr_counts, bins, linestyle='red') plot.set_xlabel(r'Time difference [\si{\ns}]') plot.set_ylabel(r'Number events with time difference') plot.set_xlimits(bins[0], bins[-1]) plot.set_ylimits(0) plot.save_as_pdf('dt' + path.replace('/', '_'))
def analyse(data): # Time differences all 3 combinations # Only one of the roof detectors with signal # Compare showers (i.e. at least 2 on roof) with 501/510 coincidences # ... event_node = data.get_node('/station_99/events') print 'Total number of events: %d' % event_node.nrows plot = Plot() bins = np.arange(-100, 100, 2.5) for i, j in itertools.combinations(range(4), 2): selection = event_node.read_where('(t%d > 0) & (t%d > 0)' % i, j) dt = selection['t%d' % i] - selection['t%d' % j] counts, bins = np.histogram(dt, bins=bins) plot.histogram(counts, bins) plot.set_ylimits(min=0) plot.set_ylabel('Counts') plot.set_xlabel('Time difference [ns]') plot.save_as_pdf('muonlab_t3_dt')
def analyse(data, id): event_node = data.get_node('/station_99/events') print 'Total number of events: %d' % event_node.nrows cq = CoincidenceQuery(data) coincidences = cq.all(stations=[99]) coincident_events = cq.events_from_stations(coincidences, [99], n=1) coincident_event_ids = [e[0][1]['event_id'] for e in coincident_events] event_ids = [i for i in range(event_node.nrows) if i not in coincident_event_ids] events = event_node.read_coordinates(event_ids) coincident_events = event_node.read_coordinates(coincident_event_ids) print 'Total number of events not in coincidence: %d' % len(events) print 'Total number of events in coincidence: %d' % len(coincident_events) cph1 = coincident_events['pulseheights'][:, 0] cph2 = coincident_events['pulseheights'][:, 1] ph1 = events['pulseheights'][:, 0] ph2 = events['pulseheights'][:, 1] plot = Plot() bins = np.arange(0, 4000, 50) for ph, ls in [(cph1, 'black,dotted'), (cph2, 'red,dotted'), (ph1, 'black'), (ph2, 'red')]: counts, bins = np.histogram(ph, bins=bins) plot.histogram(counts, bins, linestyle=ls) plot.set_xlimits(min=0, max=4000) plot.set_ylimits(min=.5) plot.set_ylabel('Counts') plot.set_xlabel('Pulseheight [ADC]') plot.save_as_pdf('muonlab_pulseheights_%d' % id) cdt = coincident_events['t2'] - coincident_events['t1'] dt = events['t2'] - events['t1'] plot = Plot() bins = np.arange(-100, 100, 2.5) for t, ls in [(dt, ''), (cdt, 'dotted')]: counts, bins = np.histogram(t, bins=bins) plot.histogram(counts, bins, linestyle=ls) plot.set_ylimits(min=0) plot.set_ylabel('Counts') plot.set_xlabel('Time difference [ns]') plot.save_as_pdf('muonlab_dt_%d' % id)
def plot_contribution_station(self, n, ref_n): plot = Plot('semilogy') colors = [ 'red', 'blue', 'green', 'purple', 'gray', 'brown', 'cyan', 'magenta', 'orange', 'teal' ] padding = 0.25 bins = linspace(0, 20, 150) plot.histogram(*histogram(n, bins=bins)) plot.draw_vertical_line(1) for j, density in enumerate(range(1, 8) + [15] + [20]): n_slice = n.compress(abs(ref_n - density) < padding) counts, bins = histogram(n_slice, bins=bins) plot.histogram(counts, bins + (j / 100.), linestyle=colors[j % len(colors)]) plot.set_ylimits(min=0.9, max=1e5) plot.set_xlimits(min=bins[0], max=bins[-1]) plot.set_xlabel(r'HiSPARC detected density [\si{\per\meter\squared}]') plot.set_ylabel(r'Counts') return plot
def plot_ns_histogram(ids, **kwargs): """ Plot a histogram of the nanosecond part of the ext_timestamps """ if type(ids) is int: ids = [ids] # Define Bins low = 0 high = int(1e9) bin_size = 5e6 # 1e7 = 10ms, 1e6 = 1 ms, 1e3 = 1 us bins = np.arange(low, high + bin_size, bin_size) # Begin Figure plot = Plot() for id in ids: ext_timestamps, deltas = get(id) nanoseconds = nanoseconds_from_ext_timestamp(ext_timestamps) n, bins = np.histogram(nanoseconds, bins, normed=1) plot.histogram(n, bins) if kwargs.keys(): plot.set_title('Tijdtest ' + kwargs[kwargs.keys()[0]]) plot.set_xlabel(r'nanosecond part of timestamp [ns]') plot.set_ylabel(r'p') plot.set_xlimits(0, 1e9) plot.set_ylimits(.95e-9, 1.05e-9) # Save Figure if len(ids) == 1: name = 'nanoseconds_histogram/tt_nanos_hist_%03d' % ids[0] elif kwargs.keys(): name = 'nanoseconds_histogram/tt_nanos_hist_' + kwargs[kwargs.keys() [0]] try: plot.save_as_pdf(PLOT_PATH + name) except: print 'tt_analyse: Failed ns hist for %s' % str(ids) print 'tt_analyse: Plotted histogram'
def main(station_number=501, date=datetime.date(2016, 2, 1)): filepath = os.path.join(ESD_PATH, date.strftime('%Y/%-m/%Y_%-m_%-d.h5')) with tables.open_file(filepath, 'r') as data: station = Station(station_number) events = data.get_node( '/hisparc/cluster_%s/station_%d' % (station.cluster().lower(), station_number), 'events') ext_timestamps = events.col('ext_timestamp') ext_timestamps.sort() difs = ext_timestamps[1:] - ext_timestamps[:-1] print('Minimum: %d. Maximum: %d. n(diff < 100 us): %d' % (min(difs), max(difs), len(numpy.where(difs < 1e5)[0]))) bins = numpy.logspace(2, 11) plot = Plot('semilogx') plot.histogram(*numpy.histogram(difs, bins=bins)) plot.set_xlabel(r'Time between subsequent triggers [\si{\ns}]') plot.set_ylabel('Occurance') plot.set_ylimits(min=0) plot.set_xlimits(min(bins), max(bins)) plot.save_as_pdf('time_between_triggers_%d' % station_number)
def main(): # Draw random numbers from the normal distribution np.random.seed(1) N = np.random.normal(size=2000) # define bin edges edge = 5 bin_width = .1 bins = np.arange(-edge, edge + .5 * bin_width, bin_width) # build histogram and x, y values at the center of the bins n, bins = np.histogram(N, bins=bins) x = (bins[:-1] + bins[1:]) / 2 y = n # fit normal distribution pdf to data f = lambda x, N, mu, sigma: N * scipy.stats.norm.pdf(x, mu, sigma) popt, pcov = scipy.optimize.curve_fit(f, x, y) print("Parameters from fit (N, mu, sigma):", popt) # make graph graph = Plot() # graph histogram graph.histogram(n, bins) # graph model with fit parameters x = np.linspace(-edge, edge, 100) graph.plot(x, f(x, *popt), mark=None) # set labels and limits graph.set_xlabel("value") graph.set_ylabel("count") graph.set_label("Fit to data") graph.set_xlimits(-6, 6) # save graph to file graph.save('histogram-fit')
def plot_offset_distribution(ids, **kwargs): """Offset distribution""" # Begin Figure plot = Plot() offsets = [ np.average([x for x in get(id)[1] if abs(x) < 100]) for id in ids ] bins = np.arange(-70, 70, 2) n, bins = np.histogram(offsets, bins) plot.histogram(n, bins) bin_centers = (bins[:-1] + bins[1:]) / 2 popt, pcov = curve_fit(gauss, bin_centers, n, p0=[1., np.mean(offsets), np.std(offsets)]) plot.plot(bin_centers, gauss(bin_centers, *popt), mark=None, linestyle='gray') if kwargs.keys(): plot.set_title('Tijdtest offset distribution ' + kwargs[kwargs.keys()[0]]) plot.set_label(r'$\mu={1:.1f}$, $\sigma={2:.1f}$'.format(*popt)) plot.set_xlabel(r'Offset [\si{\nano\second}]') plot.set_ylabel(r'Counts') plot.set_ylimits(min=0) # Save Figure name = 'box/tt_offset_distribution' if kwargs.keys(): name += kwargs[kwargs.keys()[0]] plot.save_as_pdf(PLOT_PATH + name) print 'tt_analyse: Plotted offsets'
def plot_times(): plot = Plot('semilogx') data = read_times() walltimes = data['walltime'] / 60. / 60. # To hours print 'Total time: %d years.' % (sum(walltimes) / 24. / 365.) print 'Longest job: %d hours.' % max(walltimes) print 'Shortest job: %d seconds.' % (min(walltimes) * 60. * 60.) counts, bins = histogram(log10(walltimes), bins=300) plot.histogram(counts, 10**bins, linestyle='fill=black') plot.add_pin_at_xy(4, max(counts), 'short', location='above left', use_arrow=False) plot.draw_vertical_line(4, 'gray') plot.add_pin_at_xy(24, max(counts), 'generic', location='above left', use_arrow=False) plot.draw_vertical_line(24, 'gray') plot.add_pin_at_xy(96, max(counts), 'long', location='above left', use_arrow=False) plot.draw_vertical_line(96, 'gray') plot.add_pin_at_xy(2000, max(counts), 'extra-long', location='above left', use_arrow=False) plot.draw_vertical_line(2000, 'gray') plot.set_ylabel(r'Count') plot.set_xlabel(r'Walltime [\si{\hour}]') plot.set_ylimits(min=0) plot.set_xlimits(min=3e-3, max=3e3) plot.save_as_pdf('shower_walltime')
def determine_detector_timing_offsets(s, events): """Determine the offsets between the station detectors. ADL: Currently assumes detector 1 is a good reference. But this is not always the best choice. Perhaps it should be determined using more data (more than one day) to be more accurate. """ bins = arange(-100 + 1.25, 100, 2.5) col = (cl for cl in COLORS) graph = Plot() ids = range(1, 5) reference = 2 for j in [1, 3, 4]: if j == reference: continue tref = events.col('t%d' % reference) tj = events.col('t%d' % j) dt = (tj - tref).compress((tref >= 0) & (tj >= 0)) y, bins = histogram(dt, bins=bins) c = col.next() graph.histogram(y, bins, linestyle='%s' % c) x = (bins[:-1] + bins[1:]) / 2 try: popt, pcov = curve_fit(gauss, x, y, p0=(len(dt), 0., 10.)) graph.draw_vertical_line(popt[1], linestyle='%s' % c) print '%d-%d: %f (%f)' % (j, reference, popt[1], popt[2]) except (IndexError, RuntimeError): print '%d-%d: failed' % (j, reference) graph.set_title('Time difference, station %d' % (s)) graph.set_xlimits(-100, 100) graph.set_ylimits(min=0) graph.set_xlabel('$\Delta t$') graph.set_ylabel('Counts') graph.save_as_pdf('detector_offsets_%s' % s)
def compare_ttrigger(): with tables.open_file(DATA_PATH, 'r') as data: processed = data.get_node(GROUP, 'events_processed') filtered = data.get_node(GROUP, 'events_filtered') assert all( processed.col('ext_timestamp') == filtered.col('ext_timestamp')) trig_proc = processed.col('t_trigger') trig_filt = filtered.col('t_trigger') dt_trigger = trig_filt - trig_proc density = (processed.col('n1') + processed.col('n2') + processed.col('n3') + processed.col('n4')) / 2 print 'Density range:', density.min(), density.max() print 'dt trigger range:', dt_trigger.min(), dt_trigger.max() if len(trig_proc) > 4000: plot = Plot() bins = [linspace(0, 30, 100), arange(-11.25, 75, 2.5)] c, x, y = histogram2d(density, dt_trigger, bins=bins) # plot.histogram2d(c, x, y, bitmap=True, type='color', colormap='viridis') plot.histogram2d(log10(c + 0.01), x, y, type='area') plot.set_xlabel('Particle density') plot.set_ylabel('Difference in trigger time') plot.save_as_pdf('hist2d') else: plot = Plot() plot.scatter( density, dt_trigger, mark='o', markstyle='mark size=0.6pt, very thin, semitransparent') plot.set_xlabel('Particle density') plot.set_ylabel('Difference in trigger time') plot.save_as_pdf('scatter') plot = Plot() c, bins = histogram(dt_trigger, arange(-10, 200, 2.5)) c = where(c < 100, c, 100) plot.histogram(c, bins) plot.set_ylimits(0, 100) plot.set_ylabel('Counts') plot.set_xlabel('Difference in trigger time') plot.save_as_pdf('histogram') plot = Plot() c, bins = histogram(trig_proc, arange(-10, 200, 2.5)) plot.histogram(c, bins) c, bins = histogram(trig_filt, arange(-10, 200, 2.5)) plot.histogram(c, bins, linestyle='red') plot.set_ylimits(0) plot.set_ylabel('Counts') plot.set_xlabel('Trigger time') plot.save_as_pdf('histogram_t')
def plot_n_histogram(path='/'): with tables.open_file(RESULT_DATA, 'r') as data: sims = data.get_node(path + 'cluster_simulations') ud_n1 = sims.station_0.events.col('n1') ud_n2 = sims.station_0.events.col('n2') lr_n1 = sims.station_1.events.col('n1') lr_n2 = sims.station_1.events.col('n2') bins = np.linspace(0, 80, 40) ud_counts1, _ = np.histogram(ud_n1, bins) ud_counts2, _ = np.histogram(ud_n2, bins) lr_counts1, _ = np.histogram(lr_n1, bins) lr_counts2, _ = np.histogram(lr_n2, bins) plot = Plot() plot.histogram(ud_counts1, bins, linestyle='black') plot.histogram(ud_counts2, bins, linestyle='red') plot.histogram(lr_counts1, bins + 0.01, linestyle='black, dashed') plot.histogram(lr_counts2, bins + 0.01, linestyle='red, dashed') plot.set_xlabel(r'Number of detected particles') plot.set_ylabel(r'Number of events with n detected') plot.set_xlimits(bins[0], bins[-1]) plot.set_ylimits(0) plot.save_as_pdf('n_histogram' + path.replace('/', '_'))
def plot_pulseintegrals(): station_number = 501 in_bins = linspace(1, 15000, 200) ph_bins = linspace(10, 1500, 200) az_bins = linspace(-pi, pi, 40) ze_bins = linspace(0, pi / 2., 50) min_n = 1.5 max_zenith = radians(45) with tables.open_file(STATION_PATH, 'r') as data: sn = data.get_node('/s%d' % station_number) n_filter = set( sn.events.get_where_list( '(n1 >= min_n) & (n2 >= min_n) & (n4 >= min_n)')) z_filter = set( sn.reconstructions.get_where_list( '(zenith < max_zenith) & d1 & d2 & d4')) filter = list(n_filter & z_filter) integrals = sn.events.col('integrals')[filter] pulseheights = sn.events.col('pulseheights')[filter] azimuths = sn.reconstructions.col('azimuth')[filter] zeniths = sn.reconstructions.col('zenith')[filter] plot = Plot() counts, az_bins = histogram(azimuths, bins=az_bins) plot.histogram(counts, az_bins) # Smoothed version of azimuth histogram to counter discreteness at low zenith. smoothing = normal(scale=radians(8), size=len(azimuths)) counts, az_bins = histogram(norm_angle(azimuths + smoothing), bins=az_bins) plot.histogram(counts, az_bins, linestyle='gray') plot.draw_horizontal_line(mean(counts), linestyle='red') plot.draw_horizontal_line(mean(counts) + sqrt(mean(counts)), linestyle='dashed, red') plot.draw_horizontal_line(mean(counts) - sqrt(mean(counts)), linestyle='dashed, red') plot.set_ylimits(min=0) plot.set_xlimits(-pi, pi) plot.save_as_pdf('azimuth') plot = Plot() counts, ze_bins = histogram(zeniths, bins=ze_bins) plot.histogram(counts, ze_bins) plot.set_ylimits(min=0) plot.set_xlimits(0, pi / 2) plot.save_as_pdf('zeniths') for i in range(4): plot = Plot('semilogy') counts, in_bins = histogram(integrals[:, i], bins=in_bins) plot.histogram(counts, in_bins) counts, in_bins = histogram(integrals[:, i] * cos(zeniths), bins=in_bins) plot.histogram(counts, in_bins, linestyle='red') plot.set_ylimits(min=1) plot.save_as_pdf('integrals_%d' % i) plot = Plot('semilogy') counts, ph_bins = histogram(pulseheights[:, i], bins=ph_bins) plot.histogram(counts, ph_bins) counts, ph_bins = histogram(pulseheights[:, i] * cos(zeniths), bins=ph_bins) plot.histogram(counts, ph_bins, linestyle='red') plot.set_ylimits(min=1) plot.save_as_pdf('pulseheights_%d' % i)
def analyse_reconstructions(path): seed = os.path.basename(os.path.dirname(path)) cq = CoincidenceQuery(path) c_ids = cq.coincidences.get_where_list('N >= 3') if not len(cq.reconstructions) or not len(c_ids): cq.finish() return c_recs = cq.reconstructions.read_coordinates(c_ids) # Angles zen_out = c_recs['zenith'] azi_out = c_recs['azimuth'] zen_in = c_recs['reference_zenith'] azi_in = c_recs['reference_azimuth'] # Cores x_out = c_recs['x'] y_out = c_recs['y'] x_in = c_recs['reference_x'] y_in = c_recs['reference_y'] # Size size_out = c_recs['size'] energy_out = c_recs['energy'] size_in = c_recs['reference_size'] energy_in = c_recs['reference_energy'] energy = np.log10(energy_in[0]) zenith = np.degrees(zen_in[0]) label = r'$E=10^{%d}$eV, $\theta={%.1f}^{\circ}$' % (energy, zenith) # Azimuth bins = np.linspace(-np.pi, np.pi, 21) acounts_out, bins = np.histogram(azi_out, bins) acounts_in, bins = np.histogram(azi_in, bins) plota = Plot() plota.histogram(acounts_out, bins) plota.histogram(acounts_in, bins, linestyle='red') plota.set_xlabel(r'$\phi$ [\si{\radian}]') plota.set_xlimits(-np.pi, np.pi) plota.set_ylabel(r'Counts') plota.set_ylimits(min=0) plota.save_as_pdf('plots/azimuth_in_out_%s' % seed) # Zenith bins = np.linspace(0, np.pi / 2, 21) zcounts_out, bins = np.histogram(zen_out, bins) zcounts_in, bins = np.histogram(zen_in, bins) plotz = Plot() plotz.histogram(zcounts_out, bins) plotz.histogram(zcounts_in, bins, linestyle='red') plotz.set_xlabel(r'$\theta$ [\si{\radian}]') plotz.set_xlimits(0, np.pi / 2) plotz.set_ylabel(r'Counts') plotz.set_ylimits(min=0) plotz.save_as_pdf('plots/zenith_in_out_%s' % seed) # Angle between angle_distances = angle_between(zen_out, azi_out, zen_in, azi_in) if len(np.isfinite(angle_distances)): bins = np.linspace(0, np.pi / 2, 91) counts, bins = np.histogram(angle_distances, bins=bins) plotd = Plot() plotd.histogram(counts, np.degrees(bins)) sigma = np.percentile(angle_distances[np.isfinite(angle_distances)], 67) plotd.set_label(label + r', 67\%% within \SI{%.1f}{\degree}' % np.degrees(sigma)) plotd.set_xlabel(r'Angle between reconstructions [\si{\degree}]') plotd.set_ylabel('Counts') plotd.set_xlimits(np.degrees(bins[0]), np.degrees(bins[-1])) plotd.set_ylimits(min=0) plotd.save_as_pdf('plots/angle_between_in_out_%s' % seed) # Distance beween filter = size_out != 1e6 core_distances = np.sqrt( (x_out.compress(filter) - x_in.compress(filter))**2 + (y_out.compress(filter) - y_in.compress(filter))**2) if len(np.isfinite(core_distances)): bins = np.linspace(0, 1000, 100) counts, bins = np.histogram(core_distances, bins=bins) plotc = Plot() plotc.histogram(counts, bins) sigma = np.percentile(core_distances[np.isfinite(core_distances)], 67) # energy = np.log10(energy_in[0]) zenith = np.degrees(zen_in[0]) # plotc.set_label(r'$E=10^{%d}$eV, $\theta={%.1f}^{\circ}$, 67\%% ' 'within \SI{%.1f}{\meter}' % (energy, zenith, sigma)) plotc.set_xlabel(r'Distance between cores [\si{\meter}]') plotc.set_ylabel('Counts') plotc.set_xlimits(bins[0], bins[-1]) plotc.set_ylimits(min=0) plotc.save_as_pdf('plots/core_distance_between_in_out_%s' % seed) # Core positions filter = size_out != 1e6 plotc = Plot() for x0, x1, y0, y1 in zip(x_out, x_in, y_out, y_in): plotc.plot([x0, x1], [y0, y1]) plotc.set_xlabel(r'x [\si{\meter}]') plotc.set_ylabel(r'y [\si{\meter}]') plotc.set_xlimits(bins[0], bins[-1]) plotc.set_ylimits(min=0) plotc.save_as_pdf('plots/core_positions_in_out_%s' % seed) # Shower size relative_size = size_out.compress(filter) / size_in.compress(filter) counts, bins = np.histogram(relative_size, bins=np.logspace(-2, 2, 21)) plots = Plot('semilogx') plots.histogram(counts, bins) plots.set_xlabel('Relative size') plots.set_ylabel('Counts') plots.set_xlimits(bins[0], bins[-1]) plots.set_ylimits(min=0) plots.save_as_pdf('plots/size_in_out_%s' % seed) # Cleanup cq.finish()
import tables from numpy import degrees, histogram, isnan from artist import Plot from sapphire import ReconstructESDEvents with tables.open_file('/Users/arne/Datastore/esd/2013/10/2013_10_28.h5', 'r') as data: for s in [501, 502, 503, 504, 505, 506, 508, 509]: rec = ReconstructESDEvents(data, '/hisparc/cluster_amsterdam/station_%d' % s, s) rec.reconstruct_directions(detector_ids=[0, 2, 3]) azimuths = [ degrees(a) for a, z in zip(rec.phi, rec.theta) if degrees(z) > 10 and not isnan(a) ] n, bins = histogram(azimuths, bins=range(-180, 190, 10)) graph = Plot() graph.histogram(n, bins) graph.set_title('Station %d' % s) graph.set_xlabel('Azimuth') graph.set_xlimits(-180, 180) graph.set_ylimits(min=0) graph.save_as_pdf('azimuths_123_s%d' % s)
def determine_station_timing_offsets(data): """Determine the offsets between the stations.""" c = .3 ref_station_number = 501 ref_d_off = DETECTOR_OFFSETS[ref_station_number] ref_events = data.root.hisparc.cluster_amsterdam.station_501.events ref_t = array([ where( ref_events.col('t1') == -999, 9000, ref_events.col('t1') - ref_d_off[0]), where( ref_events.col('t2') == -999, 9000, ref_events.col('t2') - ref_d_off[1]), where( ref_events.col('t3') == -999, 9000, ref_events.col('t3') - ref_d_off[2]), where( ref_events.col('t4') == -999, 9000, ref_events.col('t4') - ref_d_off[3]) ]) ref_min_t = ref_t.min(axis=0) station_number = 510 d_off = DETECTOR_OFFSETS[station_number] events = data.root.hisparc.cluster_amsterdam.station_510.events t = array([ where(events.col('t1') == -999, 90000, events.col('t1') - d_off[0]), where(events.col('t2') == -999, 90000, events.col('t2') - d_off[1]), where(events.col('t3') == -999, 90000, events.col('t3') - d_off[2]), where(events.col('t4') == -999, 90000, events.col('t4') - d_off[3]) ]) min_t = t.min(axis=0) dt = [] for event, ref_event in itertools.izip(events, ref_events): if (ref_event['t_trigger'] in ERR or event['t_trigger'] in ERR): dt.append(nan) continue dt.append((int(event['ext_timestamp']) - int(ref_event['ext_timestamp'])) - (event['t_trigger'] - ref_event['t_trigger'])) dt = array(dt) dt = dt + (min_t - ref_min_t) plot = Plot() bins = linspace(-50, 50, 100) y, bins = histogram(dt, bins=bins) plot.histogram(y, bins) x = (bins[:-1] + bins[1:]) / 2 try: popt, pcov = curve_fit(gauss, x, y, p0=(len(dt), 0., 10)) station_offset = popt[1] plot.draw_vertical_line(station_offset) bins = linspace(-50, 50, 1000) plot.plot(bins, gauss(bins, *popt), mark=None, linestyle='gray') except RuntimeError: station_offset = 0. print station_offset plot.set_title('Time difference, station 510-501') plot.set_xlimits(-50, 50) plot.set_ylimits(min=0) plot.set_xlabel('$\Delta t$ [ns]') plot.set_ylabel('Counts') plot.save_as_pdf('station_offsets')
def determine_station_timing_offsets(d, data): # First determine detector offsets for each station offsets = {} for s in [501, 510]: station_group = data.get_node('/hisparc/cluster_amsterdam/station_%d' % s) offsets[s] = determine_detector_timing_offsets2(station_group.events) ref_station = 501 ref_d_off = offsets[ref_station] station = 510 cq = CoincidenceQuery(data, '/coincidences') dt = [] d_off = offsets[station] stations = [ref_station, station] coincidences = cq.all(stations) c_events = cq.events_from_stations(coincidences, stations) for events in c_events: # Filter for possibility of same station twice in coincidence if len(events) is not 2: continue if events[0][0] == ref_station: ref_event = events[0][1] event = events[1][1] else: ref_event = events[1][1] event = events[0][1] try: ref_t = min([ref_event['t%d' % (i + 1)] - ref_d_off[i] for i in range(4) if ref_event['t%d' % (i + 1)] not in ERR]) t = min([event['t%d' % (i + 1)] - d_off[i] for i in range(4) if event['t%d' % (i + 1)] not in ERR]) except ValueError: continue if (ref_event['t_trigger'] in ERR or event['t_trigger'] in ERR): continue dt.append((int(event['ext_timestamp']) - int(ref_event['ext_timestamp'])) - (event['t_trigger'] - ref_event['t_trigger']) + (t - ref_t)) bins = linspace(-150, 150, 200) y, bins = histogram(dt, bins=bins) x = (bins[:-1] + bins[1:]) / 2 try: popt, pcov = curve_fit(gauss, x, y, p0=(len(dt), 0., 50)) station_offset = popt[1] except RuntimeError: station_offset = 0. offsets[station] = [detector_offset + station_offset for detector_offset in offsets[station]] print 'Station 501 - 510: %f (%f)' % (popt[1], popt[2]) graph = Plot() graph.histogram(y, bins) graph.set_title('Time difference, between station 501-510') graph.set_label('%s' % d.replace('_', ' ')) graph.set_xlimits(-150, 150) graph.set_ylimits(min=0) graph.set_xlabel('$\Delta t$') graph.set_ylabel('Counts') graph.save_as_pdf('%s' % d)
def anti_coincidences(data): """Analyse events Compare density between events in coincidence and those not """ station_groups = ['/s%d' % number for number in STATIONS] plot = Plot('semilogy') plot2 = Plot() ids = [1, 2, 3, 4] colors = ['red', 'blue'] linestyles = ['solid', 'dashed'] for s_id, s_path in enumerate(data.root.coincidences.s_index): events = data.get_node(s_path, 'events') # Get all events which are in a coincidence ceids = [ e_idx for c_idx in data.root.coincidences.c_index for s_idx, e_idx in c_idx if s_idx == s_id ] coin_events = events.read_coordinates(ceids) all_events = events.read() bins = linspace(0.01, 40, 300) # Should filter -999 values, but there are only ~60 of those. coin_counts, bins = histogram(sum(coin_events['n%d' % id] for id in ids) / 2., bins=bins) all_counts, bins = histogram(sum(all_events['n%d' % id] for id in ids) / 2., bins=bins) anticoin_counts = all_counts - coin_counts # All events plot.histogram(all_counts, bins, linestyle='dotted, %s' % colors[s_id]) # Events in coincidence plot.histogram(coin_counts, bins, linestyle='solid, %s' % colors[s_id]) # Events not in coincidence plot.histogram(anticoin_counts, bins, linestyle='dashed, %s' % colors[s_id]) bins = linspace(0.01, 20, 50) coin_counts, bins = histogram(sum(coin_events['n%d' % id] for id in ids) / 2., bins=bins) all_counts, bins = histogram(sum(all_events['n%d' % id] for id in ids) / 2., bins=bins) detection_efficiency = coin_counts.astype('float') / all_counts plot2.plot((bins[1:] + bins[:-1]) / 2., detection_efficiency, linestyle='%s' % linestyles[s_id], mark=None) plot.set_ylimits(min=0.2) plot.set_xlimits(min=bins[0], max=15) plot.set_ylabel(r'Number of events') plot.set_xlabel(r'Particle density [\si{\per\square\meter}]') plot.save_as_pdf('anti_coincidences') plot2.set_ylimits(min=0., max=1.) plot2.set_xlimits(min=0) plot2.set_ylabel(r'Chance at coincidence') plot2.set_xlabel(r'Particle density [\si{\per\square\meter}]') plot2.save_as_pdf('detection_efficiency')
def plot_reconstruction_accuracy(): combinations = ['~d1 | ~d2 | ~d3 | ~d4', 'd1 & d2 & d3 & d4'] station_path = '/cluster_simulations/station_%d' with tables.open_file(RESULT_PATH, 'r') as data: cluster = data.root.coincidences._v_attrs.cluster coincidences = data.root.coincidences.coincidences c_recs = data.root.coincidences.reconstructions graph = Plot() da = angle_between(c_recs.col('zenith'), c_recs.col('azimuth'), c_recs.col('reference_zenith'), c_recs.col('reference_azimuth')) ids = c_recs.col('id') N = coincidences.read_coordinates(ids, field='N') for k, filter in enumerate([N == 3, N > 3]): n, bins = histogram(da.compress(filter), bins=arange(0, pi, .1)) graph.histogram(n, bins, linestyle=GRAYS[k % len(GRAYS)]) failed = len(coincidences.get_where_list('N >= 3')) - c_recs.nrows graph.set_ylimits(min=0) graph.set_xlimits(min=0, max=pi) graph.set_ylabel('Count') graph.set_xlabel('Angle between input and reconstruction [rad]') graph.set_title('Coincidences') graph.set_label('Failed to reconstruct %d events' % failed) graph.save_as_pdf('coincidences_alt') for station in cluster.stations: station_group = data.get_node(station_path % station.number) recs = station_group.reconstructions rows = coincidences.get_where_list('s%d == True' % station.number) reference_azimuth = coincidences.read_coordinates(rows, field='azimuth') reference_zenith = coincidences.read_coordinates(rows, field='zenith') graph = Plot() for k, combo in enumerate(combinations): selected_reconstructions = recs.read_where(combo) filtered_azimuth = array([ reference_azimuth[i] for i in selected_reconstructions['id'] ]) filtered_zenith = array([ reference_zenith[i] for i in selected_reconstructions['id'] ]) azimuth = selected_reconstructions['azimuth'] zenith = selected_reconstructions['zenith'] da = angle_between(zenith, azimuth, filtered_zenith, filtered_azimuth) n, bins = histogram(da, bins=arange(0, pi, .1)) graph.histogram(n, bins, linestyle=GRAYS[k % len(GRAYS)]) failed = station_group.events.nrows - recs.nrows graph.set_ylimits(min=0) graph.set_xlimits(min=0, max=pi) graph.set_ylabel('Count') graph.set_xlabel('Angle between input and reconstruction [rad]') graph.set_title('Station: %d' % station.number) graph.set_label('Failed to reconstruct %d events' % failed) graph.save_as_pdf('s_%d' % station.number)
def plot_active_stations(timestamps, stations, aligned_data, data, i): first_ts = [] last_ts = [] stations_with_data = [] assert aligned_data.shape[0] == len(stations) for n in range(aligned_data.shape[0]): prev_ts = 0 for ts, has_data in zip(timestamps, aligned_data[n]): if has_data: if prev_ts > 30: # Running for at least 30 hours. first_ts.append(ts) stations_with_data.append(stations[n]) break else: prev_ts += 1 else: prev_ts = 0 for station in stations_with_data: end_ts = get_station_end_timestamp(station, data) if end_ts is not None: last_ts.append(end_ts) first_ts = sorted(first_ts) last_ts = sorted(last_ts) diff_stations = array([1] * len(first_ts) + [-1] * len(last_ts)) idx = argsort(first_ts + last_ts) n_stations = diff_stations[idx].cumsum() # Get maximinum number of simultaneaously active stations per 7 days n_active_aligned = (aligned_data != 0).sum(axis=0) n_binned, t_binned, _ = binned_statistic(timestamps, n_active_aligned, npmax, bins=len(timestamps) / (7 * 24)) # Get average number of detected events per 7 days # todo; scale 2/4 detector stations summed_data = aligned_data.sum(axis=0) e_binned, t_binned, _ = binned_statistic(timestamps, summed_data, average, bins=len(timestamps) / (7 * 24)) plot = Plot(width=r'.5\textwidth') plot.plot([t / 1e9 for t in sorted(first_ts + last_ts)], n_stations, linestyle='gray, thick', mark=None, use_steps=True) plot.histogram(n_binned, t_binned / 1e9, linestyle='thick') plot.histogram(e_binned * max(n_binned) / max(e_binned), t_binned / 1e9, linestyle='blue') plot.set_axis_options('line join=round') plot.set_ylabel('Number of stations') plot.set_xlabel('Date') plot.set_ylimits(min=0) plot.set_xticks([datetime_to_gps(date(y, 1, 1)) / 1e9 for y in YEARS[::3]]) plot.set_xtick_labels(['%d' % y for y in YEARS[::3]]) plot.save_as_pdf('active_stations_%s' % ['network', 'spa'][i])
def analyse_reconstructions(data): cq = CoincidenceQuery(data) c_ids = data.root.coincidences.coincidences.read_where('s501', field='id') c_recs = cq.reconstructions.read_coordinates(c_ids) s_recs = data.root.hisparc.cluster_amsterdam.station_501.reconstructions zenc = c_recs['zenith'] azic = c_recs['azimuth'] zens = s_recs.col('zenith') azis = s_recs.col('azimuth') high_zenith = (zenc > .2) & (zens > .2) for minn in [1, 2, 4, 8, 16]: filter = (s_recs.col('min_n') > minn) length = len(azis.compress(high_zenith & filter)) shifts501 = np.random.normal(0, .06, length) azicounts, x, y = np.histogram2d(azis.compress(high_zenith & filter) + shifts501, azic.compress(high_zenith & filter), bins=np.linspace(-np.pi, np.pi, 73)) plota = Plot() plota.histogram2d(azicounts, np.degrees(x), np.degrees(y), type='reverse_bw', bitmap=True) # plota.set_title('Reconstructed azimuths for events in coincidence (zenith gt .2 rad)') plota.set_xlabel(r'$\phi_{501}$ [\si{\degree}]') plota.set_ylabel(r'$\phi_{Science Park}$ [\si{\degree}]') plota.set_xticks([-180, -90, 0, 90, 180]) plota.set_yticks([-180, -90, 0, 90, 180]) plota.save_as_pdf('azimuth_501_spa_minn%d' % minn) length = sum(filter) shifts501 = np.random.normal(0, .04, length) zencounts, x, y = np.histogram2d(zens.compress(filter) + shifts501, zenc.compress(filter), bins=np.linspace(0, np.pi / 3., 41)) plotz = Plot() plotz.histogram2d(zencounts, np.degrees(x), np.degrees(y), type='reverse_bw', bitmap=True) # plotz.set_title('Reconstructed zeniths for station events in coincidence') plotz.set_xlabel(r'$\theta_{501}$ [\si{\degree}]') plotz.set_ylabel(r'$\theta_{Science Park}$ [\si{\degree}]') plotz.set_xticks([0, 15, 30, 45, 60]) plotz.set_yticks([0, 15, 30, 45, 60]) plotz.save_as_pdf('zenith_501_spa_minn%d' % minn) distances = angle_between(zens.compress(filter), azis.compress(filter), zenc.compress(filter), azic.compress(filter)) counts, bins = np.histogram(distances, bins=np.linspace(0, np.pi, 91)) plotd = Plot() plotd.histogram(counts, np.degrees(bins)) sigma = np.degrees(np.percentile(distances[np.isfinite(distances)], 67)) plotd.set_label(r'67\%% within \SI{%.1f}{\degree}' % sigma) # plotd.set_title('Distance between reconstructed angles for station and cluster') plotd.set_xlabel('Angle between reconstructions [\si{\degree}]') plotd.set_ylabel('Counts') plotd.set_xlimits(min=0, max=90) plotd.set_ylimits(min=0) plotd.save_as_pdf('angle_between_501_spa_minn%d' % minn)
start = (data[sn]['timestamp'][0] - first) / 3600 end = start + len(data[sn]) extended_data[i, start:end] = ((data[sn]['counts'] > 500) & (data[sn]['counts'] < 5000)) return timestamps, extended_data if __name__ == "__main__": timestamps, eventtime = get_aligned() summed_data = eventtime.sum(axis=0) plot = Plot() bins = arange(-.5, len(STATIONS) + 1.5) counts, bins = histogram(summed_data, bins=bins) counts_in_years = counts / 24. / 365. plot.histogram(counts_in_years, bins, linestyle='semitransparent') # Exluding data from before 26-09-2008 start = argmax(timestamps > datetime_to_gps(date(2008, 9, 26))) counts, bins = histogram(summed_data[start:], bins=bins) counts_in_years = counts / 24. / 365. print[(i, sum(counts_in_years[i:])) for i in range(11)] plot.histogram(counts_in_years, bins) # Exluding data from before 08-03-2010 start = argmax(timestamps > datetime_to_gps(date(2010, 3, 8))) counts, bins = histogram(summed_data[start:], bins=bins) counts_in_years = counts / 24. / 365. print[(i, sum(counts_in_years[i:])) for i in range(11)] plot.histogram(counts_in_years, bins, linestyle='blue')
for i, sn in enumerate(data.keys()): start = (data[sn]['timestamp'][0] - first) / 3600 end = start + len(data[sn]) extended_data[i, start:end] = ((data[sn]['counts'] > 500) & (data[sn]['counts'] < 5000)) return timestamps, extended_data if __name__ == "__main__": timestamps, eventtime = get_aligned() summed_data = eventtime.sum(axis=0) plot = Plot() counts, bins = histogram(summed_data, bins=arange(-.5, 100.5, 1)) counts_in_years = counts / 24. / 365. plot.histogram(counts_in_years, bins) # Exluding data from before 08-03-2010 start = argmax(timestamps > datetime_to_gps(date(2010, 3, 8))) counts, bins = histogram(summed_data[start:], bins=bins) counts_in_years = counts / 24. / 365. plot.histogram(counts_in_years, bins, linestyle='blue') # Exluding data from before 01-07-2011 start = argmax(timestamps > datetime_to_gps(date(2011, 7, 1))) counts, bins = histogram(summed_data[start:], bins=bins) counts_in_years = counts / 24. / 365. plot.histogram(counts_in_years, bins, linestyle='red') plot.set_ylimits(min=0) plot.set_xlimits(min=-0.5, max=100.5)
def plot_reconstructions(): with tables.open_file('data.h5', 'r') as data: rec = data.root.s501.reconstructions reco = data.root.s501_original.reconstructions # Compare azimuth distribution bins = linspace(-pi, pi, 20) # Radians plot = Plot() plot.histogram(*histogram(rec.col('azimuth'), bins=bins)) plot.histogram(*histogram(reco.col('azimuth'), bins=bins), linestyle='red') plot.set_ylimits(min=0) plot.set_xlimits(-pi, pi) plot.set_ylabel('counts') plot.set_xlabel(r'Azimuth [\si{\radian}]') plot.save_as_pdf('azimuth') # Compare zenith distribution bins = linspace(0, pi / 2, 20) # Radians plot = Plot() plot.histogram(*histogram(rec.col('zenith'), bins=bins)) plot.histogram(*histogram(reco.col('zenith'), bins=bins), linestyle='red') plot.set_ylimits(min=0) plot.set_xlimits(0, pi / 2) plot.set_ylabel('counts') plot.set_xlabel(r'Zenith [\si{\radian}]') plot.save_as_pdf('zenith') # Compare angles between old and new bins = linspace(0, 20, 20) # Degrees plot = Plot() filter = (rec.col('zenith') > .5) d_angle = angle_between(rec.col('zenith'), rec.col('azimuth'), reco.col('zenith'), reco.col('azimuth')) plot.histogram(*histogram(degrees(d_angle), bins=bins)) plot.histogram(*histogram(degrees(d_angle).compress(filter), bins=bins), linestyle='red') plot.histogram(*histogram(degrees(d_angle).compress(invert(filter)), bins=bins), linestyle='blue') plot.set_ylimits(min=0) plot.set_xlimits(0, 20) plot.set_ylabel('counts') plot.set_xlabel(r'Angle between [\si{\degree}]') plot.save_as_pdf('angle_between')
def plot_angles(data): """Make azimuth and zenith plots to compare the results""" rec501 = data.get_node('/hisparc/cluster_amsterdam/station_501', 'reconstructions') rec510 = data.get_node('/hisparc/cluster_amsterdam/station_510', 'reconstructions') zen501 = rec501.col('zenith') zen510 = rec510.col('zenith') azi501 = rec501.col('azimuth') azi510 = rec510.col('azimuth') minn501 = rec501.col('min_n') minn510 = rec510.col('min_n') sigmas = [] blas = [] minns = [0, 1, 2, 4, 8, 16, 24] high_zenith = (zen501 > .2) & (zen510 > .2) for minn in minns: filter = (minn501 > minn) & (minn510 > minn) length = len(azi501.compress(high_zenith & filter)) shifts501 = np.random.normal(0, .06, length) shifts510 = np.random.normal(0, .06, length) azicounts, x, y = np.histogram2d( azi501.compress(high_zenith & filter) + shifts501, azi510.compress(high_zenith & filter) + shifts510, bins=np.linspace(-pi, pi, 73)) plota = Plot() plota.histogram2d(azicounts, degrees(x), degrees(y), type='reverse_bw', bitmap=True) # plota.set_title('Reconstructed azimuths for events in coincidence (zenith gt .2 rad)') plota.set_xlabel(r'$\phi_{501}$ [\si{\degree}]') plota.set_ylabel(r'$\phi_{510}$ [\si{\degree}]') plota.set_xticks([-180, -90, 0, 90, 180]) plota.set_yticks([-180, -90, 0, 90, 180]) plota.save_as_pdf('azimuth_501_510_minn%d' % minn) length = len(zen501.compress(filter)) shifts501 = np.random.normal(0, .04, length) shifts510 = np.random.normal(0, .04, length) zencounts, x, y = np.histogram2d(zen501.compress(filter) + shifts501, zen510.compress(filter) + shifts510, bins=np.linspace(0, pi / 3., 41)) plotz = Plot() plotz.histogram2d(zencounts, degrees(x), degrees(y), type='reverse_bw', bitmap=True) # plotz.set_title('Reconstructed zeniths for station events in coincidence') plotz.set_xlabel(r'$\theta_{501}$ [\si{\degree}]') plotz.set_ylabel(r'$\theta_{510}$ [\si{\degree}]') plotz.set_xticks([0, 15, 30, 45, 60]) plotz.set_yticks([0, 15, 30, 45, 60]) plotz.save_as_pdf('zenith_501_510_minn%d' % minn) distances = angle_between(zen501.compress(filter), azi501.compress(filter), zen510.compress(filter), azi510.compress(filter)) counts, bins = np.histogram(distances, bins=linspace(0, pi, 100)) plotd = Plot() plotd.histogram(counts, degrees(bins)) sigma = degrees(percentile(distances[isfinite(distances)], 68)) sigmas.append(sigma) bla = degrees(percentile(distances[isfinite(distances)], 95)) blas.append(bla) plotd.set_label(r'67\%% within \SI{%.1f}{\degree}' % sigma) # plotd.set_title('Distance between reconstructed angles for station events') plotd.set_xlabel(r'Angle between reconstructions [\si{\degree}]') plotd.set_ylabel('Counts') plotd.set_xlimits(min=0, max=90) plotd.set_ylimits(min=0) plotd.save_as_pdf('angle_between_501_510_minn%d' % minn) plot = Plot() plot.plot(minns, sigmas, mark='*') plot.plot(minns, blas) plot.set_ylimits(min=0, max=40) plot.set_xlabel('Minimum number of particles in each station') plot.set_ylabel(r'Angle between reconstructions [\si{\degree}]') plot.save_as_pdf('angle_between_501_510_v_minn')
def plot_angles(data): """Make azimuth and zenith plots to compare the results""" rec = data.root.reconstructions zenhis = rec.col('reconstructed_theta') zenkas = rec.col('reference_theta') azihis = rec.col('reconstructed_phi') azikas = rec.col('reference_phi') min_n = rec.col('min_n134') high_zenith = (zenhis > .2) & (zenkas > .2) for minn in [0, 1, 2, 4]: filter = (min_n > minn) azicounts, x, y = np.histogram2d(azihis.compress(high_zenith & filter), azikas.compress(high_zenith & filter), bins=np.linspace(-pi, pi, 73)) plota = Plot() plota.histogram2d(azicounts, degrees(x), degrees(y), type='reverse_bw', bitmap=True) # plota.set_title('Reconstructed azimuths for events in coincidence (zenith gt .2 rad)') plota.set_xlabel(r'$\phi_\textrm{HiSPARC}$ [\si{\degree}]') plota.set_ylabel(r'$\phi_\textrm{KASCADE}$ [\si{\degree}]') plota.set_xticks([-180, -90, 0, 90, 180]) plota.set_yticks([-180, -90, 0, 90, 180]) plota.save_as_pdf('azimuth_his_kas_minn%d' % minn) zencounts, x, y = np.histogram2d(zenhis.compress(filter), zenkas.compress(filter), bins=np.linspace(0, pi / 3., 41)) plotz = Plot() plotz.histogram2d(zencounts, degrees(x), degrees(y), type='reverse_bw', bitmap=True) # plotz.set_title('Reconstructed zeniths for station events in coincidence') plotz.set_xlabel(r'$\theta_\textrm{HiSPARC}$ [\si{\degree}]') plotz.set_ylabel(r'$\theta_\textrm{KASCADE}$ [\si{\degree}]') plotz.set_xticks([0, 15, 30, 45, 60]) plotz.set_yticks([0, 15, 30, 45, 60]) plotz.save_as_pdf('zenith_his_kas_minn%d' % minn) distances = angle_between(zenhis.compress(filter), azihis.compress(filter), zenkas.compress(filter), azikas.compress(filter)) counts, bins = np.histogram(distances, bins=linspace(0, pi, 100)) plotd = Plot() plotd.histogram(counts, degrees(bins)) sigma = degrees(scoreatpercentile(distances, 67)) plotd.set_title(r'$N_\textrm{MIP} \geq %d$' % minn) plotd.set_label(r'67\%% within \SI{%.1f}{\degree}' % sigma) # plotd.set_title('Distance between reconstructed angles for station events') plotd.set_xlabel('Angle between reconstructions [\si{\degree}]') plotd.set_ylabel('Counts') plotd.set_xlimits(min=0, max=90) plotd.set_ylimits(min=0) plotd.save_as_pdf('angle_between_his_kas_minn%d' % minn)