use of qupath.lib.objects.hierarchy.TMAGrid in project qupath by qupath.
the class TMAGridOverlay method paintOverlay.
@Override
public void paintOverlay(final Graphics2D g, final ImageRegion imageRegion, final double downsampleFactor, final ImageData<BufferedImage> imageData, final boolean paintCompletely) {
if (!isVisible())
return;
PathObjectHierarchy hierarchy = imageData == null ? null : imageData.getHierarchy();
if (hierarchy == null)
return;
TMAGrid tmaGrid = hierarchy.getTMAGrid();
if (tmaGrid == null)
return;
Graphics2D g2d = (Graphics2D) g.create();
// Set alpha composite if needed
setAlphaComposite(g2d);
// Rectangle serverBounds = imageRegion.getBounds();
// Ensure antialias is on...?
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
PathHierarchyPaintingHelper.paintTMAGrid(g2d, tmaGrid, getOverlayOptions(), hierarchy.getSelectionModel(), downsampleFactor);
g2d.dispose();
}
use of qupath.lib.objects.hierarchy.TMAGrid in project qupath by qupath.
the class TMADearrayerPluginIJ method addRunnableTasks.
@Override
protected void addRunnableTasks(final ImageData<BufferedImage> imageData, final PathObject parentObject, List<Runnable> tasks) {
if (dearrayer == null)
dearrayer = new Dearrayer();
tasks.add(() -> {
try {
dearrayer.runDetection(imageData, getParameterList(imageData), null);
TMAGrid tmaGrid = dearrayer.getTMAGrid();
if (tmaGrid != null)
imageData.getHierarchy().setTMAGrid(tmaGrid);
} catch (Exception e) {
logger.error("Error running TMA dearrayer", e);
}
});
}
use of qupath.lib.objects.hierarchy.TMAGrid in project qupath by qupath.
the class PathObjectTools method getTMACoreObjects.
/**
* Extract a list of TMA cores from an object hierarchy. If no cores are present, an empty list is returned.
*
* @param hierarchy
* @param includeMissingCores
* @return
*/
public static List<TMACoreObject> getTMACoreObjects(final PathObjectHierarchy hierarchy, final boolean includeMissingCores) {
TMAGrid tmaGrid = hierarchy.getTMAGrid();
if (tmaGrid == null || tmaGrid.nCores() == 0)
return Collections.emptyList();
// If we have a TMA grid, add all the objects
if (includeMissingCores)
return tmaGrid.getTMACoreList();
List<TMACoreObject> cores = new ArrayList<>();
for (TMACoreObject core : tmaGrid.getTMACoreList()) {
if (!core.isMissing())
cores.add(core);
}
return cores;
}
use of qupath.lib.objects.hierarchy.TMAGrid in project qupath by qupath.
the class TMADataImporter method importTMAData.
public static void importTMAData(ImageData<?> imageData) {
if (imageData == null) {
Dialogs.showNoImageError(TITLE);
return;
}
PathObjectHierarchy hierarchy = imageData.getHierarchy();
if (hierarchy.getTMAGrid() == null) {
Dialogs.showErrorMessage(TITLE, "No TMA grid has been set for the selected image!");
return;
}
// Show a GUI with the current TMA grid status
TMAGrid grid = hierarchy.getTMAGrid();
CoreInfoGrid infoGrid = new CoreInfoGrid(grid);
// Create the table
TableView<CoreInfoRow> table = new TableView<>();
table.getItems().setAll(infoGrid.getRows());
for (int c = 0; c < grid.getGridWidth(); c++) {
final int col = c;
TableColumn<CoreInfoRow, TMACoreObject> tableColumn = new TableColumn<>();
tableColumn.setCellValueFactory(column -> new ReadOnlyObjectWrapper<>(column.getValue().get(col)));
tableColumn.setCellFactory(column -> new CoreInfoTableCell());
tableColumn.setResizable(false);
table.getColumns().add(tableColumn);
}
table.widthProperty().addListener(c -> {
Pane headerRow = (Pane) table.lookup("TableHeaderRow");
headerRow.setMaxHeight(0);
headerRow.setMinHeight(0);
headerRow.setPrefHeight(0);
headerRow.setVisible(false);
});
table.getSelectionModel().setCellSelectionEnabled(true);
BorderPane pane = new BorderPane();
pane.setCenter(table);
// table.setPadding(new Insets(5));
// Label label = new Label("Import TMA map or unique identifiers for TMA cores.");
// pane.setTop(label);
Button btnImportData = new Button("Import data");
btnImportData.setTooltip(new Tooltip("Import TMA core data from a tab-delimited or .csv file"));
btnImportData.setOnAction(e -> {
if (handleImportDataFromFile(infoGrid))
table.refresh();
});
Button btnPasteData = new Button("Paste data");
btnPasteData.setTooltip(new Tooltip("Paste tab-delimited TMA core data from the clipboard"));
btnPasteData.setOnAction(e -> {
if (handleImportDataFromClipboard(infoGrid))
table.refresh();
});
Button btnPasteGrid = new Button("Paste grid");
btnPasteGrid.setTooltip(new Tooltip("Paste a tab-delimited grid containing TMA core names from the clipboard"));
btnPasteGrid.setOnAction(e -> {
if (handlePasteGrid(infoGrid)) {
table.refresh();
}
});
Button btnLoadGrid = new Button("Import grid");
btnLoadGrid.setTooltip(new Tooltip("Import a grid containing TMA core names from a tab-delimited or .csv file"));
btnLoadGrid.setOnAction(e -> {
if (handleLoadGridFromFile(infoGrid))
table.refresh();
});
GridPane buttonPane = PaneTools.createColumnGridControls(btnImportData, btnPasteData, btnLoadGrid, btnPasteGrid);
buttonPane.setHgap(10);
buttonPane.setPadding(new Insets(5, 0, 5, 0));
pane.setBottom(buttonPane);
if (Dialogs.builder().title(TITLE).content(pane).buttons(ButtonType.APPLY, ButtonType.CANCEL).showAndWait().orElse(ButtonType.CANCEL) == ButtonType.APPLY) {
infoGrid.synchronizeTMAGridToInfo();
hierarchy.fireObjectsChangedEvent(infoGrid, new ArrayList<>(grid.getTMACoreList()));
return;
}
}
use of qupath.lib.objects.hierarchy.TMAGrid in project qupath by qupath.
the class TMACommands method createAugmentedTMAGrid.
/**
* Add a new row or column to a TMA grid.
*
* @param hierarchy
* @param selectedCore
* @param type
* @return
*/
private static TMAGrid createAugmentedTMAGrid(final PathObjectHierarchy hierarchy, final TMACoreObject selectedCore, final TMAAddType type) {
TMAGrid grid = hierarchy.getTMAGrid();
// Convert to easier form
boolean addAfter = type == TMAAddType.COLUMN_AFTER || type == TMAAddType.ROW_AFTER;
boolean addColumn = type == TMAAddType.COLUMN_AFTER || type == TMAAddType.COLUMN_BEFORE;
// Try to identify the row/column that we want
int row = -1;
int col = -1;
if (selectedCore != null) {
for (int y = 0; y < grid.getGridHeight(); y++) {
for (int x = 0; x < grid.getGridWidth(); x++) {
if (grid.getTMACore(y, x) == selectedCore) {
if (addAfter) {
row = y + 1;
col = x + 1;
} else {
row = y;
col = x;
}
break;
}
}
}
}
// If we don't have a row or column, choose based on the add type
if (row < 0) {
switch(type) {
case COLUMN_AFTER:
col = grid.getGridWidth();
break;
case COLUMN_BEFORE:
col = 0;
break;
case ROW_AFTER:
row = grid.getGridHeight();
break;
case ROW_BEFORE:
row = 0;
break;
default:
break;
}
}
// Compute the width of the new grid
int newWidth = addColumn ? grid.getGridWidth() + 1 : grid.getGridWidth();
int newHeight = addColumn ? grid.getGridHeight() : grid.getGridHeight() + 1;
// Loop through cores, getting mean widths, heights & displacements
RunningStatistics statsWidth = new RunningStatistics();
RunningStatistics statsHeight = new RunningStatistics();
RunningStatistics statsDx = new RunningStatistics();
RunningStatistics statsDy = new RunningStatistics();
for (int r = 0; r < grid.getGridHeight(); r++) {
TMACoreObject coreColBefore = null;
for (int c = 0; c < grid.getGridWidth(); c++) {
TMACoreObject core = grid.getTMACore(r, c);
if (!core.hasROI())
continue;
statsWidth.addValue(core.getROI().getBoundsWidth());
statsHeight.addValue(core.getROI().getBoundsHeight());
if (coreColBefore != null && coreColBefore.hasROI()) {
statsDx.addValue(core.getROI().getCentroidX() - coreColBefore.getROI().getCentroidX());
}
if (r > 0) {
TMACoreObject coreRowBefore = grid.getTMACore(r - 1, c);
if (coreRowBefore != null && coreRowBefore.hasROI()) {
statsDy.addValue(core.getROI().getCentroidY() - coreRowBefore.getROI().getCentroidY());
}
}
coreColBefore = core;
}
}
double meanWidth = statsWidth.getMean();
double meanHeight = statsHeight.getMean();
double meanDx = statsDx.getMean();
double meanDy = statsDy.getMean();
double diameter = (meanWidth + meanHeight) / 2;
// Create a new list of cores, adding where necessary
List<TMACoreObject> coresNew = new ArrayList<>();
for (int r = 0; r < newHeight; r++) {
for (int c = 0; c < newWidth; c++) {
// Copy existing rows & columns, or create new cores if required
if (addColumn) {
if (c < col) {
coresNew.add(grid.getTMACore(r, c));
} else if (c > col) {
coresNew.add(grid.getTMACore(r, c - 1));
} else if (c == col) {
// Try to get average x & y coordinates between surrounding columns
double x1, x2, y;
if (col == 0) {
x2 = grid.getTMACore(r, c).getROI().getCentroidX();
x1 = x2 - meanDx * 2;
y = grid.getTMACore(r, c).getROI().getCentroidY();
} else if (col == grid.getGridWidth()) {
x1 = grid.getTMACore(r, c - 1).getROI().getCentroidX();
x2 = x1 + meanDx * 2;
y = grid.getTMACore(r, c - 1).getROI().getCentroidY();
} else {
x1 = grid.getTMACore(r, c - 1).getROI().getCentroidX();
x2 = grid.getTMACore(r, c).getROI().getCentroidX();
y = (grid.getTMACore(r, c - 1).getROI().getCentroidY() + grid.getTMACore(r, c).getROI().getCentroidY()) / 2;
}
TMACoreObject coreNew = PathObjects.createTMACoreObject((x1 + x2) / 2, y, diameter, true);
coresNew.add(coreNew);
}
} else {
if (r < row) {
coresNew.add(grid.getTMACore(r, c));
} else if (r > row) {
coresNew.add(grid.getTMACore(r - 1, c));
} else if (r == row) {
// Try to get average x & y coordinates between surrounding columns
double x, y1, y2;
if (row == 0) {
y2 = grid.getTMACore(r, c).getROI().getCentroidY();
y1 = y2 - meanDy * 2;
x = grid.getTMACore(r, c).getROI().getCentroidX();
} else if (row == grid.getGridHeight()) {
y1 = grid.getTMACore(r - 1, c).getROI().getCentroidY();
y2 = y1 + meanDy * 2;
x = grid.getTMACore(r - 1, c).getROI().getCentroidX();
} else {
y1 = grid.getTMACore(r - 1, c).getROI().getCentroidY();
y2 = grid.getTMACore(r, c).getROI().getCentroidY();
x = (grid.getTMACore(r - 1, c).getROI().getCentroidX() + grid.getTMACore(r, c).getROI().getCentroidX()) / 2;
}
TMACoreObject coreNew = PathObjects.createTMACoreObject(x, (y1 + y2) / 2, diameter, true);
coresNew.add(coreNew);
}
}
}
}
// Update with a new TMAGrid
return DefaultTMAGrid.create(coresNew, newWidth);
}
Aggregations