Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception when setting point colors/classifications in v0.4.1 #1202

Closed
OpenScienceProject opened this issue Jan 9, 2023 · 7 comments
Closed
Labels
Milestone

Comments

@OpenScienceProject
Copy link

OpenScienceProject commented Jan 9, 2023

Describe the bug
On QuPath 0.4.1, when I try to create points, at the moment I right click to set a Class, the bug appears, and a log window indicates:

INFO: QuPath build: Version: 0.4.1 Build time: 2023-01-07, 12:00 INFO: Setting tile cache size to 3972.00 MB (25.0% max memory) INFO: Refreshing extensions in Path/to/QuPath/extensions/extensions INFO: Added extension: Path/to/QuPath/extensions/extensions/qupath-extension-stardist-0.4.0.jar INFO: Added extension: Path/to/QuPath/extensions/extensions/qupath-extension-cellpose-0.6.0.jar INFO: Added extension: Path/to/QuPath/extensions/extensions/qupath-extension-imagecombiner-0.2.3.jar INFO: Initializing type adapters INFO: CUDA detected and will be used if possible. Use DnnTools.setUseCuda(false) to turn this off. INFO: Loaded extension BIOP Cellpose extension (3 ms) INFO: Bio-Formats version 6.11.1 INFO: Bio-Formats memoization is turned OFF (based on Java 17.0.5+8, Bio-Formats 6.11.1) INFO: Loaded extension Bio-Formats options (Bio-Formats 6.11.1) (9 ms) INFO: Loaded extension ImageCombiner extension (1 ms) INFO: Loaded extension ImageJ extension (34 ms) INFO: Loaded extension Processing extension (16 ms) INFO: Loaded extension Rich script editor extension (144 ms) INFO: Loaded extension SVG export extension (0 ms) INFO: Loaded extension StarDist extension (2 ms) INFO: OpenSlide version 3.4.1 INFO: Starting QuPath with parameters: [] INFO: Update check for https://github.com/qupath/qupath INFO: No newer release for QuPath (0.4.1 is newer than 0.4.1) INFO: Update check for https://github.com/qupath/qupath-extension-stardist INFO: No newer release for StarDist extension (0.4.0 is newer than 0.4.0) INFO: Update check for https://github.com/biop/qupath-extension-cellpose INFO: No newer release for Cellpose 2D QuPath Extension (0.6.0 is newer than 0.6.0) WARN: Selecting project file /media/image_in/T7 Shield/Recherche/LABO/12.22-Efferocytose_InCuCyte/qupath/QupathProject_donneur1/project.qpproj INFO: Project set to Project: QupathProject_donneur1-project INFO: Setting max Bio-Formats readers to 20 WARN: Removing alpha channel ... (a lot of warnings) WARN: Removing alpha channel ERROR: QuPath exception: Bidirectional binding failed, setting to the previous value java.lang.RuntimeException: Bidirectional binding failed, setting to the previous value at com.sun.javafx.binding.BidirectionalBinding$TypedGenericBidirectionalBinding.invalidated(BidirectionalBinding.java:677) at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:136) at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80) at javafx.beans.property.ObjectPropertyBase.fireValueChangedEvent(ObjectPropertyBase.java:106) at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:113) at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:147) at javafx.css.StyleableObjectProperty.set(StyleableObjectProperty.java:82) at javafx.scene.control.Labeled.setTextFill(Labeled.java:766) at org.controlsfx.glyphfont.Glyph.setColor(Glyph.java:288) at qupath.lib.gui.tools.IconFactory.createROIIcon(IconFactory.java:275) at qupath.lib.gui.tools.IconFactory.createPathObjectIcon(IconFactory.java:228) at qupath.lib.gui.tools.PathObjectLabels$PathObjectMiniPane.setPathObject(PathObjectLabels.java:253) at qupath.lib.gui.tools.PathObjectLabels$PathObjectTreeCell.updateItem(PathObjectLabels.java:126) at qupath.lib.gui.tools.PathObjectLabels$PathObjectTreeCell.updateItem(PathObjectLabels.java:113) at javafx.scene.control.TreeCell.updateItem(TreeCell.java:533) at javafx.scene.control.TreeCell.lambda$new$3(TreeCell.java:173) at javafx.beans.WeakInvalidationListener.invalidated(WeakInvalidationListener.java:83) at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:348) at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80) at javafx.beans.property.ObjectPropertyBase.fireValueChangedEvent(ObjectPropertyBase.java:106) at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:113) at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:147) at javafx.scene.control.TreeView.setRoot(TreeView.java:479) at qupath.lib.gui.panes.PathObjectHierarchyView.setImageData(PathObjectHierarchyView.java:424) at qupath.lib.gui.panes.PathObjectHierarchyView.changed(PathObjectHierarchyView.java:446) at qupath.lib.gui.panes.PathObjectHierarchyView.changed(PathObjectHierarchyView.java:64) at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:360) at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80) at javafx.beans.property.ObjectPropertyBase.fireValueChangedEvent(ObjectPropertyBase.java:106) at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:113) at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:147) at qupath.lib.gui.QuPathGUI.fireImageDataChangedEvent(QuPathGUI.java:4538) at qupath.lib.gui.QuPathGUI$MultiviewManager.imageDataChanged(QuPathGUI.java:5077) at qupath.lib.gui.viewer.QuPathViewer.fireImageDataChanged(QuPathViewer.java:1695) at qupath.lib.gui.viewer.QuPathViewer.setImageData(QuPathViewer.java:1596) at qupath.lib.gui.QuPathGUI.openImageEntry(QuPathGUI.java:2992) at qupath.lib.gui.panes.ProjectBrowser.lambda$new$4(ProjectBrowser.java:201) at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86) at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234) at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74) at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54) at javafx.event.Event.fireEvent(Event.java:198) at javafx.scene.Scene$ClickGenerator.postProcess(Scene.java:3599) at javafx.scene.Scene$MouseHandler.process(Scene.java:3903) at javafx.scene.Scene.processMouseEvent(Scene.java:1887) at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2620) at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:411) at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:301) at java.base/java.security.AccessController.doPrivileged(Unknown Source) at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:450) at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424) at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:449) at com.sun.glass.ui.View.handleMouseEvent(View.java:551) at com.sun.glass.ui.View.notifyMouse(View.java:937) at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method) at com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:316) at java.base/java.lang.Thread.run(Unknown Source) Caused by DuplicatableGlyph.textFill : A bound value cannot be set. at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:143) at javafx.css.StyleableObjectProperty.set(StyleableObjectProperty.java:82) at javafx.beans.property.ObjectProperty.setValue(ObjectProperty.java:78) at com.sun.javafx.binding.BidirectionalBinding$TypedGenericBidirectionalBinding.invalidated(BidirectionalBinding.java:650) at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:136) at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80) at javafx.beans.property.ObjectPropertyBase.fireValueChangedEvent(ObjectPropertyBase.java:106) at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:113) at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:147) at javafx.css.StyleableObjectProperty.set(StyleableObjectProperty.java:82) at javafx.scene.control.Labeled.setTextFill(Labeled.java:766) at org.controlsfx.glyphfont.Glyph.setColor(Glyph.java:288) at qupath.lib.gui.tools.IconFactory.createROIIcon(IconFactory.java:275) at qupath.lib.gui.tools.IconFactory.createPathObjectIcon(IconFactory.java:228) at qupath.lib.gui.tools.PathObjectLabels$PathObjectMiniPane.setPathObject(PathObjectLabels.java:253) at qupath.lib.gui.tools.PathObjectLabels$PathObjectTreeCell.updateItem(PathObjectLabels.java:126) at qupath.lib.gui.tools.PathObjectLabels$PathObjectTreeCell.updateItem(PathObjectLabels.java:113) at javafx.scene.control.TreeCell.updateItem(TreeCell.java:533) at javafx.scene.control.TreeCell.lambda$new$3(TreeCell.java:173) at javafx.beans.WeakInvalidationListener.invalidated(WeakInvalidationListener.java:83) at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:348) at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80) at javafx.beans.property.ObjectPropertyBase.fireValueChangedEvent(ObjectPropertyBase.java:106) at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:113) at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:147) at javafx.scene.control.TreeView.setRoot(TreeView.java:479) at qupath.lib.gui.panes.PathObjectHierarchyView.setImageData(PathObjectHierarchyView.java:424) at qupath.lib.gui.panes.PathObjectHierarchyView.changed(PathObjectHierarchyView.java:446) at qupath.lib.gui.panes.PathObjectHierarchyView.changed(PathObjectHierarchyView.java:64) at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:360) at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:80) at javafx.beans.property.ObjectPropertyBase.fireValueChangedEvent(ObjectPropertyBase.java:106) at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:113) at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:147) at qupath.lib.gui.QuPathGUI.fireImageDataChangedEvent(QuPathGUI.java:4538) at qupath.lib.gui.QuPathGUI$MultiviewManager.imageDataChanged(QuPathGUI.java:5077) at qupath.lib.gui.viewer.QuPathViewer.fireImageDataChanged(QuPathViewer.java:1695) at qupath.lib.gui.viewer.QuPathViewer.setImageData(QuPathViewer.java:1596) at qupath.lib.gui.QuPathGUI.openImageEntry(QuPathGUI.java:2992) at qupath.lib.gui.panes.ProjectBrowser.lambda$new$4(ProjectBrowser.java:201) at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86) at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234) at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191) at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56) at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114) at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74) at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54) at javafx.event.Event.fireEvent(Event.java:198) at javafx.scene.Scene$ClickGenerator.postProcess(Scene.java:3599) at javafx.scene.Scene$MouseHandler.process(Scene.java:3903) at javafx.scene.Scene.processMouseEvent(Scene.java:1887) at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2620) at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:411) at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:301) at java.base/java.security.AccessController.doPrivileged(Unknown Source) at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:450) at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424) at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:449) at com.sun.glass.ui.View.handleMouseEvent(View.java:551) at com.sun.glass.ui.View.notifyMouse(View.java:937) at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method) at com.sun.glass.ui.gtk.GtkApplication.lambda$runLoop$11(GtkApplication.java:316) at java.base/java.lang.Thread.run(Unknown Source) INFO: Image data set to ImageData: Brightfield (other), Training Img (Classifier) ERROR: Bidirectional binding failed, setting to the previous value (see full stack trace above, or use 'debug' log level) ERROR: Bidirectional binding failed, setting to the previous value (see full stack trace above, or use 'debug' log level)

When I run it on QuPath 0.4.0, I don't have this issue.

To Reproduce
Steps to reproduce the behavior:

  1. Go to 'Click to add points'
  2. Click on 'Set Class'

Expected behavior
Unable to set Class to points.

Screenshots
Screenshot from 2023-01-09 10-00-42

Desktop (please complete the following information):

  • OS: Ubuntu 22.04
  • QuPath Version: 0.4.1

Additional context
It is a version of QuPath build on source to be compatible with Cuda for Gpu acceleration (for CellPose).

@petebankhead
Copy link
Member

Thanks @OpenScienceProject I can replicate the problem.

The issue comes from how the icon colors are set; ultimately, it's connected to some changes that were made to overcome some awkward JavaFX/ControlsFX behavior that was making the icon colors wrong in dark mode.

I'll look into it, but I suspect a new release will be needed to have an effective workaround.

Sidenote: I see that changing the Default object color in the preferences doesn't change the icon colors properly; this is probably a related issue.

@petebankhead
Copy link
Member

Since you're building from source anyway, commenting out the line 275 - glyph.setColor(color) - from IconFactory.java should at least stop the exception (the icon color will be wrong, but not the color displayed in the viewer):
https://github.com/qupath/qupath/blob/main/qupath-gui-fx/src/main/java/qupath/lib/gui/tools/IconFactory.java#L275

The exception is really mysterious though, since it's complaining about a value being bound immediately after it has been explicitly unbound... so I'm really not sure yet what's going on. Setting the color simply sets the textFillProperty() so it's very odd.

@petebankhead
Copy link
Member

Actually, ignore that last suggestion... change line 375 of GuiTools.java instead:
https://github.com/qupath/qupath/blame/main/qupath-gui-fx/src/main/java/qupath/lib/gui/tools/GuiTools.java#L343

Using

textFillProperty().bind(glyph.textFillProperty());

instead of

textFillProperty().bindBidirectional(glyph.textFillProperty());

seems to fix the issue, but I need to check it doesn't have some other undesirable effect.

@petebankhead petebankhead changed the title Issue on QuPath 0.4.1, unable to make points Exception when setting point colors/classifications in v0.4.1 Jan 9, 2023
@petebankhead petebankhead added this to the v0.4.2 milestone Jan 9, 2023
petebankhead added a commit to petebankhead/qupath that referenced this issue Jan 10, 2023
Fixes
* qupath#1202
* qupath#1203
Also fix minor typo.
@zindy
Copy link
Contributor

zindy commented Jan 13, 2023

I've just compiled QuPath from main and can confirm that this bug has now been fixed (in 0.4.1, setting a point annotation class causes a "bidirectional binding failed error").

Thanks Pete!

@petebankhead
Copy link
Member

Brilliant, thanks @zindy! Very reassuring to have any fixes validated, I hope v0.4.2 can last longer than v0.4.0 and v0.4.1 :)

@OpenScienceProject
Copy link
Author

The fix worked for me too.
Thank you Pete.

@petebankhead
Copy link
Member

v0.4.2 is now available so I'll close this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants