Skip to content

Commit

Permalink
Merge pull request #18 from petebankhead/fixes
Browse files Browse the repository at this point in the history
Bug fixes
  • Loading branch information
petebankhead committed Jun 9, 2022
2 parents f5842b4 + f03ea05 commit 727d893
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 7 deletions.
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ plugins {
// To create a shadow/fat jar, including dependencies
id 'com.github.johnrengelman.shadow' version '7.0.0'
// To manage included native libraries
id 'org.bytedeco.gradle-javacpp-platform' version '1.5.6'
id 'org.bytedeco.gradle-javacpp-platform' version '1.5.7'
}

repositories {
Expand All @@ -26,7 +26,7 @@ ext.moduleName = 'qupath.extension.stardist'

description = 'QuPath extension to use StarDist'

version = "0.3.0"
version = "0.3.1-SNAPSHOT"

dependencies {
def qupathVersion = "0.3.0" // For now
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
51 changes: 48 additions & 3 deletions src/main/java/qupath/ext/stardist/StarDist2D.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package qupath.ext.stardist;

import java.awt.image.BufferedImage;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
Expand Down Expand Up @@ -47,8 +48,10 @@
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryCollection;
import org.locationtech.jts.geom.Location;
import org.locationtech.jts.geom.Polygon;
import org.locationtech.jts.geom.util.GeometryFixer;
import org.locationtech.jts.index.strtree.STRtree;
import org.locationtech.jts.simplify.VWSimplifier;
import org.slf4j.Logger;
Expand Down Expand Up @@ -97,7 +100,7 @@
*
* @author Pete Bankhead (this implementation, but based on the others)
*/
public class StarDist2D {
public class StarDist2D implements AutoCloseable {

private final static Logger logger = LoggerFactory.getLogger(StarDist2D.class);

Expand Down Expand Up @@ -537,7 +540,7 @@ public Builder inputAdd(double... values) {
* @return this builder
*/
public Builder inputScale(double... values) {
this.ops.add(ImageOps.Core.subtract(values));
this.ops.add(ImageOps.Core.multiply(values));
return this;
}

Expand Down Expand Up @@ -921,11 +924,25 @@ private PathObject convertToObject(PotentialNucleus nucleus, ImagePlane plane, d
var geomNucleus = simplify(nucleus.geometry);
PathObject pathObject;
if (cellExpansion > 0) {
// cellExpansion = geomNucleus.getPrecisionModel().makePrecise(cellExpansion);
// cellExpansion = Math.round(cellExpansion);
var geomCell = CellTools.estimateCellBoundary(geomNucleus, cellExpansion, cellConstrainScale);
if (mask != null)
if (geomCell instanceof GeometryCollection && geomNucleus instanceof Polygon) {
if (!geomCell.isValid()) {
// Sometimes buffer creates invalid geometries
// (Note that the fix should already be applied by estimateCellBoundary in v0.4.0)
geomCell = GeometryFixer.fix(geomCell);
logger.debug("Used GeometryFixer to fix an invalid cell boundary geometry");
}
}
if (mask != null) {
geomCell = GeometryTools.attemptOperation(geomCell, g -> g.intersection(mask));
}
geomCell = simplify(geomCell);

// Intersection with complex mask could give linestrings - which we want to remove
geomCell = GeometryTools.ensurePolygonal(geomCell);

if (geomCell.isEmpty()) {
logger.warn("Empty cell boundary at {} will be skipped", nucleus.geometry.getCentroid());
return null;
Expand Down Expand Up @@ -1069,6 +1086,13 @@ private List<PotentialNucleus> detectObjectsForTile(ImageDataOp op, DnnModel<?>
requestPadded = RegionRequest.createInstance(server.getPath(), downsample, x1, y1, x2-x1, y2-y1);
}

// // Hack to visualize the tiles that are computed (for debugging)
// imageData.getHierarchy().addPathObject(
// PathObjects.createAnnotationObject(
// ROIs.createRectangleROI(request),
// PathClassFactory.getPathClass("Temporary")
// ));

try (@SuppressWarnings("unchecked")
var scope = new PointerScope()) {
Mat mat;
Expand Down Expand Up @@ -1350,6 +1374,11 @@ private List<PotentialNucleus> filterNuclei(List<PotentialNucleus> potentialNucl
if (envelope.intersects(env) && nucleus.geometry.intersects(nucleus2.geometry)) {
// Retain the nucleus only if it is not fragmented, or less than half its original area
var difference = nucleus2.geometry.difference(nucleus.geometry);

// Discard linestrings
if (difference instanceof GeometryCollection)
difference = GeometryTools.ensurePolygonal(difference);

if (difference instanceof Polygon && difference.getArea() > nucleus2.fullArea / 2.0)
nucleus2.geometry = difference;
else {
Expand Down Expand Up @@ -1406,5 +1435,21 @@ int getClassification() {
}

}


/**
* Close and cleanup resources.
*
* @implNote In practice, this means close any {@link DnnModel} stored if it is an instance of
* {@link Closeable} or {@link AutoCloseable}.
* This can be important to avoid memory leaks, particularly if using a GPU.
*/
@Override
public void close() throws Exception {
if (dnn instanceof Closeable) {
((Closeable) dnn).close();
} else if (dnn instanceof AutoCloseable)
((AutoCloseable) dnn).close();
}

}
2 changes: 1 addition & 1 deletion src/main/java/qupath/ext/stardist/StarDistExtension.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public String getDescription() {

@Override
public Version getQuPathVersion() {
return Version.parse("0.3.0-rc2");
return Version.parse("0.3.0");
}

@Override
Expand Down

0 comments on commit 727d893

Please sign in to comment.