From 0637cc62c8aa2c1a654ba5ff5f3a85d91d4dfb2b Mon Sep 17 00:00:00 2001 From: Pete Date: Mon, 9 Sep 2024 12:24:08 +0100 Subject: [PATCH 1/2] Add tile padding as an option --- .../ext/instanseg/ui/InstanSegController.java | 10 +++++++++- .../ext/instanseg/ui/InstanSegPreferences.java | 8 ++++++++ .../qupath/ext/instanseg/ui/InstanSegTask.java | 14 ++++++++++---- .../qupath/ext/instanseg/ui/instanseg_control.fxml | 14 ++++++++++++++ .../qupath/ext/instanseg/ui/strings.properties | 2 ++ 5 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/main/java/qupath/ext/instanseg/ui/InstanSegController.java b/src/main/java/qupath/ext/instanseg/ui/InstanSegController.java index 5847a34..381492d 100644 --- a/src/main/java/qupath/ext/instanseg/ui/InstanSegController.java +++ b/src/main/java/qupath/ext/instanseg/ui/InstanSegController.java @@ -88,6 +88,8 @@ public class InstanSegController extends BorderPane { @FXML private ChoiceBox tileSizeChoiceBox; @FXML + private ChoiceBox tilePaddingChoiceBox; + @FXML private Spinner threadSpinner; @FXML private ToggleButton selectAllAnnotationsButton; @@ -173,6 +175,7 @@ private InstanSegController(QuPathGUI qupath) throws IOException { // Options configureTileSizes(); + configureTilePadding(); configureDeviceChoices(); configureThreadSpinner(); configureInputChannelCombo(); @@ -590,13 +593,18 @@ private static List getRemoteModels() { return List.copyOf(models); } + private void configureTilePadding() { + tilePaddingChoiceBox.getItems().addAll(16, 32, 48, 64, 80, 96); + tilePaddingChoiceBox.setValue(InstanSegPreferences.tilePaddingProperty().getValue()); + tilePaddingChoiceBox.valueProperty().addListener((v, o, n) -> InstanSegPreferences.tilePaddingProperty().set(n)); + } + private void configureTileSizes() { // The use of 32-bit signed ints for coordinates of the intermediate sparse matrix *might* be // an issue for very large tile sizes - but I haven't seen any evidence of this. // We definitely can't have very small tiles, because they must be greater than 2 x the padding. tileSizeChoiceBox.getItems().addAll(256, 512, 1024, 2048); - tileSizeChoiceBox.getSelectionModel().select(Integer.valueOf(512)); tileSizeChoiceBox.setValue(InstanSegPreferences.tileSizeProperty().getValue()); tileSizeChoiceBox.valueProperty().addListener((v, o, n) -> InstanSegPreferences.tileSizeProperty().set(n)); } diff --git a/src/main/java/qupath/ext/instanseg/ui/InstanSegPreferences.java b/src/main/java/qupath/ext/instanseg/ui/InstanSegPreferences.java index 8456a0d..d24149f 100644 --- a/src/main/java/qupath/ext/instanseg/ui/InstanSegPreferences.java +++ b/src/main/java/qupath/ext/instanseg/ui/InstanSegPreferences.java @@ -41,6 +41,10 @@ enum OnlinePermission { "intanseg.tile.size", 512); + private static final IntegerProperty tilePaddingProperty = PathPrefs.createPersistentPreference( + "intanseg.tile.padding", + 32); + private static final BooleanProperty makeMeasurementsProperty = PathPrefs.createPersistentPreference( "intanseg.measurements", true); @@ -82,6 +86,10 @@ static IntegerProperty tileSizeProperty() { return tileSizeProperty; } + static IntegerProperty tilePaddingProperty() { + return tilePaddingProperty; + } + static BooleanProperty makeMeasurementsProperty() { return makeMeasurementsProperty; } diff --git a/src/main/java/qupath/ext/instanseg/ui/InstanSegTask.java b/src/main/java/qupath/ext/instanseg/ui/InstanSegTask.java index 18e31f5..f7952cf 100644 --- a/src/main/java/qupath/ext/instanseg/ui/InstanSegTask.java +++ b/src/main/java/qupath/ext/instanseg/ui/InstanSegTask.java @@ -48,9 +48,10 @@ class InstanSegTask extends Task { @Override protected Void call() { + int nThreads = InstanSegPreferences.numThreadsProperty().get(); var taskRunner = new TaskRunnerFX( QuPathGUI.getInstance(), - InstanSegPreferences.numThreadsProperty().getValue()); + nThreads); var selectedObjects = imageData.getHierarchy().getSelectionModel().getSelectedObjects(); Optional path = model.getPath(); @@ -69,13 +70,16 @@ protected Void call() { if (nChecked > 0 && nChecked < nOutputs) { outputChannels = this.outputChannels.stream().mapToInt(Integer::intValue).toArray(); } + int tileSize = InstanSegPreferences.tileSizeProperty().get(); + int tilePadding = InstanSegPreferences.tilePaddingProperty().get(); var instanSeg = InstanSeg.builder() .model(model) .device(device) .inputChannels(channels.stream().map(InputChannelItem::getTransform).toList()) .outputChannels(outputChannels) - .tileDims(InstanSegPreferences.tileSizeProperty().get()) + .tileDims(tileSize) + .interTilePadding(tilePadding) .taskRunner(taskRunner) .makeMeasurements(makeMeasurements) .randomColors(randomColors) @@ -88,6 +92,7 @@ protected Void call() { .%s .outputChannels(%s) .tileDims(%d) + .interTilePadding(%d) .nThreads(%d) .makeMeasurements(%s) .randomColors(%s) @@ -100,8 +105,9 @@ protected Void call() { outputChannels.length == 0 ? "" : Arrays.stream(outputChannels) .mapToObj(Integer::toString) .collect(Collectors.joining(", ")), - InstanSegPreferences.tileSizeProperty().get(), - InstanSegPreferences.numThreadsProperty().getValue(), + tileSize, + tilePadding, + nThreads, makeMeasurements, randomColors ).strip(); diff --git a/src/main/resources/qupath/ext/instanseg/ui/instanseg_control.fxml b/src/main/resources/qupath/ext/instanseg/ui/instanseg_control.fxml index a33ed0f..e9ceb34 100644 --- a/src/main/resources/qupath/ext/instanseg/ui/instanseg_control.fxml +++ b/src/main/resources/qupath/ext/instanseg/ui/instanseg_control.fxml @@ -176,6 +176,20 @@ + + + + + + + diff --git a/src/main/resources/qupath/ext/instanseg/ui/strings.properties b/src/main/resources/qupath/ext/instanseg/ui/strings.properties index c6523f3..59506e0 100644 --- a/src/main/resources/qupath/ext/instanseg/ui/strings.properties +++ b/src/main/resources/qupath/ext/instanseg/ui/strings.properties @@ -56,6 +56,8 @@ ui.options.threads = Threads ui.options.threads.tooltip = Define the preferred number of threads ui.options.tilesize = Tile size ui.options.tilesize.tooltip = Define the approximate tile size +ui.options.tileboundary = Tile padding +ui.options.tileboundary.tooltip = Define how much padding to add on tile boundaries.\nSmaller values can make processing faster, but may cause objects to be split or broken at tile boundaries. ui.options.input-channels = Input channels ui.options.input-channels.tooltip = Define the set of channels to be used in inference ui.options.makeMeasurements = Make measurements From 6bd3f0cd9e1322bce7694f250db326ff23298e71 Mon Sep 17 00:00:00 2001 From: Pete Date: Mon, 9 Sep 2024 13:00:26 +0100 Subject: [PATCH 2/2] Tooltips, cloud icon, output channel fix --- .../ext/instanseg/ui/InstanSegController.java | 2 +- .../ext/instanseg/ui/ModelListCell.java | 3 +- .../ext/instanseg/ui/instanseg_control.fxml | 39 +++++++++++++++---- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/src/main/java/qupath/ext/instanseg/ui/InstanSegController.java b/src/main/java/qupath/ext/instanseg/ui/InstanSegController.java index 381492d..31bd585 100644 --- a/src/main/java/qupath/ext/instanseg/ui/InstanSegController.java +++ b/src/main/java/qupath/ext/instanseg/ui/InstanSegController.java @@ -458,7 +458,7 @@ private void refreshModelChoice() { var nOutputs = model.getOutputChannels().orElse(1); comboOutputChannels.getCheckModel().clearChecks(); comboOutputChannels.getItems().setAll(OutputChannelItem.getOutputsForChannelCount(nOutputs)); - if (!outputChannelCache.restoreChecks()) { + if (!outputChannelCache.restoreChecks() || comboOutputChannels.getCheckModel().isEmpty()) { comboOutputChannels.getCheckModel().checkAll(); } } diff --git a/src/main/java/qupath/ext/instanseg/ui/ModelListCell.java b/src/main/java/qupath/ext/instanseg/ui/ModelListCell.java index b4743da..0d896d8 100644 --- a/src/main/java/qupath/ext/instanseg/ui/ModelListCell.java +++ b/src/main/java/qupath/ext/instanseg/ui/ModelListCell.java @@ -1,5 +1,6 @@ package qupath.ext.instanseg.ui; +import javafx.scene.control.ContentDisplay; import javafx.scene.control.ListCell; import javafx.scene.control.Tooltip; import org.controlsfx.glyphfont.FontAwesome; @@ -46,7 +47,7 @@ public void updateItem(InstanSegModel model, boolean empty) { private Glyph createOnlineIcon() { GlyphFont fontAwesome = GlyphFontRegistry.font("FontAwesome"); - return fontAwesome.create(FontAwesome.Glyph.DOWNLOAD); + return fontAwesome.create(FontAwesome.Glyph.CLOUD); } } diff --git a/src/main/resources/qupath/ext/instanseg/ui/instanseg_control.fxml b/src/main/resources/qupath/ext/instanseg/ui/instanseg_control.fxml index e9ceb34..6d52673 100644 --- a/src/main/resources/qupath/ext/instanseg/ui/instanseg_control.fxml +++ b/src/main/resources/qupath/ext/instanseg/ui/instanseg_control.fxml @@ -136,7 +136,10 @@ -