Search in sources :

Example 1 with DensityMapBuilder

use of qupath.lib.analysis.heatmaps.DensityMaps.DensityMapBuilder in project qupath by qupath.

the class LoadResourceCommand method run.

@Override
public void run() {
    String title = resourceType.getDialogTitle();
    var cachedServers = new WeakHashMap<ImageData<BufferedImage>, ImageServer<BufferedImage>>();
    var overlay = PixelClassificationOverlay.create(qupath.getOverlayOptions(), cachedServers, new ColorModelRenderer(null));
    overlay.setMaxThreads(nThreads);
    for (var viewer : qupath.getViewers()) viewer.setCustomPixelLayerOverlay(overlay);
    var comboClassifiers = new ComboBox<String>();
    try {
        updateAvailableItems(comboClassifiers.getItems());
    } catch (IOException e) {
        logger.error(e.getLocalizedMessage(), e);
    }
    var selectedResource = Bindings.createObjectBinding(() -> {
        String name = comboClassifiers.getSelectionModel().getSelectedItem();
        cachedServers.clear();
        if (name != null) {
            try {
                var project = qupath.getProject();
                var manager = resourceType.getManager(project);
                S resource;
                if (manager != null && manager.contains(name))
                    resource = manager.get(name);
                else
                    resource = extras.get(name);
                if (resource instanceof UriResource) {
                    UriUpdater.fixUris((UriResource) resource, project);
                }
                return resource;
            } catch (Exception ex) {
                // TODO: Investigate why this is triggered twice
                Dialogs.showErrorNotification(resourceType.getDialogTitle(), ex);
            }
        }
        return null;
    }, comboClassifiers.getSelectionModel().selectedItemProperty());
    var label = new Label(resourceType.choosePrompt());
    label.setLabelFor(comboClassifiers);
    selectedResource.addListener((v, o, n) -> {
        cachedServers.clear();
        updateServers(n, cachedServers);
    });
    // Add file chooser
    var menu = new ContextMenu();
    var miLoadClassifier = new MenuItem("Import from files");
    miLoadClassifier.setOnAction(e -> {
        List<File> files = Dialogs.promptForMultipleFiles(title, null, resourceType.filePrompt(), "json");
        if (files == null || files.isEmpty())
            return;
        try {
            addExternalJson(files, resourceType.getManager(qupath.getProject()), extras);
            updateAvailableItems(comboClassifiers.getItems());
        } catch (IOException ex) {
            Dialogs.showErrorMessage(title, ex);
        }
    });
    var miOpenAsText = new MenuItem("Show as text");
    miOpenAsText.setOnAction(e -> {
        var name = comboClassifiers.getSelectionModel().getSelectedItem();
        var resource = selectedResource.get();
        if (resource == null)
            return;
        try {
            // Pass the resource class, since it can be required for including the appropriate JSON properties
            var json = GsonTools.getInstance(true).toJson(resource, resourceType.getResourceClass());
            if (!name.endsWith(".json"))
                name = name + ".json";
            // Show in script editor if possible; this may include better formatting and syntax highlighting
            var scriptEditor = qupath == null ? null : qupath.getScriptEditor();
            if (scriptEditor != null)
                scriptEditor.showScript(name, json);
            else
                Dialogs.showTextWindow(qupath.getStage(), name, json, Modality.NONE, false);
        } catch (Exception ex) {
            Dialogs.showErrorMessage("Show model as text", "Unable to create a text representation of '" + name + "', sorry!");
        }
    });
    miOpenAsText.disableProperty().bind(selectedResource.isNull());
    // Enable setting number of threads
    var miThreads = new MenuItem("Set parallel threads");
    miThreads.setOnAction(e -> {
        var params = new ParameterList().addIntParameter("nThreads", "Number of parallel threads", nThreads, null, "Number of threads to use for live prediction");
        if (!Dialogs.showParameterDialog("Set parallel threads", params))
            return;
        // var result = Dialogs.showInputDialog("Set parallel threads", "Number of threads to use for live prediction", (double)nThreads);
        var val = params.getIntParameterValue("nThreads");
        if (val == nThreads)
            return;
        if (val < 0)
            nThreads = PathPrefs.numCommandThreadsProperty().get();
        else
            nThreads = Math.max(1, val);
        if (overlay != null)
            overlay.setMaxThreads(nThreads);
    });
    menu.getItems().addAll(miLoadClassifier, miOpenAsText, new SeparatorMenuItem(), miThreads);
    var btnLoadExistingClassifier = GuiTools.createMoreButton(menu, Side.RIGHT);
    var classifierName = new SimpleStringProperty(null);
    classifierName.bind(comboClassifiers.getSelectionModel().selectedItemProperty());
    var pane = new GridPane();
    pane.setPadding(new Insets(10.0));
    pane.setHgap(5);
    pane.setVgap(10);
    pane.setPrefWidth(350.0);
    int row = 0;
    PaneTools.addGridRow(pane, row++, 0, "Choose model to apply to the current image", label, comboClassifiers, btnLoadExistingClassifier);
    PaneTools.setToExpandGridPaneWidth(comboClassifiers);
    if (resourceType.getResourceClass().equals(PixelClassifier.class)) {
        var labelRegion = new Label("Region");
        var comboRegionFilter = PixelClassifierUI.createRegionFilterCombo(qupath.getOverlayOptions());
        @SuppressWarnings("unchecked") var tilePane = PixelClassifierUI.createPixelClassifierButtons(qupath.imageDataProperty(), (ObjectExpression<PixelClassifier>) selectedResource, classifierName);
        PaneTools.addGridRow(pane, row++, 0, "Control where the pixel classification is applied during preview", labelRegion, comboRegionFilter, comboRegionFilter);
        PaneTools.addGridRow(pane, row++, 0, "Apply pixel classification", tilePane, tilePane, tilePane);
        PaneTools.setToExpandGridPaneWidth(tilePane);
    } else if (resourceType.getResourceClass().equals(DensityMapBuilder.class)) {
        @SuppressWarnings("unchecked") var buttonPane = DensityMapUI.createButtonPane(qupath, qupath.imageDataProperty(), (ObjectExpression<DensityMapBuilder>) selectedResource, classifierName, Bindings.createObjectBinding(() -> overlay), false);
        PaneTools.addGridRow(pane, row++, 0, null, buttonPane, buttonPane, buttonPane);
        PaneTools.setToExpandGridPaneWidth(buttonPane);
    }
    // Handle drag and drop
    pane.setOnDragOver(e -> {
        e.acceptTransferModes(TransferMode.COPY);
        e.consume();
    });
    pane.setOnDragDropped(e -> {
        logger.trace("File(s) dragged onto pane");
        Dragboard dragboard = e.getDragboard();
        if (dragboard.hasFiles()) {
            try {
                addExternalJson(dragboard.getFiles(), resourceType.getManager(qupath.getProject()), extras);
                updateAvailableItems(comboClassifiers.getItems());
            } catch (Exception ex) {
                Dialogs.showErrorMessage(title, ex);
            }
        }
    });
    var stage = new Stage();
    stage.setTitle(title);
    stage.setScene(new Scene(pane));
    stage.initOwner(qupath.getStage());
    stage.sizeToScene();
    stage.setResizable(false);
    stage.show();
    stage.setOnHiding(e -> {
        if (overlay != null)
            overlay.stop();
        logger.debug("Resetting overlay");
        for (var viewer : qupath.getViewers()) {
            if (viewer.getCustomPixelLayerOverlay() == overlay)
                viewer.resetCustomPixelLayerOverlay();
        }
    });
    stage.focusedProperty().addListener((v, o, n) -> {
        if (n && overlay != null) {
            for (var viewer : qupath.getViewers()) viewer.setCustomPixelLayerOverlay(overlay);
        }
        // Make sure we have all the servers we need - but don't reset existing ones
        updateServers(selectedResource.get(), cachedServers);
    });
    overlay.setLivePrediction(true);
}
Also used : UriResource(qupath.lib.io.UriResource) Insets(javafx.geometry.Insets) Label(javafx.scene.control.Label) ContextMenu(javafx.scene.control.ContextMenu) BufferedImage(java.awt.image.BufferedImage) Stage(javafx.stage.Stage) Dragboard(javafx.scene.input.Dragboard) GridPane(javafx.scene.layout.GridPane) ComboBox(javafx.scene.control.ComboBox) DensityMapBuilder(qupath.lib.analysis.heatmaps.DensityMaps.DensityMapBuilder) MenuItem(javafx.scene.control.MenuItem) SeparatorMenuItem(javafx.scene.control.SeparatorMenuItem) IOException(java.io.IOException) SimpleStringProperty(javafx.beans.property.SimpleStringProperty) SeparatorMenuItem(javafx.scene.control.SeparatorMenuItem) Scene(javafx.scene.Scene) IOException(java.io.IOException) ColorModelRenderer(qupath.lib.gui.images.stores.ColorModelRenderer) PixelClassifier(qupath.lib.classifiers.pixel.PixelClassifier) ParameterList(qupath.lib.plugins.parameters.ParameterList) File(java.io.File) ObjectExpression(javafx.beans.binding.ObjectExpression) WeakHashMap(java.util.WeakHashMap)

Aggregations

BufferedImage (java.awt.image.BufferedImage)1 File (java.io.File)1 IOException (java.io.IOException)1 WeakHashMap (java.util.WeakHashMap)1 ObjectExpression (javafx.beans.binding.ObjectExpression)1 SimpleStringProperty (javafx.beans.property.SimpleStringProperty)1 Insets (javafx.geometry.Insets)1 Scene (javafx.scene.Scene)1 ComboBox (javafx.scene.control.ComboBox)1 ContextMenu (javafx.scene.control.ContextMenu)1 Label (javafx.scene.control.Label)1 MenuItem (javafx.scene.control.MenuItem)1 SeparatorMenuItem (javafx.scene.control.SeparatorMenuItem)1 Dragboard (javafx.scene.input.Dragboard)1 GridPane (javafx.scene.layout.GridPane)1 Stage (javafx.stage.Stage)1 DensityMapBuilder (qupath.lib.analysis.heatmaps.DensityMaps.DensityMapBuilder)1 PixelClassifier (qupath.lib.classifiers.pixel.PixelClassifier)1 ColorModelRenderer (qupath.lib.gui.images.stores.ColorModelRenderer)1 UriResource (qupath.lib.io.UriResource)1