Cheese Phantom - CIRS HU-ED

260 views
Skip to first unread message

Ethan Butson

unread,
Jul 28, 2023, 12:27:44 AM7/28/23
to Pylinac
Hi Brains Trust,

Trying to adapt the Cheese Phantom module to the CIRS Electron Density phantom, and initially had some similar problems to the Gammex phantom errors. I implemented the recommendations, with the foam block, which fixed the "non-empty take" error, but Pylinac is now raising a ValueError and looks like it hasn't found the phantom centre (traceback attached). I'm wondering if it's due to the fact that the phantom isn't cylindrical or if it's another issue?... Anyway, code also plots an image from the dicom stack before the analysis as a sanity check.

Would appreciate any help and/or insight people may have. Images attached. :)

Sincerely,

Ethan B.
cirs_phantom.py
traceback.txt

Ethan Butson

unread,
Jul 28, 2023, 12:31:18 AM7/28/23
to Pylinac
Can't attach images it seems. Attached as link from onedrive.



James Kerns

unread,
Jul 28, 2023, 2:50:58 PM7/28/23
to Ethan Butson, Pylinac
You're really close. Unfortunately, pylinac also needs a small change, or if you can change your setup just slightly it could work. 

Here's what I get after two tweaks.
hu_origin_slice_variance = 150
localization_radius = 60
catphan_radius_mm = 155

This is 90% of it. There's an assumption that the localization ring values are mostly near the median. This is true when the ROIs are spaced fairly well apart. I'm using the closer ring of ROIs for localization. 
If you want to use this ring then you'll need to change this line (pylinac/pylinac/ct.py at release-v3.13 · jrkerns/pylinac · GitHub). I used 60 and 20 and with the above changes I was able to get the analysis working. 

The reason I didn't use the outer ring, which probably would've not run into this problem is that the localization ring also assumes there are very low and very high HU values. In the catphan there is air and teflon, so that assumption holds true.
In your outer ring there's no low HU ROI. This will fail the hu_origin_slice_variance test because it tests for HUs below the variance and above the variance. If you can and are willing to swap one of the outer ROIs with air/empty, then you 
will likely be able to get this working with just the tweaks from above (albeit with different localization_radius). 

I have been thinking about these "detection" tests and how I can rework them. I'm currently thinking of a plugin type framework where the user can specify functions for various things including detection. So in the future you'd write a custom function and it would (in this case) be passed the slice and you'd process the slice yourself to do custom logic.



On Thu, Jul 27, 2023 at 11:31 PM Ethan Butson <ethanb...@gmail.com> wrote:
Can't attach images it seems. Attached as link from onedrive.



--
You received this message because you are subscribed to the Google Groups "Pylinac" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pylinac+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pylinac/ad2fcffa-0091-4bf4-94fe-cad43f04bfe8n%40googlegroups.com.
Figure_1.png

Ethan Butson

unread,
Jul 29, 2023, 3:46:29 AM7/29/23
to Pylinac
I'm still getting the same ValueError...which is weird if it's working on your system. I also tried making a new venv, reinstalling pylinac and then making your suggested changes, same issue. When I'm back in at work will swap one of the outer segments to air (or maybe the lung inhale) and try it again...seems like the easiest fix. Really appreciate your work and support!

That sounds fair, plugins sound great! I love the automation Pylinac provides, but I understand the difficulty in ensuring the system is flexible enough. A thought in that vein, I feel since we already need to input the ROIs to the Cheese module, since we know the geometry of interest (i.e. location and size), then you could pass the ROIs as a sort of initial guess and then, kind of like with the Winston Lutz algorithms, find the area of the inserts near the initial point. I.e. fit/check the circle, verify it's close to the expected ROI  size and then minimise the actual positions to expected positions to find the rotation...something like from scipy transform module I recommended for the MTWL stuff. That way you avoid the HU assumptions r.e. high/low HU...you's just need to set a contrast-noise-ratio to determine if each circle. Big change vs how it's currently implemented, but just a thought. :)

Once again, thanks for the ideas! Will give it a try next week and report back then..

James Kerns

unread,
Jul 31, 2023, 6:07:11 PM7/31/23
to Pylinac
Hmm, weird. I used the 3.13 version and also master branch and both worked. Let me know if you're still running into problems.

Ethan Butson

unread,
Aug 1, 2023, 11:38:51 PM8/1/23
to Pylinac
Took a new scan and it worked with the suggestions provided...except for using the outer diameter....for whatever reason it only seems to work with the inner diameter. *shrug*.

This is more a point of interest for field testing a project idea at the moment, so will possibly come back around to having a deeper look at the code when I've got some more free time. For the moment it gives me the data I need. Thanks again, you're a legend and really appreciate your support! :)

James Kerns

unread,
Aug 2, 2023, 10:55:39 AM8/2/23
to Pylinac
I'd like to support the CIRS phantom since it's a commercial phantom. Would you be willing to send me those/more scans and/or allow me to use one set as the demo dataset? (I'd clean the basic tags).

Ethan Butson

unread,
Aug 2, 2023, 9:50:16 PM8/2/23
to Pylinac
So, I ended up messing around with it a bit more, and by pulling the "middle variation" in a bit further, was able to get it to work on my system with the inner ring by using 60 and 40 as bounds rather than 60 and 20.

I'll check with my bosses, but I can't imagine there being an issue. Let me know what sort of scans you'd like (kV/mAs/orientations/offsets/etc) and I can scan them one afternoon. Just wondering if it would be useful for pylinac if you had/posted a "wish-list" for images/datasets, so that way people know what would be most useful to contribute? From the outside, I don't know what y'all would find useful. :)

James Kerns

unread,
Aug 3, 2023, 11:04:09 AM8/3/23
to Pylinac
Oooh,  a wish-list. That sounds like a great idea. I've been mulling over if I should switch forums to something more capable like discourse. That would provide better links, rendering, categorization, etc but I'd have to pay for it. Github also has a forum-like tool but it doesn't seem as capable. I'll have to investigate!

James Kerns

unread,
Nov 9, 2023, 3:34:19 PM11/9/23
to Pylinac
Coming back to this. Is the center supposed to be an ROI? It looks like it on the website but you had this commented out.

James Kerns

unread,
Nov 9, 2023, 3:53:01 PM11/9/23
to Pylinac

Ethan Butson

unread,
Nov 9, 2023, 4:41:30 PM11/9/23
to Pylinac
Hi mate,

Absolutely the central insert is supposed to be an ROI. We use a weird central insert locally and commenting the ROI out was for trying to get it to work with existing/old scans. Sorry for the confusion.

liptec...@gmail.com

unread,
Jan 9, 2024, 8:45:38 PM1/9/24
to Pylinac
Hi Ethan and James,

Happy New Year!

Is pylinac v 3.18 ready for CIRS062M ?
Is it as easy as:

from pylinac import CIRS062M
CIRS062M.run_demo

Thanks for sharing.

regards,
LipTeck

Ethan Butson

unread,
Jan 9, 2024, 9:55:06 PM1/9/24
to Pylinac
Hi LipTeck,

There is no CIRS062M in the pylinac namespace, and there is no run_demo, but otherwise should be ready to rock and roll! So, import the module via cheese (from pylinac.cheese import CIRS062M) and it should be fine. Let us know how you go. 😊

Sincerely,

Ethan B

LipTeck CHEW

unread,
Jan 10, 2024, 3:04:03 AM1/10/24
to Ethan Butson, Pylinac
Hi Ethan,

I tried with:

from pylinac.cheese import CIRS062M
data_folder = r"D:/CIRS062M"
CIRS062M = CIRS062M(data_folder)
CIRS062M.analyze()
# print text to the console
print(CIRS062M.results())
# return a dictionary or dataclass
results = CIRS062M.results_data()
# view analyzed image summary
CIRS062M.plot_analyzed_image()
# save the images
CIRS062M.save_analyzed_image()
# finally, save a PDF
CIRS062M.publish_pdf()

Encountered error:
>>> %Run CIRS062M.py
C:\Users\chewlipteck\env\lib\site-packages\numpy\core\fromnumeric.py:3432: RuntimeWarning: Mean of empty slice.
  return _methods._mean(a, axis=axis, dtype=dtype,
C:\Users\chewlipteck\env\lib\site-packages\numpy\core\_methods.py:190: RuntimeWarning: invalid value encountered in double_scalars
  ret = ret.dtype.type(ret / rcount)
Traceback (most recent call last):
  File "C:\Users\chewlipteck\Documents\Work\Computing\Python\Python Scripts\pylinac\python\CIRS062M.py", line 4, in <module>
    CIRS062M.analyze()
  File "C:\Users\chewlipteck\env\lib\site-packages\pylinac\cheese.py", line 229, in analyze
    self.localize()
  File "C:\Users\chewlipteck\env\lib\site-packages\pylinac\ct.py", line 1769, in localize
    self._phantom_center_func = self.find_phantom_axis()
  File "C:\Users\chewlipteck\env\lib\site-packages\pylinac\ct.py", line 1843, in find_phantom_axis
    fit_zx = np.poly1d(np.polyfit(zs[common_idxs], center_xs[common_idxs], deg=1))
  File "<__array_function__ internals>", line 180, in polyfit
  File "C:\Users\chewlipteck\env\lib\site-packages\numpy\lib\polynomial.py", line 638, in polyfit
    raise TypeError("expected non-empty vector for x")
TypeError: expected non-empty vector for x

regards,
LipTeck

You received this message because you are subscribed to a topic in the Google Groups "Pylinac" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/pylinac/ZkYKHtaVNhE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to pylinac+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/pylinac/00ac19a2-5e79-4414-80cf-dea2c22060a0n%40googlegroups.com.

James Kerns

unread,
Jan 10, 2024, 10:57:45 AM1/10/24
to Pylinac
The CIRS analysis is pretty new so there may be a bug or two. You can upload the images here and I'll take a look.  Pylinac image donation form (google.com) Thanks

LipTeck CHEW

unread,
Jan 11, 2024, 8:49:30 PM1/11/24
to James Kerns, Pylinac
Just uploaded a CIRS062M with water insert

James Kerns

unread,
Jan 12, 2024, 2:32:23 PM1/12/24
to Pylinac
The Phantom is sitting directly on the table. This causes detection of the phantom area to fail since the phantom and table produce one contiguous ROI. Set the phantom on a low-density material like a foam block and you should have better luck. I will add a section to the cheese docs about this.

cirs.png

liptec...@gmail.com

unread,
Jan 18, 2024, 8:01:15 PM1/18/24
to Pylinac
Hi James,

Is it possible to add a line to ignore or crop off the table?

regards,
LipTeck

LipTeck CHEW

unread,
Jan 22, 2024, 11:05:27 PM1/22/24
to Pylinac
Hi James and Ethan,

We re-scanned with a foam as base to separate the phantom from the couch and it worked!

regards,
LipTeck

CIRS062M_report.pdf

LipTeck CHEW

unread,
Jan 24, 2024, 10:17:07 PM1/24/24
to Pylinac
Hi James,

How do we include the plot of density vs HU in the report?
The title font is too big. Hope to reduce it.

Thank you.

regards,
LipTeck
Reply all
Reply to author
Forward
0 new messages