Search in sources :

Example 1 with ImageServer

use of qupath.lib.images.servers.ImageServer in project qupath by qupath.

the class ContourTracing method traceGeometriesImpl.

private static List<GeometryWrapper> traceGeometriesImpl(ImageServer<BufferedImage> server, TileRequest tile, Geometry clipArea, ChannelThreshold... thresholds) throws IOException {
    if (thresholds.length == 0)
        return Collections.emptyList();
    var request = tile.getRegionRequest();
    var list = new ArrayList<GeometryWrapper>();
    var img = server.readBufferedImage(request);
    // Get an image to threshold
    var channelType = server.getMetadata().getChannelType();
    int h = img.getHeight();
    int w = img.getWidth();
    // If we have probabilities, then the 'true' classification is the one with the highest values.
    // If we have classifications, then the 'true' classification is the value of the pixel (which is expected to have a single band).
    boolean doClassification = channelType == ImageServerMetadata.ChannelType.PROBABILITY || channelType == ImageServerMetadata.ChannelType.CLASSIFICATION;
    if (doClassification) {
        SimpleImage image;
        if (channelType == ImageServerMetadata.ChannelType.PROBABILITY) {
            // Convert probabilities to classifications
            var raster = img.getRaster();
            var nChannels = server.nChannels();
            float[] output = new float[w * h];
            for (int y = 0; y < h; y++) {
                for (int x = 0; x < w; x++) {
                    int maxInd = 0;
                    float maxVal = raster.getSampleFloat(x, y, 0);
                    for (int c = 1; c < nChannels; c++) {
                        float val = raster.getSampleFloat(x, y, c);
                        if (val > maxVal) {
                            maxInd = c;
                            maxVal = val;
                        }
                        output[y * w + x] = (float) maxInd;
                    }
                }
            }
            image = SimpleImages.createFloatImage(output, w, h);
        } else {
            // Handle classifications
            var raster = img.getRaster();
            var pixels = raster.getSamples(0, 0, w, h, 0, (float[]) null);
            image = SimpleImages.createFloatImage(pixels, w, h);
        }
        for (var threshold : thresholds) {
            int c = threshold.getChannel();
            Geometry geometry = ContourTracing.createTracedGeometry(image, c, c, tile);
            if (geometry != null && !geometry.isEmpty()) {
                if (clipArea != null) {
                    geometry = GeometryTools.attemptOperation(geometry, g -> g.intersection(clipArea));
                    geometry = GeometryTools.homogenizeGeometryCollection(geometry);
                }
                if (!geometry.isEmpty() && geometry.getArea() > 0) {
                    // Exclude lines/points that can sometimes arise
                    list.add(new GeometryWrapper(geometry, c));
                }
            }
        }
    } else {
        // Apply the provided threshold to all channels
        var raster = img.getRaster();
        for (var threshold : thresholds) {
            Geometry geometry = ContourTracing.createTracedGeometry(raster, threshold.getMinThreshold(), threshold.getMaxThreshold(), threshold.getChannel(), tile);
            if (geometry != null) {
                if (clipArea != null) {
                    geometry = GeometryTools.attemptOperation(geometry, g -> g.intersection(clipArea));
                    geometry = GeometryTools.homogenizeGeometryCollection(geometry);
                }
                if (!geometry.isEmpty() && geometry.getArea() > 0) {
                    // Exclude lines/points that can sometimes arise
                    list.add(new GeometryWrapper(geometry, threshold.getChannel()));
                }
            }
        }
    }
    return list;
}
Also used : Geometry(org.locationtech.jts.geom.Geometry) ImageServer(qupath.lib.images.servers.ImageServer) BiFunction(java.util.function.BiFunction) LoggerFactory(org.slf4j.LoggerFactory) Coordinate(org.locationtech.jts.geom.Coordinate) Future(java.util.concurrent.Future) Map(java.util.Map) ImageIO(javax.imageio.ImageIO) ImageServers(qupath.lib.images.servers.ImageServers) Path(java.nio.file.Path) BufferedImage(java.awt.image.BufferedImage) Collection(java.util.Collection) PathObjects(qupath.lib.objects.PathObjects) Quadtree(org.locationtech.jts.index.quadtree.Quadtree) Collectors(java.util.stream.Collectors) Executors(java.util.concurrent.Executors) PathObject(qupath.lib.objects.PathObject) Objects(java.util.Objects) List(java.util.List) Stream(java.util.stream.Stream) Polygon(org.locationtech.jts.geom.Polygon) ImagePlane(qupath.lib.regions.ImagePlane) Geometry(org.locationtech.jts.geom.Geometry) ThreadTools(qupath.lib.common.ThreadTools) Pattern(java.util.regex.Pattern) PolygonExtracter(org.locationtech.jts.geom.util.PolygonExtracter) Deque(java.util.Deque) Function(java.util.function.Function) TreeSet(java.util.TreeSet) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) Raster(java.awt.image.Raster) BiConsumer(java.util.function.BiConsumer) TileRequest(qupath.lib.images.servers.TileRequest) GeometryTools(qupath.lib.roi.GeometryTools) AffineTransformation(org.locationtech.jts.geom.util.AffineTransformation) ExecutorService(java.util.concurrent.ExecutorService) GeometryFactory(org.locationtech.jts.geom.GeometryFactory) Logger(org.slf4j.Logger) GeneralTools(qupath.lib.common.GeneralTools) RegionRequest(qupath.lib.regions.RegionRequest) IOException(java.io.IOException) PathObjectTools(qupath.lib.objects.PathObjectTools) ExecutionException(java.util.concurrent.ExecutionException) ROI(qupath.lib.roi.interfaces.ROI) LineString(org.locationtech.jts.geom.LineString) TreeMap(java.util.TreeMap) Polygonizer(org.locationtech.jts.operation.polygonize.Polygonizer) ArrayDeque(java.util.ArrayDeque) Collections(java.util.Collections) Envelope(org.locationtech.jts.geom.Envelope) ImageServerMetadata(qupath.lib.images.servers.ImageServerMetadata) ArrayList(java.util.ArrayList)

Example 2 with ImageServer

use of qupath.lib.images.servers.ImageServer in project qupath by qupath.

the class ContourTracing method traceGeometriesImpl.

@SuppressWarnings("unchecked")
private static Map<Integer, Geometry> traceGeometriesImpl(ImageServer<BufferedImage> server, Collection<TileRequest> tiles, Geometry clipArea, ChannelThreshold... thresholds) throws IOException {
    if (thresholds.length == 0)
        return Collections.emptyMap();
    Map<Integer, Geometry> output = new LinkedHashMap<>();
    var pool = Executors.newFixedThreadPool(ThreadTools.getParallelism());
    try {
        List<List<GeometryWrapper>> wrappers = invokeAll(pool, tiles, t -> traceGeometries(server, t, clipArea, thresholds));
        var geometryMap = wrappers.stream().flatMap(p -> p.stream()).collect(Collectors.groupingBy(g -> g.label));
        // Determine 'inter-tile boundaries' - union operations can be very slow, so we want to restrict them
        // only to geometries that really require them.
        var xBoundsSet = new TreeSet<Integer>();
        var yBoundsSet = new TreeSet<Integer>();
        for (var t : tiles) {
            xBoundsSet.add(t.getImageX());
            xBoundsSet.add(t.getImageX() + t.getImageWidth());
            yBoundsSet.add(t.getImageY());
            yBoundsSet.add(t.getImageY() + t.getImageHeight());
        }
        int[] xBounds = xBoundsSet.stream().mapToInt(x -> x).toArray();
        int[] yBounds = yBoundsSet.stream().mapToInt(y -> y).toArray();
        var futures = new LinkedHashMap<Integer, Future<Geometry>>();
        // Merge objects with the same classification
        for (var entry : geometryMap.entrySet()) {
            var list = entry.getValue();
            if (list.isEmpty())
                continue;
            futures.put(entry.getKey(), pool.submit(() -> mergeGeometryWrappers(list, xBounds, yBounds)));
        }
        for (var entry : futures.entrySet()) output.put(entry.getKey(), entry.getValue().get());
    } catch (Exception e) {
        throw new IOException(e);
    } finally {
        pool.shutdown();
    }
    return output;
}
Also used : Geometry(org.locationtech.jts.geom.Geometry) ImageServer(qupath.lib.images.servers.ImageServer) BiFunction(java.util.function.BiFunction) LoggerFactory(org.slf4j.LoggerFactory) Coordinate(org.locationtech.jts.geom.Coordinate) Future(java.util.concurrent.Future) Map(java.util.Map) ImageIO(javax.imageio.ImageIO) ImageServers(qupath.lib.images.servers.ImageServers) Path(java.nio.file.Path) BufferedImage(java.awt.image.BufferedImage) Collection(java.util.Collection) PathObjects(qupath.lib.objects.PathObjects) Quadtree(org.locationtech.jts.index.quadtree.Quadtree) Collectors(java.util.stream.Collectors) Executors(java.util.concurrent.Executors) PathObject(qupath.lib.objects.PathObject) Objects(java.util.Objects) List(java.util.List) Stream(java.util.stream.Stream) Polygon(org.locationtech.jts.geom.Polygon) ImagePlane(qupath.lib.regions.ImagePlane) Geometry(org.locationtech.jts.geom.Geometry) ThreadTools(qupath.lib.common.ThreadTools) Pattern(java.util.regex.Pattern) PolygonExtracter(org.locationtech.jts.geom.util.PolygonExtracter) Deque(java.util.Deque) Function(java.util.function.Function) TreeSet(java.util.TreeSet) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) Raster(java.awt.image.Raster) BiConsumer(java.util.function.BiConsumer) TileRequest(qupath.lib.images.servers.TileRequest) GeometryTools(qupath.lib.roi.GeometryTools) AffineTransformation(org.locationtech.jts.geom.util.AffineTransformation) ExecutorService(java.util.concurrent.ExecutorService) GeometryFactory(org.locationtech.jts.geom.GeometryFactory) Logger(org.slf4j.Logger) GeneralTools(qupath.lib.common.GeneralTools) RegionRequest(qupath.lib.regions.RegionRequest) IOException(java.io.IOException) PathObjectTools(qupath.lib.objects.PathObjectTools) ExecutionException(java.util.concurrent.ExecutionException) ROI(qupath.lib.roi.interfaces.ROI) LineString(org.locationtech.jts.geom.LineString) TreeMap(java.util.TreeMap) Polygonizer(org.locationtech.jts.operation.polygonize.Polygonizer) ArrayDeque(java.util.ArrayDeque) Collections(java.util.Collections) Envelope(org.locationtech.jts.geom.Envelope) ImageServerMetadata(qupath.lib.images.servers.ImageServerMetadata) TreeSet(java.util.TreeSet) List(java.util.List) ArrayList(java.util.ArrayList) IOException(java.io.IOException) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) LinkedHashMap(java.util.LinkedHashMap)

Example 3 with ImageServer

use of qupath.lib.images.servers.ImageServer in project qupath by qupath.

the class QuPathGUI method refreshExtensions.

/**
 * Check the extensions directory, loading any new extensions found there.
 * @param showNotification if true, display a notification if a new extension has been loaded
 */
public void refreshExtensions(final boolean showNotification) {
    boolean initializing = initializingMenus.get();
    initializingMenus.set(true);
    // Refresh the extensions
    extensionClassLoader.refresh();
    extensionLoader.reload();
    // Sort the extensions by name, to ensure predictable loading order
    // (also, menus are in a better order if ImageJ extension installed before OpenCV extension)
    List<QuPathExtension> extensions = new ArrayList<>();
    Iterator<QuPathExtension> iterator = extensionLoader.iterator();
    while (iterator.hasNext()) {
        try {
            extensions.add(iterator.next());
        } catch (Throwable e) {
            if (getStage() != null && getStage().isShowing()) {
                Dialogs.showErrorMessage("Extension error", "Error loading extension - check 'View -> Show log' for details.");
            }
            logger.error(e.getLocalizedMessage(), e);
        }
    }
    Collections.sort(extensions, Comparator.comparing(QuPathExtension::getName));
    Version qupathVersion = getVersion();
    for (QuPathExtension extension : extensions) {
        if (!loadedExtensions.containsKey(extension.getClass())) {
            Version version = extension.getVersion();
            try {
                long startTime = System.currentTimeMillis();
                extension.installExtension(this);
                long endTime = System.currentTimeMillis();
                logger.info("Loaded extension {} ({} ms)", extension.getName(), endTime - startTime);
                if (version != null)
                    logger.debug("{} was written for QuPath {}", extension.getName(), version);
                else
                    logger.debug("{} does not report a compatible QuPath version", extension.getName());
                loadedExtensions.put(extension.getClass(), extension);
                if (showNotification)
                    Dialogs.showInfoNotification("Extension loaded", extension.getName());
            } catch (Exception | LinkageError e) {
                String message = "Unable to load " + extension.getName();
                if (showNotification)
                    Dialogs.showErrorNotification("Extension error", message);
                logger.error("Error loading extension " + extension + ": " + e.getLocalizedMessage(), e);
                if (!Objects.equals(qupathVersion, version)) {
                    if (version == null)
                        logger.warn("QuPath version for which the '{}' was written is unknown!", extension.getName());
                    else if (version.equals(qupathVersion))
                        logger.warn("'{}' reports that it is compatible with the current QuPath version {}", extension.getName(), qupathVersion);
                    else
                        logger.warn("'{}' was written for QuPath {} but current version is {}", extension.getName(), version, qupathVersion);
                }
                try {
                    logger.error("It is recommended that you delete {} and restart QuPath", URLDecoder.decode(extension.getClass().getProtectionDomain().getCodeSource().getLocation().toExternalForm(), StandardCharsets.UTF_8));
                } catch (Exception e2) {
                    logger.debug("Error finding code source " + e2.getLocalizedMessage(), e2);
                }
                defaultActions.SHOW_LOG.handle(null);
            }
        }
    }
    // Set the ImageServer to also look on the same search path
    List<ImageServerBuilder<?>> serverBuildersBefore = ImageServerProvider.getInstalledImageServerBuilders();
    ImageServerProvider.setServiceLoader(ServiceLoader.load(ImageServerBuilder.class, extensionClassLoader));
    if (showNotification) {
        // A bit convoluted... but try to show new servers that have been loaded by comparing with the past
        List<String> serverBuilders = serverBuildersBefore.stream().map(s -> s.getName()).collect(Collectors.toList());
        List<String> serverBuildersUpdated = ImageServerProvider.getInstalledImageServerBuilders().stream().map(s -> s.getName()).collect(Collectors.toList());
        serverBuildersUpdated.removeAll(serverBuilders);
        for (String builderName : serverBuildersUpdated) {
            Dialogs.showInfoNotification("Image server loaded", builderName);
        }
    }
    initializingMenus.set(initializing);
}
Also used : Change(javafx.collections.ListChangeListener.Change) PathObjectHierarchyView(qupath.lib.gui.panes.PathObjectHierarchyView) SelectedMeasurementTableView(qupath.lib.gui.panes.SelectedMeasurementTableView) Version(qupath.lib.common.Version) ProjectBrowser(qupath.lib.gui.panes.ProjectBrowser) ListChangeListener(javafx.collections.ListChangeListener) Map(java.util.Map) Path(java.nio.file.Path) ReleaseVersion(qupath.lib.gui.extensions.UpdateChecker.ReleaseVersion) Rectangle2D(javafx.geometry.Rectangle2D) PathObjects(qupath.lib.objects.PathObjects) Rectangle(javafx.scene.shape.Rectangle) BooleanProperty(javafx.beans.property.BooleanProperty) Project(qupath.lib.projects.Project) ObservableList(javafx.collections.ObservableList) Divider(javafx.scene.control.SplitPane.Divider) QuPathExtension(qupath.lib.gui.extensions.QuPathExtension) ByteArrayOutputStream(java.io.ByteArrayOutputStream) FXCollections(javafx.collections.FXCollections) PathIcons(qupath.lib.gui.tools.IconFactory.PathIcons) PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) Bindings(javafx.beans.binding.Bindings) LinkedHashMap(java.util.LinkedHashMap) TreeTableView(javafx.scene.control.TreeTableView) PreferencePane(qupath.lib.gui.panes.PreferencePane) Commands(qupath.lib.gui.commands.Commands) QuPathStyleManager(qupath.lib.gui.prefs.QuPathStyleManager) IOException(java.io.IOException) OverlayOptions(qupath.lib.gui.viewer.OverlayOptions) Preferences(java.util.prefs.Preferences) ROI(qupath.lib.roi.interfaces.ROI) PathTools(qupath.lib.gui.viewer.tools.PathTools) ParameterPanelFX(qupath.lib.gui.dialogs.ParameterPanelFX) DragDropImportListener(qupath.lib.gui.viewer.DragDropImportListener) ImageView(javafx.scene.image.ImageView) TMAGrid(qupath.lib.objects.hierarchy.TMAGrid) Image(javafx.scene.image.Image) PathIO(qupath.lib.io.PathIO) EventHandler(javafx.event.EventHandler) ImageServer(qupath.lib.images.servers.ImageServer) BooleanBinding(javafx.beans.binding.BooleanBinding) TextInputControl(javafx.scene.control.TextInputControl) URLDecoder(java.net.URLDecoder) UncaughtExceptionHandler(java.lang.Thread.UncaughtExceptionHandler) Date(java.util.Date) URISyntaxException(java.net.URISyntaxException) ObjectInputStream(java.io.ObjectInputStream) KeyCombination(javafx.scene.input.KeyCombination) DefaultImageRegionStore(qupath.lib.gui.images.stores.DefaultImageRegionStore) ByteArrayInputStream(java.io.ByteArrayInputStream) Locale(java.util.Locale) GitHubProject(qupath.lib.gui.extensions.GitHubProject) ImageIO(javax.imageio.ImageIO) RotateEvent(javafx.scene.input.RotateEvent) WindowEvent(javafx.stage.WindowEvent) PathInteractivePlugin(qupath.lib.plugins.PathInteractivePlugin) Orientation(javafx.geometry.Orientation) MenuItem(javafx.scene.control.MenuItem) Ellipse(javafx.scene.shape.Ellipse) ImageServerProvider(qupath.lib.images.servers.ImageServerProvider) Collection(java.util.Collection) Font(javafx.scene.text.Font) ServiceLoader(java.util.ServiceLoader) Collectors(java.util.stream.Collectors) BorderStroke(javafx.scene.layout.BorderStroke) PathObject(qupath.lib.objects.PathObject) Objects(java.util.Objects) ImageTypeSetting(qupath.lib.gui.prefs.PathPrefs.ImageTypeSetting) ProjectIO(qupath.lib.projects.ProjectIO) GuiTools(qupath.lib.gui.tools.GuiTools) ExecutorCompletionService(java.util.concurrent.ExecutorCompletionService) Scene(javafx.scene.Scene) ListView(javafx.scene.control.ListView) ReadOnlyObjectProperty(javafx.beans.property.ReadOnlyObjectProperty) SimpleStringProperty(javafx.beans.property.SimpleStringProperty) Action(org.controlsfx.control.action.Action) PathClassFactory(qupath.lib.objects.classes.PathClassFactory) ScriptEditor(qupath.lib.gui.scripting.ScriptEditor) TableColumn(javafx.scene.control.TableColumn) HashSet(java.util.HashSet) Insets(javafx.geometry.Insets) DetectionDisplayMode(qupath.lib.gui.viewer.OverlayOptions.DetectionDisplayMode) ExecutorService(java.util.concurrent.ExecutorService) KeyCode(javafx.scene.input.KeyCode) ActionAccelerator(qupath.lib.gui.ActionTools.ActionAccelerator) Logger(org.slf4j.Logger) Dialog(javafx.scene.control.Dialog) Label(javafx.scene.control.Label) MenuBar(javafx.scene.control.MenuBar) ActionIcon(qupath.lib.gui.ActionTools.ActionIcon) ServerBuilder(qupath.lib.images.servers.ImageServerBuilder.ServerBuilder) ScrollEvent(javafx.scene.input.ScrollEvent) Consumer(java.util.function.Consumer) SimpleBooleanProperty(javafx.beans.property.SimpleBooleanProperty) Stage(javafx.stage.Stage) ViewerPlusDisplayOptions(qupath.lib.gui.viewer.ViewerPlusDisplayOptions) Comparator(java.util.Comparator) PathTool(qupath.lib.gui.viewer.tools.PathTool) Arrays(java.util.Arrays) ServerTools(qupath.lib.images.servers.ServerTools) ActionUtils(org.controlsfx.control.action.ActionUtils) ActionDescription(qupath.lib.gui.ActionTools.ActionDescription) ReadOnlyBooleanProperty(javafx.beans.property.ReadOnlyBooleanProperty) StackPane(javafx.scene.layout.StackPane) AnnotationPane(qupath.lib.gui.panes.AnnotationPane) JFXPanel(javafx.embed.swing.JFXPanel) Category(java.util.Locale.Category) ParameterList(qupath.lib.plugins.parameters.ParameterList) TabPane(javafx.scene.control.TabPane) ScriptException(javax.script.ScriptException) CountingPanelCommand(qupath.lib.gui.commands.CountingPanelCommand) SplitPane(javafx.scene.control.SplitPane) Border(javafx.scene.layout.Border) Event(javafx.event.Event) Set(java.util.Set) KeyEvent(javafx.scene.input.KeyEvent) Screen(javafx.stage.Screen) AffineTransform(java.awt.geom.AffineTransform) QuPathViewerListener(qupath.lib.gui.viewer.QuPathViewerListener) StandardCharsets(java.nio.charset.StandardCharsets) Executors(java.util.concurrent.Executors) PathAnnotationObject(qupath.lib.objects.PathAnnotationObject) Platform(javafx.application.Platform) Region(javafx.scene.layout.Region) CommandFinderTools(qupath.lib.gui.tools.CommandFinderTools) InputDisplayCommand(qupath.lib.gui.commands.InputDisplayCommand) ImageRegionStoreFactory(qupath.lib.gui.images.stores.ImageRegionStoreFactory) ThreadTools(qupath.lib.common.ThreadTools) DefaultScriptEditor(qupath.lib.gui.scripting.DefaultScriptEditor) GitHubRepo(qupath.lib.gui.extensions.GitHubProject.GitHubRepo) BorderPane(javafx.scene.layout.BorderPane) ButtonData(javafx.scene.control.ButtonBar.ButtonData) SimpleDateFormat(java.text.SimpleDateFormat) PathPlugin(qupath.lib.plugins.PathPlugin) Projects(qupath.lib.projects.Projects) StandardCopyOption(java.nio.file.StandardCopyOption) ArrayList(java.util.ArrayList) TabClosingPolicy(javafx.scene.control.TabPane.TabClosingPolicy) QuPathViewerPlus(qupath.lib.gui.viewer.QuPathViewerPlus) ObjectOutputStream(java.io.ObjectOutputStream) LinkedHashSet(java.util.LinkedHashSet) Color(javafx.scene.paint.Color) CirclePopupMenu(jfxtras.scene.menu.CirclePopupMenu) TitledPane(javafx.scene.control.TitledPane) Files(java.nio.file.Files) ToolBar(javafx.scene.control.ToolBar) GeneralTools(qupath.lib.common.GeneralTools) Node(javafx.scene.Node) CheckBox(javafx.scene.control.CheckBox) ProjectCommands(qupath.lib.gui.commands.ProjectCommands) File(java.io.File) PathObjectTools(qupath.lib.objects.PathObjectTools) Menu(javafx.scene.control.Menu) Cursor(javafx.scene.Cursor) KeyCodeCombination(javafx.scene.input.KeyCodeCombination) Paths(java.nio.file.Paths) SimpleObjectProperty(javafx.beans.property.SimpleObjectProperty) Tab(javafx.scene.control.Tab) PathPrefs(qupath.lib.gui.prefs.PathPrefs) StringBinding(javafx.beans.binding.StringBinding) Pos(javafx.geometry.Pos) Area(java.awt.geom.Area) CheckMenuItem(javafx.scene.control.CheckMenuItem) LoggerFactory(org.slf4j.LoggerFactory) UpdateChecker(qupath.lib.gui.extensions.UpdateChecker) Parent(javafx.scene.Parent) ContextMenu(javafx.scene.control.ContextMenu) URI(java.net.URI) ImageServers(qupath.lib.images.servers.ImageServers) TableView(javafx.scene.control.TableView) ImageType(qupath.lib.images.ImageData.ImageType) Shape(java.awt.Shape) BufferedImage(java.awt.image.BufferedImage) GroovyLanguage(qupath.lib.gui.scripting.languages.GroovyLanguage) ImageServerBuilder(qupath.lib.images.servers.ImageServerBuilder) FileNotFoundException(java.io.FileNotFoundException) TreeView(javafx.scene.control.TreeView) SeparatorMenuItem(javafx.scene.control.SeparatorMenuItem) QuPathViewer(qupath.lib.gui.viewer.QuPathViewer) List(java.util.List) Duration(javafx.util.Duration) ColorToolsFX(qupath.lib.gui.tools.ColorToolsFX) Optional(java.util.Optional) LogManager(qupath.lib.gui.logging.LogManager) RadioMenuItem(javafx.scene.control.RadioMenuItem) WorkflowCommandLogView(qupath.lib.gui.panes.WorkflowCommandLogView) TextArea(javafx.scene.control.TextArea) ButtonType(javafx.scene.control.ButtonType) MouseEvent(javafx.scene.input.MouseEvent) HashMap(java.util.HashMap) BrightnessContrastCommand(qupath.lib.gui.commands.BrightnessContrastCommand) UriImageSupport(qupath.lib.images.servers.ImageServerBuilder.UriImageSupport) Dialogs(qupath.lib.gui.dialogs.Dialogs) SwingUtilities(javax.swing.SwingUtilities) HostServices(javafx.application.HostServices) ZoomEvent(javafx.scene.input.ZoomEvent) TMACommands(qupath.lib.gui.commands.TMACommands) Tooltip(javafx.scene.control.Tooltip) ImageDetailsPane(qupath.lib.gui.panes.ImageDetailsPane) ImageData(qupath.lib.images.ImageData) Desktop(java.awt.Desktop) RoiTools(qupath.lib.roi.RoiTools) ObjectProperty(javafx.beans.property.ObjectProperty) Iterator(java.util.Iterator) ProjectImageEntry(qupath.lib.projects.ProjectImageEntry) TableRow(javafx.scene.control.TableRow) PathClass(qupath.lib.objects.classes.PathClass) TMACoreObject(qupath.lib.objects.TMACoreObject) DropShadow(javafx.scene.effect.DropShadow) MenuTools(qupath.lib.gui.tools.MenuTools) BorderStrokeStyle(javafx.scene.layout.BorderStrokeStyle) ActionEvent(javafx.event.ActionEvent) ToggleGroup(javafx.scene.control.ToggleGroup) LogViewerCommand(qupath.lib.gui.commands.LogViewerCommand) SwingFXUtils(javafx.embed.swing.SwingFXUtils) Collections(java.util.Collections) InputStream(java.io.InputStream) DialogButton(qupath.lib.gui.dialogs.Dialogs.DialogButton) ImageServerBuilder(qupath.lib.images.servers.ImageServerBuilder) QuPathExtension(qupath.lib.gui.extensions.QuPathExtension) ArrayList(java.util.ArrayList) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) ScriptException(javax.script.ScriptException) FileNotFoundException(java.io.FileNotFoundException) Version(qupath.lib.common.Version) ReleaseVersion(qupath.lib.gui.extensions.UpdateChecker.ReleaseVersion)

Example 4 with ImageServer

use of qupath.lib.images.servers.ImageServer in project qupath by qupath.

the class QuPathViewer method setImageData.

/**
 * Set the current image for this viewer.
 * @param imageDataNew
 */
public void setImageData(ImageData<BufferedImage> imageDataNew) {
    if (this.imageDataProperty.get() == imageDataNew)
        return;
    imageDataChanging.set(true);
    // Remove listeners for previous hierarchy
    ImageData<BufferedImage> imageDataOld = this.imageDataProperty.get();
    if (imageDataOld != null) {
        imageDataOld.getHierarchy().removePathObjectListener(this);
        imageDataOld.getHierarchy().getSelectionModel().removePathObjectSelectionListener(this);
    }
    // Determine if the server has remained the same, so we can avoid shifting the viewer
    boolean sameServer = false;
    if (imageDataOld != null && imageDataNew != null && imageDataOld.getServerPath().equals(imageDataNew.getServerPath()))
        sameServer = true;
    this.imageDataProperty.set(imageDataNew);
    ImageServer<BufferedImage> server = imageDataNew == null ? null : imageDataNew.getServer();
    PathObjectHierarchy hierarchy = imageDataNew == null ? null : imageDataNew.getHierarchy();
    long startTime = System.currentTimeMillis();
    if (imageDisplay != null) {
        boolean keepDisplay = PathPrefs.keepDisplaySettingsProperty().get();
        // This is a bit of a hack to avoid calling internal methods for ImageDisplay
        // See https://github.com/qupath/qupath/issues/601
        boolean displaySet = false;
        if (imageDataNew != null && keepDisplay) {
            if (imageDisplay.getImageData() != null && serversCompatible(imageDataNew.getServer(), imageDisplay.getImageData().getServer())) {
                imageDisplay.setImageData(imageDataNew, keepDisplay);
                displaySet = true;
            } else {
                for (var viewer : QuPathGUI.getInstance().getViewers()) {
                    if (this == viewer || viewer.getImageData() == null)
                        continue;
                    var tempServer = viewer.getServer();
                    var currentServer = imageDataNew.getServer();
                    if (serversCompatible(tempServer, currentServer)) {
                        var json = viewer.getImageDisplay().toJSON(false);
                        imageDataNew.setProperty(ImageDisplay.class.getName(), json);
                        imageDisplay.setImageData(imageDataNew, false);
                        displaySet = true;
                        break;
                    }
                }
            }
        }
        if (!displaySet)
            imageDisplay.setImageData(imageDataNew, keepDisplay);
        // See https://github.com/qupath/qupath/issues/843
        if (server != null && !server.isRGB()) {
            var colors = imageDisplay.availableChannels().stream().filter(c -> c instanceof DirectServerChannelInfo).map(c -> c.getColor()).collect(Collectors.toList());
            if (server.nChannels() == colors.size())
                updateServerChannels(server, colors);
        }
    }
    long endTime = System.currentTimeMillis();
    logger.debug("Setting ImageData time: {} ms", endTime - startTime);
    initializeForServer(server);
    if (!sameServer) {
        setDownsampleFactorImpl(getZoomToFitDownsampleFactor(), -1, -1);
        centerImage();
    }
    fireImageDataChanged(imageDataOld, imageDataNew);
    if (imageDataNew != null) {
        // hierarchyPainter = new PathHierarchyPainter(hierarchy);
        hierarchy.addPathObjectListener(this);
        hierarchy.getSelectionModel().addPathObjectSelectionListener(this);
    }
    setSelectedObject(null);
    // TODO: Consider shifting, fixing magnification, repainting etc.
    if (isShowing())
        repaint();
    logger.info("Image data set to {}", imageDataNew);
}
Also used : Color(java.awt.Color) GridOverlay(qupath.lib.gui.viewer.overlays.GridOverlay) Change(javafx.collections.ListChangeListener.Change) Rectangle2D(java.awt.geom.Rectangle2D) StackPane(javafx.scene.layout.StackPane) ColorConvertOp(java.awt.image.ColorConvertOp) ListChangeListener(javafx.collections.ListChangeListener) ImageRegion(qupath.lib.regions.ImageRegion) SimpleIntegerProperty(javafx.beans.property.SimpleIntegerProperty) ColorToolsAwt(qupath.lib.color.ColorToolsAwt) ColorTools(qupath.lib.common.ColorTools) GraphicsContext(javafx.scene.canvas.GraphicsContext) Set(java.util.Set) Canvas(javafx.scene.canvas.Canvas) KeyEvent(javafx.scene.input.KeyEvent) AffineTransform(java.awt.geom.AffineTransform) Observable(javafx.beans.Observable) AbstractOverlay(qupath.lib.gui.viewer.overlays.AbstractOverlay) ImageInputStream(javax.imageio.stream.ImageInputStream) Platform(javafx.application.Platform) RoiEditor(qupath.lib.roi.RoiEditor) BooleanProperty(javafx.beans.property.BooleanProperty) SimpleDoubleProperty(javafx.beans.property.SimpleDoubleProperty) ObservableList(javafx.collections.ObservableList) RectangleROI(qupath.lib.roi.RectangleROI) FXCollections(javafx.collections.FXCollections) PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) IntegerProperty(javafx.beans.property.IntegerProperty) ArrayList(java.util.ArrayList) AlphaComposite(java.awt.AlphaComposite) TextAlignment(javafx.scene.text.TextAlignment) Stroke(java.awt.Stroke) PathOverlay(qupath.lib.gui.viewer.overlays.PathOverlay) ImageReader(javax.imageio.ImageReader) GeneralTools(qupath.lib.common.GeneralTools) RegionRequest(qupath.lib.regions.RegionRequest) AwtTools(qupath.lib.awt.common.AwtTools) PathObjectSelectionListener(qupath.lib.objects.hierarchy.events.PathObjectSelectionListener) IOException(java.io.IOException) File(java.io.File) PathObjectTools(qupath.lib.objects.PathObjectTools) Cursor(javafx.scene.Cursor) ROI(qupath.lib.roi.interfaces.ROI) PathTools(qupath.lib.gui.viewer.tools.PathTools) SimpleObjectProperty(javafx.beans.property.SimpleObjectProperty) PixelCalibration(qupath.lib.images.servers.PixelCalibration) ObservableValue(javafx.beans.value.ObservableValue) PathObjectHierarchyListener(qupath.lib.objects.hierarchy.events.PathObjectHierarchyListener) TMAGrid(qupath.lib.objects.hierarchy.TMAGrid) PathPrefs(qupath.lib.gui.prefs.PathPrefs) LookupOp(java.awt.image.LookupOp) ImageServerMetadata(qupath.lib.images.servers.ImageServerMetadata) EventHandler(javafx.event.EventHandler) ImageServer(qupath.lib.images.servers.ImageServer) Point2D(java.awt.geom.Point2D) IIOMetadata(javax.imageio.metadata.IIOMetadata) LoggerFactory(org.slf4j.LoggerFactory) RenderingHints(java.awt.RenderingHints) TMAGridOverlay(qupath.lib.gui.viewer.overlays.TMAGridOverlay) PixelClassificationOverlay(qupath.lib.gui.viewer.overlays.PixelClassificationOverlay) InvalidationListener(javafx.beans.InvalidationListener) DefaultImageRegionStore(qupath.lib.gui.images.stores.DefaultImageRegionStore) ObservableMeasurementTableData(qupath.lib.gui.measure.ObservableMeasurementTableData) PathObjectHierarchyEvent(qupath.lib.objects.hierarchy.events.PathObjectHierarchyEvent) DirectServerChannelInfo(qupath.lib.display.DirectServerChannelInfo) ImageIO(javax.imageio.ImageIO) NoninvertibleTransformException(java.awt.geom.NoninvertibleTransformException) Method(java.lang.reflect.Method) QuPathGUI(qupath.lib.gui.QuPathGUI) Pane(javafx.scene.layout.Pane) MoveTool(qupath.lib.gui.viewer.tools.MoveTool) Shape(java.awt.Shape) Composite(java.awt.Composite) Image(java.awt.Image) BufferedImage(java.awt.image.BufferedImage) Collection(java.util.Collection) Collectors(java.util.stream.Collectors) PathDetectionObject(qupath.lib.objects.PathDetectionObject) PathObject(qupath.lib.objects.PathObject) Objects(java.util.Objects) List(java.util.List) GuiTools(qupath.lib.gui.tools.GuiTools) ColorToolsFX(qupath.lib.gui.tools.ColorToolsFX) Graphics(java.awt.Graphics) ImagePlane(qupath.lib.regions.ImagePlane) SimpleLongProperty(javafx.beans.property.SimpleLongProperty) ReadOnlyLongProperty(javafx.beans.property.ReadOnlyLongProperty) Rectangle(java.awt.Rectangle) ReadOnlyObjectProperty(javafx.beans.property.ReadOnlyObjectProperty) MouseEvent(javafx.scene.input.MouseEvent) ImageChannel(qupath.lib.images.servers.ImageChannel) DoubleProperty(javafx.beans.property.DoubleProperty) ImageRenderer(qupath.lib.gui.images.stores.ImageRenderer) ByteLookupTable(java.awt.image.ByteLookupTable) ColorSpace(java.awt.color.ColorSpace) ImageDisplay(qupath.lib.display.ImageDisplay) ImageRegionStoreHelpers(qupath.lib.gui.images.stores.ImageRegionStoreHelpers) HashSet(java.util.HashSet) Graphics2D(java.awt.Graphics2D) Tooltip(javafx.scene.control.Tooltip) ImageData(qupath.lib.images.ImageData) ICC_Profile(java.awt.color.ICC_Profile) KeyCode(javafx.scene.input.KeyCode) ObjectProperty(javafx.beans.property.ObjectProperty) Logger(org.slf4j.Logger) Iterator(java.util.Iterator) WritableImage(javafx.scene.image.WritableImage) HierarchyOverlay(qupath.lib.gui.viewer.overlays.HierarchyOverlay) LongProperty(javafx.beans.property.LongProperty) PathHierarchyImageServer(qupath.lib.gui.images.servers.PathHierarchyImageServer) TMACoreObject(qupath.lib.objects.TMACoreObject) SimpleBooleanProperty(javafx.beans.property.SimpleBooleanProperty) SwingFXUtils(javafx.embed.swing.SwingFXUtils) ChangeListener(javafx.beans.value.ChangeListener) Collections(java.util.Collections) TileListener(qupath.lib.gui.images.stores.TileListener) PathTool(qupath.lib.gui.viewer.tools.PathTool) PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) DirectServerChannelInfo(qupath.lib.display.DirectServerChannelInfo) BufferedImage(java.awt.image.BufferedImage) ImageDisplay(qupath.lib.display.ImageDisplay)

Example 5 with ImageServer

use of qupath.lib.images.servers.ImageServer in project qupath by qupath.

the class ConvertCommand method run.

@Override
public void run() {
    long startTime = System.currentTimeMillis();
    try {
        if (inputFile == null || outputFile == null)
            throw new IOException("Incorrect given path(s)");
    } catch (IOException e) {
        logger.error(e.getLocalizedMessage());
        return;
    }
    // Change name if not ending with .ome.tif
    if (!outputFile.getAbsolutePath().toLowerCase().endsWith(".ome.tif"))
        outputFile = new File(outputFile.getParentFile(), GeneralTools.getNameWithoutExtension(outputFile) + ".ome.tif");
    if (outputFile.exists() && !overwrite) {
        logger.error("Output file " + outputFile + " exists!");
        return;
    }
    if (inputFile.equals(outputFile)) {
        logger.error("Input and output files are the same!");
        return;
    }
    String[] args;
    if (series >= 0)
        args = new String[] { "--classname", BioFormatsServerBuilder.class.getName(), "--series", Integer.toString(series) };
    else
        args = new String[0];
    createTileCache();
    try (ImageServer<BufferedImage> server = ImageServers.buildServer(inputFile.toURI(), args)) {
        // Get compression from user (or CompressionType.DEFAULT)
        // CompressionType compressionType = stringToCompressionType(compression);
        CompressionType compressionType = compression;
        // Check that compression is compatible with image
        if (!Arrays.stream(CompressionType.values()).filter(c -> c.supportsImage(server)).anyMatch(c -> c == compressionType)) {
            logger.error("Chosen compression " + compressionType.toString() + " is not compatible with the input image.");
        }
        if (tileSize > -1) {
            tileWidth = tileSize;
            tileHeight = tileSize;
        }
        Builder builder = new OMEPyramidWriter.Builder(server).compression(compressionType).tileSize(tileWidth, tileHeight).parallelize(parallelize);
        if (bigTiff != null)
            builder = builder.bigTiff(bigTiff.booleanValue());
        // Make pyramidal, if requested
        if (downsample < 1)
            downsample = server.getDownsampleForResolution(0);
        if (pyramid > 1)
            builder.scaledDownsampling(downsample, pyramid);
        else
            builder.downsamples(downsample);
        String patternRange = "(\\d+)-(\\d+)";
        String patternInteger = "\\d+";
        // Parse z-slices, remembering to convert from 1-based (inclusive) to 0-based (upper value exclusive) indexing
        if (zSlices == null || zSlices.isBlank() || "all".equals(zSlices)) {
            builder.allZSlices();
        } else if (zSlices.matches(patternRange)) {
            int zStart = Integer.parseInt(zSlices.substring(0, zSlices.indexOf("-")));
            int zEnd = Integer.parseInt(zSlices.substring(zSlices.indexOf("-") + 1));
            if (zEnd == zStart)
                builder.zSlice(zStart - 1);
            else if (zStart > zEnd) {
                logger.error("Invalid range of --zslices (must be ascending): " + zSlices);
                return;
            } else
                builder.zSlices(zStart - 1, zEnd);
        } else if (zSlices.matches(patternInteger)) {
            int z = Integer.parseInt(zSlices);
            builder.zSlice(z - 1);
        } else {
            logger.error("Unknown value for --zslices: " + zSlices);
            return;
        }
        // Parse timepoints, remembering to convert from 1-based (inclusive) to 0-based (upper value exclusive) indexing
        if ("all".equals(timepoints)) {
            builder.allTimePoints();
        } else if (timepoints.matches(patternRange)) {
            int tStart = Integer.parseInt(timepoints.substring(0, timepoints.indexOf("-")));
            int tEnd = Integer.parseInt(timepoints.substring(timepoints.indexOf("-") + 1));
            if (tStart == tEnd)
                builder.timePoint(tStart - 1);
            else if (tStart > tEnd) {
                logger.error("Invalid range of --timepoints (must be ascending): " + timepoints);
                return;
            } else
                builder.timePoints(tStart - 1, tEnd);
        } else if (timepoints.matches(patternInteger)) {
            int t = Integer.parseInt(timepoints);
            builder.timePoint(t - 1);
        } else {
            logger.error("Unknown value for --timepoints: " + timepoints);
            return;
        }
        // Parse the bounding box, if required
        if (crop != null && !crop.isBlank()) {
            var matcher = Pattern.compile("(\\d+),(\\d+),(\\d+),(\\d+)").matcher(crop);
            if (matcher.matches()) {
                int x = Integer.parseInt(matcher.group(1));
                int y = Integer.parseInt(matcher.group(2));
                int w = Integer.parseInt(matcher.group(3));
                int h = Integer.parseInt(matcher.group(4));
                builder.region(x, y, w, h);
            } else {
                logger.error("Unknown value for --crop: " + crop);
                return;
            }
        }
        builder.build().writeSeries(outputFile.getPath());
        long duration = System.currentTimeMillis() - startTime;
        logger.info(String.format("%s written in %.1f seconds", outputFile.getAbsolutePath(), duration / 1000.0));
    } catch (Exception e) {
        logger.error(e.getLocalizedMessage(), e);
    }
}
Also used : Arrays(java.util.Arrays) ImageServer(qupath.lib.images.servers.ImageServer) Logger(org.slf4j.Logger) Builder(qupath.lib.images.writers.ome.OMEPyramidWriter.Builder) BufferedImage(java.awt.image.BufferedImage) Parameters(picocli.CommandLine.Parameters) GeneralTools(qupath.lib.common.GeneralTools) Subcommand(qupath.lib.gui.extensions.Subcommand) ImageServerProvider(qupath.lib.images.servers.ImageServerProvider) LoggerFactory(org.slf4j.LoggerFactory) IOException(java.io.IOException) BioFormatsServerBuilder(qupath.lib.images.servers.bioformats.BioFormatsServerBuilder) File(java.io.File) Option(picocli.CommandLine.Option) ImageRegionStoreFactory(qupath.lib.gui.images.stores.ImageRegionStoreFactory) Pattern(java.util.regex.Pattern) Command(picocli.CommandLine.Command) ImageServers(qupath.lib.images.servers.ImageServers) CompressionType(qupath.lib.images.writers.ome.OMEPyramidWriter.CompressionType) PathPrefs(qupath.lib.gui.prefs.PathPrefs) Builder(qupath.lib.images.writers.ome.OMEPyramidWriter.Builder) BioFormatsServerBuilder(qupath.lib.images.servers.bioformats.BioFormatsServerBuilder) IOException(java.io.IOException) BufferedImage(java.awt.image.BufferedImage) IOException(java.io.IOException) Builder(qupath.lib.images.writers.ome.OMEPyramidWriter.Builder) File(java.io.File) CompressionType(qupath.lib.images.writers.ome.OMEPyramidWriter.CompressionType)

Aggregations

BufferedImage (java.awt.image.BufferedImage)17 ImageServer (qupath.lib.images.servers.ImageServer)17 IOException (java.io.IOException)15 Logger (org.slf4j.Logger)14 LoggerFactory (org.slf4j.LoggerFactory)14 ArrayList (java.util.ArrayList)13 PathObject (qupath.lib.objects.PathObject)13 Collectors (java.util.stream.Collectors)12 Collections (java.util.Collections)11 ROI (qupath.lib.roi.interfaces.ROI)11 Collection (java.util.Collection)10 List (java.util.List)10 Map (java.util.Map)10 ImageData (qupath.lib.images.ImageData)10 PathObjectTools (qupath.lib.objects.PathObjectTools)10 RegionRequest (qupath.lib.regions.RegionRequest)10 Arrays (java.util.Arrays)9 LinkedHashMap (java.util.LinkedHashMap)9 PathObjectHierarchy (qupath.lib.objects.hierarchy.PathObjectHierarchy)9 HashSet (java.util.HashSet)8