Picket Fence using CR Karestream

136 views
Skip to first unread message

Pedro Argolo Piedade

unread,
Mar 26, 2020, 11:15:31 AM3/26/20
to Pylinac
James it si possible uses CR Karestream to do this test ? I do not have EPID.
Thanks

James Kerns

unread,
Apr 3, 2020, 6:09:23 PM4/3/20
to Pylinac
If your CR outputs DICOM then it should be possible although I have not tried. CR is not a use case in Pylinac.

Pedro Argolo Piedade

unread,
Mar 15, 2023, 4:37:31 PM3/15/23
to Pylinac
Hi James, how are you?
I create a code to convert CR into EPID image. 
I run the pylinac picket fence. But I think still getting the colimated part and not the irradiated gap.
Attached the files. I think we need to chage the way we irradiate de CR. It has a sensitivity very different from the EPID.
My best regards
Pedro P
rtplan.ipynb

James Kerns

unread,
Mar 20, 2023, 5:04:43 PM3/20/23
to Pylinac
Hello Pedro, 
      Thanks for sharing. It looks like your picket detection is inverted? The tongue and groove lines appear on the darker areas of the image, meaning the brighter areas are the pickets, no?
Screenshot 2023-03-20 160339.png

James Kerns

unread,
May 15, 2023, 3:20:10 PM5/15/23
to Pedro Argolo Piedade, Pylinac
Analyzing both of your images with a default analysis gives me the correct pickets as far as I can tell. What version of pylinac are you using? Also, you should consider spacing out the "pickets" further apart. See point 2:  Picket Fence — pylinac 3.10.0 documentation

Figure_1.png

On Mon, May 15, 2023 at 11:28 AM Pedro Argolo Piedade <pedroar...@gmail.com> wrote:
Hi James, I have made a new test, but I believe is a Garden Fence, a static shoots.
image.png
As a CR image we have (0028, 0004) Photometric Interpretation = 'MONOCHROME2'
image.png
I have inverted the pixel but still getting in the wrong area 
image.png

I have attached the dicom files for you.

Can you give me some ideas?

My best regards and sorry for the delay on answering

Pedro P


--
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/-LiX5Gj7JXM/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/37f89e57-fb97-416f-808e-4b1cc82824adn%40googlegroups.com.


--
Pedro Argôlo Piedade
Físico Médico - Radioterapia São Sebastião
www.radioterapiass.com.br
+55-048-91672105
pedroar...@gmail.com
skype: pedroargolopie
whatsapp: +554891672105

Pedro Argolo Piedade

unread,
May 15, 2023, 4:36:55 PM5/15/23
to James Kerns, Pylinac
Thanks for your feedback. 
I am using Pylinac 3.4.0., python 3.9.7 and notebooks [GCC 9.4.0] 6.4.4


Pedro Argolo Piedade

unread,
Dec 4, 2023, 11:11:07 AM12/4/23
to James Kerns, Pylinac
Hi James how are you?
I finished the code for converting CR to EPID images.

I have a upload file issue when performing the picketed fence test. Is there a limitation on the file size to upload? I struggle to debug with Django framework. I do not find the error on the Logs files debug.log.

Do you have any insights?

My best regards

Pedro P



Em seg., 15 de mai. de 2023 16:20, James Kerns <jker...@gmail.com> escreveu:

James Kerns

unread,
Dec 4, 2023, 5:48:38 PM12/4/23
to Pylinac
Django? Pylinac does not use Django. It looked like you were using Google colab previously. Are you using QATrack+? If so, this is a question to ask on the correct forum:  QATrack+ - Google Groups. There is a file upload setting you might be running into here, but this has to do w/ streaming vs writing to disk which may or may not be related to your issue: https://docs.djangoproject.com/en/4.2/ref/settings/#std-setting-FILE_UPLOAD_MAX_MEMORY_SIZE

Pedro Argolo Piedade

unread,
Dec 5, 2023, 10:03:40 AM12/5/23
to James Kerns, Pylinac, Thiago Fontana, Felipe Eisenhut
Sorry James, I am using QaTrack+ to analyze the garden fence (CR plates  images saturate with picket fence).
I am using  the test list:
image.png
The Macro function I use is Pylinac.
Usually the code look like this:

import io
import pylinac

# run the picket fence analysis using pylinac
# note the use of `BIN_FILE` rather than `FILE` since we are dealing with an image
pf = pylinac.PicketFence(BIN_FILE.path, filter=5)
pf.analyze(tolerance=0.5, action_tolerance=0.03, invert=False)

# our dictionary of results to return
pf_upload_analysis = {
    "percent passing": pf.percent_passing,
    "max error": pf.max_error,
    "number of pickets": pf.num_pickets,
    "orientation": pf.orientation,
}

# create a pylinac PDF and create an attachment with it
data = io.BytesIO()
pf.publish_pdf(data)
UTILS.write_file("testingpfpdf.pdf", data)

# convert the image to a png file so it can be displayed when performing the test list
UTILS.write_file("pf-image.png", pf.image)

I was going to adapt the function CRtoEpid in this code.
def CRtoEPID(fpath):
    # authors : Guillaume Lemaitre <g.lema...@gmail.com>
    # license : MIT
   
    # FIXME: add a full-sized MR image in the testing data
    filename = ('EPID_base/AS1200.dcm')
    ds = pydicom.dcmread(filename)
   
    filename2 = (fpath)
    ds2 = pydicom.dcmread(filename2)
   
    # get the pixel information into a numpy array
    data = ds.pixel_array
    data2 = ds2.pixel_array

    #(0028, 0004) Photometric Interpretation CS: 'MONOCHROME2'
    if  ds2.PhotometricInterpretation == 'MONOCHROME2':
        # Inverter os valores de pixel
        max_value = np.amax(data2)
        imagem_invertida = max_value - data2
    else:
        imagem_invertida = data2
   
    print('The image has {} x {} voxels'.format(data.shape[0],data.shape[1]))
    data_downsampling = imagem_invertida
    print('The downsampled image has {} x {} voxels'.format(data_downsampling.shape[0], data_downsampling.shape[1]))
   
    # copy the data back to the original data set
    ds.PixelData = data_downsampling.tobytes()
    # update the information regarding the shape of the data array
    ds.Rows, ds.Columns = data_downsampling.shape
   
    #Photometric Interpretation MONO1 para MONO2
    ds.PhotometricInterpretation = ds2.PhotometricInterpretation
   
    #CR (0018, 1164) Imager Pixel Spacing                DS: [0.168, 0.168]
    #EPID (3002, 0011) Image Plane Pixel Spacing           DS: [0.336, 0.336]
    ds.ImagePlanePixelSpacing = ds2.ImagerPixelSpacing
   
    #RT Image SID
    ds.RTImageSID = "1000.0"
   
    #(0028, 0002) Samples per Pixel                   US: 1
    #ds.SamplesperPixel = ds2.SamplesperPixel
    #So tem no CR (0028, 0034) Pixel Aspect Ratio                  IS: [1, 1]
    #(0028, 0100) Bits Allocated                      US: 16
    ds.BitsAllocated = ds2.BitsAllocated
    #(0028, 0101) Bits Stored                         US: 12
    ds.BitsStored =ds2.BitsStored
    #(0028, 0102) High Bit                            US: 11
    ds.HighBit =ds2.HighBit
    #(0028, 0103) Pixel Representation                US: 0
    ds.PixelRepresentation = ds2.PixelRepresentation
    #(0028, 0106) Smallest Image Pixel Value          US: 0
    # Verificar e copiar SmallestImagePixelValue, se existir
    if hasattr(ds2, 'SmallestImagePixelValue'):
        ds.SmallestImagePixelValue = ds2.SmallestImagePixelValue
    else:
        ds.SmallestImagePixelValue = 0
    #(0028, 0107) Largest Image Pixel Value           US: 4095
    if hasattr(ds2, 'LargestImagePixelValue'):
        ds.LargestImagePixelValue = ds2.LargestImagePixelValue
    else:
        ds.LargestImagePixelValue = 0

    # so tem no CR (0028, 0301) Burned In Annotation                CS: 'NO'
    #(0028, 1050) Window Center                       DS: '2048.0'
    ds.WindowCenter = ds2.WindowCenter
    #(0028, 1051) Window Width                        DS: '4096.0'
    ds.WindowWidth = ds2.WindowWidth
    #(0028, 1052) Rescale Intercept                   DS: '0.0'
    ds.RescaleIntercept = ds2.RescaleIntercept
    #(0028, 1053) Rescale Slope                       DS: '1.0'
    ds.RescaleSlope = ds2.RescaleSlope
    #(0028, 1054) Rescale Type                        LO: 'US'
    ds.RescaleType = ds2.RescaleType
    #so tem no CR (0028, 2110) Lossy Image Compression             CS: '00'
   
    #gerando novo UID
    novouid = generate_uid()
    #print(ds.SOPInstanceUID)
    ds.SOPInstanceUID = novouid

    pat_name = ds2.PatientName
    # salvando a imagem
    # Obter a data atual
    data_atual = datetime.now()
    nome_arquivo = "ImagensConvertidas/CRepid_"+ds2.StudyDate+"."+ds2.StudyTime+"."+str(data_atual)+".dcm"
    cr_MOD = nome_arquivo.replace(':', '')
    #cr_MOD = "ImagensConvertidas/CRepid_"+ds2.StudyDate+"."+ds2.StudyTime+"."+str(data_atual)+".dcm"
    ds.save_as(cr_MOD)
   
    return cr_MOD

Performing the weekly test
image.png

Performing the test:
image.png

Uploanding the converted dicom image using the Notebook to create this new Image we usually have 10 to 30MB, I have changed the CR configuration to decrease the size of the files.

image.png
Here is the error of the failed upload.
image.png

I was trying yo find here the error to debug
image.png
Last error was 29/november/2023 and is not about the upload.
image.png
 The file was upload inside QAtrack+
image.png


This is my question: where can I go to debug?

I have installed using a Hyper-V on windows server 2019, using ubuntu 18.04.6
image.png
 I followed the tutorial https://docs.qatrackplus.com/en/stable/install/linux.html and installed Python 3.6.9.
image.png
I will look better in the group support.

My best regards and sorry for the long email.


Pedro P
Reply all
Reply to author
Forward
0 new messages