def _plot_pareto_frontier(self, ranks=None, save_path=None, is_show=True, save_format="html"):
        """Plot pareto frontier with plotly.

        :param ranks: the rank list of the metrics to be shown in the pareto frontier chart
        :param save_path: the path to save the pareto frontier chart
        :param is_show: whether to show the pareto frontier chart
        :param save_format: the format of the pareto frontier chart, can be "html" or "image"
        """
        assert save_path is not None or is_show, "you must specify the save path or set is_show to True"
        if self._len_first_metric() <= 1:
            logger.warning("There is no need to plot pareto frontier with only one metric")
            return

        ranks = ranks or [1, 2]
        index = [i - 1 for i in ranks]
        self._mark_pareto_frontier()
        nodes_to_be_plotted = self._get_candidates()

        if not nodes_to_be_plotted:
            logger.warning("there is no candidate to be plotted.")
            return
        # plot pareto frontier
        try:
            import pandas as pd
            import plotly.graph_objects as go

            pd.options.mode.chained_assignment = None
        except ImportError:
            logger.warning("Please make sure you installed pandas and plotly successfully.")
            return

        # select column to shown in pareto frontier chat
        metric_column = self._get_metrics_name_by_indices(index)
        # to support 3d pareto_frontier
        if len(metric_column) < 2:
            logger.error("you can not plot pareto frontier with less than 2 metrics")
            return
        dict_data = defaultdict(list)
        for k, v in nodes_to_be_plotted.items():
            dict_data["model_id"].append(k)
            dict_data["is_pareto_frontier"].append(v.is_pareto_frontier)
            dict_data["marker_color"].append("red" if v.is_pareto_frontier else "blue")
            dict_data["marker_size"].append(12 if v.is_pareto_frontier else 8)
            show_list = [k]
            for metric_name in metric_column:
                dict_data[metric_name].append(v.metrics.value[metric_name].value)
                show_list.append(f"{metric_name}: {v.metrics.value}")
            dict_data["show_text"].append("<br>".join(show_list))
        data = pd.DataFrame(dict_data)

        fig = go.Figure()
        fig.add_trace(
            go.Scatter(
                x=dict_data[metric_column[index[0]]],
                y=dict_data[metric_column[index[1]]],
                mode="markers",
                name="all footprints",
                marker={"color": dict_data["marker_color"], "size": dict_data["marker_size"]},
                customdata=dict_data["show_text"],
                hovertemplate="%{customdata}",
            )
        )
        pareto_frontiers_data = data.loc[data["is_pareto_frontier"]]
        pareto_frontiers_data = pareto_frontiers_data.sort_values(metric_column, ascending=True)
        fig.add_trace(
            go.Scatter(
                x=pareto_frontiers_data[metric_column[index[0]]],
                y=pareto_frontiers_data[metric_column[index[1]]],
                mode="lines",
                name="pareto frontiers",
            )
        )
        size_params = {"width": 1000, "height": 600}
        fig.update_layout(xaxis_title=metric_column[index[0]], yaxis_title=metric_column[index[1]], **size_params)

        if save_path:
            if save_format == "html":
                save_path = f"{save_path}.html" if not str(save_path).endswith(".html") else save_path
                fig.write_html(save_path)
            elif save_format == "image":
                save_path = f"{save_path}.png" if not str(save_path).endswith(".png") else save_path
                fig.write_image(save_path)

        if is_show:
            fig.show()
Plot pareto frontier with plotly.

        :param ranks: the rank list of the metrics to be shown in the pareto frontier chart
        :param save_path: the path to save the pareto frontier chart
        :param is_show: whether to show the pareto frontier chart
        :param save_format: the format of the pareto frontier chart, can be "html" or "image"
        
olive/engine/footprint.py