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")));
}
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));
}
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 & 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);
}
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;
}
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());
}
Aggregations