use of qupath.lib.plugins.parameters.ParameterList in project qupath by qupath.
the class NeuralNetworksClassifier method createParameterList.
@Override
protected ParameterList createParameterList() {
ParameterList params = new ParameterList();
params.addIntParameter("nHidden", "Number of hidden layers", 8, null, "Number of hidden layers for neural network (must be >= 2)");
params.addIntParameter("termCritMaxIterations", "Termination criterion - max iterations", 100, null, "Optional termination criterion based on maximum number of iterations - set <= 0 to disable and use accuracy criterion only");
params.addDoubleParameter("termCritEPS", "Termination criterion - accuracy", 0.01, null, "Optional termination criterion based on out-of-bag error - set <= 0 to disable and use max trees only");
return params;
}
use of qupath.lib.plugins.parameters.ParameterList in project qupath by qupath.
the class Commands method promptToSetGridLineSpacing.
/**
* Prompt to input the spacing for the grid lines optionally displayed on viewers.
* @param options the {@link OverlayOptions} that manage the grid lines.
*/
public static void promptToSetGridLineSpacing(OverlayOptions options) {
GridLines gridLines = options.getGridLines();
ParameterList params = new ParameterList().addDoubleParameter("hSpacing", "Horizontal spacing", gridLines.getSpaceX()).addDoubleParameter("vSpacing", "Vertical spacing", gridLines.getSpaceY()).addBooleanParameter("useMicrons", "Use microns", gridLines.useMicrons());
if (!Dialogs.showParameterDialog("Set grid spacing", params))
return;
gridLines = new GridLines();
gridLines.setSpaceX(params.getDoubleParameterValue("hSpacing"));
gridLines.setSpaceY(params.getDoubleParameterValue("vSpacing"));
gridLines.setUseMicrons(params.getBooleanParameterValue("useMicrons"));
options.gridLinesProperty().set(gridLines);
}
use of qupath.lib.plugins.parameters.ParameterList in project qupath by qupath.
the class ExportObjectsCommand method runGeoJsonExport.
/**
* Run the path object GeoJSON export command.
* @param qupath
* @return success
* @throws IOException
*/
public static boolean runGeoJsonExport(QuPathGUI qupath) throws IOException {
// Get ImageData
var imageData = qupath.getImageData();
if (imageData == null)
return false;
// Get hierarchy
PathObjectHierarchy hierarchy = imageData.getHierarchy();
String allObjects = "All objects";
String selectedObjects = "Selected objects";
String defaultObjects = hierarchy.getSelectionModel().noSelection() ? allObjects : selectedObjects;
// Params
var parameterList = new ParameterList().addChoiceParameter("exportOptions", "Export ", defaultObjects, Arrays.asList(allObjects, selectedObjects), "Choose which objects to export - run a 'Select annotations/detections' command first if needed").addBooleanParameter("excludeMeasurements", "Exclude measurements", false, "Exclude object measurements during export - for large numbers of detections this can help reduce the file size").addBooleanParameter("doPretty", "Pretty JSON", false, "Pretty GeoJSON is more human-readable but results in larger file sizes").addBooleanParameter("doFeatureCollection", "Export as FeatureCollection", true, "Export as a 'FeatureCollection', which is a standard GeoJSON way to represent multiple objects; if not, a regular JSON object/array will be export").addBooleanParameter("doZip", "Compress data (zip)", false, "Compressed files take less memory");
if (!Dialogs.showParameterDialog("Export objects", parameterList))
return false;
Collection<PathObject> toProcess;
var comboChoice = parameterList.getChoiceParameterValue("exportOptions");
if (comboChoice.equals("Selected objects")) {
if (hierarchy.getSelectionModel().noSelection()) {
Dialogs.showErrorMessage("No selection", "No selection detected!");
return false;
}
toProcess = hierarchy.getSelectionModel().getSelectedObjects();
} else
toProcess = hierarchy.getObjects(null, null);
// Remove PathRootObject
toProcess = toProcess.stream().filter(e -> !e.isRootObject()).collect(Collectors.toList());
// Check if includes ellipse(s), as they will need to be polygonized
var nEllipses = toProcess.stream().filter(ann -> isEllipse(ann)).count();
if (nEllipses > 0) {
String message = nEllipses == 1 ? "1 ellipse will be polygonized, continue?" : String.format("%d ellipses will be polygonized, continue?", nEllipses);
var response = Dialogs.showYesNoDialog("Ellipse polygonization", message);
if (!response)
return false;
}
File outFile;
// Get default name & output directory
var project = qupath.getProject();
String defaultName = imageData.getServer().getMetadata().getName();
if (project != null) {
var entry = project.getEntry(imageData);
if (entry != null)
defaultName = entry.getImageName();
}
defaultName = GeneralTools.getNameWithoutExtension(defaultName);
File defaultDirectory = project == null || project.getPath() == null ? null : project.getPath().toFile();
while (defaultDirectory != null && !defaultDirectory.isDirectory()) defaultDirectory = defaultDirectory.getParentFile();
if (parameterList.getBooleanParameterValue("doZip"))
outFile = Dialogs.promptToSaveFile("Export to file", defaultDirectory, defaultName + ".zip", "ZIP archive", ".zip");
else
outFile = Dialogs.promptToSaveFile("Export to file", defaultDirectory, defaultName + ".geojson", "GeoJSON", ".geojson");
// If user cancels
if (outFile == null)
return false;
List<GeoJsonExportOptions> options = new ArrayList<>();
if (parameterList.getBooleanParameterValue("excludeMeasurements"))
options.add(GeoJsonExportOptions.EXCLUDE_MEASUREMENTS);
if (parameterList.getBooleanParameterValue("doPretty"))
options.add(GeoJsonExportOptions.PRETTY_JSON);
if (parameterList.getBooleanParameterValue("doFeatureCollection"))
options.add(GeoJsonExportOptions.FEATURE_COLLECTION);
// Export
QP.exportObjectsToGeoJson(toProcess, outFile.getAbsolutePath(), options.toArray(GeoJsonExportOptions[]::new));
// Notify user of success
int nObjects = toProcess.size();
String message = nObjects == 1 ? "1 object was exported to " + outFile.getAbsolutePath() : String.format("%d objects were exported to %s", nObjects, outFile.getAbsolutePath());
Dialogs.showInfoNotification("Succesful export", message);
// Get history workflow
var historyWorkflow = imageData.getHistoryWorkflow();
// args for workflow step
Map<String, String> map = new LinkedHashMap<>();
map.put("path", outFile.getPath());
String method = comboChoice.equals(allObjects) ? "exportAllObjectsToGeoJson" : "exportSelectedObjectsToGeoJson";
String methodTitle = comboChoice.equals(allObjects) ? "Export all objects" : "Export selected objects";
String optionsString = options.stream().map(o -> "\"" + o.name() + "\"").collect(Collectors.joining(", "));
map.put("options", optionsString);
if (!optionsString.isEmpty())
optionsString = ", " + optionsString;
String methodString = String.format("%s(%s%s)", method, "\"" + GeneralTools.escapeFilePath(outFile.getPath()) + "\"", optionsString);
historyWorkflow.addStep(new DefaultScriptableWorkflowStep(methodTitle, map, methodString));
return true;
}
use of qupath.lib.plugins.parameters.ParameterList in project qupath by qupath.
the class TMACommands method promptToRelabelTMAGrid.
/**
* Prompt to relabel the core names within a TMA grid.
* @param imageData image containing the TMA grid
*/
public static void promptToRelabelTMAGrid(ImageData<?> imageData) {
String title = "Relabel TMA grid";
if (imageData == null) {
Dialogs.showNoImageError(title);
return;
}
if (imageData.getHierarchy().getTMAGrid() == null) {
Dialogs.showErrorMessage(title, "No TMA grid selected!");
return;
}
ParameterList params = new ParameterList();
params.addStringParameter("labelsHorizontal", "Column labels", columnLabelsProperty.get(), "Enter column labels.\nThis can be a continuous range of letters or numbers (e.g. 1-10 or A-J),\nor a discontinuous list separated by spaces (e.g. A B C E F G).");
params.addStringParameter("labelsVertical", "Row labels", rowLabelsProperty.get(), "Enter row labels.\nThis can be a continuous range of letters or numbers (e.g. 1-10 or A-J),\nor a discontinuous list separated by spaces (e.g. A B C E F G).");
params.addChoiceParameter("labelOrder", "Label order", rowFirstProperty.get() ? "Row first" : "Column first", Arrays.asList("Column first", "Row first"), "Create TMA labels either in the form Row-Column or Column-Row");
if (!Dialogs.showParameterDialog(title, params))
return;
// Parse the arguments
String labelsHorizontal = params.getStringParameterValue("labelsHorizontal");
String labelsVertical = params.getStringParameterValue("labelsVertical");
boolean rowFirst = "Row first".equals(params.getChoiceParameterValue("labelOrder"));
// Figure out if this will work
TMAGrid grid = imageData.getHierarchy().getTMAGrid();
String[] columnLabels = PathObjectTools.parseTMALabelString(labelsHorizontal);
String[] rowLabels = PathObjectTools.parseTMALabelString(labelsVertical);
if (columnLabels.length < grid.getGridWidth()) {
Dialogs.showErrorMessage(title, "Not enough column labels specified!");
return;
}
if (rowLabels.length < grid.getGridHeight()) {
Dialogs.showErrorMessage(title, "Not enough row labels specified!");
return;
}
// Apply the labels
QP.relabelTMAGrid(imageData.getHierarchy(), labelsHorizontal, labelsVertical, rowFirst);
// Add to workflow history
imageData.getHistoryWorkflow().addStep(new DefaultScriptableWorkflowStep("Relabel TMA grid", String.format("relabelTMAGrid(\"%s\", \"%s\", %s)", GeneralTools.escapeFilePath(labelsHorizontal), GeneralTools.escapeFilePath(labelsVertical), Boolean.toString(rowFirst))));
// Store values
rowLabelsProperty.set(labelsVertical);
columnLabelsProperty.set(labelsHorizontal);
rowFirstProperty.set(rowFirst);
}
use of qupath.lib.plugins.parameters.ParameterList in project qupath by qupath.
the class EstimateStainVectorsCommand method showStainEditor.
@SuppressWarnings("unchecked")
public static ColorDeconvolutionStains showStainEditor(final BufferedImage img, final ColorDeconvolutionStains stains) {
//
int[] buf = img.getRGB(0, 0, img.getWidth(), img.getHeight(), null, 0, img.getWidth());
// int[] rgb = buf;
int[] rgb = EstimateStainVectors.subsample(buf, 10000);
float[] red = ColorDeconvolutionHelper.getRedOpticalDensities(rgb, stains.getMaxRed(), null);
float[] green = ColorDeconvolutionHelper.getGreenOpticalDensities(rgb, stains.getMaxGreen(), null);
float[] blue = ColorDeconvolutionHelper.getBlueOpticalDensities(rgb, stains.getMaxBlue(), null);
// panelPlots.setBorder(BorderFactory.createTitledBorder(null, "Stain vector scatterplots", TitledBorder.CENTER, TitledBorder.TOP));
StainsWrapper stainsWrapper = new StainsWrapper(stains);
Node panelRedGreen = createScatterPanel(new ScatterPlot(red, green, null, rgb), stainsWrapper, AxisColor.RED, AxisColor.GREEN);
Node panelRedBlue = createScatterPanel(new ScatterPlot(red, blue, null, rgb), stainsWrapper, AxisColor.RED, AxisColor.BLUE);
Node panelGreenBlue = createScatterPanel(new ScatterPlot(green, blue, null, rgb), stainsWrapper, AxisColor.GREEN, AxisColor.BLUE);
// GridPane panelPlots = PanelToolsFX.createColumnGrid(panelRedGreen, panelRedBlue, panelGreenBlue);
GridPane panelPlots = new GridPane();
panelPlots.setHgap(10);
panelPlots.add(panelRedGreen, 0, 0);
panelPlots.add(panelRedBlue, 1, 0);
panelPlots.add(panelGreenBlue, 2, 0);
// panelPlots.getChildren().addAll(panelRedGreen, panelRedBlue, panelGreenBlue);
panelPlots.setPadding(new Insets(0, 0, 10, 0));
BorderPane panelSouth = new BorderPane();
TableView<Integer> table = new TableView<>();
table.getItems().setAll(1, 2, 3);
stainsWrapper.addStainListener(new StainChangeListener() {
@Override
public void stainChanged(StainsWrapper stainsWrapper) {
table.refresh();
}
});
TableColumn<Integer, String> colName = new TableColumn<>("Name");
colName.setCellValueFactory(v -> new SimpleStringProperty(stainsWrapper.getStains().getStain(v.getValue()).getName()));
TableColumn<Integer, String> colOrig = new TableColumn<>("Original");
colOrig.setCellValueFactory(v -> new SimpleStringProperty(stainArrayAsString(Locale.getDefault(Category.FORMAT), stainsWrapper.getOriginalStains().getStain(v.getValue()), " | ", 3)));
TableColumn<Integer, String> colCurrent = new TableColumn<>("Current");
colCurrent.setCellValueFactory(v -> new SimpleStringProperty(stainArrayAsString(Locale.getDefault(Category.FORMAT), stainsWrapper.getStains().getStain(v.getValue()), " | ", 3)));
TableColumn<Integer, String> colAngle = new TableColumn<>("Angle");
colAngle.setCellValueFactory(v -> {
return new SimpleStringProperty(GeneralTools.formatNumber(StainVector.computeAngle(stainsWrapper.getOriginalStains().getStain(v.getValue()), stainsWrapper.getStains().getStain(v.getValue())), 2));
});
// new SimpleStringProperty(stainsWrapper.getStains().getStain(v.getValue()).arrayAsString(", ", 3)));
table.getColumns().addAll(colName, colOrig, colCurrent, colAngle);
table.setColumnResizePolicy(TableView.UNCONSTRAINED_RESIZE_POLICY);
table.setPrefHeight(120);
// // Fix first & preferred column sizes
// int widthName = 0, widthStain = 0;
// for (int row = 0; row < table.getRowCount(); row++) {
// TableCellRenderer renderer = table.getCellRenderer(row, 0);
// Component comp = table.prepareRenderer(renderer, row, 0);
// widthName = Math.max(comp.getPreferredSize().width, widthName);
//
// renderer = table.getCellRenderer(row, 1);
// comp = table.prepareRenderer(renderer, row, 1);
// widthStain = Math.max(comp.getPreferredSize().width, widthStain);
// renderer = table.getCellRenderer(row, 2);
// comp = table.prepareRenderer(renderer, row, 2);
// widthStain = Math.max(comp.getPreferredSize().width, widthStain);
// }
// table.getColumnModel().getColumn(0).setMaxWidth(widthName + 10);
// table.getColumnModel().getColumn(0).setPreferredWidth(widthName + 10);
// table.getColumnModel().getColumn(1).setPreferredWidth(widthStain + 20);
// table.getColumnModel().getColumn(2).setPreferredWidth(widthStain + 20);
// Create auto detection parameters
ParameterList params = new ParameterList().addDoubleParameter("minStainOD", "Min channel OD", 0.05, "", "Minimum staining OD - pixels with a lower OD in any channel (RGB) are ignored (default = 0.05)").addDoubleParameter("maxStainOD", "Max total OD", 1., "", "Maximum staining OD - more densely stained pixels are ignored (default = 1)").addDoubleParameter("ignorePercentage", "Ignore extrema", 1., "%", "Percentage of extreme pixels to ignore, to improve robustness in the presence of noise/other artefacts (default = 1)").addBooleanParameter("checkColors", "Exclude unrecognised colors (H&E only)", false, "Exclude unexpected colors (e.g. green) that are likely to be caused by artefacts and not true staining");
// .addDoubleParameter("ignorePercentage", "Ignore extrema", 1., "%", 0, 20, "Percentage of extreme pixels to ignore, to improve robustness in the presence of noise/other artefacts");
Button btnAuto = new Button("Auto");
btnAuto.setOnAction(e -> {
double minOD = params.getDoubleParameterValue("minStainOD");
double maxOD = params.getDoubleParameterValue("maxStainOD");
double ignore = params.getDoubleParameterValue("ignorePercentage");
// Only accept if H&E
boolean checkColors = params.getBooleanParameterValue("checkColors") && stainsWrapper.getOriginalStains().isH_E();
ignore = Math.max(0, Math.min(ignore, 100));
// ColorDeconvolutionStains stains = estimateStains(imgFinal, stainsWrapper.getStains(), minOD, maxOD, ignore);
try {
ColorDeconvolutionStains stainsNew = EstimateStainVectors.estimateStains(img, stainsWrapper.getStains(), minOD, maxOD, ignore, checkColors);
stainsWrapper.setStains(stainsNew);
} catch (Exception e2) {
Dialogs.showErrorMessage("Estimate stain vectors", e2);
}
});
ParameterPanelFX panelParams = new ParameterPanelFX(params);
// panelParams.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
BorderPane panelAuto = new BorderPane();
// panelAuto.setBorder(BorderFactory.createTitledBorder("Auto detect"));
panelAuto.setCenter(panelParams.getPane());
panelAuto.setBottom(btnAuto);
// JScrollPane scrollPane = new JScrollPane(table);
// JPanel panelTable = new JPanel(new BorderLayout());
// panelTable.add(scrollPane, BorderLayout.CENTER);
// // JTextArea textInstructions = new JTextArea();
// // textInstructions.setWrapStyleWord(true);
// // textInstructions.setLineWrap(true);
// // textInstructions.setText(
// // "Viewer for manually and automatically adjusting stain vectors used for stain separation.\n\n" +
// // "Each stain vector is 3 values describing the red, green and blue components that define the colour of each " +
// // "stain (e.g. hematoxylin, DAB, eosin). The scatterplots show how these relate to pixel colours for each " +
// // "combination of red, green and blue.\n\n" +
// // "'Good' stain vectors should point along the edges of the scattered points, ignoring any artefacts resulting from " +
// // "pixels that don't belong to normal staining patterns."
// // );
// // panelTable.add(new JScrollPane(textInstructions), BorderLayout.SOUTH);
// panelTable.setBorder(BorderFactory.createTitledBorder("Stain vectors"));
panelSouth.setCenter(new TitledPane("Stain vectors", table));
panelSouth.setBottom(new TitledPane("Auto detect", panelAuto));
BorderPane panelMain = new BorderPane();
panelMain.setCenter(panelPlots);
panelMain.setBottom(panelSouth);
if (Dialogs.showConfirmDialog("Visual Stain Editor", panelMain)) {
return stainsWrapper.getStains();
} else {
stainsWrapper.resetStains();
return stainsWrapper.getStains();
}
}
Aggregations