def plot_wobble(source_position, n_points, ax=None): """ Plot 2D map of ON/OFF positions w.r.t. to the camera center Parameters ---------- source_position: Source position in the camera frame, array-like [x,y] n_points: Number of observation points. Rotation angle for each next observation is determined as 360/n_points ax: `matplotlib.pyplot.axes` or None Returns ------- ax: `matplotlib.pyplot.axes` """ from lstchain.reco.utils import rotate if ax is None: ax = plt.gca() opacity = 0.2 marker_size = 20 color_map_name = 'Set1' # https://matplotlib.org/gallery/color/colormap_reference.html colors = get_cmap(color_map_name).colors ax.set_prop_cycle(color=colors) rotation_angle = 360. / n_points labels = [ 'Source', ] + [f'OFF {rotation_angle * x}' for x in range(1, n_points)] ax.plot((0, 0), '.', markersize=marker_size, alpha=opacity, color='black', label="Camera center") for off_point in range(n_points): first_point = tuple( rotate( list( zip(source_position[0].to_value(), source_position[1].to_value()))[0], rotation_angle * off_point)[0]) ax.plot(first_point[0], first_point[1], '.', markersize=marker_size, alpha=opacity, label=labels[off_point]) ax.annotate(labels[off_point], xy=(first_point[0] - 0.1, first_point[1] + 0.05), label=labels[off_point]) ax.set_ylim(-0.7, 0.7) ax.set_xlim(-0.7, 0.7) ax.set_ylabel("(m)") ax.set_xlabel("Position in the camera (m)") return ax
def analyze_wobble(config): """ Extracts the theta2 plot of a dataset taken with wobble observations Parameters ---------- config_file """ fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(20, 8)) n_points = config['analysis']['parameters']['n_points'] theta2_cut = config['analysis']['selection']['theta2'][0] LOGGER.info( "Running wobble analysis with %s off-source observation points", n_points) LOGGER.info("Analyzing runs %s", config['analysis']['runs']) observation_time, data = merge_dl2_runs(config['input']['data_tag'], config['analysis']['runs'], config['input']['columns_to_read']) LOGGER.debug('\nPreselection:\n%s', config['preselection']) for key, value in config['preselection'].items(): LOGGER.debug('\nParameter: %s, range: %s, value type: %s', key, value, type(value)) selected_data = filter_events(data, filters=config['preselection']) # Add theta2 to selected data true_source_position = extract_source_position( selected_data, config['input']['observed_source']) plotting.plot_wobble(true_source_position, n_points, ax1) named_datasets = [] named_datasets.append( ('ON data', np.array(compute_theta2(selected_data, true_source_position)), 1)) n_on = np.sum(named_datasets[0][1] < theta2_cut) n_off = 0 rotation_angle = 360. / n_points origin_x = selected_data['reco_src_x'] origin_y = selected_data['reco_src_y'] for off_point in range(1, n_points): t_off_data = selected_data.copy() off_xy = rotate(tuple(zip(origin_x, origin_y)), rotation_angle * off_point) t_off_data['reco_src_x'] = [xy[0] for xy in off_xy] t_off_data['reco_src_y'] = [xy[1] for xy in off_xy] named_datasets.append( (f'OFF {rotation_angle * off_point}', np.array(compute_theta2(t_off_data, true_source_position)), 1)) n_off += np.sum(named_datasets[-1][1] < theta2_cut) stat = WStatCountsStatistic(n_on, n_off, 1. / (n_points - 1)) # API change for attributes significance and excess in the new gammapy version: https://docs.gammapy.org/dev/api/gammapy.stats.WStatCountsStatistic.html lima_significance = stat.sqrt_ts.item() lima_excess = stat.n_sig LOGGER.info('Observation time %s', observation_time) LOGGER.info('Number of "ON" events %s', n_on) LOGGER.info('Number of "OFF" events %s', n_off) LOGGER.info('ON/OFF observation time ratio %s', 1. / (n_points - 1)) LOGGER.info('Excess is %s', lima_excess) LOGGER.info('Li&Ma significance %s', lima_significance) plotting.plot_1d_excess(named_datasets, lima_significance, r'$\theta^2$ [deg$^2$]', theta2_cut, ax2) if config['output']['interactive'] is True: LOGGER.info( 'Interactive mode ON, plots will be only shown, but not saved') plt.show() else: LOGGER.info('Interactive mode OFF, no plots will be displayed') plt.ioff() plt.savefig(f"{config['output']['directory']}/wobble.png") plt.close()