Search in sources :

Example 1 with PixelClassificationMeasurementManager

use of qupath.opencv.ml.pixel.PixelClassificationMeasurementManager 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);
        }
    }
}
Also used : LinkedHashSet(java.util.LinkedHashSet) ArrayList(java.util.ArrayList) BufferedImage(java.awt.image.BufferedImage) PolygonROI(qupath.lib.roi.PolygonROI) PathAnnotationObject(qupath.lib.objects.PathAnnotationObject) ImageServer(qupath.lib.images.servers.ImageServer) PathDetectionObject(qupath.lib.objects.PathDetectionObject) TMACoreObject(qupath.lib.objects.TMACoreObject) PolygonROI(qupath.lib.roi.PolygonROI) ROI(qupath.lib.roi.interfaces.ROI) MetadataStore(qupath.lib.objects.MetadataStore) PathObject(qupath.lib.objects.PathObject) PixelClassificationMeasurementManager(qupath.opencv.ml.pixel.PixelClassificationMeasurementManager)

Aggregations

BufferedImage (java.awt.image.BufferedImage)1 ArrayList (java.util.ArrayList)1 LinkedHashSet (java.util.LinkedHashSet)1 ImageServer (qupath.lib.images.servers.ImageServer)1 MetadataStore (qupath.lib.objects.MetadataStore)1 PathAnnotationObject (qupath.lib.objects.PathAnnotationObject)1 PathDetectionObject (qupath.lib.objects.PathDetectionObject)1 PathObject (qupath.lib.objects.PathObject)1 TMACoreObject (qupath.lib.objects.TMACoreObject)1 PolygonROI (qupath.lib.roi.PolygonROI)1 ROI (qupath.lib.roi.interfaces.ROI)1 PixelClassificationMeasurementManager (qupath.opencv.ml.pixel.PixelClassificationMeasurementManager)1