Example #1
0
def plot_auc(x_values: np.ndarray,
             y_values: np.ndarray,
             title: str,
             ax: Axes,
             print_coords: bool = False) -> None:
    """
    Plot a curve given the x and y values of each point.
    :param x_values: x coordinate of each data point to be plotted
    :param y_values: y coordinate of each data point to be plotted
    :param title: Title of the plot
    :param ax: matplotlib.axes.Axes object for plotting
    :param print_coords: If true, prints out the coordinates of each point on the graph.
    """
    ax.plot(x_values, y_values)
    ax.set_xlim(left=0, right=1)
    ax.set_ylim(bottom=0, top=1)
    ax.set_title(title)

    if print_coords:
        # write values of points
        for x, y in zip(x_values, y_values):
            ax.annotate(f"{x:0.3f}, {y:0.3f}",
                        xy=(x, y),
                        xytext=(15, 0),
                        textcoords='offset points')
Example #2
0
def auto_text(text: str, ax: Axes, text_xy: tuple = None, index: int = -1):
    """
    Automatically add the text.

    Parameters
    ----------
    text : str
        The content of the text.

    ax : Axes
        The axes to plot the data on.

    text_xy : tuple
        The relative position. The horizontal bound is the xlim. The vertical is the two curves.

    index : int
        The index of the lines to add text. Default -1 (the last line).
    """
    lines = ax.get_lines()
    if len(lines) == 0:
        return ax
    vis_data = lines[index].get_data()
    color = lines[index].get_color()
    if text_xy is None:
        text_xy = _TEXT_XY
    xy = text_position(vis_data, text_xy)
    ax.annotate(text, xy, ha="left", va="center", color=color)
    return ax
Example #3
0
def draw_rule(cc: ControlChart, ax: axes.Axes, above: pd.Series,
              below: pd.Series, rule_name: str) -> NoReturn:
    """
    Invokes one of the points_* rules to identify out-of-control points

    Parameters
    ----------
    cc : ControlChart
        The control chart object.
    ax : axes.Axes
        The Axes object.
    above : pd.Series
        The pandas Series for the points above rule.
    below : pd.Series
        The pandas Series for the points below a rule.
    """
    y_percent = (cc.y.max() - cc.y.min()) / 100

    for x, y in above.items():
        ax.annotate(rule_name,
                    xy=(x, y),
                    xytext=(x, y + y_percent * 5),
                    color=colour4)

    for x, y in below.items():
        ax.annotate(rule_name,
                    xy=(x, y),
                    xytext=(x, y - y_percent * 5),
                    color=colour4)
def add_value_labels(ax: Axes,
                     spacing: int = 5,
                     percentage: bool = False) -> None:
    """ Add labels to the end of each bar in a bar chart.

    Overwrite labels on axes if they already exist.

    Args:
        ax (Axes): The matplotlib object containing the axes of the plot to annotate.
        spacing (int): The distance between the labels and the bars.
        percentage (bool): if y-value is a percentage
    """
    for child in ax.get_children():
        if isinstance(child, Annotation):
            child.remove()

    for rect in ax.patches:
        y_value = rect.get_height()
        x_value = rect.get_x() + rect.get_width() / 2

        label = ("{:.2f}%".format(y_value * 100)
                 if percentage else "{:.1f}".format(y_value))

        ax.annotate(
            label,
            (x_value, y_value),
            xytext=(0, spacing),  # Vertically shift label by `space`
            textcoords="offset points",  # Interpret `xytext` as offset in points
            ha="center",  # Horizontally center label
            va="bottom",  # Vertically align label
        )
Example #5
0
def MRE_notation_marks(axes: Axes):

    MRE_TIME_POINTS = [0, 7, 14]  # days when MRE was applied

    arrow_angle = 0.7  # radians from a downwards line perpendicular to x axis
    offset_head = 0.3  # offset of arrow head from annotation point, given in data coordinates(=days)
    offset_base = offset_head + math.sin(arrow_angle)  # offset of arrow base
    head_y = -0.03  # given as fraction of axes size
    base_y = head_y - 0.07  # given as fraction of axes size

    arrow_properties = dict(
        arrowstyle="wedge,tail_width=0.7",
        fc="0.6",
        ec="0.1",
    )

    for time_point in MRE_TIME_POINTS:

        # axes.annotate(
        #               s='',
        #               xy=(time_point - offset_head_x, head_y ), # arrow head coordinates
        #               xytext=(time_point - offset_base_x, base_y), # arrow base coordinates
        #               xycoords=('data', 'axes fraction'),
        #               arrowprops=arrow_properties,
        #               )
        axes.annotate(
            s='',
            xy=(time_point - offset_head, head_y),  # arrow head coordinates
            xytext=(time_point - offset_base,
                    base_y),  # arrow base coordinates
            xycoords=('data', 'axes fraction'),
            textcoords=('data', 'axes fraction'),
            arrowprops=(arrow_properties))
Example #6
0
def add_horizontal_value_labels(ax: Axes, spacing: float = 5) -> None:
    """Add labels to the end of each bar in a bar chart."""

    # For each bar: Place a label
    for rect in ax.patches:
        # Get X and Y placement of label from rect.
        x_value = rect.get_width()
        y_value = rect.get_y() + rect.get_height() / 2

        # Number of points between bar and label. Change to your liking.
        space = spacing
        # Vertical alignment for positive values
        ha = "left"

        # If value of bar is negative: Place label below bar
        if x_value < 0:
            # Invert space to place label below
            space *= -1
            # Horizontally align label at right
            ha = "right"

        label = f"{int(x_value)}"
        # Create annotation
        ax.annotate(
            label,  # Use `label` as label
            (x_value, y_value),  # Place label at end of the bar
            xytext=(space, 0),  # Vertically shift label by space
            textcoords="offset points",  # Interpret xytext as offset in points
            ha=ha,  # Horizontally center label
            va="center",  # Vertically align label differently
            fontsize=8,
        )
Example #7
0
 def plot_track(
     self,
     axis: Axes = None,
     show: bool = False,
     color: str = 'k',
     coastline: bool = True,
     **kwargs,
 ):
     kwargs.update({'color': color})
     if axis is None:
         fig = pyplot.figure()
         axis = fig.add_subplot(111)
     for i in range(len(self.speed)):
         # when dealing with nautical degrees, U is sine and V is cosine.
         U = self.speed.iloc[i] * numpy.sin(
             numpy.deg2rad(self.direction.iloc[i]))
         V = self.speed.iloc[i] * numpy.cos(
             numpy.deg2rad(self.direction.iloc[i]))
         axis.quiver(self.longitude.iloc[i], self.latitude.iloc[i], U, V,
                     **kwargs)
         if i % 6 == 0:
             axis.annotate(
                 self.data['datetime'].iloc[i],
                 (self.longitude.iloc[i], self.latitude.iloc[i]),
             )
     if show:
         axis.axis('scaled')
     if bool(coastline) is True:
         plot_coastline(axis, show)
Example #8
0
def draw_rules(cc: ControlChart, ax: axes.Axes) -> NoReturn:
    """
    Invokes all of the points_* rules to identify out-of-control points

    Parameters
    ----------
    cc : ControlChart
        The control chart object.
    ax : axes.Axes
        The Axes object.
    """
    aboves = defaultdict(str)
    belows = defaultdict(str)
    for label, rule in [('1', points_one), ('2', points_two),
                        ('3', points_three), ('4', points_four)]:
        above, below = rule(cc)
        for x, y in above.items():
            aboves[(x, y)] += label
        for x, y in below.items():
            belows[(x, y)] += label

    y_percent = (cc.y.max() - cc.y.min()) / 100

    for (x, y), rule_names in aboves.items():
        ax.annotate(rule_names,
                    xy=(x, y),
                    xytext=(x, y + y_percent * 5),
                    color=colour4)

    for (x, y), rule_names in belows.items():
        ax.annotate(rule_names,
                    xy=(x, y),
                    xytext=(x, y - y_percent * 5),
                    color=colour4)
Example #9
0
def add_arrow(
    ax: Axes,
    tip: Tuple[float, float],
    rot: float = 60,
    length: float = 20,
    trans: Optional[Transform] = None,
):
    """
    Highlight part of a plot by pointing an arrow to it.

    :param ax:  Axes to plot on.
    :param tip:  Where the arrow points at (location of the arrow end).
    :param rot:  Rotation of the arrow, in degrees. 0 is pointing east.
    :param length:  Lenght of the arrow, in points (1/72-th of an inch).
    :param trans:  Coordinate system of `point`. Default: `ax.transAxes`, for
                axes coordinates. Other interesting options: `ax.transData`,
                `ax.get_xaxis_transform()`, and `ax.get_yaxis_transform()`.
    :return:
    """
    if trans is None:
        trans = ax.transAxes
    tip = array(tip)
    angle = (rot / 360) * tau
    vector_length = points_to_figcoords(length, trans)
    vector = vector_length * array([cos(angle), sin(angle)])
    base = tip - vector
    ax.annotate(
        "",
        tip,
        base,
        xycoords=trans,
        textcoords=trans,
        arrowprops=dict(fc="black"),
    )
Example #10
0
def plot_annotate_stages(exp_result: ExperimentResult, ax: Axes) -> None:
    xmin = 0
    max_len = exp_result.obs_trajectories.global_infection_summary.shape[0]
    ylim = ax.get_ylim()
    ax.set_ylim([ylim[0], 1.5 * ylim[1]])

    for strategy in get_stage_strategy(exp_result.obs_trajectories.stage[:, 0,
                                                                         0]):
        xmax = max_len if strategy.end_day is None else min(
            strategy.end_day, max_len)
        y = 0.82 * ax.get_ylim()[1]
        ax.annotate('',
                    xy=(xmin, y),
                    xytext=(xmax, y),
                    xycoords='data',
                    textcoords='data',
                    arrowprops={
                        'arrowstyle': '<->',
                        'color': 'red',
                        'linewidth': 1
                    })

        xcenter = xmin + (xmax - xmin) / 2

        ax.annotate(f'{strategy.stage}',
                    xy=(xcenter, 0.92 * ax.get_ylim()[1]),
                    ha='center',
                    va='center',
                    fontsize=8)
        xmin = xmax
Example #11
0
 def _annotate_label(ax: Axes, label: AnyStr, text_x: float, text_y: float,
                     rotation: float, text_style: Dict):
     if abs(rotation) > 0:
         text_loc = np.array((text_x, text_y))
         text_style['rotation'] = ax.transData.transform_angles(
             np.array((rotation, )), text_loc.reshape((1, 2)))[0]
         text_style['rotation_mode'] = 'anchor'
     ax.annotate(label, (text_x, text_y), **text_style)
Example #12
0
 def annotate_plot(ax: Axes, label: str) -> None:
     ax.annotate(f'({label})', (0.5, 0.),
                 xytext=(0, -25 - 20),
                 textcoords='offset points',
                 xycoords='axes fraction',
                 ha='center',
                 va='center',
                 size=14)
Example #13
0
def plot_histogram_to_ax(ax: Axes, flux_ratios: [float], is_blue: bool):
    """
    Produce a histogram showing the distribution of the non_ss_spectra ratios
    """
    ax.set_title(f"Histogram of the H$\\{'beta' if is_blue else 'alpha'}$:continuum\nflux ratio over the fibre array")
    bin_edges = np.arange(0, 125, 5)
    ax.set_yscale("log")
    ax.yaxis.set_major_formatter(ScalarFormatter())
    ax.set(ylabel="count", xlabel="flux ratio")
    ax.hist(flux_ratios, bins=bin_edges, align="mid", rwidth=0.8, density=False)
    ax.annotate(f"max={max(flux_ratios):.2f}\nmin={min(flux_ratios):.2f}", xy=(0.5, 0.85), xycoords="axes fraction")
    return
Example #14
0
def draw_fit_on_ax_over_range(ax: Axes, start: Quantity, end: Quantity, fit: Model, annotate: bool = True,
                              color: str = "m", line_width: float = 0.5, y_shift: float = 0,
                              split: bool = False, subtract_continuum: bool = False):
    x_plot = Quantity(np.linspace(start.value, end.value, 1000), start.unit)

    if not split or not isinstance(fit, CompoundModel):
        # Draw the whole model, and optionally subtract the continuum
        y_plot = fit(x_plot)
        if subtract_continuum and isinstance(fit, CompoundModel) and "continuum" in fit.submodel_names:
            continuum_fit = fit["continuum"]
            y_plot = np.subtract(y_plot, continuum_fit(x_plot))

        ax.plot(x_plot, np.add(y_plot, y_shift), "-",
                color=_fit_colors[0], linewidth=line_width, alpha=0.5, zorder=2)
    else:
        # Draw the individual elements (except continuum) - cannot subtract the continuum as all offest from zero
        color_ix = 0
        for sub in fit:
            if isinstance(sub, Polynomial1D) and "cont" in sub.name:
                # It's the continuum.  Leave it.
                pass
            else:
                y_plot = sub(x_plot)
                ax.plot(x_plot, np.add(y_plot, y_shift), "-",
                        color=_fit_colors[color_ix], linewidth=line_width, alpha=0.5, zorder=2)
                color_ix += 1

    if annotate:
        if isinstance(fit, CompoundModel):
            text = describe_compound_fit(fit, for_matplotlib=True, include_amplitude=False, include_flux=False)
        elif isinstance(fit, Gaussian1D):
            text = describe_gaussian_fit(fit, for_matplotlib=True, include_amplitude=True, include_flux=False)
        else:
            text = f"Cannot yet describe {fit.__class__.__name__}"

        # Have to take the units off for this, otherwise you get an UnitConversionError when saving the plot
        peak_position = (fit.mean_0.value, max(y_plot).value)
        if "delta" in fit.name:
            xytext = (0.05, 0.5)
        elif "gamma" in fit.name:
            xytext = (0.1, 0.6)
        elif "beta" in fit.name:
            xytext = (0.25, 0.7)
        elif "He" in fit.name:
            xytext = (0.2, 0.85)
        else:
            xytext = (0.65, 0.8)

        ax.annotate(text, xycoords="data", xy=peak_position, textcoords="axes fraction", xytext=xytext,
                    color=color, fontsize="4")
    return
Example #15
0
def annotate_bars(
    ax: Axes = None,
    v_offset: int = 10,
    h_offset: int = 0,
    labels: Sequence[str | int | float] = None,
    fontsize: int = 14,
    **kwargs: Any,
) -> None:
    """Annotate each bar in bar plot with a label.

    Args:
        ax (matplotlib.axes.Axes): The axes to annotate.
        v_offset (int): Vertical offset between the labels and the bars.
        h_offset (int): Horizontal offset between the labels and the bars.
        labels (list[str]): Labels used for annotating bars. If not provided, defaults
            to the y-value of each bar.
        fontsize (int): Annotated text size in pts. Defaults to 14.
        **kwargs: Additional arguments (rotation, arrowprops, etc.) are passed to
            ax.annotate().
    """
    if ax is None:
        ax = plt.gca()

    if labels is None:
        labels = [int(patch.get_height()) for patch in ax.patches]

    y_max = 0

    for rect, label in zip(ax.patches, labels):

        y_pos = rect.get_height()
        x_pos = rect.get_x() + rect.get_width() / 2 + h_offset

        if ax.get_yscale() == "log":
            y_pos = y_pos + np.log(v_offset if v_offset > 1 else 1)
        else:
            y_pos = y_pos + v_offset

        y_max = max(y_max, y_pos)

        txt = f"{label:,}" if isinstance(label, (int, float)) else label
        # place label at end of the bar and center horizontally
        ax.annotate(txt, (x_pos, y_pos),
                    ha="center",
                    fontsize=fontsize,
                    **kwargs)

    # ensure enough vertical space to display label above highest bar
    ax.set(ylim=(None, y_max * 1.1))
Example #16
0
def annotate_cost_and_time(ax: axes.Axes,
                           time_step: Optional[int] = None,
                           cumul_cost: Optional[float] = None) -> None:
    """
    Annotate the cost and time step at the bottom left of the drawing plot

    :param ax: matplotlib axes on which to draw
    :param time_step: current time step
    :param cumul_cost: the cumulative cost at the current time step
    """
    msg = ''
    if time_step is not None:
        msg += '\ntime: {}'.format(time_step)
    if cumul_cost is not None:
        msg += '\ndiscounted total cost: {:.0f}'.format(cumul_cost)
    ax.annotate(msg, (0, -1), color='k', size=14)
Example #17
0
def draw_buffer(ax: axes.Axes,
                coord: types.Coord2D,
                num_items: int,
                max_capacity: int,
                color: str,
                do_annotations: bool,
                do_reverse: bool = False,
                is_extra_high: Optional[bool] = False) -> List[mpatches.Patch]:
    """Draw a horizontal buffer diagram on axes, at a certain coordinate,
    with items added from the left ('top' is on the left.)

    :param ax: matplotlib axes on which to draw
    :param coord: coordinate at which to place buffer (bottom left of it)
    :param num_items: number of items in the buffer (state)
    :param max_capacity: max capacity of the buffer
    :param color: color of the buffer
    :param do_annotations: whether to annotate the buffer with the current state
    :param do_reverse: if true, draw the buffer in reverse (items added from right)
    :param is_extra_high: if true, draw a buffer that is twice the height of the default option
    """

    b_width = 3
    if is_extra_high:
        b_height = 2
    else:
        b_height = 1
    p1 = mpatches.Rectangle(coord, b_width, b_height, color=color)
    fill_fraction = num_items / max_capacity
    f_width = (1 - fill_fraction) * b_width
    ax.add_patch(p1)

    if do_reverse:
        white_coord = (coord[0] + b_width - f_width, coord[1])
        p2 = mpatches.Rectangle(white_coord, f_width, b_height, color='w')
    else:
        p2 = mpatches.Rectangle(coord, f_width, b_height, color='w')
    ax.add_patch(p2)

    p3 = mpatches.Rectangle(coord, b_width, b_height, fill=False, color='k')
    ax.add_patch(p3)

    if do_annotations:
        msg = '{:.0f}'.format(num_items)
        text_coord = [coord[0] + .2, coord[1] + b_height + 0.2]
        ax.annotate(msg, coord, text_coord, size=14)

    return [p1, p2, p3]
Example #18
0
def Graphing_TimePlot(data: list,
                      dates: list,
                      ax: axes.Axes,
                      label: str,
                      rotation=20,
                      diff_mode=False,
                      annotations=False):
    """Plot the change in cases and deaths per country as a timeline.
        
    **Args:**
        data(list):         The data to index by time.
        dates(list):        A list of dates to graph against data.
        ax(axes.Axes):      A premade axis to attach the graph to.
        label(str):         The graph title.
        rotation(int):      X-axis label rotation. Default is 20.
        diff_mode(bool):    Calculates the diff on every date value passed. Default is False (off).
        annotations(bool):  Annotates the data points to each line plotted. Default is False (off).

    """

    if diff_mode:
        yData_series = timeManips_timestampConvert(
            dates).diff().iloc[:, 0].tolist()
    else:
        yData_series = timeManips_timestampConvert(dates)

    markerline, stemline, baseline = ax.stem(yData_series,
                                             data,
                                             linefmt="C3-",
                                             basefmt="k-",
                                             use_line_collection=True)

    plt.setp(markerline, mec="k", mfc="w",
             zorder=3)  # recolour markers and remove line through them
    markerline.set_ydata(np.zeros(len(yData_series)))

    if annotations:
        # Annotate lines
        vert = np.array(['top', 'bottom'])[(data > 0).astype(int)]
        for d, l, r, va in zip(yData_series, data, data, vert):
            if not (l > 0 or l < 0):
                continue
            text = ax.annotate(r,
                               xy=(d, l),
                               xytext=(-3, np.sign(l) * 3),
                               textcoords="offset points",
                               va=va,
                               ha="right")
            text.set_rotation(-45)

    # Formatting
    ax.set_title(label)
    plt.xticks(rotation=rotation)
    ax.get_yaxis().set_visible(True)

    # Make spines invisible.
    for spine in ["left", "top", "right"]:
        ax.spines[spine].set_visible(False)
    return
Example #19
0
def plot_scheduling(ax: Axes,
                    instance: List[Task],
                    scheduling: List[Procesor],
                    xmax: float,
                    name: Optional[str] = None):
    colors = [
        'orange', 'blue', 'red', 'yellow', 'green', 'purple', 'pink', 'gray'
    ]
    if name is not None:
        ax.set_title(name)
    ax.grid(True)

    ax.set_xlim(0, xmax)
    ax.set_xlabel('Time')
    ax.set_ylabel('Processor')
    ax.set_ylim(0, 10 * len(scheduling))
    ax.set_yticks([5 + 10 * i for i in range(len(scheduling))])
    ax.set_yticklabels([proc.id for proc in reversed(scheduling)])

    for i, proc in enumerate(reversed(scheduling)):
        for j, task in enumerate(proc.tasks):
            t_id = task.task.id
            color = colors[t_id % len(colors)]
            ax.broken_barh([(task.start, task.end - task.start)],
                           (0.5 + 10 * i, 9),
                           facecolors=color,
                           label=str(t_id))
            ax.annotate(str(t_id),
                        xy=(task.start, 9.5 + 10 * i),
                        xycoords='data',
                        horizontalalignment='left',
                        verticalalignment='top')

    starts: DefaultDict[float, Set[int]] = defaultdict(set)
    for task in instance:
        starts[task.ready].add(task.id)
    ticks_ready_time = sorted(starts.keys())
    labels_ready_time = [str(starts[x]) for x in ticks_ready_time]

    ax2 = ax.twiny()
    ax2.set_xlabel('Tasks with ready time')
    ax2.set_xlim(ax.get_xlim())
    ax2.set_xticks(ticks_ready_time)
    ax2.set_xticklabels(labels_ready_time)
Example #20
0
def draw_straight_arrows(ax: axes.Axes,
                         from_coord: types.Coord2D,
                         to_coord: types.Coord2D,
                         color: str,
                         active: bool,
                         effect: int,
                         do_annotations: bool,
                         no_head: bool = False) -> List[mpatches.Patch]:
    """Draw a straight arrow between two points, indicating an activity.

    :param ax: matplotlib axes on which to draw
    :param from_coord: point at the tail of the arrow (bottom left of it)
    :param to_coord: point at the head of the arrow (bottom left of it)
    :param color: color of the arrow when active
    :param active: whether arrow is active (are items arriving)
    :param effect: what value/no of items are being processed along the arrow
    :param do_annotations: whether to annotate the arrow with the no of items
        being processd
    :param no_head: whether do suppress a head to arrow
    """
    alpha = 0.3 if not active else 1
    color = 'k' if not active else color
    if no_head:
        a_style = '-'
        do_annotations = False
    else:
        a_style = mpatches.ArrowStyle("-|>", head_length=7, head_width=4)
    mid = 0.5
    mid_from_coord = [from_coord[0], from_coord[1] + mid]
    mid_to_coord = [to_coord[0], to_coord[1] + mid]
    p1 = mpatches.FancyArrowPatch(mid_from_coord,
                                  mid_to_coord,
                                  arrowstyle=a_style,
                                  alpha=alpha,
                                  color=color)
    ax.add_patch(p1)

    if do_annotations and active:
        msg = '{:.0f}'.format(abs(effect))
        text_coord = [(from_coord[0] + to_coord[0]) * .5 - 0.6,
                      to_coord[1] + 1.]
        ax.annotate(msg, from_coord, text_coord, size=14, color=color)

    return [p1]
def draw_polygon(ax: Axes, polygon: Polygon, size: int = size, ticks: int = ticks, font_size: int = font_size) -> None:
    """Plot a polygon to the current matplotlib figure."""
    max_x, min_x = ceil(max(p.x for p in polygon.points)), floor(min(p.x for p in polygon.points))
    max_y, min_y = ceil(max(p.y for p in polygon.points)), floor(min(p.y for p in polygon.points))
    size_x = max_x - min_x
    size_y = max_y - min_y
    ax.set_aspect('equal')
    ax.set_xlim(min_x - size_x * 0.05, max_x + size_x * 0.05)
    ax.set_ylim(min_y - size_y * 0.05, max_y + size_y * 0.05)
    ticks -= 1
    ax.xaxis.set_major_locator(ticker.MultipleLocator(base=round(size_x / ticks)))
    ax.yaxis.set_major_locator(ticker.MultipleLocator(base=round(size_y / ticks)))
    ax.grid(color='grey')

    polygon_points = list(polygon.points_as_tuples())

    plt_polygon = pyplot.Polygon(polygon_points, fill=None, color='0.25', linewidth=.5)
    ax.add_patch(plt_polygon)
    pyplot.plot(list([x[0] for x in polygon_points]), list([x[1] for x in polygon_points]),
                color='black', linestyle='None', marker='.', markersize=3)

    if isinstance(polygon, TriangulatedPolygon):
        edges = set()
        for triangle in polygon.triangles:
            for edge in triangle.edges:
                if (edge.a.index, edge.b.index) in edges:
                    # The edge was already plotted
                    continue
                if edge.a.index in ((edge.b.index - 1) % len(polygon), (edge.b.index + 1) % len(polygon)):
                    # The edge is a polygon edge, thus we ignore it
                    continue

                pyplot.plot([edge.a.x, edge.b.x], [edge.a.y, edge.b.y], color='0.5', linestyle='--', alpha=0.5)
                edges.add((edge.a.index, edge.b.index))
                edges.add((edge.b.index, edge.a.index))

    for i in range(0, len(polygon), 2):
        ax.annotate(str(i), xy=polygon_points[i],
                    xytext=(
                        polygon_points[i][0] + round(size_x / ticks) / 20,
                        polygon_points[i][1] + round(size_y / ticks) / 20),
                    fontsize=font_size, color='0.3', alpha=.8)
Example #22
0
def label_barh(ax: Axes, labels: List[AnyStr]):
    """"Labels the bars of a matplotlib Horizontal Bar Plot (plt.barh)

    todo: Adjust axis to fit labels in a smarter way

    Parameters
    ----------
    ax: Axes object containing the plot we wish to label
    labels: List containing the labels of each column
    """
    bars = ax.patches
    assert len(bars) == len(
        labels), "Number of labels is different from the number of bars"
    for bar, label in zip(bars, labels):
        x = bar.get_width()
        y = bar.get_y() + bar.get_height() / 2
        ax.annotate(label, xy=(x, y), ha="left", va="center", clip_on=True)
        # We increase the axis by 3% to fit the labels.
        x_min, x_max = ax.get_xlim()
        ax.set_xlim(x_min, 1.03 * x_max)
Example #23
0
def annotate_point(ax: Axes, x: Sequence, y: Sequence, t: Any) -> None:
    """

    :param ax:
    :param x:
    :param y:
    :param t:
    :return:
    """
    if ax is None:
        ax = pyplot.gca()
    ax.annotate(
        f"{t:.2f}",
        (x, y),
        textcoords="offset points",
        fontsize="xx-small",
        bbox=semi_opaque_round_tight_bbox,
        annotation_clip=True,  # see details https://github.com/matplotlib/matplotlib/issues/14354#issuecomment-523630316
        clip_on=True,
        **rt_ann_transform,
    )
Example #24
0
def _format_ax(ax: Axes,
               fmt: Format,
               log_scale: bool = False,
               limits: Optional[Tuple[float, float]] = None):
    if limits:
        ax.set_ylim(*limits)

    if log_scale:
        ax.set_yscale("log")

    m, M = ax.get_ylim()

    fmt = make_formater(fmt)

    for rect in ax.patches:
        h = rect.get_height()
        va = "center"
        if log_scale:
            log_m, log_M = log(m, 10), log(M, 10)
            log_h = log(h, 10)
            if (log_h - log_m) / (log_M - log_m) < 0.25:
                y = h
                va = "bottom"
            else:
                y = pow(10, (log_h + log_m) / 2)
        else:
            if (h - m) / (M - m) < 0.25:
                y = h
                va = "bottom"
            else:
                y = 0.6 * rect.get_height()
        x = rect.get_x() + rect.get_width() / 2
        ax.annotate(
            fmt(rect.get_height()),
            (x, y),
            ha="center",
            va=va,
            rotation=90,
        )
Example #25
0
def autoLabel(rects: container.BarContainer, ax: axes.Axes, fontSize: int):
    """ Attach a text label above each bar in rects, displaying its height.
    
    **Args:**
        rects(container.BarContainer):   The rectangles to bind to.
        ax(axes.Axes):                        The axis to bind to.
        fontSize(int):               The size of the font used.

    """

    for rect in rects:
        height = rect.get_height()
        # XYtext is the position on "top" of bar (x, y)
        ax.annotate('{:.2f}'.format(height),
                    xy=(rect.get_x() + rect.get_width() / 2, height),
                    xytext=(0, 5 * np.sign(height)),
                    textcoords="offset points",
                    fontsize=fontSize,
                    ha='center',
                    va='center_baseline')

    return
Example #26
0
def plot2D(
          ax: Axes,
          correlations: Correlations,
          atoms: Tuple[str],
          *,
          color: str = 'tab20',
          nolabels: bool = False,
          showlegend: bool = False,
          offset: int = 0) \
          -> Tuple[List,List]:
    '''Plots 2D spectra and slices for 3D spectra returns handles and annotations to be 
    used by the Slices3D class which uses them to update the figure when the mouse is scrolled.
    '''

    legend = {}
    handles = []
    text = []
    residue_colors = get_residue_colors(color)

    for sequence_number, residue_type, chemical_shifts in correlations:
        color = residue_colors[residue_type]
        handle = ax.plot(*chemical_shifts, 'o', c=color)[0]
        handles.append(handle)
        legend[residue_type] = handle
        if not nolabels:
            used_labels = set(t.get_text() for t in text)
            label = _check_label(f'{residue_type}{sequence_number + offset}',
                                 used_labels)
            text.append(ax.annotate(label, chemical_shifts))

    # Show the legend when showlegend argument is passed
    if showlegend:
        # Residues are added as they are encountered, not in sorted order
        sort_legend = {
            color: residue
            for residue, color in sorted(legend.items())
        }
        ax.legend(sort_legend.keys(), sort_legend.values())

    if not ax.xaxis_inverted():
        ax.invert_xaxis()
    if not ax.yaxis_inverted():
        ax.invert_yaxis()

    # Label axes
    ax.set_xlabel(AXIS_LABELS[atoms[0][0]])
    ax.set_ylabel(AXIS_LABELS[atoms[1][0]])

    return handles, text
Example #27
0
    def _plot_totals(self, total_barplot_ax: Axes,
                     orientation: Literal['top', 'right']):
        """
        Makes the bar plot for totals
        """
        params = self.plot_group_extra
        counts_df = params['counts_df']
        if self.categories_order is not None:
            counts_df = counts_df.loc[self.categories_order]
        if params['color'] is None:
            if f'{self.groupby}_colors' in self.adata.uns:
                color = self.adata.uns[f'{self.groupby}_colors']
            else:
                color = 'salmon'
        else:
            color = params['color']

        if orientation == 'top':
            counts_df.plot(
                kind="bar",
                color=color,
                position=0.5,
                ax=total_barplot_ax,
                edgecolor="black",
                width=0.65,
            )
            # add numbers to the top of the bars
            max_y = max([p.get_height() for p in total_barplot_ax.patches])

            for p in total_barplot_ax.patches:
                p.set_x(p.get_x() + 0.5)
                if p.get_height() >= 1000:
                    display_number = f'{np.round(p.get_height()/1000, decimals=1)}k'
                else:
                    display_number = np.round(p.get_height(), decimals=1)
                total_barplot_ax.annotate(
                    display_number,
                    (p.get_x() + p.get_width() / 2.0,
                     (p.get_height() + max_y * 0.05)),
                    ha="center",
                    va="top",
                    xytext=(0, 10),
                    fontsize="x-small",
                    textcoords="offset points",
                )
            # for k in total_barplot_ax.spines.keys():
            #     total_barplot_ax.spines[k].set_visible(False)
            total_barplot_ax.set_ylim(0, max_y * 1.4)

        elif orientation == 'right':
            counts_df.plot(
                kind="barh",
                color=color,
                position=-0.3,
                ax=total_barplot_ax,
                edgecolor="black",
                width=0.65,
            )

            # add numbers to the right of the bars
            max_x = max([p.get_width() for p in total_barplot_ax.patches])
            for p in total_barplot_ax.patches:
                if p.get_width() >= 1000:
                    display_number = f'{np.round(p.get_width()/1000, decimals=1)}k'
                else:
                    display_number = np.round(p.get_width(), decimals=1)
                total_barplot_ax.annotate(
                    display_number,
                    ((p.get_width()), p.get_y() + p.get_height()),
                    ha="center",
                    va="top",
                    xytext=(10, 10),
                    fontsize="x-small",
                    textcoords="offset points",
                )
            total_barplot_ax.set_xlim(0, max_x * 1.4)

        total_barplot_ax.grid(False)
        total_barplot_ax.axis("off")
def plot_station_positions(directions_file_path: Path, stations: list, ax: Axes, grid_config: GridConfig=default_domains.bc_mh_044,
                           save_upstream_boundaries_to_shp=False):


    with Dataset(str(directions_file_path)) as ds:
        flow_dirs = ds.variables["flow_direction_value"][:]
        flow_acc_area = ds.variables["accumulation_area"][:]
        lons_2d, lats_2d = [ds.variables[k][:] for k in ["lon", "lat"]]



    basemap, reg_of_interest = grid_config.get_basemap_using_shape_with_polygons_of_interest(lons_2d, lats_2d,
                                                                                             shp_path=default_domains.MH_BASINS_PATH,
                                                                                             resolution="i")


    cell_manager = CellManager(flow_dirs, lons2d=lons_2d, lats2d=lats_2d, accumulation_area_km2=flow_acc_area)
    station_to_model_point = cell_manager.get_model_points_for_stations(station_list=stations, nneighbours=8)

    #####
    xx, yy = basemap(lons_2d, lats_2d)
    upstream_edges = cell_manager.get_upstream_polygons_for_points(
        model_point_list=list(station_to_model_point.values()), xx=xx, yy=yy)

    upstream_edges_latlon = cell_manager.get_upstream_polygons_for_points(
        model_point_list=list(station_to_model_point.values()), xx=lons_2d, yy=lats_2d)




    plot_utils.draw_upstream_area_bounds(ax, upstream_edges=upstream_edges, color="r", linewidth=0.6)

    if save_upstream_boundaries_to_shp:
        plot_utils.save_to_shape_file(upstream_edges_latlon, folder_path="mh/engage_report/upstream_stations_areas/mh_{}".format(grid_config.dx), in_proj=None)


    basemap.drawrivers(linewidth=0.2)
    basemap.drawstates(linewidth=0.1)
    basemap.drawcountries(linewidth=0.1)
    basemap.drawcoastlines(linewidth=0.2)


    pos_ids, lons_pos, lats_pos = [], [], []
    pos_labels = []
    legend_lines = []
    for i, (s, mp) in enumerate(sorted(station_to_model_point.items(), key=lambda p: p[0].latitude, reverse=True), start=1):
        pos_ids.append(s.id)
        pos_labels.append(i)
        lons_pos.append(mp.longitude)
        lats_pos.append(mp.latitude)

        legend_lines.append("{}: {}".format(i, s.id))

    xm, ym = basemap(lons_pos, lats_pos)
    ax.scatter(xm, ym, c="g", s=20)
    for txt, x1, y1, pos_label in zip(pos_ids, xm, ym, pos_labels):
        ax.annotate(pos_label, xy=(x1, y1))



    at = AnchoredText("\n".join(legend_lines), prop=dict(size=8), frameon=True, loc=1)

    at.patch.set_boxstyle("round,pad=0.,rounding_size=0.2")
    ax.add_artist(at)
    def show_agent_opinions(
        self,
        t=-1,
        direction=True,
        sort=False,
        ax: Axes = None,
        fig: Figure = None,
        colorbar: bool = True,
        title: str = "Agent opinions",
        show_middle=True,
        **kwargs,
    ) -> Tuple[Figure, Axes]:
        cmap = kwargs.pop("cmap", OPINIONS_CMAP)

        idx = get_time_point_idx(self.sn.result.t, t)
        opinions = self.sn.result.y[:, idx]
        agents = np.arange(self.sn.N)
        if not direction:
            # only magnitude
            opinions = np.abs(opinions)

        if np.iterable(sort) or sort:

            if isinstance(sort, np.ndarray):
                # sort passed as indices
                ind = sort
            else:
                logger.warning(
                    "sorting opinions for `show_agent_opinions` means agent indices are jumbled"
                )
                # sort by opinion
                ind = np.argsort(opinions)
            opinions = opinions[ind]

        v = self._get_equal_opinion_limits()
        sm = ScalarMappable(norm=Normalize(*v), cmap=cmap)
        color = sm.to_rgba(opinions)

        ax.barh(
            agents,
            opinions,
            color=color,
            edgecolor="None",
            linewidth=0,  # remove bar borders
            height=1,  # per agent
            **kwargs,
        )
        ax.axvline(x=0, ls="-", color="k", alpha=0.5, lw=1)
        if (np.iterable(sort) or sort) and show_middle:
            min_idx = np.argmin(np.abs(opinions))
            ax.hlines(
                y=min_idx,
                xmin=v[0],
                xmax=v[1],
                ls="--",
                color="k",
                alpha=0.5,
                lw=1,
            )
            ax.annotate(
                f"{min_idx}",
                xy=(np.min(opinions), min_idx),
                fontsize="small",
                color="k",
                alpha=0.5,
                va="bottom",
                ha="left",
            )
        if colorbar:
            # create colorbar axes without stealing from main ax
            cbar = colorbar_inset(sm,
                                  "outer bottom",
                                  size="5%",
                                  pad=0.01,
                                  ax=ax)
            sns.despine(ax=ax, bottom=True)
            ax.tick_params(axis="x", bottom=False, labelbottom=False)
            cbar.set_label(OPINION_SYMBOL)

        ax.set_ylim(0, self.sn.N)
        ax.set_xlim(*v)
        if not colorbar:
            # xlabel not part of colorbar
            ax.set_xlabel(OPINION_SYMBOL)
        ax.set_ylabel("Agent $i$")
        ax.yaxis.set_major_locator(MaxNLocator(5))
        if title:
            ax.set_title(title)
        return fig, ax
Example #30
0
class Projector(object):
    dpi = 100  # make sure that figures can be displayed pixel-precise

    css = '''
    body {
      margin:0px;
      background-color: #FFFFFF;
    }
    .panel {
      background-color: #000000;
      overflow: hidden;
    }
    .bk.frame {
      background-color: #FFFFFF;
      color: #FFFFFF;
    }
    .bk.legend {
      background-color: #16425B;
      color: #CCCCCC;
    }
    .bk.hot {
      background-color: #2896A5;
      color: #CCCCCC;
    }
    .bk.profile {
      background-color: #40C1C7;
      color: #CCCCCC;
    }
    .bk.colorbar {
      background-color: #2896A5;
      color: #CCCCCC;
    '''

    def __init__(self, calibprojector: str = None, use_panel: bool = True, p_width=1280, p_height=800,
                 show_colorbar: bool = False, position_colorbar: str = "vertical",
                 show_legend: bool = False, show_hot: bool = False,
                 show_profile: bool = False, ):
        """
        Args:
            calibprojector:
            use_panel: Automatically display
            p_width: x native resolution of the projector
            p_height: y native resolution of the projector
            show_colorbar:
            position_colorbar: "vertical" or "horizontal"
            show_legend:
            show_hot:
            show_profile
        """
        self.version = '2.2.p'
        self.ax = None
        self.figure = None
        self.json_filename = calibprojector

        # flags
        self.enable_legend = show_legend
        self.enable_hot = show_hot
        self.enable_colorbar = show_colorbar
        self.pos_colorbar = position_colorbar
        self._ratio = 10
        self.enable_profile = show_profile

        if calibprojector is None:
            self.p_width = p_width
            self.p_height = p_height
            self.p_frame_top = 50
            self.p_frame_left = 50
            self.p_frame_width = 700
            self.p_frame_height = 500
            # Colorbar
            self.col_top = 0
            self.col_left = 0 if self.pos_colorbar == "vertical" else self.p_frame_left
            self.col_width = self.p_frame_width if self.pos_colorbar == "horizontal" \
                                           else round(self.p_frame_width / self._ratio)
            self.col_height = self.p_frame_height if self.pos_colorbar == "vertical" \
                                           else round(self.p_frame_height / self._ratio)

            self.leg_width = round(self.p_frame_width/4)
            self.leg_height = round(self.p_frame_width/3)
            self.leg_top = 0
            self.leg_left = 0
        else:
            self.load_json(calibprojector)

        self._size_label_cbar = 15
        self._label = None

        # panel components (panes)
        self.panel = None
        self.frame = None
        self.legend = None
        self.hot = None
        self.profile = None
        self.colorbar = None
        self.sidebar = None
        # This is to solve issue #3. Give 0.01 ms to each Text from ax.arists to be plotted
        self._target_time = 0.00
        self._paused_time = None

        self.create_panel()
        if use_panel is True:
            self.start_server()

    @property
    def _dim_label_ax(self):
        return [0, 0, 2, 0.1] if self.pos_colorbar == "horizontal" else [0, 0, 0.1, 2]

    def create_panel(self):
        """ Initializes the matplotlib figure and empty axes according to projector calibration.

        The figure can be accessed by its attribute. It will be 'deactivated' to prevent random apperance in notebooks.
        """
        pn.extension(raw_css=[self.css])
        # Create a panel object and serve it within an external bokeh browser that will be opened in a separate window

        # In this special case, a "tight" layout would actually add again white space to the plt canvas,
        # which was already cropped by specifying limits to the axis

        self.figure = Figure(figsize=(self.p_frame_width / self.dpi, self.p_frame_height / self.dpi),
                             dpi=self.dpi)
        self.ax = Axes(self.figure, [0., 0., 1., 1.])
        self.figure.add_axes(self.ax)
        self.ax.set_axis_off()
        self.ax.get_xaxis().set_visible(False)
        self.ax.get_yaxis().set_visible(False)

        self.frame = pn.pane.Matplotlib(self.figure,
                                        width=self.p_frame_width,
                                        height=self.p_frame_height,
                                        margin=[self.p_frame_top, 0, 0, self.p_frame_left],
                                        tight=False,
                                        dpi=self.dpi,
                                        css_classes=['frame']
                                        )
        plt.close(self.figure)  # close figure to prevent inline display

        if self.enable_colorbar:
            self.create_colorbar()

        if self.enable_legend:
            self.create_legend()

        if self.enable_hot:
            self.create_hot()

        if self.enable_profile:
            self.create_profile()

        # Combine panel and deploy bokeh server
        if self.pos_colorbar == "vertical":
            self.sidebar = pn.Column(self.colorbar, self.legend, self.hot, self.profile,
                                     margin=[self.p_frame_top, 0, 0, 0],
                                     )

            self.panel = pn.Row(pn.Column(self.frame, None),
                                self.sidebar,
                                width=self.p_width,
                                height=self.p_height,
                                sizing_mode='fixed',
                                css_classes=['panel']
                                )
        elif self.pos_colorbar == "horizontal":
            self.sidebar = pn.Column(self.legend, self.hot, self.profile,
                                     margin=[self.p_frame_top, 0, 0, 0],
                                     )
            self.panel = pn.Row(pn.Column(self.frame, self.colorbar),
                                self.sidebar,
                                width=self.p_width,
                                height=self.p_height,
                                sizing_mode='fixed',
                                css_classes=['panel']
                                )
        else:
            raise AttributeError

        return True

    def create_colorbar(self):
        empty_fig_bg_cb = Figure()
        self.colorbar = pn.pane.Matplotlib(empty_fig_bg_cb,
                                           width= self.col_width,
                                           height= self.col_height,
                                           margin=[self.col_top, 0, 0, self.col_left],
                                           dpi=self.dpi*2,
                                           css_classes=['colorbar'],
                                           tight=True)

    def create_legend(self):
        empty_fig_bg_ld = Figure()
        self.legend = pn.pane.Matplotlib(empty_fig_bg_ld,
                                           width=self.leg_width,
                                           height=self.leg_height,
                                           margin=[self.leg_top, 0, 0, self.leg_left],
                                           dpi=self.dpi*2,
                                           css_classes=['legend'],
                                           tight=True)

    def create_hot(self):
        self.hot = pn.Column("### Hot area",
                             width=100,
                             height=100,
                             margin=[0, 0, 0, 0],
                             css_classes=['hot']
                             )

    def create_profile(self):
        self.profile = pn.Column("### Profile",
                                 width=100,
                                 height=100,
                                 margin=[0, 0, 0, 0],
                                 css_classes=['profile']
                                 )

    def set_colorbar(self, vmin: float, vmax: float, cmap="viridis", norm=None, label: str = None):
        """
        Create a colorbar and display the figure in the colorbar widget
        Args:
            vmin: Minimun value of the colorbar
            vmax: Maximum value of the colorbar
            cmap: Colormap of the colorbar
            norm: (optionl) Normalization, in case that not, this is internally managed
            label: Text to display as label in the colorbar
        Returns:

        """
        if self.colorbar is not None:
            if isinstance(cmap, str):
                cmap = plt.get_cmap(cmap)
            label = label if label is not None else self._label
            cb = Figure()
            ax = Axes(cb, self._dim_label_ax)
            cb.add_axes(ax)
            norm = matplotlib.colors.Normalize(vmin=vmin, vmax=vmax) if norm is None else norm
            cb1 = matplotlib.colorbar.ColorbarBase(ax, cmap=cmap, norm=norm, orientation=self.pos_colorbar)
            cb1.set_label(label, size=self._size_label_cbar) if label is not None else None
            cb1.ax.tick_params(labelsize=self._size_label_cbar)
            self.colorbar.object = cb
            self.colorbar.param.trigger("object")

    def set_legend(self, handles=None, labels=None, *args):
        """
        Create a legend with the information of frame with the ax.get_legend_handles_labels().
        External handles and labels can be used
        Returns:

        """
        if self.legend is not None:
            ld = Figure()
            if handles is None and labels is None:
                if args == ():
                    ld.legend(*self.ax.get_legend_handles_labels())
                else:
                    ld.legend(*args)
            else:
                ld.legend(labels=labels,
                          handles=handles
                          )
            self.legend.object = ld
            self.legend.param.trigger("object")


    def write_text(self, text: str = "cgre-aachen / open_AR_Sandbox"):
        """
        Display a custom text to be displayed in the middle of the sandbox
        Args:
            text: message to display
        Returns:

        """
        self.ax.texts = []
        x = (self.ax.get_xlim()[1] - self.ax.get_xlim()[0])/2
        y = (self.ax.get_ylim()[1] - self.ax.get_ylim()[0])/2
        self.ax.annotate(text, (x, y), zorder=1000000, xycoords="data", fontsize=18, ha='center',
                         va='top', wrap=True)
        self.trigger()

    def _replace_figure_with_pyplot(self):
        """Deprecated!! workaround to fix bug of no dpi"""
        figure = plt.figure(figsize=(self.p_frame_width / self.dpi, self.p_frame_height / self.dpi),
                            dpi=self.dpi)
        ax = plt.Axes(figure, [0., 0., 1., 1.])
        figure.add_axes(ax)
        plt.close(figure)  # close figure to prevent inline display
        ax.set_axis_off()
        self.figure = figure
        self.ax = ax
        self.frame.object = figure
        self.trigger()

    def start_server(self):
        """
        Display the panel object in a new browser window
        Returns:

        """
        # Check for instances and close them?
        self.panel.show(threaded=False)  # , title="Sandbox frame!")#, port = 4242, use_reloader = False)
        # TODO: check how can check if the port exist/open and overwrite it
        logger.info('Projector initialized and server started.\n'
              'Please position the browser window accordingly and enter fullscreen!')
        return True

    def clear_axes(self):
        """
        Empty the axes of the current figure and trigger the update of the figure in the panel.
        Returns:

        """
        self.ax.cla()
        self.trigger()
        return True

    def _clock(self):
        """
        To to be sure that panel have enough time to display the figure he want. Solves issue #3
        """
        ctext = [isinstance(text, matplotlib.text.Text) for text in self.ax.texts]
        coll = [isinstance(coll, matplotlib.collections.PathCollection) for coll in self.ax.collections]
        if True in ctext or True in coll:
            sec = (len(coll)+len(ctext))*self._target_time  # Give 0.005 ms to each Text from contours to be plotted
            self._paused_time = sec
            plt.pause(sec)
        else:
            self._paused_time = None

    def trigger(self):
        """
        Update the panel figure if modified 
        Returns:

        """

        # self.figure.canvas.draw_idle()  # TODO: do we need this or not?
        self.frame.param.trigger('object')
        self._clock()
        return True

    def save_json(self, file: str = 'projector_calibration.json'):
        """
        Saves the current state of the projector in a .JSON calibration file
        Args:
            file: address to save the calibration

        Returns:

        """
        with open(file, "w") as calibration_json:
            data = {'version': self.version,
                    'p_width': self.p_width,
                    'p_height': self.p_height,
                    'p_frame_top': self.p_frame_top,
                    'p_frame_left': self.p_frame_left,
                    'p_frame_width': self.p_frame_width,
                    'p_frame_height': self.p_frame_height,
                    'col_top': self.col_top,
                    'col_left': self.col_left,
                    'col_width': self.col_width,
                    'col_height': self.col_height,
                    'pos_colorbar': self.pos_colorbar,
                    'leg_top': self.leg_top,
                    'leg_left': self.leg_left,
                    'leg_width': self.leg_width,
                    'leg_height': self.leg_height,
                    }
            json.dump(data, calibration_json)
        logger.info('JSON configuration file saved: %s' % str(file))
        return True

    def load_json(self, file: str):
        """
        Load a calibration file (.JSON format) and actualizes the panel parameters
        Args:
            file: address of the calibration to load

        Returns:

        """
        def json_load(dict_data):
            if dict_data['version'] == self.version:
                self.p_width = dict_data.get('p_width')
                self.p_height = dict_data.get('p_height')
                self.p_frame_top = dict_data.get('p_frame_top')
                self.p_frame_left = dict_data.get('p_frame_left')
                self.p_frame_width = dict_data.get('p_frame_width')
                self.p_frame_height = dict_data.get('p_frame_height')
                self.col_top = dict_data.get('col_top')
                self.col_left = dict_data.get('col_left')
                self.col_width = dict_data.get('col_width')
                self.col_height = dict_data.get('col_height')
                self.pos_colorbar = dict_data.get('pos_colorbar')
                self.leg_top = dict_data.get('leg_top')
                self.leg_left = dict_data.get('leg_left')
                self.leg_width = dict_data.get('leg_width')
                self.leg_height =dict_data.get('leg_height')

                logger.info("JSON configuration loaded for projector")
            else:
                logger.warning("JSON configuration incompatible." +
                      "\nPlease select a valid calibration file or start a new calibration!")
        if os.path.isfile(file):
            with open(file) as calibration_json:
                data = json.load(calibration_json)
                json_load(data)
        else:
            data = json.loads(file)
            json_load(data)
        return True

    def calibrate_projector(self):
        self._create_widgets()
        panel = pn.Column("### Projector dashboard arrangement",
                          self._widget_p_frame_top,
                          self._widget_p_frame_left,
                          self._widget_p_frame_width,
                          self._widget_p_frame_height,
                          '<b>Save file<b>',
                          self._widget_json_filename,
                          self._widget_json_save
                          )
        return panel

    def show_widgets_sidepanels(self):
        tabs = pn.Tabs(("Colorbar", self.show_widget_colorbar()),
                       ("Legend", self.show_widget_legend()))
        return tabs

    def show_widget_colorbar(self):
        self._create_widgets_colorbar()
        panel1 = pn.Column("### Colorbar",
                           self._widgets_show_colorbar,
                           self._widget_label,
                           self._widget_refresh_col
                          )
        panel2 = pn.Column(self._widget_colorbar_ori,
                           self._widget_top_colorbar,
                           self._widget_left_colorbar,
                           self._widget_width_colorbar,
                           self._widget_height_colorbar,
                           self._widget_col_background)
        return pn.Row(panel1, panel2)

    def show_widget_legend(self):
        self._create_widgets_legend()
        panel3 = pn.Column("### Legend",
                           self._widgets_show_legend,
                           self._widget_refresh_leg)
        panel4 = pn.Column(self._widget_top_legend,
                           self._widget_left_legend,
                           self._widget_width_legend,
                           self._widget_height_legend,
                           self._widget_leg_background)
        return pn.Row(panel3, panel4)

    def _create_widgets(self):
        # projector widgets and links
        self._widget_p_frame_top = pn.widgets.IntSlider(name='Main frame top margin',
                                                        value=self.p_frame_top,
                                                        start=0,
                                                        end=self.p_height - 20)
        self._widget_p_frame_top.link(self.frame, callbacks={'value': self._callback_p_frame_top})

        self._widget_p_frame_left = pn.widgets.IntSlider(name='Main frame left margin',
                                                         value=self.p_frame_left,
                                                         start=0,
                                                         end=self.p_width - 20)
        self._widget_p_frame_left.link(self.frame, callbacks={'value': self._callback_p_frame_left})

        self._widget_p_frame_width = pn.widgets.IntSlider(name='Main frame width',
                                                          value=self.p_frame_width,
                                                          start=10,
                                                          end=self.p_width)
        self._widget_p_frame_width.link(self.frame, callbacks={'value': self._callback_p_frame_width})

        self._widget_p_frame_height = pn.widgets.IntSlider(name='Main frame height',
                                                           value=self.p_frame_height,
                                                           start=10,
                                                           end=self.p_height)
        self._widget_p_frame_height.link(self.frame, callbacks={'value': self._callback_p_frame_height})

        self._widget_json_filename = pn.widgets.TextInput(name='Choose a calibration filename:')
        self._widget_json_filename.param.watch(self._callback_json_filename, 'value', onlychanged=False)
        self._widget_json_filename.value = _calibration_dir + 'my_projector_calibration.json'

        self._widget_json_save = pn.widgets.Button(name='Save calibration')
        self._widget_json_save.param.watch(self._callback_json_save, 'clicks', onlychanged=False)

        return True

    def _create_widgets_colorbar(self):
        self._widget_colorbar_ori = pn.widgets.Select(name='Orientation Colorbar',
                                                    options=["vertical", "horizontal"],
                                                   value=self.pos_colorbar)
        self._widget_colorbar_ori.param.watch(self._callback_colorbar_ori, 'value', onlychanged=False)

        self._widgets_show_colorbar = pn.widgets.Checkbox(name='Show colorbar',
                                                          value=self.enable_colorbar)
        self._widgets_show_colorbar.param.watch(self._callback_enable_colorbar, 'value',
                                                onlychanged=False)

        self._widget_top_colorbar = pn.widgets.IntSlider(name='Top space',
                                                        value=self.col_top,
                                                        start=0,
                                                        end=self.p_height - 20)
        self._widget_top_colorbar.param.watch(self._callback_top_colorbar, 'value', onlychanged=False)

        self._widget_left_colorbar = pn.widgets.IntSlider(name='Left space',
                                                         value=self.col_left,
                                                         start=0,
                                                         end=self.p_width - 20)
        self._widget_left_colorbar.param.watch(self._callback_left_colorbar, 'value', onlychanged=False)

        self._widget_width_colorbar = pn.widgets.IntSlider(name='Width Colorbar',
                                                          value=self.col_width,
                                                          start=1,
                                                          end=self.p_width)
        self._widget_width_colorbar.param.watch(self._callback_width_colorbar, 'value', onlychanged=False)

        self._widget_height_colorbar = pn.widgets.IntSlider(name='Height colorbar',
                                                           value=self.col_height,
                                                           start=1,
                                                           end=self.p_height)
        self._widget_height_colorbar.param.watch(self._callback_height_colorbar, 'value', onlychanged=False)

        self._widget_label = pn.widgets.TextInput(name='Label of colorbar')
        self._widget_label.param.watch(self._callback_label, 'value', onlychanged=False)

        self._widget_refresh_col = pn.widgets.Button(name="Refresh label",
                                                    button_type="success")
        self._widget_refresh_col.param.watch(self._callback_refresh, 'clicks',
                                            onlychanged=False)

        self._widget_col_background = pn.widgets.ColorPicker(name='Color background colorbar', value="#2896A5")
        self._widget_col_background.param.watch(self._callback_col_background, 'value', onlychanged=False)

    def _create_widgets_legend(self):
        self._widgets_show_legend = pn.widgets.Checkbox(name='Show legend',
                                                        value=self.enable_legend)
        self._widgets_show_legend.param.watch(self._callback_enable_legend, 'value',
                                                onlychanged=False)

        self._widget_top_legend = pn.widgets.IntSlider(name='Top space',
                                                        value=self.leg_top,
                                                        start=0,
                                                        end=self.p_height - 20)
        self._widget_top_legend.param.watch(self._callback_top_legend, 'value', onlychanged=False)

        self._widget_left_legend = pn.widgets.IntSlider(name='Left space',
                                                         value=self.leg_left,
                                                         start=0,
                                                         end=self.p_width - 20)
        self._widget_left_legend.param.watch(self._callback_left_legend, 'value', onlychanged=False)

        self._widget_width_legend = pn.widgets.IntSlider(name='Width Legend',
                                                          value=self.leg_width,
                                                          start=1,
                                                          end=self.p_width)
        self._widget_width_legend.param.watch(self._callback_width_legend, 'value', onlychanged=False)

        self._widget_height_legend = pn.widgets.IntSlider(name='Height Legend',
                                                           value=self.leg_height,
                                                           start=1,
                                                           end=self.p_height)
        self._widget_height_legend.param.watch(self._callback_height_legend, 'value', onlychanged=False)

        self._widget_refresh_leg = pn.widgets.Button(name="Refresh legend",
                                                    button_type="success")
        self._widget_refresh_leg.param.watch(self._callback_refresh_leg, 'clicks',
                                            onlychanged=False)

        self._widget_leg_background = pn.widgets.ColorPicker(name='Color background colorbar', value="#16425B")
        self._widget_leg_background.param.watch(self._callback_leg_background, 'value', onlychanged=False)

    def _callback_label(self, event):
        self._label = event.new if event.new != "" else None

    def _callback_refresh(self, event):
        self.set_colorbar(0, 1, label=self._label)

    def _callback_refresh_leg(self, event):
        self.set_legend()

    def _callback_enable_colorbar(self, event):
        self.enable_colorbar = event.new
        self.set_colorbar_widget()

    def _callback_enable_legend(self, event):
        self.enable_legend = event.new
        if self.enable_legend:
            self.create_legend()
            self.sidebar.insert(1, self.legend)
        else:
            if self.legend is not None:
                self.sidebar.remove(self.legend) if self.legend in self.sidebar else None

    def set_colorbar_widget(self):
        if self.colorbar is not None:
            for pa in self.panel:
                if self.colorbar in pa:
                    pa.remove(self.colorbar)
                    break
        if self.enable_colorbar:
            if self.pos_colorbar == "horizontal":
                self.create_colorbar()
                self.colorbar.margin = [0, 0, 0, self.p_frame_left]
                self.panel[0].insert(1, self.colorbar)
            elif self.pos_colorbar == "vertical":
                self.create_colorbar()
                self.sidebar.insert(0, self.colorbar)
            self._widget_height_colorbar.value = self.col_height = self.p_frame_height if self.pos_colorbar == "vertical" \
                else round(self.p_frame_height / self._ratio)
            self._widget_width_colorbar.value = self.col_width = self.p_frame_width if self.pos_colorbar == "horizontal" \
                                           else round(self.p_frame_width / self._ratio)
            self._widget_left_colorbar.value = self.col_left = 0 if self.pos_colorbar == "vertical" else self.p_frame_left
            self._widget_top_colorbar.value = self.col_top = 0

    def _callback_colorbar_ori(self, event):
        self.pos_colorbar = event.new
        self.set_colorbar_widget()

    def _callback_top_colorbar(self, event):
        self.colorbar.margin[0] = event.new
        self.colorbar.param.trigger('object')

    def _callback_left_colorbar(self, event):
        self.colorbar.margin[-1] = event.new
        self.colorbar.param.trigger('object')

    def _callback_width_colorbar(self, event):
        self.colorbar.width = event.new
        self.colorbar.param.trigger('object')

    def _callback_height_colorbar(self, event):
        self.colorbar.height = event.new
        self.colorbar.param.trigger('object')

    def _callback_top_legend(self, event):
        self.leg_top = event.new
        self.legend.margin[0] = event.new
        self.legend.param.trigger('object')

    def _callback_left_legend(self, event):
        self.leg_left = event.new
        self.legend.margin[-1] = event.new
        self.legend.param.trigger('object')

    def _callback_width_legend(self, event):
        self.leg_width = event.new
        self.legend.width = event.new
        self.legend.param.trigger('object')

    def _callback_height_legend(self, event):
        self.leg_height = event.new
        self.legend.height = event.new
        self.legend.param.trigger('object')

    def _callback_p_frame_top(self, target, event):
        self.p_frame_top = event.new
        m = target.margin
        n = event.new
        # just changing single indices does not trigger updating of pane
        target.margin = [n, m[1], m[2], m[3]]

    def _callback_p_frame_left(self, target, event):
        self.p_frame_left = event.new
        m = target.margin
        n = event.new
        target.margin = [m[0], m[1], m[2], n]

    def _callback_p_frame_width(self, target, event):
        self.p_frame_width = event.new
        target.width = event.new
        target.param.trigger('object')

    def _callback_p_frame_height(self, target, event):
        self.p_frame_height = event.new
        target.height = event.new
        target.param.trigger('object')

    def _callback_json_filename(self, event):
        self.json_filename = event.new

    def _callback_json_save(self, event):
        if self.json_filename is not None:
            self.save_json(file=self.json_filename)

    def _callback_col_background(self, event):
        self.colorbar.background = event.new

    def _callback_leg_background(self, event):
        self.legend.background = event.new