pylidc icon indicating copy to clipboard operation
pylidc copied to clipboard

Showing patients with multiple nodules

Open jasonjin1 opened this issue 3 years ago • 9 comments
trafficstars

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.

jasonjin1 avatar Aug 11 '22 02:08 jasonjin1

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.

notmatthancock avatar Aug 11 '22 22:08 notmatthancock

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.

jasonjin1 avatar Aug 16 '22 20:08 jasonjin1

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]

notmatthancock avatar Aug 17 '22 02:08 notmatthancock

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.

jasonjin1 avatar Aug 23 '22 05:08 jasonjin1

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).

notmatthancock avatar Aug 23 '22 13:08 notmatthancock

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.

jasonjin1 avatar Aug 23 '22 14:08 jasonjin1

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.

notmatthancock avatar Aug 23 '22 14:08 notmatthancock

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.

jasonjin1 avatar Aug 23 '22 14:08 jasonjin1

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

...

mask = annotation3_nodule1.boolean_mask()
...

etc

notmatthancock avatar Aug 23 '22 15:08 notmatthancock