Search in sources :

Example 1 with PixelCalibration

use of qupath.lib.images.servers.PixelCalibration in project qupath by qupath.

the class DelaunayClusteringPlugin method addRunnableTasks.

@Override
protected void addRunnableTasks(ImageData<T> imageData, PathObject parentObject, List<Runnable> tasks) {
    // Get pixel sizes, if possible
    ImageServer<?> server = imageData.getServer();
    double pixelWidth = 1, pixelHeight = 1;
    PixelCalibration cal = server.getPixelCalibration();
    boolean hasMicrons = server != null && cal.hasPixelSizeMicrons();
    if (hasMicrons) {
        pixelWidth = cal.getPixelWidthMicrons();
        pixelHeight = cal.getPixelHeightMicrons();
    }
    double distanceThresholdPixels;
    if (cal.hasPixelSizeMicrons())
        distanceThresholdPixels = params.getDoubleParameterValue("distanceThresholdMicrons") / cal.getAveragedPixelSizeMicrons();
    else
        distanceThresholdPixels = params.getDoubleParameterValue("distanceThreshold");
    tasks.add(new DelaunayRunnable(imageData, parentObject, params.getBooleanParameterValue("addClusterMeasurements"), pixelWidth, pixelHeight, distanceThresholdPixels, params.getBooleanParameterValue("limitByClass")));
}
Also used : PixelCalibration(qupath.lib.images.servers.PixelCalibration)

Example 2 with PixelCalibration

use of qupath.lib.images.servers.PixelCalibration in project qupath by qupath.

the class SpecifyAnnotationCommand method init.

private void init() {
    pane = new GridPane();
    int row = 0;
    var cbMicrons = new CheckBox("Use " + GeneralTools.micrometerSymbol());
    var units = Bindings.createStringBinding(() -> {
        if (cbMicrons.isSelected())
            return GeneralTools.micrometerSymbol();
        return "px";
    }, cbMicrons.selectedProperty());
    var comboType = new ComboBox<ROI_TYPE>(FXCollections.observableArrayList(ROI_TYPE.values()));
    comboType.setMaxWidth(Double.MAX_VALUE);
    comboType.getSelectionModel().select(ROI_TYPE.RECTANGLE);
    PaneTools.addGridRow(pane, row++, 0, "Type of ROI to create", createLabelFor(comboType, "Type"), comboType, comboType);
    var comboClassification = new ComboBox<>(qupath.getAvailablePathClasses());
    comboClassification.setMaxWidth(Double.MAX_VALUE);
    comboClassification.setCellFactory(o -> {
        return new ClassificationCell();
    });
    // comboClassification.cell;
    PaneTools.addGridRow(pane, row++, 0, "Classification for the annotation (may be empty if annotation should be unclassified)", createLabelFor(comboClassification, "Classification"), comboClassification, comboClassification);
    var tfX = new TextField("");
    var tfY = new TextField("");
    var tfWidth = new TextField("1000");
    var tfHeight = new TextField("1000");
    tfX.setPrefColumnCount(10);
    tfY.setPrefColumnCount(10);
    tfWidth.setPrefColumnCount(10);
    tfHeight.setPrefColumnCount(10);
    PaneTools.addGridRow(pane, row++, 0, "X-coordinate of top left of annotation bounding box (if missing or < 0, annotation will be centered in current viewer)", createLabelFor(tfX, "X origin"), tfX, createBoundLabel(units));
    PaneTools.addGridRow(pane, row++, 0, "Y-coordinate of top left of annotation bounding box (if missing or < 0, annotation will be centered in current viewer)", createLabelFor(tfY, "Y origin"), tfY, createBoundLabel(units));
    PaneTools.addGridRow(pane, row++, 0, "Width of annotation bounding box (must be > 0)", createLabelFor(tfWidth, "Width"), tfWidth, createBoundLabel(units));
    PaneTools.addGridRow(pane, row++, 0, "Height of annotation bounding box (must be > 0)", createLabelFor(tfHeight, "Height"), tfHeight, createBoundLabel(units));
    cbMicrons.setMaxWidth(Double.MAX_VALUE);
    PaneTools.addGridRow(pane, row++, 0, "Specify coordinates in " + GeneralTools.micrometerSymbol() + " - pixel calibration information must be available", cbMicrons, cbMicrons, cbMicrons);
    var cbLock = new CheckBox("Set locked");
    cbLock.setMaxWidth(Double.MAX_VALUE);
    PaneTools.addGridRow(pane, row++, 0, "Set annotation as locked, so that it can't be immediately edited", cbLock, cbLock, cbLock);
    var tfName = new TextField("");
    PaneTools.addGridRow(pane, row++, 0, "Name of annotation (can be empty)", createLabelFor(tfName, "Name"), tfName, tfName);
    var btnAdd = new Button("Add annotation");
    btnAdd.setOnAction(e -> {
        var viewer = qupath.getViewer();
        var imageData = viewer == null ? null : viewer.getImageData();
        if (imageData == null) {
            Dialogs.showNoImageError("Create annotation");
            return;
        }
        var server = imageData.getServer();
        var hierarchy = imageData.getHierarchy();
        double xScale = 1;
        double yScale = 1;
        PixelCalibration cal = server.getPixelCalibration();
        if (cbMicrons.isSelected()) {
            if (!cal.hasPixelSizeMicrons()) {
                Dialogs.showErrorMessage("Create annotation", "No pixel size information available! Try again using pixel units.");
                return;
            }
            xScale = 1.0 / cal.getPixelWidthMicrons();
            yScale = 1.0 / cal.getPixelHeightMicrons();
        }
        var xOrig = tryToParse(tfX.getText());
        var yOrig = tryToParse(tfY.getText());
        var width = tryToParse(tfWidth.getText());
        var height = tryToParse(tfHeight.getText());
        if (width == null || width.doubleValue() <= 0 || height == null || height.doubleValue() <= 0) {
            Dialogs.showErrorMessage("Create annotation", "Width and height must be specified, and > 0!");
            return;
        }
        double w = width.doubleValue() * xScale;
        double h = height.doubleValue() * yScale;
        // It helps to start at integer pixels, since otherwise the width can be surprising when exporting regions
        // (since when requesting ROIs, Math.ceil is currently applied to ensure that the full ROI is included).
        double x;
        if (xOrig == null || xOrig.doubleValue() < 0)
            x = (int) Math.max(0, viewer.getCenterPixelX() - w / 2.0);
        else
            x = xOrig.doubleValue() * xScale;
        double y;
        if (yOrig == null || yOrig.doubleValue() < 0)
            y = (int) Math.max(viewer.getCenterPixelY() - h / 2.0, 0);
        else
            y = yOrig.doubleValue() * yScale;
        if (x + w > server.getWidth() || y + h > server.getHeight()) {
            Dialogs.showErrorMessage("Create annotation", "Specified annotation is too large for the image bounds!");
            return;
        }
        int z = viewer.getZPosition();
        int t = viewer.getTPosition();
        ROI roi = null;
        switch(comboType.getSelectionModel().getSelectedItem()) {
            case ELLIPSE:
                roi = ROIs.createEllipseROI(x, y, w, h, ImagePlane.getPlane(z, t));
                break;
            case RECTANGLE:
                roi = ROIs.createRectangleROI(x, y, w, h, ImagePlane.getPlane(z, t));
                break;
            default:
                Dialogs.showErrorMessage("Create annotation", "No ROI type selected!");
                return;
        }
        var pathClass = comboClassification.getSelectionModel().getSelectedItem();
        if (pathClass != null && !pathClass.isValid())
            pathClass = null;
        var annotation = PathObjects.createAnnotationObject(roi, pathClass);
        // Set name, if necessary
        var name = tfName.getText();
        if (name != null && !name.isEmpty())
            annotation.setName(name);
        if (cbLock.isSelected())
            ((PathAnnotationObject) annotation).setLocked(true);
        hierarchy.addPathObject(annotation);
    });
    btnAdd.setMaxWidth(Double.MAX_VALUE);
    PaneTools.addGridRow(pane, row++, 0, "Create annotation with specified options & add to object hierarchy", btnAdd, btnAdd, btnAdd);
    PaneTools.setFillWidth(Boolean.TRUE, tfX, tfY, tfWidth, tfHeight, btnAdd, comboType);
    PaneTools.setHGrowPriority(Priority.ALWAYS, tfX, tfY, tfWidth, tfHeight, btnAdd, comboType);
    pane.setHgap(5);
    pane.setVgap(5);
    pane.setPadding(new Insets(10));
}
Also used : GridPane(javafx.scene.layout.GridPane) Insets(javafx.geometry.Insets) Button(javafx.scene.control.Button) CheckBox(javafx.scene.control.CheckBox) ComboBox(javafx.scene.control.ComboBox) TextField(javafx.scene.control.TextField) PixelCalibration(qupath.lib.images.servers.PixelCalibration) ROI(qupath.lib.roi.interfaces.ROI)

Example 3 with PixelCalibration

use of qupath.lib.images.servers.PixelCalibration in project qupath by qupath.

the class QuPathViewer method getImageLocationString.

/**
 * Get a string representing the image coordinates for a particular x &amp; y location.
 * @param xx x-coordinate in the image space (not the component/viewer space)
 * @param yy y-coordinate in the image space (not the component/viewer space)
 * @param useCalibratedUnits
 * @return
 */
private String getImageLocationString(double xx, double yy, boolean useCalibratedUnits) {
    ImageServer<BufferedImage> server = getServer();
    if (server == null)
        return "";
    String units;
    if (xx < 0 || yy < 0 || xx > server.getWidth() - 1 || yy > server.getHeight() - 1)
        return "";
    double xDisplay = xx;
    double yDisplay = yy;
    PixelCalibration cal = server.getPixelCalibration();
    if (useCalibratedUnits && cal.hasPixelSizeMicrons()) {
        units = GeneralTools.micrometerSymbol();
        xDisplay *= cal.getPixelWidthMicrons();
        yDisplay *= cal.getPixelHeightMicrons();
    } else {
        units = "px";
    }
    // See if we're on top of a TMA core
    String prefix = "";
    TMAGrid tmaGrid = getHierarchy().getTMAGrid();
    if (tmaGrid != null) {
        TMACoreObject core = PathObjectTools.getTMACoreForPixel(tmaGrid, xx, yy);
        if (core != null && core.getName() != null)
            prefix = "Core: " + core.getName() + "\n";
    }
    String s = null;
    RegionRequest request = ImageRegionStoreHelpers.getTileRequest(server, xx, yy, downsampleFactor.get(), getZPosition(), getTPosition());
    if (request != null) {
        BufferedImage img = regionStore.getCachedTile(server, request);
        int xi = 0, yi = 0;
        if (img == null) {
            // Try getting a value from the thumbnail for the whole image
            BufferedImage imgThumbnail = regionStore.getCachedThumbnail(server, getZPosition(), getTPosition());
            if (imgThumbnail != null) {
                img = imgThumbnail;
                double downsample = (double) server.getWidth() / imgThumbnail.getWidth();
                xi = (int) (xx / downsample + .5);
                yi = (int) (yy / downsample + .5);
            }
        } else {
            xi = (int) ((xx - request.getX()) / request.getDownsample());
            yi = (int) ((yy - request.getY()) / request.getDownsample());
        }
        if (img != null) {
            // Make sure we are within range
            xi = Math.min(xi, img.getWidth() - 1);
            yi = Math.min(yi, img.getHeight() - 1);
            // Get the value, having applied any required color transforms
            if (imageDisplay != null)
                s = imageDisplay.getTransformedValueAsString(img, xi, yi);
        }
    }
    // Append z, t position if required
    String zString = null;
    if (server.nZSlices() > 1) {
        double zSpacing = server.getPixelCalibration().getZSpacingMicrons();
        if (!useCalibratedUnits || Double.isNaN(zSpacing))
            zString = "z = " + getZPosition();
        else
            zString = String.format("z = %.2f %s", getZPosition() * zSpacing, GeneralTools.micrometerSymbol());
    }
    String tString = null;
    if (server.nTimepoints() > 1) {
        // TODO: Consider use of TimeUnit
        // TimeUnit timeUnit = server.getTimeUnit();
        // if (!useMicrons || timeUnit == null)
        tString = "t = " + getTPosition();
    // else
    // tString = String.format("z = %.2f %s", getTPosition(), timeUnit.toString());
    }
    String dimensionString;
    if (tString == null && zString == null)
        dimensionString = "";
    else {
        dimensionString = "\n";
        if (zString != null) {
            dimensionString += zString;
            if (tString != null)
                dimensionString += ", " + tString;
        } else
            dimensionString += tString;
    }
    if (s != null)
        return String.format("%s%.2f, %.2f %s\n%s%s", prefix, xDisplay, yDisplay, units, s, dimensionString);
    else
        return String.format("%s%.2f, %.2f %s%s", prefix, xDisplay, yDisplay, units, dimensionString);
// if (s != null)
// return String.format("<html><center>%.2f, %.2f %s<br>%s", xDisplay, yDisplay, units, s);
// else
// return String.format("<html><center>%.2f, %.2f %s", xDisplay, yDisplay, units);
}
Also used : TMACoreObject(qupath.lib.objects.TMACoreObject) TMAGrid(qupath.lib.objects.hierarchy.TMAGrid) PixelCalibration(qupath.lib.images.servers.PixelCalibration) RegionRequest(qupath.lib.regions.RegionRequest) BufferedImage(java.awt.image.BufferedImage)

Example 4 with PixelCalibration

use of qupath.lib.images.servers.PixelCalibration in project qupath by qupath.

the class DoGSuperpixelsPlugin method getPreferredPixelSizeMicrons.

@Override
protected double getPreferredPixelSizeMicrons(final ImageData<BufferedImage> imageData, final ParameterList params) {
    double pixelSize = params.getDoubleParameterValue("downsampleFactor");
    PixelCalibration cal = imageData.getServer().getPixelCalibration();
    if (imageData != null && cal.hasPixelSizeMicrons())
        pixelSize *= cal.getAveragedPixelSizeMicrons();
    return pixelSize;
}
Also used : PixelCalibration(qupath.lib.images.servers.PixelCalibration)

Example 5 with PixelCalibration

use of qupath.lib.images.servers.PixelCalibration in project qupath by qupath.

the class IJTools method calibrateImagePlus.

/**
 * Set an ImagePlus's Calibration and FileInfo properties based on a RegionRequest and PathImageServer.
 * It is assumed at the image contained in the ImagePlus has been correctly read from the server.
 *
 * @param imp
 * @param request
 * @param server
 */
public static void calibrateImagePlus(final ImagePlus imp, final RegionRequest request, final ImageServer<BufferedImage> server) {
    // Set the file info & calibration appropriately
    // TODO: Check if this is correct!  And consider storing more info regarding actual server...
    Calibration cal = new Calibration();
    double downsampleFactor = request.getDownsample();
    PixelCalibration pixelCalibration = server.getPixelCalibration();
    double pixelWidth = pixelCalibration.getPixelWidthMicrons();
    double pixelHeight = pixelCalibration.getPixelHeightMicrons();
    if (!Double.isNaN(pixelWidth + pixelHeight)) {
        cal.pixelWidth = pixelWidth * downsampleFactor;
        cal.pixelHeight = pixelHeight * downsampleFactor;
        cal.pixelDepth = pixelCalibration.getZSpacingMicrons();
        if (server.nTimepoints() > 1) {
            cal.frameInterval = server.getMetadata().getTimepoint(1);
            if (server.getMetadata().getTimeUnit() != null)
                cal.setTimeUnit(server.getMetadata().getTimeUnit().toString());
        }
        cal.setUnit("um");
    }
    // Set the origin
    cal.xOrigin = -request.getX() / downsampleFactor;
    cal.yOrigin = -request.getY() / downsampleFactor;
    // Need to set calibration afterwards, as it will be copied
    imp.setCalibration(cal);
    FileInfo fi = imp.getFileInfo();
    File file = new File(server.getPath());
    fi.directory = file.getParent() + File.separator;
    fi.fileName = file.getName();
    String path = server.getPath();
    if (path != null && path.toLowerCase().startsWith("http"))
        fi.url = path;
    imp.setFileInfo(fi);
    imp.setProperty("Info", "location=" + server.getPath());
}
Also used : FileInfo(ij.io.FileInfo) Calibration(ij.measure.Calibration) PixelCalibration(qupath.lib.images.servers.PixelCalibration) PixelCalibration(qupath.lib.images.servers.PixelCalibration) ZipFile(java.util.zip.ZipFile) File(java.io.File)

Aggregations

PixelCalibration (qupath.lib.images.servers.PixelCalibration)31 BufferedImage (java.awt.image.BufferedImage)9 ArrayList (java.util.ArrayList)8 ROI (qupath.lib.roi.interfaces.ROI)8 RegionRequest (qupath.lib.regions.RegionRequest)7 MeasurementList (qupath.lib.measurements.MeasurementList)6 PathObject (qupath.lib.objects.PathObject)6 Calibration (ij.measure.Calibration)5 PathCellObject (qupath.lib.objects.PathCellObject)5 ParameterList (qupath.lib.plugins.parameters.ParameterList)5 List (java.util.List)4 Collection (java.util.Collection)3 HashMap (java.util.HashMap)3 Map (java.util.Map)3 ImagePlus (ij.ImagePlus)2 ByteProcessor (ij.process.ByteProcessor)2 FloatProcessor (ij.process.FloatProcessor)2 ImageProcessor (ij.process.ImageProcessor)2 Graphics2D (java.awt.Graphics2D)2 LinkedHashMap (java.util.LinkedHashMap)2