Summing DCM images for picketfence analysis

Hi Guys

I have 3 sets of images produced by 3 different sub fields (due to carriage movement, the EPID saves them as 3 different images in integrated mode). Is there a way to sum these imaegs in the PicketFence module like in Starshot module?

I tried to load mulitple image using the starshot module and try to set the image attrubute of PicketFence module to the one in the starshot module; but it doesn’t work.

Is there any other workaround?

In the worst case, I have to sum the arrays and write it as a new DCM file.

Thank you


Hey Jothy,
This is a great question, and it sounds like you got close. I’d like to add the “from_multiples” functionality to picketfence because I know having multiple images is fairly common.

Until then, this gist may help.

I’m not sure what your script looked like, but the idea is to use the underlying Image class, which both the starshot and picketfence modules use. The Image class has a method for loading multiple images from a list of file paths. Thus, while the workaround feels a little “hacky”, it’s not doing anything that wasn’t meant to be done.

Note however, that there are some differences by directly setting the picketfence image attribute. If you look at the source code for load_image(), it also checks for noise and inversion. The gist includes what you can add to make it completely comparable.

Let me know if this doesn’t work for you and we’ll keep looking for solutions!


Thanks James

How do I get acess to the ‘Image’ class in PicketFence

I tried

mypf = PicketFence()

and it says there is no image attribute.



pf.image is an instance of the Image class and is constructed when you load an image. For example when you do

pf = PicketFence(‘my/pf’)
pf.image # ← this exists

it constructs an Image instance from the file you passed. In your code, you’re operating on the image attribute before it’s constructed (you haven’t loaded an image yet, but are about to).

Thus, that’s why the gist uses the syntax:

pf = PicketFence()

pf.image does not exist yet because no image was actually loaded.

pf.image = Image.from_multiples([path1, …]) # make an Image explicitly and set it to the image attr.

now it exists

pf.image didn’t exist yet but is made by explicitly constructing an Image instance. Also, the from_multiples() method is a class method, meaning it can’t operate on existing instances and thus why pf.image.from_multiples() is not a valid call, even if the image attribute existed.

As a rule of thumb, from... usually denotes a class method; here’s a numpy example.

Thanks James

The images are loaded but not analysed. This is what I use

mypf.analyze(tolerance=0.15, action_tolerance=0.03,num_pickets=5)

It throws:

if max(pix_vals) > np.percentile(self.picket_array, 80):
ValueError: max() arg is an empty sequence

But the summed image looks pretty OK with pl.imshow



My guess is image inversion. Most EPID images are actually inverted from what we think; i.e. dose values lower pixel value rather than the other way around. So, as the gist suggested, try:

pf = PicketFence()
path1 = ‘blah/blah’
pf.image = Image.from_multiples([path1, …])
pf.image.check_inversion() # ← makes sure pixel values increase with dose

If this doesn’t work, I would try using the demo image, or some other image you know works, and doubling it. In other words,

pf = PicketFence()
path1 = path2 = ‘path/to/image/you/know/runs’
pf.image = Image.from_multiples([path1, path2])

If this fails it’s my problem. If this works then you should add the inversion check method and try your original images. If after all that it still fails you can send me the files and I’ll see what the problem is. I’ll also add this to the list of features in the next release, which should be soon (1-2 weeks).

Sorry it’s not as easy as it should’ve been.


That works!!

Thanks very much!