Search in sources :

Example 96 with PathObject

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

the class RetainedTrainingObjects method put.

Map<PathClass, List<PathObject>> put(final String key, final Map<PathClass, List<PathObject>> value) {
    if (key == null)
        throw new IllegalArgumentException("Cannot retain objects without a key! Do you have a project open?");
    // Also, we create a new map to ensure it's sorted
    Map<PathClass, List<PathObject>> newMap = new TreeMap<>();
    for (PathClass pathClass : value.keySet()) {
        List<PathObject> originalList = value.get(pathClass);
        List<PathObject> newList = originalList.stream().map(p -> {
            if (p.isDetection())
                return PathObjects.createDetectionObject(p.getROI(), p.getPathClass(), p.getMeasurementList());
            else {
                logger.debug("Adding non-detection object to retained map: {}", p);
                return p;
            }
        }).collect(Collectors.toList());
        newMap.put(pathClass, newList);
        value.put(pathClass, newList);
    }
    return retainedObjectsMap.put(key, value);
}
Also used : Logger(org.slf4j.Logger) Externalizable(java.io.Externalizable) ObjectOutput(java.io.ObjectOutput) PathObjects(qupath.lib.objects.PathObjects) LoggerFactory(org.slf4j.LoggerFactory) PathClass(qupath.lib.objects.classes.PathClass) IOException(java.io.IOException) HashMap(java.util.HashMap) PathClassFactory(qupath.lib.objects.classes.PathClassFactory) Collectors(java.util.stream.Collectors) ArrayList(java.util.ArrayList) PathObject(qupath.lib.objects.PathObject) List(java.util.List) TreeMap(java.util.TreeMap) Map(java.util.Map) Entry(java.util.Map.Entry) ObjectInput(java.io.ObjectInput) Collections(java.util.Collections) PathClass(qupath.lib.objects.classes.PathClass) PathObject(qupath.lib.objects.PathObject) ArrayList(java.util.ArrayList) List(java.util.List) TreeMap(java.util.TreeMap)

Example 97 with PathObject

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

the class ClassifierBuilderPane method hierarchyChanged.

@Override
public void hierarchyChanged(PathObjectHierarchyEvent event) {
    if (event.getSource() == this)
        return;
    if (!Platform.isFxApplicationThread()) {
        Platform.runLater(() -> hierarchyChanged(event));
        return;
    }
    // Flag that the hierarchy has changed if this is any kind of event other than an object classification event
    hierarchyChanged = hierarchyChanged || !event.isObjectClassificationEvent();
    // TODO: Avoid reliance on this, and instead check the training objects used
    if (event.isStructureChangeEvent()) {
        // Don't respond to adding/removing annotation objects without classes set
        if (event.isAddedOrRemovedEvent()) {
            PathObject pathObjectChanged = event.getChangedObjects().get(0);
            if (!(pathObjectChanged instanceof PathAnnotationObject) || pathObjectChanged.getPathClass() == null)
                return;
        }
    } else if (event.isObjectClassificationEvent()) {
        // If classifications have changed, we only care if these contain annotations
        boolean containsAnnotations = containsObjectsOfClass(event.getChangedObjects(), PathAnnotationObject.class);
        if (!containsAnnotations)
            return;
    } else if (event.getEventType() == HierarchyEventType.CHANGE_OTHER) {
        return;
    }
    // TODO: See if calls can be reduced
    maybeUpdate();
}
Also used : PathAnnotationObject(qupath.lib.objects.PathAnnotationObject) PathObject(qupath.lib.objects.PathObject)

Example 98 with PathObject

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

the class FeatureSelectionPane method makeFeatureSelectionPanel.

BorderPane makeFeatureSelectionPanel(final QuPathGUI qupath) {
    tableFeatures.setTooltip(new Tooltip("Select object features to be used by the classifier"));
    TableColumn<SelectableFeature, String> columnName = new TableColumn<>("Feature name");
    columnName.setCellValueFactory(new PropertyValueFactory<>("featureName"));
    columnName.setEditable(false);
    TableColumn<SelectableFeature, Boolean> columnSelected = new TableColumn<>("Selected");
    columnSelected.setCellValueFactory(new PropertyValueFactory<>("selected"));
    columnSelected.setCellFactory(column -> new CheckBoxTableCell<>());
    columnSelected.setEditable(true);
    columnSelected.setResizable(false);
    columnName.prefWidthProperty().bind(tableFeatures.widthProperty().subtract(columnSelected.widthProperty()));
    tableFeatures.getColumns().add(columnName);
    tableFeatures.getColumns().add(columnSelected);
    tableFeatures.getSelectionModel().setSelectionMode(SelectionMode.MULTIPLE);
    tableFeatures.setEditable(true);
    ContextMenu menu = new ContextMenu();
    MenuItem itemSelect = new MenuItem("Select");
    itemSelect.setOnAction(e -> {
        for (SelectableFeature feature : tableFeatures.getSelectionModel().getSelectedItems()) feature.setSelected(true);
    });
    menu.getItems().add(itemSelect);
    MenuItem itemDeselect = new MenuItem("Deselect");
    itemDeselect.setOnAction(e -> {
        for (SelectableFeature feature : tableFeatures.getSelectionModel().getSelectedItems()) feature.setSelected(false);
    });
    menu.getItems().add(itemDeselect);
    menu.getItems().add(new SeparatorMenuItem());
    MenuItem itemDelete = new MenuItem("Delete highlighted features");
    itemDelete.setOnAction(e -> {
        List<String> highlightedFeatures = new ArrayList<>();
        for (SelectableFeature feature : tableFeatures.getSelectionModel().getSelectedItems()) highlightedFeatures.add(feature.getFeatureName());
        int nFeatures = highlightedFeatures.size();
        ImageData<?> imageData = qupath.getImageData();
        if (nFeatures == 0 || imageData == null || imageData.getHierarchy().isEmpty())
            return;
        String f = nFeatures == 1 ? "1 feature" : nFeatures + " features";
        if (!Dialogs.showYesNoDialog("Delete feature measurements", "Are you sure you want to permanently delete " + f + " from all objects?"))
            return;
        // Determine the features to remove
        // Loop through objects and delete features
        List<PathObject> changedObjects = new ArrayList<>();
        for (PathObject pathObject : imageData.getHierarchy().getFlattenedObjectList(null)) {
            // TODO: Consider if non-detection objects should be supported
            if (!pathObject.isDetection())
                continue;
            // Remove measurements & log as changed, if necessary
            MeasurementList ml = pathObject.getMeasurementList();
            int sizeBefore = ml.size();
            ml.removeMeasurements(highlightedFeatures.toArray(new String[0]));
            ml.close();
            int sizeAfter = ml.size();
            if (sizeAfter != sizeBefore)
                changedObjects.add(pathObject);
        }
        imageData.getHierarchy().fireObjectMeasurementsChangedEvent(this, changedObjects);
        tableFeatures.getSelectionModel().clearSelection();
        if (!hasFeatures())
            ensureMeasurementsUpdated();
    // classifierData.setFeaturesSelected(features, false);
    // tableFeatures.repaint();
    });
    menu.getItems().add(itemDelete);
    tableFeatures.setContextMenu(menu);
    // Button to update the features
    BorderPane panelButtons = new BorderPane();
    // Button btnUpdateFeatures = new Button("Update feature table");
    // btnUpdateFeatures.setTooltip(new Tooltip("Check all objects & available features"));
    // btnUpdateFeatures.setOnAction(e -> {
    // ensureMeasurementsUpdated();
    // if (panelIntensities != null)
    // panelIntensities.setAvailableMeasurements(getAvailableFeatures(), "mean", "dab");
    // });
    Button btnSelectAll = new Button("Select all");
    btnSelectAll.setOnAction(e -> {
        if (!hasFeatures())
            ensureMeasurementsUpdated();
        for (SelectableFeature feature : tableFeatures.getItems()) feature.setSelected(true);
    });
    Button btnSelectNone = new Button("Select none");
    btnSelectNone.setOnAction(e -> {
        if (!hasFeatures())
            ensureMeasurementsUpdated();
        for (SelectableFeature feature : tableFeatures.getItems()) feature.setSelected(false);
    });
    GridPane panelSelectButtons = PaneTools.createColumnGridControls(btnSelectAll, btnSelectNone);
    panelButtons.setTop(panelSelectButtons);
    // panelButtons.setBottom(btnUpdateFeatures);
    // btnUpdateFeatures.prefWidthProperty().bind(panelButtons.widthProperty());
    BorderPane panelFeatures = new BorderPane();
    panelFeatures.setCenter(tableFeatures);
    panelFeatures.setBottom(panelButtons);
    ensureMeasurementsUpdated();
    return panelFeatures;
}
Also used : BorderPane(javafx.scene.layout.BorderPane) GridPane(javafx.scene.layout.GridPane) Tooltip(javafx.scene.control.Tooltip) MeasurementList(qupath.lib.measurements.MeasurementList) ArrayList(java.util.ArrayList) ContextMenu(javafx.scene.control.ContextMenu) MenuItem(javafx.scene.control.MenuItem) SeparatorMenuItem(javafx.scene.control.SeparatorMenuItem) SeparatorMenuItem(javafx.scene.control.SeparatorMenuItem) TableColumn(javafx.scene.control.TableColumn) PathObject(qupath.lib.objects.PathObject) Button(javafx.scene.control.Button)

Example 99 with PathObject

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

the class ParameterDialogWrapper method createDialog.

private Stage createDialog(final PathInteractivePlugin<T> plugin, final ParameterList params, final PluginRunner<T> pluginRunner) {
    panel = new ParameterPanelFX(params);
    panel.getPane().setPadding(new Insets(5, 5, 5, 5));
    // panel.addParameterChangeListener(new ParameterChangeListener() {
    // 
    // @Override
    // public void parameterChanged(ParameterList parameterList, String key, boolean isAdjusting) {
    // 
    // if (!plugin.requestLiveUpdate())
    // return;
    // 
    // PathObjectHierarchy hierarchy = pluginRunner.getHierarchy();
    // if (hierarchy == null)
    // return;
    // 
    // Collection<Class<? extends PathObject>> supportedParents = plugin.getSupportedParentObjectClasses();
    // 
    // PathObject selectedObject = pluginRunner.getSelectedObject();
    // if (selectedObject == null) {
    // if (supportedParents.contains(PathRootObject.class))
    // Collections.singleton(hierarchy.getRootObject());
    // } else if (supportedParents.contains(selectedObject.getClass()))
    // Collections.singleton(selectedObject);
    // }
    // 
    // });
    // final Button btnRun = new Button("Run " + plugin.getName());
    final Button btnRun = new Button("Run");
    btnRun.textProperty().bind(Bindings.createStringBinding(() -> {
        if (btnRun.isDisabled())
            return "Please wait...";
        else
            return "Run";
    }, btnRun.disabledProperty()));
    final Stage dialog = new Stage();
    QuPathGUI qupath = QuPathGUI.getInstance();
    if (qupath != null)
        dialog.initOwner(qupath.getStage());
    dialog.setTitle(plugin.getName());
    final String emptyLabel = " \n";
    final Label label = new Label(emptyLabel);
    label.setStyle("-fx-font-weight: bold;");
    label.setPadding(new Insets(5, 5, 5, 5));
    label.setAlignment(Pos.CENTER);
    label.setTextAlignment(TextAlignment.CENTER);
    btnRun.setOnAction(e -> {
        // Check if we have the parent objects available to make this worthwhile
        if (plugin instanceof PathInteractivePlugin) {
            // // Strip off any of our extra parameters
            // params.removeParameter(KEY_REGIONS);
            boolean alwaysPrompt = plugin.alwaysPromptForObjects();
            ImageData<?> imageData = pluginRunner.getImageData();
            Collection<PathObject> selected = imageData == null ? Collections.emptyList() : imageData.getHierarchy().getSelectionModel().getSelectedObjects();
            Collection<? extends PathObject> parents = PathObjectTools.getSupportedObjects(selected, plugin.getSupportedParentObjectClasses());
            if (alwaysPrompt || parents == null || parents.isEmpty()) {
                if (!ParameterDialogWrapper.promptForParentObjects(pluginRunner, plugin, alwaysPrompt && !parents.isEmpty()))
                    return;
            }
        // promptForParentObjects
        }
        dialog.getScene().setCursor(Cursor.WAIT);
        btnRun.setDisable(true);
        Runnable runnable = new Runnable() {

            @Override
            public void run() {
                try {
                    WorkflowStep lastStep = pluginRunner.getImageData().getHistoryWorkflow().getLastStep();
                    boolean success = plugin.runPlugin(pluginRunner, ParameterList.getParameterListJSON(params, "  "));
                    WorkflowStep lastStepNew = pluginRunner.getImageData().getHistoryWorkflow().getLastStep();
                    if (success && lastStep != lastStepNew)
                        lastWorkflowStep = lastStepNew;
                    else
                        lastWorkflowStep = null;
                } catch (Exception e) {
                    Dialogs.showErrorMessage("Plugin error", e);
                } catch (OutOfMemoryError e) {
                    // This doesn't actually work...
                    Dialogs.showErrorMessage("Out of memory error", "Out of memory - try to close other applications, or decrease the number of parallel processors in the QuPath preferences");
                } finally {
                    Platform.runLater(() -> {
                        QuPathGUI.getInstance().pluginRunningProperty().set(false);
                        dialog.getScene().setCursor(Cursor.DEFAULT);
                        label.setText(plugin.getLastResultsDescription());
                        btnRun.setDisable(false);
                    });
                }
            }
        };
        Thread t = new Thread(runnable, "Plugin thread");
        QuPathGUI.getInstance().pluginRunningProperty().set(true);
        t.start();
    });
    BorderPane pane = new BorderPane();
    ScrollPane scrollPane = new ScrollPane();
    label.setMaxWidth(Double.MAX_VALUE);
    scrollPane.setContent(panel.getPane());
    scrollPane.setFitToWidth(true);
    pane.setCenter(scrollPane);
    btnRun.setMaxWidth(Double.MAX_VALUE);
    btnRun.setPadding(new Insets(5, 5, 5, 5));
    pane.setBottom(btnRun);
    Scene scene = new Scene(pane);
    dialog.setScene(scene);
    // Request focus, to make it easier to run from the keyboard
    btnRun.requestFocus();
    dialog.sizeToScene();
    return dialog;
}
Also used : BorderPane(javafx.scene.layout.BorderPane) Insets(javafx.geometry.Insets) WorkflowStep(qupath.lib.plugins.workflow.WorkflowStep) Label(javafx.scene.control.Label) Scene(javafx.scene.Scene) ParameterPanelFX(qupath.lib.gui.dialogs.ParameterPanelFX) PathInteractivePlugin(qupath.lib.plugins.PathInteractivePlugin) PathObject(qupath.lib.objects.PathObject) Button(javafx.scene.control.Button) ScrollPane(javafx.scene.control.ScrollPane) Stage(javafx.stage.Stage)

Example 100 with PathObject

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

the class PathIntensityClassifierPane method updateIntensityHistogram.

private void updateIntensityHistogram() {
    String selected = comboIntensities.getSelectionModel().getSelectedItem();
    PathObjectHierarchy hierarchy = getHierarchy();
    // if (!"None".equals(selected) || hierarchy == null)
    if ("None".equals(selected) || hierarchy == null) {
        if (panelHistogram != null)
            panelHistogram.getHistogramData().clear();
        return;
    }
    // Try to make a histogram & set it in the panel
    // PathObject pathObjectSelected = hierarchy.getSelectionModel().getSelectedPathObject();
    // For now, always use all objects (not direct descendants only)
    Collection<PathObject> pathObjects = null;
    // if (pathObjectSelected == null || !pathObjectSelected.hasChildren())
    pathObjects = hierarchy.getDetectionObjects();
    // else
    // pathObjects = hierarchy.getDescendantObjects(pathObjectSelected, pathObjects, PathDetectionObject.class);
    // Histogram histogram = Histogram.makeMeasurementHistogram(pathObjects, (String)selected, 256);
    double[] values = Histogram.getMeasurementValues(pathObjects, (String) selected);
    Histogram histogram = new Histogram(values, 128);
    // Compute quartile values
    Arrays.sort(values);
    int nNaNs = 0;
    // NaNs should be at the end of the list
    for (int i = values.length - 1; i >= 0; i--) {
        if (Double.isNaN(values[i]))
            nNaNs++;
        else
            break;
    }
    // Should be same as histogram.getCountSum() ?
    int nValues = values.length - nNaNs;
    assert nValues == histogram.getCountSum();
    if (nValues > 0) {
        double median = values[nValues / 2];
        double quartile1 = values[(int) (nValues / 4 + .5)];
        double quartile3 = values[(int) (nValues * 3 / 4 + .5)];
        logger.info(String.format("%s Quartile 1: %.4f", selected, quartile1));
        logger.info(String.format("%s Median: %.4f", selected, median));
        logger.info(String.format("%s Quartile 3: %.4f", selected, quartile3));
        RunningStatistics stats = StatisticsHelper.computeRunningStatistics(values);
        logger.info(String.format("%s Mean: %.4f", selected, stats.getMean()));
        logger.info(String.format("%s Std.Dev.: %.4f", selected, stats.getStdDev()));
        panelHistogram.getHistogramData().setAll(HistogramPanelFX.createHistogramData(histogram, true, (Integer) null));
    } else
        panelHistogram.getHistogramData().clear();
    updateHistogramThresholdLines();
}
Also used : PathObjectHierarchy(qupath.lib.objects.hierarchy.PathObjectHierarchy) Histogram(qupath.lib.analysis.stats.Histogram) PathObject(qupath.lib.objects.PathObject) RunningStatistics(qupath.lib.analysis.stats.RunningStatistics)

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