Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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()