def plot_3d(
    points: np.ndarray,
    labels: np.ndarray,
    colors: list[str] | None = None,
    save: bool = True,
    f_name: str = "",
) -> "matplotlib.figure.Figure":  # pragma: no cover
    """
    Generates a 3-D plot in of the provided points where the labels define the color that will be used to color each
    data point. Concretely, the color of points[i] is defined by colors(labels[i]). Thus, there should be as many labels
     as colors.

    :param points: arrays with 3-D coordinates of the plots to be plotted.
    :param labels: array of integers that determines the color used in the plot for the data point.
        Need to start from 0 and be sequential from there on.
    :param colors: Optional argument to specify colors to be used in the plot. If provided, this array should contain
    as many colors as labels.
    :param save:  When set to True, saves image into a file inside `ART_DATA_PATH` with the name `f_name`.
    :param f_name: Name used to save the file when save is set to True.
    :return: A figure object.
    """
    # Disable warnings of unused import because all imports in this block are required
    # pylint: disable=unused-import
    # import matplotlib
    import matplotlib.pyplot as plt

    from mpl_toolkits import mplot3d  # noqa: F401

    if colors is None:  # pragma: no cover
        colors = []
        for i in range(len(np.unique(labels))):
            colors.append("C" + str(i))
    else:
        if len(colors) != len(np.unique(labels)):
            raise ValueError("The amount of provided colors should match the number of labels in the 3pd plot.")

    fig = plt.figure()
    axis = plt.axes(projection="3d")

    for i, coord in enumerate(points):
        try:
            color_point = labels[i]
            axis.scatter3D(coord[0], coord[1], coord[2], color=colors[color_point])  # type: ignore
        except IndexError:
            raise ValueError(
                "Labels outside the range. Should start from zero and be sequential there after"
            ) from IndexError
    if save:  # pragma: no cover
        file_name = os.path.realpath(os.path.join(config.ART_DATA_PATH, f_name))
        folder = os.path.split(file_name)[0]

        if not os.path.exists(folder):
            os.makedirs(folder)
        fig.savefig(file_name, bbox_inches="tight")
        logger.info("3d-plot saved to %s.", file_name)

    return fig

    Generates a 3-D plot in of the provided points where the labels define the color that will be used to color each
    data point. Concretely, the color of points[i] is defined by colors(labels[i]). Thus, there should be as many labels
     as colors.

    :param points: arrays with 3-D coordinates of the plots to be plotted.
    :param labels: array of integers that determines the color used in the plot for the data point.
        Need to start from 0 and be sequential from there on.
    :param colors: Optional argument to specify colors to be used in the plot. If provided, this array should contain
    as many colors as labels.
    :param save:  When set to True, saves image into a file inside `ART_DATA_PATH` with the name `f_name`.
    :param f_name: Name used to save the file when save is set to True.
    :return: A figure object.
    
art/visualization.py