Search in sources :

Example 11 with PathObject

use of qupath.lib.objects.PathObject in project qupath by qupath.

the class Commands method promptToDeleteObjects.

/**
 * Prompt to delete objects of a specified type, or all objects.
 * @param imageData
 * @param cls
 */
public static void promptToDeleteObjects(ImageData<?> imageData, Class<? extends PathObject> cls) {
    if (imageData == null)
        return;
    PathObjectHierarchy hierarchy = imageData.getHierarchy();
    // Handle no specified class - indicates all objects of all types should be cleared
    if (cls == null) {
        int n = hierarchy.nObjects();
        if (n == 0)
            return;
        String message;
        if (n == 1)
            message = "Delete object?";
        else
            message = "Delete all " + n + " objects?";
        if (Dialogs.showYesNoDialog("Delete objects", message)) {
            hierarchy.clearAll();
            hierarchy.getSelectionModel().setSelectedObject(null);
            imageData.getHistoryWorkflow().addStep(new DefaultScriptableWorkflowStep("Clear all objects", "clearAllObjects();"));
        }
        return;
    }
    // Handle clearing TMA grid
    if (TMACoreObject.class.equals(cls)) {
        if (hierarchy.getTMAGrid() != null) {
            if (Dialogs.showYesNoDialog("Delete objects", "Clear TMA grid?")) {
                hierarchy.setTMAGrid(null);
                PathObject selected = hierarchy.getSelectionModel().getSelectedObject();
                if (selected instanceof TMACoreObject)
                    hierarchy.getSelectionModel().setSelectedObject(null);
                imageData.getHistoryWorkflow().addStep(new DefaultScriptableWorkflowStep("Clear TMA Grid", "clearTMAGrid();"));
            }
            return;
        }
    }
    // Handle clearing objects of another specified type
    Collection<PathObject> pathObjects = hierarchy.getObjects(null, cls);
    if (pathObjects.isEmpty())
        return;
    int n = pathObjects.size();
    String message = n == 1 ? "Delete 1 object?" : "Delete " + n + " objects?";
    if (Dialogs.showYesNoDialog("Delete objects", message)) {
        hierarchy.removeObjects(pathObjects, true);
        PathObject selected = hierarchy.getSelectionModel().getSelectedObject();
        if (selected != null && selected.getClass().isAssignableFrom(cls))
            hierarchy.getSelectionModel().setSelectedObject(null);
        if (selected != null && selected.getClass().isAssignableFrom(cls))
            hierarchy.getSelectionModel().setSelectedObject(null);
        if (cls == PathDetectionObject.class)
            imageData.getHistoryWorkflow().addStep(new DefaultScriptableWorkflowStep("Clear detections", "clearDetections();"));
        else if (cls == PathAnnotationObject.class)
            imageData.getHistoryWorkflow().addStep(new DefaultScriptableWorkflowStep("Clear annotations", "clearAnnotations();"));
        else if (cls == TMACoreObject.class)
            imageData.getHistoryWorkflow().addStep(new DefaultScriptableWorkflowStep("Clear TMA grid", "clearTMAGrid();"));
        else
            logger.warn("Cannot clear all objects for class {}", cls);
    }
}
Also used : DefaultScriptableWorkflowStep(qupath.lib.plugins.workflow.DefaultScriptableWorkflowStep) PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) PathAnnotationObject(qupath.lib.objects.PathAnnotationObject) PathObject(qupath.lib.objects.PathObject) TMACoreObject(qupath.lib.objects.TMACoreObject)

Example 12 with PathObject

use of qupath.lib.objects.PathObject in project qupath by qupath.

the class Commands method requestShapeFeatures.

private static void requestShapeFeatures(ImageData<?> imageData, Collection<ShapeFeatures> features) {
    if (imageData == null)
        return;
    var featureArray = features.toArray(ShapeFeatures[]::new);
    if (featureArray.length == 0)
        return;
    Collection<PathObject> selected = imageData.getHierarchy().getSelectionModel().getSelectedObjects();
    if (selected.isEmpty()) {
        Dialogs.showWarningNotification("Shape features", "No objects selected!");
    } else {
        selected = new ArrayList<>(selected);
        String featureString = Arrays.stream(featureArray).map(f -> "\"" + f.name() + "\"").collect(Collectors.joining(", "));
        QP.addShapeMeasurements(imageData, selected, featureArray);
        imageData.getHistoryWorkflow().addStep(new DefaultScriptableWorkflowStep("Add shape measurements", String.format("addShapeMeasurements(%s)", featureString)));
        if (selected.size() == 1)
            Dialogs.showInfoNotification("Shape features", "Shape features calculated for one object");
        else
            Dialogs.showInfoNotification("Shape features", "Shape features calculated for " + selected.size() + " objects");
    }
}
Also used : Arrays(java.util.Arrays) ServerTools(qupath.lib.images.servers.ServerTools) PathTileObject(qupath.lib.objects.PathTileObject) StackPane(javafx.scene.layout.StackPane) ImageWriter(qupath.lib.images.writers.ImageWriter) ParameterList(qupath.lib.plugins.parameters.ParameterList) ImageRegion(qupath.lib.regions.ImageRegion) Map(java.util.Map) PathObjects(qupath.lib.objects.PathObjects) Screen(javafx.stage.Screen) WorkflowStep(qupath.lib.plugins.workflow.WorkflowStep) PathAnnotationObject(qupath.lib.objects.PathAnnotationObject) Project(qupath.lib.projects.Project) ShapeFeatures(qupath.lib.analysis.features.ObjectMeasurements.ShapeFeatures) MeasurementMapPane(qupath.lib.gui.panes.MeasurementMapPane) BorderPane(javafx.scene.layout.BorderPane) StringProperty(javafx.beans.property.StringProperty) RectangleROI(qupath.lib.roi.RectangleROI) CheckBoxListCell(javafx.scene.control.cell.CheckBoxListCell) PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) Supplier(java.util.function.Supplier) Bindings(javafx.beans.binding.Bindings) ViewTrackerControlPane(qupath.lib.gui.viewer.recording.ViewTrackerControlPane) Projects(qupath.lib.projects.Projects) ArrayList(java.util.ArrayList) CheckListView(org.controlsfx.control.CheckListView) ROIs(qupath.lib.roi.ROIs) ShapeSimplifier(qupath.lib.roi.ShapeSimplifier) TextAlignment(javafx.scene.text.TextAlignment) PathClassPane(qupath.lib.gui.panes.PathClassPane) GridPane(javafx.scene.layout.GridPane) Files(java.nio.file.Files) GeneralTools(qupath.lib.common.GeneralTools) RegionRequest(qupath.lib.regions.RegionRequest) Window(java.awt.Window) DistanceTools(qupath.lib.analysis.DistanceTools) IOException(java.io.IOException) File(java.io.File) OverlayOptions(qupath.lib.gui.viewer.OverlayOptions) PathObjectTools(qupath.lib.objects.PathObjectTools) ROI(qupath.lib.roi.interfaces.ROI) QP(qupath.lib.scripting.QP) GridLines(qupath.lib.gui.viewer.GridLines) PathPrefs(qupath.lib.gui.prefs.PathPrefs) RenderedImageServer(qupath.lib.gui.images.servers.RenderedImageServer) PaneTools(qupath.lib.gui.tools.PaneTools) PathIO(qupath.lib.io.PathIO) Button(javafx.scene.control.Button) Pos(javafx.geometry.Pos) ImageServer(qupath.lib.images.servers.ImageServer) CombineOp(qupath.lib.roi.RoiTools.CombineOp) LoggerFactory(org.slf4j.LoggerFactory) ObservableDoubleValue(javafx.beans.value.ObservableDoubleValue) ComboBox(javafx.scene.control.ComboBox) ImageServers(qupath.lib.images.servers.ImageServers) PolygonROI(qupath.lib.roi.PolygonROI) QuPathGUI(qupath.lib.gui.QuPathGUI) Pane(javafx.scene.layout.Pane) TextField(javafx.scene.control.TextField) BufferedImage(java.awt.image.BufferedImage) Collection(java.util.Collection) Collectors(java.util.stream.Collectors) PathDetectionObject(qupath.lib.objects.PathDetectionObject) PathObject(qupath.lib.objects.PathObject) QuPathViewer(qupath.lib.gui.viewer.QuPathViewer) Priority(javafx.scene.layout.Priority) List(java.util.List) DefaultScriptableWorkflowStep(qupath.lib.plugins.workflow.DefaultScriptableWorkflowStep) ProjectIO(qupath.lib.projects.ProjectIO) GuiTools(qupath.lib.gui.tools.GuiTools) TMASummaryViewer(qupath.lib.gui.tma.TMASummaryViewer) ImagePlane(qupath.lib.regions.ImagePlane) PathCellObject(qupath.lib.objects.PathCellObject) Scene(javafx.scene.Scene) WorkflowCommandLogView(qupath.lib.gui.panes.WorkflowCommandLogView) TextArea(javafx.scene.control.TextArea) ButtonType(javafx.scene.control.ButtonType) Action(org.controlsfx.control.action.Action) HashMap(java.util.HashMap) DoubleProperty(javafx.beans.property.DoubleProperty) Function(java.util.function.Function) Dialogs(qupath.lib.gui.dialogs.Dialogs) Insets(javafx.geometry.Insets) ActionTools(qupath.lib.gui.ActionTools) Tooltip(javafx.scene.control.Tooltip) WeakHashMap(java.util.WeakHashMap) ImageData(qupath.lib.images.ImageData) RoiTools(qupath.lib.roi.RoiTools) Modality(javafx.stage.Modality) Logger(org.slf4j.Logger) Label(javafx.scene.control.Label) Iterator(java.util.Iterator) ImageWriterTools(qupath.lib.images.writers.ImageWriterTools) TMACoreObject(qupath.lib.objects.TMACoreObject) Stage(javafx.stage.Stage) Collections(java.util.Collections) ContentDisplay(javafx.scene.control.ContentDisplay) DialogButton(qupath.lib.gui.dialogs.Dialogs.DialogButton) DefaultScriptableWorkflowStep(qupath.lib.plugins.workflow.DefaultScriptableWorkflowStep) PathObject(qupath.lib.objects.PathObject)

Example 13 with PathObject

use of qupath.lib.objects.PathObject in project qupath by qupath.

the class CountingPanelCommand method makeButtonPanel.

@SuppressWarnings("deprecation")
private Pane makeButtonPanel() {
    if (qupath == null)
        return null;
    VBox panel = new VBox();
    panel.setSpacing(10);
    // TilePane panel = new TilePane(Orientation.VERTICAL);
    // panel.setBorder(BorderFactory.createEmptyBorder(5, 10, 10, 10));
    sliderRadius = new Slider(1, 100, PathPrefs.pointRadiusProperty().get());
    sliderRadius.valueProperty().addListener(event -> {
        PathPrefs.pointRadiusProperty().set((int) sliderRadius.getValue());
        // PathPrefs.setMinPointSeparation(sliderRadius.getValue());
        qupath.getViewer().repaint();
    });
    // panel.setSpacing(10);
    BorderPane sliderPane = new BorderPane();
    sliderPane.setLeft(new Label("Point size"));
    sliderPane.setCenter(sliderRadius);
    // Add load/save buttons
    btnLoad = new Button("Load points");
    btnLoad.setOnAction(event -> {
        if (hierarchy == null)
            return;
        File file = Dialogs.promptForFile(null, null, "TSV (Tab delimited)", new String[] { "tsv" });
        if (file == null)
            return;
        try {
            List<PathObject> pointsList = null;
            if (file.toPath().toString().endsWith(".zip"))
                pointsList = PointIO.readPointsObjectList(file);
            else if (file.toPath().toString().endsWith(".tsv"))
                pointsList = PointIO.readPoints(file);
            if (pointsList != null) {
                for (PathObject points : pointsList) hierarchy.addPathObject(points);
            }
        } catch (IOException e) {
            Dialogs.showErrorMessage("Load points error", e);
        }
    });
    btnSave = new Button("Save points");
    btnSave.setOnAction(event -> {
        if (countingPanel == null)
            return;
        // Prompt the user with choice over which annotations to save
        ListView<PathObject> listView = countingPanel.getListView();
        var selection = listView.getSelectionModel().getSelectedItems();
        List<PathObject> pointsList = countingPanel.getPathObjects();
        if (!selection.isEmpty()) {
            ArrayList<String> choiceList = new ArrayList<>();
            choiceList.addAll(Arrays.asList("All point annotations", "Selected objects"));
            var choice = Dialogs.showChoiceDialog("Save points", "Choose point annotations to save", Arrays.asList("All points", "Selected points"), savingOption);
            if (choice == null)
                return;
            if (choice.equals("Selected points"))
                pointsList = selection;
            savingOption = choice;
        }
        if (pointsList.isEmpty()) {
            Dialogs.showErrorMessage("Save points", "No points available!");
            return;
        }
        String defaultName = null;
        try {
            // Sorry, this is lazy...
            defaultName = ServerTools.getDisplayableImageName(qupath.getViewer().getServer()) + "-points.tsv";
        } catch (Exception e) {
        // Ignore...
        }
        ;
        File file = Dialogs.promptToSaveFile(null, null, defaultName, "TSV (Tab delimited)", "tsv");
        if (file == null)
            return;
        try {
            PointIO.writePoints(file, pointsList);
        } catch (IOException e) {
            Dialogs.showErrorMessage("Save points error", e);
        }
    });
    GridPane panelLoadSave = PaneTools.createColumnGridControls(btnLoad, btnSave);
    var actionConvexPoints = ActionTools.createSelectableAction(PathPrefs.showPointHullsProperty(), "Show point convex hull");
    var actionSelectedColor = ActionTools.createSelectableAction(PathPrefs.useSelectedColorProperty(), "Highlight selected objects by color");
    var actionDetectionsToPoints = qupath.createImageDataAction(imageData -> Commands.convertDetectionsToPoints(imageData, true));
    actionDetectionsToPoints.setText("Convert detections to points");
    var btnConvert = ActionTools.createButton(actionDetectionsToPoints, false);
    var convertPane = new Pane(btnConvert);
    btnConvert.prefWidthProperty().bind(convertPane.widthProperty());
    var cbConvex = ActionTools.createCheckBox(actionConvexPoints);
    var cbSelected = ActionTools.createCheckBox(actionSelectedColor);
    // panel.setSpacing(5);
    panel.getChildren().addAll(cbConvex, cbSelected, sliderPane, convertPane, panelLoadSave);
    return panel;
}
Also used : BorderPane(javafx.scene.layout.BorderPane) GridPane(javafx.scene.layout.GridPane) Slider(javafx.scene.control.Slider) Label(javafx.scene.control.Label) ArrayList(java.util.ArrayList) IOException(java.io.IOException) GridPane(javafx.scene.layout.GridPane) Pane(javafx.scene.layout.Pane) BorderPane(javafx.scene.layout.BorderPane) IOException(java.io.IOException) PathObject(qupath.lib.objects.PathObject) Button(javafx.scene.control.Button) VBox(javafx.scene.layout.VBox) File(java.io.File)

Example 14 with PathObject

use of qupath.lib.objects.PathObject in project qupath by qupath.

the class CountingPanelCommand method attemptToSelectPoints.

private void attemptToSelectPoints() {
    if (hierarchy == null || countingPanel == null)
        return;
    logger.trace("Attempting to select");
    PathObject pathObjectSelected = hierarchy.getSelectionModel().getSelectedObject();
    // Try to set selected object to be a Point object
    if (pathObjectSelected == null || !PathObjectTools.hasPointROI(pathObjectSelected)) {
        List<PathObject> pointObjects = countingPanel.getPathObjects();
        if (pointObjects.isEmpty())
            hierarchy.getSelectionModel().setSelectedObject(null);
        else
            // Use the first point object
            hierarchy.getSelectionModel().setSelectedObject(pointObjects.get(0));
    }
}
Also used : PathObject(qupath.lib.objects.PathObject)

Example 15 with PathObject

use of qupath.lib.objects.PathObject in project qupath by qupath.

the class ExportObjectsCommand method runGeoJsonExport.

/**
 * Run the path object GeoJSON export command.
 * @param qupath
 * @return success
 * @throws IOException
 */
public static boolean runGeoJsonExport(QuPathGUI qupath) throws IOException {
    // Get ImageData
    var imageData = qupath.getImageData();
    if (imageData == null)
        return false;
    // Get hierarchy
    PathObjectHierarchy hierarchy = imageData.getHierarchy();
    String allObjects = "All objects";
    String selectedObjects = "Selected objects";
    String defaultObjects = hierarchy.getSelectionModel().noSelection() ? allObjects : selectedObjects;
    // Params
    var parameterList = new ParameterList().addChoiceParameter("exportOptions", "Export ", defaultObjects, Arrays.asList(allObjects, selectedObjects), "Choose which objects to export - run a 'Select annotations/detections' command first if needed").addBooleanParameter("excludeMeasurements", "Exclude measurements", false, "Exclude object measurements during export - for large numbers of detections this can help reduce the file size").addBooleanParameter("doPretty", "Pretty JSON", false, "Pretty GeoJSON is more human-readable but results in larger file sizes").addBooleanParameter("doFeatureCollection", "Export as FeatureCollection", true, "Export as a 'FeatureCollection', which is a standard GeoJSON way to represent multiple objects; if not, a regular JSON object/array will be export").addBooleanParameter("doZip", "Compress data (zip)", false, "Compressed files take less memory");
    if (!Dialogs.showParameterDialog("Export objects", parameterList))
        return false;
    Collection<PathObject> toProcess;
    var comboChoice = parameterList.getChoiceParameterValue("exportOptions");
    if (comboChoice.equals("Selected objects")) {
        if (hierarchy.getSelectionModel().noSelection()) {
            Dialogs.showErrorMessage("No selection", "No selection detected!");
            return false;
        }
        toProcess = hierarchy.getSelectionModel().getSelectedObjects();
    } else
        toProcess = hierarchy.getObjects(null, null);
    // Remove PathRootObject
    toProcess = toProcess.stream().filter(e -> !e.isRootObject()).collect(Collectors.toList());
    // Check if includes ellipse(s), as they will need to be polygonized
    var nEllipses = toProcess.stream().filter(ann -> isEllipse(ann)).count();
    if (nEllipses > 0) {
        String message = nEllipses == 1 ? "1 ellipse will be polygonized, continue?" : String.format("%d ellipses will be polygonized, continue?", nEllipses);
        var response = Dialogs.showYesNoDialog("Ellipse polygonization", message);
        if (!response)
            return false;
    }
    File outFile;
    // Get default name & output directory
    var project = qupath.getProject();
    String defaultName = imageData.getServer().getMetadata().getName();
    if (project != null) {
        var entry = project.getEntry(imageData);
        if (entry != null)
            defaultName = entry.getImageName();
    }
    defaultName = GeneralTools.getNameWithoutExtension(defaultName);
    File defaultDirectory = project == null || project.getPath() == null ? null : project.getPath().toFile();
    while (defaultDirectory != null && !defaultDirectory.isDirectory()) defaultDirectory = defaultDirectory.getParentFile();
    if (parameterList.getBooleanParameterValue("doZip"))
        outFile = Dialogs.promptToSaveFile("Export to file", defaultDirectory, defaultName + ".zip", "ZIP archive", ".zip");
    else
        outFile = Dialogs.promptToSaveFile("Export to file", defaultDirectory, defaultName + ".geojson", "GeoJSON", ".geojson");
    // If user cancels
    if (outFile == null)
        return false;
    List<GeoJsonExportOptions> options = new ArrayList<>();
    if (parameterList.getBooleanParameterValue("excludeMeasurements"))
        options.add(GeoJsonExportOptions.EXCLUDE_MEASUREMENTS);
    if (parameterList.getBooleanParameterValue("doPretty"))
        options.add(GeoJsonExportOptions.PRETTY_JSON);
    if (parameterList.getBooleanParameterValue("doFeatureCollection"))
        options.add(GeoJsonExportOptions.FEATURE_COLLECTION);
    // Export
    QP.exportObjectsToGeoJson(toProcess, outFile.getAbsolutePath(), options.toArray(GeoJsonExportOptions[]::new));
    // Notify user of success
    int nObjects = toProcess.size();
    String message = nObjects == 1 ? "1 object was exported to " + outFile.getAbsolutePath() : String.format("%d objects were exported to %s", nObjects, outFile.getAbsolutePath());
    Dialogs.showInfoNotification("Succesful export", message);
    // Get history workflow
    var historyWorkflow = imageData.getHistoryWorkflow();
    // args for workflow step
    Map<String, String> map = new LinkedHashMap<>();
    map.put("path", outFile.getPath());
    String method = comboChoice.equals(allObjects) ? "exportAllObjectsToGeoJson" : "exportSelectedObjectsToGeoJson";
    String methodTitle = comboChoice.equals(allObjects) ? "Export all objects" : "Export selected objects";
    String optionsString = options.stream().map(o -> "\"" + o.name() + "\"").collect(Collectors.joining(", "));
    map.put("options", optionsString);
    if (!optionsString.isEmpty())
        optionsString = ", " + optionsString;
    String methodString = String.format("%s(%s%s)", method, "\"" + GeneralTools.escapeFilePath(outFile.getPath()) + "\"", optionsString);
    historyWorkflow.addStep(new DefaultScriptableWorkflowStep(methodTitle, map, methodString));
    return true;
}
Also used : Arrays(java.util.Arrays) GeneralTools(qupath.lib.common.GeneralTools) GeoJsonExportOptions(qupath.lib.io.PathIO.GeoJsonExportOptions) Collection(java.util.Collection) IOException(java.io.IOException) PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) Collectors(java.util.stream.Collectors) File(java.io.File) ArrayList(java.util.ArrayList) PathObject(qupath.lib.objects.PathObject) LinkedHashMap(java.util.LinkedHashMap) Dialogs(qupath.lib.gui.dialogs.Dialogs) List(java.util.List) ParameterList(qupath.lib.plugins.parameters.ParameterList) DefaultScriptableWorkflowStep(qupath.lib.plugins.workflow.DefaultScriptableWorkflowStep) Map(java.util.Map) QP(qupath.lib.scripting.QP) QuPathGUI(qupath.lib.gui.QuPathGUI) PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) DefaultScriptableWorkflowStep(qupath.lib.plugins.workflow.DefaultScriptableWorkflowStep) PathObject(qupath.lib.objects.PathObject) ParameterList(qupath.lib.plugins.parameters.ParameterList) GeoJsonExportOptions(qupath.lib.io.PathIO.GeoJsonExportOptions) File(java.io.File)

Aggregations

PathObject (qupath.lib.objects.PathObject)182 ArrayList (java.util.ArrayList)84 ROI (qupath.lib.roi.interfaces.ROI)74 PathObjectHierarchy (qupath.lib.objects.hierarchy.PathObjectHierarchy)61 List (java.util.List)48 BufferedImage (java.awt.image.BufferedImage)37 IOException (java.io.IOException)37 PathClass (qupath.lib.objects.classes.PathClass)37 Collectors (java.util.stream.Collectors)35 PathAnnotationObject (qupath.lib.objects.PathAnnotationObject)34 Map (java.util.Map)33 Logger (org.slf4j.Logger)33 LoggerFactory (org.slf4j.LoggerFactory)33 ImageData (qupath.lib.images.ImageData)31 TMACoreObject (qupath.lib.objects.TMACoreObject)31 Collection (java.util.Collection)29 Collections (java.util.Collections)29 HashMap (java.util.HashMap)28 PathObjectTools (qupath.lib.objects.PathObjectTools)26 Arrays (java.util.Arrays)25