if os.path.isdir(RESULT_DIR): os.rmdir(RESULT_DIR) os.mkdir(RESULT_DIR) if os.path.isdir(ROI_DIR): os.rmdir(ROI_DIR) os.mkdir(ROI_DIR) from rfData import rfClass ##Get an ROI from the first file in the directory so I know ##its size in pixels print '\n ROI selection to determine ROI size in pixels' tmpRf = rfClass(TISSUE_A_DIR + '/' + os.listdir(TISSUE_A_DIR)[0], 'rfd') tmpRf.SetRoiFixedSize(WINDOWX, WINDOWY) region = tmpRf.data[tmpRf.roiY[0]:tmpRf.roiY[1], tmpRf.roiX[0]:tmpRf.roiX[1]] roiPoints, roiLines = region.shape psdPoints = roiPoints//2 ##Set up CZT parameters for PSD calculation### lowCut = 0.0 highCut = 15.0 freqStep = (highCut - lowCut)/psdPoints spectrumFreq = np.arange(0,psdPoints)*freqStep + lowCut fracUnitCircle = (highCut - lowCut)/(tmpRf.fs/10**6) cztW = np.exp(1j* (-2*np.pi*fracUnitCircle)/psdPoints )
RESULT_DIR = DATA_DIR + '/results' if os.path.isdir(RESULT_DIR): os.rmdir(RESULT_DIR) os.mkdir(RESULT_DIR) if os.path.isdir(ROI_DIR): os.rmdir(ROI_DIR) os.mkdir(ROI_DIR) from rfData import rfClass ##Get an ROI from the first file in the directory so I know ##its size in pixels print '\n ROI selection to determine ROI size in pixels' tmpRf = rfClass(TISSUE_A_DIR + '/' + os.listdir(TISSUE_A_DIR)[0], 'rfd') tmpRf.SetRoiFixedSize(WINDOWX, WINDOWY) region = tmpRf.data[tmpRf.roiY[0]:tmpRf.roiY[1], tmpRf.roiX[0]:tmpRf.roiX[1]] roiPoints, roiLines = region.shape psdPoints = roiPoints // 2 ##Set up CZT parameters for PSD calculation### lowCut = 0.0 highCut = 15.0 freqStep = (highCut - lowCut) / psdPoints spectrumFreq = np.arange(0, psdPoints) * freqStep + lowCut fracUnitCircle = (highCut - lowCut) / (tmpRf.fs / 10**6) cztW = np.exp(1j * (-2 * np.pi * fracUnitCircle) / psdPoints)
phased = False DATA_DIR = sys.argv[1] import os if not os.path.isdir(DATA_DIR): print '\nError ' + DATA_DIR + ' is not a valid path.' sys.exit() from rfData import rfClass ##Get an ROI from the first file in the directory so I know ##its size in pixels print '\n ROI selection to determine ROI size in pixels' tmpRf = rfClass(DATA_DIR + '/' + os.listdir(DATA_DIR)[0], 'rfd') tmpRf.SetRoiFixedSize(WINDOWX, WINDOWY) region = tmpRf.data[tmpRf.roiY[0]:tmpRf.roiY[1], tmpRf.roiX[0]:tmpRf.roiX[1]] roiPoints, roiLines = region.shape psdPoints = roiPoints // 2 ##Set up CZT parameters for PSD calculation### lowCut = 0.0 highCut = 15.0 freqStep = (highCut - lowCut) / psdPoints spectrumFreq = np.arange(0, psdPoints) * freqStep + lowCut fracUnitCircle = (highCut - lowCut) / (tmpRf.fs / 10**6)
phased = False DATA_DIR = sys.argv[1] import os if not os.path.isdir(DATA_DIR): print '\nError ' + DATA_DIR + ' is not a valid path.' sys.exit() from rfData import rfClass ##Get an ROI from the first file in the directory so I know ##its size in pixels print '\n ROI selection to determine ROI size in pixels' tmpRf = rfClass(DATA_DIR + '/' + os.listdir(DATA_DIR)[0], 'rfd') tmpRf.SetRoiFixedSize(WINDOWX, WINDOWY) region = tmpRf.data[tmpRf.roiY[0]:tmpRf.roiY[1], tmpRf.roiX[0]:tmpRf.roiX[1]] roiPoints, roiLines = region.shape psdPoints = roiPoints//2 ##Set up CZT parameters for PSD calculation### lowCut = 0.0 highCut = 15.0 freqStep = (highCut - lowCut)/psdPoints spectrumFreq = np.arange(0,psdPoints)*freqStep + lowCut fracUnitCircle = (highCut - lowCut)/(tmpRf.fs/10**6)
#!/usr/bin/python from rfData import rfClass import os,sys if len(sys.argv) < 2 or len(sys.argv) > 3: print "\nError, Usage is: " print os.path.basename(sys.argv[0]) + " rfFile <filetype> \n" sys.exit() if len(sys.argv) == 2: rf = rfClass(sys.argv[1] , 'rfd') if len(sys.argv) == 3: rf = rfClass(sys.argv[1], sys.argv[2]) rf.DisplayBmodeImage()
Usage: python singleRfdFile.py RFD_NAME ''' MAX_STRAIN = .02 import os, sys START_DIR = os.getcwd() RFD_NAME = sys.argv[1] BASE_DIR = RFD_NAME[:-4] + 'dir' from rfData import rfClass rf = rfClass(RFD_NAME, 'rfd') os.mkdir(BASE_DIR) #B-mode images os.mkdir(BASE_DIR + '/Bmode') for frame in range(rf.nFrames): rf.SaveBModeImages( BASE_DIR + '/Bmode/f' + str(frame).zfill(3) , frame) #use M-player to create a movie os.chdir(BASE_DIR + '/Bmode') os.system('mencoder "mf://*.png" -mf fps=4 -o ../bMode.avi -ovc lavc -lavcopts vcodec=msmpeg4v2:vbitrate=1600') os.chdir(START_DIR) #Create ITK strain images
reader = sitk.ImageFileReader() if bModeFile: if bModeFile == '.mhd': #read in B-mode from ITK file reader.SetFileName(bModeFile) bModeItk = reader.Execute() bMode = sitk.GetArrayFromImage(bModeItk).T bModeSpacing = bModeItk.GetSpacing() bModeOrigin = bModeItk.GetOrigin() else: #Read in RF data, let the origin be 0,0 from rfData import rfClass rf = rfClass(bModeFile, 'rfd') rf.ReadFrame(0) temp = rf.data from scipy.signal import hilbert from numpy import log10 bMode = log10(abs(hilbert(temp, axis=0))) bMode = bMode - bMode.max() bModeOrigin = [0., 0.] bModeSpacing = [rf.deltaY, rf.deltaX] bMode[bMode < -3] = -3 reader.SetFileName(strainFile) paramImItk = reader.Execute() paramImage = sitk.GetArrayFromImage(paramImItk).T
sys.exit() #Establish paths BASE_PATH, RFD_NAME = os.path.split(os.path.abspath(sys.argv[1])) print "\nProcessing file named: " + RFD_NAME + "\non path: " + BASE_PATH + "\n" RESULT_DIR = BASE_PATH +'/' + RFD_NAME[:-4] + 'Bmode' if os.path.isdir(RESULT_DIR): print "\nError, data set already processed." print "Directory: " + RESULT_DIR + " Exists. \n" sys.exit() os.makedirs(RESULT_DIR) os.makedirs(RESULT_DIR + '/images') from rfData import rfClass rf = rfClass(BASE_PATH + '/' + RFD_NAME, 'rfd') for frames in range(rf.nFrames): rf.SaveBModeImage(RESULT_DIR + '/images/frame_' + str(frames).zfill(3), image = frames) #Create movies import readrfd header = readrfd.headerInfo(BASE_PATH + '/' + RFD_NAME) fps = int( header[3] ) import os os.system('''mencoder "mf://''' + RESULT_DIR + '''/images/*.png" -mf type=png:fps=5 -ovc lavc -o '''+ RESULT_DIR + '/bMode_fps5.avi') os.system('''mencoder "mf://''' + RESULT_DIR + '''/images/*.png" -mf type=png:fps=''' + str(fps)+''' -ovc lavc -o '''+ RESULT_DIR + '/bMode_fpsActual' + str(fps) +'.avi' )
reader = sitk.ImageFileReader() if bModeFile: if bModeFile == '.mhd': #read in B-mode from ITK file reader.SetFileName(bModeFile) bModeItk = reader.Execute() bMode = sitk.GetArrayFromImage(bModeItk).T bModeSpacing = bModeItk.GetSpacing() bModeOrigin = bModeItk.GetOrigin() else: #Read in RF data, let the origin be 0,0 from rfData import rfClass rf = rfClass(bModeFile, 'rfd') rf.ReadFrame(0) temp = rf.data from scipy.signal import hilbert from numpy import log10 bMode = log10(abs(hilbert(temp, axis = 0))) bMode = bMode - bMode.max() bModeOrigin = [0., 0.] bModeSpacing = [rf.deltaY, rf.deltaX] bMode[bMode < -3] = -3 reader.SetFileName(strainFile) paramImItk = reader.Execute() paramImage = sitk.GetArrayFromImage(paramImItk).T
def __init__(self, fname, dataType, postFile=None, selectRoi=False, windowYmm=1.0, windowXmm=4.0, rangeYmm=1.0, rangeXmm=.6, overlap=.65, strainKernelmm=6.0): '''Input: fname: (string) Either a file containing a sequence of frames with motion, or a pre-compression file. dataType: (string) The filetype of the input files, see rfClass for allowed types postFile: (string) A file of post compression data, the same type and dimensions as the input file windowYmm: (float) the axial window size of the block match window in mm windowXmm: (float) The lateral window size of the block match window in mm rangeYmm: (float) The axial search range for the block match window in mm rangeXmm: (float) The lateral search range for the block match window in mm overlap: (float) [0-1]. The axial overlap between block matching windows. strainKernelmm: (float) The size of the least squares strain estimation kernel in mm. ''' super(blockMatchClass, self).__init__(fname, dataType) if postFile: self.postRf = rfClass(postFile, dataType) else: self.postRf = None self.windowYmm = windowYmm self.windowXmm = windowXmm self.rangeYmm = rangeYmm self.rangeXmm = rangeXmm #axial block size self.windowY = int(self.windowYmm / self.deltaY) if not self.windowY % 2: self.windowY += 1 self.halfY = self.windowY // 2 #lateral block size if self.imageType == 'la': self.windowX = int(self.windowXmm / self.deltaX) else: self.windowX = 21 if not self.windowX % 2: self.windowX += 1 self.halfX = self.windowX // 2 #search range if self.imageType == 'la': self.rangeX = int(self.rangeXmm / self.deltaX) else: self.rangeX = 10 self.rangeY = int(self.rangeYmm / self.deltaY) self.smallRangeY = 3 self.smallRangeX = 2 #overlap and step self.overlap = overlap self.stepY = int((1 - self.overlap) * self.windowY) ####work out tracking boundaries self.startY = 0 + self.rangeY + self.smallRangeY + self.halfY self.stopY = self.points - self.halfY - self.smallRangeY - self.rangeY #last pixel that can fit a window self.startX = 0 + self.halfX + self.rangeX + self.smallRangeX self.stopX = self.lines - self.halfX - self.smallRangeX - self.rangeX ###Allow for selection of an ROI#### if self.imageType == 'la' and selectRoi: self.SetRoiBoxSelect() if self.roiX[0] > self.startX: self.startX = self.roiX[0] if self.roiX[1] < self.stopX: self.stopX = self.roiX[1] if self.roiY[0] > self.startY: self.startY = self.roiY[0] if self.roiY[1] < self.stopY: self.stopY = self.roiY[1] ###Re-adjust roiX, roiY for display self.roiY = [self.startY, self.stopY] self.roiX = [self.startX, self.stopX] if selectRoi and self.imageType == 'la': self.ShowRoiImage() ###create arrays containing window centers in rf data coordinates self.windowCenterY = range(self.startY, self.stopY, self.stepY) self.numY = len(self.windowCenterY) self.windowCenterX = range(self.startX, self.stopX) self.numX = len(self.windowCenterX) #work out strainwindow in rf pixels, divide by step to convert to displacement pixels #make odd number self.strainWindow = int(strainKernelmm / (self.deltaY * self.stepY)) if not self.strainWindow % 2: self.strainWindow += 1 self.halfLsq = self.strainWindow // 2 self.strainwindowmm = self.strainWindow * self.deltaY * self.stepY if self.numY - 1 < self.strainWindow or self.numX < 1: print "ROI is too small" import sys sys.exit()
#!/usr/bin/python from rfData import rfClass import os, sys if len(sys.argv) < 2 or len(sys.argv) > 3: print "\nError, Usage is: " print os.path.basename(sys.argv[0]) + " rfFile <filetype> \n" sys.exit() if len(sys.argv) == 2: rf = rfClass(sys.argv[1], 'rfd') if len(sys.argv) == 3: rf = rfClass(sys.argv[1], sys.argv[2]) rf.DisplayBmodeImage()
def __init__(self, sampleName, refName, dataType, numRefFrames = 0, refAttenuation = .5, freqLow = 2., freqHigh = 8., attenuationKernelSizeYmm = 12, blockYmm = 8, blockXmm = 8, overlapY = .85, overlapX = .85, bscFitRadius = 1.0, centerFreqSimulation = 5.0, sigmaSimulation = 1.0 ): '''Description: This class implements the reference phantom method of Yao et al. It inherits from the RF data class defined for working with simulations and Seimens rfd files. Input: sampleName: Filename of sample RF data refName: Filename of reference RF data dataType: The file type of the sample and reference RFdata. Must be the same. numRefFrames: The number of frames to use in the reference data set to calculate the reference spectrum. A value of 0 will use all the frames in the data set. refAttenuation: Assuming a linear dependence of attenuation on frequency, the attenuation slope in dB/(cm MHz) freqLow: The low frequency for the CZT in MHz freqHigh: The high frequency for the CZT in MHz attenuationKernelSizeMM: The size of the data segment used to do the least squares fitting to find center frequency shift with depth. blockSize[Y,X]mm: overlap[Y,X]: frequencySmoothingKernel: (MHz) Throughout the code I'll call the 1-D segment where a single FFT is performed a window A block will refer to a 2-D region spanning multiple windows axially and several A-lines where a power spectrum is calculated by averaging FFTs ''' import numpy super(attenuation, self).__init__(sampleName, dataType, centerFreqSimulation, sigmaSimulation) #For data from clinical scanners the reference and sample data will be the same file #type. For simulations I will be using a different file type if dataType == 'sim': self.refRf = rfClass(refName, 'multiSim', centerFreqSimulation, sigmaSimulation) else: self.refRf = rfClass(refName, dataType) #Work out which reference frames to use. First make sure that I haven't selected too many #to use if numRefFrames >= 1 and numRefFrames < self.refRf.nFrames: self.numRefFrames = numRefFrames else: self.numRefFrames = self.refRf.nFrames #Next, instead of picking adjacent reference frames, use reference frames that are evenly spaced #throughout the data set, to get beamlines as uncorrelated as possible self.refFrameStep = self.refRf.nFrames//numRefFrames self.refFrames = numpy.arange(0,numRefFrames)*self.refFrameStep #read in frames self.refRf.ReadFrame() self.ReadFrame() #Check to see that reference data and sample data contain #the same number of points if self.points != self.refRf.points or self.lines != self.refRf.lines: print "Error. Sample and reference images must be the same size. \n\ " return #Attenuation estimation parameters self.betaRef = refAttenuation #get window sizes and overlap self.blockYmm = blockYmm self.blockXmm = blockXmm self.overlapY = overlapY self.overlapX = overlapX self.blockX =int( self.blockXmm/self.deltaX) self.blockY =int( self.blockYmm/self.deltaY) #make the block sizes in pixels odd numbers for the sake of calculating their centers if not self.blockY%2: self.blockY +=1 if not self.blockX%2: self.blockX +=1 self.halfY = self.blockY//2 self.halfX = self.blockX//2 #overlap the blocks axially by self.overlapY% stepY = int( (1-self.overlapY)*self.blockY ) startY = self.halfY stopY = self.points - self.halfY - 1 self.blockCenterY = range(startY, stopY, stepY) #Set the attenuation kernel size in mm #Work it out in points #Make kernel size an odd number of poitns #Work out kernel size in mm self.attenuationKernelSizeYmm = attenuationKernelSizeYmm #attenuation estimation size used in least squares fit self.lsqFitPoints = int(self.attenuationKernelSizeYmm/(stepY*self.deltaY) ) #make this number odd if not self.lsqFitPoints%2: self.lsqFitPoints += 1 self.halfLsq = self.lsqFitPoints//2 self.attenuationKernelSizeYmm = self.lsqFitPoints*stepY*self.deltaY #cutoff some more points because of least squares fitting, cross correlation self.attenCenterY= self.blockCenterY[self.halfLsq + 1:-(self.halfLsq + 1)] stepX = int( (1-self.overlapX)*self.blockX ) if stepX < 1: stepX = 1 startX =self.halfX stopX = self.lines - self.halfX self.blockCenterX = range(startX, stopX, stepX) ##Within each block a Welch-Bartlett style spectrum will be estimated ##Figure out the number of points used in an individual FFT based on ##a 50% overlap and rounding the block size to be divisible by 4 self.blockY -= self.blockY%4 self.bartlettY = self.blockY//2 self.spectrumFreqStep = (freqHigh - freqLow)/self.bartlettY self.radiusInPoints = int( bscFitRadius/self.spectrumFreqStep) self.spectrumFreq = numpy.arange(0, self.bartlettY)*self.spectrumFreqStep + freqLow #set-up parameters for the chirpZ transform fracUnitCircle = (freqHigh - freqLow)/(self.fs/10**6) self.cztW = numpy.exp(1j* (-2*numpy.pi*fracUnitCircle)/self.bartlettY ) self.cztA = numpy.exp(1j* (2*numpy.pi*freqLow/(self.fs/10**6) ) )
def __init__(self, fname, dataType, postFile = None, selectRoi = False,windowYmm = 1.0, windowXmm = 4.0, rangeYmm = 1.0, rangeXmm = .6, overlap = .65, strainKernelmm = 6.0): '''Input: fname: (string) Either a file containing a sequence of frames with motion, or a pre-compression file. dataType: (string) The filetype of the input files, see rfClass for allowed types postFile: (string) A file of post compression data, the same type and dimensions as the input file windowYmm: (float) the axial window size of the block match window in mm windowXmm: (float) The lateral window size of the block match window in mm rangeYmm: (float) The axial search range for the block match window in mm rangeXmm: (float) The lateral search range for the block match window in mm overlap: (float) [0-1]. The axial overlap between block matching windows. strainKernelmm: (float) The size of the least squares strain estimation kernel in mm. ''' super(blockMatchClass, self).__init__(fname, dataType) if postFile: self.postRf = rfClass(postFile, dataType) else: self.postRf = None self.windowYmm = windowYmm self.windowXmm = windowXmm self.rangeYmm = rangeYmm self.rangeXmm = rangeXmm #axial block size self.windowY = int(self.windowYmm/self.deltaY) if not self.windowY%2: self.windowY += 1 self.halfY = self.windowY//2 #lateral block size if self.imageType == 'la': self.windowX = int(self.windowXmm/self.deltaX) else: self.windowX = 21 if not self.windowX%2: self.windowX +=1 self.halfX = self.windowX//2 #search range if self.imageType == 'la': self.rangeX = int(self.rangeXmm/self.deltaX) else: self.rangeX = 10 self.rangeY = int(self.rangeYmm/self.deltaY) self.smallRangeY = 3 self.smallRangeX = 2 #overlap and step self.overlap = overlap self.stepY =int( (1 - self.overlap)*self.windowY ) ####work out tracking boundaries self.startY = 0 + self.rangeY + self.smallRangeY + self.halfY self.stopY = self.points - self.halfY - self.smallRangeY - self.rangeY #last pixel that can fit a window self.startX = 0 + self.halfX + self.rangeX + self.smallRangeX self.stopX = self.lines - self.halfX - self.smallRangeX - self.rangeX ###Allow for selection of an ROI#### if self.imageType == 'la' and selectRoi: self.SetRoiBoxSelect() if self.roiX[0] > self.startX: self.startX = self.roiX[0] if self.roiX[1] < self.stopX: self.stopX = self.roiX[1] if self.roiY[0] > self.startY: self.startY = self.roiY[0] if self.roiY[1] < self.stopY: self.stopY = self.roiY[1] ###Re-adjust roiX, roiY for display self.roiY = [self.startY, self.stopY] self.roiX = [self.startX, self.stopX] if selectRoi and self.imageType == 'la': self.ShowRoiImage() ###create arrays containing window centers in rf data coordinates self.windowCenterY = range(self.startY,self.stopY, self.stepY) self.numY = len(self.windowCenterY) self.windowCenterX = range(self.startX,self.stopX) self.numX = len(self.windowCenterX) #work out strainwindow in rf pixels, divide by step to convert to displacement pixels #make odd number self.strainWindow = int(strainKernelmm/(self.deltaY*self.stepY) ) if not self.strainWindow%2: self.strainWindow += 1 self.halfLsq = self.strainWindow//2 self.strainwindowmm = self.strainWindow*self.deltaY*self.stepY if self.numY - 1 < self.strainWindow or self.numX < 1: print "ROI is too small" import sys sys.exit()
phased = False DATA_DIR = sys.argv[1] REFPHANFILE = sys.argv[2] import os if not os.path.isdir(DATA_DIR): print '\nError ' + DATA_DIR + ' is not a valid path.' sys.exit() from rfData import rfClass ##Get an ROI from the first file in the directory so I know ##its size in pixels tmpRf = rfClass(DATA_DIR + '/' + os.listdir(DATA_DIR)[0], 'rfd') counter = 0 allFiles = os.listdir(DATA_DIR ) allFiles = [f for f in allFiles if 'rfd' in f] refPhanRf = rfClass(REFPHANFILE, 'rfd') for fName in allFiles: tmpRf = rfClass(DATA_DIR + '/' + fName, 'rfd') if not phased: tmpRf.SetRoiFixedSize(WINDOWX, WINDOWY) else: tmpRf.SetRoiFixedSize(WINDOWX_PA, WINDOWY) refPhanRf.SetRoiFixedSize(WINDOWX_PA, WINDOWY)