Skip to content

Matplotlib Plots

mpl_plots

plot_trajectories

plot_trajectories(
    trajectories: List[Trajectory], scatter_3d: bool = False
) -> Tuple[Figure, Figure, Union[Figure, None]]

Plots the trajectories in 2d or 3d using matplotlib.

This function creates one 2D or 3D plot for the xy(z) coordinates of the trajectories, one subplot for the xyz coordinates and one subplot for the rpy angles.

Parameters:

  • trajectories (List[Trajectory]) –

    List of trajectories to plot.

  • scatter_3d (bool, default: False ) –

    Whether to create a 3D scatter plot. Defaults to False.

Returns:

  • Tuple[Figure, Figure, Union[Figure, None]]

    Tuple[Figure, Figure, Union[Figure, None]]: Figures for the position, xyz and rpy plots.

Source code in trajectopy\visualization\mpl_plots.py
def plot_trajectories(
    trajectories: List[Trajectory], scatter_3d: bool = False
) -> Tuple[Figure, Figure, Union[Figure, None]]:
    """Plots the trajectories in 2d or 3d using matplotlib.

    This function creates one 2D or 3D plot for the xy(z) coordinates of the trajectories,
    one subplot for the xyz coordinates and one subplot for the rpy angles.

    Args:
        trajectories (List[Trajectory]): List of trajectories to plot.
        scatter_3d (bool, optional): Whether to create a 3D scatter plot. Defaults to False.

    Returns:
        Tuple[Figure, Figure, Union[Figure, None]]: Figures for the position, xyz and rpy plots.
    """
    fig_pos = plot_positions(trajectories=trajectories, scatter_3d=scatter_3d)
    fig_xyz = plot_xyz(trajectories=trajectories)
    fig_rpy = plot_rpy(trajectories=trajectories)
    return fig_pos, fig_xyz, fig_rpy

plot_correlation_heatmap

plot_correlation_heatmap(
    estimated_parameters: AlignmentParameters,
    enabled_only: bool = True,
) -> Figure

Plots the correlation heatmap of the alignment parameters using matplotlib.

Parameters:

  • estimated_parameters (AlignmentParameters) –

    Estimated parameters.

  • enabled_only (bool, default: True ) –

    Whether to consider only enabled parameters. Defaults to True.

Returns:

  • Figure

    plt.Figure: Correlation heatmap figure.

Source code in trajectopy\visualization\mpl_plots.py
def plot_correlation_heatmap(estimated_parameters: AlignmentParameters, enabled_only: bool = True) -> Figure:
    """Plots the correlation heatmap of the alignment parameters using matplotlib.

    Args:
        estimated_parameters (AlignmentParameters): Estimated parameters.
        enabled_only (bool, optional): Whether to consider only enabled parameters. Defaults to True.

    Returns:
        plt.Figure: Correlation heatmap figure.
    """
    covariance_matrix = estimated_parameters.get_covariance_matrix(enabled_only=enabled_only)
    std_devs = np.sqrt(np.diag(covariance_matrix))
    correlation_matrix = covariance_matrix / np.outer(std_devs, std_devs)
    np.fill_diagonal(correlation_matrix, np.nan)
    fig, ax = plt.subplots()
    ax.grid(False)
    im, _ = _heatmap(
        correlation_matrix,
        estimated_parameters.params_labels(enabled_only=enabled_only, lower_case=True),
        estimated_parameters.params_labels(enabled_only=enabled_only, lower_case=True),
        ax=ax,
        cmap="coolwarm",
        cbarlabel="Correlation",
        cbar_kw={"format": "%.2f"},
    )
    _annotate_heatmap(im, valfmt="{x:.2f}")
    ax.set_aspect("auto")

    plt.tight_layout()
    return fig

plot_covariance_heatmap

plot_covariance_heatmap(
    estimated_parameters: AlignmentParameters,
    enabled_only: bool = True,
) -> Figure

Plots the covariance heatmap of the alignment parameters using matplotlib.

Parameters:

  • estimated_parameters (AlignmentParameters) –

    Estimated parameters.

  • enabled_only (bool, default: True ) –

    Whether to consider only enabled parameters. Defaults to True.

Returns:

  • Figure

    plt.Figure: Covariance heatmap figure.

Source code in trajectopy\visualization\mpl_plots.py
def plot_covariance_heatmap(estimated_parameters: AlignmentParameters, enabled_only: bool = True) -> Figure:
    """Plots the covariance heatmap of the alignment parameters using matplotlib.

    Args:
        estimated_parameters (AlignmentParameters): Estimated parameters.
        enabled_only (bool, optional): Whether to consider only enabled parameters. Defaults to True.

    Returns:
        plt.Figure: Covariance heatmap figure.
    """
    covariance_matrix = estimated_parameters.get_covariance_matrix(enabled_only=enabled_only)
    fig, ax = plt.subplots()
    ax.grid(False)
    im, _ = _heatmap(
        covariance_matrix,
        estimated_parameters.params_labels(enabled_only=enabled_only, lower_case=True),
        estimated_parameters.params_labels(enabled_only=enabled_only, lower_case=True),
        ax=ax,
        cmap="coolwarm",
        cbarlabel="Covariance",
        cbar_kw={"format": "%.2f"},
    )
    _annotate_heatmap(im, valfmt="{x:.3f}")
    ax.set_aspect("auto")
    plt.tight_layout()
    return fig

plot_ate_3d

plot_ate_3d(
    ate_results: List[ATEResult],
    plot_settings: MPLPlotSettings = MPLPlotSettings(),
) -> Figure

Plots the ATE results in 2D using matplotlib.

Parameters:

Returns:

  • Figure ( Figure ) –

    Figure containing the plot.

Source code in trajectopy\visualization\mpl_plots.py
def plot_ate_3d(ate_results: List[ATEResult], plot_settings: MPLPlotSettings = MPLPlotSettings()) -> Figure:
    """
    Plots the ATE results in 2D using matplotlib.

    Args:
        ate_results (List[ATEResult]): List of ATE results.
        plot_settings (MPLPlotSettings, optional): Plot settings. Defaults to MPLPlotSettings().

    Returns:
        Figure: Figure containing the plot.
    """
    fig = plt.figure()
    ax = fig.add_subplot(111, projection="3d")

    for ate_result in ate_results:
        if len(ate_result.index) == 0:
            logger.warning("Skipping %s as it has no data", ate_result.name)
            continue
        ax.plot(
            (
                ate_result.pos_dev_cross_h * plot_settings.unit_multiplier
                if plot_settings.directed_ate
                else ate_result.pos_dev_x * plot_settings.unit_multiplier
            ),
            (
                ate_result.pos_dev_along * plot_settings.unit_multiplier
                if plot_settings.directed_ate
                else ate_result.pos_dev_y * plot_settings.unit_multiplier
            ),
            (
                ate_result.pos_dev_cross_v * plot_settings.unit_multiplier
                if plot_settings.directed_ate
                else ate_result.pos_dev_z * plot_settings.unit_multiplier
            ),
            ".",
            label=ate_result.name,
        )

    ax.set_xlabel(f"{'Horizontal Cross-Track' if plot_settings.directed_ate else 'X'} {plot_settings.unit_str}")
    ax.set_ylabel(f"{'Along-Track' if plot_settings.directed_ate else 'Y'} {plot_settings.unit_str}")
    ax.set_zlabel(f"{'Vertical Cross-Track' if plot_settings.directed_ate else 'Z'} {plot_settings.unit_str}")

    ax.legend()
    plt.tight_layout()
    return fig

plot_ate_bars

plot_ate_bars(
    ate_results: List[ATEResult],
    plot_settings: MPLPlotSettings = MPLPlotSettings(),
    mode: str = "positions",
) -> Figure

Plots multiple ATE results as bars for different characteristics.

Shows min, max, mean, median, rms, std using matplotlib.

Parameters:

  • ate_results (List[ATEResult]) –

    List of ATE results.

  • plot_settings (MPLPlotSettings, default: MPLPlotSettings() ) –

    Plot settings. Defaults to MPLPlotSettings().

  • mode (str, default: 'positions' ) –

    Mode to plot. Either 'positions' or 'rotations'. Defaults to 'positions'.

Returns:

  • Figure ( Figure ) –

    Bar plot figure.

Source code in trajectopy\visualization\mpl_plots.py
def plot_ate_bars(
    ate_results: List[ATEResult],
    plot_settings: MPLPlotSettings = MPLPlotSettings(),
    mode: str = "positions",
) -> Figure:
    """Plots multiple ATE results as bars for different characteristics.

    Shows min, max, mean, median, rms, std using matplotlib.

    Args:
        ate_results (List[ATEResult]): List of ATE results.
        plot_settings (MPLPlotSettings, optional): Plot settings. Defaults to MPLPlotSettings().
        mode (str, optional): Mode to plot. Either 'positions' or 'rotations'. Defaults to 'positions'.

    Returns:
        Figure: Bar plot figure.
    """
    fig, ax = plt.subplots()

    bar_width = 0.9 / len(ate_results)
    characteristics = ["Min", "Max", "Mean", "Median", "RMS", "STD"]
    unit = plot_settings.unit_str if mode == "positions" else "[°]"
    spacings = np.linspace(
        -bar_width * (len(ate_results) - 1) / 2,
        bar_width * (len(ate_results) - 1) / 2,
        len(ate_results),
    )
    x_positions = np.arange(len(characteristics))
    for deviation, spacing in zip(ate_results, spacings):
        if mode == "rotations" and deviation.abs_dev.rot_dev is None:
            continue

        if mode == "positions":
            data = [
                deviation.pos_dev_min * plot_settings.unit_multiplier,
                deviation.pos_dev_max * plot_settings.unit_multiplier,
                deviation.pos_ate * plot_settings.unit_multiplier,
                deviation.pos_dev_median * plot_settings.unit_multiplier,
                deviation.pos_dev_rms * plot_settings.unit_multiplier,
                deviation.pos_dev_std * plot_settings.unit_multiplier,
            ]
        elif mode == "rotations":
            data = [
                np.rad2deg(deviation.rot_dev_min),
                np.rad2deg(deviation.rot_dev_max),
                np.rad2deg(deviation.rot_ate),
                np.rad2deg(deviation.rot_dev_median),
                np.rad2deg(deviation.rot_dev_rms),
                np.rad2deg(deviation.rot_dev_std),
            ]
        else:
            raise ValueError("Mode must be either 'positions' or 'rotations'")
        ax.bar(x_positions + spacing, data, width=bar_width, label=deviation.name)

    ax.set_xlabel("Characteristic")
    ax.set_ylabel(f"Value {unit}")
    ax.set_xticks(x_positions)
    ax.set_xticklabels(characteristics)
    ax.legend()

    return fig

plot_compact_ate_hist

plot_compact_ate_hist(
    ate_result: ATEResult,
    plot_settings: MPLPlotSettings = MPLPlotSettings(),
) -> Figure

Plots compact ATE histograms for the given ATEResult. The plot contains histograms for the position deviations and, if available, the rotation deviations.

Parameters:

Returns:

  • Figure ( Figure ) –

    Figure containing the plot.

Source code in trajectopy\visualization\mpl_plots.py
def plot_compact_ate_hist(ate_result: ATEResult, plot_settings: MPLPlotSettings = MPLPlotSettings()) -> Figure:
    """
    Plots compact ATE histograms for the given ATEResult.
    The plot contains histograms for the position deviations and, if available, the rotation deviations.

    Args:
        ate_result (ATEResult): ATE result to plot.
        plot_settings (MPLPlotSettings, optional): Plot settings. Defaults to MPLPlotSettings().

    Returns:
        Figure: Figure containing the plot.
    """
    fig = plt.figure()
    pos_ax = plt.subplot(2, 1, 1)
    plot_position_ate_hist(ate_result, plot_settings)
    pos_ax.ticklabel_format(style="sci", axis="y", scilimits=(0, 0))

    if ate_result.abs_dev.rot_dev is not None:
        rot_ax = plt.subplot(2, 1, 2)
        plot_rotation_ate_hist(ate_result, plot_settings)
        rot_ax.ticklabel_format(style="sci", axis="y", scilimits=(0, 0))

    plt.tight_layout()
    return fig

plot_ate

plot_ate(
    ate_results: Union[ATEResult, List[ATEResult]],
    plot_settings: MPLPlotSettings = MPLPlotSettings(),
) -> Figure

Plots ATE for the given ATEResult(s) as a line plot using matplotlib. If available, the plot contains the position and rotation deviations. The x-axis depends on the sorting of the trajectory.

Parameters:

Returns:

  • Figure ( Figure ) –

    Figure containing the plot.

Source code in trajectopy\visualization\mpl_plots.py
def plot_ate(
    ate_results: Union[ATEResult, List[ATEResult]],
    plot_settings: MPLPlotSettings = MPLPlotSettings(),
) -> Figure:
    """
    Plots ATE for the given ATEResult(s) as a line plot using matplotlib.
    If available, the plot contains the position and rotation deviations.
    The x-axis depends on the sorting of the trajectory.

    Args:
        ate_results (Union[ATEResult, List[ATEResult]]): ATE result(s) to plot.
        plot_settings (MPLPlotSettings, optional): Plot settings. Defaults to MPLPlotSettings().

    Returns:
        Figure: Figure containing the plot.
    """
    deviation_list = ate_results if isinstance(ate_results, list) else [ate_results]
    trajectories_list = [dev.trajectory for dev in deviation_list]
    trajectories_sorting = get_sorting(traj.sorting for traj in trajectories_list)
    all_unix = all(traj.is_unix_time for traj in trajectories_list)
    x_label = derive_xlabel_from_sortings(trajectories_sorting, all_unix)

    fig = plt.figure()

    ax_pos = plt.subplot(2, 1, 1)
    ax_pos.set_xlabel(x_label)
    ax_pos.set_ylabel(f"Deviation {plot_settings.unit_str}")
    if all_unix and trajectories_sorting == TrajectoriesSorting.ALL_TIME:
        ax_pos.xaxis.set_major_formatter(DATE_FORMATTER)

    if any(dev.abs_dev.rot_dev for dev in deviation_list):
        ax_rot = plt.subplot(2, 1, 2)
        ax_rot.set_xlabel(x_label)
        ax_rot.set_ylabel("Deviation [°]")
        if all_unix and trajectories_sorting == TrajectoriesSorting.ALL_TIME:
            ax_rot.xaxis.set_major_formatter(DATE_FORMATTER)
    else:
        ax_rot = None

    for dev in deviation_list:
        if len(dev.index) == 0:
            logger.warning("Skipping %s as it has no data", dev.name)
            continue

        index = (
            dev.trajectory.datetimes
            if all_unix and trajectories_sorting == TrajectoriesSorting.ALL_TIME
            else dev.index
        )

        ax_pos.plot(index, dev.pos_dev_comb * plot_settings.unit_multiplier)
        if ax_rot is not None:
            ax_rot.plot(index, np.rad2deg(dev.rot_dev_comb))

    fig.legend([dev.name for dev in deviation_list], ncol=3, loc="upper center")
    plt.tight_layout()
    return fig

plot_ate_dof

plot_ate_dof(
    ate_result: ATEResult,
    plot_settings: MPLPlotSettings = MPLPlotSettings(),
) -> Figure

Plots ATE DOF (Degrees of Freedom) for the given ATEResult as a line plot using matplotlib.

The DOF plot shows the deviations in the x, y, and z directions for position and rotation.

Parameters:

Returns:

  • Figure ( Figure ) –

    Figure containing the plot.

Source code in trajectopy\visualization\mpl_plots.py
def plot_ate_dof(
    ate_result: ATEResult,
    plot_settings: MPLPlotSettings = MPLPlotSettings(),
) -> Figure:
    """Plots ATE DOF (Degrees of Freedom) for the given ATEResult as a line plot using matplotlib.

    The DOF plot shows the deviations in the x, y, and z directions for position and rotation.

    Args:
        ate_result (ATEResult): ATE result to plot.
        plot_settings (MPLPlotSettings, optional): Plot settings. Defaults to MPLPlotSettings().

    Returns:
        Figure: Figure containing the plot.
    """
    trajectory = ate_result.trajectory
    x_label = derive_xlabel_from_sortings(
        TrajectoriesSorting.ALL_SPATIAL if trajectory.sorting == Sorting.PATH_LENGTH else TrajectoriesSorting.ALL_TIME,
        trajectory.is_unix_time,
    )

    is_unix_time = trajectory.is_unix_time and trajectory.sorting == Sorting.TIME

    fig = plt.figure()

    ax_pos = plt.subplot(2, 1, 1)
    ax_pos.set_xlabel(x_label)
    ax_pos.set_ylabel(f"Deviation {plot_settings.unit_str}")
    if is_unix_time:
        ax_pos.xaxis.set_major_formatter(DATE_FORMATTER)

    if ate_result.has_orientation:
        ax_rot = plt.subplot(2, 1, 2)
        ax_rot.set_xlabel(x_label)
        ax_rot.set_ylabel("Deviation [°]")
        if is_unix_time:
            ax_rot.xaxis.set_major_formatter(DATE_FORMATTER)
    else:
        ax_rot = None

    if len(ate_result.index) == 0:
        logger.warning("Skipping %s as it has no data", ate_result.name)
        return fig

    pos_dev_x = ate_result.pos_dev_along if plot_settings.directed_ate else ate_result.pos_dev_x
    pos_dev_y = ate_result.pos_dev_cross_h if plot_settings.directed_ate else ate_result.pos_dev_y
    pos_dev_z = ate_result.pos_dev_cross_v if plot_settings.directed_ate else ate_result.pos_dev_z

    index = ate_result.trajectory.datetimes if is_unix_time else ate_result.index

    ax_pos.plot(
        index,
        pos_dev_x * plot_settings.unit_multiplier,
        label="Along-Track" if plot_settings.directed_ate else "X",
    )
    ax_pos.plot(
        index,
        pos_dev_y * plot_settings.unit_multiplier,
        label="Horizontal Cross-Track" if plot_settings.directed_ate else "Y",
    )
    ax_pos.plot(
        index,
        pos_dev_z * plot_settings.unit_multiplier,
        label="Vertical Cross-Track" if plot_settings.directed_ate else "Z",
    )
    ax_pos.legend()

    if ax_rot is not None:
        ax_rot.plot(index, np.rad2deg(ate_result.rot_dev_x), label="Roll")
        ax_rot.plot(index, np.rad2deg(ate_result.rot_dev_y), label="Pitch")
        ax_rot.plot(index, np.rad2deg(ate_result.rot_dev_z), label="Yaw")
        ax_rot.legend()

    ax_pos.set_title(f"{ate_result.name}")
    plt.tight_layout()
    return fig

plot_ate_edf

plot_ate_edf(
    ate_results: Union[ATEResult, List[ATEResult]],
    plot_settings: MPLPlotSettings = MPLPlotSettings(),
) -> Figure

Plots ATE EDF for the given ATEResult(s) as a line plot using matplotlib. The EDF (Empirical Distribution Function) shows the cumulative probability of the deviations. Using this plot, one can easily see how many percent of the deviations are below a certain value.

Parameters:

Returns:

  • Figure ( Figure ) –

    Figure containing the plot.

Source code in trajectopy\visualization\mpl_plots.py
def plot_ate_edf(
    ate_results: Union[ATEResult, List[ATEResult]],
    plot_settings: MPLPlotSettings = MPLPlotSettings(),
) -> Figure:
    """
    Plots ATE EDF for the given ATEResult(s) as a line plot using matplotlib.
    The EDF (Empirical Distribution Function) shows the cumulative probability of the deviations.
    Using this plot, one can easily see how many percent of the deviations are below a certain value.

    Args:
        ate_results (Union[ATEResult, List[ATEResult]]): ATE result to plot.
        plot_settings (MPLPlotSettings, optional): Plot settings. Defaults to MPLPlotSettings().

    Returns:
        Figure: Figure containing the plot.
    """
    deviation_list = ate_results if isinstance(ate_results, list) else [ate_results]

    fig = plt.figure()

    plot_position_ate_edf(deviation_list, plot_settings)
    plot_rotation_ate_edf(deviation_list)

    fig.legend([dev.name for dev in deviation_list], ncol=3, loc="upper center")
    plt.tight_layout()
    return fig

plot_rpe

plot_rpe(
    rpe_results: List[RPEResult],
) -> Tuple[Figure, Figure]

Plots the RPE results as a line plot with violin plots for the position and rotation deviations.

Depending on the pair distance unit, the unit of the position deviations is either in meters/meters (%) or meters/seconds. The unit of the rotation deviations is respectively in degrees/m or degrees/second.

Parameters:

  • rpe_results (list[RelativeTrajectoryDeviations]) –

    list of RelativeTrajectoryDeviations

Returns:

  • Tuple[Figure, Figure]

    Tuple[Figure, Figure]: metric and time RPE plots

Source code in trajectopy\visualization\mpl_plots.py
def plot_rpe(rpe_results: List[RPEResult]) -> Tuple[Figure, Figure]:
    """Plots the RPE results as a line plot with violin plots for the position and rotation deviations.

    Depending on the pair distance unit, the unit of the position deviations
    is either in meters/meters (%) or meters/seconds. The unit of the rotation
    deviations is respectively in degrees/m or degrees/second.

    Args:
        rpe_results (list[RelativeTrajectoryDeviations]): list of RelativeTrajectoryDeviations

    Returns:
        Tuple[Figure, Figure]: metric and time RPE plots

    """
    if not isinstance(rpe_results, list):
        rpe_results = [rpe_results]

    fig_metric, (fig_pos_metric, fig_rot_metric) = plt.subplots(2, 1)
    fig_time, (fig_pos_time, fig_rot_time) = plt.subplots(2, 1)

    fig_pos_metric.set_ylabel("Position RPE [%]")
    fig_pos_time.set_ylabel("Position RPE [m/s]")

    fig_rot_metric.set_ylabel("Rotation RPE [deg / 100m]")
    fig_rot_time.set_ylabel("Rotation RPE [deg/s]")

    fig_pos_metric.set_xlabel("pair distance [m]")
    fig_pos_time.set_xlabel("pair distance [s]")
    fig_rot_metric.set_xlabel("pair distance [m]")
    fig_rot_time.set_xlabel("pair distance [s]")

    figure_dict: Dict[str, Dict[PairDistanceUnit, Axes]] = {
        "pos": {
            PairDistanceUnit.METER: fig_pos_metric,
            PairDistanceUnit.SECOND: fig_pos_time,
        },
        "rot": {
            PairDistanceUnit.METER: fig_rot_metric,
            PairDistanceUnit.SECOND: fig_rot_time,
        },
    }

    plot_rpe_pos(figure_dict["pos"], rpe_results)
    plot_rpe_rot(figure_dict["rot"], rpe_results)

    add_rpy_legend(figure_dict)

    ret_sum = 1 if any(dev.rpe_dev.pair_distance_unit == PairDistanceUnit.METER for dev in rpe_results) else 0
    if any(dev.rpe_dev.pair_distance_unit == PairDistanceUnit.SECOND for dev in rpe_results):
        ret_sum += 2

    plt.close({1: fig_time, 2: fig_metric}.get(ret_sum))
    plt.tight_layout()
    return {
        0: (None, None),
        1: (fig_metric, None),
        2: (None, fig_time),
        3: (fig_metric, fig_time),
    }[ret_sum]

scatter_ate

scatter_ate(
    ate_result: ATEResult,
    plot_settings: MPLPlotSettings = MPLPlotSettings(),
) -> Tuple[Figure, Figure]

Plots the ATE results as a scatter plot with color-coded deviations.

Parameters:

Source code in trajectopy\visualization\mpl_plots.py
def scatter_ate(ate_result: ATEResult, plot_settings: MPLPlotSettings = MPLPlotSettings()) -> Tuple[Figure, Figure]:
    """
    Plots the ATE results as a scatter plot with color-coded deviations.

    Args:
        ate_result (ATEResult): ATE result to plot.
        plot_settings (MPLPlotSettings, optional): Plot settings. Defaults to MPLPlotSettings().
    """
    pos_fig = plt.figure()
    _colored_scatter_plot(
        xyz=ate_result.trajectory.xyz,
        c_list=ate_result.pos_dev_comb * plot_settings.unit_multiplier,
        c_label=f"Deviation {plot_settings.unit_str}",
        plot_settings=plot_settings,
    )

    if not ate_result.has_orientation:
        return pos_fig, None

    rot_fig = plt.figure()
    _colored_scatter_plot(
        xyz=ate_result.trajectory.xyz,
        c_list=ate_result.rot_dev_comb * 180 / np.pi,
        c_label="Deviation [°]",
        plot_settings=plot_settings,
    )
    return pos_fig, rot_fig

plot_positions

plot_positions(
    trajectories: List[Trajectory], scatter_3d: bool = False
) -> Figure

Plots xy(z) coordinates of trajectories as 2d or 3d plot

Source code in trajectopy\visualization\mpl_plots.py
def plot_positions(trajectories: List[Trajectory], scatter_3d: bool = False) -> Figure:
    """Plots xy(z) coordinates of trajectories as 2d or 3d plot"""
    x_label, y_label, z_label = get_axis_label(trajectories=trajectories)

    if scatter_3d:
        fig_pos = plt.figure()
        ax_pos = fig_pos.add_subplot(111, projection="3d")
        ax_pos.set_zlabel(z_label)  # type: ignore
    else:
        fig_pos, ax_pos = plt.subplots()
        ax_pos.axis("equal")

    ax_pos.set_xlabel(x_label)
    ax_pos.set_ylabel(y_label)

    legend_names = []
    for traj in trajectories:
        xyz = traj.xyz
        legend_names.append(traj.name)

        # pos fig
        if scatter_3d:
            ax_pos.plot(xyz[:, 0], xyz[:, 1], xyz[:, 2])
        else:
            ax_pos.plot(xyz[:, 0], xyz[:, 1])

    if scatter_3d:
        set_aspect_equal_3d(ax_pos)

    fig_pos.legend(legend_names, ncol=4, loc="upper center")
    return fig_pos

plot_xyz

plot_xyz(trajectories: List[Trajectory]) -> Figure

Plots xyz coordinates of trajectories as subplots

Source code in trajectopy\visualization\mpl_plots.py
def plot_xyz(trajectories: List[Trajectory]) -> Figure:
    """Plots xyz coordinates of trajectories as subplots"""
    fig_xyz, axs_xyz = plt.subplots(3, 1, sharex=True)

    for ax, label in zip(axs_xyz, get_axis_label(trajectories=trajectories)):
        ax.set_ylabel(label)

    trajectories_sorting = get_sorting([traj.sorting for traj in trajectories])
    all_unix = all(traj.is_unix_time for traj in trajectories)
    x_label = derive_xlabel_from_sortings(trajectories_sorting, all_unix)

    axs_xyz[-1].set_xlabel(x_label)

    if all_unix and trajectories_sorting == TrajectoriesSorting.ALL_TIME:
        axs_xyz[-1].xaxis.set_major_formatter(DATE_FORMATTER)

    legend_names = []
    for traj in trajectories:
        legend_names.append(traj.name)
        xyz = traj.xyz

        # xyz fig
        for j, ax in enumerate(axs_xyz):
            ax.plot(
                (traj.datetimes if all_unix and trajectories_sorting == TrajectoriesSorting.ALL_TIME else traj.index),
                xyz[:, j],
            )

    fig_xyz.legend(legend_names, ncol=4, loc="upper center")
    return fig_xyz

plot_rpy

plot_rpy(
    trajectories: List[Trajectory],
) -> Union[Figure, None]

Plots rpy coordinates of trajectories as subplots

Source code in trajectopy\visualization\mpl_plots.py
def plot_rpy(trajectories: List[Trajectory]) -> Union[Figure, None]:
    """Plots rpy coordinates of trajectories as subplots"""
    fig_rpy, axs_rpy = plt.subplots(3, 1, sharex=True)
    trajectories_sorting = get_sorting([traj.sorting for traj in trajectories])
    all_unix = all(traj.is_unix_time for traj in trajectories)
    x_label = derive_xlabel_from_sortings(trajectories_sorting, all_unix)

    axs_rpy[-1].set_xlabel(x_label)

    if all_unix and trajectories_sorting == TrajectoriesSorting.ALL_TIME:
        axs_rpy[-1].xaxis.set_major_formatter(DATE_FORMATTER)

    not_empty = False
    legend_names = []
    for traj in trajectories:
        # rpy fig
        if traj.rotations and len(traj.rotations) > 0:
            legend_names.append(traj.name)
            rpy = traj.rpy
            ylabels = ["roll [°]", "pitch [°]", "yaw [°]"]
            for j, (ax, yl) in enumerate(zip(axs_rpy, ylabels)):
                ax.plot(
                    (
                        traj.datetimes
                        if all_unix and trajectories_sorting == TrajectoriesSorting.ALL_TIME
                        else traj.index
                    ),
                    np.rad2deg(rpy[:, j]),
                )
                ax.set_ylabel(yl)
            not_empty = True

    fig_rpy.legend(legend_names, ncol=4, loc="upper center")

    return fig_rpy if not_empty else None