def plot_single_decomposition_runtime(
            self, decomposition_runtime_metric_specification,
            decomposition_runtime_axes_specification):

        base_filename = "{}__by__{}".format(
            decomposition_runtime_metric_specification["filename"],
            decomposition_runtime_axes_specification["filename"])
        output_path, filename = self._construct_output_path_and_filename(
            base_filename)

        logger.debug("output_path is {};\t filename is {}".format(
            output_path, filename))

        if not self.overwrite_existing_files and os.path.exists(filename):
            logger.info(
                "Skipping generation of {} as this file already exists".format(
                    filename))
            return

        values_dict = self._get_values_dict(
            base_filename, decomposition_runtime_axes_specification,
            decomposition_runtime_metric_specification)

        fig, ax = plt.subplots(figsize=(FIGSIZE[0] - 0.75, FIGSIZE[1]))
        if self.paper_mode:
            print decomposition_runtime_axes_specification
            ax.set_title(
                decomposition_runtime_axes_specification['plot_title'],
                fontsize=PLOT_TITLE_FONT_SIZE)
        else:
            title = decomposition_runtime_metric_specification['name'] + "\n"
            title += self._get_sol_count_string(values_dict)
            ax.set_title(title, fontsize=PLOT_TITLE_FONT_SIZE)

        sorted_keys = sorted(values_dict.keys())
        percentiles = decomposition_runtime_metric_specification["percentiles"]
        linewidths = decomposition_runtime_metric_specification.get(
            "linewidths", [0.5] * len(percentiles))
        color_values = decomposition_runtime_metric_specification.get(
            "color_values")

        lines = np.zeros((len(percentiles), len(sorted_keys)))
        for i, key in enumerate(sorted_keys):
            lines[:, i] = np.percentile(values_dict[key], percentiles)

        t_start = time()
        handles = []
        median_legend_handle = None
        for i, p in enumerate(percentiles):
            sorted_keys = sorted(values_dict.keys())
            if p == 50:
                sorted_keys[0] += 0.15
                sorted_keys[-1] -= 0.15
            line = ax.plot(sorted_keys,
                           lines[i][:],
                           linewidth=linewidths[i],
                           color="k",
                           label="median" if p == 50 else None,
                           solid_capstyle='round')

            line[0].set_path_effects([
                path_effects.Stroke(linewidth=linewidths[i] + 0.5,
                                    foreground='w'),
                path_effects.Normal()
            ])

            if i < len(percentiles) - 1:
                if color_values:
                    c = plt.cm.inferno(color_values[i])
                else:
                    c = plt.cm.inferno(0.01 * p)
                if p == 50:
                    median_legend_handle = line[0]
                    handles[-1].set_label("{}% - {}%".format(
                        percentiles[i - 1], percentiles[i + 1]))
                else:
                    handles.append(
                        mpatches.Patch(color=c,
                                       label="{}% - {}%".format(
                                           p, percentiles[i + 1])))
                ax.fill_between(
                    sorted_keys,
                    lines[i][:],
                    lines[i + 1][:],
                    facecolor=matplotlib.colors.to_rgba(
                        c, 0.8),  # apply alpha only to facecolor
                )
        handles.reverse()
        #if median_legend_handle:
        #    handles.append(median_legend_handle)

        leg = ax.legend(handles=handles,
                        fontsize=LEGEND_LABEL_FONT_SIZE - 2,
                        loc=2,
                        title="percentiles",
                        handletextpad=.35,
                        borderaxespad=0.175,
                        borderpad=0.2,
                        handlelength=1.75)

        plt.setp(leg.get_title(), fontsize=LEGEND_TITLE_FONT_SIZE - 1)
        plt.gca().add_artist(leg)

        sec_leg = ax.legend(handles=[median_legend_handle],
                            fontsize=LEGEND_LABEL_FONT_SIZE - 1,
                            loc=1,
                            title="",
                            handletextpad=.35,
                            borderaxespad=0.175,
                            borderpad=0.2,
                            handlelength=1.75,
                            frameon=True)

        print "Plotting:", time() - t_start, "seconds"

        if "x_axis_ticks" in decomposition_runtime_axes_specification:
            ax.set_xticks(
                decomposition_runtime_axes_specification["x_axis_ticks"])
            ax.set_xticklabels(
                map(str,
                    decomposition_runtime_axes_specification["x_axis_ticks"]))

        if decomposition_runtime_metric_specification.get(
                "use_log_scale", False):
            plt.yscale('log')
            plt.autoscale(True)

        if "xlim" in decomposition_runtime_axes_specification:
            ax.set_xlim(decomposition_runtime_axes_specification['xlim'][0],
                        decomposition_runtime_axes_specification['xlim'][1])

        ax.tick_params(axis="x", **DEFAULT_MAJOR_TICK_PARAMS)
        ax.tick_params(axis="y", **DEFAULT_MAJOR_TICK_PARAMS)
        ax.tick_params(axis="x", **DEFAULT_MINOR_TICK_PARAMS)
        ax.tick_params(axis="y", **DEFAULT_MINOR_TICK_PARAMS)

        for tick in ax.xaxis.get_major_ticks():
            tick.label.set_fontsize(TICK_LABEL_FONT_SIZE)
        for tick in ax.yaxis.get_major_ticks():
            tick.label.set_fontsize(TICK_LABEL_FONT_SIZE)

        #plt.xlim(-5,41)

        ax.grid(
        )  # to change grid style parameters, modify the BOXPLOT_..._TICK_PARAMS dicts defined at the top of the file

        ax.set_xlabel(decomposition_runtime_axes_specification['x_axis_title'],
                      fontsize=X_AXIS_LABEL_FONT_SIZE)
        ax.set_ylabel(
            decomposition_runtime_metric_specification['y_axis_title'],
            fontsize=Y_AXIS_LABEL_FONT_SIZE)

        self._show_and_or_save_plots(output_path, filename)
Beispiel #2
0
def plot_img_boxes(img,
                   boxes,
                   classes,
                   extras=None,
                   plt_ax=None,
                   figsize=None,
                   class_names=None,
                   real_pixels=False,
                   box_centered=True):
    if not plt_ax:
        _, plt_ax = plt.subplots(figsize=figsize)
    colors = np.array([[1, 0, 1], [0, 0, 1], [0, 1, 1], [0, 1, 0], [1, 1, 0],
                       [1, 0, 0]])

    if type(img) == PIL.Image.Image:
        width = img.width
        height = img.height
    elif type(img) in [torch.Tensor, np.ndarray]:
        # if len(img.shape)>3: img = img[0]
        if type(img) == torch.Tensor:
            img = img.clone().cpu().numpy()
        width = img.shape[2]
        height = img.shape[1]
        img = img.transpose(1, 2, 0)
        if (img < 1.01).all() and (img >= 0).all():
            img = img.clip(
                0, 1
            )  # avoid "Clipping input data to the valid range" warning after tensor roundings
    else:
        raise (f"Unkown type for image: {type(img)}")

    if len(boxes) > 0 and not real_pixels:
        boxes[:, 0] *= width
        boxes[:, 2] *= width
        boxes[:, 1] *= height
        boxes[:, 3] *= height

    for i in range(len(boxes)):
        b, class_id = boxes[i], classes[i]
        if b[0] == 0:
            break

        color = colors[class_id % len(colors)]

        if box_centered:
            x, y = (b[0] - b[2] / 2, b[1] - b[3] / 2)
            w, h = (b[2], b[3])
        else:
            x, y = b[0], b[1]
            w, h = b[2], b[3]

        patch = plt_ax.add_patch(
            patches.Rectangle([x, y], w, h, fill=False, edgecolor=color, lw=2))
        patch.set_path_effects([
            patheffects.Stroke(linewidth=1, foreground='black', alpha=0.5),
            patheffects.Normal()
        ])

        s = class_names[class_id] if class_names else str(class_id)
        if extras:
            s += "\n" + str(extras[i])
        patch = plt_ax.text(x + 2,
                            y,
                            s,
                            verticalalignment='top',
                            color=color,
                            fontsize=12,
                            weight='bold')
        patch.set_path_effects([
            patheffects.Stroke(linewidth=1, foreground='black', alpha=0.5),
            patheffects.Normal()
        ])

    _ = plt_ax.imshow(img)
    plt.show()
Beispiel #3
0
def main():
    myhero = Heuro(email, password)
    # Small dictionary to convert API output to a readable format
    mygender = {
        0: "female",
        1: "male"
    }
    # mypipe = myhero.make_pipeline(pipeline="test_pipe")
    # print(mypipe)
    # upload = myhero.ingest_file('../data/images/test_faces_2.jpg', pipeline_id)
    """
    file_to_ingest = '../data/audio/man-woman.mp3'
    file_to_ingest = '../data/images/four-in-car.jpeg'
    file_to_ingest = '../data/images/family1.jpeg'
    image_to_ingest = "../data/images/thb1.jpg"
    audio_to_ingest = '../data/audio/man-woman.mp3'
    audio_to_ingest = '../data/video/tagueule.mp3'
    image_to_ingest = '../data/video/tagueule.png'
    image_to_ingest = '../data/images/four-in-car.jpeg'
    image_to_ingest = '../data/images/mp1.jpeg'
    audio_to_ingest = "../data/audio/baby-talk.mp3"
    image_to_ingest = '../data/images/girls.jpg'
    audio_to_ingest = "../data/audio/tom_scott_trim.mp3"
    """

    # Image first, just because
    audio_to_ingest = "../data/audio/ambianceinsidecar.mp3"
    image_to_ingest = '../data/images/4.jpg'
    files_to_ingest = [image_to_ingest, audio_to_ingest]

    if image_to_ingest[-3:] != "png" and \
                    image_to_ingest[-3:] != "jpg" and \
                    image_to_ingest[-4:] != "jpeg" and \
            audio_to_ingest[-3:] != "mp3":
        sys.exit(" Sorry. File format is not recognized.")

    is_jpeg = detect_jpeg(file_to_ingest=image_to_ingest)
    results = analyse_file_api(files_to_ingest, target_api=myhero, pipeline_id=pipeline_id)
    # print(results)
    # r1 = analyse_file_api(image_to_ingest, target_api=myhero, pipeline_id=pipeline_id)
    r1 = results[0]
    watch_json = True # False
    if watch_json:
        import json
        with open('jsonwatch_image.txt', 'w') as outf:
            json.dump(r1, outf, sort_keys = True, indent = 4, separators=(',', ':'))

    # Audio second
    if audio_to_ingest[-3:] != "mp3":
        sys.exit(" Sorry. Image file format is not recognized.")

    # r2 = analyse_file_api(audio_to_ingest, target_api=myhero, pipeline_id=pipeline_id)
    r2 = results[1]

    # Distinguish between image and audio (different output formats)
    # inference_audio = {}
    # inference_image = {}

    r_video = r1['result']['output']['classification']
    # for x, y in zip(r_output.keys(), r_output.values()):
    #     print(str(x)+": "+str(np.array(y).shape)+str(y))
    people = r_video.get('objects')

    # Test if we got anything at all out
    if not people:
        sys.exit("Error: the API did not detect any people.")

    n_people = len(people)
    gender_image = []
    age_image = []
    face_xy = []
    for person in people:
        gender_image.append(person['gender'])
        age_image.append(person['ageGroup'])
        face_xy.append((person['face']['X'], person['face']['Y']))

    r_audio = r2['result']['output']
    # for x, y in zip(r_output.keys(), r_output.values()):
    #     print(str(x)+": "+str(y))
    gender_audio = r_audio['gender']
    age_audio = r_audio['age']
    language = r_audio['language']

    # if file_to_ingest[-3:] == "mp3":
        # with open('jsonwatch_audio.txt', 'w') as outf:
        #     json.dump(r, outf, sort_keys = True, indent = 4, separators=(',', ':'))
    # elif file_to_ingest[-3:] == "png" or\
    #                 file_to_ingest[-3:] == "jpg" or\
    #                 file_to_ingest[-4:] == "jpeg":

    print("=== Audio evaluation ===")
    print("gender_audio: ", gender_audio)
    print("age_audio: ", age_audio)
    print("language: ", language)

    print("=== Video evaluation ===")
    print("n_people: ", n_people)
    print("gender_image: ", [mygender[gen] for gen in gender_image])
    print("age_image: ",  age_image)
    print("faces: ",  face_xy)

    children = False
    if "Child" in age_image:
        children = True
    n_male = gender_image.count(1)
    n_female = gender_image.count(0)
    n_child = age_image.count("Child")
    n_adult = age_image.count("Adult")
    if n_female > n_male:
        maj_sex = "female"
    elif n_female < n_male:
        maj_sex = "male"
    else:
        maj_sex = None

    if n_child > n_adult:
        maj_age = "Child"
    else:
        maj_age = "Adult"
    # if n_male==0 or n_female==0:
    #     mix_sex = False
    # else:
    #     mix_sex = True
    print()
    print("=== Overall mood ===")
    print("Children: ", children)
    print("Gender Majority: ", maj_sex)
    print("Age Majority: ", maj_age)

    if gender_audio == maj_sex:
        print("Audio agrees with video on gender.")
    else:
        print("AI cannot determine gender using audio.")
    # print("Sex Mix: ", mix_sex)

    if is_jpeg:
        from PIL import Image
        # with open(image_to_ingest, 'r') as im_input:
        #     im = Image.open(im_input)
        im = Image.open(image_to_ingest, 'r')
        im.save("Foto.png") #, 'w')
        # with open("Foto.png", 'w') as foto:
        #     im.save(foto)
        img = mpimage.imread('Foto.png', 'r')
    else:
        img = mpimage.imread(image_to_ingest)
    plt.imshow(img)

    for age, gend, face in zip(age_image, gender_image, face_xy):
        plt.text(face[0], face[1], str(age)+"\n"+str(mygender[gend]), color='white',
                 fontsize=24).set_path_effects([path_effects.Stroke(linewidth=4, foreground='black'), path_effects.Normal()])
    plt.xticks([])
    plt.yticks([])
    plt.show()
    outfile = "../data/output/output.jpg"
    with open(outfile, 'w') as outf:
        plt.savefig(outf)
    # Remove png file, only needed for visualization
    if is_jpeg:
        os.remove('Foto.png')
Beispiel #4
0
    def plot_values(self, lons, lats, vals, fmt='%s', valmask=None,
                    color='#000000', textsize=14, labels=None,
                    labeltextsize=10, labelcolor='#000000',
                    showmarker=False, labelbuffer=25, outlinecolor='#FFFFFF'):
        """Plot values onto the map

        Args:
          lons (list): longitude values to use for placing `vals`
          lats (list): latitude values to use for placing `vals`
          vals (list): actual values to place on the map
          fmt (str, optional): Format specification to use for representing the
            values. For example, the default is '%s'.
          valmask (list, optional): Boolean list to use as masking of the
            `vals` while adding to the map.
          color (str, list, optional): Color to use while plotting the `vals`.
            This can be a list to specify each color to use with each value.
          textsize (str, optional): Font size to draw text.
            labels (list, optional): Optional list of labels to place below the
            plotting of `vals`
          labeltextsize (int, optional): Size of the label text
          labelcolor (str, optional): Color to use for drawing labels
          showmarker (bool, optional): Place a marker on the map for the label
          labelbuffer (int): pixel buffer around labels
          outlinecolor (color): color to use for text outlines
        """
        if valmask is None:
            valmask = [True] * len(lons)
        if labels is None:
            labels = [''] * len(lons)
        if isinstance(color, str):
            color = [color] * len(lons)
        bbox = self.fig.get_window_extent().transformed(
            self.fig.dpi_scale_trans.inverted())
        axbbox = self.ax.get_window_extent().transformed(
            self.fig.dpi_scale_trans.inverted())
        axx0 = axbbox.x0 * self.fig.dpi
        axx1 = (axbbox.x0 + axbbox.width) * self.fig.dpi
        axy0 = axbbox.y0 * self.fig.dpi
        axy1 = (axbbox.y0 + axbbox.height) * self.fig.dpi
        figwidth = bbox.width * self.fig.dpi
        figheight = bbox.height * self.fig.dpi
        if self.textmask is None:
            self.textmask = np.zeros((int(figwidth), int(figheight)), bool)
        thisax = self.ax
        # Create a fake label, to test out our scaling
        t0 = self.fig.text(0.5, 0.5, "ABCDEFGHIJ", transform=thisax.transAxes,
                           color='None', size=textsize)
        bbox = t0.get_window_extent(self.fig.canvas.get_renderer())
        xpixels_per_char = bbox.width / 10.
        ypixels = bbox.height
        for o, a, v, m, c, label in zip(lons, lats, vals, valmask,
                                        color, labels):
            if not m:
                continue

            ha = 'center'
            mystr = fmt % (v,)
            max_mystr_len = max([len(s) for s in mystr.split("\n")])
            mystr_lines = len(mystr.split("\n"))
            # compute the pixel coordinate of this data point
            (x, y) = thisax.projection.transform_point(o, a, ccrs.Geodetic())
            (imgx, imgy) = thisax.transData.transform([x, y])
            imgx0 = int(imgx - (max_mystr_len * xpixels_per_char / 2.0))
            if imgx0 < axx0:
                ha = 'left'
                imgx0 = imgx
            imgx1 = imgx0 + max_mystr_len * xpixels_per_char
            if imgx1 > axx1:
                imgx1 = imgx
                imgx0 = imgx1 - max_mystr_len * xpixels_per_char
                ha = 'right'
            imgy0 = int(imgy)
            imgy1 = imgy0 + mystr_lines * ypixels
            # Now we buffer
            imgx0 = max([0, imgx0 - labelbuffer])
            imgx1 = min([figwidth, (imgx0 + 2 * labelbuffer +
                                    max_mystr_len * xpixels_per_char)])
            imgy0 = max([0, imgy0 - labelbuffer * 0.75])
            imgy1 = min([figheight, (imgy0 +
                                     mystr_lines * ypixels +
                                     2 * labelbuffer * 0.75)])
            _cnt = np.sum(np.where(self.textmask[int(imgx0):int(imgx1),
                                                 int(imgy0):int(imgy1)],
                                   1, 0))
            # If we have more than 15 pixels of overlap, don't plot this!
            if _cnt > 15:
                if self.debug:
                    print("culling |%s| due to overlap, %s" % (repr(mystr),
                                                               _cnt))
                continue
            if self.debug:
                rec = plt.Rectangle([imgx0,
                                     imgy0],
                                    (imgx1 - imgx0),
                                    (imgy1 - imgy0),
                                    facecolor='None', edgecolor='r')
                self.fig.patches.append(rec)
            # Useful for debugging this algo
            if self.debug:
                print(("label: %s imgx: %s/%s-%s imgy: %s/%s-%s "
                       "x:%s-%s y:%s-%s _cnt:%s"
                       ) % (repr(mystr), imgx, axx0, axx1, imgy, axy0, axy1,
                            imgx0, imgx1, imgy0, imgy1, _cnt))
            self.textmask[int(imgx0):int(imgx1), int(imgy0):int(imgy1)] = True
            t0 = thisax.text(o, a, mystr, color=c,
                             size=textsize, zorder=Z_OVERLAY+2,
                             va='center' if not showmarker else 'bottom',
                             ha=ha, transform=ccrs.PlateCarree())
            bbox = t0.get_window_extent(self.fig.canvas.get_renderer())
            if self.debug:
                rec = plt.Rectangle([bbox.x0, bbox.y0],
                                    bbox.width, bbox.height,
                                    facecolor='None', edgecolor='k')
                self.fig.patches.append(rec)
            if showmarker:
                thisax.scatter(o, a, marker='+', zorder=Z_OVERLAY+2,
                               color='k', transform=ccrs.PlateCarree())
            t0.set_clip_on(True)
            t0.set_path_effects([PathEffects.Stroke(linewidth=3,
                                                    foreground=outlinecolor),
                                 PathEffects.Normal()])

            if label and label != '':
                thisax.annotate("%s" % (label, ), xy=(x, y), ha='center',
                                va='top',
                                xytext=(0, 0 - textsize/2),
                                color=labelcolor,
                                textcoords="offset points",
                                zorder=Z_OVERLAY+1,
                                clip_on=True, fontsize=labeltextsize)
Beispiel #5
0
def plot_online_prediction(preds_dict,
                           new_inputs_dict,
                           online_stg,
                           t_predict,
                           robot_future,
                           dt,
                           max_speed,
                           color_dict=None,
                           data_id=0,
                           focus_on=None,
                           focus_window_height=6,
                           line_alpha=0.7,
                           line_width=0.2,
                           edge_width=2,
                           circle_edge_width=0.5,
                           only_predict=None,
                           edge_line_width=1.0,
                           dpi=300,
                           fig_height=4,
                           xlim=(0, 100),
                           ylim=(0, 50),
                           figsize=None,
                           return_frame=False,
                           return_fig=False,
                           printing=False,
                           robot_circle=False,
                           add_legend=True,
                           title=None,
                           flip_axes=False,
                           omit_names=False,
                           plot_edges=True,
                           axes_labels=True,
                           rotate_axes_text=0,
                           save_at=None):

    if color_dict is None:
        # This changes colors per run.
        color_dict = defaultdict(dict)

    if dt is None:
        raise ValueError(
            'You must supply a time delta, the argument dt cannot be None!')

    robot_node = online_stg.robot_node

    if figsize is None:
        aspect_ratio = float(xlim[1] - xlim[0]) / (ylim[1] - ylim[0])
        figsize = (fig_height * aspect_ratio, fig_height)

    predict_horizon = robot_future.shape[0]

    if t_predict < online_stg.hyperparams['minimum_history_length']:
        return

    ###################
    ### Predictions ###
    ###################
    outputs = {k: v.cpu().numpy() for k, v in preds_dict.items()}

    ########################
    ### Data Preparation ###
    ########################
    output_pos = dict()
    sampled_zs = dict()
    for node in online_stg.nodes:
        if robot_node == node:
            continue

        key = str(node) + '/y'
        z_key = str(node) + '/z'

        output_pos[node] = integrate_trajectory(outputs[key], [0, 1],
                                                new_inputs_dict[node][0],
                                                [0, 1],
                                                dt,
                                                output_limit=max_speed,
                                                velocity_in=True)
        sampled_zs[node] = outputs[z_key]

    ######################
    ### Visualizations ###
    ######################
    fig, ax = plt.subplots(figsize=figsize)
    not_added_samples = True
    for node_name in online_stg.nodes:
        if focus_on is not None and node_name != focus_on:
            continue

        predictions = output_pos[node_name][:, 0]
        z_values = sampled_zs[node_name][:, 0]

        # Predicted trails
        if only_predict is None or (only_predict is not None
                                    and node_name == only_predict):
            if not_added_samples:
                #                 plt.plot([] , [], 'r', label='Sampled Futures')
                not_added_samples = False

            for sample_num in range(output_pos[node_name].shape[0]):
                z_value = tuple(z_values[sample_num])
                if z_value not in color_dict[node_name]:
                    color_dict[node_name][z_value] = "#%06x" % random.randint(
                        0, 0xFFFFFF)

                ax.plot(predictions[sample_num, :, 0],
                        predictions[sample_num, :, 1],
                        color=color_dict[node_name][z_value],
                        linewidth=line_width,
                        alpha=line_alpha,
                        zorder=2)

        # Current Node Position
        circle = plt.Circle(
            (new_inputs_dict[node_name][0, 0], new_inputs_dict[node_name][0,
                                                                          1]),
            0.3,
            facecolor='b' if 'Home' in node_name.type else 'g',
            edgecolor='k',
            lw=circle_edge_width,
            zorder=3)
        ax.add_artist(circle)

        #         if focus_on:
        #             ax.set_title(node_name)
        #         else:
        #             ax.text(prefix[-1, 0] + 0.4, prefix[-1, 1], node_name, zorder=4)

        if not omit_names:
            ax.text(new_inputs_dict[node_name][0, 0] + 0.4,
                    new_inputs_dict[node_name][0, 1],
                    node_name,
                    zorder=4)

    # Robot Node
    if focus_on is None:
        robot_future = robot_future[:, 0:2]

        future_all_zeros = not np.any(robot_future)
        if not future_all_zeros and robot_node in new_inputs_dict:
            ax.plot(robot_future[:, 0],
                    robot_future[:, 1],
                    'w--',
                    path_effects=[
                        pe.Stroke(linewidth=edge_width, foreground='k'),
                        pe.Normal()
                    ])

            circle = plt.Circle(
                (new_inputs_dict[robot_node][0, 0],
                 new_inputs_dict[robot_node][0, 1]),
                0.3,
                facecolor='b' if 'Home' in robot_node.type else 'g',
                edgecolor='k',
                lw=circle_edge_width,
                zorder=3)
            ax.add_artist(circle)

            # Radius of influence
            if robot_circle:
                circle = plt.Circle((new_inputs_dict[robot_node][0, 0],
                                     new_inputs_dict[robot_node][0, 1]),
                                    online_stg.hyperparams['edge_radius'],
                                    fill=False,
                                    color='r',
                                    linestyle='--',
                                    zorder=3)
                ax.plot([], [], 'r--', label='Edge Radius')
                ax.add_artist(circle)

            if not omit_names:
                ax.text(new_inputs_dict[robot_node][0, 0] + 0.4,
                        new_inputs_dict[robot_node][0, 1],
                        robot_node,
                        zorder=4)

    if plot_edges:
        already_seen_pairs = list()
        for node_A, egdes_and_neighbors in online_stg.scene_graph.node_edges_and_neighbors.items(
        ):
            for edge_type, neigbors in egdes_and_neighbors.items():
                for node_B in neigbors:
                    if (node_A, node_B) in already_seen_pairs:
                        continue

                    already_seen_pairs.append((node_B, node_A))

                    if robot_node not in [node_A, node_B]:
                        edge_age = min([
                            online_stg.node_models_dict[str(
                                node_A)].get_mask_for_edge_to(node_B).item(),
                            online_stg.node_models_dict[str(
                                node_B)].get_mask_for_edge_to(node_A).item()
                        ])
                    else:
                        edge_age = 1

                    plt.plot([
                        new_inputs_dict[node_A][0, 0],
                        new_inputs_dict[node_B][0, 0]
                    ], [
                        new_inputs_dict[node_A][0, 1],
                        new_inputs_dict[node_B][0, 1]
                    ],
                             color='k',
                             lw=edge_line_width,
                             dashes=[edge_age, 1 - edge_age],
                             zorder=-1)

    if focus_on is not None:
        y_radius = focus_window_height
        x_radius = aspect_ratio * y_radius
        ax.set_ylim((prefix[-1, 1] - y_radius, prefix[-1, 1] + y_radius))
        ax.set_xlim((prefix[-1, 0] - x_radius, prefix[-1, 0] + x_radius))

    if ylim is not None:
        ax.set_ylim(ylim)
    if xlim is not None:
        ax.set_xlim(xlim)

    if add_legend and robot_circle and not future_all_zeros:
        ax.legend(loc='best')

    if title is not None:
        ax.set_title(title)

    if axes_labels:
        ax.set_xlabel('$x$ Position (m)')
        ax.set_ylabel('$y$ Position (m)')

    if rotate_axes_text != 0:
        plt.xticks(rotation=rotate_axes_text)
        plt.yticks(rotation=rotate_axes_text)

    fig.tight_layout()

    if return_fig:
        return fig

    if return_frame:
        buffer_ = StringIO()
        plt.savefig(buffer_, format="png", transparent=True, dpi=dpi)
        buffer_.seek(0)
        data = np.asarray(Image.open(buffer_))

        plt.close(fig)
        return data

    if save_at is not None:
        plt.savefig(save_at, dpi=dpi, transparent=True)

    plt.show()
    plt.close(fig)
def cell_wise_velocity(adata, genes, x=0, y=1, basis='trimap', n_columns=1, color=None, label_on_embedding=True,
                       cmap=None, s_kwargs_dict={}, layer='X', cell_ind='all', quiver_scale=None, figsize=None,
                       **q_kwargs):
    """Plot the velocity vector of each cell.

    Parameters
    ----------
        adata: :class:`~anndata.AnnData`
            an Annodata object.
        genes: `list`
            The gene names whose gene expression will be faceted.
        x: `int` (default: `0`)
            The column index of the low dimensional embedding for the x-axis
        y: `int` (default: `1`)
            The column index of the low dimensional embedding for the y-axis
        basis: `str` (default: `trimap`)
            The reduced dimension embedding of cells to visualize.
        n_columns: `int  (default: 1)
            The number of columns of the resulting plot.
        color: `list` or None (default: None)
            A list of attributes of cells (column names in the adata.obs) will be used to color cells.
        cmap: `plt.cm` or None (default: None)
            The color map function to use.
        s_kwargs_dict: `dict` (default: {})
            The dictionary of the scatter arguments.
        layer: `str` (default: X)
            Which layer of expression value will be used.
        cell_ind: `str` or `list` (default: all)
            the cell index that will be chosen to draw velocity vectors.
        quiver_scale: `float` or None (default: None)
            scale of quiver plot (default: None). Number of data units per arrow length unit, e.g., m/s per plot width;
            a smaller scale parameter makes the arrow longer. If None, we will use quiver_autoscaler to calculate the scale.
        figsize: `None` or `[float, float]` (default: None)
            The width and height of a figure.
        q_kwargs:
            Additional parameters that will be passed to plt.quiver function

    Returns
    -------
        Nothing but a cell wise quiver plot
    """
    import matplotlib.pyplot as plt
    import matplotlib.patheffects as PathEffects

    if cmap is None and color is None:
        cmap = plt.cm.RdBu_r

    n_cells, n_genes = adata.shape[0], len(genes)
    # {"alpha": 0.5, "s": 8, "edgecolor": "0.8", "lw": 0.15}
    if cell_ind is "all":
        ix_choice = np.arange(adata.shape[0])
    elif cell_ind is 'random':
        ix_choice = np.random.choice(np.range(adata.shape[0]), size=1000, replace=False)
    elif type(cell_ind) is int:
        ix_choice = np.random.choice(np.range(adata.shape[0]), size=cell_ind, replace=False)
    elif type(cell_ind) is list:
        ix_choice = cell_ind

    scatter_kwargs = dict(alpha=0.4, s=8, edgecolor=None, linewidth=0)
    if s_kwargs_dict is not None:
        scatter_kwargs.update(s_kwargs_dict)

    # layer_keys = list(adata.layers.keys())
    # layer_keys.extend(['X', 'protein'])

    if layer is 'X':
        E_vec = adata[:, adata.var.index.isin(genes)].X.T
    elif layer in adata.layers.keys():
        E_vec = adata[:, adata.var.index.isin(genes)].layers[layer].T
    elif layer is 'protein': # update subset here
        E_vec = adata[:, adata.var.index.isin(genes)].obsm[layer].T
    else:
        raise Exception(f'The {layer} you passed in is not existed in the adata object.')

    if color is not None:
        color = list(set(color).intersection(adata.obs.keys()))
        n_genes, genes = len(color), color
        E_vec = adata.obs[color].values.T.flatten() if len(color) > 0 else np.empty((0, 1))

    if ('X_' + basis in adata.obsm.keys()) and ('velocity_' + basis in adata.obsm.keys()):
        X = adata.obsm['X_' + basis][:, [x, y]]
        V = adata.obsm['velocity_' + basis][:, [x, y]]
    else:
        if 'X_' + basis not in adata.obsm.keys():
            reduceDimension(adata, velocity_key='velocity_S', reduction_method=basis)
        if 'kmc' not in adata.uns_keys():
            cell_velocities(adata, vkey='pca', basis=basis, method='analytical')
            X = adata.obsm['X_' + basis][:, [x, y]]
            V = adata.obsm['velocity_' + basis][:, [x, y]]
        else:
            kmc = adata.uns['kmc']
            X = adata.obsm['X_' + basis][:, [x, y]]
            V = kmc.compute_density_corrected_drift(X, kmc.Idx, normalize_vector=True)
            adata.obsm['velocity_' + basis] = V

    if 0 in E_vec.shape:
        raise Exception(f'The gene names {genes} (or cell annotations {color}) provided are not existed in your data.')

    if quiver_scale is None:
        quiver_scale = quiver_autoscaler(X, V)
    quiver_kwargs = {"angles": 'xy', "scale_units": 'xy', 'scale': quiver_scale, "minlength": 1.5, "alpha": 0.4}
    quiver_kwargs.update(q_kwargs)

    n_columns, plot_per_gene = n_columns, 1 # we may also add random velocity results
    nrow, ncol = int(np.ceil(plot_per_gene * n_genes / n_columns)), n_columns
    if figsize is None:
        plt.figure(None, (ncol * 3, nrow * 3), dpi=160)
    else:
        plt.figure(None, (figsize[0]*ncol, figsize[1]*nrow)) # , dpi=160

    E_vec = E_vec.A.flatten() if issparse(E_vec) else E_vec.flatten()
    V = V.A[:, [x, y]] if issparse(V) else V[:, [x, y]]
    # iterate over cell first then a different dimension/gene/column
    df = pd.DataFrame({"x": np.tile(X[:, 0], n_genes), "y": np.tile(X[:, 1], n_genes), "u": np.tile(V[:, 0], n_genes),
                       "v": np.tile(V[:, 1], n_genes), 'gene': np.repeat(np.array(genes), n_cells),
                       "expression": E_vec}, index=range(n_cells * n_genes))

    # the following code is inspired by https://github.com/velocyto-team/velocyto-notebooks/blob/master/python/DentateGyrus.ipynb
    gs = plt.GridSpec(nrow, ncol)
    for i, gn in enumerate(genes):
        ax = plt.subplot(gs[i*plot_per_gene])
        try:
            ix=np.where(adata.var.index == gn)[0][0]
        except:
            ix = gn in adata.obs.columns
            if not ix:
                continue

        cur_pd = df.loc[df.gene == gn, :]

        E_vec = cur_pd.loc[:, 'expression']

        if color is None:
            limit = np.max(np.abs(np.percentile(E_vec, [1, 99])))  # upper and lowe limit / saturation

            E_vec = E_vec + limit  # that is: tmp_colorandum - (-limit)
            E_vec = E_vec / (2 * limit)  # that is: tmp_colorandum / (limit - (-limit))
            E_vec = np.clip(E_vec, 0, 1)

            ax.scatter(cur_pd.iloc[:, 0], cur_pd.iloc[:, 1], c=cmap(E_vec), **scatter_kwargs)
        else:
            import seaborn as sns
            # List of RGB triplets
            color_labels = E_vec.unique()
            rgb_values = sns.color_palette("Set2", len(color_labels))

            # Map label to RGB
            color_map = pd.DataFrame(zip(color_labels, rgb_values), index=color_labels)

            ax.scatter(cur_pd.iloc[:, 0], cur_pd.iloc[:, 1], c=color_map.loc[E_vec, 1].values, **scatter_kwargs)

            if label_on_embedding:
                for i in color_labels:
                    color_cnt = np.median(cur_pd.iloc[np.where(E_vec == i)[0], :2], 0)
                    txt=ax.text(color_cnt[0], color_cnt[1], str(i),
                             fontsize=13) # , bbox={"facecolor": "w", "alpha": 0.6}
                    txt.set_path_effects([
                        PathEffects.Stroke(linewidth=5, foreground="w", alpha=0.1),
                        PathEffects.Normal()])

        ax.quiver(cur_pd.iloc[ix_choice, 0], cur_pd.iloc[ix_choice, 1],
                   cur_pd.iloc[ix_choice, 2], cur_pd.iloc[ix_choice, 3],
                   **quiver_kwargs)
        ax.axis("off")

    plt.show()
Beispiel #7
0
def _midiplot(onsets,offsets,pitch):
    plt.figure(figsize=(20,10))
    
    for i in range(0,len(onsets)):
        plt.plot([onsets[i],offsets[i]], [pitch[i],pitch[i]], 'k', lw=2, path_effects=[pe.Stroke(linewidth=2, foreground='k'), pe.Normal()], zorder=5)
        
    plt.xlabel("Beats")
    plt.ylabel("Pitch (C4=60)")
Beispiel #8
0
def dashboard(prediction,
              tlm,
              times,
              limits,
              modelname='PSMC',
              msid='1pdeaat',
              errorplotlimits=None,
              yplotlimits=None,
              fig=None,
              savefig=True):
    """ Plot Xija model dashboard.

    :param prediction: model prediction
    :param tlm: telemetry 
    :param times: model/telemetry time values
    :param limits: model limit dict, (e.g. {"units":"C", "caution_high":-12.0,
                                            "planning_limit":-14.0})
    :param modelname: Name of model (e.g. "ACA")
    :param msid: msid name (e.g. "aacccdpt")
    :param errorplotlimits: list or tuple of min and max x axis plot boundaries for both righthand
           plots

    Note: prediction, tlm, and times must all have the same number of values.

    """

    # Set some plot characteristic default values
    # matplotlib.rcParams['xtick.major.pad'] = 10
    # matplotlib.rcParams['ytick.major.pad'] = 5
    matplotlib.rc('font', family='sans-serif')
    matplotlib.rc('font', weight='light')

    error = tlm - prediction
    stats = calcquantiles(error)

    # In this case the data is not discretized to a limited number of count values, or has too
    # many possible values to work with calcquantstats(), such as with tlm_fep1_mong.
    if len(np.sort(list(set(tlm)))) > 1000:
        quantized_tlm = digitize_data(tlm)
        quantstats = calcquantstats(quantized_tlm, error)
    else:
        quantstats = calcquantstats(tlm, error)

    units = limits['units']
    cautionhigh = limits.get('caution_high', None)
    planninglimit = limits.get('planning_limit', None)
    acisi_limit = limits.get('acisi_limit', None)
    aciss_limit = limits.get('aciss_limit', None)
    fp_sens_limit = limits.get('fp_sens_limit', None)

    startsec = DateTime(times[0]).secs
    stopsec = DateTime(times[-1]).secs

    xtick = np.linspace(startsec, stopsec, 10)
    xlab = [lab[:8] for lab in DateTime(xtick).date]

    if not fig:
        # fig = plt.figure(figsize=(16, 10), facecolor=[1, 1, 1])
        fig = plt.figure(figsize=(15, 8))
    else:
        fig.clf()

    # ---------------------------------------------------------------------------------------------
    # Axis 1 - Model and Telemetry vs Time
    #
    # This plot is in the upper lefthand corner and shows predicted temperatures in red and
    # telemetry in blue vs time.
    #

    ax1 = fig.add_axes([0.1, 0.38, 0.44, 0.50], frameon=True)
    ax1.plot(times, prediction, color='#d92121', linewidth=1, label='Model')
    ax1.plot(times, tlm, color='#386cb0', linewidth=1.5, label='Telemetry')
    ax1.set_title('%s Temperature (%s)' %
                  (modelname.replace('_', ' '), msid.upper()),
                  fontsize=18,
                  y=1.00)
    ax1.set_ylabel('Temperature deg%s' % units, fontsize=18)
    if yplotlimits is not None:
        ax1.set_ylim(yplotlimits)
    ax1.set_yticklabels(ax1.get_yticks(), fontsize=14)
    ax1.set_xticks(xtick)
    ax1.set_xticklabels('')
    ax1.set_xlim(xtick[0] - 10, times[-1])
    ax1.grid(True)

    if cautionhigh:

        # Draw caution high limit line.
        ylim1 = ax1.get_ylim()
        dy = ylim1[1] - ylim1[0]
        if ylim1[1] - 2 <= cautionhigh:
            ax1.set_ylim(ylim1[0], cautionhigh + dy / 7.)
            ax1.set_yticklabels(ax1.get_yticks(), fontsize=14)
        ylim1 = ax1.get_ylim()
        yellowlimitline = ax1.plot(ax1.get_xlim(), [cautionhigh, cautionhigh],
                                   'orange',
                                   linewidth=1.5)
        if ylim1[1] <= cautionhigh:
            ax1.set_ylim(ylim1[0], cautionhigh + 1)

        # Print caution high limit value (remember plot is 50% of fig height).
        #chfig = 0.50 * (cautionhigh - ylim1[0]) / (np.diff(ylim1)) + 0.38
        #txt = fig.text(0.11, chfig - 0.000, 'Caution High (Yellow) = {:4.1f} {}'.format(
        #    cautionhigh, units), ha="left", va="bottom", size=18)
        #txt.set_bbox(dict(color='white', alpha=0.8))
        xlim1 = ax1.get_xlim()
        chx = 0.02 * (xlim1[1] - xlim1[0]) + xlim1[0]
        chy = 0.01 * (ylim1[1] - ylim1[0]) + cautionhigh
        txt = ax1.text(chx,
                       chy,
                       'Caution High (Yellow) = {:4.1f} {}'.format(
                           cautionhigh, units),
                       ha="left",
                       va="bottom",
                       fontsize=12)
        txt.set_path_effects([
            path_effects.Stroke(linewidth=3, foreground='white', alpha=0.7),
            path_effects.Normal()
        ])

        txt.set_bbox(dict(color='white', alpha=0))

    if planninglimit:

        # Draw planning limit line.
        planninglimitline1 = ax1.plot(ax1.get_xlim(),
                                      [planninglimit, planninglimit],
                                      'g--',
                                      linewidth=1.5)
        ylim1 = ax1.get_ylim()

        # Print planning limit value (remember plot is 50% of fig height).
        #if (ylim1[-1] - planninglimit) / np.diff(ylim1) < 0.1:
        #    plfig = 0.50 * (planninglimit - ylim1[0]) / (np.diff(ylim1)) + 0.38
        #else:
        #    # <-- figure coordinates (plot is 50% of fig height)
        #    plfig = 0.50 * (planninglimit - ylim1[0]) / (np.diff(ylim1)) + 0.38 + 0.01
        #
        #if cautionhigh:
        #    if np.abs(planninglimit - cautionhigh)/np.diff(ylim1) < 0.1:
        #        plfig = plfig + 0.02

        #txt = fig.text(0.11, plfig - 0.005, 'Planning Limit = {:4.1f} {}'.format(
        #       planninglimit, units), ha="left", va="top", size=18)
        #txt.set_bbox(dict(color='white', alpha=0.8))

        xlim1 = ax1.get_xlim()
        plx = 0.02 * (xlim1[1] - xlim1[0]) + xlim1[0]
        ply = 0.01 * (ylim1[1] - ylim1[0]) + planninglimit
        txt = ax1.text(plx,
                       ply,
                       'Planning Limit = {:4.1f} {}'.format(
                           planninglimit, units),
                       ha="left",
                       va="bottom",
                       fontsize=12)
        txt.set_path_effects([
            path_effects.Stroke(linewidth=3, foreground='white', alpha=0.7),
            path_effects.Normal()
        ])
        # txt.set_bbox(dict(color='white', alpha=0))

    if acisi_limit:

        # Draw ACIS-I limit line.
        acisilimitline = ax1.plot(ax1.get_xlim(), [acisi_limit, acisi_limit],
                                  'b-.',
                                  linewidth=1.5)

        ylim1 = ax1.get_ylim()

        xlim1 = ax1.get_xlim()
        plx = 0.02 * (xlim1[1] - xlim1[0]) + xlim1[0]
        ply = 0.01 * (ylim1[1] - ylim1[0]) + acisi_limit
        txt = ax1.text(plx,
                       ply,
                       'ACIS-I Limit = {:4.1f} {}'.format(acisi_limit, units),
                       ha="left",
                       va="bottom",
                       fontsize=14)
        txt.set_path_effects([
            path_effects.Stroke(linewidth=4, foreground='white', alpha=1.0),
            path_effects.Normal()
        ])

    if aciss_limit:

        # Draw ACIS-S limit line.
        acisslimitline = ax1.plot(ax1.get_xlim(), [aciss_limit, aciss_limit],
                                  '-.',
                                  color='purple',
                                  linewidth=1.5)

        ylim1 = ax1.get_ylim()

        xlim1 = ax1.get_xlim()
        plx = 0.02 * (xlim1[1] - xlim1[0]) + xlim1[0]
        ply = 0.01 * (ylim1[1] - ylim1[0]) + aciss_limit
        txt = ax1.text(plx,
                       ply,
                       'ACIS-S Limit = {:4.1f} {}'.format(aciss_limit, units),
                       ha="left",
                       va="bottom",
                       fontsize=14)
        txt.set_path_effects([
            path_effects.Stroke(linewidth=4, foreground='white', alpha=1.0),
            path_effects.Normal()
        ])

    if fp_sens_limit:

        # Draw FP SENS limit line.
        fpsenslimitline = ax1.plot(ax1.get_xlim(),
                                   [fp_sens_limit, fp_sens_limit],
                                   '--',
                                   color='red',
                                   linewidth=1.5)

        ylim1 = ax1.get_ylim()

        xlim1 = ax1.get_xlim()
        plx = 0.02 * (xlim1[1] - xlim1[0]) + xlim1[0]
        ply = 0.01 * (ylim1[1] - ylim1[0]) + fp_sens_limit
        txt = ax1.text(plx,
                       ply,
                       'FP SENS Limit = {:4.1f} {}'.format(
                           fp_sens_limit, units),
                       ha="left",
                       va="bottom",
                       fontsize=14)
        txt.set_path_effects([
            path_effects.Stroke(linewidth=4, foreground='white', alpha=1.0),
            path_effects.Normal()
        ])

    # ---------------------------------------------------------------------------------------------
    # Axis 2 - Model Error vs Time
    #
    # This plot is in the lower lefthand corner and shows model error (telemetry - model) vs. time.
    #

    ax2 = fig.add_axes([0.1, 0.1, 0.44, 0.2], frameon=True)
    ax2.plot(times, error, color='#386cb0', label='Telemetry')
    if errorplotlimits:
        ax2.set_ylim(errorplotlimits)

    ax2.set_title('%s Model Error (Telemetry - Model)' %
                  modelname.replace('_', ' '),
                  fontsize=18,
                  y=1.00)
    ax2.set_ylabel('Error deg%s' % units, fontsize=18)
    ax2.set_yticklabels(ax2.get_yticks(), fontsize=14)
    # ax2.tick_params(axis='x', which='major', pad=1)
    ax2.set_xticks(xtick)
    ax2.set_xticklabels(xlab, fontsize=14, rotation=30, ha='right')
    ax2.set_xlim(xtick[0] - 10, times[-1])
    ax2.grid(True)

    # ---------------------------------------------------------------------------------------------
    # Axis 3 - Telemetry vs Model Error
    #
    # This plot is in the upper righthand corner of the page and shows telemetry vs. model error.
    # The code to show model temperature vs model error is commented out but can be used in place
    # of the current comparison, although the quantile lines plotted will also need to be removed.
    #

    # Add some noise to the telemetry (or model) data to make it easier to see the data (less
    # pile-up).
    #
    # band is the mean difference between counts in telemetry (resolution).
    band = np.abs(np.diff(tlm))
    band = np.mean(band[band > 0]) / 2
    noise = np.random.uniform(-band, band, len(tlm))

    ax3 = fig.add_axes([0.62, 0.38, 0.36, 0.50], frameon=True)
    ax3.plot(error,
             tlm + noise,
             'o',
             color='#386cb0',
             alpha=1,
             markersize=2,
             markeredgecolor='#386cb0')
    #ax3.plot(error, prediction + noise, 'b,', alpha = 0.1)
    ax3.set_title('%s Telemetry \n vs. Model Error' %
                  modelname.replace('_', ' '),
                  fontsize=18,
                  y=1.00)
    ax3.set_ylabel('Temperature deg%s' % units, fontsize=18)
    ax3.grid(True)

    # This is an option so that the user can tweak the two righthand plots to use a reasonable
    # set of x axis limits, either because an outlier is expanding the axis range too much, or if
    # more space is needed at the boundaries of the axis.
    if errorplotlimits:
        ax3.set_xlim(errorplotlimits)

    ax3.set_ylim(ax1.get_ylim())
    ax3.set_yticks(ax1.get_yticks())
    ax3.set_yticklabels(ax1.get_yticks(), fontsize=14)
    ylim3 = ax3.get_ylim()

    ax3.set_xticklabels(ax3.get_xticks(), fontsize=14)

    xlim3 = ax3.get_xlim()

    if cautionhigh:

        # Draw caution high limit line.
        dt = 0.05 * np.diff(ax1.get_ylim())
        yellowlimitline3 = ax3.plot(xlim3, [cautionhigh, cautionhigh],
                                    'orange',
                                    linewidth=1.5)
        if ylim3[1] <= cautionhigh:
            ax3.set_ylim(ylim3[0], cautionhigh + 1)
            ax3.set_yticklabels(ax3.get_yticks(), fontsize=18)

    if planninglimit:
        # Draw planning limit line.
        planninglimitline3 = ax3.plot(xlim3, [planninglimit, planninglimit],
                                      'g--',
                                      linewidth=1.5)

    if acisi_limit:

        # Draw ACIS-I limit line.
        acisilimitline = ax3.plot(xlim3, [acisi_limit, acisi_limit],
                                  'b-.',
                                  linewidth=1.5)

    if aciss_limit:

        # Draw ACIS-S limit line.
        acisslimitline = ax3.plot(xlim3, [aciss_limit, aciss_limit],
                                  '-.',
                                  color='purple',
                                  linewidth=1.5)

    if fp_sens_limit:

        # Draw FP SENS limit line.
        fpsenslimitline = ax3.plot(xlim3, [fp_sens_limit, fp_sens_limit],
                                   '--',
                                   color='red',
                                   linewidth=1.5)

    # Plot quantile lines for each count value
    Epoints01, Tpoints01 = getQuantPlotPoints(quantstats, 'q01')
    Epoints99, Tpoints99 = getQuantPlotPoints(quantstats, 'q99')
    Epoints50, Tpoints50 = getQuantPlotPoints(quantstats, 'q50')
    ax3.plot(Epoints01, Tpoints01, color='k', linewidth=4)
    ax3.plot(Epoints99, Tpoints99, color='k', linewidth=4)
    ax3.plot(Epoints50, Tpoints50, color=[1, 1, 1], linewidth=4)
    ax3.plot(Epoints01, Tpoints01, 'k', linewidth=2)
    ax3.plot(Epoints99, Tpoints99, 'k', linewidth=2)
    ax3.plot(Epoints50, Tpoints50, 'k', linewidth=1.5)

    xlim3 = ax3.get_xlim()
    ylim1 = ax1.get_ylim()  # Match axis 1 y scale

    # ---------------------------------------------------------------------------------------------
    # Axis 4 - Error Distribution Histogram
    #
    # This plot is in the lower righthand corner of the page and shows the error distribution
    # histogram.
    #

    ax4 = fig.add_axes([0.62, 0.1, 0.36, 0.2], frameon=True)
    n, bins, patches = ax4.hist(error,
                                40,
                                range=errorplotlimits,
                                facecolor='#386cb0')
    ax4.set_title('Error Distribution', fontsize=18, y=1.0)
    ytick4 = ax4.get_yticks()

    # This is an option so that the user can tweak the two righthand plots to use a reasonable
    # set of x axis limits, either because an outlier is expanding the axis range too much, or if
    # more space is needed at the boundaries of the axis.
    if errorplotlimits:
        ax4.set_xlim(errorplotlimits)
    else:
        xlim_offset = (np.max(error) - np.min(error)) * 0.1
        ax4.set_xlim(np.min(error) - xlim_offset, np.max(error) + xlim_offset)

    # Plot lines for statistical boundaries.
    ylim4 = ax4.get_ylim()
    ax4.set_yticklabels(
        ['%2.0f%%' % (100 * n / len(prediction)) for n in ytick4], fontsize=14)
    ax4.plot([stats['q01'], stats['q01'] + 1e-6],
             ylim4,
             color=[.5, .5, .5],
             linestyle='--',
             linewidth=1.5,
             alpha=1)
    ax4.plot([stats['q99'], stats['q99'] + 1e-6],
             ylim4,
             color=[.5, .5, .5],
             linestyle='--',
             linewidth=1.5,
             alpha=1)
    ax4.plot([np.min(error), np.min(error) + 1e-6],
             ylim4,
             color=[.5, .5, .5],
             linestyle='--',
             linewidth=1.5,
             alpha=1)
    ax4.plot([np.max(error), np.max(error) + 1e-6],
             ylim4,
             color=[.5, .5, .5],
             linestyle='--',
             linewidth=1.5,
             alpha=1)
    ax4.set_xlabel('Error deg%s' % units, fontsize=18)

    # Print labels for statistical boundaries.
    ystart = (ylim4[1] + ylim4[0]) * 0.5
    xoffset = -(.2 / 25) * np.abs(np.diff(ax4.get_xlim()))
    ptext4a = ax4.text(stats['q01'] + xoffset * 1.1,
                       ystart,
                       '1% Quantile',
                       ha="right",
                       va="center",
                       rotation=90,
                       size=14)

    if np.min(error) > ax4.get_xlim()[0]:
        ptext4b = ax4.text(np.min(error) + xoffset * 1.1,
                           ystart,
                           'Minimum Error',
                           ha="right",
                           va="center",
                           rotation=90,
                           size=14)
    ptext4c = ax4.text(stats['q99'] - xoffset * 0.9,
                       ystart,
                       '99% Quantile',
                       ha="left",
                       va="center",
                       rotation=90,
                       size=14)

    if np.max(error) < ax4.get_xlim()[1]:
        ptext4d = ax4.text(np.max(error) - xoffset * 0.9,
                           ystart,
                           'Maximum Error',
                           ha="left",
                           va="center",
                           rotation=90,
                           size=14)

    xlim4 = ax4.get_xlim()

    xlimright = [min(xlim3[0], xlim4[0]), max(xlim3[1], xlim4[1])]
    ax4.set_ylim(ylim4)
    ax4.set_xlim(xlimright)
    ax4.set_xticklabels(ax4.get_xticks(), fontsize=14)

    # Replot axis 3 using widest right hand side xlim
    if cautionhigh:
        #     # Draw caution high limit line.
        yellowlimitline3 = ax3.plot(xlimright, [cautionhigh, cautionhigh],
                                    'orange',
                                    linewidth=1.5)

    # Draw planning limit line.
    planninglimitline3 = ax3.plot(xlimright, [planninglimit, planninglimit],
                                  'g--',
                                  linewidth=1.5)
    ax3.set_xlim(xlimright)
    ax3.set_xticklabels(ax3.get_xticks())

    # I know the following code looks to be redundant and unnecessary, but for some unholy reason,
    # Matplotlib REALLY does not want the top two axes to share the same Y scale. The following
    # code is used to pound Matplotlib into submission.
    ax3.set_ylim(ax1.get_ylim())
    ax3.set_ybound(ax1.get_ylim())
    ax3.set_yticks(ax1.get_yticks())
    ax3.set_yticklabels(ax1.get_yticks())

    ax1.set_ylim(ax1.get_ylim())
    ax1.set_ybound(ax1.get_ylim())
    ax1.set_yticks(ax1.get_yticks())
    ax1.set_yticklabels(ax1.get_yticks())

    # ---------------------------------------------------------------------------------------------
    # Force redraw and save.

    plt.draw()

    if savefig:
        fig.savefig(modelname + '_' + msid.upper() + '_Model_Dashboard.png')
Beispiel #9
0
def plot_time_slice(S,
                    processed_st,
                    time_slice=None,
                    label_stations=True,
                    hires=False,
                    dem=None,
                    plot_peak=True,
                    xy_grid=None,
                    cont_int=5,
                    annot_int=50):
    """
    Plot a time slice through :math:`S` to produce a map-view plot. If time is
    not specified, then the slice corresponds to the maximum of :math:`S` in
    the time direction. Can also plot the peak of the stack function over
    time.

    Args:
        S (:class:`~xarray.DataArray`): The stack function :math:`S`
        processed_st (:class:`~obspy.core.stream.Stream`): Pre-processed
            Stream; output of :func:`~rtm.waveform.process_waveforms` (This is
            needed because Trace metadata from this Stream are used to plot
            stations on the map)
        time_slice (:class:`~obspy.core.utcdatetime.UTCDateTime`): Time of
            desired time slice. The nearest time in :math:`S` to this specified
            time will be plotted. If `None`, the time corresponding to
            :math:`\max(S)` is used (default: `None`)
        label_stations (bool): Toggle labeling stations with network and
            station codes (default: `True`)
        hires (bool): If `True`, use higher-resolution coastlines, which looks better
            but can be slow (default: `False`)
        dem (:class:`~xarray.DataArray`): Overlay time slice on a user-supplied
            DEM from :class:`~rtm.grid.produce_dem` (default: `None`)
        plot_peak (bool): Plot the peak stack function over time as a subplot
            (default: `True`)
        xy_grid (int, float, or None): If not `None`, transforms UTM
            coordinates such that the grid center is at (0, 0) — the plot
            extent is then given by (-xy_grid, xy_grid) [meters] for easting
            and northing. Only valid for projected grids
        cont_int (int): Contour interval [m] for plots with DEM data
        annot_int (int): Annotated contour interval [m] for plots with DEM data
            (these contours are thicker and labeled)

    Returns:
        :class:`~matplotlib.figure.Figure`: Output figure
    """

    # Don't plot peak of stack function when length of stack is one
    if plot_peak and len(S.time) == 1:
        plot_peak = False
        warnings.warn('Stack time length = 1, not plotting peak', RTMWarning)

    st = processed_st.copy()

    # Get coordinates of stack maximum in (latitude, longitude)
    time_max, y_max, x_max, peaks, props = get_peak_coordinates(
        S, unproject=S.UTM)

    # Gather coordinates of grid center
    lon_0, lat_0 = S.grid_center

    if S.UTM:

        # Don't use cartopy for UTM
        proj = None
        transform = None
        plot_transform = None
        lon_0, lat_0, _, _ = utm.from_latlon(S.grid_center[1],
                                             S.grid_center[0],
                                             force_zone_number=S.UTM['zone'])
        x_max, y_max, _, _ = utm.from_latlon(y_max,
                                             x_max,
                                             force_zone_number=S.UTM['zone'])
        for tr in st:
            tr.stats.longitude, tr.stats.latitude, _, _ = utm.from_latlon(
                tr.stats.latitude,
                tr.stats.longitude,
                force_zone_number=S.UTM['zone'])
    else:
        # This is a good projection to use since it preserves area
        proj = ccrs.AlbersEqualArea(central_longitude=lon_0,
                                    central_latitude=lat_0,
                                    standard_parallels=(S.y.values.min(),
                                                        S.y.values.max()))
        transform = ccrs.PlateCarree()
        plot_transform = ccrs.PlateCarree()

    if plot_peak:
        fig, (ax, ax1) = plt.subplots(figsize=(8, 12),
                                      nrows=2,
                                      gridspec_kw={'height_ratios': [3, 1]},
                                      subplot_kw=dict(projection=proj))

        #axes kluge so the second one can have a different projection
        ax1.remove()
        ax1 = fig.add_subplot(414)

    else:
        fig, ax = plt.subplots(figsize=(8, 8),
                               subplot_kw=dict(projection=proj))

    # In either case, we convert from UTCDateTime to np.datetime64
    if time_slice:
        time_to_plot = np.datetime64(time_slice)
    else:
        time_to_plot = np.datetime64(time_max)

    slice = S.sel(time=time_to_plot, method='nearest')

    # Convert UTM grid/etc to x/y coordinates with (0,0) as origin
    if xy_grid:

        # Make sure this is a projected grid
        if not S.UTM:
            raise ValueError('xy_grid can only be used with projected grids!')

        print(f'Converting to x/y grid, cropping {xy_grid:d} m from center')

        # Update dataarrays to x/y coordinates from dem
        x0 = slice.x.data.min() + slice.x_radius
        y0 = slice.y.data.min() + slice.y_radius
        slice = slice.assign_coords(x=(slice.x.data - x0))
        slice = slice.assign_coords(y=(slice.y.data - y0))

        # In case DEM has different extent than slice
        if dem is not None:
            x0_dem = dem.x.data.min() + dem.x_radius
            y0_dem = dem.y.data.min() + dem.y_radius
            dem = dem.assign_coords(x=(dem.x.data - x0_dem))
            dem = dem.assign_coords(y=(dem.y.data - y0_dem))

        lon_0 = lon_0 - x0
        lat_0 = lat_0 - y0
        x_max = x_max - x0
        y_max = y_max - y0
        for tr in st:
            tr.stats.longitude = tr.stats.longitude - x0
            tr.stats.latitude = tr.stats.latitude - y0

    if dem is None:
        if not S.UTM:
            _plot_geographic_context(ax=ax, hires=hires)
            alpha = 0.5
        else:
            alpha = 1  # Can plot slice as opaque for UTM plots w/o DEM, since nothing beneath slice
        slice_plot_kwargs = dict(ax=ax,
                                 alpha=alpha,
                                 cmap='viridis',
                                 add_colorbar=False,
                                 add_labels=False)
    else:
        # Rounding to nearest cont_int
        all_levels = np.arange(
            np.ceil(dem.min().data / cont_int),
            np.floor(dem.max().data / cont_int) + 1) * cont_int
        # Rounding to nearest annot_int
        annot_levels = np.arange(
            np.ceil(dem.min().data / annot_int),
            np.floor(dem.max().data / annot_int) + 1) * annot_int
        # Ensure we don't draw annotated levels twice
        cont_levels = []
        for level in all_levels:
            if level not in annot_levels:
                cont_levels.append(level)

        dem.plot.contour(ax=ax,
                         colors='k',
                         levels=cont_levels,
                         zorder=-1,
                         linewidths=0.3)
        # Use thicker lines for annotated contours
        cs = dem.plot.contour(ax=ax,
                              colors='k',
                              levels=annot_levels,
                              zorder=-1,
                              linewidths=0.7)
        ax.clabel(cs, fontsize=9, fmt='%d', inline=True)  # Actually annotate

        slice_plot_kwargs = dict(ax=ax,
                                 alpha=0.7,
                                 cmap='viridis',
                                 add_colorbar=False,
                                 add_labels=False)

        # Mask areas outside of DEM extent
        # Select subset of DEM that slice occupies
        dem_slice = dem.sel(x=slice.x, y=slice.y, method='nearest')
        slice.data[np.isnan(dem_slice.data)] = np.nan

    if S.UTM:
        # imshow works well here (no gridlines in translucent plot)
        sm = slice.plot.imshow(zorder=0, **slice_plot_kwargs)

        plot_transform = ax.transData

        # Label axes according to choice of xy_grid or not
        if xy_grid:
            ax.set_xlabel('X [m]')
            ax.set_ylabel('Y [m]')
        else:
            ax.set_xlabel('UTM easting [m]')
            ax.set_ylabel('UTM northing [m]')
            ax.ticklabel_format(style='plain', useOffset=False)

    else:
        # imshow performs poorly for Albers equal-area projection - use
        # pcolormesh instead (gridlines will show in translucent plot)
        sm = slice.plot.pcolormesh(transform=transform, **slice_plot_kwargs)

    # Initialize list of handles for legend
    h = [None, None, None]
    scatter_zorder = 5

    # Plot center of grid
    h[0] = ax.scatter(lon_0,
                      lat_0,
                      s=50,
                      color='limegreen',
                      edgecolor='black',
                      label='Grid center',
                      transform=plot_transform,
                      zorder=scatter_zorder)

    # Plot stack maximum
    if S.UTM:
        # x/y formatting
        label = 'Stack max'
    else:
        # Lat/lon formatting
        label = f'Stack max\n({y_max:.4f}, {x_max:.4f})'
    h[1] = ax.scatter(x_max,
                      y_max,
                      s=100,
                      color='red',
                      marker='*',
                      edgecolor='black',
                      label=label,
                      transform=plot_transform,
                      zorder=scatter_zorder)

    # Plot stations
    for tr in st:
        h[2] = ax.scatter(tr.stats.longitude,
                          tr.stats.latitude,
                          marker='v',
                          color='orange',
                          edgecolor='black',
                          label='Station',
                          transform=plot_transform,
                          zorder=scatter_zorder)
        if label_stations:
            ax.text(tr.stats.longitude,
                    tr.stats.latitude,
                    '  {}.{}'.format(tr.stats.network, tr.stats.station),
                    verticalalignment='center_baseline',
                    horizontalalignment='left',
                    fontsize=10,
                    color='white',
                    transform=plot_transform,
                    zorder=scatter_zorder,
                    path_effects=[
                        pe.Stroke(linewidth=2, foreground='black'),
                        pe.Normal()
                    ],
                    clip_on=True)

    ax.legend(h, [handle.get_label() for handle in h],
              loc='best',
              framealpha=1,
              borderpad=.3,
              handletextpad=.3)

    time_round = np.datetime64(slice.time.values + np.timedelta64(500, 'ms'),
                               's').astype(datetime)  # Nearest second
    title = 'Time: {}'.format(time_round)

    if hasattr(S, 'celerity'):
        title += f'\nCelerity: {S.celerity:g} m/s'

    # Label global maximum if applicable
    if slice.time.values == time_max:
        title = 'GLOBAL MAXIMUM\n\n' + title

    ax.set_title(title, pad=20)

    # Show x- and y-axes w/ same scale if this is a Cartesian plot
    if S.UTM:
        ax.set_aspect('equal')

    # Crop plot to show just the slice area
    if xy_grid:
        ax.set_xlim(-xy_grid, xy_grid)
        ax.set_ylim(-xy_grid, xy_grid)

    ax_pos = ax.get_position()
    cloc = [ax_pos.x1 + .02, ax_pos.y0, .02, ax_pos.height]
    cbaxes = fig.add_axes(cloc)
    cbar = fig.colorbar(sm, cax=cbaxes, label='Stack amplitude')
    cbar.solids.set_alpha(1)

    if plot_peak:
        plot_stack_peak(S, plot_max=True, ax=ax1)

    fig.show()

    return fig
modes = ('mean', 'mean_flip', 'pca_flip')
tcs = dict()
for mode in modes:
    tcs[mode] = stc.extract_label_time_course(label, src, mode=mode)
print("Number of vertices : %d" % len(stc_label.data))

# %%
# View source activations
# -----------------------

fig, ax = plt.subplots(1)
t = 1e3 * stc_label.times
ax.plot(t, stc_label.data.T, 'k', linewidth=0.5, alpha=0.5)
pe = [
    path_effects.Stroke(linewidth=5, foreground='w', alpha=0.5),
    path_effects.Normal()
]
for mode, tc in tcs.items():
    ax.plot(t, tc[0], linewidth=3, label=str(mode), path_effects=pe)
xlim = t[[0, -1]]
ylim = [-27, 22]
ax.legend(loc='upper right')
ax.set(xlabel='Time (ms)',
       ylabel='Source amplitude',
       title='Activations in Label %r' % (label.name),
       xlim=xlim,
       ylim=ylim)
mne.viz.tight_layout()

# %%
# Using vector solutions
Beispiel #11
0
def draw_outline(patch: patches.Patch, lw: int) -> None:
    stroke = patheffects.Stroke(linewidth=lw, foreground='black')
    normal = patheffects.Normal()
    patch.set_path_effects([stroke, normal])
Beispiel #12
0
def draw_total_precipitation(prep,
                             map_extent=(107., 112, 23.2, 26.5),
                             back_image='terrain-background',
                             back_image_zoom=8,
                             title="降水量实况图",
                             draw_station=True,
                             station_info='cities',
                             station_size=22,
                             just_contourf=False):
    """
    该程序用于显示多日的累积降水量分布特征, 2020/6/7按业务要求制作.

    Args:
        ax (matplotlib.axes.Axes): the `Axes` instance used for plotting.
        prep (dictionary): precipitation, dictionary: {'lon': 1D array, 'lat': 1D array, 'data': 2D array}
        map_extent (tuple, optional): (lonmin, lonmax, latmin, latmax),. Defaults to (107., 112, 23.2, 26.5).
        back_image (str, opional): the background image name. Default is stamen 'terrain-background', else is
                                      arcgis map server 'World_Physical_Map' (max zoom level is 8)
        back_image_zoom (int, optional): the zoom level for background image. Defaults to 8.
        draw_station (bool, optional): draw station name. Defaults to True.
        station_info (str, optional): station information, 'cities' is 260 city names, or province captial shows.
        station_size (int, optional): station font size. Defaults to 22.
        title (str, optional): title string. Defaults to "降水量实况图".
    
    Example:
        import pandas as pd
        from nmc_met_graphics.plot.precipitation import draw_total_precipitation
        from nmc_met_io.retrieve_micaps_server import get_model_grids

        # read data
        times = pd.date_range(start = pd.to_datetime('2020-06-02 08:00'), end =  pd.to_datetime('2020-06-07 08:00'), freq='1H')
        dataset = get_model_grids("CLDAS/RAIN01_TRI_DATA_SOURCE", times.strftime("%y%m%d%H.000"))
        data = dataset.sum(dim="time")
        data['data'].values[data['data'].values > 2400.0] = np.nan
        prep = {'lon': data['lon'].values, 'lat': data['lat'].values, 'data': data['data'].values}

        # draw the figure
        draw_total_precipitation(prep);
    """

    # set figure size
    fig = plt.figure(figsize=(16, 14.5))

    # set map projection
    datacrs = ccrs.PlateCarree()
    mapcrs = ccrs.LambertConformal(central_longitude=np.mean(map_extent[0:1]),
                                   central_latitude=np.mean(map_extent[2:3]),
                                   standard_parallels=(30, 60))
    ax = plt.axes((0.1, 0.08, 0.85, 0.92), projection=mapcrs)
    ax.set_extent(map_extent, crs=datacrs)

    # add map background
    add_china_map_2cartopy(ax, name='province', edgecolor='k', lw=1)
    add_china_map_2cartopy(ax, name='river', edgecolor='cyan', lw=1)
    if back_image == 'terrain-background':
        stamen_terrain = cimg.Stamen('terrain-background')
        ax.add_image(stamen_terrain, back_image_zoom)
    else:
        image = cimg.GoogleTiles(
            url=
            "https://server.arcgisonline.com/arcgis/rest/services/World_Physical_Map/MapServer/tile/{z}/{y}/{x}.jpg"
        )
        ax.add_image(image, back_image_zoom)

    # set colors and levels
    clevs = [50, 100, 200, 300, 400, 500, 600]
    colors = [
        '#6ab4f1', '#0001f6', '#f405ee', '#ffa900', '#fc6408', '#e80000',
        '#9a0001'
    ]
    linewidths = [1, 1, 2, 2, 3, 4, 4]
    cmap, norm = mpl.colors.from_levels_and_colors(clevs, colors, extend='max')

    # draw precipitation contour map
    x, y = np.meshgrid(prep['lon'], prep['lat'])
    if just_contourf:
        _ = ax.contourf(x,
                        y,
                        np.squeeze(prep['data']),
                        clevs,
                        norm=norm,
                        cmap=cmap,
                        transform=datacrs,
                        extend='max',
                        alpha=0.5)
    else:
        _ = ax.contourf(x,
                        y,
                        np.squeeze(prep['data']),
                        clevs,
                        norm=norm,
                        cmap=cmap,
                        transform=datacrs,
                        extend='max',
                        alpha=0.1)
        con2 = ax.contour(x,
                          y,
                          np.squeeze(prep['data']),
                          clevs,
                          norm=norm,
                          cmap=cmap,
                          transform=datacrs,
                          linewidths=linewidths)
        # add path effects
        plt.setp(con2.collections,
                 path_effects=[
                     path_effects.SimpleLineShadow(),
                     path_effects.Normal()
                 ])

    # add title and legend
    font = FontProperties(family='Microsoft YaHei', size=32)
    ax.set_title('降水量实况图(累计降水: 6月02日—6月06日)',
                 loc='center',
                 fontproperties=font)
    font = FontProperties(family='Microsoft YaHei', size=16)
    plt.legend([mpatches.Patch(color=b) for b in colors], [
        '50~100 毫米', '100~200 毫米', '200-300 毫米', '300~400 毫米', '400~500 毫米',
        '500~600 毫米', '>=600毫米'
    ],
               prop=font)

    # add city information
    if draw_station:
        if station_info == 'cities':
            cities = pd.read_csv(pkg_resources.resource_filename(
                'nmc_met_graphics',
                "resources/stations/cma_city_station_info.dat"),
                                 delimiter=r"\s+")
        else:
            cities = pd.read_csv(
                pkg_resources.resource_filename(
                    'nmc_met_graphics',
                    "resources/stations/provincial_capital.csv"))
        font = FontProperties(family='SimHei', size=22, weight='bold')
        geodetic_transform = ccrs.Geodetic()._as_mpl_transform(ax)
        for _, row in cities.iterrows():
            text_transform = offset_copy(geodetic_transform,
                                         units='dots',
                                         x=-5)
            ax.plot(row['lon'],
                    row['lat'],
                    marker='o',
                    color='white',
                    markersize=8,
                    alpha=0.7,
                    transform=datacrs)
            ax.text(row['lon'],
                    row['lat'],
                    row['city_name'],
                    clip_on=True,
                    verticalalignment='center',
                    horizontalalignment='right',
                    transform=text_transform,
                    fontproperties=font,
                    color='white',
                    path_effects=[
                        path_effects.Stroke(linewidth=1, foreground='black'),
                        path_effects.Normal()
                    ])

    return fig
Beispiel #13
0
def single_plot(robot,
                p,
                fig,
                link_plot,
                joint_plot,
                eff_plot,
                cfg_path_plots=None,
                path_history=None,
                save_dir=None,
                ax=None):
    from copy import copy
    from matplotlib.lines import Line2D
    points_traj = robot.fkine(p)
    points_traj = torch.cat([torch.zeros(len(p), 1, 2), points_traj], dim=1)
    traj_alpha = 0.3
    ends_alpha = 0.5

    lw = link_plot.get_lw()
    link_traj = [
        ax.plot(points[:, 0],
                points[:, 1],
                color='gray',
                alpha=traj_alpha,
                lw=lw,
                solid_capstyle='round')[0] for points in points_traj
    ]
    joint_traj = [
        ax.plot(points[:-1, 0],
                points[:-1, 1],
                'o',
                color='tab:red',
                alpha=traj_alpha,
                markersize=lw)[0] for points in points_traj
    ]
    eff_traj = [
        ax.plot(points[-1:, 0],
                points[-1:, 1],
                'o',
                color='black',
                alpha=traj_alpha,
                markersize=lw)[0] for points in points_traj
    ]
    # for link_plot, joint_plot, eff_plot, points in zip(link_traj, joint_traj, eff_traj, points_traj):
    #     link_plot.set_data(points[:, 0], points[:, 1])
    #     joint_plot.set_data(points[:-1, 0], points[:-1, 1])
    #     eff_plot.set_data(points[-1:, 0], points[-1:, 1])
    for i in [0, -1]:
        link_traj[i].set_alpha(ends_alpha)
        link_traj[i].set_path_effects(
            [path_effects.SimpleLineShadow(),
             path_effects.Normal()])
        joint_traj[i].set_alpha(ends_alpha)
        eff_traj[i].set_alpha(ends_alpha)
    link_traj[0].set_color('green')
    link_traj[-1].set_color('orange')
    # ax.add_artist(link_traj[2])

    # def divide(p): # divide the path into several segments that obeys the wrapping around rule [TODO]
    #     diff = torch.abs(p[:-1]-p[1:])
    #     div_idx = torch.where(diff.max(1) > np.pi)
    #     div_idx = torch.cat([-1, div_idx])
    #     segments = []
    #     for i in range(len(div_idx)-1):
    #         segments.append(p[div_idx[i]+1:div_idx[i+1]+1])
    #     segments.append(p[div_idx[-1]+1:])
    #     for i in range(len(segments)-1):
    #         if torch.sum(torch.abs(segments[i]) > np.pi) == 2:

    offset = torch.FloatTensor([[0, 0], [0, 1], [-1, 1], [-1, 0]]) * np.pi * 2
    for i, cfg_path in enumerate(cfg_path_plots):
        cfg_path.set_data(p[:, 0] + offset[i % 4, 0],
                          p[:, 1] + offset[i % 4, 1])
Beispiel #14
0
def create_plots(robot, obstacles, dist_est, checker):
    from matplotlib.cm import get_cmap
    cmaps = [get_cmap('Reds'), get_cmap('Blues')]

    if robot.dof > 2:
        fig = plt.figure(figsize=(3, 3))
        ax = fig.add_subplot(111)  #, projection='3d'
    elif robot.dof == 2:
        # Show C-space at the same time
        num_class = getattr(checker, 'num_class', 1)
        fig = plt.figure(figsize=(3 * (num_class), 3 * (num_class + 1)))
        plt.rcParams.update({
            "text.usetex": True,
            "font.family": "sans-serif",
            "font.sans-serif": ["Helvetica"]
        })
        gs = fig.add_gridspec(num_class + 1, num_class)
        ax = fig.add_subplot(
            gs[:-1, :]
        )  #sum([list(range(r*(num_class+1)+1, (r+1)*(num_class+1))) for r in range(num_class)], [])) #, projection='3d'
        cfg_path_plots = []

        size = [400, 400]
        yy, xx = torch.meshgrid(torch.linspace(-np.pi, np.pi, size[0]),
                                torch.linspace(-np.pi, np.pi, size[1]))
        grid_points = torch.stack([xx, yy], dim=2).reshape((-1, 2))
        grid_points = grid_points.double(
        ) if checker.support_points.dtype == torch.float64 else grid_points
        score_spline = dist_est(grid_points).reshape(size + [num_class])
        c_axes = []
        with sns.axes_style('ticks'):
            for cat in range(num_class):
                c_ax = fig.add_subplot(gs[-1, cat])

                # score_DiffCo = checker.score(grid_points).reshape(size)
                # score = (torch.sign(score_DiffCo)+1)/2*(score_spline-score_spline.min()) + (-torch.sign(score_DiffCo)+1)/2*(score_spline-score_spline.max())
                score = score_spline[:, :, cat]
                color_mesh = c_ax.pcolormesh(xx,
                                             yy,
                                             score,
                                             cmap=cmaps[cat],
                                             vmin=-torch.abs(score).max(),
                                             vmax=torch.abs(score).max())
                c_support_points = checker.support_points[
                    checker.gains[:, cat] != 0]
                c_ax.scatter(c_support_points[:, 0],
                             c_support_points[:, 1],
                             marker='.',
                             c='black',
                             s=1.5)
                c_ax.contour(
                    xx,
                    yy,
                    score,
                    levels=[0],
                    linewidths=1,
                    alpha=0.4,
                )  #-1.5, -0.75, 0, 0.3
                # fig.colorbar(color_mesh, ax=c_ax)
                # sparse_score = score[5:-5:10, 5:-5:10]
                # score_grad_x = -ndimage.sobel(sparse_score.numpy(), axis=1)
                # score_grad_y = -ndimage.sobel(sparse_score.numpy(), axis=0)
                # score_grad = np.stack([score_grad_x, score_grad_y], axis=2)
                # score_grad /= np.linalg.norm(score_grad, axis=2, keepdims=True)
                # score_grad_x, score_grad_y = score_grad[:, :, 0], score_grad[:, :, 1]
                # c_ax.quiver(xx[5:-5:10, 5:-5:10], yy[5:-5:10, 5:-5:10], score_grad_x, score_grad_y, color='red', width=2e-3, headwidth=2, headlength=5)
                # cfg_point = Circle(collision_cfgs[0], radius=0.05, facecolor='orange', edgecolor='black', path_effects=[path_effects.withSimplePatchShadow()])
                # c_ax.add_patch(cfg_point)
                for _ in range(4):
                    cfg_path, = c_ax.plot([], [],
                                          '-o',
                                          c='olivedrab',
                                          markersize=3)
                    cfg_path_plots.append(cfg_path)

                c_ax.set_aspect('equal', adjustable='box')
                # c_ax.axis('equal')
                c_ax.set_xlim(-np.pi, np.pi)
                c_ax.set_ylim(-np.pi, np.pi)
                c_ax.set_xticks([-np.pi, 0, np.pi])
                c_ax.set_xticklabels(['$-\pi$', '$0$', '$\pi$'])
                c_ax.set_yticks([-np.pi, 0, np.pi])
                c_ax.set_yticklabels(['$-\pi$', '$0$', '$\pi$'])
                # c_ax.tick_params(direction='in', reset=True)
                # c_ax.tick_params(which='both', direction='out', length=6, width=2, colors='r',
                #    grid_color='r', grid_alpha=0.5)
            # c_ax.set_ticks('')

    # Plot ostacles
    # ax.axis('tight')
    ax.set_xlim(-8, 8)
    ax.set_ylim(-8, 8)
    ax.set_aspect('equal', adjustable='box')
    ax.set_xticks([-4, 0, 4])
    ax.set_yticks([-4, 0, 4])
    for obs in obstacles:
        cat = obs[3] if len(obs) >= 4 else 1
        if obs[0] == 'circle':
            ax.add_patch(
                Circle(obs[1],
                       obs[2],
                       path_effects=[path_effects.withSimplePatchShadow()],
                       color=cmaps[cat](0.5)))
        elif obs[0] == 'rect':
            ax.add_patch(
                Rectangle((obs[1][0] - float(obs[2][0]) / 2,
                           obs[1][1] - float(obs[2][1]) / 2),
                          obs[2][0],
                          obs[2][1],
                          path_effects=[path_effects.withSimplePatchShadow()],
                          color=cmaps[cat](0.5)))
            # print((obs[1][0]-obs[2][0]/2, obs[1][1]-obs[2][1]/2))

    # Placeholder of the robot plot
    trans = ax.transData.transform
    lw = ((trans((1, robot.link_width)) - trans(
        (0, 0))) * 72 / ax.figure.dpi)[1]
    link_plot, = ax.plot(
        [], [],
        color='silver',
        alpha=0.1,
        lw=lw,
        solid_capstyle='round',
        path_effects=[path_effects.SimpleLineShadow(),
                      path_effects.Normal()])
    joint_plot, = ax.plot([], [], 'o', color='tab:red', markersize=lw)
    eff_plot, = ax.plot([], [], 'o', color='black', markersize=lw)

    if robot.dof > 2:
        return fig, ax, link_plot, joint_plot, eff_plot
    elif robot.dof == 2:
        return fig, ax, link_plot, joint_plot, eff_plot, cfg_path_plots
Beispiel #15
0
    def plot_calma_data(self, loudnessValues, features, duration, type,
                        **kwargs):
        """
    Takes CALMA data for a single track as input, and creates a plot.

    Parameters
    ----------
    loudnessValues : float[]
        An array of loudness / amplitude values.
    features : float[]
        Features information.
    duration : float
        The duration of the track.
    """

        # Replace colour map if needed
        if type == 'segment':
            self.colourMap = self.get_segment_colour_map(features)
        if type == 'key': self.colourMap = self.get_colour_map()

        # Hide placeholder text if visible
        try:
            self.placeHolderText.remove()
            text = self.fig.text(0.5,
                                 0.65,
                                 kwargs['title'],
                                 horizontalalignment='center',
                                 verticalalignment='center',
                                 fontsize=16)
            text.set_path_effects([
                path_effects.Stroke(linewidth=2, foreground='white'),
                path_effects.Normal()
            ])

        except (KeyError, ValueError) as v:
            self.placeHolderText.set_text('')

        # Perform pre-processing
        nploudnessValues, duration, xSpaced, average = self.pre_processing(
            loudnessValues, duration)

        # Plot waveform
        self.canvasGraph.axes.cla()
        self.canvasGraph.plot(xSpaced, nploudnessValues)

        for index, key in enumerate(features):
            # Calculate graph positions
            lx, ly, rec = self.calculate_graph_element_position(
                features, key, index, duration, average)

            # Add annotation to plot
            self.canvasGraph.annotate(key[1], (lx, ly),
                                      weight='bold',
                                      color='Black',
                                      fontsize=7,
                                      ha='center',
                                      va='center',
                                      rotation=270)
            self.ax.add_artist(rec)

        # Set axes labels
        self.ax.set_yticklabels([])
        self.ax.set_xlabel("Time (seconds)")

        # Add colour legend for keys
        keysAsSet = list(set([x[1] for x in features]))
        patches = []

        for k in keysAsSet:
            # Plot rectangle for key changes
            try:
                fc = self.colourMap[k]
            except KeyError as keyerr:
                fc = 'grey'

            patch = mpatch.Patch(color=fc, label=k)
            patches.append(patch)

        self.canvasGraph.legend(handles=patches,
                                bbox_to_anchor=(1.00, 1),
                                loc=2,
                                borderaxespad=0,
                                fontsize=7,
                                ncol=2)
        self.fig.subplots_adjust(left=0.00, right=0.85, top=0.95)

        try:
            kwargs['release']
        except KeyError as v:
            # Causes crash with multiple plots
            self.finishDraw()

        self.fig.patch.set_alpha(1.0)
        return
Beispiel #16
0
    def plot_storm_nrl(self,
                       forecast,
                       track=None,
                       image_path=os.getcwd(),
                       track_labels='fhr',
                       cone_days=5,
                       domain="dynamic_forecast",
                       ax=None,
                       return_ax=False,
                       prop={},
                       map_prop={}):
        r"""
        Creates a plot of the operational NRL forecast track along with observed track data.
        
        Parameters
        ----------
        forecast : dict
            Dict entry containing forecast data.
        track : dict
            Dict entry containing observed track data. Default is none.
        track_labels : str
            Label forecast hours with the following methods:
            '' = no label
            'fhr' = forecast hour
            'valid_utc' = UTC valid time
            'valid_edt' = EDT valid time
        cone_days : int
            Number of days to plot the forecast cone. Default is 5 days. Can select 2, 3, 4 or 5 days.
        domain : str
            Domain for the plot. Can be one of the following:
            "dynamic_forecast" - default. Dynamically focuses the domain on the forecast track.
            "dynamic" - Dynamically focuses the domain on the combined observed and forecast track.
            "lonW/lonE/latS/latN" - Custom plot domain
        ax : axes
            Instance of axes to plot on. If none, one will be generated. Default is none.
        return_ax : bool
            Whether to return axis at the end of the function. If false, plot will be displayed on the screen. Default is false.
        prop : dict
            Property of storm track lines.
        map_prop : dict
            Property of cartopy map.
        """

        #Determine if forecast is realtime
        realtime_flag = True if forecast['advisory_num'] == -1 else False

        #Set default properties
        default_prop = {
            'dots': True,
            'fillcolor': 'category',
            'linecolor': 'k',
            'category_colors': 'default',
            'linewidth': 1.0,
            'ms': 7.5,
            'cone_lw': 1.0,
            'cone_alpha': 0.6
        }
        default_map_prop = {
            'res': 'm',
            'land_color': '#FBF5EA',
            'ocean_color': '#EDFBFF',
            'linewidth': 0.5,
            'linecolor': 'k',
            'figsize': (14, 9),
            'dpi': 200
        }

        #Initialize plot
        prop = self.add_prop(prop, default_prop)
        map_prop = self.add_prop(map_prop, default_map_prop)
        self.plot_init(ax, map_prop)

        #--------------------------------------------------------------------------------------

        #Keep record of lat/lon coordinate extrema
        max_lat = None
        min_lat = None
        max_lon = None
        min_lon = None

        #Add storm or multiple storms
        if track != "":

            #Check for storm type, then get data for storm
            if isinstance(track, dict) == True:
                storm_data = track
            else:
                raise RuntimeError("Error: track must be of type dict.")

            #Retrieve storm data
            lats = storm_data['lat']
            lons = storm_data['lon']
            vmax = storm_data['vmax']
            styp = storm_data['type']
            sdate = storm_data['date']

            #Check if there's enough data points to plot
            matching_times = [i for i in sdate if i <= forecast['init']]
            check_length = len(matching_times)
            if check_length >= 2:

                #Subset until time of forecast
                matching_times = [i for i in sdate if i <= forecast['init']]
                plot_idx = sdate.index(matching_times[-1]) + 1
                lats = storm_data['lat'][:plot_idx]
                lons = storm_data['lon'][:plot_idx]
                vmax = storm_data['vmax'][:plot_idx]
                styp = storm_data['type'][:plot_idx]
                sdate = storm_data['date'][:plot_idx]

                #Account for cases crossing dateline
                if self.proj.proj4_params['lon_0'] == 180.0:
                    new_lons = np.array(lons)
                    new_lons[new_lons < 0] = new_lons[new_lons < 0] + 360.0
                    lons = new_lons.tolist()

                #Connect to 1st forecast location
                fcst_hr = np.array(forecast['fhr'])
                start_slice = 0
                if 3 in fcst_hr: start_slice = 3
                if realtime_flag == True: start_slice = int(fcst_hr[1])
                iter_hr = np.array(forecast['fhr'])[fcst_hr >= start_slice][0]
                fcst_lon = np.array(forecast['lon'])[fcst_hr >= start_slice][0]
                fcst_lat = np.array(forecast['lat'])[fcst_hr >= start_slice][0]
                fcst_type = np.array(
                    forecast['type'])[fcst_hr >= start_slice][0]
                fcst_vmax = np.array(
                    forecast['vmax'])[fcst_hr >= start_slice][0]
                if fcst_type == "":
                    fcst_type = get_storm_type(fcst_vmax, False)
                if self.proj.proj4_params['lon_0'] == 180.0:
                    if fcst_lon < 0: fcst_lon = fcst_lon + 360.0
                lons.append(fcst_lon)
                lats.append(fcst_lat)
                vmax.append(fcst_vmax)
                styp.append(fcst_type)
                sdate.append(sdate[-1] + timedelta(hours=start_slice))

                #Add to coordinate extrema
                if domain != "dynamic_forecast":
                    if max_lat == None:
                        max_lat = max(lats)
                    else:
                        if max(lats) > max_lat: max_lat = max(lats)
                    if min_lat == None:
                        min_lat = min(lats)
                    else:
                        if min(lats) < min_lat: min_lat = min(lats)
                    if max_lon == None:
                        max_lon = max(lons)
                    else:
                        if max(lons) > max_lon: max_lon = max(lons)
                    if min_lon == None:
                        min_lon = min(lons)
                    else:
                        if min(lons) < min_lon: min_lon = min(lons)
                else:
                    max_lat = lats[-1] + 0.2
                    min_lat = lats[-2] - 0.2
                    max_lon = lons[-1] + 0.2
                    min_lon = lons[-2] - 0.2

                #Plot storm line as specified
                if prop['linecolor'] == 'category':
                    type6 = np.array(styp)
                    for i in (np.arange(len(lats[1:])) + 1):
                        ltype = 'solid'
                        if type6[i] not in ['SS', 'SD', 'TD', 'TS', 'HU']:
                            ltype = 'dotted'
                        self.ax.plot(
                            [lons[i - 1], lons[i]], [lats[i - 1], lats[i]],
                            '-',
                            color=get_colors_sshws(np.nan_to_num(vmax[i])),
                            linewidth=prop['linewidth'],
                            linestyle=ltype,
                            transform=ccrs.PlateCarree(),
                            path_effects=[
                                path_effects.Stroke(
                                    linewidth=prop['linewidth'] * 1.25,
                                    foreground='k'),
                                path_effects.Normal()
                            ])
                else:
                    self.ax.plot(lons,
                                 lats,
                                 '-',
                                 color=prop['linecolor'],
                                 linewidth=prop['linewidth'],
                                 transform=ccrs.PlateCarree())

                #Plot storm dots as specified
                if prop['dots'] == True:
                    #filter dots to only 6 hour intervals
                    time_hr = np.array([i.strftime('%H%M') for i in sdate])
                    #time_idx = np.where((time_hr == '0300') | (time_hr == '0900') | (time_hr == '1500') | (time_hr == '2100'))
                    lat6 = np.array(lats)  #[time_idx]
                    lon6 = np.array(lons)  #[time_idx]
                    vmax6 = np.array(vmax)  #[time_idx]
                    type6 = np.array(styp)  #[time_idx]
                    for i, (ilon, ilat, iwnd,
                            itype) in enumerate(zip(lon6, lat6, vmax6, type6)):
                        mtype = '^'
                        if itype in ['SD', 'SS']:
                            mtype = 's'
                        elif itype in ['TD', 'TS', 'HU']:
                            mtype = 'o'
                        if prop['fillcolor'] == 'category':
                            ncol = get_colors_sshws(np.nan_to_num(iwnd))
                        else:
                            ncol = 'k'
                        self.ax.plot(ilon,
                                     ilat,
                                     mtype,
                                     color=ncol,
                                     mec='k',
                                     mew=0.5,
                                     ms=prop['ms'],
                                     transform=ccrs.PlateCarree())

        #--------------------------------------------------------------------------------------

        #Error check cone days
        if isinstance(cone_days, int) == False:
            raise TypeError("Error: cone_days must be of type int")
        if cone_days not in [5, 4, 3, 2]:
            raise ValueError(
                "Error: cone_days must be an int between 2 and 5.")

        #Error check forecast dict
        if isinstance(forecast, dict) == False:
            raise RuntimeError("Error: Forecast must be of type dict")

        #Determine first forecast index
        fcst_hr = np.array(forecast['fhr'])
        start_slice = 0
        if 3 in fcst_hr: start_slice = 3
        if realtime_flag == True: start_slice = int(fcst_hr[1])
        check_duration = fcst_hr[(fcst_hr >= start_slice)
                                 & (fcst_hr <= cone_days * 24)]

        #Check for sufficiently many hours
        if len(check_duration) > 1:

            #Generate forecast cone for forecast data
            dateline = False
            if self.proj.proj4_params['lon_0'] == 180.0: dateline = True
            cone = self.generate_nrl_cone(forecast, dateline, cone_days)

            #Contour fill cone & account for dateline crossing
            if 'cone' in forecast.keys() and forecast['cone'] == False:
                pass
            else:
                cone_lon = cone['lon']
                cone_lat = cone['lat']
                cone_lon_2d = cone['lon2d']
                cone_lat_2d = cone['lat2d']
                if self.proj.proj4_params['lon_0'] == 180.0:
                    new_lons = np.array(cone_lon_2d)
                    new_lons[new_lons < 0] = new_lons[new_lons < 0] + 360.0
                    cone_lon_2d = new_lons.tolist()
                    new_lons = np.array(cone_lon)
                    new_lons[new_lons < 0] = new_lons[new_lons < 0] + 360.0
                    cone_lon = new_lons.tolist()
                cone_2d = cone['cone']
                cone_2d = ndimage.gaussian_filter(cone_2d, sigma=0.5, order=0)
                self.ax.contourf(cone_lon_2d,
                                 cone_lat_2d,
                                 cone_2d, [0.9, 1.1],
                                 colors=['#ffffff', '#ffffff'],
                                 alpha=prop['cone_alpha'],
                                 zorder=2,
                                 transform=ccrs.PlateCarree())
                self.ax.contour(cone_lon_2d,
                                cone_lat_2d,
                                cone_2d, [0.9],
                                linewidths=prop['cone_lw'],
                                colors=['k'],
                                zorder=3,
                                transform=ccrs.PlateCarree())

            #Plot center line & account for dateline crossing
            center_lon = cone['center_lon']
            center_lat = cone['center_lat']
            if self.proj.proj4_params['lon_0'] == 180.0:
                new_lons = np.array(center_lon)
                new_lons[new_lons < 0] = new_lons[new_lons < 0] + 360.0
                center_lon = new_lons.tolist()
            self.ax.plot(center_lon,
                         center_lat,
                         color='k',
                         linewidth=2.0,
                         zorder=4,
                         transform=ccrs.PlateCarree())

            #Retrieve forecast dots
            iter_hr = np.array(forecast['fhr'])[(fcst_hr >= start_slice)
                                                & (fcst_hr <= cone_days * 24)]
            fcst_lon = np.array(forecast['lon'])[(fcst_hr >= start_slice)
                                                 & (fcst_hr <= cone_days * 24)]
            fcst_lat = np.array(forecast['lat'])[(fcst_hr >= start_slice)
                                                 & (fcst_hr <= cone_days * 24)]
            fcst_type = np.array(
                forecast['type'])[(fcst_hr >= start_slice)
                                  & (fcst_hr <= cone_days * 24)]
            fcst_vmax = np.array(
                forecast['vmax'])[(fcst_hr >= start_slice)
                                  & (fcst_hr <= cone_days * 24)]

            #Account for cases crossing dateline
            if self.proj.proj4_params['lon_0'] == 180.0:
                new_lons = np.array(fcst_lon)
                new_lons[new_lons < 0] = new_lons[new_lons < 0] + 360.0
                fcst_lon = new_lons.tolist()

            #Plot forecast dots
            for i, (ilon, ilat, itype, iwnd, ihr) in enumerate(
                    zip(fcst_lon, fcst_lat, fcst_type, fcst_vmax, iter_hr)):
                mtype = '^'
                if itype in ['SD', 'SS']:
                    mtype = 's'
                elif itype in ['TD', 'TS', 'HU', '']:
                    mtype = 'o'
                if prop['fillcolor'] == 'category':
                    ncol = get_colors_sshws(np.nan_to_num(iwnd))
                else:
                    ncol = 'k'
                #Marker width
                mew = 0.5
                use_zorder = 5
                if i == 0:
                    mew = 2.0
                    use_zorder = 10
                self.ax.plot(ilon,
                             ilat,
                             mtype,
                             color=ncol,
                             mec='k',
                             mew=mew,
                             ms=prop['ms'] * 1.3,
                             transform=ccrs.PlateCarree(),
                             zorder=use_zorder)

            #Label forecast dots
            if track_labels in [
                    'fhr', 'valid_utc', 'valid_edt', 'fhr_wind_kt',
                    'fhr_wind_mph'
            ]:
                valid_dates = [
                    forecast['init'] + timedelta(hours=int(i)) for i in iter_hr
                ]
                if track_labels == 'fhr':
                    labels = [str(i) for i in iter_hr]
                if track_labels == 'fhr_wind_kt':
                    labels = [
                        f"Hour {iter_hr[i]}\n{fcst_vmax[i]} kt"
                        for i in range(len(iter_hr))
                    ]
                if track_labels == 'fhr_wind_mph':
                    labels = [
                        f"Hour {iter_hr[i]}\n{knots_to_mph(fcst_vmax[i])} mph"
                        for i in range(len(iter_hr))
                    ]
                if track_labels == 'valid_edt':
                    labels = [
                        str(int(i.strftime('%I'))) + ' ' + i.strftime('%p %a')
                        for i in [j - timedelta(hours=4) for j in valid_dates]
                    ]
                    edt_warning = True
                if track_labels == 'valid_utc':
                    labels = [
                        f"{i.strftime('%H UTC')}\n{str(i.month)}/{str(i.day)}"
                        for i in valid_dates
                    ]
                self.plot_nhc_labels(self.ax,
                                     fcst_lon,
                                     fcst_lat,
                                     labels,
                                     k=1.2)

            #Add cone coordinates to coordinate extrema
            if 'cone' in forecast.keys() and forecast['cone'] == False:
                if domain == "dynamic_forecast" or max_lat == None:
                    max_lat = max(center_lat)
                    min_lat = min(center_lat)
                    max_lon = max(center_lon)
                    min_lon = min(center_lon)
                else:
                    if max(center_lat) > max_lat: max_lat = max(center_lat)
                    if min(center_lat) < min_lat: min_lat = min(center_lat)
                    if max(center_lon) > max_lon: max_lon = max(center_lon)
                    if min(center_lon) < min_lon: min_lon = min(center_lon)
            else:
                if domain == "dynamic_forecast" or max_lat == None:
                    max_lat = max(cone_lat)
                    min_lat = min(cone_lat)
                    max_lon = max(cone_lon)
                    min_lon = min(cone_lon)
                else:
                    if max(cone_lat) > max_lat: max_lat = max(cone_lat)
                    if min(cone_lat) < min_lat: min_lat = min(cone_lat)
                    if max(cone_lon) > max_lon: max_lon = max(cone_lon)
                    if min(cone_lon) < min_lon: min_lon = min(cone_lon)

        #--------------------------------------------------------------------------------------

        #Storm-centered plot domain
        if domain == "dynamic" or domain == 'dynamic_forecast':

            bound_w, bound_e, bound_s, bound_n = self.dynamic_map_extent(
                min_lon, max_lon, min_lat, max_lat)
            self.ax.set_extent([bound_w, bound_e, bound_s, bound_n],
                               crs=ccrs.PlateCarree())

        #Pre-generated or custom domain
        else:
            bound_w, bound_e, bound_s, bound_n = self.set_projection(domain)

        #Plot parallels and meridians
        #This is currently not supported for all cartopy projections.
        try:
            self.plot_lat_lon_lines([bound_w, bound_e, bound_s, bound_n])
        except:
            pass

        #--------------------------------------------------------------------------------------

        #Identify storm type (subtropical, hurricane, etc)
        first_fcst_wind = np.array(forecast['vmax'])[fcst_hr >= start_slice][0]
        first_fcst_mslp = np.array(forecast['mslp'])[fcst_hr >= start_slice][0]
        first_fcst_type = np.array(forecast['type'])[fcst_hr >= start_slice][0]
        if all_nan(first_fcst_wind) == True:
            storm_type = 'Unknown'
        else:
            subtrop = True if first_fcst_type in ['SD', 'SS'] else False
            cur_wind = first_fcst_wind + 0
            storm_type = get_storm_classification(np.nan_to_num(cur_wind),
                                                  subtrop, 'north_atlantic')

        #Identify storm name (and storm type, if post-tropical or potential TC)
        matching_times = [
            i for i in storm_data['date'] if i <= forecast['init']
        ]
        if check_length < 2:
            if all_nan(first_fcst_wind) == True:
                storm_name = storm_data['name']
            else:
                storm_name = num_to_text(int(storm_data['id'][2:4])).upper()
                if first_fcst_wind >= 34 and first_fcst_type in [
                        'TD', 'SD', 'SS', 'TS', 'HU'
                ]:
                    storm_name = storm_data['name']
                if first_fcst_type not in ['TD', 'SD', 'SS', 'TS', 'HU']:
                    storm_type = 'Storm'
        else:
            storm_name = num_to_text(int(storm_data['id'][2:4])).upper()
            storm_type = 'Storm'
            storm_tropical = False
            if all_nan(vmax) == True:
                storm_type = 'Unknown'
                storm_name = storm_data['name']
            else:
                for i, (iwnd, ityp) in enumerate(zip(vmax, styp)):
                    if ityp in ['SD', 'SS', 'TD', 'TS', 'HU']:
                        storm_tropical = True
                        subtrop = True if ityp in ['SD', 'SS'] else False
                        storm_type = get_storm_classification(
                            np.nan_to_num(iwnd), subtrop, 'north_atlantic')
                        if np.isnan(iwnd) == True: storm_type = 'Unknown'
                    else:
                        if storm_tropical == True:
                            storm_type = 'Post Tropical Cyclone'
                    if ityp in ['SS', 'TS', 'HU']:
                        storm_name = storm_data['name']

        #Fix storm types for non-NHC basins
        if 'cone' in forecast.keys():
            storm_type = get_storm_classification(first_fcst_wind, False,
                                                  forecast['basin'])

        #Add left title
        self.ax.set_title(f"{storm_type} {storm_name}",
                          loc='left',
                          fontsize=17,
                          fontweight='bold')

        endash = u"\u2013"
        dot = u"\u2022"

        #Get current advisory information
        first_fcst_wind = "N/A" if np.isnan(first_fcst_wind) == True else int(
            first_fcst_wind)
        first_fcst_mslp = "N/A" if np.isnan(first_fcst_mslp) == True else int(
            first_fcst_mslp)

        #Get time of advisory
        fcst_hr = forecast['fhr']
        start_slice = 0
        if 3 in fcst_hr: start_slice = 1
        if realtime_flag == True: start_slice = 1
        forecast_date = (forecast['init'] + timedelta(
            hours=fcst_hr[start_slice])).strftime("%H%M UTC %d %b %Y")
        forecast_id = forecast['advisory_num']

        #Get wind value to display
        if first_fcst_wind == "N/A":
            wind_display_value = "N/A"
        else:
            wind_display_value = knots_to_mph(first_fcst_wind)

        if forecast_id == -1:
            title_text = f"Current Intensity: {wind_display_value} mph {dot} {first_fcst_mslp} hPa"
            if 'cone' in forecast.keys() and forecast['cone'] == False:
                title_text += f"\nJTWC Issued: {forecast_date}"
            else:
                title_text += f"\nNHC Issued: {forecast_date}"
        else:
            title_text = f"Current Intensity: {wind_display_value} mph {dot} {first_fcst_mslp} hPa"
            title_text += f"\nForecast Issued: {forecast_date}"

        #Add right title
        self.ax.set_title(title_text, loc='right', fontsize=13)

        #--------------------------------------------------------------------------------------

        #Add legend
        if prop['fillcolor'] == 'category' or prop['linecolor'] == 'category':

            ex = mlines.Line2D([], [],
                               linestyle='None',
                               ms=prop['ms'],
                               mec='k',
                               mew=0.5,
                               label='Non-Tropical',
                               marker='^',
                               color='w')
            sb = mlines.Line2D([], [],
                               linestyle='None',
                               ms=prop['ms'],
                               mec='k',
                               mew=0.5,
                               label='Subtropical',
                               marker='s',
                               color='w')
            uk = mlines.Line2D([], [],
                               linestyle='None',
                               ms=prop['ms'],
                               mec='k',
                               mew=0.5,
                               label='Unknown',
                               marker='o',
                               color='w')
            td = mlines.Line2D([], [],
                               linestyle='None',
                               ms=prop['ms'],
                               mec='k',
                               mew=0.5,
                               label='Tropical Depression',
                               marker='o',
                               color=get_colors_sshws(33))
            ts = mlines.Line2D([], [],
                               linestyle='None',
                               ms=prop['ms'],
                               mec='k',
                               mew=0.5,
                               label='Tropical Storm',
                               marker='o',
                               color=get_colors_sshws(34))
            c1 = mlines.Line2D([], [],
                               linestyle='None',
                               ms=prop['ms'],
                               mec='k',
                               mew=0.5,
                               label='Category 1',
                               marker='o',
                               color=get_colors_sshws(64))
            c2 = mlines.Line2D([], [],
                               linestyle='None',
                               ms=prop['ms'],
                               mec='k',
                               mew=0.5,
                               label='Category 2',
                               marker='o',
                               color=get_colors_sshws(83))
            c3 = mlines.Line2D([], [],
                               linestyle='None',
                               ms=prop['ms'],
                               mec='k',
                               mew=0.5,
                               label='Category 3',
                               marker='o',
                               color=get_colors_sshws(96))
            c4 = mlines.Line2D([], [],
                               linestyle='None',
                               ms=prop['ms'],
                               mec='k',
                               mew=0.5,
                               label='Category 4',
                               marker='o',
                               color=get_colors_sshws(113))
            c5 = mlines.Line2D([], [],
                               linestyle='None',
                               ms=prop['ms'],
                               mec='k',
                               mew=0.5,
                               label='Category 5',
                               marker='o',
                               color=get_colors_sshws(137))
            self.ax.legend(handles=[ex, sb, uk, td, ts, c1, c2, c3, c4, c5],
                           prop={'size': 11.5})

        #Add forecast label warning
        try:
            if edt_warning == True:
                warning_text = "All times displayed are in EDT\n\n"
            else:
                warning_text = ""
        except:
            warning_text = ""
        try:
            warning_text += f"The cone of uncertainty in this product was generated internally\nusing {cone['year']} derived NRL cone radii.\n\n"
        except:
            pass

        self.ax.text(0.99,
                     0.01,
                     warning_text,
                     fontsize=9,
                     color='k',
                     alpha=0.7,
                     transform=self.ax.transAxes,
                     ha='right',
                     va='bottom',
                     zorder=10)

        credit_text = self.plot_credit()
        self.add_credit(credit_text)

        #Return axis if specified, otherwise display figure
        if ax != None or return_ax == True:
            return self.ax
        else:
            plt.savefig(
                f"{image_path}/{track['id']}_{forecast_date.replace(' ','')}")
            plt.close()
Beispiel #17
0
hts = np.array([extract(m, "Elevation") for m in mountains])

# Histogram plot of mountain heights.

with plt.xkcd():  # Cueball: "Why?"  Black hat: "Why not?"
    plt.hist(hts, 20, facecolor='cyan', alpha=0.75)
    plt.figure(1)
    print("Histogram of the heights of named mountains.")
    plt.xlabel("Mountain height")
    plt.ylabel("Mountain count")
    plt.show(1)

# Ordinary data plot of mountain heights.

plt.figure(2)
pef = [path_effects.SimpleLineShadow(), path_effects.Normal()]
plt.plot(np.sort(hts), '--', path_effects=pef)
print("Heights of the mountains of the world.")
plt.show(2)

with open('countries.json', encoding="utf-8") as data_file:
    countries = json.load(data_file)

pops = np.array([extract(c, "Population") for c in countries])
gdp = np.array([extract(c, "GDP") for c in countries])
gdppc = gdp / pops
pops_log = np.log(pops) / np.log(10)

# Scatter plot of population against GDP per person.

plt.figure(3)
Beispiel #18
0
def _draw_outline(o, lw: int):
    "Outline bounding box onto image `Patch`."
    o.set_path_effects([
        patheffects.Stroke(linewidth=lw, foreground='black'),
        patheffects.Normal()
    ])
Beispiel #19
0
def stremline_plot(adata, genes, x=0, y=1, method='sparseVFC', basis='trimap', n_columns=1, color=None, label_on_embedding=True,
                   cmap=None, s_kwargs_dict={}, layer='X', xy_grid_nums=[30, 30], density=1, g_kwargs_dict={},
                   V_threshold=1e-5, figsize=None, show_quiver=True, **streamline_kwargs):
    """Plot the streamline of vector field based on the sampled cells.

    Parameters
    ----------
        adata: :class:`~anndata.AnnData`
            an Annodata object.
        genes: `list`
            The gene names whose gene expression will be faceted.
        x: `int` (default: `0`)
            The column index of the low dimensional embedding for the x-axis
        y: `int` (default: `1`)
            The column index of the low dimensional embedding for the y-axis
        method: `str` (default: `SparseVFC`)
            Method to reconstruct the vector field. Currently it supports either SparseVFC (default) or the empirical method
            Gaussian kernel method from RNA velocity (Gaussian).
        basis: `str` (default: `trimap`)
            The reduced dimension embedding of cells to visualize.
        n_columns: `int  (default: 1)
            The number of columns of the resulting plot.
        color: `list` or None (default: None)
            A list of attributes of cells (column names in the adata.obs) will be used to color cells.
        cmap: `plt.cm` or None (default: None)
            The color map function to use.
        s_kwargs_dict: `dict` (default: {})
            The dictionary of the scatter arguments.
        layer: `str` (default: X)
            Which layer of expression value will be used.
        xy_grid_nums: `tuple` (default: (5, 5))
            the number of grids in either x or y axis.
        density: `float` or None (default: 1)
            density of the plt.streamplot function.
        q_kwargs_dict: `dict` (default: {})
            A dictionary of the parameters for the plt.quiver function.
        V_threshold: `None` or `float`
            The threshold of velocity value for visualization
        figsize: `None` or `[float, float]` (default: None)
            The width and height of a figure.
        show_quiver: `bool` (default: True)
            Whether also show the quiver plot in additional to the streamline plot.
        **streamline_kwargs:
            Additional parameters that will be passed to plt.streamplot function

    Returns
    -------
        Nothing but a cell wise quiver plot
    """
    import matplotlib.pyplot as plt
    import matplotlib.patheffects as PathEffects

    streamplot_kwargs={"density": density, "linewidth": None, "color": None, "cmap": None, "norm": None, "arrowsize": 1, "arrowstyle": '-|>',
                       "minlength": 0.1, "transform": None, "zorder": None, "start_points": None, "maxlength": 4.0,
                       "integration_direction": 'both'}
    streamplot_kwargs.update(streamline_kwargs)

    if cmap is None and color is None:
        cmap = plt.cm.RdBu_r

    n_cells, n_genes = adata.shape[0], len(genes)
    # {"alpha": 0.5, "s": 8, "edgecolor": "0.8", "lw": 0.15}

    scatter_kwargs = dict(alpha=0.4, s=8, edgecolor=None, linewidth=0)
    if s_kwargs_dict is not None:
        scatter_kwargs.update(s_kwargs_dict)

    if layer is 'X':
        E_vec = adata[:, adata.var.index.isin(genes)].X.T
    elif layer in adata.layers.keys():
        E_vec = adata[:, adata.var.index.isin(genes)].layers[layer].T
    elif layer is 'protein': # update subset here
        E_vec = adata[:, adata.var.index.isin(genes)].obsm[layer].T
    else:
        raise Exception(f'The {layer} you passed in is not existed in the adata object.')

    if color is not None:
        color = list(set(color).intersection(adata.obs.keys()))
        n_genes, genes = len(color), color
        E_vec = adata.obs[color].values.T.flatten() if len(color) > 0 else np.empty((0, 1))

    if ('X_' + basis in adata.obsm.keys()) and ('velocity_' + basis in adata.obsm.keys()):
        X = adata.obsm['X_' + basis][:, [x, y]]
        V = adata.obsm['velocity_' + basis][:, [x, y]]
    else:
        if 'X_' + basis not in adata.obsm.keys():
            reduceDimension(adata, velocity_key='velocity_S', reduction_method=basis)
        if 'kmc' not in adata.uns_keys():
            cell_velocities(adata, vkey='pca', basis=basis, method='analytical')
            X = adata.obsm['X_' + basis][:, [x, y]]
            V = adata.obsm['velocity_' + basis][:, [x, y]]
        else:
            kmc = adata.uns['kmc']
            X = adata.obsm['X_' + basis][:, [x, y]]
            V = kmc.compute_density_corrected_drift(X, kmc.Idx, normalize_vector=True)
            adata.obsm['velocity_' + basis] = V

    if 0 in E_vec.shape:
        raise Exception(f'The gene names {genes} (or cell annotations {color}) provided are not existed in your data.')

    if method is 'SparseVFC' and adata.obsm['X_' + basis].shape[1] == 2:
        if 'VecFld_' + basis not in adata.uns.keys():
            VectorField(adata, basis=basis)
        X_grid, V_grid =  adata.uns['VecFld_' + basis]['grid'], adata.uns['VecFld_' + basis]['grid_V']
        N = int(np.sqrt(V_grid.shape[0]))
        X_grid, V_grid = np.array([np.unique(X_grid[:, 0]), np.unique(X_grid[:, 1])]), \
                 np.array([V_grid[:, 0].reshape((N, N)), V_grid[:, 1].reshape((N, N))])
    elif 'grid_velocity_' + basis in adata.uns.keys():
        X_grid, V_grid, _ = adata.uns['grid_velocity_' + basis]['X_grid'], adata.uns['grid_velocity_' + basis]['V_grid'], \
                            adata.uns['grid_velocity_' + basis]['D']
    else:
        grid_kwargs_dict = {"density": None, "smooth": None, "n_neighbors": None, "min_mass": None, "autoscale": False,
                            "adjust_for_stream": True, "V_threshold": None}
        grid_kwargs_dict.update(g_kwargs_dict)

        X_grid, V_grid, D = velocity_on_grid(X[:, [x, y]], V[:, [x, y]], xy_grid_nums, **grid_kwargs_dict)


    # if quiver_scale is None:
    #     quiver_scale = quiver_autoscaler(X_grid, V_grid)
    # quiver_kwargs = {"angles": 'xy', "scale_units": 'xy', 'scale': quiver_scale, "minlength": 1.5}
    # quiver_kwargs.update(q_kwargs)

    n_columns, plot_per_gene = n_columns, 1 # we may also add random velocity results
    nrow, ncol = int(np.ceil(plot_per_gene * n_genes / n_columns)), n_columns
    if figsize is None:
        plt.figure(None, (3*ncol, 3*nrow), dpi=160) #
    else:
        plt.figure(None, (figsize[0]*ncol, figsize[1]*nrow)) # , dpi=160

    E_vec = E_vec.A.flatten() if issparse(E_vec) else E_vec.flatten()
    V = V.A[:, [x, y]] if issparse(V) else V[:, [x, y]]
    # iterate over cell first then a different dimension/gene/column
    df = pd.DataFrame({"x": np.tile(X[:, 0], n_genes), "y": np.tile(X[:, 1], n_genes), "u": np.tile(V[:, 0], n_genes),
                       "v": np.tile(V[:, 1], n_genes), 'gene': np.repeat(np.array(genes), n_cells),
                       "expression": E_vec}, index=range(n_cells * n_genes))

    # the following code is inspired by https://github.com/velocyto-team/velocyto-notebooks/blob/master/python/DentateGyrus.ipynb
    gs = plt.GridSpec(nrow, ncol)
    for i, gn in enumerate(genes):
        ax = plt.subplot(gs[i*plot_per_gene])
        try:
            ix=np.where(adata.var.index == gn)[0][0]
        except:
            ix = gn in adata.obs.columns
            if not ix:
                continue

        cur_pd = df.loc[df.gene == gn, :]

        E_vec = cur_pd.loc[:, 'expression']

        if color is None:
            limit = np.max(np.abs(np.percentile(E_vec, [1, 99])))  # upper and lowe limit / saturation

            E_vec = E_vec + limit  # that is: tmp_colorandum - (-limit)
            E_vec = E_vec / (2 * limit)  # that is: tmp_colorandum / (limit - (-limit))
            E_vec = np.clip(E_vec, 0, 1)

            ax.scatter(cur_pd.iloc[:, 0], cur_pd.iloc[:, 1], c=cmap(E_vec), **scatter_kwargs)
        else:
            import seaborn as sns
            # List of RGB triplets
            color_labels = E_vec.unique()
            rgb_values = sns.color_palette("Set2", len(color_labels))

            # Map label to RGB
            color_map = pd.DataFrame(zip(color_labels, rgb_values), index=color_labels)

            ax.scatter(cur_pd.iloc[:, 0], cur_pd.iloc[:, 1], c=color_map.loc[E_vec, 1].values, **scatter_kwargs)

            if label_on_embedding:
                for i in color_labels:
                    color_cnt = np.median(cur_pd.iloc[np.where(E_vec == i)[0], :2], 0)
                    txt=ax.text(color_cnt[0], color_cnt[1], str(i),
                             fontsize=13) # , bbox={"facecolor": "w", "alpha": 0.6}
                    txt.set_path_effects([
                        PathEffects.Stroke(linewidth=5, foreground="w", alpha=0.1),
                        PathEffects.Normal()])
        if show_quiver:
            ax.quiver(X_grid[0], X_grid[1], V_grid[0], V_grid[1], color = 'gray', alpha = 0.7) # , **quiver_kwargs

        mass = np.sqrt((V_grid ** 2).sum(0))
        if V_threshold is not None:
            if V_threshold is not None:
                V_grid[0][mass.reshape(V_grid[0].shape) < V_threshold] = np.nan

        streamplot_kwargs.update({"linewidth": 4 * mass / mass[~np.isnan(mass)].max()})

        ax.streamplot(X_grid[0], X_grid[1], V_grid[0], V_grid[1], **streamplot_kwargs)
        ax.axis("off")

    plt.show()
Beispiel #20
0
def add_mslp_label(ax, proj_ccrs, mslp, lat, lon):
    """
    Add mslp low and high label

    Args:
        ax (matplotlib.axes.Axes):  the `Axes` instance used for plotting.
        proj_ccrs (cartopy projection): cartopy projection object.
        mslp (np.array): numpy array.
        lat (np.array): latitude
        lon (np.array): longitdue
    """

    #Label MSLP extrema
    def _extrema(mat, mode='wrap', window=50):
        mn = minimum_filter(mat, size=window, mode=mode)
        mx = maximum_filter(mat, size=window, mode=mode)
        return np.nonzero(mat == mn), np.nonzero(mat == mx)
    
    #Determine an appropriate window given the lat/lon grid resolution
    res = lat[1] - lat[0]
    nwindow = int(9.5 / res)
    mslp = np.ma.masked_invalid(mslp)
    local_min, local_max = _extrema(mslp, mode='wrap', window=nwindow)
    
    #Determine axis boundaries
    xmin, xmax, ymin, ymax = ax.get_extent()
    lons2d, lats2d = np.meshgrid(lon, lat)
    transformed = proj_ccrs.transform_points(proj_ccrs, lons2d, lats2d)
    x = transformed[..., 0]
    y = transformed[..., 1]
    
    #Get location of extrema on grid
    xlows = x[local_min]; xhighs = x[local_max]
    ylows = y[local_min]; yhighs = y[local_max]
    lowvals = mslp[local_min]; highvals = mslp[local_max]
    yoffset = 0.022*(ymax-ymin)
    dmin = yoffset
    
    #Plot low pressures
    xyplotted = []
    for x,y,p in zip(xlows, ylows, lowvals):
        if x < xmax-yoffset and x > xmin+yoffset and y < ymax-yoffset and y > ymin+yoffset:
            dist = [np.sqrt((x-x0)**2+(y-y0)**2) for x0,y0 in xyplotted]
            if not dist or min(dist) > dmin: #,fontweight='bold'
                a = ax.text(x,y,'L',fontsize=28,
                        ha='center',va='center',color='r',fontweight='normal')
                b = ax.text(x,y-yoffset,repr(int(p)),fontsize=14,
                        ha='center',va='top',color='r',fontweight='normal')
                a.set_path_effects([mpatheffects.Stroke(linewidth=1.5, foreground='black'),
                       mpatheffects.SimpleLineShadow(),mpatheffects.Normal()])
                b.set_path_effects([mpatheffects.Stroke(linewidth=1.0, foreground='black'),
                       mpatheffects.SimpleLineShadow(),mpatheffects.Normal()])
                xyplotted.append((x,y))
                
    #Plot high pressures
    xyplotted = []
    for x,y,p in zip(xhighs, yhighs, highvals):
        if x < xmax-yoffset and x > xmin+yoffset and y < ymax-yoffset and y > ymin+yoffset:
            dist = [np.sqrt((x-x0)**2+(y-y0)**2) for x0,y0 in xyplotted]
            if not dist or min(dist) > dmin:
                a = ax.text(x,y,'H',fontsize=28,
                        ha='center',va='center',color='b',fontweight='normal')
                b = ax.text(x,y-yoffset,repr(int(p)),fontsize=14,
                        ha='center',va='top',color='b',fontweight='normal')
                a.set_path_effects([mpatheffects.Stroke(linewidth=1.5, foreground='black'),
                       mpatheffects.SimpleLineShadow(),mpatheffects.Normal()])
                b.set_path_effects([mpatheffects.Stroke(linewidth=1.0, foreground='black'),
                       mpatheffects.SimpleLineShadow(),mpatheffects.Normal()])
                xyplotted.append((x,y))
Beispiel #21
0
def plot_fixed_points(
    vecfld,
    marker="o",
    markersize=200,
    cmap=None,
    filltype=["full", "top", "none"],
    background=None,
    save_show_or_return='return',
    save_kwargs={},
    ax=None,
):
    """Plot fixed points stored in the VectorField2D class.

    Arguments
    ---------
        vecfld: :class:`~VectorField2D`
            An instance of the VectorField2D class which presumably has fixed points computed and stored.
        marker: `str` (default: `o`)
            The marker type. Any string supported by matplotlib.markers.
        markersize: `float` (default: 200)
            The size of the marker.
        cmap: string (optional, default 'Blues')
            The name of a matplotlib colormap to use for coloring or shading the confidence of fixed points. If None, the
            default color map will set to be viridis (inferno) when the background is white (black).
        filltype: list
            The fill type used for stable, saddle, and unstable fixed points. Default is 'full', 'top' and 'none',
            respectively.
        background: `str` or None (default: None)
            The background color of the plot.
        save_show_or_return: {'show', 'save', 'return'} (default: `return`)
            Whether to save, show or return the figure.
        save_kwargs: `dict` (default: `{}`)
            A dictionary that will passed to the save_fig function. By default it is an empty dictionary and the save_fig function
            will use the {"path": None, "prefix": 'plot_fixed_points', "dpi": None, "ext": 'pdf', "transparent": True, "close":
            True, "verbose": True} as its parameters. Otherwise you can provide a dictionary that properly modify those keys
            according to your needs.
        ax: :class:`~matplotlib.axes.Axes`
            The matplotlib axes used for plotting. Default is to use the current axis.
    """
    import matplotlib
    from matplotlib import rcParams, markers
    import matplotlib.patheffects as PathEffects
    from matplotlib.colors import to_hex

    if background is None:
        _background = rcParams.get("figure.facecolor")
        _background = to_hex(
            _background) if type(_background) is tuple else _background
    else:
        _background = background

    if _background in ["#ffffff", "black"]:
        _theme_ = ("inferno")
    else:
        _theme_ = ("viridis")
    _cmap = _themes[_theme_]["cmap"] if cmap is None else cmap

    Xss, ftype = vecfld.get_fixed_points(get_types=True)
    confidence = vecfld.get_Xss_confidence()

    if ax is None:
        ax = plt.gca()

    cm = matplotlib.cm.get_cmap(_cmap) if type(_cmap) is str else _cmap
    for i in range(len(Xss)):
        cur_ftype = ftype[i]
        marker_ = markers.MarkerStyle(marker=marker,
                                      fillstyle=filltype[int(cur_ftype + 1)])
        ax.scatter(*Xss[i],
                   marker=marker_,
                   s=markersize,
                   c=np.array(cm(confidence[i])).reshape(1, -1),
                   edgecolor=_select_font_color(_background),
                   linewidths=1,
                   cmap=_cmap,
                   vmin=0,
                   zorder=5)
        txt = ax.text(
            *Xss[i],
            repr(i),
            c=('black'
               if cur_ftype == -1 else 'blue' if cur_ftype == 0 else 'red'),
            horizontalalignment='center',
            verticalalignment='center',
            zorder=6,
            weight='bold',
        )
        txt.set_path_effects([
            PathEffects.Stroke(linewidth=1.5,
                               foreground=_background,
                               alpha=0.8),
            PathEffects.Normal(),
        ])

    if save_show_or_return == "save":
        s_kwargs = {
            "path": None,
            "prefix": 'plot_fixed_points',
            "dpi": None,
            "ext": 'pdf',
            "transparent": True,
            "close": True,
            "verbose": True
        }
        s_kwargs = update_dict(s_kwargs, save_kwargs)

        save_fig(**s_kwargs)
    elif save_show_or_return == "show":
        plt.tight_layout()
        plt.show()
    elif save_show_or_return == "return":
        return ax
Beispiel #22
0
    async def ingame_(self, ctx, *, username):
        ds_type = utils.DSType(ctx.invoked_with.lower())
        dsobj = await ds_type.fetch(ctx, username, name=True)

        queries = []
        for num in range(29):
            table = f"{ds_type.table}{num or ''}"
            base = f'SELECT * FROM {table} WHERE ' \
                   f'{table}.world = $1 AND {table}.id = $2'

            queries.append(base)

        query = " UNION ALL ".join(queries)
        async with self.bot.pool.acquire() as conn:
            records = await conn.fetch(query, ctx.server, dsobj.id)
            data = [ds_type.Class(rec) for rec in records]
            data.reverse()

        rows = [
            f"**{dsobj.name}** | {ctx.world.show(clean=True)} {ctx.world.icon}"
        ]

        urls = []
        for url_type in ["ingame", "guest", "twstats"]:
            url = getattr(dsobj, f"{url_type}_url")
            urls.append(f"[{url_type.capitalize()}]({url})")

        rows.append(" | ".join(urls))

        points = f"**Punkte:** `{utils.seperator(dsobj.points)}` | **Rang:** `{dsobj.rank}`"

        if hasattr(dsobj, 'tribe_id'):
            tribe = await self.bot.fetch_tribe(ctx.server, dsobj.tribe_id)
            desc = tribe.mention if tribe else "None"
            villages = f"**Stamm:** {desc}"
        else:
            villages = f"**Mitglieder:** `{dsobj.member}`"

        villages += f" | **Dörfer:** `{utils.seperator(dsobj.villages)}`"
        rows.extend(["", points, villages, "", "**Besiegte Gegner:**"])

        bash_rows = OrderedDict()
        for index, stat in enumerate(
            ['all_bash', 'att_bash', 'def_bash', 'sup_bash']):

            if index == 3 and isinstance(dsobj, utils.Tribe):
                value = await dsobj.fetch_supbash(ctx)
                rank_value = None
            else:
                value = getattr(dsobj, stat)
                rank_stat = f"{stat.split('_')[0]}_rank"
                rank_value = getattr(dsobj, rank_stat)

            stat_title = self.bot.msg['statTitle'][stat]
            represent = f"{stat_title}: `{sep(value)}`"

            if rank_value:
                represent += f" | Rang: `{rank_value}`"

            bash_rows[represent] = value

        clean = sorted(bash_rows.items(), key=lambda l: l[1], reverse=True)
        rows.extend([line[0] for line in clean])

        profile = discord.Embed(description="\n".join(rows))
        profile.colour = discord.Color.blue()

        image_url = await self.fetch_profile_picture(dsobj)
        if image_url is not None:
            profile.set_thumbnail(url=image_url)

        filled = [0] * (29 - len(data)) + [d.points for d in data]
        plot_data = pd.DataFrame({'x_coord': range(29), 'y_coord': filled})

        config = {
            'color':
            '#3498db',
            'linewidth':
            5,
            'path_effects':
            [patheffects.SimpleLineShadow(linewidth=8),
             patheffects.Normal()]
        }

        figure = self.create_figure()

        if not data:
            plt.ylim(top=50, bottom=-3)

        figure.plot('x_coord', 'y_coord', data=plot_data, **config)
        figure.grid(axis='y', zorder=1, alpha=0.3)

        buf = io.BytesIO()
        plt.savefig(buf, format='png', dpi=100, transparent=True)
        buf.seek(0)
        plt.close()

        file = discord.File(buf, "example.png")
        profile.set_image(url="attachment://example.png")
        await ctx.send(embed=profile, file=file)
Beispiel #23
0
def plot_predictions(eval_data_dict,
                     model_registrar,
                     robot_node,
                     hyperparams,
                     device,
                     dt,
                     max_speed,
                     color_dict=None,
                     num_samples=100,
                     data_id=2,
                     t_predict=56,
                     radius_of_influence=3.0,
                     node_circle_size=0.3,
                     focus_on=None,
                     focus_window_height=6,
                     line_alpha=0.7,
                     line_width=0.2,
                     edge_width=2,
                     circle_edge_width=0.5,
                     only_predict=None,
                     dpi=300,
                     fig_height=4,
                     ylim=(0, 50),
                     xlim=(0, 100),
                     figsize=None,
                     tick_fontsize=13,
                     xlabel='$x$ position (m)',
                     ylabel='$y$ position (m)',
                     custom_xticks=None,
                     custom_yticks=None,
                     legend_loc=None,
                     return_frame=False,
                     return_fig=False,
                     printing=False,
                     robot_circle=True,
                     robot_shift_future=0.0,
                     robot_shift='x',
                     add_legend=True,
                     title=None,
                     flip_axes=False,
                     omit_names=False,
                     axes_labels=True,
                     rotate_axes_text=0,
                     save_at=None):

    from model.dyn_stg import SpatioTemporalGraphCVAEModel
    from utils.scene_utils import create_batch_scene_graph

    if color_dict is None:
        # This changes colors per run.
        color_dict = defaultdict(dict)

    if dt is None:
        raise ValueError(
            'You must supply a time delta, the argument dt cannot be None!')

    if figsize is None:
        aspect_ratio = float(xlim[1] - xlim[0]) / (ylim[1] - ylim[0])
        figsize = (fig_height * aspect_ratio, fig_height)

    max_time = eval_data_dict['input_dict'][robot_node][data_id, :].shape[0]
    predict_horizon = hyperparams['prediction_horizon']

    if t_predict < hyperparams['minimum_history_length']:
        raise ValueError('ERROR: t_predict must be >= %d' %
                         hyperparams['minimum_history_length'])
    elif t_predict + predict_horizon >= max_time:
        raise ValueError('ERROR: t_predict must be <= %d' %
                         (max_time - predict_horizon - 1))

    ###################
    ### Predictions ###
    ###################
    tic = timeit.default_timer()

    tic0 = timeit.default_timer()

    hyperparams['state_dim'] = eval_data_dict['input_dict'][robot_node].shape[
        2]
    hyperparams['pred_dim'] = len(eval_data_dict['pred_indices'])
    hyperparams['pred_indices'] = eval_data_dict['pred_indices']
    hyperparams['nodes_standardization'] = eval_data_dict[
        "nodes_standardization"]
    hyperparams["labels_standardization"] = eval_data_dict[
        "labels_standardization"]

    kwargs_dict = {
        'dynamic_edges':
        hyperparams['dynamic_edges'],
        'edge_state_combine_method':
        hyperparams['edge_state_combine_method'],
        'edge_influence_combine_method':
        hyperparams['edge_influence_combine_method']
    }

    # Create the aggregate scene_graph for all the data, allowing
    # for batching, just like the old one. Then, for speed tests
    # we'll show how much faster this method is than keeping the
    # full version. Can show graphs of forward inference time vs problem size
    # with two lines (using aggregate graph, using online-computed graph).
    input_dict = {
        k: v[[data_id]]
        for k, v in eval_data_dict['input_dict'].items()
    }
    label_dict = {k: v[[data_id]] for k, v in eval_data_dict['labels'].items()}
    robot_future = eval_data_dict['input_dict'][robot_node][[data_id],
                                                            t_predict +
                                                            1:t_predict +
                                                            predict_horizon +
                                                            1]

    if robot_shift_future != 0.0:
        idx = 4 if robot_shift == 'x' else 5
        print('Shifting %s by %.2f!' % (robot_shift, robot_shift_future))
        robot_future[..., idx] += robot_shift_future
        robot_future[..., idx - 2] = cumtrapz(
            robot_future[..., idx], axis=1, initial=0,
            dx=dt) + robot_future[0, 0, idx - 2]
        robot_future[..., idx - 4] = cumtrapz(
            robot_future[..., idx - 2], axis=1, initial=0,
            dx=dt) + robot_future[0, 0, idx - 4]

    with torch.no_grad():
        test_stg = SpatioTemporalGraphCVAEModel(robot_node, model_registrar,
                                                hyperparams, kwargs_dict, None,
                                                device)

        test_agg_scene_graph = create_batch_scene_graph(
            input_dict,
            float(hyperparams['edge_radius']),
            use_old_method=(hyperparams['dynamic_edges'] == 'no'))
        if hyperparams['dynamic_edges'] == 'yes':
            test_agg_scene_graph.compute_edge_scaling(
                hyperparams['edge_addition_filter'],
                hyperparams['edge_removal_filter'])

        test_stg.set_scene_graph(test_agg_scene_graph)

        test_inputs = {
            k: torch.from_numpy(v).float()
            for k, v in input_dict.items() if v.size > 0
        }
        test_labels = {
            k: torch.from_numpy(v).float()
            for k, v in label_dict.items()
        }

        test_inputs[str(robot_node) +
                    "_future"] = torch.from_numpy(robot_future).float()
        test_inputs['traj_lengths'] = torch.tensor([t_predict])
        if hyperparams['dynamic_edges'] == 'yes':
            test_inputs['edge_scaling_mask'] = torch.from_numpy(
                test_agg_scene_graph.edge_scaling_mask).float()

        toc0 = timeit.default_timer()
        if printing:
            print("constructing feed_dict took: ", toc0 - tic0,
                  " (s), running pytorch!")

        tic0 = timeit.default_timer()
        outputs = test_stg.predict(test_inputs,
                                   hyperparams['prediction_horizon'],
                                   num_samples)
        toc0 = timeit.default_timer()

        outputs = {k: v.cpu().numpy() for k, v in outputs.items()}

    if printing:
        print("done running pytorch!, took (s): ", toc0 - tic0)

    toc = timeit.default_timer()

    if printing:
        print("total time taken (s): ", toc - tic)

    ########################
    ### Data Preparation ###
    ########################
    prefixes_dict = dict()
    futures_dict = dict()
    nodes = test_agg_scene_graph.nodes
    prefix_earliest_idx = max(0, t_predict - predict_horizon)
    for node in nodes:
        if robot_node == node:
            continue

        node_data = input_dict[node]
        if printing:
            print('node', node)
            print('node_data.shape', node_data.shape)

        prefixes_dict[node] = node_data[[0], prefix_earliest_idx:t_predict + 1,
                                        0:2]
        futures_dict[node] = node_data[[0], t_predict + 1:t_predict +
                                       predict_horizon + 1]
        if printing:
            print('node', node)
            print('prefixes_dict[node].shape', prefixes_dict[node].shape)
            print('futures_dict[node].shape', futures_dict[node].shape)

    # 44.72 km/h = 40.76 ft/s (ie. that's the max value that a coordinate can be)
    output_pos = dict()
    sampled_zs = dict()
    for node in nodes:
        if robot_node == node:
            continue

        key = str(node) + '/y'
        z_key = str(node) + '/z'

        output_pos[node] = integrate_trajectory(outputs[key], [0, 1],
                                                futures_dict[node][0, 0],
                                                [0, 1],
                                                dt,
                                                output_limit=max_speed,
                                                velocity_in=True)
        sampled_zs[node] = outputs[z_key]

    if printing:
        print('prefixes_dict[node].shape', prefixes_dict[node].shape)
        print('futures_dict[node].shape', futures_dict[node].shape)
        print('output_pos[node].shape', output_pos[node].shape)
        print('sampled_zs[node].shape', sampled_zs[node].shape)

    ######################
    ### Visualizations ###
    ######################
    fig, ax = plt.subplots(figsize=figsize)
    not_added_prefix = True
    not_added_future = True
    not_added_samples = True
    for node_name in prefixes_dict:
        if focus_on is not None and node_name != focus_on:
            continue

        prefix = prefixes_dict[node_name][0]
        future = futures_dict[node_name][0]
        predictions = output_pos[node_name][:, 0]
        z_values = sampled_zs[node_name][:, 0]

        prefix_all_zeros = not np.any(prefix)
        future_all_zeros = not np.any(future)
        if prefix_all_zeros and future_all_zeros:
            continue

        if not (xlim[0] <= prefix[-1, 0] <=
                xlim[1]) or not (ylim[0] <= prefix[-1, 1] <= ylim[1]):
            continue

        if np.any([prefix[-1, 0], prefix[-1, 1]]):
            # Prefix trails
            prefix_start_idx = first_nonzero(np.sum(prefix, axis=1),
                                             axis=0,
                                             invalid_val=-1)
            if not_added_prefix:
                ax.plot(prefix[prefix_start_idx:, 0],
                        prefix[prefix_start_idx:, 1],
                        'k--',
                        label='History')
                not_added_prefix = False
            else:
                ax.plot(prefix[prefix_start_idx:, 0], prefix[prefix_start_idx:,
                                                             1], 'k--')

            # Predicted trails
            if only_predict is None or (only_predict is not None
                                        and node_name == only_predict):
                if not_added_samples:
                    # plt.plot([] , [], 'r', label='Sampled Futures')
                    not_added_samples = False

                for sample_num in range(output_pos[node_name].shape[0]):
                    z_value = tuple(z_values[sample_num])
                    if z_value not in color_dict[node_name]:
                        color_dict[node_name][
                            z_value] = "#%06x" % random.randint(0, 0xFFFFFF)

                    ax.plot(predictions[sample_num, :, 0],
                            predictions[sample_num, :, 1],
                            color=color_dict[node_name][z_value],
                            linewidth=line_width,
                            alpha=line_alpha)

            # Future trails
            future_start_idx = first_nonzero(np.sum(future, axis=1),
                                             axis=0,
                                             invalid_val=-1)
            future_end_idx = future.shape[0] - first_nonzero(
                np.sum(future, axis=1)[::-1], axis=0, invalid_val=-1)
            if not_added_future:
                ax.plot(future[future_start_idx:future_end_idx, 0],
                        future[future_start_idx:future_end_idx, 1],
                        'w--',
                        path_effects=[
                            pe.Stroke(linewidth=edge_width, foreground='k'),
                            pe.Normal()
                        ],
                        label='Actual Future')
                not_added_future = False
            else:
                ax.plot(future[future_start_idx:future_end_idx, 0],
                        future[future_start_idx:future_end_idx, 1],
                        'w--',
                        path_effects=[
                            pe.Stroke(linewidth=edge_width, foreground='k'),
                            pe.Normal()
                        ])

            # Current Node Position
            circle = plt.Circle(
                (prefix[-1, 0], prefix[-1, 1]),
                node_circle_size,
                facecolor='b' if 'Home' in node_name.type else 'g',
                edgecolor='k',
                lw=circle_edge_width,
                zorder=3)
            ax.add_artist(circle)

            #         if focus_on:
            #             ax.set_title(node_name)
            #         else:
            #             ax.text(prefix[-1, 0] + 0.4, prefix[-1, 1], node_name, zorder=4)

            if not omit_names:
                ax.text(prefix[-1, 0] + 0.4,
                        prefix[-1, 1],
                        node_name,
                        zorder=4)

    # Robot Node
    if focus_on is None:
        prefix_earliest_idx = max(0, t_predict - predict_horizon)
        robot_prefix = eval_data_dict['input_dict'][robot_node][
            data_id, prefix_earliest_idx:t_predict + 1, 0:2]
        prefix_start_idx = first_nonzero(np.sum(robot_prefix, axis=1),
                                         axis=0,
                                         invalid_val=-1)
        #         robot_future = eval_data_dict[robot_node][data_id, t_predict + 1 : t_predict + predict_horizon + 1, 0:2]
        robot_future = robot_future[0, :, 0:2].copy()

        prefix_all_zeros = not np.any(robot_prefix)
        future_all_zeros = not np.any(robot_future)
        if not (prefix_all_zeros and future_all_zeros) and (
            (xlim[0] <= robot_prefix[-1, 0] <= xlim[1]) and
            (ylim[0] <= robot_prefix[-1, 1] <= ylim[1])):
            ax.plot(robot_prefix[prefix_start_idx:, 0],
                    robot_prefix[prefix_start_idx:, 1], 'k--')
            ax.plot(robot_future[:, 0],
                    robot_future[:, 1],
                    'w--',
                    path_effects=[
                        pe.Stroke(linewidth=edge_width, foreground='k'),
                        pe.Normal()
                    ])

            circle = plt.Circle(
                (robot_prefix[-1, 0], robot_prefix[-1, 1]),
                node_circle_size,
                facecolor='b' if 'Home' in robot_node.type else 'g',
                edgecolor='k',
                lw=circle_edge_width,
                zorder=3)
            ax.add_artist(circle)

            # Radius of influence
            if robot_circle:
                circle = plt.Circle((robot_prefix[-1, 0], robot_prefix[-1, 1]),
                                    radius_of_influence,
                                    fill=False,
                                    color='r',
                                    linestyle='--',
                                    zorder=3)
                ax.plot([], [], 'r--', label='Edge Radius')
                ax.add_artist(circle)

            if not omit_names:
                ax.text(robot_prefix[-1, 0] + 0.4,
                        robot_prefix[-1, 1],
                        robot_node,
                        zorder=4)

    if focus_on is None:
        ax.set_ylim(ylim)
        ax.set_xlim(xlim)
    else:
        y_radius = focus_window_height
        x_radius = aspect_ratio * y_radius
        ax.set_ylim((prefix[-1, 1] - y_radius, prefix[-1, 1] + y_radius))
        ax.set_xlim((prefix[-1, 0] - x_radius, prefix[-1, 0] + x_radius))

    if add_legend:
        if legend_loc is not None:
            leg = ax.legend(loc=legend_loc, handlelength=4)
        else:
            leg = ax.legend(loc='best', handlelength=4)

        for line in leg.get_lines():
            line.set_linewidth(2.25)
        for text in leg.get_texts():
            text.set_fontsize(14)

    if title is not None:
        ax.set_title(title)

    if axes_labels:
        ax.set_xlabel(xlabel, fontsize=tick_fontsize)
        ax.set_ylabel(ylabel, fontsize=tick_fontsize)

    if rotate_axes_text != 0:
        if custom_xticks is not None:
            plt.xticks(custom_xticks,
                       rotation=rotate_axes_text,
                       fontsize=tick_fontsize)
        else:
            plt.xticks(rotation=rotate_axes_text, fontsize=tick_fontsize)

        if custom_yticks is not None:
            plt.yticks(custom_yticks,
                       rotation=rotate_axes_text,
                       fontsize=tick_fontsize)
        else:
            plt.yticks(rotation=rotate_axes_text, fontsize=tick_fontsize)
    else:
        if custom_xticks is not None:
            plt.xticks(custom_xticks, fontsize=tick_fontsize)
        else:
            plt.xticks(fontsize=tick_fontsize)

        if custom_yticks is not None:
            plt.yticks(custom_yticks, fontsize=tick_fontsize)
        else:
            plt.yticks(fontsize=tick_fontsize)

    fig.tight_layout()

    if return_fig:
        return fig

    if return_frame:
        buffer_ = StringIO()
        plt.savefig(buffer_, format="png", transparent=True, dpi=dpi)
        buffer_.seek(0)
        data = np.asarray(Image.open(buffer_))

        plt.close(fig)
        return data

    if save_at is not None:
        plt.savefig(save_at, dpi=300, transparent=True)

    plt.show()
    plt.close(fig)
Beispiel #24
0
    def create_figure(self,
                      frameno=0,
                      binning=1,
                      dpi=None,
                      stretch='log',
                      vmin=1,
                      vmax=5000,
                      cmap='gray',
                      data_col='FLUX',
                      annotate=True,
                      time_format='ut',
                      show_flags=False,
                      label=None):
        """Returns a matplotlib Figure object that visualizes a frame.

        Parameters
        ----------
        frameno : int
            Image number in the target pixel file.

        binning : int
            Number of frames around `frameno` to co-add. (default: 1).

        dpi : float, optional [dots per inch]
            Resolution of the output in dots per Kepler CCD pixel.
            By default the dpi is chosen such that the image is 440px wide.

        vmin : float, optional
            Minimum cut level (default: 1).

        vmax : float, optional
            Maximum cut level (default: 5000).

        cmap : str, optional
            The matplotlib color map name.  The default is 'gray',
            can also be e.g. 'gist_heat'.

        raw : boolean, optional
            If `True`, show the raw pixel counts rather than
            the calibrated flux. Default: `False`.

        annotate : boolean, optional
            Annotate the Figure with a timestamp and target name?
            (Default: `True`.)

        show_flags : boolean, optional
            Show the quality flags?
            (Default: `False`.)

        label : str
            Label text to show in the bottom left corner of the movie.

        Returns
        -------
        image : array
            An array of unisgned integers of shape (x, y, 3),
            representing an RBG colour image x px wide and y px high.
        """
        # Get the flux data to visualize
        flx = self.flux_binned(frameno=frameno,
                               binning=binning,
                               data_col=data_col)

        # Determine the figsize and dpi
        shape = list(flx.shape)
        shape = [shape[1], shape[0]]
        if dpi is None:
            # Twitter timeline requires dimensions between 440x220 and 1024x512
            # so we make 440 the default
            dpi = 440 / float(shape[0])

        # libx264 require the height to be divisible by 2, we ensure this here:
        shape[0] -= ((shape[0] * dpi) % 2) / dpi

        # Create the figureand display the flux image using matshow
        fig = pl.figure(figsize=shape, dpi=dpi)
        # Display the image using matshow
        ax = fig.add_subplot(1, 1, 1)
        if self.verbose:
            print('{} vmin/vmax = {}/{} (median={})'.format(
                data_col, vmin, vmax, np.nanmedian(flx)))

        if stretch == 'linear':
            stretch_fn = visualization.LinearStretch()
        elif stretch == 'sqrt':
            stretch_fn = visualization.SqrtStretch()
        elif stretch == 'power':
            stretch_fn = visualization.PowerStretch(1.0)
        elif stretch == 'log':
            stretch_fn = visualization.LogStretch()
        elif stretch == 'asinh':
            stretch_fn = visualization.AsinhStretch(0.1)
        else:
            raise ValueError('Unknown stretch: {0}.'.format(stretch))

        transform = (stretch_fn +
                     visualization.ManualInterval(vmin=vmin, vmax=vmax))
        flx_transform = 255 * transform(flx)
        # Make sure to remove all NaNs!
        flx_transform[~np.isfinite(flx_transform)] = 0
        ax.imshow(flx_transform.astype(int),
                  aspect='auto',
                  origin='lower',
                  interpolation='nearest',
                  cmap=cmap,
                  norm=NoNorm())
        if annotate:  # Annotate the frame with a timestamp and target name?
            fontsize = 3. * shape[0]
            margin = 0.03
            # Print target name in lower left corner
            if label is None:
                label = self.objectname
            txt = ax.text(margin,
                          margin,
                          label,
                          family="monospace",
                          fontsize=fontsize,
                          color='white',
                          transform=ax.transAxes)
            txt.set_path_effects([
                path_effects.Stroke(linewidth=fontsize / 6.,
                                    foreground='black'),
                path_effects.Normal()
            ])
            # Print a timestring in the lower right corner
            txt2 = ax.text(1 - margin,
                           margin,
                           self.timestamp(frameno, time_format=time_format),
                           family="monospace",
                           fontsize=fontsize,
                           color='white',
                           ha='right',
                           transform=ax.transAxes)
            txt2.set_path_effects([
                path_effects.Stroke(linewidth=fontsize / 6.,
                                    foreground='black'),
                path_effects.Normal()
            ])
            # Print quality flags in upper right corner
            if show_flags:
                flags = self.quality_flags(frameno)
                if len(flags) > 0:
                    txt3 = ax.text(margin,
                                   1 - margin,
                                   '\n'.join(flags),
                                   family="monospace",
                                   fontsize=fontsize * 1.3,
                                   color='white',
                                   ha='left',
                                   va='top',
                                   transform=ax.transAxes,
                                   linespacing=1.5,
                                   backgroundcolor='red')
                    txt3.set_path_effects([
                        path_effects.Stroke(linewidth=fontsize / 6.,
                                            foreground='black'),
                        path_effects.Normal()
                    ])
        ax.set_xticks([])
        ax.set_yticks([])
        ax.axis('off')
        fig.subplots_adjust(left=0.0, right=1.0, top=1.0, bottom=0.0)
        fig.canvas.draw()
        return fig
Beispiel #25
0
def plot_predictions_during_training(test_stg,
                                     inputs,
                                     num_predicted_timesteps,
                                     num_samples,
                                     dt,
                                     max_speed,
                                     color_dict=None,
                                     data_id=None,
                                     t_predict=56,
                                     focus_on=None,
                                     node_circle_size=0.3,
                                     focus_window_height=6,
                                     line_alpha=0.7,
                                     line_width=0.2,
                                     edge_width=2,
                                     circle_edge_width=0.5,
                                     only_predict=None,
                                     dpi=300,
                                     fig_height=4,
                                     return_frame=False,
                                     return_fig=True,
                                     printing=False,
                                     robot_circle=True,
                                     add_legend=True,
                                     title=None,
                                     flip_axes=False,
                                     omit_names=False,
                                     axes_labels=True,
                                     rotate_axes_text=0,
                                     save_at=None):

    if color_dict is None:
        # This changes colors per run.
        color_dict = defaultdict(dict)

    if dt is None:
        raise ValueError(
            'You must supply a time delta, the argument dt cannot be None!')

    robot_node = test_stg.robot_node
    figsize = (5, 5)
    traj_lengths = inputs['traj_lengths'].cpu().numpy().astype(int)
    predict_horizon = num_predicted_timesteps

    if data_id is None:
        data_id = np.random.choice([
            idx for idx, traj_len in enumerate(traj_lengths)
            if t_predict + predict_horizon < traj_len
        ])

    max_time = inputs[robot_node][data_id, :].shape[0]
    traj_length = traj_lengths[data_id]

    if t_predict < test_stg.hyperparams['minimum_history_length']:
        raise ValueError('ERROR: t_predict must be >= %d' %
                         test_stg.hyperparams['minimum_history_length'])
    elif t_predict + predict_horizon >= traj_length:
        raise ValueError('ERROR: t_predict must be <= %d' %
                         (traj_length - predict_horizon - 1))

    ###################
    ### Predictions ###
    ###################
    inputs = {k: v[[data_id]] for k, v in inputs.items()}
    robot_future = inputs[robot_node][[0], t_predict + 1:t_predict +
                                      predict_horizon + 1]
    inputs[str(robot_node) + "_future"] = robot_future
    inputs['traj_lengths'] = torch.tensor([t_predict])

    with torch.no_grad():
        tic0 = timeit.default_timer()
        outputs = test_stg.predict(inputs, num_predicted_timesteps,
                                   num_samples)
        toc0 = timeit.default_timer()

        outputs = {k: v.cpu().numpy() for k, v in outputs.items()}

    if printing:
        print("done running pytorch!, took (s): ", toc0 - tic0)

    ########################
    ### Data Preparation ###
    ########################
    prefixes_dict = dict()
    futures_dict = dict()
    nodes = list(test_stg.nodes)
    prefix_earliest_idx = max(0, t_predict - predict_horizon)
    for node in nodes:
        if robot_node == node:
            continue

        node_data = inputs[node].cpu().numpy()
        if printing:
            print('node', node)
            print('node_data.shape', node_data.shape)

        prefixes_dict[node] = node_data[[0], prefix_earliest_idx:t_predict + 1,
                                        0:2]
        futures_dict[node] = node_data[[0], t_predict +
                                       1:min(t_predict + predict_horizon +
                                             1, traj_length)]
        if printing:
            print('node', node)
            print('prefixes_dict[node].shape', prefixes_dict[node].shape)
            print('futures_dict[node].shape', futures_dict[node].shape)

    # 44.72 km/h = 40.76 ft/s (ie. that's the max value that a coordinate can be)
    output_pos = dict()
    sampled_zs = dict()
    for node in nodes:
        if robot_node == node:
            continue

        key = str(node) + '/y'
        z_key = str(node) + '/z'

        output_pos[node] = integrate_trajectory(outputs[key], [0, 1],
                                                futures_dict[node][0, 0],
                                                [0, 1],
                                                dt,
                                                output_limit=max_speed,
                                                velocity_in=True)
        sampled_zs[node] = outputs[z_key]

    if printing:
        print('prefixes_dict[node].shape', prefixes_dict[node].shape)
        print('futures_dict[node].shape', futures_dict[node].shape)
        print('output_pos[node].shape', output_pos[node].shape)
        print('sampled_zs[node].shape', sampled_zs[node].shape)

    ######################
    ### Visualizations ###
    ######################
    fig, ax = plt.subplots(figsize=figsize)
    not_added_prefix = True
    not_added_future = True
    not_added_samples = True
    for node_name in prefixes_dict:
        if focus_on is not None and node_name != focus_on:
            continue

        prefix = prefixes_dict[node_name][0]
        future = futures_dict[node_name][0]
        predictions = output_pos[node_name][:, 0]
        z_values = sampled_zs[node_name][:, 0]

        prefix_all_zeros = not np.any(prefix)
        future_all_zeros = not np.any(future)
        if prefix_all_zeros and future_all_zeros:
            continue

        if np.any([prefix[-1, 0], prefix[-1, 1]]):
            # Prefix trails
            prefix_start_idx = first_nonzero(np.sum(prefix, axis=1),
                                             axis=0,
                                             invalid_val=-1)
            if not_added_prefix:
                ax.plot(prefix[prefix_start_idx:, 0],
                        prefix[prefix_start_idx:, 1],
                        'k--',
                        label='History')
                not_added_prefix = False
            else:
                ax.plot(prefix[prefix_start_idx:, 0], prefix[prefix_start_idx:,
                                                             1], 'k--')

            # Predicted trails
            if only_predict is None or (only_predict is not None
                                        and node_name == only_predict):
                if not_added_samples:
                    #                 plt.plot([] , [], 'r', label='Sampled Futures')
                    not_added_samples = False

                for sample_num in range(output_pos[node_name].shape[0]):
                    z_value = tuple(z_values[sample_num])
                    if z_value not in color_dict[node_name]:
                        color_dict[node_name][
                            z_value] = "#%06x" % random.randint(0, 0xFFFFFF)

                    ax.plot(predictions[sample_num, :, 0],
                            predictions[sample_num, :, 1],
                            color=color_dict[node_name][z_value],
                            linewidth=line_width,
                            alpha=line_alpha)

            # Future trails
            future_start_idx = first_nonzero(np.sum(future, axis=1),
                                             axis=0,
                                             invalid_val=-1)
            future_end_idx = future.shape[0] - first_nonzero(
                np.sum(future, axis=1)[::-1], axis=0, invalid_val=-1)
            if not_added_future:
                ax.plot(future[future_start_idx:future_end_idx, 0],
                        future[future_start_idx:future_end_idx, 1],
                        'w--',
                        path_effects=[
                            pe.Stroke(linewidth=edge_width, foreground='k'),
                            pe.Normal()
                        ],
                        label='Actual Future')
                not_added_future = False
            else:
                ax.plot(future[future_start_idx:future_end_idx, 0],
                        future[future_start_idx:future_end_idx, 1],
                        'w--',
                        path_effects=[
                            pe.Stroke(linewidth=edge_width, foreground='k'),
                            pe.Normal()
                        ])

            # Current Node Position
            circle = plt.Circle(
                (prefix[-1, 0], prefix[-1, 1]),
                node_circle_size,
                facecolor='b' if 'Home' in node_name.type else 'g',
                edgecolor='k',
                lw=circle_edge_width,
                zorder=3)
            ax.add_artist(circle)

            #         if focus_on:
            #             ax.set_title(node_name)
            #         else:
            #             ax.text(prefix[-1, 0] + 0.4, prefix[-1, 1], node_name, zorder=4)

            if not omit_names:
                ax.text(prefix[-1, 0] + 0.4,
                        prefix[-1, 1],
                        node_name,
                        zorder=4)

    # Robot Node
    if focus_on is None:
        prefix_earliest_idx = max(0, t_predict - predict_horizon)
        robot_prefix = inputs[robot_node][0, prefix_earliest_idx:t_predict + 1,
                                          0:2].cpu().numpy()
        robot_future = inputs[robot_node][
            0, t_predict + 1:min(t_predict + predict_horizon + 1, traj_length),
            0:2].cpu().numpy()

        prefix_all_zeros = not np.any(robot_prefix)
        future_all_zeros = not np.any(robot_future)
        if not (prefix_all_zeros and future_all_zeros):
            ax.plot(robot_prefix[:, 0], robot_prefix[:, 1], 'k--')
            ax.plot(robot_future[:, 0],
                    robot_future[:, 1],
                    'w--',
                    path_effects=[
                        pe.Stroke(linewidth=edge_width, foreground='k'),
                        pe.Normal()
                    ])

            circle = plt.Circle(
                (robot_prefix[-1, 0], robot_prefix[-1, 1]),
                node_circle_size,
                facecolor='b' if 'Home' in robot_node.type else 'g',
                edgecolor='k',
                lw=circle_edge_width,
                zorder=3)
            ax.add_artist(circle)

            # Radius of influence
            if robot_circle:
                circle = plt.Circle((robot_prefix[-1, 0], robot_prefix[-1, 1]),
                                    test_stg.hyperparams['edge_radius'],
                                    fill=False,
                                    color='r',
                                    linestyle='--',
                                    zorder=3)
                ax.plot([], [], 'r--', label='Edge Radius')
                ax.add_artist(circle)

            if not omit_names:
                ax.text(robot_prefix[-1, 0] + 0.4,
                        robot_prefix[-1, 1],
                        robot_node,
                        zorder=4)

    if focus_on is not None:
        y_radius = focus_window_height
        x_radius = aspect_ratio * y_radius
        ax.set_ylim((prefix[-1, 1] - y_radius, prefix[-1, 1] + y_radius))
        ax.set_xlim((prefix[-1, 0] - x_radius, prefix[-1, 0] + x_radius))

    if add_legend:
        ax.legend(loc='best')

    if title is not None:
        ax.set_title(title)

    string_splitter = ' '
    if omit_names:
        string_splitter = '\n'

    if axes_labels:
        ax.set_xlabel('Longitudinal Court Position ($l$)')
        ax.set_ylabel('Lateral Court%sPosition ($w$)' % string_splitter)

    if rotate_axes_text != 0:
        plt.xticks(rotation=rotate_axes_text)
        plt.yticks(rotation=rotate_axes_text)

    fig.tight_layout()

    if return_fig:
        return fig

    if return_frame:
        buffer_ = StringIO()
        plt.savefig(buffer_, format="png", transparent=True, dpi=dpi)
        buffer_.seek(0)
        data = np.asarray(Image.open(buffer_))

        plt.close(fig)
        return data

    if save_at is not None:
        plt.savefig(save_at, dpi=300, transparent=True)

    plt.show()
    plt.close(fig)
    def plot_spectrum_heatmap(self,
                              plot_spec1=True,
                              frange=[],
                              title="Audio Comparison",
                              cmap="plasma",
                              background_color="white",
                              background_alpha=0.5):
        """
        Plots a heatmap and spectrogram showing the relative hot and cool spots of thw two compared AudioAnalyzer class instances. 
        A number of options are available to customize the appearance of the generated plot. 
        """

        #       DATAFRAME SETUP
        if plot_spec1:
            df = self.original_df
        else:
            df = self.modified_df

        df['ratio_amplitude'] = self.ratio_df.scaled_amplitude

        df['attenuated_scaled'] = df.scaled_amplitude
        df['boosted_scaled'] = df.scaled_amplitude

        if len(frange):
            plot_df = df.loc[(df.bins >= frange[0] / 1000)
                             & (df.bins <= frange[1] / 1000)]
            ratio_df = self.ratio_df.loc[
                (self.ratio_df.bins >= frange[0] / 1000)
                & (self.ratio_df.bins <= frange[1] / 1000)]
        else:
            plot_df = df
            ratio_df = self.ratio_df

#       FIGURE SETUP
        fig = plt.figure(figsize=(20, 10))
        ax1 = fig.add_subplot(211, facecolor="white")
        # ax1 = plt.subplot2grid((8,1), (0,0), rowspan=5, facecolor="white", fig=fig)
        ax2 = fig.add_subplot(211, facecolor="#00000000")
        # ax2 = plt.subplot2grid((8,1), (0,0), rowspan=2, facecolor="#00000000", fig=fig)
        # fig2 = plt.figure(figsize=(32, 8))
        # cbaxes = fig2.add_subplot(32,1,1)
        cbaxes = plt.subplot2grid((16, 1), (10, 0))
        cbaxes.set_title("Scaled Amplitude Ratio", size=14)

        #       HEATMAP PLOT
        sns.heatmap(data=ratio_df.set_index('bins').transpose(),
                    cbar=True,
                    cbar_ax=cbaxes,
                    cbar_kws={"orientation": "horizontal"},
                    cmap=cmap,
                    alpha=0.95,
                    zorder=1,
                    ax=ax1,
                    vmin=0.0,
                    vmax=1.0)
        ax1.set_xlabel("")
        ax1.set_xticks([])
        ax1.set_ylabel("")
        ax1.set_yticks([])

        #       FREQUENCY PLOT
        sns.lineplot(data=plot_df,
                     x="bins",
                     y="scaled_amplitude",
                     color='black',
                     zorder=10,
                     ax=ax2,
                     path_effects=[
                         path_effects.SimpleLineShadow(),
                         path_effects.Normal()
                     ])
        ax2.fill_between(x=plot_df.bins,
                         y1=plot_df.scaled_amplitude,
                         color='white',
                         alpha=0.0)
        ax2.fill_between(x=plot_df.bins,
                         y1=plot_df.scaled_amplitude,
                         y2=1.0,
                         color=background_color,
                         alpha=background_alpha)

        ax2.set_xlabel("Frequency (kHz)", size=28)
        ax2.set_ylabel("Scaled Amplitude", size=28)

        ax2.margins(0)
        fig.suptitle(title, size=36, y=0.95)
def solar_corr(data,
               labels,
               center,
               ax=False,
               moon_orbit=0.25,
               base_circle_size=50,
               calc_corr=True,
               orbits=10,
               show_window=True,
               image_path="solar.png",
               save_png=True,
               title="Solar Correlation Map",
               selected=[],
               show_labels=True):
    labels = np.array(labels)
    center_idx, center_idx_bool = label_to_idx(labels, center)
    plot_idx = 23
    all_idx = np.logical_not(center_idx_bool)
    positive = transform_to_positive_corrs(
        data, center_idx) if calc_corr else transform_to_positive(
            data, center_idx)
    corr_dist = transform_to_correlation_dist(data) if calc_corr else data
    sun_corr_dist = corr_dist[center_idx]
    colors = np.linspace(0, 1, num=len(sun_corr_dist))
    cordinate_to_correlation = {}
    step = 1.0 / orbits
    last_orbit = 0.1

    fig = plt.gcf()
    if not ax:
        fig.set_size_inches(20, 20)
    labels_idx = np.array([center_idx])

    # matplotlib.rcParams.update({'font.size': 14})

    all_labels = []
    all_circles = []

    color_map = plt.get_cmap("Paired")
    color_map_circle = plt.get_cmap("Greys", 10)
    color_map_tab10 = plt.get_cmap("tab20")

    if not ax:
        ax = fig.add_subplot(111)
    ax.xaxis.set_visible(False)
    ax.yaxis.set_visible(False)

    if not ax:
        ax.set_position([0.01, 0.01, 0.98, 0.98])  # set a new position

    # place sun:
    all_circles.append(
        ax.scatter(0,
                   0,
                   color=color_map_circle(7),
                   s=base_circle_size * 2,
                   label=labels[center_idx],
                   zorder=zorder_planet))
    # ax.text(0, 0.25, str(labels[center_idx]), verticalalignment="center", horizontalalignment='center', color=color_map_circle(7), zorder=zorder_label)

    last_orbit_had_values = False
    min_orbit = 0
    for orbit in range(1, orbits + 1):
        new_orbit = step * orbit + 0.1
        idx = (sun_corr_dist >= (1 - last_orbit)) & (sun_corr_dist >
                                                     (1 - new_orbit)) & all_idx
        idx_int = np.where(idx)[0]

        last_orbit = new_orbit

        if (sum(idx) == 0 and not last_orbit_had_values):
            min_orbit = orbit
            continue
        else:
            last_orbit_had_values = True

        orbit = orbit - min_orbit

        corr_dists = []
        for index in idx_int:
            corr_dists = np.append(corr_dists, corr_dist[center_idx][index])
        sort_args = np.argsort(corr_dists)
        idx_int = idx_int[sort_args]

        labels_idx = np.append(labels_idx, idx_int)
        planets = sum(idx)
        angles = get_angles(orbit, planets, ax, True)

        print(orbit)
        print(angles)
        print("IDX: " + str(sum(idx)) + " current orbit " + str(new_orbit) +
              " " + "last orbit: " + str(last_orbit))
        last_idx = -1
        # place planets
        while np.any(idx):
            idx_int = np.where(idx)[0]

            remaining = sum(idx)
            # current_planet = planets - remaining
            current_planet = 0
            print(current_planet)
            # breakpoint()
            current_idx = idx_int[current_planet]
            angle = angles[planets - remaining]
            x = get_x(angle, orbit)
            y = get_y(angle, orbit)
            # current_idx = idx_int[current_planet]
            color = colors[current_idx]
            # plt.scatter(x, y, color=color_map(color), s=100, label=labels[current_idx])
            cordinate_to_correlation[(x, y)] = {
                "is_planet": True,
                "corr_sun": corr_dist[center_idx, current_idx]
            }

            planet_idx = current_idx

            planet_corr = corr_dist[planet_idx]

            # ax.text(x-0.35, y+0.2, "{0:.3f}".format(planet_corr[center_idx]))
            col = "#03C03C" if positive[planet_idx] else "#FF6961"
            if orbit == orbits:
                col = "grey"
            # ax.text(x + 0.15, y + 0.15, str(labels[planet_idx]), verticalalignment="bottom", horizontalalignment='left',
            #        color=col, fontsize='small')
            moon_idx = (planet_corr >= 0.65) & idx
            moon_idx_int = np.where(moon_idx)[0]
            moons = sum(moon_idx)
            moon_angles = get_angles(0, moons, ax, False)

            # add orbit around planet if it has moons
            if moons > 1:
                circle = plt.Circle((x, y),
                                    moon_orbit,
                                    color='lightgrey',
                                    alpha=0.8,
                                    fill=True,
                                    zorder=zorder_moonorbit)
                ax.add_artist(circle)
                all_circles.append(circle)
            else:
                pointcol = color_map_tab10(
                    2) if labels[planet_idx] in selected else color_map_tab10(
                        0)
                labelcol = color_map_tab10(
                    2) if labels[planet_idx] in selected else color_map_tab10(
                        0)

                idx[planet_idx] = False
                all_idx[planet_idx] = False
                all_circles.append(
                    ax.scatter(x,
                               y,
                               color=pointcol,
                               s=base_circle_size,
                               label=labels[current_idx],
                               zorder=zorder_planet))

                # all_labels.append(ax.text(x + 0.15 if x > 0 else x - 0.15, y + 0.15 if y > 0 else y - 0.15, str(labels[planet_idx]), verticalalignment="center", horizontalalignment='right' if x < 0 else 'left',
                #    color=col, fontsize='small'))
                if show_labels:
                    all_labels.append(
                        ax.text(x,
                                y,
                                str(labels[planet_idx]),
                                verticalalignment="center",
                                horizontalalignment='right',
                                color=labelcol,
                                zorder=zorder_label,
                                path_effects=[
                                    path_effects.Stroke(linewidth=3,
                                                        foreground='white'),
                                    path_effects.Normal()
                                ]))
                continue

            if (current_idx != last_idx):
                print(labels[planet_idx])
                print("Drawing Moons " + str(current_idx) + " moons " +
                      str(sum(moon_idx)))

            last_idx = current_idx

            while np.any(moon_idx):
                remaining_moons = sum(moon_idx)
                current_moon = moons - remaining_moons
                current_moon_idx = moon_idx_int[current_moon]
                angle = moon_angles[current_moon]
                m_x = get_x(angle, moon_orbit) + x
                m_y = get_y(angle, moon_orbit) + y

                pointcol = color_map_tab10(2) if labels[
                    current_moon_idx] in selected else color_map_tab10(0)
                labelcol = color_map_tab10(
                    2) if labels[planet_idx] in selected else color_map_tab10(
                        0)

                all_circles.append(
                    ax.scatter(m_x,
                               m_y,
                               color=pointcol,
                               s=base_circle_size,
                               label=labels[current_moon_idx],
                               zorder=zorder_planet))
                cordinate_to_correlation[(m_x, m_y)] = {
                    "is_planet": False,
                    "corr_sun": corr_dist[center_idx][current_moon_idx]
                }
                col = "#03C03C" if positive[current_moon_idx] else "#FF6961"
                if orbit == orbits:
                    col = "grey"
                #all_labels.append(ax.text(m_x + 0.1 if m_x > x else m_x - 0.1, m_y + 0.1 if m_y > y else m_y - 0.1, str(labels[current_moon_idx]), verticalalignment="center",
                #        horizontalalignment='right' if m_x < x else 'left', fontsize='small', color=col))
                if show_labels:
                    all_labels.append(
                        ax.text(
                            m_x,
                            m_y,
                            str(labels[current_moon_idx]),
                            verticalalignment="center",
                            horizontalalignment='right' if m_x < x else 'left',
                            color=labelcol,
                            zorder=zorder_label,
                            path_effects=[
                                path_effects.Stroke(linewidth=3,
                                                    foreground='white'),
                                path_effects.Normal()
                            ]))
                moon_idx[current_moon_idx] = False
                idx[current_moon_idx] = False
                all_idx[current_moon_idx] = False

        # last_orbit = new_orbit

        print("Drawing circle")
        circlecol = color_map_circle((1 - ((orbit - 1) * step)) / 2)
        circle = plt.Circle((0, 0),
                            orbit,
                            color=circlecol,
                            fill=False,
                            zorder=zorder_orbit)

        ax.add_artist(circle)

        if 1 - float(orbit + min_orbit) / 10 > 0:
            orbit_t = ax.text(0,
                              -orbit + 0.1,
                              "{0:.1f}".format(1 -
                                               float(orbit + min_orbit) / 10),
                              verticalalignment="bottom",
                              horizontalalignment="center",
                              color=circlecol,
                              zorder=zorder_orbit)
            all_circles.append(orbit_t)

    labels_pos = np.array(labels)[labels_idx]
    recs = []

    # ax = plt.gca()

    if not ax:
        ax.axis("equal")
    # ax.margins(x=-0.3, y=-0.3)
    # ax.axis([-5, 5, -5, 5])
    # plt.axis([-10, 10, -10, 10])

    legend_elements = [
        Line2D([0], [0],
               linestyle='none',
               marker='o',
               color=color_map_tab10(0),
               label='candidate',
               markersize=10),
        Line2D([0], [0],
               linestyle='none',
               marker='o',
               color=color_map_circle(7),
               label='document',
               markersize=10)
    ]
    if len(selected) > 0:
        legend_elements.append(
            Line2D([0], [0],
                   linestyle='none',
                   marker='o',
                   color=color_map_tab10(2),
                   label='selected candidate',
                   markersize=10))
    ax.legend(handles=legend_elements, loc='upper left').set_zorder(102)

    # plt.subplots_adjust(top=0.95)

    if save_png:
        plt.savefig(image_path)
    if show_window:
        # only require mplcursors if we need an interactive plot
        # import mplcursors
        # cooordinate_to_correlation[(sel.target.x, sel.target.y)]["corr_sun"])
        # cursors = mplcursors.cursor(hover=True)
        # @cursors.connect("add")
        def _(sel):
            sel.annotation.set(position=(15, -15))
            # Note: Needs to be set separately due to matplotlib/matplotlib#8956.
            sel.annotation.get_bbox_patch().set(fc="lightgrey")
            sel.annotation.arrow_patch.set(arrowstyle="simple",
                                           fc="white",
                                           alpha=0)
            sel.annotation.set_text("Correlation to sun \n{}".format(
                cordinate_to_correlation[(sel.target[0],
                                          sel.target[1])]["corr_sun"]))

        if show_labels:
            adjust_text(all_labels,
                        add_objects=all_circles,
                        va="center",
                        ha="left",
                        ax=ax,
                        zorder=zorder_annotations,
                        horizontalalignment='left',
                        verticalalignment='center',
                        arrowprops=dict(connectionstyle="angle3",
                                        arrowstyle='-',
                                        color='darkgrey'))

            # for item in all_labels:
            #    item.set_fontsize(10)

        if not ax:
            plt.show()
def plot_animations(animations, joint_parents, scale_max, scale_min,
                    save=False, save_overlayed=False,
                    dataset_name=None, subset_name=None, fill=6, overwrite=False):
    if save:
        if not os.path.exists('videos'):
            os.makedirs('videos')
        dir_name = os.path.join('videos', dataset_name)
        if not os.path.exists(dir_name):
            os.makedirs(dir_name)
        if subset_name is not None:
            dir_name = os.path.join(dir_name, subset_name)
            if not os.path.exists(dir_name):
                os.makedirs(dir_name)
    total_animations = len(animations)
    joint_colors = list(sorted(colors.cnames.keys()))[::-1]
    total_colors = len(joint_colors)
    num_frames = len(animations[0])
    for ai, anim in enumerate(animations):
        if save:
            save_file_name = os.path.join(dir_name, str(ai).zfill(fill) + '.mp4')
            if not overwrite and os.path.exists(save_file_name):
                continue
        fig = plt.figure(figsize=(12, 8))
        ax = p3.Axes3D(fig)
        ax.set_xlim3d(scale_min[0], scale_max[0])
        ax.set_zlim3d(scale_min[1], scale_max[1])
        ax.set_ylim3d(scale_min[2], scale_max[2])
        ax.set_xticks([], False)
        ax.set_yticks([], False)
        ax.set_zticks([], False)
        ax.patch.set_alpha(0.)
        lines = [ax.plot([0, 0], [0, 0], [0, 0], color=joint_colors[ai % total_colors],
                         lw=2,
                         path_effects=[pe.Stroke(linewidth=3, foreground='black'),
                                       pe.Normal()])[0] for _ in range(anim.shape[1])]
        # ani = animation.FuncAnimation(fig, animate_joints, frames=num_frames,
        #                               fargs=(lines, animations[ai], parents),
        #                               interval=100, blit=True, repeat=True)
        if save:
            animation.FuncAnimation(fig, animate_joints, frames=num_frames,
                                    fargs=(lines, animations[ai], joint_parents),
                                    interval=100, blit=True, repeat=True).save(save_file_name)
        print('\rGenerating animations: {0:d}/{1:d} done ({2:.2f}%).'
              .format(ai + 1, total_animations, 100. * (ai + 1) / total_animations), end='')
        plt.cla()
        plt.close()

    if save_overlayed:
        save_file_name = os.path.join(dir_name, 'overlayed.mp4')
        if overwrite or not os.path.exists(save_file_name):
            lines = []
            fig = plt.figure(figsize=(12, 8))
            ax = p3.Axes3D(fig)
            ax.set_xlim3d(scale_min[0], scale_max[0])
            ax.set_zlim3d(scale_min[1], scale_max[1])
            ax.set_ylim3d(scale_min[2], scale_max[2])
            ax.set_xticks([], False)
            ax.set_yticks([], False)
            ax.set_zticks([], False)
            for ai, anim in enumerate(animations):
                lines.extend([ax.plot([0, 0], [0, 0], [0, 0], color=joint_colors[ai % total_colors],
                                      lw=2,
                                      path_effects=[pe.Stroke(linewidth=3, foreground='black'),
                                                    pe.Normal()])[0] for _ in range(anim.shape[1])])
            animation.FuncAnimation(fig, animate_joints, frames=num_frames,
                                    fargs=(lines, animations, joint_parents),
                                    interval=100, blit=True, repeat=True).save(save_file_name)
Beispiel #29
0
def _draw_outline(o, lw):
    o.set_path_effects([
        patheffects.Stroke(linewidth=lw, foreground='black'),
        patheffects.Normal()
    ])
Beispiel #30
0
def main():

    url = 'https://opendata.ecdc.europa.eu/covid19/casedistribution/csv'
    # df_ecdc = pd.read_html(url)
    df_ecdc = pd.read_csv('csv')

    df_owid = pd.read_csv('owid.csv')

    days = 14
    weeks = 2

    for region in (
        'Americas',
        'Nordic',
        'Europe',
        'Asia',
        'Oceania',
        'Africa',
        'G7',
        'EU',
        ):
        countries = d_regions[region]

        x = []
        y = []
        colors = []
        l_total_tests_per_thousand = []
        sizes = deathsCumulative = []
        labels = []
        z = []

        # print(df_ecdc)
        # print(df_owid)
        # print(df_ecdc['countryterritoryCode'].unique())
        # exit()
        for country in df_ecdc['countryterritoryCode'].unique():
            if country not in df_owid['iso_code'].unique():
                continue
            # if country not in europe + g7:
            #     continue
            # if country not in americas:
            #     continue
            if country not in countries:
                continue

            casesTotal = df_ecdc[df_ecdc['countryterritoryCode'] == country]['cases_weekly'].sum()
            if casesTotal < 100:  # Faroe Islands 188, Iceland 1882
                print('casesTotal', country, casesTotal)
                continue

            cases = df_ecdc[df_ecdc['countryterritoryCode'] == country]['cases_weekly']
            deaths = df_ecdc[df_ecdc['countryterritoryCode'] == country]['deaths_weekly']
            x2 = cases.head(1 * weeks).sum()
            x1 = cases.head(2 * weeks).tail(1 * weeks).sum()
            # if country == 'LTU':
            #     continue  # negative values???
            #     print(cases.to_string())
            #     exit()
            # if country in ('CYP',):
            #     continue  # no testing?
            y2 = deaths.head(1 * weeks).sum()
            y1 = deaths.head(2 * weeks).tail(1 * weeks).sum()
            # if x1 == 0 or y1 == 0:
            #     continue

            total_tests_per_thousand = df_owid[df_owid['iso_code'] == country]['total_tests_per_thousand']
            if total_tests_per_thousand.max() == 0:
                continue

            label = df_owid[df_owid['iso_code'] == country]['location'].iloc[0]

            # changeCasesWeekly = 100 * (x2 - x1) / x1
            # changeDeathsWeekly = 100 * (y2 - y1) / y1

            # x1 = cases.sum() - cases.head(7).sum()
            # x2 = cases.sum()
            x1 = cases.head(2 * weeks).tail(1 * weeks).sum()
            x2 = cases.head(1 * weeks).sum()
            if x1 < 0 or x2 < 0:
                continue
            if x1 == 0:
                changeCasesWeekly = 0
            else:
                changeCasesWeekly = 100 * (x2 - x1) / x1
            # Skip outliers.
            if changeCasesWeekly > 200:
                # Small absolute change.
                if y1 < 50 or y2 < 50:
                    changeCasesWeekly = 200
                else:
                    pass
                # print('changeCasesWeekly', country, changeCasesWeekly)
                # continue

            # y1 = deaths.sum() - deaths.head(7).sum()
            # y2 = deaths.sum()
            x1 = deaths.head(2 * weeks).tail(1 * weeks).sum()
            x2 = deaths.head(1 * weeks).sum()
            if y1 == 0:  # Faroe Islands have zero deaths
                changeDeathsWeekly = 0
            else:
                changeDeathsWeekly = 100 * (y2 - y1) / y1
            # Skip when deaths are negative:
            # https://www.theguardian.com/world/2020/aug/12/coronavirus-death-toll-in-england-revised-down-by-more-than-5000
            if y1 < 0 or y2 < 0:
                continue
            # Skip outliers.
            if changeDeathsWeekly > 200:
                # Few absolute changes.
                if y1 < 50 or y2 < 50:
                    changeDeathsWeekly = 200
                else:
                    pass
                # print('changeDeathsWeekly', country, changeDeathsWeekly)
                # continue

            # z2 = total_tests_per_thousand.max()
            # # Skip if no testing.
            # if z2 == 0 or np.isnan(z2):
            #     if country in ('FRO',):
            #         change = 0
            #     else:
            #         continue
            # else:
            #     for i in range(7, 21):
            #         z1 = total_tests_per_thousand.iloc[-i]
            #         if z1 == z2:
            #             continue
            #         if not np.isnan(z1):
            #             change = 100 * (z2 - z1) / z1
            #             break
            #     else:
            #         change = 0
            #         # print(country, z2)
            #         # print(total_tests_per_thousand.to_string())
            #         # exit()

            v1 = total_tests_per_thousand.tail(3 * days).head(1 * days).max()
            v2 = total_tests_per_thousand.tail(2 * days).head(1 * days).max()
            v3 = total_tests_per_thousand.tail(1 * days).max()
            z2 = v3 - v2
            z1 = v2 - v1

            if z1 == 0:
                change = 0
            else:
                change = 100 * (z2 - z1) / z1
            z.append(change)

            # z.append(100 * (z2 - z1) / z1)

            l_total_tests_per_thousand.append(total_tests_per_thousand.max())

            x.append(changeCasesWeekly)
            y.append(changeDeathsWeekly)
            labels.append(label)
            # sizes.append(5 * math.sqrt(deaths))
            deathsTotal = df_ecdc[df_ecdc['countryterritoryCode'] == country]['deaths_weekly'].sum()
            # size = 10 * deathsTotal ** (1/3)
            size = max(20, 10 * deathsTotal ** (1/3))
            sizes.append(size)
            # print(country, changeCasesWeekly, changeDeathsWeekly, size)

        # for _ in l_total_tests_per_thousand:
        #     colors.append(_ / max(l_total_tests_per_thousand))

        colors = z

        fig, ax = plt.subplots()

        fig.set_size_inches(16 / 2, 9 / 2)

        for t in reversed(sorted(zip(sizes, x, y, colors, labels))):
            sizes.append(t[0])
            x.append(t[1])
            y.append(t[2])
            colors.append(t[3])
            labels.append(t[4])
        sizes = sizes[len(sizes)//2:]
        x = x[len(x)//2::]
        y = y[len(y)//2::]
        colors = colors[len(colors)//2::]
        labels = labels[len(labels)//2::]

        paths = ax.scatter(
            x, y,
            c = colors,
            s = sizes,
            marker = 'o',
            # label = labels,
            edgecolor = 'black',
            linewidth = 0.1,
            # font = {
            #     # 'family' : 'normal',
            #     # 'weight' : 'bold',
            #     'size'   : 'small',
            #     },
            alpha = 0.5,
            cmap = 'viridis',
            # vmin = min(l_total_tests_per_thousand),
            # vmax = max(l_total_tests_per_thousand),
            vmin = min(0, min(colors)),
            vmax = max(0, max(colors)),
            # vmax = 25,
            )

        # ax.axhline(0, color='black', linewidth=0.5, linestyle='--')
        # ax.axvline(0, color='black', linewidth=0.5, linestyle='--')

        cbar = fig.colorbar(paths)
        # cbar.set_label('Total tests per thousand')
        # cbar.set_label('Weekly change in total tests (%)')
        # cbar.set_label(f'{days} day change in weekly tests (%)')
        cbar.set_label('Change in weekly tests (%)')

        texts = []
        for xi, yi, label in zip(x, y, labels):
            texts.append(ax.text(
                xi, yi, label,
                size='xx-small',
        ##        ha='left', va='bottom',
                ha='center', va='center',
                color='white',
                path_effects=[
                    path_effects.Stroke(linewidth=1, foreground='black'),
                    path_effects.Normal(),
                    ],
                ))

        # adjust_text(texts, arrowprops=dict(arrowstyle='->', color='black'))
        adjust_text(texts)

        # legend_elements = []
        # print(colors)
        # print(max(colors))
        # print(l_total_tests_per_thousand)
        # print(max(l_total_tests_per_thousand))
        # print(min(l_total_tests_per_thousand))
        # exit()
        # for total_tests_per_thousand in [0, ]:
        #     label = forwardPE
        #     if forwardPE == 30:
        #         label = '30+'
        #     legend_elements.append(
        #         Line2D(
        #             [0], [0], marker='o',
        #             color = 'white',  # don't show line
        #             label=label,
        #             markerfacecolor=color_forwardPE(forwardPE),
        #             markersize=10,
        #             ))
        # legend_color = ax.legend(
        #     handles=legend_elements,
        #     loc='upper right',
        #     title=args.color,
        #     # bbox_to_anchor=(0.75, 1),
        #     bbox_to_anchor=(0.95, 1),
        #     )

        # # produce a legend with a cross section of sizes from the scatter
        # handles, labels = scatter.legend_elements(
        #     prop="sizes", alpha=0.5,
        #     func=lambda s: s / 3.01,
        #     )
        # labels[-1] = '5.0+'
        # labels = labels[0::2]
        # handles = handles[0::2]
        # legend_size = ax.legend(
        #     handles, labels, loc="upper right",
        #     title=args.size,
        #     # func=lambda s: np.sqrt(s) / 4,
        #     )
        # ax.add_artist(legend_size)

        # ax.set_xlabel('Weekly change in total cases (%)')
        # ax.set_ylabel('Weekly change in total fatalities (%)')
        # ax.set_xlabel(f'{weeks} week change in weekly cases (%)')
        # ax.set_ylabel(f'{weeks} week change in weekly fatalities (%)')
        ax.set_xlabel(f'Change in weekly cases (%)')
        ax.set_ylabel(f'Change in weekly fatalities (%)')
        ax.set_title(region)

        # ax.set_xlim(0, 75)  # El Salvador
        # ax.set_ylim(0, 65)  # Mexico
        # ax.set_xlim(0, 100)  # Ghana
        # ax.set_ylim(0, 120)  # Senegal
        # ax.set_xlim(0, 5 + 5 * max((25, max(x), max(y))) // 5)
        # ax.set_ylim(0, 5 + 5 * max((25, max(x), max(y))) // 5)

        # ax.set_xlim(0, 25)  # Canada
        # ax.set_ylim(0, 30)  # Canada

        # ax.set_xlim(0, min(100, 2 + 2 * max((20, max(x))) // 2))
        # ax.set_ylim(0, min(100, 2 + 2 * max((20, max(y))) // 2))

        ax.axvline(x=0, ls='--', color='.1', lw=0.5)
        ax.axhline(y=0, ls='--', color='.1', lw=0.5)

        path = 'plot_bubble_{}.png'.format(region)
        fig.savefig(path, dpi=200)
        print(path)
        fig.savefig('plot_bubble_{}_{}.png'.format(region, date.today().isoformat()), dpi=200)

    return