Dear All,
Sorry for the late reply, I can only work on this stuff between routine work and so have limited time to devote to it. I've traced the 20min wait per file to version mismatches. Once I updated numpy everything speeded up just fine.
Johnathan,
Sorry, was being inconsistent.
For anyone that might have a use for this stuff, I've pasted my script below: it works perfectly but still needs a little work (exception catching etc,) Still, I've verified that it does indeed linearise my data. Please excuse the copious commented scribbles; I'm still learning
Greg
"""
The purpose of this file is to linearise the data in a directory containing DICOM files.
It will parse the directory,each file in turn and at the end print a list of the avg for a ROI
200 x 200 pixels around the center of the image.
The inverse of the Kodak STP is then multiplied by each element in each DICOM file
and saved
"""
##############################################################
# Modules
##############################################################
import dicom # to read dicom files, also imports numpy/scipy
import glob # glob function, allows pattern matching
import csv # to write a CSV files at the end
import os
from wxPython.wx import * # GUI Support
import matplotlib.pyplot # to allow plots
from scipy.optimize import curve_fit # curve fitting routines
import numpy
import scipy
ROIsize=200 # this is the size of the ROI we want to average
Average_ROI=[0]
# the following list is the Air KERMAs measured for each file
x=[0.29, 0.44, 0.65, 1.02, 1.6, 2.68, 4.14, 6.68, 10.45, 16.98, 27.28, 34.11, 42.45]
'''
#############################################
# Standard STP equation for Kodak CR plates #
#############################################
'''
def model_func(x, a, b):
return (a *numpy.log(x)) + b
application = wxPySimpleApp() # needed when using wx module
'''
##################################
# Dialog to open DICOM Directory #
##################################
'''
print "Opening DICOM Directory" # info to stdout
dialog = wxDirDialog ( None, message = 'Pick a directory containing DICOM Files.' )
if dialog.ShowModal() == wxID_OK:
mypath = dialog.GetPath()
else:
mypath = None
print "No directory selected, bye!"
exit()
dialog.Destroy() # get rid of dialog
DicomFiles = glob.glob(mypath + "\*.dcm") # list of dicom files
print "Reading DICOM Files:"
'''
##########################################################
# Each file is read, and a ROI is measured using ROIsize #
# as a square, the average is then stored as an array #
##########################################################
'''
for file in DicomFiles:
ds = dicom.read_file(file, force=True) # read file
maxRows = ds.Rows # max rows in image
maxCols = ds.Columns # max cols in image
startRow = (maxRows/2) - (ROIsize/2) # start of ROI
endRow = (maxRows/2) + (ROIsize/2) # end of ROI
startCol = (maxCols/2) - (ROIsize/2)
endCol = (maxCols/2) + (ROIsize/2)
n=1 # count for average
sum=0 # zero sum
for rows in range(startRow,endRow,1):
for cols in range(startCol,endCol,1):
sum = sum + ds.pixel_array[rows,cols] # add all pixel values in ROI
n=n+1
Average_ROI.append(float(sum)/(n-1)) # append the average to list Average_ROI
# n-1 as we start at n=1, have to type case
# int -> float to get floating point division
print "average: %.3f" % (float(sum)/(n-1)) # info to stdout
'''
########################################
# Remove the first element as the list #
# is created with # Average_ROI[0] = 0 #
# and sort data to correspond with y #
########################################
'''
Average_ROI.remove(0) # list created with 0 as 1st element
Average_ROI.sort() # filenames are not in "dose" order-> sort
print "Saving PV against Dose data to CSV file"
'''
#################################
# save Pv vs KERMA data to file #
#################################
'''
matplotlib.pyplot.scatter(x,Average_ROI)
matplotlib.pyplot.show()
csv_out = open(os.path.join(mypath, "Dose_PV_Data.csv"), "wb")
#csv_out = open("DataFile.csv", "wb") # open file for writing
mywriter = csv.writer(csv_out) # create csv writer object
for row in zip(x, Average_ROI): # write relevant data (zip converts data to
# be saved in rows)
mywriter.writerow(row)
csv_out.close() # close file
print "Starting to fit data..."
y = Average_ROI
opt_parms, parm_cov = curve_fit(model_func, x, y, maxfev=1000)
a,b = opt_parms
print a,b
print x
print y
print model_func(x, a,b)
matplotlib.pyplot.scatter(x,y)
matplotlib.pyplot.plot(x,model_func(x,a,b))
matplotlib.pyplot.show()
'''
##########################################################
# We now need to linearise the data for each file in the #
# dicom directory mypath. A new directory must then be #
# created in the mypath directory and the linear DICOM #
# files saved here #
##########################################################
'''
print "Opening DICOM Directory to save LINEAR files" # info to stdout
dialog = wxDirDialog ( None, message = 'Pick a directory to save linear DICOM Files.' )
if dialog.ShowModal() == wxID_OK:
mysavepath = dialog.GetPath()
else:
mysavepath = "c:"
print "Data being saved in c:\tmp"
dialog.Destroy()
n=1 # this number used for the saved filename
for file in DicomFiles:
print file # info to stdout
ds = dicom.read_file(file, force=True) # read file
slope = a
alpha = 1.0/slope
fs = 4000.0/a # needs to be slope wanted/actual slope
print 'The value of a is ' + repr(a) + ', and fs is ' + repr(fs)
LPV=fs*numpy.exp(ds.pixel_array*alpha) # convert array to Linear PV
LPV_int = numpy.uint16(numpy.rint(LPV)) # round numbers and convert to
# unsigned int 16 bit
# convert to raw bytes
ds.PixelData = LPV_int.tostring() # write pixel data back to file object
save_file = mysavepath + `n` + ".dcm"
print save_file
ds.save_as(save_file)
n=n+1
p=raw_input("Press return to exit: ")
exit()