Skip to content

Showing & Exporting

figure

Figures, the plot window and export.

A :class:Figure is a titled page of plots. It only stores how to draw itself, so lists of figures are cheap to create; the plots are rendered when a page is first shown or exported. A figure may offer several variants (for example the quantity used to color a trajectory), which the plot window offers in a drop-down and :func:export_figures writes to separate files.

The same :class:PlotWindow is used by the GUI and by :func:show in scripts.

Figure

Figure(
    title: str,
    render: RenderFunction | None = None,
    variants: dict[str, RenderFunction] | None = None,
)

A titled page of plots.

Parameters:

  • title (str) –

    Title of the page (tab title in the plot window and file name stem on export).

  • render (RenderFunction | None, default: None ) –

    Draws the plots into the given layout.

  • variants (dict[str, RenderFunction] | None, default: None ) –

    Alternatively, several named render functions; the user picks one in a drop-down.

Source code in trajectopy\visualization\figure.py
def __init__(
    self,
    title: str,
    render: RenderFunction | None = None,
    variants: dict[str, RenderFunction] | None = None,
) -> None:
    if (render is None) == (variants is None):
        raise ValueError("Provide either render or variants.")
    self.title = title
    self.variants: dict[str, RenderFunction] = variants if variants is not None else {"": render}  # type: ignore[dict-item]
    if not self.variants:
        raise ValueError("A figure needs at least one variant.")

create_widget

create_widget(use_opengl: bool = False) -> QWidget

Creates an interactive widget showing the figure (with a variant selector if needed).

Parameters:

  • use_opengl (bool, default: False ) –

    Draw with OpenGL, if available. Much faster for large data sets.

Source code in trajectopy\visualization\figure.py
def create_widget(self, use_opengl: bool = False) -> QtWidgets.QWidget:
    """Creates an interactive widget showing the figure (with a variant selector if needed).

    Args:
        use_opengl: Draw with OpenGL, if available. Much faster for large data sets.
    """
    return _FigureWidget(self, use_opengl=use_opengl)

export

export(
    path: str, variant: str | None = None, width: int = 1600
) -> None

Exports the figure (or one of its variants) to a PNG, JPG or SVG file.

Parameters:

  • path (str) –

    Output file; the format is derived from the extension.

  • variant (str | None, default: None ) –

    Name of the variant to export. Defaults to the first one.

  • width (int, default: 1600 ) –

    Width in pixels of raster images.

Source code in trajectopy\visualization\figure.py
def export(self, path: str, variant: str | None = None, width: int = 1600) -> None:
    """Exports the figure (or one of its variants) to a PNG, JPG or SVG file.

    Args:
        path: Output file; the format is derived from the extension.
        variant: Name of the variant to export. Defaults to the first one.
        width: Width in pixels of raster images.
    """
    app = ensure_app()
    render = self.variants[variant if variant is not None else next(iter(self.variants))]
    graphics = pg.GraphicsLayoutWidget()
    render(graphics.ci)
    _settle_layout(app, graphics)
    _render_to_file(graphics, path, width)

PlotWindow

PlotWindow(
    figures: Sequence[Figure],
    title: str = "Trajectopy",
    export_format: str = "png",
    export_width: int = 1600,
    use_opengl: bool = True,
    parent: QWidget | None = None,
)

Bases: QMainWindow

Window showing figures as tabs. Tabs are rendered when they are first opened.

Source code in trajectopy\visualization\figure.py
def __init__(
    self,
    figures: Sequence[Figure],
    title: str = "Trajectopy",
    export_format: str = "png",
    export_width: int = 1600,
    use_opengl: bool = True,
    parent: QtWidgets.QWidget | None = None,
) -> None:
    super().__init__(parent)
    self.setWindowTitle(title)
    self.figures = list(figures)
    self.export_format = export_format
    self.export_width = export_width
    self.use_opengl = use_opengl

    self.tabs = QtWidgets.QTabWidget()
    self.tabs.setDocumentMode(True)
    for figure in self.figures:
        placeholder = QtWidgets.QWidget()
        QtWidgets.QVBoxLayout(placeholder).setContentsMargins(0, 0, 0, 0)
        self.tabs.addTab(placeholder, figure.title)
    self.tabs.currentChanged.connect(self._ensure_rendered)
    self.setCentralWidget(self.tabs)

    toolbar = self.addToolBar("Export")
    toolbar.setMovable(False)
    toolbar.addAction("Export Plot…", self.export_current)
    toolbar.addAction("Export All…", self.export_all)

    if (screen := QtGui.QGuiApplication.primaryScreen()) is not None:
        available = screen.availableGeometry()
        self.resize(int(available.width() * 0.7), int(available.height() * 0.75))

    self._ensure_rendered(0)

ensure_app

ensure_app() -> QApplication

Returns the running Qt application, creating one if necessary (required before creating plots).

Source code in trajectopy\visualization\figure.py
def ensure_app() -> QtWidgets.QApplication:
    """Returns the running Qt application, creating one if necessary (required before creating plots)."""
    app = QtWidgets.QApplication.instance()
    if app is None:
        app = pg.mkQApp("Trajectopy")
    return app  # type: ignore[return-value]

opengl_available

opengl_available() -> bool

Whether an OpenGL context can be created (not the case e.g. in some remote sessions and VMs).

Source code in trajectopy\visualization\figure.py
def opengl_available() -> bool:
    """Whether an OpenGL context can be created (not the case e.g. in some remote sessions and VMs)."""
    global _opengl_available
    if _opengl_available is None:
        context = QtGui.QOpenGLContext()
        _opengl_available = context.create() and context.isValid()
        if not _opengl_available:
            logger.info("OpenGL is not available; plots are drawn in software.")
    return _opengl_available

export_figures

export_figures(
    figures: Sequence[Figure],
    directory: str,
    export_format: str = "png",
    width: int = 1600,
) -> list[str]

Exports all figures (and all their variants) to image files in directory.

Returns:

  • list[str] –

    list[str]: Paths of the written files.

Source code in trajectopy\visualization\figure.py
def export_figures(
    figures: Sequence[Figure], directory: str, export_format: str = "png", width: int = 1600
) -> list[str]:
    """Exports all figures (and all their variants) to image files in ``directory``.

    Returns:
        list[str]: Paths of the written files.
    """
    os.makedirs(directory, exist_ok=True)
    paths = []
    for index, figure in enumerate(figures, start=1):
        for variant in figure.variants:
            stem = _safe_filename(f"{index:02d}_{figure.title}" + (f"_{variant}" if variant else ""))
            path = os.path.join(directory, f"{stem}.{export_format}")
            figure.export(path, variant=variant, width=width)
            paths.append(path)
    return paths

show

show(
    figures: Figure | Sequence[Figure],
    title: str = "Trajectopy",
    block: bool = True,
    use_opengl: bool = True,
) -> PlotWindow

Shows figures in a plot window.

Parameters:

  • figures (Figure | Sequence[Figure]) –

    Figure(s) to show, one tab each.

  • title (str, default: 'Trajectopy' ) –

    Window title.

  • block (bool, default: True ) –

    Run the Qt event loop until the window is closed (for scripts). Use False if an event loop is already running, e.g. inside a Qt application.

  • use_opengl (bool, default: True ) –

    Draw with OpenGL, if available. Much faster for large data sets.

Returns:

Source code in trajectopy\visualization\figure.py
def show(
    figures: Figure | Sequence[Figure], title: str = "Trajectopy", block: bool = True, use_opengl: bool = True
) -> PlotWindow:
    """Shows figures in a plot window.

    Args:
        figures: Figure(s) to show, one tab each.
        title: Window title.
        block: Run the Qt event loop until the window is closed (for scripts). Use ``False`` if an
            event loop is already running, e.g. inside a Qt application.
        use_opengl: Draw with OpenGL, if available. Much faster for large data sets.

    Returns:
        PlotWindow: The window.
    """
    app = ensure_app()
    window = PlotWindow([figures] if isinstance(figures, Figure) else figures, title=title, use_opengl=use_opengl)
    window.show()
    if block:
        app.exec()
    return window

set_theme

set_theme(dark: bool) -> None

Selects the theme for plots created from now on.

Source code in trajectopy\visualization\style.py
def set_theme(dark: bool) -> None:
    """Selects the theme for plots created from now on."""
    global _current_theme
    _current_theme = DARK if dark else LIGHT
    # Antialiasing is enabled per curve (see ``antialias``), because Qt draws antialiased wide lines very slowly.
    pg.setConfigOptions(background=_current_theme.background, foreground=_current_theme.foreground, antialias=False)