use of qupath.lib.objects.MetadataStore in project qupath by qupath.
the class ObservableMeasurementTableData method updateMeasurementList.
/**
* Update the entire measurement list for the current objects.
* @see #setImageData(ImageData, Collection)
*/
public synchronized void updateMeasurementList() {
// PathPrefs.setAllredMinPercentagePositive(0);
builderMap.clear();
// Add the image name
if (!PathPrefs.maskImageNamesProperty().get())
builderMap.put("Image", new ImageNameMeasurementBuilder(imageData));
// Check if we have any annotations / TMA cores
boolean containsDetections = false;
boolean containsAnnotations = false;
// boolean containsParentAnnotations = false;
boolean containsTMACores = false;
boolean containsRoot = false;
List<PathObject> pathObjectListCopy = new ArrayList<>(list);
for (PathObject temp : pathObjectListCopy) {
if (temp instanceof PathAnnotationObject) {
// if (temp.hasChildren())
// containsParentAnnotations = true;
containsAnnotations = true;
} else if (temp instanceof TMACoreObject) {
containsTMACores = true;
} else if (temp instanceof PathDetectionObject) {
containsDetections = true;
} else if (temp.isRootObject())
containsRoot = true;
}
boolean detectionsAnywhere = imageData == null ? containsDetections : !imageData.getHierarchy().getDetectionObjects().isEmpty();
// Include the object displayed name
// if (containsDetections || containsAnnotations || containsTMACores)
builderMap.put("Name", new ObjectNameMeasurementBuilder());
// Include the class
if (containsAnnotations || containsDetections) {
builderMap.put("Class", new PathClassMeasurementBuilder());
// Get the name of the containing TMA core if we have anything other than cores
if (imageData != null && imageData.getHierarchy().getTMAGrid() != null) {
builderMap.put("TMA core", new TMACoreNameMeasurementBuilder());
}
// Get the name of the first parent object
builderMap.put("Parent", new ParentNameMeasurementBuilder());
}
// Include the TMA missing status, if appropriate
if (containsTMACores) {
builderMap.put("Missing", new MissingTMACoreMeasurementBuilder());
}
if (containsAnnotations || containsDetections) {
builderMap.put("ROI", new ROINameMeasurementBuilder());
}
// Add centroids
if (containsAnnotations || containsDetections || containsTMACores) {
// ROICentroidMeasurementBuilder builder = new ROICentroidMeasurementBuilder(imageData, CentroidType.X);
// builderMap.put("Centroid X", builder);
// builder = new ROICentroidMeasurementBuilder(imageData, CentroidType.Y);
// builderMap.put("Centroid Y", builder);
ROICentroidMeasurementBuilder builder = new ROICentroidMeasurementBuilder(imageData, CentroidType.X);
builderMap.put(builder.getName(), builder);
builder = new ROICentroidMeasurementBuilder(imageData, CentroidType.Y);
builderMap.put(builder.getName(), builder);
}
// If we have metadata, store it
Set<String> metadataNames = new LinkedHashSet<>();
metadataNames.addAll(builderMap.keySet());
for (PathObject pathObject : pathObjectListCopy) {
if (pathObject instanceof MetadataStore) {
metadataNames.addAll(((MetadataStore) pathObject).getMetadataKeys());
}
}
// Ensure we have suitable builders
for (String name : metadataNames) {
if (!builderMap.containsKey(name))
builderMap.put(name, new StringMetadataMeasurementBuilder(name));
}
// Get all the 'built-in' feature measurements, stored in the measurement list
Collection<String> features = PathClassifierTools.getAvailableFeatures(pathObjectListCopy);
// Add derived measurements if we don't have only detections
if (containsAnnotations || containsTMACores || containsRoot) {
if (detectionsAnywhere) {
var builder = new ObjectTypeCountMeasurementBuilder(PathDetectionObject.class);
builderMap.put(builder.getName(), builder);
features.add(builder.getName());
}
// Here, we allow TMA cores to act like annotations
manager = new DerivedMeasurementManager(getImageData(), containsAnnotations || containsTMACores);
for (MeasurementBuilder<?> builder2 : manager.getMeasurementBuilders()) {
builderMap.put(builder2.getName(), builder2);
features.add(builder2.getName());
}
}
// If we have an annotation, add shape features
if (containsAnnotations) {
boolean anyPoints = false;
boolean anyAreas = false;
boolean anyLines = false;
@SuppressWarnings("unused") boolean anyPolygons = false;
for (PathObject pathObject : pathObjectListCopy) {
if (!pathObject.isAnnotation())
continue;
ROI roi = pathObject.getROI();
if (roi == null)
continue;
if (roi.isPoint())
anyPoints = true;
if (roi.isArea())
anyAreas = true;
if (roi.isLine())
anyLines = true;
if (pathObject.getROI() instanceof PolygonROI)
anyPolygons = true;
}
// Add point count, if needed
if (anyPoints) {
MeasurementBuilder<?> builder = new NumPointsMeasurementBuilder();
builderMap.put(builder.getName(), builder);
features.add(builder.getName());
}
// Add spatial measurements, if needed
if (anyAreas) {
MeasurementBuilder<?> builder = new AreaMeasurementBuilder(imageData);
builderMap.put(builder.getName(), builder);
features.add(builder.getName());
builder = new PerimeterMeasurementBuilder(imageData);
builderMap.put(builder.getName(), builder);
features.add(builder.getName());
}
if (anyLines) {
MeasurementBuilder<?> builder = new LineLengthMeasurementBuilder(imageData);
builderMap.put(builder.getName(), builder);
features.add(builder.getName());
}
// if (anyPolygons) {
// MeasurementBuilder<?> builder = new MaxDiameterMeasurementBuilder(imageData);
// builderMap.put(builder.getName(), builder);
// features.add(builder.getName());
//
// builder = new MinDiameterMeasurementBuilder(imageData);
// builderMap.put(builder.getName(), builder);
// features.add(builder.getName());
// }
}
if (containsAnnotations || containsTMACores || containsRoot) {
var pixelClassifier = getPixelLayer(imageData);
if (pixelClassifier instanceof ImageServer<?>) {
ImageServer<BufferedImage> server = (ImageServer<BufferedImage>) pixelClassifier;
if (server.getMetadata().getChannelType() == ImageServerMetadata.ChannelType.CLASSIFICATION || server.getMetadata().getChannelType() == ImageServerMetadata.ChannelType.PROBABILITY) {
var pixelManager = new PixelClassificationMeasurementManager(server);
for (String name : pixelManager.getMeasurementNames()) {
// String nameLive = name + " (live)";
String nameLive = "(Live) " + name;
builderMap.put(nameLive, new PixelClassifierMeasurementBuilder(pixelManager, name));
features.add(nameLive);
}
}
}
}
// Update all the lists, if necessary
boolean changes = false;
if (metadataNames.size() != metadataList.size() || !metadataNames.containsAll(metadataList)) {
changes = metadataList.setAll(metadataNames);
}
if (features.size() != measurementList.size() || !features.containsAll(measurementList))
changes = measurementList.setAll(features);
if (changes) {
if (metadataList.isEmpty())
fullList.setAll(measurementList);
else {
fullList.setAll(metadataList);
fullList.addAll(measurementList);
}
}
}
Aggregations