use of qupath.lib.objects.PathObject in project qupath by qupath.
the class SplitAnnotationsPlugin method getTasks.
@Override
protected Collection<Runnable> getTasks(final PluginRunner<T> runner) {
Collection<? extends PathObject> parentObjects = getParentObjects(runner);
if (parentObjects == null || parentObjects.isEmpty())
return Collections.emptyList();
// Add a single task, to avoid multithreading - which may complicate setting parents
List<Runnable> tasks = new ArrayList<>(1);
PathObjectHierarchy hierarchy = getHierarchy(runner);
// Want to reset selection
PathObject selected = hierarchy.getSelectionModel().getSelectedObject();
tasks.add(() -> {
/*
* Resolving the hierarchy with many objects can be very slow.
* Here, we take an object, split it and then add it below the original object in the hierarchy.
* We then just need to remove the originals, allowing the newly-added objects to have their
* parents reassigned.
*/
List<PathObject> toAdd = new ArrayList<>();
List<PathObject> toRemove = new ArrayList<>();
List<PathObject> localSplit = new ArrayList<>();
Set<PathObject> toSelect = new HashSet<>();
for (PathObject pathObject : parentObjects) {
localSplit.clear();
ROI roiOrig = pathObject.getROI();
if (roiOrig == null) {
toSelect.add(pathObject);
continue;
}
var splitROIs = RoiTools.splitROI(roiOrig);
if (splitROIs.size() == 1)
continue;
toRemove.add(pathObject);
for (var r : splitROIs) {
var annotation = PathObjects.createAnnotationObject(r, pathObject.getPathClass());
annotation.setLocked(pathObject.isLocked());
localSplit.add(annotation);
}
if (pathObject.hasChildren()) {
for (var temp : localSplit) hierarchy.addPathObjectBelowParent(pathObject, temp, false);
} else
pathObject.addPathObjects(localSplit);
toAdd.addAll(localSplit);
}
if (toAdd.isEmpty() && toRemove.isEmpty())
return;
hierarchy.getSelectionModel().clearSelection();
toSelect.addAll(toAdd);
hierarchy.removeObjects(toRemove, true);
// hierarchy.addPathObjects(toAdd, false);
hierarchy.getSelectionModel().selectObjects(toSelect);
if (toSelect.contains(selected))
hierarchy.getSelectionModel().setSelectedObject(selected, true);
});
return tasks;
}
use of qupath.lib.objects.PathObject in project qupath by qupath.
the class QP method clearTMAGrid.
/**
* Remove the TMA grid from the current {@code PathObjectHierarchy}.
*
* @see #getCurrentHierarchy
*/
public static void clearTMAGrid() {
PathObjectHierarchy hierarchy = getCurrentHierarchy();
if (hierarchy == null)
return;
hierarchy.setTMAGrid(null);
PathObject selected = hierarchy.getSelectionModel().getSelectedObject();
if (selected instanceof TMACoreObject)
hierarchy.getSelectionModel().setSelectedObject(null);
}
use of qupath.lib.objects.PathObject in project qupath by qupath.
the class FindConvexHullDetectionsPlugin method addRunnableTasks.
@Override
protected void addRunnableTasks(ImageData<T> imageData, PathObject parentObject, List<Runnable> tasks) {
boolean deleteImmediately = Boolean.TRUE.equals(params.getBooleanParameterValue("deleteImmediately"));
tasks.add(new PathTask() {
private List<PathObject> toRemove;
private int nRemoved;
@Override
public void run() {
toRemove = getConvexHullDetections(imageData.getHierarchy(), parentObject, params.getIntParameterValue("nIterations"));
nRemoved = toRemove.size();
}
@Override
public void taskComplete(boolean wasCancelled) {
if (wasCancelled)
return;
if (toRemove != null && !toRemove.isEmpty()) {
if (deleteImmediately)
imageData.getHierarchy().removeObjects(toRemove, false);
else {
imageData.getHierarchy().getSelectionModel().deselectObject(parentObject);
imageData.getHierarchy().getSelectionModel().selectObjects(toRemove);
}
toRemove = null;
nObjectsRemoved.addAndGet(nRemoved);
}
}
@Override
public String getLastResultsDescription() {
String process = deleteImmediately ? "Removed " : "Selected ";
if (Boolean.TRUE.equals(params.getBooleanParameterValue("deleteImmediately")))
if (nRemoved == 1)
return process + " 1 object";
return process + nRemoved + " objects";
}
});
}
use of qupath.lib.objects.PathObject in project qupath by qupath.
the class FindConvexHullDetectionsPlugin method getConvexHullDetections.
static List<PathObject> getConvexHullDetections(final PathObjectHierarchy hierarchy, final PathObject parent, final int nIterations) {
Map<Point2, PathObject> pointsMap = new HashMap<>();
List<PathObject> convexDetections = new ArrayList<>();
Collection<PathObject> pathObjects = PathObjectTools.getDescendantObjects(parent, null, PathDetectionObject.class);
if (pathObjects.isEmpty())
return Collections.emptyList();
// Populate the points map
pointsMap.clear();
for (PathObject child : pathObjects) {
if (!child.hasROI())
continue;
pointsMap.put(new Point2(child.getROI().getCentroidX(), child.getROI().getCentroidY()), child);
}
// Determine what to remove
List<Point2> points = new ArrayList<>(pointsMap.keySet());
for (int i = 0; i < nIterations; i++) {
List<Point2> convexPoints = ConvexHull.getConvexHull(points);
if (convexPoints != null) {
for (Point2 p : convexPoints) convexDetections.add(pointsMap.get(p));
points.removeAll(convexPoints);
}
}
return convexDetections;
}
use of qupath.lib.objects.PathObject in project qupath by qupath.
the class RigidObjectEditorCommand method run.
@Override
public void run() {
// Object is already being edited
if (this.originalObject != null) {
// viewer.setSelectedObject(tempObject);
return;
}
// Get the selected object
viewer = qupath.getViewer();
PathObject pathObject = getSelectedObject(viewer);
if (pathObject == null || !(pathObject.isAnnotation() || pathObject.isTMACore())) {
Dialogs.showErrorNotification("Rotate annotation", "No annotation selected!");
return;
}
if (pathObject.isLocked()) {
Dialogs.showErrorNotification("Rotate annotation", "Selected annotation is locked!");
return;
}
// if (pathObject.getROI().isPoint()) {
// Dialogs.showErrorNotification("Rotate annotation", "Point annotations cannot be rotated, sorry!");
// return;
// }
ImageRegion bounds = viewer.getServerBounds();
if (pathObject.isTMACore()) {
for (PathObject child : pathObject.getChildObjectsAsArray()) {
if (isSuitableAnnotation(child)) {
originalObjectROIs.put(child, child.getROI());
}
}
if (originalObjectROIs.isEmpty()) {
Dialogs.showErrorMessage("Rigid refinement problem", "TMA core must contain empty annotations objects for rigid refinement");
return;
}
}
originalObjectROIs.put(pathObject, pathObject.getROI());
this.originalObject = pathObject;
viewer.setActiveTool(null);
qupath.setToolSwitchingEnabled(false);
viewer.addViewerListener(this);
viewer.getView().addEventHandler(MouseEvent.ANY, mouseListener);
// // Remove selected object & create an overlay showing the currently-being-edited version
// viewer.getHierarchy().removeObject(originalObject, true, true);
transformer = new RoiAffineTransformer(bounds, originalObject.getROI());
// editingROI = new RotatedROI((PathArea)originalObject.getROI());
// editingROI.setAngle(Math.PI/3);
overlay = new AffineEditOverlay(viewer.getOverlayOptions());
viewer.getCustomOverlayLayers().add(overlay);
PathPrefs.paintSelectedBoundsProperty().set(false);
// Create & show temporary object
for (Entry<PathObject, ROI> entry : originalObjectROIs.entrySet()) ((PathROIObject) entry.getKey()).setROI(transformer.getTransformedROI(entry.getValue(), false));
// Reset any existing editor (and its visible handles)
viewer.getROIEditor().setROI(null);
viewer.repaint();
// tempObject = createTransformedObject();
// ((PathAnnotationObject)tempObject).setLocked(true);
// viewer.setSelectedObject(tempObject);
}
Aggregations