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

Showing patients with multiple nodules #55

Open
jasonjin1 opened this issue Aug 11, 2022 · 9 comments
Open

Showing patients with multiple nodules #55

jasonjin1 opened this issue Aug 11, 2022 · 9 comments

Comments

@jasonjin1
Copy link

Hi, I had a question about how to go through a patient with multiple nodules. For example, I can see the first nodule of patient #1 and each annotation mask/slice to go along with it, but if patient 1 has multiple nodules each with different annotations is there any way I can check that?

Precisely, if a patient has more than 1 nodule, how would I know they have more than 1 and be able to access the other nodules? Thank you.

@notmatthancock
Copy link
Owner

There's no such thing as "nodule" in the LIDC dataset, i.e., there's no field that indicates Annotation 1 and Annotation 2 actually refer to the same physical nodule.

However, there is a utility implemented for clustering annotations of a scan based on the proximity of the annotation coordinates (see here: https://pylidc.github.io/tuts/scan.html#annotation-clustering). The result of clustering is a list of annotation groups (i.e., a list of list of annotations). Each annotation group is assumed to be associated with the same nodule.

Once you have an annotation group, you can use the consensus function (https://pylidc.github.io/tuts/consensus.html) to collapse them into a single bounding box.

@jasonjin1
Copy link
Author

jasonjin1 commented Aug 16, 2022

Hi, thank you.
I had another question regarding showing each annotation's mask. For example when I try to use the scan code for annotation 7 of patient 0078:

`patient_id = "LIDC-IDRI-0078"
scan = pl.query(pl.Scan).filter(pl.Scan.patient_id == patient_id).first()

ann = scan.annotations[7]
vol = ann.scan.to_volume()
padding = [(30,10), (10,25), (0,0)]
mask mask = ann.boolean_mask(pad=padding)
fig,ax = plt.subplots(1,2,figsize=(5,3))

ax.imshow(mask[:,:,2], cmap=plt.cm.gray)
ax.axis('off')
plt.show()`

I get an error message that states "Index 2 is out of bounds for axis 2 with size 2." This is odd to me because I can directly see the mask images for annotations 1-6 with this code easily but once it gets to 7 it does not work anymore. Do you know how I can view the 7th annotation in a plot? Thank you in advance.

Edit: I can also view annotations 8-13 fine but once i reach annotation 7, it seems it is the only one that has this error.

@notmatthancock
Copy link
Owner

There's no reason that all the annotations were annotated on the same number of slices. mask[:,:,2] is attempting to get the third slice of the mask, and apparently for annotation index 7, it was only annotated on two slices of the CT scan. E.g., maybe radiologist 1 thought a nodule spanned 3 slices while radiologist 1 only thought it spanned 2 slices.

If you just want to view the masks, use the middle slice for each or something, e.g.,

mask[:, :, mask.shape[2] // 2]

@jasonjin1
Copy link
Author

Thank you again. I've been working with the cluster_annotations and wondered if there was any way to pull the mask images individually. After using the cluster function, it returns the number of annotations per nodule such as in 0078:

# => Nodule 1 has 4 annotations.
# => Nodule 2 has 4 annotations.
# => Nodule 3 has 1 annotations.
# => Nodule 4 has 4 annotations.

Is there any way to pull the mask slice into a plot like in a 2D array such as [0][2] referring to nodule 1, annotation 3? Or not specifically this, but just in a way that would let me know which nodule in the list it belongs to? I know the annotation class lets us pull each image from a patient but it lacks the specificity of which nodule the mask belongs to. Annotation consensus only seems to allow us to plot all the annotations on one mask.

Thank you in advance.

@notmatthancock
Copy link
Owner

Sorry, I'm not sure what you're asking. It sounds like the cluster annotations function already gives your what you want. It returns a list of list of list of annotations. cluster_annotations()[0][2].boolean_mask() gives you the mask for the 3rd annotation on nodule 1. cluster_annotations()[i][j] is the j'th Annotation instance on the i'th nodule (according to the clustering procedure).

@jasonjin1
Copy link
Author

Hi, I believe that is what I'm looking for, thank you. I'm sorry I'm still confused about how to use the cluser_annotations()[i][j] to pull up the mask picture. Using mask = cluster_annotations()[0][2].boolean_mask() gives me an error and states "Cluster_annotations" is not defined. I'm precisely trying to pull up said mask in a pyplot to save the picture such as it does in annotation visualization.

@notmatthancock
Copy link
Owner

notmatthancock commented Aug 23, 2022

cluster_annotations is a member function of the Scan class: https://pylidc.github.io/scan.html#pylidc.Scan.cluster_annotations

  1. Retrieve a Scan instance (e.g., querying for a certain patient ID)
  2. Run cluster_annotations on the scan. This groups annotations such that scan.cluster_annotations()[i] is a list of annotations of nodule i for the given scan. scan.cluster_annotations()[i] contains at maximum 4 annotations because of how annotations were performed in the LIDC dataset.

@jasonjin1
Copy link
Author

Hi, I'm sorry, I still can't seem to get the code correct. I'm currently running it like so
scan = pl.query(pl.Scan).filter(pl.Scan.patient_id == 'LIDC-IDRI-0078').first()
vol = scan.to_volume()
nods = scan.cluster_annotations()
scan.cluster_annotations()[0][2].boolean_mask()

And then trying to get this mask using the rest of the annotation visualization such as
padding = [(30,10), (10,25), (0,0)]
mask = ann.boolean_mask(pad=padding)
fig,ax = plt.subplots(1,2,figsize=(5,3))
ax.imshow(mask[:, :, mask.shape[2] // 2], cmap=plt.cm.gray)

This doesn't seem to work and I'm not sure how to go from the cluster_annotations class to the scan annotation visualization. Thank you and sorry again.

@notmatthancock
Copy link
Owner

notmatthancock commented Aug 23, 2022

nodules = scan.cluster_annotations()
nodule1 = nodules[0]
annotation3_nodule1 = nodule1[2]

...

mask = annotation3_nodule1.boolean_mask()
...

etc

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

No branches or pull requests

2 participants