spacr.qt.widgets.timelapse_movie¶
Watching a track break, rather than reading that one did.
TrackStats can tell you that a field produced 41 tracks with a median
length of 6 frames in a 30-frame series. It cannot tell you why, and why
is the only thing that changes what you do next: two cells that touch for
three frames and come apart with their identities swapped needs a different
setting from one cell that leaves the field and comes back.
So this shows the frames. One field plays as a movie; clicking it opens a filmstrip above, which is the same frames laid out at once and scrollable, because a break is easiest to find by scrubbing and easiest to understand by seeing the frames either side of it together.
Everything reuses the rendering already in
spacr.qt.widgets.timelapse_preview – render_frame colours mask
outlines by track id and draws the trailing polyline, and track_colour
is deterministic. That is what makes the colours mean something: an object
that keeps its track id keeps its colour in every frame and in every
thumbnail, so an identity swap reads as an object that changes colour
partway through the strip.
Classes¶
One field's frames, side by side and scrollable. |
|
One field of view: a movie, and a filmstrip that opens above it. |
|
Several fields stacked, with one set of controls over all of them. |
Module Contents¶
- class spacr.qt.widgets.timelapse_movie.FilmStrip(parent: PySide6.QtWidgets.QWidget | None = None)[source]¶
Bases:
PySide6.QtWidgets.QScrollAreaOne field’s frames, side by side and scrollable.
Horizontal only. A vertical scrollbar here would fight the panel’s own, and there is never more than one row.
- Parameters:
parent – parent widget.
Create the horizontal thumbnail strip.
The viewport paints nothing: the strip is scaffolding that positions thumbnails, and an auto-filled one is one more opaque rectangle over the page.
- Parameters:
parent – parent widget, or
None.
- class spacr.qt.widgets.timelapse_movie.FovMovie(title: str = '', parent: PySide6.QtWidgets.QWidget | None = None)[source]¶
Bases:
PySide6.QtWidgets.QWidgetOne field of view: a movie, and a filmstrip that opens above it.
Renders lazily and caches by
(frame, objects, tracks). Flipping a toggle on a 30-frame field would otherwise re-render every frame twice – once for the movie and once for the strip – on the GUI thread.- Parameters:
title – the caption above the movie. Empty draws none.
parent – parent widget.
Create an empty movie view for one field.
- Parameters:
title – caption shown above the frames.
parent – parent widget, or
None.
- frame_count() int[source]¶
How many frames this field has.
- Returns:
the frame count, 0 when nothing is loaded.
- play() None[source]¶
Start playing, unless there is nothing to animate.
A SINGLE FRAME IS NOT A MOVIE: starting a timer for it would spin the event loop to redraw the same picture.
- set_fps(fps: float) None[source]¶
Set the playback rate.
Floored at half a frame per second, because the interval is derived by division and a rate of zero is an infinite one.
- Parameters:
fps – the wanted frames per second.
- set_overlays(*, objects: bool, tracks: bool) None[source]¶
Toggle the mask outlines and the track tails independently.
- Parameters:
objects – whether mask outlines are drawn.
tracks – whether track tails are drawn.
- set_sequence(images, labels=None, tracks=None, channel: int = 0) None[source]¶
Bind one field’s frames, its per-frame labels and its tracks.
labelsis expected to be ALREADY relabelled by track id (seerelabel_by_track). That is what makes a colour mean a track rather than a per-frame segmentation index, and it is the caller’s job because the relabelling is what the tracker produced.- Parameters:
images – the field’s frames as an array-like stack, first axis time; each frame may carry channels, of which
channelis shown. None clears the movie.
- set_strip_open(open_: bool) None[source]¶
Show or hide the filmstrip under the movie.
- Parameters:
open – True to show it.
- show_frame(index: int) None[source]¶
Put
indexon the canvas and keep every control agreeing.- Parameters:
index – zero-based frame index; clamped to the frames loaded.
- strip_is_open() bool[source]¶
Expanded or not – a state, not a question about the screen.
isHidden()and notisVisible(): a widget inside a parent that has not been shown yet reportsisVisible() == Falsehowever it was configured, so the expanded state would read as collapsed for every movie built before its screen is on screen – and the click that expanded it would appear to do nothing.
- class spacr.qt.widgets.timelapse_movie.TimelapseMoviePanel(parent: PySide6.QtWidgets.QWidget | None = None)[source]¶
Bases:
PySide6.QtWidgets.QWidgetSeveral fields stacked, with one set of controls over all of them.
Stacked rather than tabbed on purpose: comparing two fields is the point of showing more than one, and a tab hides the thing you are comparing against.
- Parameters:
parent – parent widget.
Build the panel that shows several fields as synchronised movies.
- Parameters:
parent – parent widget, or
None.
- max_fields() int[source]¶
How many fields this panel will stack at once.
A CAP, because each field is its own movie with its own timer, and a plate with hundreds would start hundreds of them.
- Returns:
the field cap.
- movies() List[FovMovie][source]¶
The field movies currently stacked.
A LIST COPY, so a caller cannot restack the panel by mutating it.
- Returns:
the movies, in display order.
- set_fields(fields: Sequence[dict]) None[source]¶
Show one movie per entry, up to the user’s ceiling.
- Parameters:
fields – dicts of
{"title", "images", "labels", "tracks", "channel"}. Extra entries are dropped rather than queued – the ceiling is about memory, so holding the surplus would defeat it.
- set_fps(fps: float) None[source]¶
Set the playback rate on every stacked field at once.
- Parameters:
fps – the wanted frames per second.
- set_max_fields(count: int) None[source]¶
Cap how many fields are held at once.
Applied by dropping the surplus immediately rather than at the next preview: a user lowering this has just been told the machine is short of memory, and the setting has to give it back now.
- Parameters:
count – how many fields may be held at once; clamped to 1 through
MAX_FIELDS_CEILING(8), and fields beyond it are dropped at once.