From bf455a261808de05325be5000cda423a2bbac9bd Mon Sep 17 00:00:00 2001 From: deroulers Date: Sun, 16 Mar 2025 05:40:33 +0100 Subject: [PATCH] Enable to distinguish manual and automatic masks in GUI --- cellpose/gui/gui.py | 48 +++++++++++++++++++++++++---- cellpose/gui/guihelpwindowtext.html | 4 +++ cellpose/gui/io.py | 3 ++ 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/cellpose/gui/gui.py b/cellpose/gui/gui.py index 614b877a..e6f7edb5 100644 --- a/cellpose/gui/gui.py +++ b/cellpose/gui/gui.py @@ -268,6 +268,7 @@ def __init__(self, image=None, logger=None): for i in range(3): self.cmap.append( make_cmap(i).getLookupTable(start=0.0, stop=255.0, alpha=False)) + self.manualPatternSide = 6 if MATPLOTLIB: self.colormap = (plt.get_cmap("gist_ncar")(np.linspace(0.0, .9, 1000000)) * @@ -431,6 +432,15 @@ def make_buttons(self): self.MCheckBox.toggled.connect(self.toggle_masks) self.drawBoxG.addWidget(self.MCheckBox, b0, 0, 1, 5) + b0 += 1 + # don't distinguish masks of manually labelled cells + self.markManualMasksOn = True + self.MMCheckBox = QCheckBox("DISTINGUISH MANUAL [M]") + self.MMCheckBox.setFont(self.medfont) + self.MMCheckBox.setChecked(True) + self.MMCheckBox.toggled.connect(self.toggle_masks) + self.drawBoxG.addWidget(self.MMCheckBox, b0, 0, 1, 5) + b0 += 1 # turn off outlines self.outlinesOn = False # turn off by default @@ -883,6 +893,8 @@ def keyPressEvent(self, event): 1).isEnabled()) if event.key() == QtCore.Qt.Key_X: self.MCheckBox.toggle() + if event.key() == QtCore.Qt.Key_M: + self.MMCheckBox.toggle() if event.key() == QtCore.Qt.Key_Z: self.OCheckBox.toggle() if event.key() == QtCore.Qt.Key_Left or event.key( @@ -1150,6 +1162,10 @@ def toggle_masks(self): self.masksOn = True else: self.masksOn = False + if self.MMCheckBox.isChecked(): + self.markManualMasksOn = True + else: + self.markManualMasksOn = False if self.OCheckBox.isChecked(): self.outlinesOn = True else: @@ -1808,7 +1824,17 @@ def draw_mask(self, z, ar, ac, vr, vc, color, idx=None): if z == self.currentZ: self.layerz[ar, ac, :3] = color if self.masksOn: - self.layerz[ar, ac, -1] = self.opacity + if self.markManualMasksOn: + c = np.tile(np.array([[True, False], [False, True]]), + (self.cellpix.shape[1:] + + np.array((self.manualPatternSide - 1,) * 2)) + // (2 * self.manualPatternSide) + ).repeat(self.manualPatternSide, axis=1) \ + .repeat(self.manualPatternSide, axis=0) + self.layerz[ar, ac, -1] = self.opacity * np.logical_not( + c[ar, ac]).astype(np.uint8) + else: + self.layerz[ar, ac, -1] = self.opacity if self.outlinesOn: self.layerz[vr, vc] = np.array(self.outcolor) @@ -1858,13 +1884,23 @@ def draw_layer(self): #print(self.cellpix.shape, self.outpix.shape, self.cellpix.max(), self.outpix.max()) self.layerz = np.zeros((self.Ly, self.Lx, 4), np.uint8) if self.masksOn: - self.layerz[..., :3] = self.cellcolors[self.cellpix[self.currentZ], :] - self.layerz[..., 3] = self.opacity * (self.cellpix[self.currentZ] - > 0).astype(np.uint8) + cZ = self.currentZ + self.layerz[..., :3] = self.cellcolors[self.cellpix[cZ], :] + self.layerz[..., 3] = self.opacity * (self.cellpix[cZ] > 0).astype(np.uint8) + if self.markManualMasksOn and self.ismanual.sum() > 0: + c = np.tile(np.array([[True, False], [False, True]]), + (self.cellpix.shape[1:] + + np.array((self.manualPatternSide - 1,) * 2)) + // (2 * self.manualPatternSide) + ).repeat(self.manualPatternSide, axis=1) \ + .repeat(self.manualPatternSide, axis=0) + self.layerz[..., 3] -= self.opacity * ( + self.ismanual[np.maximum(self.cellpix[cZ], 1) - 1] & + c[:self.cellpix.shape[1], :self.cellpix.shape[2]] & \ + (self.cellpix[cZ] > 0)).astype(np.uint8) if self.selected > 0: - self.layerz[self.cellpix[self.currentZ] == self.selected] = np.array( + self.layerz[self.cellpix[cZ] == self.selected] = np.array( [255, 255, 255, self.opacity]) - cZ = self.currentZ stroke_z = np.array([s[0][0] for s in self.strokes]) inZ = np.nonzero(stroke_z == cZ)[0] if len(inZ) > 0: diff --git a/cellpose/gui/guihelpwindowtext.html b/cellpose/gui/guihelpwindowtext.html index 4ca5d209..808cef9e 100644 --- a/cellpose/gui/guihelpwindowtext.html +++ b/cellpose/gui/guihelpwindowtext.html @@ -123,6 +123,10 @@ X turn masks ON or OFF + + M + distinguish masks of manually labelled cells ON or OFF + Z toggle outlines ON or OFF diff --git a/cellpose/gui/io.py b/cellpose/gui/io.py index 1dc2e0cd..723839f9 100644 --- a/cellpose/gui/io.py +++ b/cellpose/gui/io.py @@ -386,6 +386,9 @@ def _load_seg(parent, filename=None, image=None, image_file=None, load_3D=False) _masks_to_gui(parent, dat["masks"], outlines=dat["outlines"], colors=colors) + if "ismanual" in dat and len(dat["ismanual"]) == parent.ncells: + parent.ismanual = dat["ismanual"] + parent.draw_layer() if "est_diam" in dat: parent.Diameter.setText("%0.1f" % dat["est_diam"])