Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Streamline PathObject and simplify working with classifications #1593

Merged
merged 2 commits into from
Aug 17, 2024

Conversation

petebankhead
Copy link
Member

This PR removes some methods from PathObject that were previously deprecated.

It also introduces

public void setClassification(String classification)
public void getClassification()

which now exist alongside the earlier methods

// The originals
public void setPathClass(PathClass pathClass)
public PathClass getPathClass()

// New in v0.4.0
public void setClassifications(Collection<String> classifications)
public Set<String> getClassifications()

Having 3 different ways to set/get classifications may seem a bit much, but the intention is to make scripting as intuitive as possible. Each method has a different purpose:

  1. PathClass encapsulates everything about the classification: the different pieces (e.g. subclassifications) and the color; this is used internally
  2. The 'classification' is simply a String representation of the PathClass; it can represent the key pieces (with a colon delimiter for subclassifications), but not the color
  3. The 'classifications' are a set that represents the different part of the classification, but not the color; this is intended for cases when you'd really like to have multiple classifications, and what to treat the 'derived' parts of a classification as if they are basically separate classifications (e.g. CD3: CD8)

In Groovy, checking if a cell has the derived classification "Tumor: Positive", and setting it to "Tumor: Negative" if not, would look like this:

// Original Java way (used in QuPath for all of the early years)
if (pathObject.getPathClass() != getPathClass("Tumor: Positive")) {
    pathObject.setPathClass(getPathClass("Tumor: Negative"))
}

// Using Groovy's way to avoid get/set
if (pathObject.pathClass != getPathClass("Tumor: Positive")) {
    pathObject.pathClass = getPathClass("Tumor: Negative")
}

// With strings
if (pathObject.classification != "Tumor: Positive") {
    pathObject.classification = "Tumor: Negative"
}

// With classifications
if (pathObject.classifications != ["Tumor: Positive"] as Set) {
    pathObject.classifications = ["Tumor", "Negative"]
}

I think the working with string is a bit less cumbersome and confusing than needing to add lots of getPathClass() lines. But it is more powerful with tricks like this

// Set all cells to be classified as 'Tumor'
getCellObjects().each {it.classification = 'Tumor'}

// And 'Negative' as a (sub?) classification to all cells
getCellObjects().each {it.classifications  = 'Negative'}

// Remove 'Negative' as a (sub?) classification from all cells
getCellObjects().each {it.classifications -= 'Negative'}

// Select all the objects classification *exactly* as tumor
selectObjects {it.classification == 'Tumor'}

// Select all the objects with 'Tumor' *somewhere* in their classification
selectObjects {'Tumor' in it.classifications}

The fact that classification and classifications differ by only a letter might be a bit confusing, but getting it wrong should throw an exception.... so hopefully the benefits are worth it.

Remove deprecated methods.
This is a convenience method to help work with classifications easily within scripts.
@petebankhead petebankhead added this to the v0.6.0 milestone Aug 17, 2024
@petebankhead petebankhead merged commit 4e7c424 into qupath:main Aug 17, 2024
3 checks passed
@petebankhead petebankhead deleted the path-objects branch August 17, 2024 19:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant