Search in sources :

Example 11 with QuPathViewer

use of qupath.lib.gui.viewer.QuPathViewer in project qupath by qupath.

the class ToolBarComponent method promptToUpdateMagnification.

void promptToUpdateMagnification() {
    QuPathViewer viewer = qupath.getViewer();
    if (viewer == null || !viewer.hasServer())
        return;
    double fullMagnification = viewer.getServer().getMetadata().getMagnification();
    boolean hasMagnification = !Double.isNaN(fullMagnification);
    if (hasMagnification) {
        double defaultValue = Math.rint(viewer.getMagnification() * 1000) / 1000;
        Double value = Dialogs.showInputDialog("Set magnification", "Enter magnification", defaultValue);
        if (value == null)
            return;
        if (Double.isFinite(value) && value > 0)
            viewer.setMagnification(value.doubleValue());
        else
            Dialogs.showErrorMessage("Set downsample factor", "Invalid magnification " + value + ". \nPlease use a value greater than 0.");
    } else {
        double defaultValue = Math.rint(viewer.getDownsampleFactor() * 1000) / 1000;
        Double value = Dialogs.showInputDialog("Set downsample factor", "Enter downsample factor", defaultValue);
        if (value == null)
            return;
        if (Double.isFinite(value) && value > 0)
            viewer.setDownsampleFactor(value.doubleValue());
        else
            Dialogs.showErrorMessage("Set downsample factor", "Invalid downsample " + value + ". \nPlease use a value greater than 0.");
    }
}
Also used : QuPathViewer(qupath.lib.gui.viewer.QuPathViewer)

Example 12 with QuPathViewer

use of qupath.lib.gui.viewer.QuPathViewer in project qupath by qupath.

the class OMEPyramidWriterCommand method run.

@Override
public void run() {
    if (currentTask != null && !currentTask.isDone()) {
        if (!Dialogs.showConfirmDialog("OME Pyramid writer", "Do you want to stop the current export?"))
            // TODO: Delete exporting file?
            return;
        else {
            currentTask.cancel(true);
        }
    }
    QuPathViewer viewer = qupath.getViewer();
    int zPos = viewer.getZPosition();
    int tPos = viewer.getTPosition();
    ImageData<BufferedImage> imageData = viewer.getImageData();
    if (imageData == null) {
        Dialogs.showNoImageError("OME Pyramid writer");
        return;
    }
    ImageServer<BufferedImage> server = imageData.getServer();
    // Region
    PathObject selected = imageData.getHierarchy().getSelectionModel().getSelectedObject();
    ImageRegion region = null;
    int width, height;
    if (selected == null || !selected.hasROI() || !selected.getROI().isArea()) {
        width = server.getWidth();
        height = server.getHeight();
    } else {
        region = ImageRegion.createInstance(selected.getROI());
        width = region.getWidth();
        height = region.getHeight();
    }
    // Set compression - with a sanity check for validity, defaulting to another comparable method if necessary
    CompressionType compression = getDefaultPyramidCompression();
    List<String> compatibleCompression = Arrays.stream(CompressionType.values()).filter(c -> c.supportsImage(server)).map(c -> c.toFriendlyString()).collect(Collectors.toList());
    if (!compatibleCompression.contains(compression.toFriendlyString()))
        compression = CompressionType.DEFAULT;
    var params = new ParameterList().addChoiceParameter("compression", "Compression type", compression.toFriendlyString(), compatibleCompression).addIntParameter("scaledDownsample", "Pyramidal downsample", scaledDownsample.get(), "", 1, 8, "Amount to downsample each consecutive pyramidal level; use 1 to indicate the image should not be pyramidal").addIntParameter("tileSize", "Tile size", getDefaultTileSize(), "px", "Tile size for export (should be between 128 and 8192)").addBooleanParameter("parallelize", "Parallelize export", parallelizeTiling.get(), "Export image tiles in parallel - " + "this should be faster, best keep it on unless you encounter export problems").addBooleanParameter("allZ", "All z-slices", allZ.get(), "Include all z-slices in the stack").addBooleanParameter("allT", "All timepoints", allT.get(), "Include all timepoints in the time-series");
    boolean singleTile = server.getTileRequestManager().getTileRequests(RegionRequest.createInstance(server)).size() == 1;
    params.setHiddenParameters(server.nZSlices() == 1, "allZ");
    params.setHiddenParameters(server.nTimepoints() == 1, "allT");
    params.setHiddenParameters(singleTile, "tileSize", "parallelize");
    if (!Dialogs.showParameterDialog("Export OME-TIFF", params))
        return;
    compression = CompressionType.fromFriendlyString((String) params.getChoiceParameterValue("compression"));
    defaultPyramidCompression.set(compression);
    int downsampleScale = params.getIntParameterValue("scaledDownsample");
    scaledDownsample.set(downsampleScale);
    int tileSize = params.getIntParameterValue("tileSize");
    boolean parallelize = params.getBooleanParameterValue("parallelize");
    if (!singleTile) {
        tileSize = GeneralTools.clipValue(tileSize, 128, 8192);
        defaultTileSize.set(tileSize);
        parallelizeTiling.set(parallelize);
    }
    boolean doAllZ = false;
    boolean doAllT = false;
    if (server.nZSlices() > 1) {
        doAllZ = params.getBooleanParameterValue("allZ");
        allZ.set(doAllZ);
    }
    if (server.nTimepoints() > 1) {
        doAllT = params.getBooleanParameterValue("allT");
        allT.set(doAllT);
    }
    OMEPyramidWriter.Builder builder = new OMEPyramidWriter.Builder(server);
    if (region != null) {
        builder = builder.region(region);
    } else {
        if (server.nZSlices() > 1 && !doAllZ)
            builder.zSlice(zPos);
        if (server.nTimepoints() > 1 && !doAllT)
            builder.timePoint(tPos);
    }
    builder.compression(compression);
    if (downsampleScale <= 1 || Math.max(width, height) / server.getDownsampleForResolution(0) < minSizeForTiling.get())
        builder.downsamples(server.getDownsampleForResolution(0));
    else
        builder.scaledDownsampling(server.getDownsampleForResolution(0), downsampleScale);
    // Set tile size; if we just have one tile, use the image width & height
    if (singleTile)
        builder = builder.tileSize(width, height);
    else
        builder = builder.tileSize(tileSize).parallelize(parallelize);
    if (server.nZSlices() > 1 && doAllZ)
        builder.allZSlices();
    if (server.nTimepoints() > 1 && doAllT)
        builder.allTimePoints();
    // Prompt for file
    File fileOutput = Dialogs.promptToSaveFile("Write pyramid", null, null, "OME TIFF pyramid", ".ome.tif");
    if (fileOutput == null)
        return;
    String name = fileOutput.getName();
    // We can have trouble with only the '.tif' part of the name being included
    if (name.endsWith(".tif") && !name.endsWith(".ome.tif"))
        fileOutput = new File(fileOutput.getParentFile(), name.substring(0, name.length() - 4) + ".ome.tif");
    OMEPyramidSeries writer = builder.build();
    if (pool == null) {
        pool = Executors.newSingleThreadExecutor(ThreadTools.createThreadFactory("ome-pyramid-export", false));
    }
    currentTask = pool.submit(new WriterTask(OMEPyramidWriter.createWriter(writer), fileOutput.getAbsolutePath()));
}
Also used : Arrays(java.util.Arrays) ImageServer(qupath.lib.images.servers.ImageServer) LoggerFactory(org.slf4j.LoggerFactory) IntegerProperty(javafx.beans.property.IntegerProperty) Dialogs(qupath.lib.gui.dialogs.Dialogs) Future(java.util.concurrent.Future) ParameterList(qupath.lib.plugins.parameters.ParameterList) OMEPyramidSeries(qupath.lib.images.writers.ome.OMEPyramidWriter.OMEPyramidSeries) ImageRegion(qupath.lib.regions.ImageRegion) CompressionType(qupath.lib.images.writers.ome.OMEPyramidWriter.CompressionType) ExecutorService(java.util.concurrent.ExecutorService) QuPathGUI(qupath.lib.gui.QuPathGUI) ImageData(qupath.lib.images.ImageData) ObjectProperty(javafx.beans.property.ObjectProperty) Logger(org.slf4j.Logger) BufferedImage(java.awt.image.BufferedImage) GeneralTools(qupath.lib.common.GeneralTools) RegionRequest(qupath.lib.regions.RegionRequest) Collectors(java.util.stream.Collectors) File(java.io.File) Executors(java.util.concurrent.Executors) PathObject(qupath.lib.objects.PathObject) ClosedByInterruptException(java.nio.channels.ClosedByInterruptException) QuPathViewer(qupath.lib.gui.viewer.QuPathViewer) List(java.util.List) BooleanProperty(javafx.beans.property.BooleanProperty) ThreadTools(qupath.lib.common.ThreadTools) PathPrefs(qupath.lib.gui.prefs.PathPrefs) ImageRegion(qupath.lib.regions.ImageRegion) BufferedImage(java.awt.image.BufferedImage) PathObject(qupath.lib.objects.PathObject) OMEPyramidSeries(qupath.lib.images.writers.ome.OMEPyramidWriter.OMEPyramidSeries) ParameterList(qupath.lib.plugins.parameters.ParameterList) CompressionType(qupath.lib.images.writers.ome.OMEPyramidWriter.CompressionType) File(java.io.File) QuPathViewer(qupath.lib.gui.viewer.QuPathViewer)

Example 13 with QuPathViewer

use of qupath.lib.gui.viewer.QuPathViewer in project qupath by qupath.

the class MeasurementMapPane method showMap.

private void showMap() {
    String measurement = listMeasurements.getSelectionModel().getSelectedItem();
    QuPathViewer viewer = qupath.getViewer();
    if (viewer == null || measurement == null)
        return;
    // Reuse mappers if we can
    mapper = mapperMap.get(measurement);
    var colorMapper = selectedColorMap.getValue();
    if (mapper == null) {
        mapper = new MeasurementMapper(colorMapper, measurement, viewer.getHierarchy().getObjects(null, null));
        if (mapper.isValid())
            mapperMap.put(measurement, mapper);
    } else if (colorMapper != null) {
        mapper.setColorMapper(colorMapper);
    }
    if (mapper != null && mapper.isValid()) {
        updatingSliders = true;
        sliderMin.setMin(Math.min(mapper.getDataMinValue(), mapper.getDisplayMinValue()));
        sliderMin.setMax(Math.max(mapper.getDataMaxValue(), mapper.getDisplayMaxValue()));
        sliderMin.setValue(mapper.getDisplayMinValue());
        sliderMin.setBlockIncrement((sliderMin.getMax() - sliderMin.getMin()) / 100);
        sliderMax.setMin(Math.min(mapper.getDataMinValue(), mapper.getDisplayMinValue()));
        sliderMax.setMax(Math.max(mapper.getDataMaxValue(), mapper.getDisplayMaxValue()));
        sliderMax.setValue(mapper.getDisplayMaxValue());
        sliderMax.setBlockIncrement((sliderMax.getMax() - sliderMax.getMin()) / 100);
        updatingSliders = false;
    }
    colorMapKeyImage = createPanelKey(mapper.getColorMapper());
    updateColorMapperKey();
    mapper.setExcludeOutsideRange(cbExcludeOutside.isSelected());
    viewer.forceOverlayUpdate();
    updateMapperBrightnessContrast();
    OverlayOptions overlayOptions = viewer.getOverlayOptions();
    if (overlayOptions != null)
        overlayOptions.setMeasurementMapper(mapper);
}
Also used : OverlayOptions(qupath.lib.gui.viewer.OverlayOptions) MeasurementMapper(qupath.lib.gui.tools.MeasurementMapper) QuPathViewer(qupath.lib.gui.viewer.QuPathViewer)

Example 14 with QuPathViewer

use of qupath.lib.gui.viewer.QuPathViewer in project qupath by qupath.

the class RotateImageCommand method createDialog.

Stage createDialog() {
    QuPathViewer viewerTemp = qupath.getViewer();
    if (dialog == null) {
        dialog = new Stage();
        dialog.initOwner(qupath.getStage());
        dialog.initStyle(StageStyle.TRANSPARENT);
        dialog.setTitle("Rotate view");
        StackPane pane = new StackPane();
        pane.setPadding(new Insets(5));
        slider = new CircularSlider();
        slider.setPrefSize(150, 150);
        slider.setValue(viewerTemp == null ? 0 : Math.toDegrees(viewerTemp.getRotation()));
        slider.setTickSpacing(10);
        slider.setShowValue(true);
        slider.setSnapToTicks(false);
        slider.setOnKeyPressed(e -> {
            if (e.getCode() == KeyCode.SHIFT) {
                slider.setSnapToTicks(true);
                slider.setShowTickMarks(true);
            }
        });
        slider.setOnKeyReleased(e -> {
            if (e.getCode() == KeyCode.SHIFT) {
                slider.setSnapToTicks(false);
                slider.setShowTickMarks(false);
            }
        });
        slider.setPadding(new Insets(5, 0, 10, 0));
        slider.setTooltip(new Tooltip("Double-click to manually set the rotation"));
        final DropShadow shadow = new DropShadow();
        shadow.setColor(Color.rgb(0, 0, 0, 0.65));
        slider.setEffect(shadow);
        final Button button = new Button("x");
        button.setTooltip(new Tooltip("Close image rotation slider"));
        button.setOnMouseClicked(e -> dialog.close());
        pane.getChildren().addAll(slider, button);
        final double[] delta = new double[2];
        slider.getTextArea().setOnMousePressed(e -> {
            delta[0] = dialog.getX() - e.getScreenX();
            delta[1] = dialog.getY() - e.getScreenY();
        });
        slider.getTextArea().setOnMouseDragged(e -> {
            dialog.setX(e.getScreenX() + delta[0]);
            dialog.setY(e.getScreenY() + delta[1]);
        });
        StackPane.setAlignment(button, Pos.TOP_RIGHT);
        // Set opacity for the close button
        pane.setStyle("-fx-background-color: transparent; -fx-background-radius: 10;");
        final double outOpacity = .2;
        button.setOpacity(outOpacity);
        FadeTransition fade = new FadeTransition();
        fade.setDuration(Duration.millis(150));
        fade.setNode(button);
        pane.setOnMouseEntered(e -> {
            fade.stop();
            fade.setFromValue(button.getOpacity());
            fade.setToValue(1.);
            fade.play();
        });
        pane.setOnMouseExited(e -> {
            fade.stop();
            fade.setFromValue(button.getOpacity());
            fade.setToValue(outOpacity);
            fade.play();
        });
        final Scene scene = new Scene(pane);
        scene.setFill(Color.TRANSPARENT);
        dialog.setOnHiding(e -> {
            qupath.viewerProperty().removeListener(this);
            dialog = null;
        });
        dialog.setScene(scene);
        dialog.setResizable(true);
    }
    if (viewerTemp != null)
        slider.rotationProperty().bindBidirectional(viewerTemp.rotationProperty());
    return dialog;
}
Also used : Insets(javafx.geometry.Insets) CircularSlider(qupath.lib.gui.CircularSlider) Button(javafx.scene.control.Button) FadeTransition(javafx.animation.FadeTransition) Tooltip(javafx.scene.control.Tooltip) Stage(javafx.stage.Stage) Scene(javafx.scene.Scene) StackPane(javafx.scene.layout.StackPane) DropShadow(javafx.scene.effect.DropShadow) QuPathViewer(qupath.lib.gui.viewer.QuPathViewer)

Aggregations

QuPathViewer (qupath.lib.gui.viewer.QuPathViewer)14 BufferedImage (java.awt.image.BufferedImage)8 PathObject (qupath.lib.objects.PathObject)7 Logger (org.slf4j.Logger)5 LoggerFactory (org.slf4j.LoggerFactory)5 File (java.io.File)4 Collection (java.util.Collection)4 Collectors (java.util.stream.Collectors)4 GeneralTools (qupath.lib.common.GeneralTools)4 ImageData (qupath.lib.images.ImageData)4 IOException (java.io.IOException)3 ArrayList (java.util.ArrayList)3 List (java.util.List)3 QuPathGUI (qupath.lib.gui.QuPathGUI)3 Dialogs (qupath.lib.gui.dialogs.Dialogs)3 PathObjectHierarchy (qupath.lib.objects.hierarchy.PathObjectHierarchy)3 ImageJ (ij.ImageJ)2 ImagePlus (ij.ImagePlus)2 Collections (java.util.Collections)2 IntegerProperty (javafx.beans.property.IntegerProperty)2