use of qupath.lib.measurements.MeasurementList in project qupath by qupath.
the class ShapeFeaturesPlugin method addRunnableTasks.
@Override
protected void addRunnableTasks(final ImageData<T> imageData, final PathObject parentObject, List<Runnable> tasks) {
PixelCalibration cal = imageData == null ? null : imageData.getServer().getPixelCalibration();
boolean useMicrons = params.getBooleanParameterValue("useMicrons") && cal != null && cal.hasPixelSizeMicrons();
double pixelWidth = useMicrons ? cal.getPixelWidthMicrons() : 1;
double pixelHeight = useMicrons ? cal.getPixelHeightMicrons() : 1;
String unit = useMicrons ? GeneralTools.micrometerSymbol() : "px";
boolean doArea = params.getBooleanParameterValue("area");
boolean doPerimeter = params.getBooleanParameterValue("perimeter");
boolean doCircularity = params.getBooleanParameterValue("circularity");
ROI roi = (parentObject.hasROI() && parentObject.getROI().isArea()) ? parentObject.getROI() : null;
if (roi != null) {
tasks.add(new Runnable() {
@Override
public void run() {
try {
MeasurementList measurementList = parentObject.getMeasurementList();
ROI roi;
if (parentObject instanceof PathCellObject) {
roi = ((PathCellObject) parentObject).getNucleusROI();
if (roi != null && roi.isArea())
addMeasurements(measurementList, roi, "Nucleus Shape: ", pixelWidth, pixelHeight, unit, doArea, doPerimeter, doCircularity);
roi = parentObject.getROI();
if (roi != null && roi.isArea())
addMeasurements(measurementList, roi, "Cell Shape: ", pixelWidth, pixelHeight, unit, doArea, doPerimeter, doCircularity);
} else {
roi = parentObject.getROI();
if (roi != null && roi.isArea())
addMeasurements(measurementList, roi, "ROI Shape: ", pixelWidth, pixelHeight, unit, doArea, doPerimeter, doCircularity);
}
measurementList.close();
} catch (Exception e) {
e.printStackTrace();
throw (e);
}
}
});
}
}
use of qupath.lib.measurements.MeasurementList in project qupath by qupath.
the class SmoothFeaturesPlugin method addRunnableTasks.
@Override
protected void addRunnableTasks(final ImageData<T> imageData, final PathObject parentObject, List<Runnable> tasks) {
double fwhm;
ImageServer<T> server = imageData.getServer();
String fwhmStringTemp;
PixelCalibration cal = server == null ? null : server.getPixelCalibration();
if (cal != null && cal.hasPixelSizeMicrons()) {
fwhm = getParameterList(imageData).getDoubleParameterValue("fwhmMicrons");
fwhmStringTemp = GeneralTools.createFormatter(2).format(fwhm) + " " + GeneralTools.micrometerSymbol();
fwhm /= cal.getAveragedPixelSizeMicrons();
// params.addDoubleParameter("fwhmPixels", "Radius (FWHM)", fwhm, "pixels"); // Set the FWHM in pixels too
} else {
fwhm = getParameterList(imageData).getDoubleParameterValue("fwhmPixels");
fwhmStringTemp = GeneralTools.createFormatter(2).format(fwhm) + " px";
}
// sigma = 50;
final String fwhmString = fwhmStringTemp;
final double fwhmPixels = fwhm;
final boolean withinClass = params.getBooleanParameterValue("smoothWithinClasses");
final boolean useLegacyNames = params.containsKey("useLegacyNames") && Boolean.TRUE.equals(params.getBooleanParameterValue("useLegacyNames"));
tasks.add(new Runnable() {
@Override
public void run() {
try {
if (!parentObject.hasChildren())
return;
// System.out.println("Smoothing with FWHM " +fwhmPixels);
// TODO: MAKE A MORE ELEGANT LIST!!!!
List<PathObject> pathObjects = PathObjectTools.getFlattenedObjectList(parentObject, null, false);
Iterator<PathObject> iterObjects = pathObjects.iterator();
while (iterObjects.hasNext()) {
PathObject temp = iterObjects.next();
if (!(temp instanceof PathDetectionObject || temp instanceof PathTileObject))
iterObjects.remove();
}
if (pathObjects.isEmpty())
return;
// TODO: ACCESS & USE THE CLASSIFIER DATA!!!!
List<String> measurements = new ArrayList<>(PathClassifierTools.getAvailableFeatures(pathObjects));
Iterator<String> iter = measurements.iterator();
while (iter.hasNext()) {
String name = iter.next().toLowerCase();
if (name.endsWith("smoothed") || name.startsWith("smoothed") || name.contains(" - smoothed (fwhm ") || name.startsWith("smoothed denominator (local density, ") || name.startsWith("nearby detection counts"))
iter.remove();
}
logger.debug(String.format("Smooth features: %s (FWHM: %.2f px)", parentObject.getDisplayedName(), fwhmPixels));
smoothMeasurements(pathObjects, measurements, fwhmPixels, fwhmString, withinClass, useLegacyNames);
// // REMOVE - the purpose was to test a 'difference of Gaussians' type of thing
// List<String> namesAdded1 = new ArrayList<>(smoothMeasurements(pathObjects, measurements, fwhmPixels));
// List<String> namesAdded2 = new ArrayList<>(smoothMeasurements(pathObjects, measurements, fwhmPixels * 2));
// for (PathObject pathObject : pathObjects) {
// MeasurementList ml = pathObject.getMeasurementList();
// ml.ensureListOpen();
// for (int i = 0; i < namesAdded1.size(); i++) {
// String name1 = namesAdded1.get(i);
// String name2 = namesAdded2.get(i);
// double m1 = ml.getMeasurementValue(name1);
// double m2 = ml.getMeasurementValue(name2);
// ml.addMeasurement(name1 + " - " + name2, m1 - m2);
// }
// ml.closeList();
// }
} catch (Exception e) {
e.printStackTrace();
throw (e);
}
}
});
}
use of qupath.lib.measurements.MeasurementList in project qupath by qupath.
the class LocalBinaryPatternsPlugin method processObject.
static boolean processObject(final PathObject pathObject, final ParameterList params, final ImageServer<BufferedImage> server, final ColorDeconvolutionStains stains) throws InterruptedException, IOException {
String stainsName = (String) params.getChoiceParameterValue("stainChoice");
double mag = params.getDoubleParameterValue("magnification");
// int d = params.getIntParameterValue("haralickDistance");
boolean includeStats = params.getBooleanParameterValue("includeStats");
boolean doCircular = params.getBooleanParameterValue("doCircular");
double downsample = server.getMetadata().getMagnification() / mag;
ROI pathROI = pathObject.getROI();
if (pathROI == null)
return false;
// Get bounds
ImmutableDimension size = getPreferredTileSizePixels(server, params);
if (size.getWidth() / downsample < 1 || size.getHeight() / downsample < 1)
return false;
RegionRequest region = RegionRequest.createInstance(server.getPath(), downsample, (int) (pathROI.getCentroidX() + .5) - size.width / 2, (int) (pathROI.getCentroidY() + .5) - size.height / 2, size.width, size.height, pathROI.getT(), pathROI.getZ());
// System.out.println(bounds);
// System.out.println("Size: " + size);
BufferedImage img = server.readBufferedImage(region);
// System.out.println("Image size: " + img.getWidth() + " x " + img.getHeight() + " pixels");
// Get a buffer containing the image pixels
int w = img.getWidth();
int h = img.getHeight();
int[] buf = img.getRGB(0, 0, w, h, null, 0, w);
// Create a color transformer to get the images we need
float[] pixels = new float[buf.length];
SimpleModifiableImage pxImg = SimpleImages.createFloatImage(pixels, w, h);
MeasurementList measurementList = pathObject.getMeasurementList();
String postfix = " (" + getDiameterString(server, params) + ")";
if (stainsName.equals("H-DAB")) {
processTransformedImage(pxImg, buf, pixels, measurementList, "Hematoxylin" + postfix, ColorTransformer.ColorTransformMethod.Hematoxylin_H_DAB, stains, includeStats, doCircular);
processTransformedImage(pxImg, buf, pixels, measurementList, "DAB" + postfix, ColorTransformer.ColorTransformMethod.DAB_H_DAB, stains, includeStats, doCircular);
} else if (stainsName.equals("H&E")) {
processTransformedImage(pxImg, buf, pixels, measurementList, "Hematoxylin" + postfix, ColorTransformer.ColorTransformMethod.Hematoxylin_H_E, stains, includeStats, doCircular);
processTransformedImage(pxImg, buf, pixels, measurementList, "Eosin" + postfix, ColorTransformer.ColorTransformMethod.Eosin_H_E, stains, includeStats, doCircular);
} else if (stainsName.equals("H-DAB (8-bit)")) {
processTransformedImage(pxImg, buf, pixels, measurementList, "Hematoxylin 8-bit" + postfix, ColorTransformer.ColorTransformMethod.Hematoxylin_H_DAB_8_bit, stains, includeStats, doCircular);
processTransformedImage(pxImg, buf, pixels, measurementList, "DAB 8-bit" + postfix, ColorTransformer.ColorTransformMethod.DAB_H_DAB_8_bit, stains, includeStats, doCircular);
} else if (stainsName.equals("H&E (8-bit)")) {
processTransformedImage(pxImg, buf, pixels, measurementList, "Hematoxylin 8-bit" + postfix, ColorTransformer.ColorTransformMethod.Hematoxylin_H_E_8_bit, stains, includeStats, doCircular);
processTransformedImage(pxImg, buf, pixels, measurementList, "Eosin 8-bit" + postfix, ColorTransformer.ColorTransformMethod.Eosin_H_E_8_bit, stains, includeStats, doCircular);
} else if (stainsName.equals("Optical density")) {
processTransformedImage(pxImg, buf, pixels, measurementList, "OD sum" + postfix, ColorTransformer.ColorTransformMethod.Optical_density_sum, stains, includeStats, doCircular);
} else if (stainsName.equals("RGB")) {
processTransformedImage(pxImg, buf, pixels, measurementList, "Red" + postfix, ColorTransformer.ColorTransformMethod.Red, stains, includeStats, doCircular);
processTransformedImage(pxImg, buf, pixels, measurementList, "Green" + postfix, ColorTransformer.ColorTransformMethod.Green, stains, includeStats, doCircular);
processTransformedImage(pxImg, buf, pixels, measurementList, "Blue" + postfix, ColorTransformer.ColorTransformMethod.Blue, stains, includeStats, doCircular);
} else if (stainsName.equals("Grayscale")) {
processTransformedImage(pxImg, buf, pixels, measurementList, "Grayscale" + postfix, ColorTransformer.ColorTransformMethod.RGB_mean, stains, includeStats, doCircular);
}
measurementList.close();
return true;
}
use of qupath.lib.measurements.MeasurementList 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