From a699f501ed318428f41cd9a8ac467c0bfd15b226 Mon Sep 17 00:00:00 2001 From: lleplat Date: Wed, 11 Sep 2024 11:57:38 +0100 Subject: [PATCH 1/4] Select all members owner when all group selected --- .../ext/omero/gui/browser/serverbrowser/Browser.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/qupath/ext/omero/gui/browser/serverbrowser/Browser.java b/src/main/java/qupath/ext/omero/gui/browser/serverbrowser/Browser.java index fe00515..74b941f 100644 --- a/src/main/java/qupath/ext/omero/gui/browser/serverbrowser/Browser.java +++ b/src/main/java/qupath/ext/omero/gui/browser/serverbrowser/Browser.java @@ -369,7 +369,8 @@ public PixelAPI fromString(String string) { } else { owner.getItems().addAll(group.getSelectionModel().getSelectedItem().getOwners()); } - owner.getSelectionModel().select(client.getServer().getDefaultOwner().orElse(Owner.getAllMembersOwner()));owner.setConverter(new StringConverter<>() { + owner.getSelectionModel().select(client.getServer().getDefaultOwner().orElse(Owner.getAllMembersOwner())); + owner.setConverter(new StringConverter<>() { @Override public String toString(Owner object) { return object == null ? "" : object.getFullName(); @@ -475,15 +476,17 @@ private void setUpListeners() { browserModel.getSelectedGroup().addListener((p, o, n) -> { owner.getItems().clear(); - if (n != null) { + if (n == null) { + owner.getSelectionModel().select(null); + } else { if (n.equals(Group.getAllGroupsGroup())) { owner.getItems().addAll(client.getServer().getOwners()); + owner.getSelectionModel().select(Owner.getAllMembersOwner()); } else { owner.getItems().addAll(n.getOwners()); + owner.getSelectionModel().selectFirst(); } } - - owner.getSelectionModel().selectFirst(); }); browserModel.getSelectedGroup().bind(group.getSelectionModel().selectedItemProperty()); browserModel.getSelectedOwner().bind(owner.getSelectionModel().selectedItemProperty()); From f2ae91b3f55b5aaee8f0d5837a07442aac5c06ab Mon Sep 17 00:00:00 2001 From: lleplat Date: Wed, 11 Sep 2024 12:00:02 +0100 Subject: [PATCH 2/4] Thumbnail not found fix --- src/main/java/qupath/ext/omero/core/apis/ApisHandler.java | 4 ++-- .../java/qupath/ext/omero/core/apis/WebGatewayApi.java | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/java/qupath/ext/omero/core/apis/ApisHandler.java b/src/main/java/qupath/ext/omero/core/apis/ApisHandler.java index 418eb4a..206fbb5 100644 --- a/src/main/java/qupath/ext/omero/core/apis/ApisHandler.java +++ b/src/main/java/qupath/ext/omero/core/apis/ApisHandler.java @@ -502,7 +502,7 @@ public CompletableFuture> getThumbnail(long id) { } /** - * See {@link WebGatewayApi#getThumbnail(long, int)}. + * See {@link WebGatewayApi#getThumbnail(long)}. * Thumbnails are cached in a cache of size {@link #THUMBNAIL_CACHE_SIZE}. */ public CompletableFuture> getThumbnail(long id, int size) { @@ -510,7 +510,7 @@ public CompletableFuture> getThumbnail(long id, int size IdSizeWrapper key = new IdSizeWrapper(id, size); CompletableFuture> request = thumbnailsCache.get( key, - () -> webGatewayApi.getThumbnail(id, size) + () -> webGatewayApi.getThumbnail(id) ); request.thenAccept(response -> { diff --git a/src/main/java/qupath/ext/omero/core/apis/WebGatewayApi.java b/src/main/java/qupath/ext/omero/core/apis/WebGatewayApi.java index 6febd18..72d8e72 100644 --- a/src/main/java/qupath/ext/omero/core/apis/WebGatewayApi.java +++ b/src/main/java/qupath/ext/omero/core/apis/WebGatewayApi.java @@ -37,7 +37,7 @@ class WebGatewayApi { private static final String PROJECT_ICON_NAME = "folder16.png"; private static final String DATASET_ICON_NAME = "folder_image16.png"; private static final String ORPHANED_FOLDER_ICON_NAME = "folder_yellow16.png"; - private static final String THUMBNAIL_URL = "%s/webgateway/render_thumbnail/%d/%d"; + private static final String THUMBNAIL_URL = "%s/webgateway/render_thumbnail/%d"; private static final String IMAGE_DATA_URL = "%s/webgateway/imgData/%d"; private static final String TILE_URL = "%s/webgateway/render_image_region/%d/%d/%d/?" + "tile=%d,%d,%d,%d,%d" + @@ -110,13 +110,12 @@ public CompletableFuture> getOrphanedFolderIcon() { *

This function is asynchronous.

* * @param id the OMERO image ID - * @param size the max width and max height the thumbnail should have * @return a CompletableFuture with the thumbnail, or an empty Optional if an error occurred */ - public CompletableFuture> getThumbnail(long id, int size) { + public CompletableFuture> getThumbnail(long id) { changeNumberOfThumbnailsLoading(true); - return ApiUtilities.getImage(String.format(THUMBNAIL_URL, host, id, size)).thenApply(thumbnail -> { + return ApiUtilities.getImage(String.format(THUMBNAIL_URL, host, id)).thenApply(thumbnail -> { changeNumberOfThumbnailsLoading(false); return thumbnail; }); From ed297c8ad63557c0575984cd2dbf8a0f86752a22 Mon Sep 17 00:00:00 2001 From: lleplat Date: Wed, 11 Sep 2024 13:47:37 +0100 Subject: [PATCH 3/4] Fixed tests --- .../ext/omero/core/apis/ApisHandler.java | 19 ++++------------ .../core/imageserver/OmeroImageServer.java | 22 ------------------- .../connectionsmanager/connection/Image.java | 2 +- .../ext/omero/core/apis/TestApisHandler.java | 11 ---------- .../omero-web/installPixelBufferMs.sh | 5 +++++ src/test/resources/server.sh | 1 + 6 files changed, 11 insertions(+), 49 deletions(-) diff --git a/src/main/java/qupath/ext/omero/core/apis/ApisHandler.java b/src/main/java/qupath/ext/omero/core/apis/ApisHandler.java index 206fbb5..b62c501 100644 --- a/src/main/java/qupath/ext/omero/core/apis/ApisHandler.java +++ b/src/main/java/qupath/ext/omero/core/apis/ApisHandler.java @@ -49,7 +49,6 @@ public class ApisHandler implements AutoCloseable { private static final Logger logger = LoggerFactory.getLogger(ApisHandler.class); - private static final int THUMBNAIL_SIZE = 256; private static final int THUMBNAIL_CACHE_SIZE = 1000; private static final Map PIXEL_TYPE_MAP = Map.of( "uint8", PixelType.UINT8, @@ -67,12 +66,11 @@ public class ApisHandler implements AutoCloseable { private final WebGatewayApi webGatewayApi; private final IViewerApi iViewerApi; private final BooleanProperty areOrphanedImagesLoading = new SimpleBooleanProperty(false); - private final Cache>> thumbnailsCache = CacheBuilder.newBuilder() + private final Cache>> thumbnailsCache = CacheBuilder.newBuilder() .maximumSize(THUMBNAIL_CACHE_SIZE) .build(); private final Map, BufferedImage> omeroIconsCache = new ConcurrentHashMap<>(); private final boolean canSkipAuthentication; - private record IdSizeWrapper(long id, int size) {} private ApisHandler(URI host, JsonApi jsonApi, boolean canSkipAuthentication) { this.host = host; @@ -493,29 +491,20 @@ public CompletableFuture> getOmeroIcon(Class> getThumbnail(long id) { - return getThumbnail(id, THUMBNAIL_SIZE); - } - /** * See {@link WebGatewayApi#getThumbnail(long)}. * Thumbnails are cached in a cache of size {@link #THUMBNAIL_CACHE_SIZE}. */ - public CompletableFuture> getThumbnail(long id, int size) { + public CompletableFuture> getThumbnail(long id) { try { - IdSizeWrapper key = new IdSizeWrapper(id, size); CompletableFuture> request = thumbnailsCache.get( - key, + id, () -> webGatewayApi.getThumbnail(id) ); request.thenAccept(response -> { if (response.isEmpty()) { - thumbnailsCache.invalidate(key); + thumbnailsCache.invalidate(id); } }); return request; diff --git a/src/main/java/qupath/ext/omero/core/imageserver/OmeroImageServer.java b/src/main/java/qupath/ext/omero/core/imageserver/OmeroImageServer.java index b6d3e7e..48bf7a8 100644 --- a/src/main/java/qupath/ext/omero/core/imageserver/OmeroImageServer.java +++ b/src/main/java/qupath/ext/omero/core/imageserver/OmeroImageServer.java @@ -140,28 +140,6 @@ protected BufferedImage readTile(TileRequest tileRequest) throws IOException { return pixelAPIReader.readTile(tileRequest); } - @Override - public BufferedImage getDefaultThumbnail(int z, int t) throws IOException { - Optional thumbnail = Optional.empty(); - - if (isRGB()) { - try { - thumbnail = client.getApisHandler().getThumbnail( - id, - Math.max(originalMetadata.getLevel(0).getWidth(), originalMetadata.getLevel(0).getHeight()) - ).get(); - } catch (InterruptedException | ExecutionException e) { - throw new IOException(e); - } - } - - if (thumbnail.isPresent()) { - return thumbnail.get(); - } else { - return super.getDefaultThumbnail(z, t); - } - } - @Override protected ImageServerBuilder.ServerBuilder createServerBuilder() { return ImageServerBuilder.DefaultImageServerBuilder.createInstance( diff --git a/src/main/java/qupath/ext/omero/gui/connectionsmanager/connection/Image.java b/src/main/java/qupath/ext/omero/gui/connectionsmanager/connection/Image.java index 3b1c5ca..e6f407d 100644 --- a/src/main/java/qupath/ext/omero/gui/connectionsmanager/connection/Image.java +++ b/src/main/java/qupath/ext/omero/gui/connectionsmanager/connection/Image.java @@ -42,7 +42,7 @@ public Image(WebClient client, URI imageUri) throws IOException { image.ifPresent(value -> name.setText(value.getLabel().get())) )); - client.getApisHandler().getThumbnail(imageID.getAsLong(), (int) thumbnail.getWidth()).thenAccept(thumbnail -> Platform.runLater(() -> + client.getApisHandler().getThumbnail(imageID.getAsLong()).thenAccept(thumbnail -> Platform.runLater(() -> thumbnail.ifPresent(bufferedImage -> UiUtilities.paintBufferedImageOnCanvas(bufferedImage, this.thumbnail)) )); } diff --git a/src/test/java/qupath/ext/omero/core/apis/TestApisHandler.java b/src/test/java/qupath/ext/omero/core/apis/TestApisHandler.java index 7149340..31ebb2f 100644 --- a/src/test/java/qupath/ext/omero/core/apis/TestApisHandler.java +++ b/src/test/java/qupath/ext/omero/core/apis/TestApisHandler.java @@ -540,17 +540,6 @@ void Check_Image_Thumbnail() throws ExecutionException, InterruptedException { Assertions.assertNotNull(image); } - @Test - void Check_Image_Thumbnail_With_Specific_Size() throws ExecutionException, InterruptedException { - long imageId = OmeroServer.getComplexImage().getId(); - int size = 30; - - BufferedImage image = apisHandler.getThumbnail(imageId, size).get().orElse(null); - - Assertions.assertNotNull(image); - Assertions.assertEquals(size, Math.max(image.getWidth(), image.getHeight())); - } - @Test void Check_Image_Thumbnail_With_Invalid_Image_ID() throws ExecutionException, InterruptedException { long invalidImageID = -1; diff --git a/src/test/resources/omero-web/installPixelBufferMs.sh b/src/test/resources/omero-web/installPixelBufferMs.sh index 78bc88d..e0acb5e 100755 --- a/src/test/resources/omero-web/installPixelBufferMs.sh +++ b/src/test/resources/omero-web/installPixelBufferMs.sh @@ -5,6 +5,11 @@ cd / tar -xvkf /tmp/OMERO.tar.gz +# See https://stackoverflow.com/a/78693402 +# This should be needed as long as the base image is the deprecated CentOS7 +sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-* +sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-* + # Build the pixel buffer microservice yum install git java-devel -y git clone https://github.com/glencoesoftware/omero-ms-pixel-buffer diff --git a/src/test/resources/server.sh b/src/test/resources/server.sh index ac60869..c4f6ed0 100755 --- a/src/test/resources/server.sh +++ b/src/test/resources/server.sh @@ -40,6 +40,7 @@ docker run -d \ -e ROOTPASS=password \ -p 4064:4064 \ --privileged \ + --platform linux/x86_64 \ --mount type=bind,src=$SCRIPT_DIR"/omero-server",target=/resources \ openmicroscopy/omero-server From 87702d49f7207e20b003008ff96c6564bb000325 Mon Sep 17 00:00:00 2001 From: lleplat Date: Thu, 12 Sep 2024 09:39:57 +0100 Subject: [PATCH 4/4] Thumbnail size --- .../ext/omero/core/apis/ApisHandler.java | 23 ++++++++++++++----- .../ext/omero/core/apis/WebGatewayApi.java | 7 +++--- .../core/imageserver/OmeroImageServer.java | 22 ++++++++++++++++++ .../connectionsmanager/connection/Image.java | 2 +- .../ext/omero/core/apis/TestApisHandler.java | 11 +++++++++ 5 files changed, 55 insertions(+), 10 deletions(-) diff --git a/src/main/java/qupath/ext/omero/core/apis/ApisHandler.java b/src/main/java/qupath/ext/omero/core/apis/ApisHandler.java index b62c501..418eb4a 100644 --- a/src/main/java/qupath/ext/omero/core/apis/ApisHandler.java +++ b/src/main/java/qupath/ext/omero/core/apis/ApisHandler.java @@ -49,6 +49,7 @@ public class ApisHandler implements AutoCloseable { private static final Logger logger = LoggerFactory.getLogger(ApisHandler.class); + private static final int THUMBNAIL_SIZE = 256; private static final int THUMBNAIL_CACHE_SIZE = 1000; private static final Map PIXEL_TYPE_MAP = Map.of( "uint8", PixelType.UINT8, @@ -66,11 +67,12 @@ public class ApisHandler implements AutoCloseable { private final WebGatewayApi webGatewayApi; private final IViewerApi iViewerApi; private final BooleanProperty areOrphanedImagesLoading = new SimpleBooleanProperty(false); - private final Cache>> thumbnailsCache = CacheBuilder.newBuilder() + private final Cache>> thumbnailsCache = CacheBuilder.newBuilder() .maximumSize(THUMBNAIL_CACHE_SIZE) .build(); private final Map, BufferedImage> omeroIconsCache = new ConcurrentHashMap<>(); private final boolean canSkipAuthentication; + private record IdSizeWrapper(long id, int size) {} private ApisHandler(URI host, JsonApi jsonApi, boolean canSkipAuthentication) { this.host = host; @@ -492,19 +494,28 @@ public CompletableFuture> getOmeroIcon(Class> getThumbnail(long id) { + return getThumbnail(id, THUMBNAIL_SIZE); + } + + /** + * See {@link WebGatewayApi#getThumbnail(long, int)}. + * Thumbnails are cached in a cache of size {@link #THUMBNAIL_CACHE_SIZE}. + */ + public CompletableFuture> getThumbnail(long id, int size) { try { + IdSizeWrapper key = new IdSizeWrapper(id, size); CompletableFuture> request = thumbnailsCache.get( - id, - () -> webGatewayApi.getThumbnail(id) + key, + () -> webGatewayApi.getThumbnail(id, size) ); request.thenAccept(response -> { if (response.isEmpty()) { - thumbnailsCache.invalidate(id); + thumbnailsCache.invalidate(key); } }); return request; diff --git a/src/main/java/qupath/ext/omero/core/apis/WebGatewayApi.java b/src/main/java/qupath/ext/omero/core/apis/WebGatewayApi.java index 72d8e72..14c980a 100644 --- a/src/main/java/qupath/ext/omero/core/apis/WebGatewayApi.java +++ b/src/main/java/qupath/ext/omero/core/apis/WebGatewayApi.java @@ -37,7 +37,7 @@ class WebGatewayApi { private static final String PROJECT_ICON_NAME = "folder16.png"; private static final String DATASET_ICON_NAME = "folder_image16.png"; private static final String ORPHANED_FOLDER_ICON_NAME = "folder_yellow16.png"; - private static final String THUMBNAIL_URL = "%s/webgateway/render_thumbnail/%d"; + private static final String THUMBNAIL_URL = "%s/webgateway/render_thumbnail/%d/%d"; private static final String IMAGE_DATA_URL = "%s/webgateway/imgData/%d"; private static final String TILE_URL = "%s/webgateway/render_image_region/%d/%d/%d/?" + "tile=%d,%d,%d,%d,%d" + @@ -110,12 +110,13 @@ public CompletableFuture> getOrphanedFolderIcon() { *

This function is asynchronous.

* * @param id the OMERO image ID + * @param size the max width and max height the thumbnail should have * @return a CompletableFuture with the thumbnail, or an empty Optional if an error occurred */ - public CompletableFuture> getThumbnail(long id) { + public CompletableFuture> getThumbnail(long id, int size) { changeNumberOfThumbnailsLoading(true); - return ApiUtilities.getImage(String.format(THUMBNAIL_URL, host, id)).thenApply(thumbnail -> { + return ApiUtilities.getImage(String.format(THUMBNAIL_URL, host, id, size)).thenApply(thumbnail -> { changeNumberOfThumbnailsLoading(false); return thumbnail; }); diff --git a/src/main/java/qupath/ext/omero/core/imageserver/OmeroImageServer.java b/src/main/java/qupath/ext/omero/core/imageserver/OmeroImageServer.java index 48bf7a8..b6d3e7e 100644 --- a/src/main/java/qupath/ext/omero/core/imageserver/OmeroImageServer.java +++ b/src/main/java/qupath/ext/omero/core/imageserver/OmeroImageServer.java @@ -140,6 +140,28 @@ protected BufferedImage readTile(TileRequest tileRequest) throws IOException { return pixelAPIReader.readTile(tileRequest); } + @Override + public BufferedImage getDefaultThumbnail(int z, int t) throws IOException { + Optional thumbnail = Optional.empty(); + + if (isRGB()) { + try { + thumbnail = client.getApisHandler().getThumbnail( + id, + Math.max(originalMetadata.getLevel(0).getWidth(), originalMetadata.getLevel(0).getHeight()) + ).get(); + } catch (InterruptedException | ExecutionException e) { + throw new IOException(e); + } + } + + if (thumbnail.isPresent()) { + return thumbnail.get(); + } else { + return super.getDefaultThumbnail(z, t); + } + } + @Override protected ImageServerBuilder.ServerBuilder createServerBuilder() { return ImageServerBuilder.DefaultImageServerBuilder.createInstance( diff --git a/src/main/java/qupath/ext/omero/gui/connectionsmanager/connection/Image.java b/src/main/java/qupath/ext/omero/gui/connectionsmanager/connection/Image.java index e6f407d..3b1c5ca 100644 --- a/src/main/java/qupath/ext/omero/gui/connectionsmanager/connection/Image.java +++ b/src/main/java/qupath/ext/omero/gui/connectionsmanager/connection/Image.java @@ -42,7 +42,7 @@ public Image(WebClient client, URI imageUri) throws IOException { image.ifPresent(value -> name.setText(value.getLabel().get())) )); - client.getApisHandler().getThumbnail(imageID.getAsLong()).thenAccept(thumbnail -> Platform.runLater(() -> + client.getApisHandler().getThumbnail(imageID.getAsLong(), (int) thumbnail.getWidth()).thenAccept(thumbnail -> Platform.runLater(() -> thumbnail.ifPresent(bufferedImage -> UiUtilities.paintBufferedImageOnCanvas(bufferedImage, this.thumbnail)) )); } diff --git a/src/test/java/qupath/ext/omero/core/apis/TestApisHandler.java b/src/test/java/qupath/ext/omero/core/apis/TestApisHandler.java index 31ebb2f..7149340 100644 --- a/src/test/java/qupath/ext/omero/core/apis/TestApisHandler.java +++ b/src/test/java/qupath/ext/omero/core/apis/TestApisHandler.java @@ -540,6 +540,17 @@ void Check_Image_Thumbnail() throws ExecutionException, InterruptedException { Assertions.assertNotNull(image); } + @Test + void Check_Image_Thumbnail_With_Specific_Size() throws ExecutionException, InterruptedException { + long imageId = OmeroServer.getComplexImage().getId(); + int size = 30; + + BufferedImage image = apisHandler.getThumbnail(imageId, size).get().orElse(null); + + Assertions.assertNotNull(image); + Assertions.assertEquals(size, Math.max(image.getWidth(), image.getHeight())); + } + @Test void Check_Image_Thumbnail_With_Invalid_Image_ID() throws ExecutionException, InterruptedException { long invalidImageID = -1;