Coder Social home page Coder Social logo

qupath / qupath Goto Github PK

View Code? Open in Web Editor NEW
973.0 57.0 267.0 95.74 MB

QuPath - Bioimage analysis & digital pathology

Home Page: https://qupath.github.io

License: GNU General Public License v3.0

Java 98.96% Assembly 0.18% CSS 0.21% Shell 0.03% Roff 0.62%
bioimage-informatics image-processing digital-pathology pathology machine-learning cell-segmentation whole-slide-imaging bioimage-analysis cell-analysis imagej

qupath's Introduction

Image.sc forum Total downloads Latest release downloads Paper Twitter

QuPath

QuPath is open source software for bioimage analysis.

Features include:

  • Lots of tools to annotate and view images, including whole slide & microscopy images
  • Workflows for brightfield & fluorescence image analysis
  • New algorithms for common tasks, including cell segmentation, tissue microarray dearraying
  • Interactive machine learning for object & pixel classification
  • Customization, batch-processing & data interrogation by scripting
  • Easy integration with other tools, including ImageJ

To download QuPath, go to the Latest Releases page.

For documentation, see https://qupath.readthedocs.io

For help & support, try image.sc or the links here

To build QuPath from source see here.

If you find QuPath useful in work that you publish, please cite the publication!

QuPath is an academic project intended for research use only. The software has been made freely available under the terms of the GPLv3 in the hope it is useful for this purpose, and to make analysis methods open and transparent.

Development & support

QuPath is being actively developed at the University of Edinburgh by:

Past QuPath dev team members:

  • Melvin Gelbard
  • Mahdi Lamb

For all contributors, see here.

This work is made possible in part thanks to funding from:


Background

QuPath was first designed, implemented and documented by Pete Bankhead while at Queen's University Belfast, with additional code and testing by Jose Fernandez.

Versions up to v0.1.2 are copyright 2014-2016 The Queen's University of Belfast, Northern Ireland. These were written as part of projects that received funding from:

  • Invest Northern Ireland (RDO0712612)
  • Cancer Research UK Accelerator (C11512/A20256)

Image

qupath's People

Contributors

ajay1685 avatar alanocallaghan avatar camlloyd avatar carlocastoldi avatar finglis avatar imagejan avatar iwbh15 avatar jballanc avatar juliangilbey avatar lacan avatar mahdilamb avatar matty234 avatar melvingelbard avatar petebankhead avatar rylern avatar salmadammak avatar zindy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

qupath's Issues

QuPath sometimes hangs when making selections amid large numbers of objects

Occasionally, QuPath hangs when selecting multiple objects when analyzing a large tissue image.

The bug can be intermittent during 'normal use', but is reproducible with the following steps:

  • Open a whole slide image
  • Create a single, very large annotation
  • Create a large number of detections within the annotation (at least tens/hundreds of thousands); this is easiest with the Create tiles command
  • Draw several more smaller annotations within the large one
  • In the Annotation tab, select multiple annotations
  • Wait... then give up waiting and force-quit QuPath

The problem traces back to QuPath's attempt to synchronize the selected within QuPath’s object hierarchy with the objects shown in the JavaFX TreeView used in the Hierarchy tab. Basically, JavaFX’s TreeView is forced to do a rather slow check along all expanded nodes to look for objects... and if you have a single expanded node containing >~ 10 000 objects expanded within the TreeView then this can be extremely slow.

It likely hasn't actually crashed… but it would take an unrealistically long time to become responsive again.

The problem is intermittent because expanded nodes with only a few thousand objects in them (e.g. TMA cores) can be handled quite quickly. Additionally, large numbers of objects can be handled so long as the parent objects within the tree aren't expanded, or the objects are contained within multiple smaller annotations rather than a single, very large region. As such, TMA slides and core biopsies likely work (given that the objects are stored within smaller regions), while some whole face sections may be problematic depending on what processing is performed and how.

Since the issue appears to be isolated to the display of large numbers of detections within a TreeView, a straightforward fix in a future QuPath release may be to simply exclude detections from the TreeView by default, showing instead only TMA cores and annotations.

In the meantime, hopefully this description of the issue might help anyone encountering it to know the cause, and look for workarounds for their uses.

For example, if it is still required to analyze a single large region containing a large number of detections, then Analyze → Region identification → Tiles & superpixels → Create tiles has recently received an update to enable the creation of 'annotation tiles'. Using this, the larger annotation can be partitioned into smaller ones, which can then be processed separately. Some additional care is needed to ensure that the correct annotations are selected at the appropriate time using this method, but it can be used to avoid the performance issue before a longer term fix is available.

Java heap space error

Hi,

This is Ali here. Thank you for your wonderful application. I had this error saying 'Java heap space' when trying to automate estimation of stain vectors. Does this have to do with low memory/specifications of my PC? Cause mine is i5 processor with 4GB RAM. Thanks.

Order of listed annotations is unpredictable

The order in which annotations are listed in the Annotations tab is... unpredictable at best.

It would be helpful to have them sorted consistently in a similar way to how they are displayed in the Hierarchy tab, i.e. parent annotations first.

The possibility of changing the sorted order may also be beneficial.

Positive cell detection

Hey Guys!
I try to define cells into tumor and non-tumor cells with the detection classifier and determine afterwards the positive and negative cells in the respective class (with help of positive cell detection), but this second step doesn't work. Does anyone know how to search for positive and negative cells in already defined classes over a whole TMA-slide? Thanks a lot for your help!!

Optimiziation of Positive Cell detection - example Ki67, in H DAB

H-DAB Ki67 labeled tissue,
celldetection of negative blue nuclei works best, with Hematoxylin OD Nucleus Detection.
Drawback is lack of recognition of DAB positive cells.

Recognition of DAB positive cells works best, with optical density sum for nucleus detection, but a lot of blue negative cells are not detected.

Is it possible to combine both methods? Do both analysis, keep the result of Optical density sum for positive nuclei and keep the result for negative cells from Hematoxylin OD nucleus cell ##detection?

ImageJ macro runner fails when extracting a large region

The ImageJ macro runner currently only works on TMA core objects or Annotation objects.

If any objects of this type are selected, it will extract and run a macro for the corresponding ROIs of these objects.

However, at least two things aren't good:

  • If the ROIs are too large, QuPath will try to extract them anyway... and likely hang
  • If no valid (i.e. TMA or annotation) objects are selected, QuPath will default to processing all the cores or annotations that it can find... without asking permission for this

Loading saved project/data

I have saved a project in which I had identified single cells throughout a single TMA image. Upon closing and reloading the project I can see all images, but cannot load any information from any preprocessing or cell analysis.
Log and Error below.
Thanks for your help,
Hart

INFO: Reading data from HER2.qpdata...
ERROR: Reached end of file...
ERROR: QuPath exception
at qupath.lib.objects.hierarchy.PathObjectHierarchy.setHierarchy(PathObjectHierarchy.java:627)
at qupath.lib.io.PathIO.readImageDataSerialized(PathIO.java:239)
at qupath.lib.io.PathIO.readImageData(PathIO.java:334)
at qupath.lib.gui.QuPathGUI.openSavedData(QuPathGUI.java:2399)
at qupath.lib.gui.QuPathGUI.openImage(QuPathGUI.java:2208)
at qupath.lib.gui.QuPathGUI.openImage(QuPathGUI.java:2152)
at qupath.lib.gui.commands.OpenCommand.run(OpenCommand.java:51)
at qupath.lib.gui.QuPathGUI.lambda$createCommandAction$46(QuPathGUI.java:3122)
at org.controlsfx.control.action.Action.handle(Action.java:419)
at org.controlsfx.control.action.Action.handle(Action.java:64)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
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.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.control.MenuItem.fire(MenuItem.java:462)
at com.sun.javafx.scene.control.GlobalMenuAdapter.lambda$bindMenuItemProperties$20(GlobalMenuAdapter.java:153)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
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.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.control.MenuItem.fire(MenuItem.java:462)
at com.sun.javafx.tk.quantum.GlassSystemMenu$1.action(GlassSystemMenu.java:238)

Formatting decimal numbers with dots & commands based on region

An unanticipated issue that arose from QuPath going open source is how it can - and should - behave when being run in different regions, where numbers are expected to be formatted differently.

So, for example, 1,234,567.89 in the UK or US might be written as 1.234.567,89 in Germany or 1 234 567,89 in Russia.

This is described in more detail in the Decimal mark Wikipedia article.

This scenario isn't great for software that is intended to be used worldwide for scientific applications, where the format in which numbers are entered and exported really matters.

Locales & formatting numbers

The good news is that Java can support different Locales. This makes it possible to write code that takes the region into consideration.

The very bad news is that handling this predictably is far from straightforward. This arises partly because there are many ways to format numbers within Java, some more convenient than others, and some more problematic than others. For example, considering the following Groovy script to test out different methods:

import java.text.*;

def count = 1;
def sb = new StringBuffer("\n");

def s = NumberFormat.getInstance().format(1.234); // Depends on default Locale
sb.append(count++).append(": ").append(s).append("\n");

s = NumberFormat.getInstance(Locale.GERMANY).format(1.234); // 1,234
sb.append(count++).append(": ").append(s).append("\n");

s = new DecimalFormat("#.##").format(1.234); // Depends on default Locale, 2 decimal places
sb.append(count++).append(": ").append(s).append("\n");

s = String.format("My number is %.3f", 1.234); // Depends on default Locale
sb.append(count++).append(": ").append(s).append("\n");

s = "My number is " + 1.234; // 1.234 - always uses the dot
sb.append(count++).append(": ").append(s).append("\n");

The output when I run it with my default English UK setting is:

1: 1.234
2: 1,234
3: 1.23
4: My number is 1.234
5: My number is 1.234

Alternatively, if I switch to using a German Locale I see:

1: 1,234
2: 1,234
3: 1,23
4: My number is 1,234
5: My number is 1.234

In most of these scenarios the Locale is respected (either the default, or one that is explicitly set)... but not with the simple string + concatenation.

This is a bit scary, since "My number is " + 1.234; is very tempting syntax for a programmer to use. It is highly likely to exist somewhere within QuPath's code.

Parsing numbers

Similar issues arise when parsing numbers using one of Java's myriad ways.

import java.text.*;

def count = 1;
def sb = new StringBuffer("\n");

for (def locale in [Locale.US, Locale.GERMANY]) {

    sb.append("Locale set to ").append(locale).append("\n");
    Locale.setDefault(locale);
    
    def s = NumberFormat.getInstance().parse("1.234"); // Result depends on Locale
    sb.append(count++).append(": ").append(s).append("\n");

    s = NumberFormat.getInstance().parse("1,234"); // Result depends on Locale
    sb.append(count++).append(": ").append(s).append("\n");
    
    s = Double.parseDouble("1.234"); // Always requires a dot
    sb.append(count++).append(": ").append(s).append("\n");    

    try {
        s = Double.parseDouble("1,234"); // Does not work!
    } catch (Exception e) {
        s = "I cannot parse \"1,234\"!"
    }
    sb.append(count++).append(": ").append(s).append("\n");
    
    try {
        s = Double.valueOf("1,234"); // Does not work!
    } catch (Exception e) {
        s = "I cannot get the value of \"1,234\"!"
    }
    sb.append(count++).append(": ").append(s).append("\n");
}

print(sb.toString())

The output of the script above is:

Locale set to en_US
1: 1.234
2: 1234
3: 1.234
4: I cannot parse "1,234"!
5: I cannot get the value of "1,234"!
Locale set to de_DE
6: 1234
7: 1.234
8: 1.234
9: I cannot parse "1,234"!
10: I cannot get the value of "1,234"!

Again, this is scary, because Double.valueOf(String s) and Double.parseDouble(String s) are quite natural choices for a programmer - yet they don't always work, depending upon how the number is written.

But, much worse than that, if the default Locale is used then def s = NumberFormat.getInstance().parse(String s); gives different results. You can see this in the first two entries being reversed when the Locale is changed.

This means that scripts (or data) written with QuPath with one Locale could give different or unexpected results in another Locale. What's more, it's quite possible for a user to have two computers (perhaps one Windows and one Mac) that are set up to have different Locales, but not to have noticed.

Importing/exporting

Finally, it's important to consider what happens after running QuPath's analysis. Commonly, it's necessary to put the results into another application - such as an Excel Spreadsheet.

Excel isn't immune from these issues, and will also parse numbers according to some system setting. Therefore the spreadsheet application is not guaranteed to interpret the numbers written by QuPath in the way that is intended - it's absolutely essential to check.

How does QuPath handle this?

What QuPath does now

QuPath gives some consideration to Locales in two ways, although neither is a complete solution.

Firstly, the Locale information used when saving a .qpdata file is saved with the file. This way, it can be temporarily applied when reloading the file. This at least helps reduce the possibility that a later change in Locale means that a previously-written data file cannot be read again - or is read wrongly.

Secondly, QuPath gives the user a choice of Locale on first startup (or under Help → Show setup options - along with a warning:
qupath_setup

This doesn't force any particular choice... along it at least raises the issue.

What should QuPath do?

This remains an open question - with feedback and ideas welcome.

My current suspicion is that QuPath should enforce the use of one Locale consistently throughout the application. If so, this would likely have to be Locale.US - because this is guaranteed to exist. This will enforce an internal consistency, which is less likely to be troubled by whether or not the programmer of some component or extension parses their numbers in a different way.

It may still be helpful to optionally export data for a specific Locale - but this would need to be explicitly selected (every time?), for ease of importing results into other software.

However, providing this option would require some more thought and planning for at least two reasons:

  • Some exported data should also be reimported into QuPath, e.g. exported TMA data might be imported to use the TMA data viewer - in this case the correct Locale needs to be used for importing as well.
  • There are different ways to export, both in terms of saving or copying values to the clipboard. Any 'smart' behavior in one place risks lulling a user into a false sense of security that the Locale they unthinkingly expect will always be used.

In short, it's a thorny issue. For now, the best approach is to use a Locale that formats uses dots rather than commas as the decimal mark... and then pay close attention whenever the exported results are imported elsewhere.

Immediate plans

I am considering making the first half the change suggested above in the next update, i.e. to force the use of the US Locale. There is too much that is unclear or untested whenever different Locales may be used.

However comments are welcome on the wisdom of this.

Null pointer opening TiFF files

I have downloaded dataset from https://camelyon16.grand-challenge.org/ but looks like QuPath openslide is not able to open it up and giving null pointer exception. I am able to open this file using openslide deep zoom sample server. Error below from openslide.

09:32:08.147 [JavaFX Application Thread] [WARN ] q.i.i.servers.ImageJServerBuilder - Error opening /data/CAMELYON16/Train_Tumor/Tumor_005.tif with ImageJ: Could not open /data/CAMELYON16/Train_Tumor/Tumor_005.tif with ImageJ
TIFFFetchNormalTag: Warning, ASCII value for tag "JPEGTables" does not end in null byte. Forcing it to be null.
TIFFFetchNormalTag: Warning, ASCII value for tag "JPEGTables" does not end in null byte. Forcing it to be null.
TIFFFetchNormalTag: Warning, ASCII value for tag "JPEGTables" does not end in null byte. Forcing it to be null.
TIFFFetchNormalTag: Warning, ASCII value for tag "JPEGTables" does not end in null byte. Forcing it to be null.
TIFFFetchNormalTag: Warning, ASCII value for tag "JPEGTables" does not end in null byte. Forcing it to be null.
TIFFFetchNormalTag: Warning, ASCII value for tag "JPEGTables" does not end in null byte. Forcing it to be null.
TIFFFetchNormalTag: Warning, ASCII value for tag "JPEGTables" does not end in null byte. Forcing it to be null.
TIFFFetchNormalTag: Warning, ASCII value for tag "JPEGTables" does not end in null byte. Forcing it to be null.
TIFFFetchNormalTag: Warning, ASCII value for tag "JPEGTables" does not end in null byte. Forcing it to be null.
TIFFFetchNormalTag: Warning, ASCII value for tag "JPEGTables" does not end in null byte. Forcing it to be null.
TIFFFetchNormalTag: Warning, ASCII value for tag "JPEGTables" does not end in null byte. Forcing it to be null.
TIFFFetchNormalTag: Warning, ASCII value for tag "JPEGTables" does not end in null byte. Forcing it to be null.
TIFFFetchNormalTag: Warning, ASCII value for tag "JPEGTables" does not end in null byte. Forcing it to be null.
09:32:08.264 [JavaFX Application Thread] [ERROR] q.l.i.servers.OpenslideImageServer - Openslide: Property not available: openslide.objective-power
TIFFFetchNormalTag: Warning, ASCII value for tag "JPEGTables" does not end in null byte. Forcing it to be null.
java.io.IOException: Premature end of JPEG file
at org.openslide.OpenSlide.checkError(OpenSlide.java:178)
at org.openslide.OpenSlide.paintRegionARGB(OpenSlide.java:245)
at qupath.lib.images.servers.OpenslideImageServer.readBufferedImage(OpenslideImageServer.java:203)
at qupath.lib.images.servers.OpenslideImageServer.readBufferedImage(OpenslideImageServer.java:1)
at qupath.lib.images.servers.AbstractImageServer.getBufferedThumbnail(AbstractImageServer.java:70)
at qupath.lib.images.servers.OpenslideImageServer.(OpenslideImageServer.java:147)
at qupath.lib.images.servers.OpenslideServerBuilder.buildServer(OpenslideServerBuilder.java:51)
at qupath.lib.images.servers.ImageServerProvider.buildServer(ImageServerProvider.java:115)
at qupath.lib.gui.QuPathGUI.openImage(QuPathGUI.java:2228)
at qupath.lib.gui.QuPathGUI.openImage(QuPathGUI.java:2152)
at qupath.lib.gui.commands.OpenCommand.run(OpenCommand.java:51)
at qupath.lib.gui.QuPathGUI.lambda$createCommandAction$46(QuPathGUI.java:3122)
at org.controlsfx.control.action.Action.handle(Action.java:419)
at org.controlsfx.control.action.Action.handle(Action.java:64)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
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.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.control.MenuItem.fire(MenuItem.java:462)
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.doSelect(ContextMenuContent.java:1405)
at com.sun.javafx.scene.control.skin.ContextMenuContent$MenuItemContainer.lambda$createChildren$343(ContextMenuContent.java:1358)
at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
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.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$MouseHandler.process(Scene.java:3757)
at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:352)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:275)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$300(GlassViewEventHandler.java:388)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:387)
at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
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$null$450(GtkApplication.java:139)
at java.lang.Thread.run(Thread.java:745)
09:32:08.265 [JavaFX Application Thread] [WARN ] q.l.i.servers.OpenslideServerBuilder - Unable to open /data/CAMELYON16/Train_Tumor/Tumor_005.tif with OpenSlide: null
09:32:08.265 [JavaFX Application Thread] [ERROR] q.l.i.servers.ImageServerProvider - Unable to build whole slide server - check your classpath for a suitable library (e.g. OpenSlide, BioFormats)

09:32:08.265 [JavaFX Application Thread] [ERROR] q.l.i.servers.ImageServerProvider - /home/vaibhav/QuPath/app/QuPathApp.jar:qupath/qupath-core-0.1.2.jar:qupath/qupath-core-awt-0.1.2.jar:qupath/qupath-core-processing-0.1.2.jar:qupath/qupath-core-processing-awt-0.1.2.jar:qupath/qupath-extension-ij-0.1.2.jar:qupath/qupath-extension-input-0.1.2.jar:qupath/qupath-extension-opencv-0.1.2.jar:qupath/qupath-extension-openslide-0.1.2.jar:qupath/qupath-extension-pen-0.1.2.jar:qupath/qupath-extension-script-editor-0.1.2.jar:qupath/qupath-gui-fx-0.1.2.jar:qupath/qupath-processing-ij-0.1.2.jar:qupath/qupath-processing-opencv-0.1.2.jar:jars/commons-math3-3.6.1.jar:jars/controlsfx-8.40.12.jar:jars/flowless-0.4.5.jar:jars/groovy-2.4.7.jar:jars/groovy-jsr223-2.4.7.jar:jars/gson-2.8.0.jar:jars/ij-1.51g.jar:jars/jfxtras-common-8.0-r5.jar:jars/jfxtras-menu-8.0-r5.jar:jars/jinput-2.0.6.jar:jars/jpen-2-150301.jar:jars/jutils-1.0.0.jar:jars/logback-classic-1.1.7.jar:jars/logback-core-1.1.7.jar:jars/opencv-3.1.0.jar:jars/openslide-3.4.1_2.jar:jars/packager.jar:jars/reactfx-2.0-M4u1.jar:jars/richtextfx-0.6.10.jar:jars/slf4j-api-1.7.20.jar:jars/undofx-1.2.jar:jars/wellbehavedfx-0.1.1.jar
09:32:08.266 [JavaFX Application Thread] [ERROR] q.lib.gui.helpers.DisplayHelpers - Open image: Sorry, I can't open /data/CAMELYON16/Train_Tumor/Tumor_005.tif

Cannot open .qpdata files if path to the original image has changed

QuPath stores the path of any analyzed image inside any saved .qpdata file. It then uses this path to try to reload the image whenever the .qpdata file is reopened.

However, if the path is wrong (i.e. the original image has moved) then this fails. Currently, this fails catastrophically - especially on Windows. If it is attempted to launch QuPath by double-clicking on the file, then QuPath won't ever start.

What should happen is that there should be an option to change the path instead to point to the correct image.

Language matters... problems with different location settings

While investigating a mysterious bug in which QuPath couldn't read its own data files, it became apparent that (geographical) location really matters.

Of particular importance, switching between formatting numbers with commas or dots to indicate decimals can cause havoc.

In Java, this largely depends upon the Locale that is currently set.

You can check what this is by running the following one-line script in QuPath:

print(Locale.getDefault());

For me, this prints en_GB on my machine... and likely all the other machine's I've tested QuPath on until now. And therefore the issue never came up before QuPath went open source.

Generally, using QuPath consistently with one particular Locale setting ought to work - but it might not if any non-standard formatting is used. In this particular case, an issue arose with reading color deconvolution stain information due to an unexpected use of commas mixed with decimal points. The result is that entire data files were rendered unreadable... because of this one tiny change.

However fixing this one specific problem occurrence won't be enough. For example, in the event that data files written on one computer were to be transferred to another computer with a different Locale setting, then it's likely that the data would become unreadable on the second computer. Scripts are also likely to be affected.

There are a few approaches that could be adopted to address this:

  • Fix QuPath to always use a specific Locale rather than the default. It would probably make sense to make this en_US... although I'm unsure of the implications elsewhere.
  • Fix QuPath to always use a specific Locale when saving and loading data, but otherwise allow the user to select the Locale of their choice (or the default for the computer on which QuPath is running).
  • Save the Locale information whenever saving data, and temporarily apply it whenever loading the same data - reverting back to the user's choice of Locale (if different) afterwards.

Currently I tend towards the last option (even though it wouldn't deal with locale-sensitive scripts), although additional ideas or insights would be welcome.

One thing is clear: the currently locale-lottery within QuPath needs to be addressed somehow.

CZI support with bioformat

This is not really an existing issue since I solve it but I faced the problem.

In addition to drag and drop bioformats_package.jar and qupath-extension-bioformats.jar, opening the CZI files will also require to install Visual C++ Redistributable for Visual Studio 2015 (you can find it here https://www.microsoft.com/en-us/download/details.aspx?id=48145 ) for Microsoft Windows.
It's something I missed and made the usage of bioformat to open CZI hectic (works on some computer where Visual C++ was installed but not where it was not installed.
See https://www.openmicroscopy.org/site/support/bio-formats5.3/formats/zeiss-czi.html for the bioformat documentation.

It would be useful to add this information to the documentation.

Thanks again for this very nice software!
Benjamin

Classify

Dear Pete,

I was wandering if we could use qupath to perform pixel classification, similar to what exist with weka plugin for ImageJ. And if yes, is there a tutorial for that. I have to detect adypocyte and did it with success with ImageJ/Weka but it require to export the slide to a lower resolution so ImageJ can open the image. I would be delighted to use Qupath for that if it was possible.
Benjamin

Brightness & Contrast window , suggestions

Hi Peter,
about the Brightness & Contrast window

  • would it be possible to set values with numeric fields ? (on top of using sliders)
  • that theses settings are saved within the qpdata file of the image (and thus reused when you re-open it). Up to now the settings are lost if you close and open again the program.
  • could there be an option to use the same values for all the images within a project ?

bandc_qupath

libstdc++.so.6 on Ubuntu 14.04 LTS

I untarred the file and tried to start the program but got a dependency error on Linux

./QuPath: /usr/lib/x86_64-linux-gnu/libstdc++.so.6: version `GLIBCXX_3.4.21' not found (required by ./QuPath)

I ran sudo apt-get install libstdc++6

libstdc++6 is already the newest version.

Any idea what may be causing the issue?

Appreciated.

scripting: export tiles within annotation?

I'd like to use QuPath to generate training data for a deep learning model. I am annotating various features (let's say, tumor and stroma), and generating tiles within the annotated regions via Analyze -> Region identification -> Tiles & superpixels -> Create tiles. So far so good. Next I want to export the tiles as separate images, generating a file name according to the enclosing annotation name (e.g. "tumor_tile01.tiff"). I would have thought the following code would give me the enclosing annotation name:

for (annotation in getAnnotationObjects()) {
pathClass = annotation.getPathClass()
print(pathClass)
}

But instead the console prints (a bunch of times):

INFO: null

Any suggestions would be appreciated.

Unexpected behavior when working with classifications with > 2 levels

Object classifications can form hierarchies in QuPath, as described in the documentation.

A derived class should be shown with a colon separator, e.g. Tumor: Positive and Tumor: Negative are both derived from a base classification of Tumor.

This appears to work fine, but if there are more than two 'levels' to the classification then only the final two are displayed through the user interface. Therefore while Tumor: E-cadherin: Positive can be represented in code, it would only be shown as E-cadherin: Positive on screen.

The following script can be used to print out what all the levels of the classification are.

// Get classification of selected object
def pathClass = getSelectedObject().getPathClass()
println("Classification is " + pathClass)
if (pathClass == null) {
    return
}

// Print the full classification
String fullName = pathClass.getName()
pathClass = pathClass.getParentClass()
while (pathClass != null) {
    fullName = pathClass.getName() + ": " + fullName
    pathClass = pathClass.getParentClass()
}
println("Full classification hierarchy is " + fullName)

Additionally, the Classify by specific feature command does not pay much attention to hierarchies of classification - which is somewhat unintuitive, and requires updating (or replacing).

Different cell detection result categories.

So far I have figured out how to detect cells in my TMA, make classifiers and "train" them and get the results outputted nicely from it.
However I would love to make cell detections withing different regions of my TMA, namely CD3 positive cells which are located in the stroma and those which are located in the tumor region.
Does anybody have some advice? (@petebankhead great talk in Bern 2 weeks ago btw.)
regards
frido

Multiple images in a project with the same name treated as the same

QuPath Projects are the recommended way to work with multiple images, since they keep .qpdata files under control and facilitate batch processing (among other benefits).

However, because .qpdata files are automatically named based the image name (i.e. the final part of its path), this means that different images that have the same name are matched with the same .qpdata file.

Ideally, it should be possible to include multiple images with the same name - but different path - in the same project.

If not, there should at least be a warning that this is not supported.

Simple tissue detection for TMA does not work

When trying to run the simple tissue detection for TMA, as suggested in the manual, it won´t work (the detection lines being either very coarse or not even touching the tissue of the TMA core) no matter how I change the settings. Could this be due to the yellowish background (whitespace) of my slide? How can I change this?

"No features selected!" when attempting to create detection classifier

I am not able to create classifiers because I am not able to select features. "No features selected!" when attempting to create detection classifier in the "Advanced options" drop down under "Classifier" in "Create detection classifier".

Seems like I am missing something simple -- any ideas?

Performance issues related to logging

Whenever large number of messages are logged, the current logging implementation can result in a substantial impact in performance.

This is most noticeable when running a script that outputs a lot of text. On extreme occasions, this can result in the script completing successfully - but the progress bar appears to hang since QuPath is frantically trying to get up-to-date on handling the logged messages.

A smarter implementation that can handle messages in batch, or at least does not clog up the Application thread when handling them, is required.

Bio-Formats Extension (0.0.4) does not show up in Extensions menu, cannot be accessed

Dear Dr. Bankhead,

First of all: this is an incredible piece of software! We are exploring its multiple possibilities with great excitement. Thank you very much for making it publicly available.

Among others, we are working with a lot of Zeiss *.czi and 3D Histech *.mrxs multichannel fluorescence whole slide images. The default version of QuPath can open the *.mrxs files, but only in the most coarse resolution. So I installed the Bio-Formats extension and it does show up in the "Help/Installed Extensions "dialogue. However, it does not appear in the "Extensions" Menu. Only ImageJ is accessible in this menu.

Best regards,

Arnulf Mayer, University Medical Center Mainz, Germany

Calculate intensity features command does not support tiling, can be confusing

The Analyze → Calculate features → Add intensity features (experimental) was introduced to replace the older Haralick features command, and is more flexible and capable.

However, it is not restricted only to calculating features on detections, but can also be used for TMA cores and annotations. This ought to be good... except that it can be confusing whenever a user wants to calculate detection features (which is the expected 'normal' use), but happens to have another type of object selected at the time.

Furthermore, it may even cause trouble because it does not automatically tile very large regions or give any warnings. Therefore it could cause crashes if used with very large objects selected.

Brush tool cannot make annotations in tiled rectangular area.

After creating a rectangular annotation and tiling it, the brush tools seems to be unable to make new annotations within the rectangle. Other tools work fine and can be used for selecting tiles for training a classifier, but the brush will only appear if started outside the rectangle and even when created, will not capture any objects.
brush-in-rectangle

Qupath error when changing view on a czi slide

Since the released of bioformat 5.3.0, we can now open czi axioscan slides, but today I got an error while changing the Scene in image list:

This problem do not occur on other computer with the same installation files.

Here is the error logs:

INFO: Refreshing extensions in C:\Users\xxxx\QuPath\extensions INFO: Added extension: C:\Users\xxxx\QuPath\extensions\bioformats_package.jar INFO: Added extension: C:\Users\xxxx\QuPath\extensions\qupath-extension-bioformats.jar INFO: Selected style: Modena Light INFO: Performing update check... INFO: Starting QuPath with parameters: [] ERROR: Could not load OpenSlide native library at java.lang.ClassLoader$NativeLibrary.load(Native Method) at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1941) at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1857) at java.lang.Runtime.loadLibrary0(Runtime.java:870) at java.lang.System.loadLibrary(System.java:1122) at org.openslide.OpenSlideJNI.<clinit>(OpenSlideJNI.java:55) at org.openslide.OpenSlide.<clinit>(OpenSlide.java:53) at qupath.lib.images.servers.OpenslideImageServer.<init>(OpenslideImageServer.java:91) at qupath.lib.images.servers.OpenslideServerBuilder.buildServer(OpenslideServerBuilder.java:47) at qupath.lib.images.servers.ImageServerProvider.buildServer(ImageServerProvider.java:115) at qupath.lib.gui.QuPathGUI.openImage(QuPathGUI.java:2227) at qupath.lib.gui.viewer.DragDropFileImportListener.handleFileDrop(DragDropFileImportListener.java:253) at qupath.lib.gui.viewer.DragDropFileImportListener.handle(DragDropFileImportListener.java:115) at qupath.lib.gui.viewer.DragDropFileImportListener.handle(DragDropFileImportListener.java:1) at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86) at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) 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.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$DnDGesture.fireEvent(Scene.java:2933) at javafx.scene.Scene$DnDGesture.processTargetDrop(Scene.java:3159) at javafx.scene.Scene$DnDGesture.access$6400(Scene.java:2909) at javafx.scene.Scene$DropTargetListener.drop(Scene.java:2873) at com.sun.javafx.tk.quantum.GlassSceneDnDEventHandler.lambda$handleDragDrop$309(GlassSceneDnDEventHandler.java:95) at java.security.AccessController.doPrivileged(Native Method) at com.sun.javafx.tk.quantum.GlassSceneDnDEventHandler.handleDragDrop(GlassSceneDnDEventHandler.java:92) at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleDragDrop$363(GlassViewEventHandler.java:700) at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389) at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleDragDrop(GlassViewEventHandler.java:699) at com.sun.glass.ui.View.handleDragDrop(View.java:712) at com.sun.glass.ui.View.notifyDragDrop(View.java:1037) at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191) at java.lang.Thread.run(Thread.java:745) WARN: Error opening C:\Users\xxxx\Documents\data\2016_03_15__4457.czi with ImageJ: Could not open C:\Users\xxxx\Documents\data\2016_03_15__4457.czi with ImageJ WARN: QuPath Bio-Formats extension is in beta! Be watchful for bugs... INFO: ZeissCZIReader initializing C:\Users\xxxx\Documents\data\2016_03_15__4457.czi INFO: Returning server: Bio-Formats for C:\Users\xxxx\Documents\data\2016_03_15__4457.czi INFO: Estimating H-DAB staining INFO: Image data set to ImageData: Brightfield (H-DAB), 2016_03_15__4457 INFO: ZeissCZIReader initializing C:\Users\xxxx\Documents\data\2016_03_15__4457.czi INFO: ZeissCZIReader initializing C:\Users\xxxx\Documents\data\2016_03_15__4457.czi INFO: ZeissCZIReader initializing C:\Users\xxxx\Documents\data\2016_03_15__4457.czi INFO: ZeissCZIReader initializing C:\Users\xxxx\Documents\data\2016_03_15__4457.czi INFO: ZeissCZIReader initializing C:\Users\xxxx\Documents\data\2016_03_15__4457.czi INFO: ZeissCZIReader initializing C:\Users\xxxx\Documents\data\2016_03_15__4457.czi INFO: ZeissCZIReader initializing C:\Users\xxxx\Documents\data\2016_03_15__4457.czi INFO: ZeissCZIReader initializing C:\Users\xxxx\Documents\data\2016_03_15__4457.czi INFO: ZeissCZIReader initializing C:\Users\xxxx\Documents\data\2016_03_15__4457.czi INFO: ZeissCZIReader initializing C:\Users\xxxx\Documents\data\2016_03_15__4457.czi INFO: ZeissCZIReader initializing C:\Users\xxxx\Documents\data\2016_03_15__4457.czi INFO: ZeissCZIReader initializing C:\Users\xxxx\Documents\data\2016_03_15__4457.czi INFO: ZeissCZIReader initializing C:\Users\xxxx\Documents\data\2016_03_15__4457.czi INFO: ZeissCZIReader initializing C:\Users\xxxx\Documents\data\2016_03_15__4457.czi INFO: ZeissCZIReader initializing C:\Users\xxxx\Documents\data\2016_03_15__4457.czi INFO: ZeissCZIReader initializing C:\Users\xxxx\Documents\data\2016_03_15__4457.czi ERROR: QuPath exception at qupath.lib.images.servers.OpenslideImageServer.<init>(OpenslideImageServer.java:91) at qupath.lib.images.servers.OpenslideServerBuilder.buildServer(OpenslideServerBuilder.java:47) at qupath.lib.images.servers.ImageServerProvider.buildServer(ImageServerProvider.java:115) at qupath.lib.gui.QuPathGUI.openImage(QuPathGUI.java:2227) at qupath.lib.gui.QuPathGUI.openImage(QuPathGUI.java:2151) at qupath.lib.gui.panels.PathImageDetailsPanel.tryToOpenSelectedEntry(PathImageDetailsPanel.java:293) at qupath.lib.gui.panels.PathImageDetailsPanel.lambda$2(PathImageDetailsPanel.java:261) at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86) at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) 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.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:3470) at javafx.scene.Scene$ClickGenerator.access$8100(Scene.java:3398) at javafx.scene.Scene$MouseHandler.process(Scene.java:3766) at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485) at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762) at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494) at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:380) at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:294) at java.security.AccessController.doPrivileged(Native Method) at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:416) at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389) at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:415) at com.sun.glass.ui.View.handleMouseEvent(View.java:555) at com.sun.glass.ui.View.notifyMouse(View.java:937) at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191) at java.lang.Thread.run(Thread.java:745) ERROR: QuPath exception at qupath.lib.images.servers.OpenslideImageServer.<init>(OpenslideImageServer.java:91) at qupath.lib.images.servers.OpenslideServerBuilder.buildServer(OpenslideServerBuilder.java:47) at qupath.lib.images.servers.ImageServerProvider.buildServer(ImageServerProvider.java:115) at qupath.lib.gui.QuPathGUI.openImage(QuPathGUI.java:2227) at qupath.lib.gui.QuPathGUI.openImage(QuPathGUI.java:2151) at qupath.lib.gui.panels.PathImageDetailsPanel.tryToOpenSelectedEntry(PathImageDetailsPanel.java:293) at qupath.lib.gui.panels.PathImageDetailsPanel.lambda$2(PathImageDetailsPanel.java:261) at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86) at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238) 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.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:3470) at javafx.scene.Scene$ClickGenerator.access$8100(Scene.java:3398) at javafx.scene.Scene$MouseHandler.process(Scene.java:3766) at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485) at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762) at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494) at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:380) at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:294) at java.security.AccessController.doPrivileged(Native Method) at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:416) at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389) at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:415) at com.sun.glass.ui.View.handleMouseEvent(View.java:555) at com.sun.glass.ui.View.notifyMouse(View.java:937) at com.sun.glass.ui.win.WinApplication._runLoop(Native Method) at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191) at java.lang.Thread.run(Thread.java:745)

Exporting single cell analysis txt from many cores in TMA

When exporting intensity measurements from a TMA I have a txt file for each level of the hierarchy but it would be necessary for me to know the corresponding TMA for all single cell intensities. Currently the txt is only one list of all single cells - an extra column corresponding to all higher levels of the hierarchy would be very useful.
Thanks!
Hart

Cell detection only partially supports fluorescence images

The primary cell detection command under Analyze → Cell analysis → Cell detection is primarily intended for brightfield images.

However, it ought also to work for fluorescence. Under some conditions it does, namely when:

  • the first fluorescence channel contains a nuclear staining (e.g. DAPI)
  • the Max background intensity parameter is either set negative or very high, or Background radius is negative
  • the Threshold value is set appropriately high

This is because, in the case of fluorescence data, the command only looks for the first available channel within which to detect nuclei. Furthermore, the Max background intensity and Threshold parameters, by default, are selected for optical density units... which can be far away from being sensible values for fluorescence.

The command should be adapted to use more sensible defaults in the case of fluorescence images, and to permit the selection of alternative channels.

Labels are not displayed correctly for some image formats

The recently added Show slide label command can display slide labels if there is an 'associated image' called 'label'.

This is something OpenSlide often provides, however not for all formats. In cases where it is missing, QuPath should probably also look for an image called 'macro' instead, rather than showing nothing.

Additionally, QuPath shows associated images at full size - but this can be larger than the screen, and there is no scrollbar. A better viewer for associated images is needed, or at the very least automatic rescaling of the image to fit the window.

This issue was discussed at Google Groups

Create Linux binary

QuPath should (i.e. has in the past) compile fine under Linux, with the required native libraries.

However, no distribution for Linux is available under Releases yet.

This should happen, but requires gaining access to a suitable Linux machine soon to arrange and test it...

How to continue training saved classifier

I am sure the answer to this question is simple but I just don´t find it in the "user guide". I created a detection classifier (to distinguish between tumor, stroma and immune cells) which was doing ok, so I saved it for later use. When I created it, it got better and better as I drew more annotations and set their class. However it is not working as well as it needs to. So I loaded it again today in an attempt to continue training it. I opened the classifier (Classify -> load classifier (the one I had saved the other day) -> run classifier. At this point it worked like it had when I saved it. How do I continue teaching it from here on? Drawing annotations and setting their class doesn´t work like it did when I created the classifier. Selecting Classify -> create detection classifier does not work because this way I am creating a whole new classifier. How can I get my existing classifier in the mode where I can press auto update or where it automatically continues to update? I must be missing a very simple step!

I have one more question: I am using the classifier on a TMA slide. The TMA cores differ quite a bit. So I have to adjust/train the classifier slightly for each single core until it works the way I want. Do these changes in classification only apply to the selected annotation (TMA core) or does this automatically change the classifications already made using the classifier in other TMA cores on the same slide?
Thank you very much for your help!

Kind regards,

Liese

Delaunay overlay poor performance, cannot be hidden

The Add Delaunay cluster features command has the potential to be very useful, but is currently incomplete.

The most obvious issue is that it creates an overlay that can have a considerable negative impact on repainting speed. Furthermore, this overlay cannot be removed from the GUI - the only way to get rid of it is to run the command again with Show overlay unchecked.

delaunay_overlay

The issue remains because solving it properly is likely to require a few different things:

  • Providing access to all overlays within the GUI, allowing them to be turned on/off/deleted
  • Deciding on the most important Delaunay features to use
  • Designing an appropriate data structure to store Delaunay information (possibly in a way that can be serialized?)

It is also important to remove the overlay from the plugin itself, since this introduces a very unhealthy GUI dependency. Rather, a data structure to represent the Delaunay information ought to be defined in a core module, and then the overlay code kept separate within the GUI module.

Consideration also needs to be given to whether the calculations should be updated as objects are added/removed, or (more likely) not.

Viewers not removed from internal list after closing

When using multiple viewers, these are stored in an internal list, accessible with

QuPathGUI.getInstance().getViewers()

However, whenever viewers are closed and removed, they remain within the list - when the expectation is that they would be removed. It can be hard to distinguish between viewers that are 'still there' and ones that are not, but the following code does so:

def viewers = qupath.getViewers().collect() // Original list is unmodifiable... so collect
println("Number of viewers: " + viewers.size())

// Remove viewers that are unattached to any scene
viewers.removeAll { it.getView().getScene() == null }
println("Number of viewers attached to scene: " + viewers.size())

In any case, for most users and most uses of QuPath, this does not matter.

Nevertheless, it can cause trouble when scripting with multiple viewers and is a bug that should be fixed.

(Bug encountered and described here)

Setting symlinks for JEP (Fedora 24)

Hi,

I am trying to use python with QuPath via JEP, as per the docs. I am using linux (Fedora 24) and am having trouble locating the JEP directory to symlink, and also I am not sure from the docs exactly which directory to put the symlink in.

I've tried symlinking from the jep folder in the python installation site-packages directory, to the jars directory under qpath. I've also symlinked all the contents of the jep folder, including the jep-3.6.1.jar, into the QuPath/apps/jars directory. I still get 3 errors when I run the groovy script provided in the docs; they are just 'unable to resolve class jep.Jep', etc.

I appreciate your help, thanks.

OpenWebpageCommand hangs (Linux)

Using any of the web links within QuPath on Linux does not open a browser page or window and causes QuPath to hang indefinitely

Ubuntu 16.0.4, Oracle Java 1.8.0_121

Add several czi-file Images with 2 scenes each within a Project causes crash

allways when i load more than one czi image file in a project with the button "add images",
QuPath stopps working. It stopps in a modus that looks like that:
image

the only way out is exit via Taskmanager and restart of QuPath.

I figures out, that it allways crashes with the same czi file in the list. I might be able to share this file, if required to solve the issue.

Image reading issues on macOS - updated OpenSlide binaries required

There appears to be a problem reading some images (at least .mrxs images) on macOS.

This appears to trace back to the version of gdk-pixbuf currently included with the QuPath binaries on Mac. If I link to a more recent version (gdk-pixbuf 2.36) on my local machine the same images can be opened fine.

Therefore there is a need to update the OpenSlide binaries (including dependencies) that are distributed with QuPath.

Doing this in a transferable ways seems a fairly involved process, so it may take some time.

display >3 channels in fluorescence MRXS files

Hi,

we've scanned fluorescence slides in MRXS format. The scans have 4 color channels (DAPI, FITC, TRITC, Cy5). But when opened with Qupath, we can only access the first 3 (mislabeled as RGB).
I guess this is more an issue with openslide rather than Qupath, but I couldn't find any information about that on the openslide page and wanted to check.

Best regards,
Mario

Importing/Pregeneration Annotations..

We have a lot of annotations previously done using Aperio ScanScope which generate the XML files. We already have code that can parse those files and get out the boundaries for the various objects/layers....

We'd like to be able to compare analysis results done using QuPath with those we previously did in ScanScope, without having to redraw the annotations ...

If we had the boundaries of the shapes (lets just assume polygons for general use case), would it be possible to somehow import them and create an annotation layer we could use for analysis?

Require ability to sub-classify any detections according to intensity

Currently, Classify → Create detection classifier has the option to immediately sub-classify detections according to intensity - but only if these are classified as 'Tumor'.

This is a result of the original primary application of QuPath being in the scoring of biomarkers selectively within a tumor cell population (e.g. to calculate H-scores, or Ki67 labelling indices).

Currently, classifying (or sub-classifying) detections in a general way according to staining intensity is only possibly by writing a script to do so.

It would be helpful to be able to do so more easily, and in a scriptable manner (i.e. in a way that gets logged in the workflow).

Tiling with Overlay

Is there a way to tile the image like the scripting example in the wiki here but with the classification overlay or other cell features "burned in"?

Cell detection and tissue detection not compatible at same level of hierarchy

After detecting cells within each TMA core I then ran tissue detection on the same TMA cores.
It found all tissue areas but replaced all objects. I had thousands of objects per core (for each cell) and now there is one object per core (tissue).
I was able to do cell detection within the tissue detection annotation earlier, but then didn't have the core name in my output.
I will save each separately.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.