Search in sources :

Example 6 with ImageDisplay

use of qupath.lib.display.ImageDisplay in project qupath by qupath.

the class ImageJMacroRunner method runMacro.

static void runMacro(final ParameterList params, final ImageData<BufferedImage> imageData, final ImageDisplay imageDisplay, final PathObject pathObject, final String macroText) {
    // Don't try if interrupted
    if (Thread.currentThread().isInterrupted()) {
        logger.warn("Skipping macro for {} - thread interrupted", pathObject);
        return;
    }
    PathImage<ImagePlus> pathImage;
    // Extract parameters
    double downsampleFactor = params.getDoubleParameterValue("downsampleFactor");
    boolean sendROI = params.getBooleanParameterValue("sendROI");
    boolean sendOverlay = params.getBooleanParameterValue("sendOverlay");
    ROI pathROI = pathObject.getROI();
    ImageDisplay imageDisplay2 = params.containsKey("useTransform") && Boolean.TRUE.equals(params.getBooleanParameterValue("useTransform")) ? imageDisplay : null;
    ImageServer<BufferedImage> server = imageDisplay2 == null || imageDisplay2.availableChannels().isEmpty() ? imageData.getServer() : ChannelDisplayTransformServer.createColorTransformServer(imageData.getServer(), imageDisplay.availableChannels());
    RegionRequest region = RegionRequest.createInstance(imageData.getServer().getPath(), downsampleFactor, pathROI);
    // Check the size of the region to extract - abort if it is too large of if ther isn't enough RAM
    try {
        IJTools.isMemorySufficient(region, imageData);
    } catch (Exception e1) {
        Dialogs.showErrorMessage("ImageJ macro error", e1.getMessage());
        return;
    }
    try {
        if (sendOverlay)
            pathImage = IJExtension.extractROIWithOverlay(server, pathObject, imageData.getHierarchy(), region, sendROI, null);
        else
            pathImage = IJExtension.extractROI(server, pathObject, region, sendROI);
    } catch (IOException e) {
        logger.error("Unable to extract image region " + region, e);
        return;
    }
    // IJHelpers.getImageJInstance();
    // ImageJ ij = IJHelpers.getImageJInstance();
    // if (ij != null && WindowManager.getIDList() == null)
    // ij.setVisible(false);
    // Determine a sensible argument to pass
    String argument;
    if (pathObject instanceof TMACoreObject || !pathObject.hasROI())
        argument = pathObject.getDisplayedName();
    else
        argument = String.format("Region (%d, %d, %d, %d)", region.getX(), region.getY(), region.getWidth(), region.getHeight());
    // Check if we have an image already - if so, we need to be more cautious so we don't accidentally use it...
    // boolean hasImage = WindowManager.getCurrentImage() != null;
    // Actually run the macro
    final ImagePlus imp = pathImage.getImage();
    imp.setProperty("QuPath region", argument);
    WindowManager.setTempCurrentImage(imp);
    // Ensure we've requested an instance, since this also loads any required extra plugins
    IJExtension.getImageJInstance();
    // TODO: Pay attention to how threading should be done... I think Swing EDT ok?
    try {
        // SwingUtilities.invokeAndWait(() -> {
        boolean cancelled = false;
        ImagePlus impResult = null;
        try {
            IJ.redirectErrorMessages();
            Interpreter interpreter = new Interpreter();
            impResult = interpreter.runBatchMacro(macroText, imp);
            // If we had an error, return
            if (interpreter.wasError()) {
                Thread.currentThread().interrupt();
                return;
            }
            // Get the resulting image, if available
            if (impResult == null)
                impResult = WindowManager.getCurrentImage();
        } catch (RuntimeException e) {
            logger.error(e.getLocalizedMessage());
            // DisplayHelpers.showErrorMessage("ImageJ macro error", e.getLocalizedMessage());
            Thread.currentThread().interrupt();
            cancelled = true;
        } finally {
            // IJ.runMacro(macroText, argument);
            WindowManager.setTempCurrentImage(null);
        // IJ.run("Close all");
        }
        if (cancelled)
            return;
        // Get the current image when the macro has finished - which may or may not be the same as the original
        if (impResult == null)
            impResult = imp;
        boolean changes = false;
        if (params.getBooleanParameterValue("clearObjects") && pathObject.hasChildren()) {
            pathObject.clearPathObjects();
            changes = true;
        }
        if (params.getBooleanParameterValue("getROI") && impResult.getRoi() != null) {
            Roi roi = impResult.getRoi();
            Calibration cal = impResult.getCalibration();
            PathObject pathObjectNew = roi == null ? null : IJTools.convertToAnnotation(roi, cal.xOrigin, cal.yOrigin, downsampleFactor, region.getPlane());
            if (pathObjectNew != null) {
                // If necessary, trim any returned annotation
                if (pathROI != null && !(pathROI instanceof RectangleROI) && pathObjectNew.isAnnotation() && RoiTools.isShapeROI(pathROI) && RoiTools.isShapeROI(pathObjectNew.getROI())) {
                    ROI roiNew = RoiTools.combineROIs(pathROI, pathObjectNew.getROI(), CombineOp.INTERSECT);
                    ((PathAnnotationObject) pathObjectNew).setROI(roiNew);
                }
                // Only add if we have something
                if (pathObjectNew.getROI() instanceof LineROI || !pathObjectNew.getROI().isEmpty()) {
                    pathObject.addPathObject(pathObjectNew);
                    // imageData.getHierarchy().addPathObject(IJHelpers.convertToPathObject(imp, imageData.getServer(), imp.getRoi(), downsampleFactor, false), true);
                    changes = true;
                }
            }
        }
        boolean exportAsDetection = ((String) params.getChoiceParameterValue("getOverlayAs")).equals("Detections") ? true : false;
        if (params.getBooleanParameterValue("getOverlay") && impResult.getOverlay() != null) {
            var overlay = impResult.getOverlay();
            List<PathObject> childObjects = QuPath_Send_Overlay_to_QuPath.createObjectsFromROIs(imp, Arrays.asList(overlay.toArray()), downsampleFactor, exportAsDetection, true, region.getPlane());
            if (!childObjects.isEmpty()) {
                pathObject.addPathObjects(childObjects);
                changes = true;
            }
        // for (Roi roi : impResult.getOverlay().toArray()) {
        // pathObject.addPathObject(IJTools.convertToPathObject(imp, imageData.getServer(), roi, downsampleFactor, true));
        // changes = true;
        // }
        }
        if (changes) {
            Platform.runLater(() -> imageData.getHierarchy().fireHierarchyChangedEvent(null));
        }
    // });
    } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}
Also used : Interpreter(ij.macro.Interpreter) TMACoreObject(qupath.lib.objects.TMACoreObject) IOException(java.io.IOException) Calibration(ij.measure.Calibration) ImagePlus(ij.ImagePlus) RectangleROI(qupath.lib.roi.RectangleROI) LineROI(qupath.lib.roi.LineROI) ROI(qupath.lib.roi.interfaces.ROI) Roi(ij.gui.Roi) BufferedImage(java.awt.image.BufferedImage) InvocationTargetException(java.lang.reflect.InvocationTargetException) IOException(java.io.IOException) PathAnnotationObject(qupath.lib.objects.PathAnnotationObject) PathObject(qupath.lib.objects.PathObject) RectangleROI(qupath.lib.roi.RectangleROI) LineROI(qupath.lib.roi.LineROI) RegionRequest(qupath.lib.regions.RegionRequest) ImageDisplay(qupath.lib.display.ImageDisplay)

Aggregations

ImageDisplay (qupath.lib.display.ImageDisplay)6 BufferedImage (java.awt.image.BufferedImage)3 ChannelDisplayInfo (qupath.lib.display.ChannelDisplayInfo)3 DirectServerChannelInfo (qupath.lib.display.DirectServerChannelInfo)3 ImageData (qupath.lib.images.ImageData)3 ArrayList (java.util.ArrayList)2 HashSet (java.util.HashSet)2 List (java.util.List)2 Set (java.util.Set)2 Collectors (java.util.stream.Collectors)2 Platform (javafx.application.Platform)2 BooleanProperty (javafx.beans.property.BooleanProperty)2 SimpleBooleanProperty (javafx.beans.property.SimpleBooleanProperty)2 SimpleObjectProperty (javafx.beans.property.SimpleObjectProperty)2 ChangeListener (javafx.beans.value.ChangeListener)2 ObservableValue (javafx.beans.value.ObservableValue)2 FXCollections (javafx.collections.FXCollections)2 EventHandler (javafx.event.EventHandler)2 Tooltip (javafx.scene.control.Tooltip)2 KeyCode (javafx.scene.input.KeyCode)2