def scatterplot(
    points,
    samples=None,
    ids=None,
    link_field=None,
    labels=None,
    sizes=None,
    edges=None,
    classes=None,
    figure=None,
    multi_trace=None,
    marker_size=None,
    colorscale=None,
    log_colorscale=False,
    title=None,
    trace_title=None,
    labels_title=None,
    sizes_title=None,
    edges_title=None,
    show_colorbar_title=None,
    axis_equal=False,
    **kwargs,
):
    """Generates an interactive scatterplot of the given points.

    You can attach plots generated by this method to an App session via its
    :attr:`fiftyone.core.session.Session.plots` attribute, which will
    automatically sync the session's view with the currently selected points in
    the plot. To enable this functionality, you must pass ``samples`` to this
    method.

    This method supports 2D or 3D visualizations, but interactive point
    selection is only available in 2D.

    You can use the ``labels`` parameters to define a coloring for the points,
    and you can use the ``sizes`` parameter to scale the sizes of the points.

    Args:
        points: a ``num_points x num_dims`` array-like of points
        samples (None): the :class:`fiftyone.core.collections.SampleCollection`
            whose data is being visualized
        ids (None): an array-like of IDs corresponding to the points. If not
            provided but ``samples`` are provided, the appropriate IDs will be
            extracted from the samples
        link_field (None): a field of ``samples`` whose data corresponds to
            ``points``. Can be any of the following:

            -   None, if the points correspond to samples
            -   ``"frames"``, if the points correspond to frames
            -   the name of a :class:`fiftyone.core.labels.Label` field, if the
                points correspond to the labels in this field
        labels (None): data to use to color the points. Can be any of the
            following:

            -   the name of a sample field or ``embedded.field.name`` of
                ``samples`` from which to extract numeric or string values
            -   a :class:`fiftyone.core.expressions.ViewExpression` defining
                numeric or string values to compute from ``samples`` via
                :meth:`fiftyone.core.collections.SampleCollection.values`
            -   an array-like of numeric or string values
            -   a list of array-likes of numeric or string values, if
                ``link_field`` refers to frames and/or a label list field like
                :class:`fiftyone.core.labels.Detections`
        sizes (None): data to use to scale the sizes of the points. Can be any
            of the following:

            -   the name of a sample field or ``embedded.field.name`` of
                ``samples`` from which to extract numeric values
            -   a :class:`fiftyone.core.expressions.ViewExpression` defining
                numeric values to compute from ``samples`` via
                :meth:`fiftyone.core.collections.SampleCollection.values`
            -   an array-like of numeric values
            -   a list of array-likes of numeric or string values, if
                ``link_field`` refers to frames and/or a label list field like
                :class:`fiftyone.core.labels.Detections`
        edges (None): a ``num_edges x 2`` array of row indices into ``points``
            defining undirected edges between points to render as a separate
            trace on the scatterplot
        classes (None): a list of classes whose points to plot. Only applicable
            when ``labels`` contains strings. If provided, the element order of
            this list also controls the z-order and legend order of multitrace
            plots (first class is rendered first, and thus on the bottom, and
            appears first in the legend)
        figure (None): a :class:`plotly:plotly.graph_objects.Figure` to which
            to add the plot
        multi_trace (None): whether to render each class as a separate trace.
            Only applicable when ``labels`` contains strings. By default, this
            will be true if there are up to 25 classes
        marker_size (None): the marker size to use. If ``sizes`` are provided,
            this value is used as a reference to scale the sizes of all points
        colorscale (None): a plotly colorscale to use. Only applicable when
            ``labels`` contains numeric data. See
            https://plotly.com/python/colorscales for options
        log_colorscale (False): whether to apply the colorscale on a log scale.
            This is useful to better visualize variations in smaller values
            when large values are also present
        title (None): a title for the plot
        trace_title (None): a name for the scatter trace. Only applicable when
            plotting a single trace
        labels_title (None): a title string to use for ``labels`` in the
            tooltip and the colorbar title. By default, if ``labels`` is a
            field name, this name will be used, otherwise the colorbar will not
            have a title and the tooltip will use "label"
        sizes_title (None): a title string to use for ``sizes`` in the tooltip.
            By default, if ``sizes`` is a field name, this name will be used,
            otherwise the tooltip will use "size"
        edges_title (None): a title string to use for ``edges`` in the legend.
            If none is provided, edges are not included in the legend
        show_colorbar_title (None): whether to show the colorbar title. By
            default, a title will be shown only if a value was passed to
            ``labels_title`` or an appropriate default can be inferred from
            the ``labels`` parameter
        axis_equal (False): whether to set the axes to equal scale
        **kwargs: optional keyword arguments for
            :meth:`plotly:plotly.graph_objects.Figure.update_layout`

    Returns:
        one of the following

        -   an :class:`InteractiveScatter`, for 2D points and when IDs are
            available
        -   a :class:`PlotlyNotebookPlot`, if you're working in a Jupyter
            notebook but the above conditions aren't met
        -   a plotly figure, otherwise
    """
    points = np.asarray(points)
    num_dims = points.shape[1]

    if num_dims not in {2, 3}:
        raise ValueError("This method only supports 2D or 3D points")

    labels_title, sizes_title, colorbar_title = _parse_titles(
        labels, labels_title, sizes, sizes_title, show_colorbar_title
    )

    (
        points,
        ids,
        labels,
        sizes,
        edges,
        classes,
        categorical,
    ) = parse_scatter_inputs(
        points,
        samples=samples,
        ids=ids,
        link_field=link_field,
        labels=labels,
        sizes=sizes,
        edges=edges,
        classes=classes,
    )

    if categorical:
        if multi_trace is None:
            multi_trace = len(classes) <= _MAX_LABEL_TRACES

        if multi_trace:
            figure = _plot_scatter_categorical(
                points,
                labels,
                classes,
                sizes,
                edges,
                ids,
                figure,
                marker_size,
                labels_title,
                sizes_title,
                edges_title,
                colorbar_title,
                axis_equal,
            )
        else:
            figure = _plot_scatter_categorical_single_trace(
                points,
                labels,
                classes,
                sizes,
                edges,
                ids,
                figure,
                marker_size,
                trace_title,
                labels_title,
                sizes_title,
                edges_title,
                colorbar_title,
                axis_equal,
            )
    else:
        figure = _plot_scatter_numeric(
            points,
            labels,  # numeric values
            sizes,
            edges,
            ids,
            figure,
            marker_size,
            colorscale,
            log_colorscale,
            trace_title,
            labels_title,
            sizes_title,
            edges_title,
            colorbar_title,
            axis_equal,
        )

    figure.update_layout(**_DEFAULT_LAYOUT)
    figure.update_layout(title=title, **kwargs)

    if num_dims == 3:
        if samples is not None:
            msg = "Interactive selection is only supported in 2D"
            warnings.warn(msg)

        if foc.is_jupyter_context():
            figure = PlotlyNotebookPlot(figure)

        return figure

    if ids is None:
        if foc.is_jupyter_context():
            return PlotlyNotebookPlot(figure)

        return figure

    (
        link_type,
        label_fields,
        selection_mode,
        init_fcn,
    ) = InteractiveScatter.recommend_link_type(
        label_field=link_field,
        samples=samples,
    )

    return InteractiveScatter(
        figure,
        link_type=link_type,
        init_view=samples,
        label_fields=label_fields,
        selection_mode=selection_mode,
        init_fcn=init_fcn,
    )
Generates an interactive scatterplot of the given points.

    You can attach plots generated by this method to an App session via its
    :attr:`fiftyone.core.session.Session.plots` attribute, which will
    automatically sync the session's view with the currently selected points in
    the plot. To enable this functionality, you must pass ``samples`` to this
    method.

    This method supports 2D or 3D visualizations, but interactive point
    selection is only available in 2D.

    You can use the ``labels`` parameters to define a coloring for the points,
    and you can use the ``sizes`` parameter to scale the sizes of the points.

    Args:
        points: a ``num_points x num_dims`` array-like of points
        samples (None): the :class:`fiftyone.core.collections.SampleCollection`
            whose data is being visualized
        ids (None): an array-like of IDs corresponding to the points. If not
            provided but ``samples`` are provided, the appropriate IDs will be
            extracted from the samples
        link_field (None): a field of ``samples`` whose data corresponds to
            ``points``. Can be any of the following:

            -   None, if the points correspond to samples
            -   ``"frames"``, if the points correspond to frames
            -   the name of a :class:`fiftyone.core.labels.Label` field, if the
                points correspond to the labels in this field
        labels (None): data to use to color the points. Can be any of the
            following:

            -   the name of a sample field or ``embedded.field.name`` of
                ``samples`` from which to extract numeric or string values
            -   a :class:`fiftyone.core.expressions.ViewExpression` defining
                numeric or string values to compute from ``samples`` via
                :meth:`fiftyone.core.collections.SampleCollection.values`
            -   an array-like of numeric or string values
            -   a list of array-likes of numeric or string values, if
                ``link_field`` refers to frames and/or a label list field like
                :class:`fiftyone.core.labels.Detections`
        sizes (None): data to use to scale the sizes of the points. Can be any
            of the following:

            -   the name of a sample field or ``embedded.field.name`` of
                ``samples`` from which to extract numeric values
            -   a :class:`fiftyone.core.expressions.ViewExpression` defining
                numeric values to compute from ``samples`` via
                :meth:`fiftyone.core.collections.SampleCollection.values`
            -   an array-like of numeric values
            -   a list of array-likes of numeric or string values, if
                ``link_field`` refers to frames and/or a label list field like
                :class:`fiftyone.core.labels.Detections`
        edges (None): a ``num_edges x 2`` array of row indices into ``points``
            defining undirected edges between points to render as a separate
            trace on the scatterplot
        classes (None): a list of classes whose points to plot. Only applicable
            when ``labels`` contains strings. If provided, the element order of
            this list also controls the z-order and legend order of multitrace
            plots (first class is rendered first, and thus on the bottom, and
            appears first in the legend)
        figure (None): a :class:`plotly:plotly.graph_objects.Figure` to which
            to add the plot
        multi_trace (None): whether to render each class as a separate trace.
            Only applicable when ``labels`` contains strings. By default, this
            will be true if there are up to 25 classes
        marker_size (None): the marker size to use. If ``sizes`` are provided,
            this value is used as a reference to scale the sizes of all points
        colorscale (None): a plotly colorscale to use. Only applicable when
            ``labels`` contains numeric data. See
            https://plotly.com/python/colorscales for options
        log_colorscale (False): whether to apply the colorscale on a log scale.
            This is useful to better visualize variations in smaller values
            when large values are also present
        title (None): a title for the plot
        trace_title (None): a name for the scatter trace. Only applicable when
            plotting a single trace
        labels_title (None): a title string to use for ``labels`` in the
            tooltip and the colorbar title. By default, if ``labels`` is a
            field name, this name will be used, otherwise the colorbar will not
            have a title and the tooltip will use "label"
        sizes_title (None): a title string to use for ``sizes`` in the tooltip.
            By default, if ``sizes`` is a field name, this name will be used,
            otherwise the tooltip will use "size"
        edges_title (None): a title string to use for ``edges`` in the legend.
            If none is provided, edges are not included in the legend
        show_colorbar_title (None): whether to show the colorbar title. By
            default, a title will be shown only if a value was passed to
            ``labels_title`` or an appropriate default can be inferred from
            the ``labels`` parameter
        axis_equal (False): whether to set the axes to equal scale
        **kwargs: optional keyword arguments for
            :meth:`plotly:plotly.graph_objects.Figure.update_layout`

    Returns:
        one of the following

        -   an :class:`InteractiveScatter`, for 2D points and when IDs are
            available
        -   a :class:`PlotlyNotebookPlot`, if you're working in a Jupyter
            notebook but the above conditions aren't met
        -   a plotly figure, otherwise
    
fiftyone/core/plots/plotly.py