use of qupath.lib.objects.hierarchy.TMAGrid in project qupath by qupath.
the class TMACommands method promptToAddTMARowOrColumn.
/**
* Add a new row or column to a TMA grid.
*
* @param imageData
* @param type
* @return
*/
private static boolean promptToAddTMARowOrColumn(final ImageData<?> imageData, final TMAAddType type) {
String NAME = type.commandName();
if (imageData == null) {
Dialogs.showNoImageError(NAME);
return false;
}
if (imageData.getHierarchy().getTMAGrid() == null) {
Dialogs.showErrorMessage(NAME, "No image with dearrayed TMA cores selected!");
return false;
}
PathObjectHierarchy hierarchy = imageData.getHierarchy();
PathObject selected = hierarchy.getSelectionModel().getSelectedObject();
TMACoreObject selectedCore = null;
if (selected != null)
selectedCore = PathObjectTools.getAncestorTMACore(selected);
TMAGrid gridNew = createAugmentedTMAGrid(hierarchy, selectedCore, type);
double w = imageData.getServer().getWidth();
double h = imageData.getServer().getHeight();
// Check if the core centroids all fall within the image or not
int outsideCores = 0;
for (TMACoreObject core : gridNew.getTMACoreList()) {
// Shouldn't happen...
if (!core.hasROI())
continue;
// Check if the centroid for any *new* core falls within the image
// (don't fail if an existing core is outside)
double x = core.getROI().getCentroidX();
double y = core.getROI().getCentroidY();
if (x < 0 || x >= w || y < 0 || y >= h) {
if (!hierarchy.getTMAGrid().getTMACoreList().contains(core)) {
outsideCores++;
}
// throw new IllegalArgumentException("Cannot update TMA grid - not enough space within image");
}
}
if (outsideCores > 0) {
String label = outsideCores == 1 ? "core" : "cores";
if (!Dialogs.showConfirmDialog("Add to TMA Grid", "Not enough space within image to store " + outsideCores + " new " + label + " - proceed anyway?"))
return false;
}
// If we got this far, update the grid
hierarchy.setTMAGrid(gridNew);
// Prompt for relabelling
TMACommands.promptToRelabelTMAGrid(imageData);
return true;
}
use of qupath.lib.objects.hierarchy.TMAGrid in project qupath by qupath.
the class TMAExplorer method createAndShowStage.
private void createAndShowStage() {
Project<BufferedImage> project = qupath.getProject();
entries.clear();
if (project != null) {
// Create an output directory for the images
File dirBaseImageOutput = Projects.getBaseDirectory(project);
dirBaseImageOutput = new File(dirBaseImageOutput, "TMA");
dirBaseImageOutput = new File(dirBaseImageOutput, "images");
if (!dirBaseImageOutput.exists())
dirBaseImageOutput.mkdirs();
Map<String, RunningStatistics> statsMap = new HashMap<>();
for (ProjectImageEntry<BufferedImage> imageEntry : project.getImageList()) {
// Look for data file
if (!imageEntry.hasImageData())
continue;
File dirImageOutput = new File(dirBaseImageOutput, imageEntry.getImageName());
if (!dirImageOutput.exists())
dirImageOutput.mkdirs();
// Read data
ImageData<BufferedImage> imageData;
try {
imageData = imageEntry.readImageData();
} catch (IOException e) {
logger.error("Error reading ImageData for " + imageEntry.getImageName(), e);
continue;
}
TMAGrid tmaGrid = imageData.getHierarchy().getTMAGrid();
if (tmaGrid == null) {
logger.warn("No TMA data for {}", imageEntry.getImageName());
continue;
}
// Figure out downsample value
ImageServer<BufferedImage> server = imageData.getServer();
double downsample = Math.round(5 / server.getPixelCalibration().getAveragedPixelSizeMicrons());
// Read the TMA entries
int counter = 0;
for (TMACoreObject core : tmaGrid.getTMACoreList()) {
counter++;
String name = core.getName();
if (name == null)
name = Integer.toString(counter);
File fileOutput = new File(dirImageOutput, name + ".jpg");
if (!fileOutput.exists()) {
try {
RegionRequest request = RegionRequest.createInstance(server.getPath(), downsample, core.getROI());
BufferedImage img = server.readBufferedImage(request);
ImageIO.write(img, "jpg", fileOutput);
} catch (Exception e) {
logger.error("Unable to write {}", fileOutput.getAbsolutePath());
}
}
var entry = TMAEntries.createDefaultTMAEntry(imageEntry.getImageName(), fileOutput.getAbsolutePath(), null, core.getName(), core.isMissing());
MeasurementList ml = core.getMeasurementList();
for (int i = 0; i < ml.size(); i++) {
String measurement = ml.getMeasurementName(i);
double val = ml.getMeasurementValue(i);
entry.putMeasurement(measurement, val);
if (!Double.isNaN(val)) {
RunningStatistics stats = statsMap.get(measurement);
if (stats == null) {
stats = new RunningStatistics();
statsMap.put(measurement, stats);
}
stats.addValue(val);
}
}
entries.add(entry);
}
try {
server.close();
} catch (Exception e) {
logger.warn("Problem closing server", e);
}
}
// Loop through all entries and perform outlier count
double k = 3;
for (TMAEntry entry : entries) {
int outlierCount = 0;
for (Entry<String, RunningStatistics> statsEntry : statsMap.entrySet()) {
RunningStatistics stats = statsEntry.getValue();
double val = entry.getMeasurementAsDouble(statsEntry.getKey());
if (!(val >= stats.getMean() - stats.getStdDev() * k && val <= stats.getMean() + stats.getStdDev() * k))
outlierCount++;
}
entry.putMeasurement("Outlier count", outlierCount);
}
}
Stage stage = new Stage();
stage.initOwner(qupath.getStage());
TMASummaryViewer summaryViewer = new TMASummaryViewer(stage);
summaryViewer.setTMAEntries(entries);
summaryViewer.getStage().show();
}
Aggregations