Search in sources :

Example 11 with PathObjectHierarchy

use of qupath.lib.objects.hierarchy.PathObjectHierarchy in project qupath by qupath.

the class TMASummaryViewer method updateSurvivalCurves.

private void updateSurvivalCurves() {
    String colID = null;
    String colScore = null;
    colCensored = null;
    for (String nameOrig : model.getAllNames()) {
        if (nameOrig.equals(TMACoreObject.KEY_UNIQUE_ID))
            colID = nameOrig;
        else // else if (nameOrig.equals(TMACoreObject.KEY_CENSORED))
        // colCensored = nameOrig;
        // else if (!Number.class.isAssignableFrom())
        // continue;
        {
            if (nameOrig.trim().length() == 0 || !model.getMeasurementNames().contains(nameOrig))
                continue;
            String name = nameOrig.toLowerCase();
            if (name.equals("h-score"))
                colScore = nameOrig;
            else if (name.equals("positive %") && colScore == null)
                colScore = nameOrig;
        }
    }
    // Check for a column with the exact requested name
    String colCensoredRequested = null;
    String colSurvival = getSurvivalColumn();
    if (colSurvival != null) {
        colCensoredRequested = getRequestedSurvivalCensoredColumn(colSurvival);
        if (model.getAllNames().contains(colCensoredRequested))
            colCensored = colCensoredRequested;
        else // Check for a general 'censored' column... less secure since it doesn't specify OS or RFS (but helps with backwards-compatibility)
        if (model.getAllNames().contains("Censored")) {
            logger.warn("Correct censored column for \"{}\" unavailable - should be \"{}\", but using \"Censored\" column instead", colSurvival, colCensoredRequested);
            colCensored = "Censored";
        }
    }
    if (colCensored == null && colSurvival != null) {
        logger.warn("Unable to find censored column - survival data will be uncensored");
    } else
        logger.info("Survival column: {}, Censored column: {}", colSurvival, colCensored);
    colScore = comboMainMeasurement.getSelectionModel().getSelectedItem();
    if (colID == null || colSurvival == null || colCensored == null) {
        // Adjust priority depending on whether we have any data at all..
        if (!model.getItems().isEmpty())
            logger.warn("No survival data found!");
        else
            logger.trace("No entries or survival data available");
        return;
    }
    // Generate a pseudo TMA core hierarchy
    Map<String, List<TMAEntry>> scoreMap = createScoresMap(model.getItems(), colScore, colID);
    // System.err.println("Score map size: " + scoreMap.size() + "\tEntries: " + model.getEntries().size());
    List<TMACoreObject> cores = new ArrayList<>(scoreMap.size());
    double[] scores = new double[15];
    for (Entry<String, List<TMAEntry>> entry : scoreMap.entrySet()) {
        TMACoreObject core = new TMACoreObject();
        core.setName("ID: " + entry.getKey());
        MeasurementList ml = core.getMeasurementList();
        Arrays.fill(scores, Double.POSITIVE_INFINITY);
        List<TMAEntry> list = entry.getValue();
        // Increase array size, if needed
        if (list.size() > scores.length)
            scores = new double[list.size()];
        for (int i = 0; i < list.size(); i++) {
            scores[i] = model.getNumericValue(list.get(i), colScore);
        // scores[i] = list.get(i).getMeasurement(colScore).doubleValue();
        }
        Arrays.sort(scores);
        int n = list.size();
        double score;
        if (n % 2 == 1)
            score = scores[n / 2];
        else
            score = (scores[n / 2 - 1] + scores[n / 2]) / 2;
        core.putMetadataValue(TMACoreObject.KEY_UNIQUE_ID, entry.getKey());
        // System.err.println("Putting: " + list.get(0).getMeasurement(colSurvival).doubleValue() + " LIST: " + list.size());
        ml.putMeasurement(colSurvival, list.get(0).getMeasurementAsDouble(colSurvival));
        ml.putMeasurement(colCensoredRequested, list.get(0).getMeasurementAsDouble(colCensored));
        if (colScore != null)
            ml.putMeasurement(colScore, score);
        cores.add(core);
    // logger.info(entry.getKey() + "\t" + score);
    }
    TMAGrid grid = DefaultTMAGrid.create(cores, 1);
    PathObjectHierarchy hierarchy = new PathObjectHierarchy();
    hierarchy.setTMAGrid(grid);
    kmDisplay.setHierarchy(hierarchy, colSurvival, colCensoredRequested);
    kmDisplay.setScoreColumn(comboMainMeasurement.getSelectionModel().getSelectedItem());
// new KaplanMeierPlotTMA.KaplanMeierDisplay(hierarchy, colScore).show(frame, colScore);
}
Also used : PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) TMACoreObject(qupath.lib.objects.TMACoreObject) MeasurementList(qupath.lib.measurements.MeasurementList) TMAEntry(qupath.lib.gui.tma.TMAEntries.TMAEntry) ArrayList(java.util.ArrayList) DefaultTMAGrid(qupath.lib.objects.hierarchy.DefaultTMAGrid) TMAGrid(qupath.lib.objects.hierarchy.TMAGrid) ObservableList(javafx.collections.ObservableList) ArrayList(java.util.ArrayList) MeasurementList(qupath.lib.measurements.MeasurementList) SortedList(javafx.collections.transformation.SortedList) FilteredList(javafx.collections.transformation.FilteredList) List(java.util.List)

Example 12 with PathObjectHierarchy

use of qupath.lib.objects.hierarchy.PathObjectHierarchy in project qupath by qupath.

the class PathIO method writeImageDataSerialized.

private static void writeImageDataSerialized(final OutputStream stream, final ImageData<?> imageData) throws IOException {
    try (OutputStream outputStream = new BufferedOutputStream(stream)) {
        long startTime = System.currentTimeMillis();
        ObjectOutputStream outStream = new ObjectOutputStream(outputStream);
        // Write the identifier
        outStream.writeUTF("Data file version " + DATA_FILE_VERSION);
        // Try to write a backwards-compatible image path
        var server = imageData.getServer();
        // var uris = server.getURIs();
        // String path;
        // if (uris.size() == 1) {
        // var uri = uris.iterator().next();
        // var serverPath = GeneralTools.toPath(uri);
        // if (serverPath != null && Files.exists(serverPath))
        // path = serverPath.toFile().getAbsolutePath();
        // else
        // path = uri.toString();
        // } else
        // path = server.getPath();
        // outStream.writeObject("Image path: " + path);
        // Write JSON object including QuPath version and ServerBuilder
        // Note that the builder may be null, in which case the server cannot be recreated
        var builder = server.getBuilder();
        if (builder == null)
            logger.warn("Server {} does not provide a builder - it will not be possible to recover the ImageServer from this data file", server);
        var wrapper = ServerBuilderWrapper.create(builder, server.getPath());
        String json = GsonTools.getInstance().toJson(wrapper);
        outStream.writeObject(json);
        // Write the current locale
        outStream.writeObject(Locale.getDefault(Category.FORMAT));
        // Write the rest of the main image metadata
        outStream.writeObject(imageData.getImageType());
        outStream.writeObject(imageData.getColorDeconvolutionStains());
        outStream.writeObject(imageData.getHistoryWorkflow());
        // Write the rest of the main image metadata
        PathObjectHierarchy hierarchy = imageData.getHierarchy();
        logger.info(String.format("Writing object hierarchy with %d object(s)...", hierarchy.nObjects()));
        outStream.writeObject(hierarchy);
        // Write any remaining (serializable) properties
        Map<String, Object> map = new HashMap<>();
        for (Entry<String, Object> entry : imageData.getProperties().entrySet()) {
            if (entry.getValue() instanceof Serializable)
                map.put(entry.getKey(), entry.getValue());
            else
                logger.error("Property not serializable and will not be saved!  Key: " + entry.getKey() + ", Value: " + entry.getValue());
        }
        if (map != null)
            outStream.writeObject(map);
        // Write EOF marker
        outStream.writeObject("EOF");
        long endTime = System.currentTimeMillis();
        logger.info(String.format("Image data written in %.2f seconds", (endTime - startTime) / 1000.));
    }
}
Also used : PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) Serializable(java.io.Serializable) HashMap(java.util.HashMap) ZipOutputStream(java.util.zip.ZipOutputStream) BufferedOutputStream(java.io.BufferedOutputStream) ObjectOutputStream(java.io.ObjectOutputStream) OutputStream(java.io.OutputStream) FileOutputStream(java.io.FileOutputStream) PathObject(qupath.lib.objects.PathObject) ObjectOutputStream(java.io.ObjectOutputStream) BufferedOutputStream(java.io.BufferedOutputStream)

Example 13 with PathObjectHierarchy

use of qupath.lib.objects.hierarchy.PathObjectHierarchy in project qupath by qupath.

the class PathIO method readImageDataSerialized.

@SuppressWarnings("unchecked")
private static <T> ImageData<T> readImageDataSerialized(final InputStream stream, ImageData<T> imageData, ImageServer<T> server, Class<T> cls) throws IOException {
    long startTime = System.currentTimeMillis();
    Locale locale = Locale.getDefault(Category.FORMAT);
    boolean localeChanged = false;
    try (ObjectInputStream inStream = new ObjectInputStream(new BufferedInputStream(stream))) {
        ServerBuilder<T> serverBuilder = null;
        PathObjectHierarchy hierarchy = null;
        ImageData.ImageType imageType = null;
        ColorDeconvolutionStains stains = null;
        Workflow workflow = null;
        Map<String, Object> propertyMap = null;
        String firstLine = inStream.readUTF();
        // int versionNumber = -1;
        if (!firstLine.startsWith("Data file version")) {
            logger.error("Input stream does not contain valid QuPath data!");
        }
        // else {
        // // Could try to parse version number... although frankly, at this time, we don't really care...
        // try {
        // versionNumber = NumberFormat.getInstance(Locale.US).parse(firstLine.substring("Data file version".length()).trim()).intValue();
        // } catch (Exception e) {
        // logger.warn("Unable to parse version number from {}", firstLine);
        // }
        // }
        String serverString = (String) inStream.readObject();
        // Don't log warnings if we are provided with a server
        serverBuilder = extractServerBuilder(serverString, server == null);
        while (true) {
            // logger.debug("Starting read: " + inStream.available());
            try {
                // Try to read a relevant object from the stream
                Object input = inStream.readObject();
                logger.debug("Read: {}", input);
                // If we have a Locale, then set it
                if (input instanceof Locale) {
                    if (input != locale) {
                        Locale.setDefault(Category.FORMAT, (Locale) input);
                        localeChanged = true;
                    }
                } else if (input instanceof PathObjectHierarchy)
                    hierarchy = (PathObjectHierarchy) input;
                else if (input instanceof ImageData.ImageType)
                    imageType = (ImageData.ImageType) input;
                else if (input instanceof String && "EOF".equals(input)) {
                    // else if ("EOF".equals(input)) {
                    break;
                // }
                } else if (input instanceof ColorDeconvolutionStains)
                    stains = (ColorDeconvolutionStains) input;
                else if (input instanceof Workflow)
                    workflow = (Workflow) input;
                else if (input instanceof Map)
                    propertyMap = (Map<String, Object>) input;
                else if (input == null) {
                    logger.debug("Null object will be skipped");
                } else
                    logger.warn("Unsupported object of class {} will be skipped: {}", input.getClass().getName(), input);
            } catch (ClassNotFoundException e) {
                logger.error("Unable to find class: " + e.getLocalizedMessage(), e);
            } catch (EOFException e) {
                // Try to recover from EOFExceptions - we may already have enough info
                logger.error("Reached end of file...");
                if (hierarchy == null)
                    logger.error(e.getLocalizedMessage(), e);
                break;
            }
        }
        // Create an entirely new ImageData if necessary
        var existingBuilder = imageData == null || imageData.getServer() == null ? null : imageData.getServer().getBuilder();
        if (imageData == null || !Objects.equals(serverBuilder, existingBuilder)) {
            // Create a new server if we need to
            if (server == null) {
                try {
                    server = serverBuilder.build();
                } catch (Exception e) {
                    logger.error(e.getLocalizedMessage());
                }
                ;
                if (server == null) {
                    logger.error("Warning: Unable to build server with " + serverBuilder);
                // throw new RuntimeException("Warning: Unable to create server for path " + serverPath);
                }
            }
            // TODO: Make this less clumsy... but for now we need to ensure we have a fully-initialized hierarchy (which deserialization alone doesn't achieve)
            PathObjectHierarchy hierarchy2 = new PathObjectHierarchy();
            hierarchy2.setHierarchy(hierarchy);
            hierarchy = hierarchy2;
            imageData = new ImageData<>(server, hierarchy, imageType);
        } else {
            if (imageType != null)
                imageData.setImageType(imageType);
            // Set the new hierarchy
            if (hierarchy != null)
                imageData.getHierarchy().setHierarchy(hierarchy);
        }
        // Set the other properties we have just read
        if (workflow != null) {
            imageData.getHistoryWorkflow().clear();
            imageData.getHistoryWorkflow().addSteps(workflow.getSteps());
        }
        if (stains != null) {
            imageData.setColorDeconvolutionStains(stains);
        }
        if (propertyMap != null) {
            for (Entry<String, Object> entry : propertyMap.entrySet()) imageData.setProperty(entry.getKey(), entry.getValue());
        }
        long endTime = System.currentTimeMillis();
        // if (hierarchy == null) {
        // logger.error(String.format("%s does not contain a valid QUPath object hierarchy!", file.getAbsolutePath()));
        // return null;
        // }
        logger.debug(String.format("Hierarchy with %d object(s) read in %.2f seconds", hierarchy.nObjects(), (endTime - startTime) / 1000.));
    } catch (ClassNotFoundException e1) {
        logger.warn("Class not found reading image data", e1);
    } finally {
        if (localeChanged)
            Locale.setDefault(Category.FORMAT, locale);
    }
    return imageData;
}
Also used : Locale(java.util.Locale) PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) Workflow(qupath.lib.plugins.workflow.Workflow) EOFException(java.io.EOFException) FileNotFoundException(java.io.FileNotFoundException) IOException(java.io.IOException) BufferedInputStream(java.io.BufferedInputStream) ImageData(qupath.lib.images.ImageData) EOFException(java.io.EOFException) PathObject(qupath.lib.objects.PathObject) Map(java.util.Map) HashMap(java.util.HashMap) ObjectInputStream(java.io.ObjectInputStream) ColorDeconvolutionStains(qupath.lib.color.ColorDeconvolutionStains)

Example 14 with PathObjectHierarchy

use of qupath.lib.objects.hierarchy.PathObjectHierarchy in project qupath by qupath.

the class GuiTools method promptToClearAllSelectedObjects.

/**
 * Prompt user to select all currently-selected objects (except TMA core objects).
 *
 * @param imageData
 * @return
 */
public static boolean promptToClearAllSelectedObjects(final ImageData<?> imageData) {
    // Get all non-TMA core objects
    PathObjectHierarchy hierarchy = imageData.getHierarchy();
    Collection<PathObject> selectedRaw = hierarchy.getSelectionModel().getSelectedObjects();
    List<PathObject> selected = selectedRaw.stream().filter(p -> !(p instanceof TMACoreObject)).collect(Collectors.toList());
    if (selected.isEmpty()) {
        if (selectedRaw.size() > selected.size())
            Dialogs.showErrorMessage("Delete selected objects", "No valid objects selected! \n\nNote: Individual TMA cores cannot be deleted with this method.");
        else
            Dialogs.showErrorMessage("Delete selected objects", "No objects selected!");
        return false;
    }
    int n = selected.size();
    String message;
    if (n == 1)
        message = "Delete selected object?";
    else
        message = "Delete " + n + " selected objects?";
    if (Dialogs.showYesNoDialog("Delete objects", message)) {
        // Check for descendants
        List<PathObject> children = new ArrayList<>();
        for (PathObject temp : selected) {
            children.addAll(temp.getChildObjects());
        }
        children.removeAll(selected);
        boolean keepChildren = true;
        if (!children.isEmpty()) {
            Dialogs.DialogButton response = Dialogs.showYesNoCancelDialog("Delete objects", "Keep descendant objects?");
            if (response == Dialogs.DialogButton.CANCEL)
                return false;
            keepChildren = response == Dialogs.DialogButton.YES;
        }
        hierarchy.removeObjects(selected, keepChildren);
        hierarchy.getSelectionModel().clearSelection();
        imageData.getHistoryWorkflow().addStep(new DefaultScriptableWorkflowStep("Delete selected objects", "clearSelectedObjects(" + keepChildren + ");"));
        if (keepChildren)
            logger.info(selected.size() + " object(s) deleted");
        else
            logger.info(selected.size() + " object(s) deleted with descendants");
        imageData.getHistoryWorkflow().addStep(new DefaultScriptableWorkflowStep("Delete selected objects", "clearSelectedObjects();"));
        logger.info(selected.size() + " object(s) deleted");
        return true;
    } else
        return false;
}
Also used : CheckComboBox(org.controlsfx.control.CheckComboBox) UnaryOperator(java.util.function.UnaryOperator) TextFormatter(javafx.scene.control.TextFormatter) PathRootObject(qupath.lib.objects.PathRootObject) ParameterList(qupath.lib.plugins.parameters.ParameterList) PointsROI(qupath.lib.roi.PointsROI) Matcher(java.util.regex.Matcher) Action(java.awt.Desktop.Action) ColorTools(qupath.lib.common.ColorTools) GraphicsContext(javafx.scene.canvas.GraphicsContext) Canvas(javafx.scene.canvas.Canvas) Screen(javafx.stage.Screen) PathAnnotationObject(qupath.lib.objects.PathAnnotationObject) Platform(javafx.application.Platform) CountDownLatch(java.util.concurrent.CountDownLatch) Transparency(java.awt.Transparency) Clipboard(javafx.scene.input.Clipboard) SimpleDoubleProperty(javafx.beans.property.SimpleDoubleProperty) StringProperty(javafx.beans.property.StringProperty) Callable(java.util.concurrent.Callable) PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) DefaultColorDeconvolutionStains(qupath.lib.color.ColorDeconvolutionStains.DefaultColorDeconvolutionStains) Bindings(javafx.beans.binding.Bindings) NumberFormat(java.text.NumberFormat) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) Slider(javafx.scene.control.Slider) SplitAnnotationsPlugin(qupath.lib.plugins.objects.SplitAnnotationsPlugin) GridPane(javafx.scene.layout.GridPane) Color(javafx.scene.paint.Color) GeneralTools(qupath.lib.common.GeneralTools) Commands(qupath.lib.gui.commands.Commands) Node(javafx.scene.Node) CheckBox(javafx.scene.control.CheckBox) IOException(java.io.IOException) File(java.io.File) PathObjectTools(qupath.lib.objects.PathObjectTools) Menu(javafx.scene.control.Menu) ROI(qupath.lib.roi.interfaces.ROI) SimpleObjectProperty(javafx.beans.property.SimpleObjectProperty) ObservableValue(javafx.beans.value.ObservableValue) Image(javafx.scene.image.Image) Button(javafx.scene.control.Button) ImageServer(qupath.lib.images.servers.ImageServer) CombineOp(qupath.lib.roi.RoiTools.CombineOp) DoubleBinding(javafx.beans.binding.DoubleBinding) ListCell(javafx.scene.control.ListCell) CheckMenuItem(javafx.scene.control.CheckMenuItem) LoggerFactory(org.slf4j.LoggerFactory) RenderingHints(java.awt.RenderingHints) Side(javafx.geometry.Side) ContextMenu(javafx.scene.control.ContextMenu) URI(java.net.URI) QuPathGUI(qupath.lib.gui.QuPathGUI) TextField(javafx.scene.control.TextField) MenuItem(javafx.scene.control.MenuItem) BufferedImage(java.awt.image.BufferedImage) Collection(java.util.Collection) Spinner(javafx.scene.control.Spinner) Collectors(java.util.stream.Collectors) StainVector(qupath.lib.color.StainVector) PathObject(qupath.lib.objects.PathObject) SeparatorMenuItem(javafx.scene.control.SeparatorMenuItem) QuPathViewer(qupath.lib.gui.viewer.QuPathViewer) List(java.util.List) Robot(javafx.scene.robot.Robot) DefaultScriptableWorkflowStep(qupath.lib.plugins.workflow.DefaultScriptableWorkflowStep) Pattern(java.util.regex.Pattern) ClipboardContent(javafx.scene.input.ClipboardContent) Scene(javafx.scene.Scene) ListView(javafx.scene.control.ListView) TextArea(javafx.scene.control.TextArea) ParsePosition(java.text.ParsePosition) DoubleProperty(javafx.beans.property.DoubleProperty) ColorDeconvolutionHelper(qupath.lib.color.ColorDeconvolutionHelper) Function(java.util.function.Function) Dialogs(qupath.lib.gui.dialogs.Dialogs) ColorDeconvolutionStains(qupath.lib.color.ColorDeconvolutionStains) SwingUtilities(javax.swing.SwingUtilities) Graphics2D(java.awt.Graphics2D) ActionTools(qupath.lib.gui.ActionTools) Tooltip(javafx.scene.control.Tooltip) ColorPicker(javafx.scene.control.ColorPicker) ImageData(qupath.lib.images.ImageData) Desktop(java.awt.Desktop) ObjectProperty(javafx.beans.property.ObjectProperty) Logger(org.slf4j.Logger) Label(javafx.scene.control.Label) WritableImage(javafx.scene.image.WritableImage) TMACoreObject(qupath.lib.objects.TMACoreObject) DoubleSpinnerValueFactory(javafx.scene.control.SpinnerValueFactory.DoubleSpinnerValueFactory) SimpleBooleanProperty(javafx.beans.property.SimpleBooleanProperty) Stage(javafx.stage.Stage) SpinnerValueFactory(javafx.scene.control.SpinnerValueFactory) SwingFXUtils(javafx.embed.swing.SwingFXUtils) Window(javafx.stage.Window) Collections(java.util.Collections) PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) TMACoreObject(qupath.lib.objects.TMACoreObject) ArrayList(java.util.ArrayList) DefaultScriptableWorkflowStep(qupath.lib.plugins.workflow.DefaultScriptableWorkflowStep) PathObject(qupath.lib.objects.PathObject) Dialogs(qupath.lib.gui.dialogs.Dialogs)

Example 15 with PathObjectHierarchy

use of qupath.lib.objects.hierarchy.PathObjectHierarchy 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)

Aggregations

PathObjectHierarchy (qupath.lib.objects.hierarchy.PathObjectHierarchy)85 PathObject (qupath.lib.objects.PathObject)57 ArrayList (java.util.ArrayList)38 ROI (qupath.lib.roi.interfaces.ROI)31 List (java.util.List)24 Collectors (java.util.stream.Collectors)24 TMACoreObject (qupath.lib.objects.TMACoreObject)23 BufferedImage (java.awt.image.BufferedImage)22 IOException (java.io.IOException)22 Logger (org.slf4j.Logger)22 LoggerFactory (org.slf4j.LoggerFactory)22 ImageData (qupath.lib.images.ImageData)20 PathAnnotationObject (qupath.lib.objects.PathAnnotationObject)20 Collection (java.util.Collection)19 Collections (java.util.Collections)19 Map (java.util.Map)19 File (java.io.File)17 Arrays (java.util.Arrays)16 PathObjectTools (qupath.lib.objects.PathObjectTools)16 GeneralTools (qupath.lib.common.GeneralTools)15