# Source code for dipy.viz.streamline

    import warnings

    from dipy.testing.decorators import warning_for_keywords
    from dipy.utils.optpkg import optional_package

    plt, have_plt, _ = optional_package("matplotlib.pyplot")
    fury, has_fury, _ = optional_package("fury", min_version="0.10.0")
    if has_fury:
        from dipy.viz import actor, window

    sagittal_deprecation_warning_msg = (
        "The view argument value `sagital` is deprecated and "  # codespell:ignore sagital
        "its support will be removed in a future version. Please, use `sagittal` instead."
    )

    @warning_for_keywords()
    def show_bundles(
        bundles,
        *,
        interactive=True,
        view="sagittal",
        colors=None,
        linewidth=0.3,
        save_as=None,
    ):
        """Render bundles to visualize them interactively or save them into a png.

        The function allows to just render the bundles in an interactive plot or
        to export them into a png file.

        Parameters
        ----------
        bundles : list
            Bundles to be rendered.
        interactive : boolean, optional
            If True a 3D interactive rendering is created. Default is True.
        view : str, optional
            Viewing angle. Supported options: 'sagittal', 'axial' and 'coronal'.
        colors : list, optional
           Colors to be used for each bundle. If None default colors are used.
        linewidth : float, optional
            Width of each rendered streamline. Default is 0.3.
        save_as : str, optional
            If not None rendered scene is stored in a png file with that name.
            Default is None.

        """

        if view == "sagital":  # codespell:ignore sagital
            warnings.warn(
                sagittal_deprecation_warning_msg,
                category=DeprecationWarning,
                stacklevel=2,
            )
            view = "sagittal"

        scene = window.Scene()
        scene.SetBackground(1.0, 1, 1)

        for i, bundle in enumerate(bundles):
            if colors is None:
                lines_actor = actor.streamtube(bundle, linewidth=linewidth)
            else:
                lines_actor = actor.streamtube(
                    bundle, linewidth=linewidth, colors=colors[i]
                )
            if view == "sagittal":
                lines_actor.RotateX(-90)
                lines_actor.RotateZ(90)
            elif view == "axial":
                pass
            elif view == "coronal":
                lines_actor.RotateX(-90)
            else:
                raise ValueError(
                    "Invalid view argument value. Use 'sagittal', 'axial' or 'coronal'."
                )

            scene.add(lines_actor)

        if interactive:
            window.show(scene)

        if save_as is not None:
            window.record(scene=scene, n_frames=1, out_path=save_as, size=(900, 900))

    @warning_for_keywords()
    def viz_two_bundles(b1, b2, fname, *, c1=(1, 0, 0), c2=(0, 1, 0), interactive=False):
        """Render and plot two bundles to visualize them.

        Parameters
        ----------
        b1 : Streamlines
            Bundle one to be rendered.
        b2 : Streamlines
            Bundle two to be rendered.
        fname: str
            Rendered scene is stored in a png file with that name.
        C1 : tuple, optional
            Color to be used for first bundle. Default red.
        C2 : tuple, optional
            Color to be used for second bundle. Default green.
        interactive : boolean, optional
            If True a 3D interactive rendering is created. Default is True.

        """
        ren = window.Scene()
        ren.SetBackground(1, 1, 1)

        actor1 = actor.line(b1, colors=c1)
        actor1.GetProperty().SetEdgeVisibility(1)
        actor1.GetProperty().SetRenderLinesAsTubes(1)
        actor1.GetProperty().SetLineWidth(6)
        actor1.GetProperty().SetOpacity(1)
        actor1.RotateX(-70)
        actor1.RotateZ(90)

        ren.add(actor1)

        actor2 = actor.line(b2, colors=c2)
        actor2.GetProperty().SetEdgeVisibility(1)
        actor2.GetProperty().SetRenderLinesAsTubes(1)
        actor2.GetProperty().SetLineWidth(6)
        actor2.GetProperty().SetOpacity(1)
        actor2.RotateX(-70)
        actor2.RotateZ(90)

        ren.add(actor2)

        if interactive:
            window.show(ren)

        window.record(scene=ren, n_frames=1, out_path=fname, size=(1200, 1200))
        if interactive:
            im = plt.imread(fname)
            plt.figure(figsize=(10, 10))
            plt.imshow(im)

    @warning_for_keywords()
    def viz_vector_field(
        points_aligned,
        directions,
        colors,
        offsets,
        fname,
        *,
        bundle=None,
        interactive=False,
    ):
        """Render and plot vector field.

        Parameters
        ----------
        points_aligned : List
            List containing starting positions of vectors.
        directions : List
            List containing unitary directions of vectors.
        colors : List
            List containing colors for each vector.
        offsets : List
            List containing vector field modules.
        fname: str
            Rendered scene is stored in a png file with that name.
        bundle : Streamlines, optional
            Bundle to be rendered with vector field (Default None).
        interactive : boolean, optional
            If True a 3D interactive rendering is created. Default is True.

        """
        scene = window.Scene()
        scene.SetBackground(1.0, 1, 1)
        arrows = actor.arrow(points_aligned, directions, colors, scales=offsets)
        arrows.RotateX(-70)
        arrows.RotateZ(90)
        scene.add(arrows)

        if bundle:
            actor1 = actor.line(bundle, colors=(0, 0, 1))
            actor1.RotateX(-70)
            actor1.RotateZ(90)
            scene.add(actor1)

        if interactive:
            window.show(scene)

        window.record(scene=scene, n_frames=1, out_path=fname, size=(1200, 1200))
        if interactive:
            im = plt.imread(fname)
            plt.figure(figsize=(10, 10))
            plt.imshow(im)

    @warning_for_keywords()
    def viz_displacement_mag(bundle, offsets, fname, *, interactive=False):
        """Render and plot displacement magnitude over the bundle.

        Parameters
        ----------
        bundle : Streamlines,
            Bundle to be rendered.
        offsets : List
            List containing displacement magnitdues per point on the bundle.
        fname: str
            Rendered scene is stored in a png file with that name.
        interactive : boolean, optional
            If True a 3D interactive rendering is created. Default is True.

        """
        scene = window.Scene()
        hue = (0.1, 0.9)
        hue = (0.9, 0.3)
        saturation = (0.5, 1)
        scene.background((1, 1, 1))
        lut_cmap = actor.colormap_lookup_table(
            scale_range=(offsets.min(), offsets.max()),
            hue_range=hue,
            saturation_range=saturation,
        )

        stream_actor = actor.line(
            bundle, colors=offsets, linewidth=7, lookup_colormap=lut_cmap
        )

        stream_actor.RotateX(-70)
        stream_actor.RotateZ(90)

        scene.add(stream_actor)
        bar = actor.scalar_bar(lookup_table=lut_cmap)

        scene.add(bar)

        if interactive:
            window.show(scene)

        window.record(scene=scene, n_frames=1, out_path=fname, size=(2000, 1500))
        if interactive:
            im = plt.imread(fname)
            plt.figure(figsize=(10, 10))
            plt.imshow(im)