Skip to content

Commit 832937f

Browse files
committed
Merge branch 'main' into 322-rendering-of-contour-labels-in-3d
2 parents afb031f + 743c07e commit 832937f

File tree

9 files changed

+291
-12
lines changed

9 files changed

+291
-12
lines changed

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ repos:
1010
exclude: ^\.napari-hub/.*
1111
- id: check-yaml # checks for correct yaml syntax for github actions ex.
1212
- repo: https://github.com/astral-sh/ruff-pre-commit
13-
rev: v0.14.11
13+
rev: v0.14.13
1414
hooks:
1515
- id: ruff
1616
args: [--fix, -v]

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
[![tests](https://github.com/funkelab/motile_tracker/workflows/tests/badge.svg)](https://github.com/funkelab/motile_tracker/actions)
44
[![codecov](https://codecov.io/gh/funkelab/motile_tracker/branch/main/graph/badge.svg)](https://codecov.io/gh/funkelab/motile_tracker)
55

6+
7+
An application for interactive tracking with [motile](https://github.com/funkelab/motile).
68
The full documentation of the plugin can be found [here](https://funkelab.github.io/motile_tracker/).
79

8-
An application for interactive tracking with [motile](https://github.com/funkelab/motile)
910
Motile is a library that makes it easy to solve tracking problems using optimization
1011
by framing the task as an Integer Linear Program (ILP).
1112
See the motile [documentation](https://funkelab.github.io/motile)
@@ -60,6 +61,8 @@ track objects in napari Labels or Points layers. For details, please read the
6061

6162
![motile_tracker_quick_demo](https://github.com/user-attachments/assets/07a4a954-3d2d-4d67-8f75-aec11ee14697)
6263

64+
If you are new to using motile-tracker, you can follow this [tutorial](./assets/motile-tracker_tutorial.pdf) to learn the basics.
65+
6366
## Package the application into an executable and create the installer
6467

6568
Tagging any branch will automatically trigger the deploy.yml workflow,

assets/motile-tracker_tutorial.md

Lines changed: 264 additions & 0 deletions
Large diffs are not rendered by default.

assets/motile-tracker_tutorial.pdf

1.99 MB
Binary file not shown.

src/motile_tracker/data_views/views/layers/tracks_layer_group.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,19 @@ def add_napari_layers(self) -> None:
8282

8383
if self.tracks_layer is not None:
8484
self.viewer.add_layer(self.tracks_layer)
85-
if self.seg_layer is not None:
86-
self.viewer.add_layer(self.seg_layer)
8785
if self.points_layer is not None:
8886
self.viewer.add_layer(self.points_layer)
87+
if self.seg_layer is not None:
88+
self.viewer.add_layer(self.seg_layer)
89+
# silly fix for loading zarr on Windows: load labels only at the end and then
90+
# swap layer order here to avoid error "access violation reading..."
91+
self.viewer.layers.move(-1, -2)
92+
93+
# This is just to ensure that the layer selection makes sense, because after
94+
# moving a layer, the layer tools are not updated correctly.
95+
self.viewer.layers.selection.clear()
96+
self.viewer.layers.selection.add(self.viewer.layers[-1])
97+
8998
# self.link_experimental_clipping_planes()
9099

91100
def link_experimental_clipping_planes(self):

src/motile_tracker/import_export/menus/import_dialog.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,6 @@ def _update_field_map_and_scale(self, checked: bool | None = None) -> None:
120120
self.seg = (
121121
self.segmentation_widget.include_seg() if checked is None else not checked
122122
)
123-
self.scale_widget.setVisible(self.seg)
124123

125124
if self.import_type == "csv":
126125
self.incl_z = self.dimension_widget.incl_z
@@ -161,6 +160,8 @@ def _update_field_map_and_scale(self, checked: bool | None = None) -> None:
161160
self.prop_map_widget.mapping_labels["seg_id"].setVisible(self.seg)
162161

163162
self._update_finish_button()
163+
self.scale_widget.setVisible(self.seg)
164+
164165
self._resize_dialog()
165166

166167
def infer_dims_from_segmentation(self) -> None:
@@ -198,10 +199,9 @@ def infer_dims_from_segmentation(self) -> None:
198199
def _update_segmentation_widget(self) -> None:
199200
"""Refresh the geff segmentation widget based on the geff root group."""
200201

202+
self.segmentation_widget.setVisible(False)
201203
if self.import_widget.root is not None:
202204
self.segmentation_widget.update_root(self.import_widget.root)
203-
else:
204-
self.segmentation_widget.setVisible(False)
205205
self._update_finish_button()
206206
self._resize_dialog()
207207

src/motile_tracker/import_export/menus/prop_map_widget.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ def extract_geff_property_fields(
163163
self.seg = seg
164164
self.incl_z = incl_z
165165

166-
self.setVisible(True)
166+
self.setVisible(False)
167167
self.node_attrs = list(root["nodes"]["props"].group_keys())
168168
self.metadata = dict(root.attrs.get("geff", {}))
169169

@@ -192,6 +192,7 @@ def extract_geff_property_fields(
192192
self.standard_fields.insert(1, "z")
193193

194194
self.update_mapping(seg)
195+
self.setVisible(True)
195196

196197
def _update_props_left(self) -> None:
197198
"""Update the list of columns that have not been mapped yet"""
@@ -412,6 +413,7 @@ def update_mapping(self, seg: bool = False) -> None:
412413
seg (bool = False): whether a segmentation is associated with this data
413414
"""
414415

416+
self.setVisible(False)
415417
self.mapping_labels = {}
416418
self.mapping_widgets = {}
417419
clear_layout(self.mapping_layout) # clear layout first
@@ -458,6 +460,8 @@ def update_mapping(self, seg: bool = False) -> None:
458460
self.optional_mapping_layout.addWidget(header_assign, 0, 1)
459461
self.optional_mapping_layout.addWidget(header_recompute, 0, 2)
460462
self._update_props_left()
463+
464+
self.setVisible(True)
461465
self.setMinimumHeight(350)
462466

463467
def get_name_map(self) -> dict[str, str]:

src/motile_tracker/import_export/menus/scale_widget.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,6 @@ def update(self, metadata: dict | None = None, incl_z: bool = False) -> None:
6161
ndim = 4 if incl_z else 3
6262
self.scale = list([1.0] * ndim)
6363

64-
self.setVisible(True)
6564
clear_layout(self.scale_layout)
6665
self.scale_form_layout = QFormLayout()
6766

@@ -78,6 +77,7 @@ def update(self, metadata: dict | None = None, incl_z: bool = False) -> None:
7877
self.scale_form_layout.addRow(QLabel("x"), self.x_spin_box)
7978

8079
self.scale_layout.addLayout(self.scale_form_layout)
80+
self.setVisible(True)
8181

8282
def _scale_spin_box(self, value: float) -> QDoubleSpinBox:
8383
"""Return a QDoubleSpinBox for scaling values"""

src/motile_tracker/import_export/menus/segmentation_widgets.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -331,11 +331,11 @@ def update_root(self, root: zarr.Group | None) -> None:
331331
Args:
332332
root (zarr.Group | None): The root group of the geff zarr store.
333333
"""
334+
self.setVisible(False)
334335
self.root = root
335336
clear_layout(self.related_objects_layout)
336337
self.related_object_radio_buttons = {}
337338
if self.root is not None:
338-
self.setVisible(True)
339339
metadata = dict(self.root.attrs)
340340
related_objects = metadata.get("geff", {}).get("related_objects", None)
341341
if related_objects:
@@ -346,8 +346,7 @@ def update_root(self, root: zarr.Group | None) -> None:
346346
self.button_group.addButton(radio)
347347
self.related_object_radio_buttons[obj.get("path", None)] = radio
348348
self.related_objects_layout.addWidget(radio)
349-
else:
350-
self.setVisible(False)
349+
self.setVisible(True)
351350

352351
def _toggle_segmentation(self, checked: bool) -> None:
353352
"""Toggle visibility of the segmentation widget based on the radio button

0 commit comments

Comments
 (0)