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