Skip to content

Commit

Permalink
Merge pull request #77 from MPI-Dortmund/add_selection_toggle
Browse files Browse the repository at this point in the history
Add selection toggle buttons
  • Loading branch information
thorstenwagner authored Oct 30, 2024
2 parents 9e0df6b + 62f6944 commit ce1aa27
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 27 deletions.
14 changes: 7 additions & 7 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,34 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/asottile/setup-cfg-fmt
rev: v1.20.1
rev: v2.7.0
hooks:
- id: setup-cfg-fmt
- repo: https://github.com/PyCQA/isort
rev: 5.10.1
rev: 5.13.2
hooks:
- id: isort
- repo: https://github.com/asottile/pyupgrade
rev: v2.34.0
rev: v3.19.0
hooks:
- id: pyupgrade
args: [--py38-plus, --keep-runtime-typing]
- repo: https://github.com/myint/autoflake
rev: v1.4
rev: v2.3.1
hooks:
- id: autoflake
args: ["--in-place", "--remove-all-unused-imports"]
- repo: https://github.com/psf/black
rev: 22.3.0
rev: 24.10.0
hooks:
- id: black
- repo: https://github.com/PyCQA/flake8
rev: 4.0.1
rev: 7.1.1
hooks:
- id: flake8
additional_dependencies: [flake8-typing-imports>=1.9.0]
- repo: https://github.com/tlambert03/napari-plugin-checks
rev: v0.2.0
rev: v0.3.0
hooks:
- id: napari-plugin-checks
# https://mypy.readthedocs.io/en/stable/introduction.html
Expand Down
115 changes: 95 additions & 20 deletions src/box_manager/_qt/SelectMetric.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
QHeaderView,
QLabel,
QLineEdit,
QPushButton,
QSlider,
QStyle,
QStyledItemDelegate,
Expand All @@ -58,6 +59,9 @@
# return inner


EMPTY_NAME = "-"


def check_equal(layer, compare_data):
if isinstance(layer, napari.layers.Points):
return np.array_equal(layer.data, compare_data)
Expand Down Expand Up @@ -167,7 +171,7 @@ def update_model(self, layer_dict, value, col_idx):
parent_item = self.item(parent_idx, 0)
change_children = False

for row_idx in rows_idx:
for row_idx in set(rows_idx):
child_item = parent_item.child(row_idx, col_idx)
child_item.setText(str(value))
if change_children:
Expand Down Expand Up @@ -356,7 +360,7 @@ def append_to_row(self, root_element, columns, row_idx, first_item=None):
else:
text = columns[cur_label] if cur_label in columns else "-"
col_item = QStandardItem(text)
if isinstance(text, bool):
if isinstance(text, (bool, np.bool_)):
combo_items.append((col_item, cur_label))
col_item.setEditable(True)
col_item.setCheckable(True)
Expand Down Expand Up @@ -427,9 +431,11 @@ def set_parent_only(self, value):

def get_row_selection(self):
prev_selection = {
self.model.get_value(-1, entry[1], "name")
if entry[0] == -1
else self.model.get_value(-1, entry[0], "name")
(
self.model.get_value(-1, entry[1], "name")
if entry[0] == -1
else self.model.get_value(-1, entry[0], "name")
)
for entry in self.get_row_candidates(False)
}
return prev_selection
Expand Down Expand Up @@ -542,9 +548,11 @@ def get_row_candidates(self, parent_only=None):
parent_only = self.parent_only
if parent_only:
return {
(-1, entry.parent().row())
if entry.parent().row() != -1
else (entry.parent().row(), entry.row())
(
(-1, entry.parent().row())
if entry.parent().row() != -1
else (entry.parent().row(), entry.row())
)
for entry in self.selectedIndexes()
}
else:
Expand Down Expand Up @@ -643,6 +651,8 @@ def __init__(self, napari_viewer: "napari.Viewer"):
self.metric_area = QVBoxLayout()

self.option_area = QHBoxLayout()
###
###
self.global_checkbox = QCheckBox(
"Apply on layers, not on slices", self
)
Expand Down Expand Up @@ -680,6 +690,9 @@ def __init__(self, napari_viewer: "napari.Viewer"):
self.settings_area.addWidget(self.hide_dim, stretch=1)
self.settings_area.addWidget(QLabel("Slices:", self))
self.settings_area.addWidget(self.show_mode, stretch=1)
btn = QPushButton('Toggle "Write"')
btn.clicked.connect(self._update_all_check_state)
self.settings_area.addWidget(btn)

self.setLayout(QVBoxLayout())
self.layout().addLayout(self.settings_area, stretch=0) # type: ignore
Expand Down Expand Up @@ -771,6 +784,42 @@ def _update_check_state(self, layer_name, slice_idx, attr_name, value):
attr_name
] = value

@Slot(bool)
def _update_all_check_state(self):
prev_status = self.table_widget.blockSignals(True)
cur_selection = self.table_widget.get_row_candidates(False)
layer_dict = {}
for parent_idx, row_idx in cur_selection:
if parent_idx == -1:
parent_item = self.table_widget.model.item(row_idx, 0)
parent_idx = row_idx
rows = set(range(parent_item.rowCount()))
else:
rows = {row_idx}
layer_dict.setdefault(parent_idx, set()).update(rows)

item_values = []
for parent_idx, rows in layer_dict.items():
item_values.extend(
self.table_widget.model.get_checkstates(
parent_idx, rows, "write"
)
)

check_state = not all(item_values)
for parent_idx, rows in layer_dict.items():
layer_name = self.table_widget.model.get_value(
-1, parent_idx, "name"
)
for row in rows:
self.table_widget.model.set_checkstate(
parent_idx, row, "write", check_state
)
self.napari_viewer.layers[layer_name].metadata[row][
"write"
] = check_state
self.table_widget.blockSignals(prev_status)

def _set_color(self):
if self.napari_viewer.theme == "dark":
icon = pathlib.Path(ICON_DIR, "checkmark_white.png")
Expand Down Expand Up @@ -1065,9 +1114,9 @@ def _update_name(self, event):

@Slot(object)
def _update_on_data(self, event):
'''
"""
Is triggered when data is change in one layer.
'''
"""
if not self._plugin_view_update:
layer = event.source
try:
Expand Down Expand Up @@ -1200,6 +1249,15 @@ def _prepare_entries(self, layer, *, name=None) -> list:
for e1, e2 in features_copy.groupby("identifier", sort=False)
}

try:
is_3d = layer.metadata["is_3d"]
except KeyError:
is_3d = False

empty_name = None
if name is None and is_3d:
empty_name = EMPTY_NAME

try:
max_slice = max(loop_var)
except ValueError:
Expand All @@ -1209,10 +1267,13 @@ def _prepare_entries(self, layer, *, name=None) -> list:
ident_df = slice_dict[identifier]
except KeyError:
ident_df = pd.DataFrame(columns=features_copy.columns)

try:
cur_name = name or layer.metadata[identifier]["name"]
cur_name = name or (
empty_name or layer.metadata[identifier]["name"]
)
except KeyError:
cur_name = "Manual"
cur_name = EMPTY_NAME
output_list.append(
self._prepare_columns(
pd.DataFrame(get_size(layer), dtype=float),
Expand All @@ -1229,9 +1290,11 @@ def _prepare_entries(self, layer, *, name=None) -> list:
if not output_list and name is not None:
identifier = "" if name is not None else 0
try:
cur_name = name or layer.metadata[identifier]["name"]
cur_name = name or (
empty_name or layer.metadata[identifier]["name"]
)
except KeyError:
cur_name = "Manual"
cur_name = EMPTY_NAME
features = pd.DataFrame(columns=["shown"])
output_list.append(
self._prepare_columns(
Expand Down Expand Up @@ -1277,14 +1340,15 @@ def _prepare_columns(
if is_main_group:
output_dict["write"] = "-"
else:
# Cast explicitely as bool here, because it can be np.bool_
try:
write_val = label_data.loc[slice_idx, "write"]
if write_val is not None and not np.isnan(write_val):
output_dict["write"] = write_val
output_dict["write"] = bool(write_val)
else:
output_dict["write"] = not features.empty
output_dict["write"] = bool(not features.empty)
except KeyError:
output_dict["write"] = not features.empty
output_dict["write"] = bool(not features.empty)

for col_name in features.columns:
if col_name in self.ignore_idx:
Expand Down Expand Up @@ -1410,10 +1474,19 @@ def _update_table(self, layer: napari.layers.Layer, current_slice):
else:
label_data = pd.DataFrame()
range_list.extend(full_range)

try:
is_3d = layer.metadata["is_3d"]
except KeyError:
is_3d = False

empty_name = None
if is_3d:
empty_name = EMPTY_NAME
try:
name = layer.metadata[current_slice]["name"]
name = empty_name or layer.metadata[current_slice]["name"]
except KeyError:
name = "Manual"
name = EMPTY_NAME
new_col_entry = self._prepare_columns(
pd.DataFrame(get_size(layer), dtype=float),
pd.DataFrame(columns=list(layer.features.columns) + ["shown"]),
Expand All @@ -1433,7 +1506,9 @@ def _update_table(self, layer: napari.layers.Layer, current_slice):
write_val = layer.metadata.setdefault(current_slice, {}).setdefault(
"write", None
)
check_value = write_val if write_val is not None else bool(selected)
check_value = (
bool(write_val) if write_val is not None else bool(selected)
)
if check_value != self.table_model.get_checkstate(
parent_idx, child_idx, "write"
):
Expand Down

0 comments on commit ce1aa27

Please sign in to comment.