def weightedAffineInvCompWarpCost(targetIMG, templateIMG, templateWeight, curParameters, displayStuff, targetIMGMask = None): #function [ImageWarpedToTemplate, TX, TY, ErrorIMG, CostValue] = lk_weighted_run_affine_inv_comp_warpcost(targetIMG, templateIMG, TemplateW, CurParameters, displayStuff) # [ImageWarpedToTemplate, TX, TY] = lk_warp_image_affine(targetIMG, size(templateIMG), CurParameters); targetIMGToTemplate, TX, TY = warpImageAffine(targetIMG, templateIMG.shape, curParameters) if displayStuff == True: pylab.subplot(4, 3, 5); CCSegUtils.showIMG(targetIMGToTemplate); pylab.title('template coordinates warped to image'); pylab.subplot2grid((4, 3), (1, 2), rowspan = 2, colspan = 1); pylab.cla(); CCSegUtils.showIMG(targetIMG); pylab.plot(TX[:, 0], TY[:, 0], 'b-') pylab.plot(TX[0, :], TY[0, :], 'b-') pylab.plot(TX[:, -1], TY[:, -1], 'b-') pylab.plot(TX[-1, :], TY[-1, :], 'b-') pylab.title('Coordinates on target') #print "oiajfdoijadsf" errorIMG = targetIMGToTemplate - templateIMG LKCost = numpy.sum(errorIMG * templateWeight * errorIMG) # find out if any coordinates are not in the mask if targetIMGMask != None: T = CCSegUtils.interp2q(numpy.arange(1, targetIMG.shape[1] + 1), numpy.arange(1, targetIMG.shape[0] + 1), targetIMGMask, TX, TY, extrapval = 0) if numpy.any(T == 0): LKCost = numpy.inf return (targetIMGToTemplate, TX, TY, errorIMG, LKCost)
def steepestDescentImagesAffineDisplay(SDImages, IMGSize): IMG = list() for z in range(SDImages.shape[1]): IMG.append(numpy.reshape(numpy.take(SDImages, [z], axis = 1), IMGSize)) IMG = numpy.concatenate(IMG, axis = 1) CCSegUtils.showIMG(IMG);
def jacobianAffineDisplay(jacobian, IMGSize): #% Displays the jacobian as an image in the current plot using imshow #IMG = cell(2, 6); # list of two empty lists IMG = list() IMG.append([]) IMG.append([]) for z in range(len(jacobian)): #for CurParameter = 1:6 IMG[0].append(numpy.reshape(jacobian[z][0, :], IMGSize)) IMG[1].append(numpy.reshape(jacobian[z][1, :], IMGSize)) IMG = numpy.concatenate((numpy.concatenate(IMG[0], axis = 1), numpy.concatenate(IMG[1], axis = 1)), axis = 0) #IMG = cell2mat(IMG); CCSegUtils.showIMG(IMG)
def warpImageAffine(targetIMG, templateIMGSize, affineParameters): # #function [WarpedIMG, TX, TY] = lk_warp_image_affine(targetIMG, TemplateIMGSize, Parameters) # #% [WarpedImage] = lk_warp_image_affine(targetIMG, TemplateIMGSize, Parameters) #% #% DESCRIPTION #% Warps an image onto a template using the affine parameters #% Parameters = [p1, p2, p3, p4, p5, p6]; #% Assumes that the template coordinates are [1:size(TemplateIMGSize(2)), 1:size(TemplateIMGSize(1))] #% #% PARAMETERS #% targetIMG [InputM, InputN]: the input image #% TemplateIMGSize [2]: [M, N] the size of the template #% #% RETURNS #% WarpedImage [M, N]: the portion of the warped image that was in the boundary of the template #% #% In the algorithm, the template is the input and the TemplateIMGSize comes #% from the I dont know #% #% Copyright 2013, Chris Adamson, Murdoch Childrens Research Institute #% See LICENSE for full license information. #% # #if(numel(Parameters) ~= 6) # error('Parameters should have 6 elements'); #end assert(numpy.size(affineParameters) == 6),"Affine parameters should have 6 elements" #[TemplateX, TemplateY] = meshgrid(1:TemplateIMGSize(2), 1:TemplateIMGSize(1)); templateX, templateY = numpy.meshgrid(numpy.arange(1, templateIMGSize[1] + 1), numpy.arange(1, templateIMGSize[0] + 1)) #XY = cat(1, TemplateX(:)', TemplateY(:)', ones(1, prod(TemplateIMGSize))); XY = numpy.concatenate((numpy.atleast_2d(numpy.ravel(templateX)), numpy.atleast_2d(numpy.ravel(templateY)), numpy.ones([1, numpy.prod(templateIMGSize)])), axis = 0) transformMatrix = numpy.matrix([[1 + affineParameters[0], affineParameters[2], affineParameters[4]], [affineParameters[1], 1 + affineParameters[3], affineParameters[5]], [0, 0, 1]]) TXY = transformMatrix * XY #TXY = numpy.take(TXY, [0, 1], axis = 0) TX = numpy.array(numpy.reshape(numpy.take(TXY, [0], axis = 0), templateIMGSize)) TY = numpy.array(numpy.reshape(numpy.take(TXY, [1], axis = 0), templateIMGSize)) warpedIMG = CCSegUtils.interp2q(numpy.arange(1, targetIMG.shape[1] + 1), numpy.arange(1, targetIMG.shape[0] + 1), targetIMG, TX, TY, extrapval = 0) return (warpedIMG, TX, TY)
def thicknessCC(outputBase, groundTruthFile = None, numThicknessNodes = 100, doGraphics = False): assert(isinstance(numThicknessNodes, int) and numThicknessNodes > 0),"number of thickness nodes must be non-zero, positive and of type int" segMATFile = outputBase + "_seg.hdf5" segManeditMATFile = outputBase + "_seg_manedit.hdf5" assert(os.path.isfile(segMATFile)),"Seg mat file not found: " + segMATFile (outputDir, tail) = os.path.split(outputBase) subjectID = tail FID = h5py.File(segMATFile, 'r') seg = dict() seg['IMG'] = numpy.array(FID['IMG']); #seg['initialSeg'] = numpy.array(FID['initialSeg']) > 0 seg['finalSeg'] = numpy.array(FID['finalSeg']) > 0 seg['finalSegNoArtefacts'] = numpy.array(FID['finalSegNoArtefacts']) > 0 # the greater than 0 is to convert it to a boolean array seg['templatePixdims'] = numpy.array(FID['templatePixdims']) #print seg['templatePixdims'] FID.close() #print seg['IMG'].dtype #pylab.subplot(1, 4, 1); CCSegUtils.showIMG(seg['initialSeg']) #pylab.subplot(1, 4, 2); CCSegUtils.showIMG(seg['finalSeg']) #pylab.subplot(1, 4, 3); CCSegUtils.showIMG(seg['finalSegNoArtefacts']) #pylab.subplot(1, 4, 4); CCSegUtils.showIMG(seg['IMG']) #pylab.gcf().set_size_inches((20, 10), forward = True) #pylab.show() #quit() if os.path.isfile(segManeditMATFile): print "using man edit seg" FID = h5py.File(segManeditMATFile, 'r') finalSeg = numpy.array(FID['finalSegManEdit']) > 0 FID.close() else: finalSeg = numpy.array(seg['finalSeg']) if doGraphics: outputPNG = os.path.join(outputDir, 'endpoint', subjectID + "_endpoints.png") else: outputPNG = None try: finalContours = LaplaceThicknessMethod.endpointsFind(finalSeg, outputPNG = outputPNG) except Exception as e: raise(e) #return xx, yy, scaledContours, streamlines, validStreamlines, solvedImage = LaplaceThicknessMethod.laplaceEquation2DContours(finalContours['xi'], finalContours['yi'], finalContours['xo'][::-1], finalContours['yo'][::-1], seg['templatePixdims'][0], seg['templatePixdims'][1], 1.0 / numpy.min(seg['templatePixdims']), 100, redoFactorisation = True) startV = numpy.zeros((2, numThicknessNodes)) # make start points for each streamline for z in range(numThicknessNodes): D = numpy.diff(streamlines[z], axis = 1) cumArcLength = numpy.cumsum(numpy.sqrt(numpy.sum(D * D, axis = 0))) cumArcLength = cumArcLength / cumArcLength[-1] cumArcLength = numpy.concatenate((numpy.array([0]), cumArcLength)) startV[0, z] = numpy.interp(0.5, cumArcLength, streamlines[z][0]) startV[1, z] = numpy.interp(0.5, cumArcLength, streamlines[z][1]) thicknessProfile = numpy.zeros((numThicknessNodes)) for z in range(numThicknessNodes): D = numpy.diff(streamlines[z], axis = 1) thicknessProfile[z] = numpy.sum(numpy.sqrt(numpy.sum(D * D, axis = 0))) # here, we need to scale if we are using the longitudinal method FID = h5py.File(outputBase + "_midsag.hdf5", 'r') MSPMethod = FID['MSPMethod'].value if MSPMethod == 'long': flirtMAT = numpy.matrix(numpy.array(FID['flirtMAT'])) (rotmat, skew, scales, transl, angles) = FLIRT.fsl_decomp_aff(flirtMAT) scales = numpy.diag(scales) D = numpy.abs(scales[0] - scales) if numpy.any(D > 1e-5): print "Scaling constants are not equal, this should not happen, using mean anyway" globalScale = numpy.mean(scales) print "global scale: " + str(globalScale) thicknessProfile = thicknessProfile / globalScale FID.close() thicknessProfile[numpy.logical_not(validStreamlines)] = 0 registeredThicknessProfile = registerProfile(thicknessProfile) if doGraphics: PNGDirectory = os.path.join(outputDir, "thickness") try: os.makedirs(PNGDirectory) except OSError as exc: # Python >2.5 if exc.errno == errno.EEXIST and os.path.isdir(PNGDirectory): pass else: raise Exception outputPNG = os.path.join(PNGDirectory, subjectID + "_thickness.png") pylab.clf() pylab.subplot(2, 1, 1) for z in range(len(streamlines)): if validStreamlines[z] == True: lineProps = {'color': 'b', 'linewidth': 2} else: lineProps = {'color': 'm', 'linewidth': 2} CCSegUtils.plotContour(streamlines[z], closed = False, lineProps = lineProps) if numpy.mod(z, 5) == 0: #pylab.text(streamlines[z][0, 0], streamlines[z][1, 0], str(z))startV[0, z], startV[1, z] pylab.text(startV[0, z], startV[1, z], str(z), horizontalalignment='center', verticalalignment='center', backgroundcolor='w') #CCSegUtils.plotContour(streamlinesOuter[z], closed = False) #CCSegUtils.plotContour(streamlinesInner[z], closed = False) lineProps = {'color': 'g', 'linewidth': 2} pylab.plot(scaledContours['inner'][0], scaledContours['inner'][1], **lineProps) lineProps = {'color': 'r', 'linewidth': 2} pylab.plot(scaledContours['outer'][0], scaledContours['outer'][1], **lineProps) pylab.gca().invert_yaxis() pylab.gca().get_xaxis().set_ticks([]) pylab.gca().get_yaxis().set_ticks([]) pylab.title('Streamlines') pylab.subplot(2, 1, 2) thicknessProfilePlot, = pylab.plot(thicknessProfile) registeredThicknessProfilePlot, = pylab.plot(registeredThicknessProfile) pylab.legend([thicknessProfilePlot, registeredThicknessProfilePlot], ['Original thickness profile', 'Registered thickness profile'], loc = 9) pylab.title('Thickness profile') pylab.xlabel('Node') pylab.ylabel('Thickness (mm)') #pylab.subplot(1, 2, 2); CCSegUtils.showIMG(FY, extent = [xx[0], xx[-1], yy[0], yy[-1]], ticks = True); #for z in range(numpy.size(sxi)): # CCSegUtils.plotContour(streamlinesOuter[z], closed = False) # CCSegUtils.plotContour(streamlinesInner[z], closed = False) #pylab.plot(scaledxi[0], scaledyi[0]) #pylab.plot(scaledxo[0], scaledyo[0]) #print scaledxi #print scaledyi # CCSegUtils.showIMG(FX) #print outputPNG pylab.savefig(outputPNG) CCSegUtils.cropAutoWhitePNG(outputPNG) #pylab.gcf().set_size_inches((20, 10), forward = True) #pylab.show() #quit() # perform Witelson and "Hofer and Frahm" parcellations on the CCs, output parcellations of the streamlines #../witelson_hoferfrahm_parcellation_schemes.png # first, get the leftmost and rightmost pixels maskClosed = numpy.isfinite(solvedImage) I = numpy.where(maskClosed) minCol = numpy.min(I[1]) maxCol = numpy.max(I[1]) minColRow = numpy.mean(I[0][numpy.where(I[1] == minCol)]) maxColRow = numpy.mean(I[0][numpy.where(I[1] == maxCol)]) pylab.clf() minColX = xx[minCol] minColY = yy[minColRow] maxColX = xx[maxCol] maxColY = yy[maxColRow] # get the slope of the line, rise over run cropLineM = (maxColY - minColY) / (maxColX - minColX) # get the Y intercept cropLineC = minColY - (minColX * cropLineM) #print str(cropLineM) + " * X + " + str(cropLineC) X, Y = numpy.meshgrid(xx, yy) midLineCross = Y - (cropLineM * X + cropLineC) #midLineCross = numpy.sign(midLineCross) witelsonLabels = numpy.zeros(maskClosed.shape, dtype = numpy.uint8) hoferFrahmLabels = numpy.zeros(maskClosed.shape, dtype = numpy.uint8) emsellLabels = numpy.zeros(maskClosed.shape, dtype = numpy.uint8) I = numpy.where(maskClosed) midLineCrossInMask = midLineCross[I] midLineCrossInMaskIMG = numpy.array(midLineCross) midLineCrossInMaskIMG[numpy.logical_not(maskClosed)] = numpy.nan validX = X[I] validY = Y[I] # according to the witelson and HoferFrahm parcellations, the lines of division are perpendicular to the line that cuts the CC # find the scalar projection of the vector go)ing from (minColX, minColY) to (validX, validY) on (minColX, minColY) -> (maxColX, maxColY) # construct vectors A and B, the scalar projection is A . B / |B|^2 AX = validX - minColX AY = validY - minColY BX = maxColX - minColX BY = maxColY - minColY antPostProportion = (AX * BX + AY * BY) / (BX * BX + BY * BY) del AX del AY del BX del BY # because our images are posterior to anterior, we need to invert the direction, i.e.: antPostProportion = 1.0 - antPostProportion witelsonI = numpy.zeros(validX.shape, dtype = numpy.uint8) witelsonI[numpy.where(antPostProportion < (1.0 / 3.0))] = 1 witelsonI[numpy.where(numpy.logical_and(antPostProportion < (1.0 / 2.0), witelsonI == 0))] = 2 witelsonI[numpy.where(numpy.logical_and(antPostProportion < (2.0 / 3.0), witelsonI == 0))] = 3 witelsonI[numpy.where(numpy.logical_and(antPostProportion < (4.0 / 5.0), witelsonI == 0))] = 4 witelsonI[numpy.where(witelsonI == 0)] = 5 witelsonI[midLineCrossInMask > 0] = 0 #SIMG = numpy.zeros(maskClosed.shape) #SIMG[I] = witelsonI witelsonLabels[I] = witelsonI hoferFrahmI = numpy.zeros(validX.shape, dtype = numpy.uint8) hoferFrahmI[numpy.where(antPostProportion < (1.0 / 6.0))] = 1 hoferFrahmI[numpy.where(numpy.logical_and(antPostProportion < (1.0 / 2.0), hoferFrahmI == 0))] = 2 hoferFrahmI[numpy.where(numpy.logical_and(antPostProportion < (2.0 / 3.0), hoferFrahmI == 0))] = 3 hoferFrahmI[numpy.where(numpy.logical_and(antPostProportion < (3.0 / 4.0), hoferFrahmI == 0))] = 4 hoferFrahmI[numpy.where(hoferFrahmI == 0)] = 5 hoferFrahmI[midLineCrossInMask > 0] = 0 hoferFrahmLabels[I] = hoferFrahmI emsellI = numpy.zeros(validX.shape, dtype = numpy.uint8) emsellI[numpy.where(antPostProportion < (1.0 / 6.0))] = 2 emsellI[numpy.where(numpy.logical_and(antPostProportion < (1.0 / 3.0), numpy.logical_and(emsellI == 0, midLineCrossInMask <= 0)))] = 3 emsellI[numpy.where(numpy.logical_and(antPostProportion < (1.0 / 2.0), numpy.logical_and(emsellI == 0, midLineCrossInMask <= 0)))] = 4 emsellI[numpy.where(numpy.logical_and(antPostProportion < (2.0 / 3.0), numpy.logical_and(emsellI == 0, midLineCrossInMask <= 0)))] = 5 emsellI[numpy.where(numpy.logical_and(antPostProportion < (4.0 / 5.0), numpy.logical_and(emsellI == 0, midLineCrossInMask <= 0)))] = 6 emsellI[numpy.where(numpy.logical_and(emsellI == 0, midLineCrossInMask <= 0))] = 7 emsellI[numpy.where(numpy.logical_and(emsellI == 0, antPostProportion > (1.0 / 2.0)))] = 8 # we need to find the apex of the genu # it is the pixel closest to the rightmost element of the inferior boundary # firstly find out which contour is the inferior contour # it is the contour whose minimum y coordinate is greatest if numpy.min(scaledContours['inner'][1]) > numpy.min(scaledContours['outer'][1]): inferiorContourXY = numpy.array(scaledContours['inner']) else: inferiorContourXY = numpy.array(scaledContours['outer']) #print scaledContours # find the rightmost point rightMostInnerXY = numpy.take(inferiorContourXY, [numpy.argmax(inferiorContourXY[0])], axis = 1) # get the anterior-posterior proportion that is closest to this point rightMostInnerXYClosestIDX = numpy.argmin(numpy.abs(rightMostInnerXY[0] - validX) + numpy.abs(rightMostInnerXY[1] - validY)) antPostProportionClosest = antPostProportion[rightMostInnerXYClosestIDX] midLineCrossInMaskClosest = midLineCrossInMask[rightMostInnerXYClosestIDX] emsellI[numpy.where(numpy.logical_and(numpy.logical_and(antPostProportion > antPostProportionClosest, antPostProportion < (1.0 / 2.0)), midLineCrossInMask > midLineCrossInMaskClosest))] = 1 ################### THIS DOESNT ALWAYS WORK ######################## NEW METHOD ABOVE # it is the pixel with the highest S value in the right half on the 0 contour of midLineCrossInMask # if pixels on 0 contour of midLineCrossInMask # make midLineCrossInMask image #midLineCrossInMaskIMG = numpy.zeros(maskClosed.shape) #midLineCrossInMaskIMG.fill(numpy.inf) # make SIMG #IMG = numpy.zeros(maskClosed.shape) #IMG.fill(numpy.nan) #midLineCrossInMaskIMG[I] = midLineCrossInMask #IMG[I] = S # the roll shifts elements down one row, so this says pixelsAtSignChangeIMG[I, J] = midLineCrossInMaskIMG[I, J] == 1 && midLineCrossInMaskIMG[I - 1, J] == -1 #pixelsAtSignChangeIMG = numpy.logical_and(midLineCrossInMaskIMG == 1, numpy.roll(midLineCrossInMaskIMG, 1, axis = 0) < 1) #pixelsAtSignChange = pixelsAtSignChangeIMG[I] # find highest S in the right half #SAtPixelsAtSignChange = S[pixelsAtSignChange] #R = 1 #SC = 1 #pylab.subplot(SR, SC, 1) #CCSegUtils.showIMG(FY, extent = [xx[0], xx[-1], yy[0], yy[-1]], ticks = True); #CCSegUtils.showIMG(midLineCrossInMaskIMG, extent = [xx[0], xx[-1], yy[0], yy[-1]], ticks = True) #pylab.plot(inferiorContourXY[0, rightMostIDX], inferiorContourXY[1, rightMostIDX], 'r*') # pylab.colorbar() # pylab.subplot(SR, SC, 2) # CCSegUtils.showIMG(midLineCrossInMaskIMG == 1) # # pylab.subplot(SR, SC, 3) # CCSegUtils.showIMG(pixelsAtSignChangeIMG) # #pylab.gcf().set_size_inches((20, 10), forward = True) #pylab.show() #quit() # # try: # SAtApex = numpy.max(SAtPixelsAtSignChange[SAtPixelsAtSignChange < (1.0 / 2.0)]) # print "Proportion at rostrum apex: " + str(SAtApex) # emsellI[numpy.where(numpy.logical_and(numpy.logical_and(S > SAtApex, S < (1.0 / 2.0)), midLineCrossInMask > 0))] = 1 # except Exception: # print "Rostrum apex not found, region 1 will be empty" # emsellLabels[I] = emsellI # make RGB images witelsonRGB = numpy.tile(numpy.atleast_3d(numpy.double(maskClosed)), (1, 1, 3)) hoferFrahmRGB = numpy.tile(numpy.atleast_3d(numpy.double(maskClosed)), (1, 1, 3)) emsellRGB = numpy.tile(numpy.atleast_3d(numpy.double(maskClosed)), (1, 1, 3)) #witelsonIMG = numpy.zeros(maskClosed.shape, dtype = numpy.uint8) #hoferFrahmIMG = numpy.zeros(maskClosed.shape, dtype = numpy.uint8) #emsellIMG = numpy.zeros(maskClosed.shape, dtype = numpy.uint8) #witelsonIMG[I] = witelsonLabels #hoferFrahmIMG[I] = hoferFrahmLabels #emsellIMG[I] = emsellLabels CMAP = numpy.array([[1, 1, 1], [1, 0, 0], [0, 0.5, 0], [0, 0, 1], [1, 1, 0], [1, 0, 1], [0.5, 0, 0], [0, 1, 1], [1, 0, 0.5]]) #emsellLabels = numpy.mod(emsellLabels, CMAP.shape[0]) for z in range(3): T = witelsonRGB[:, :, z] T[I] = CMAP[witelsonLabels[I], z] witelsonRGB[:, :, z] = T T = hoferFrahmRGB[:, :, z] T[I] = CMAP[hoferFrahmLabels[I], z] hoferFrahmRGB[:, :, z] = T T = emsellRGB[:, :, z] T[I] = CMAP[emsellLabels[I], z] emsellRGB[:, :, z] = T del T del I del witelsonI del hoferFrahmI del emsellI #CCSegUtils.showIMG(maskClosed, extent = [xx[0], xx[-1], yy[0], yy[-1]]) #pylab.subplot(2, 1, 1) #CCSegUtils.showIMG(witelsonRGB, extent = [xx[0], xx[-1], yy[0], yy[-1]]) #pylab.title('Witelson parcellation') #pylab.subplot(2, 1, 2) #CCSegUtils.showIMG(hoferFrahmRGB, extent = [xx[0], xx[-1], yy[0], yy[-1]]) #pylab.title('Hofer and Frahm parcellation') #pylab.plot(xx, cropLineM * xx + cropLineC, 'b-') #pylab.plot(minColX, minColY, 'g*') #pylab.plot(maxColX, maxColY, 'r*') #pylab.gcf().set_size_inches((20, 10), forward = True) #pylab.show() #pylab.savefig(outputPNG) witelsonNodeLabels = CCSegUtils.interp2q(xx, yy, numpy.double(witelsonLabels), startV[0], startV[1], interpmethod = 'nearest') witelsonNodeLabels = numpy.uint8(witelsonNodeLabels) hoferFrahmNodeLabels = CCSegUtils.interp2q(xx, yy, numpy.double(hoferFrahmLabels), startV[0], startV[1], interpmethod = 'nearest') hoferFrahmNodeLabels = numpy.uint8(hoferFrahmNodeLabels) emsellNodeLabels = CCSegUtils.interp2q(xx, yy, numpy.double(emsellLabels), startV[0], startV[1], interpmethod = 'nearest') emsellNodeLabels = numpy.uint8(emsellNodeLabels) if doGraphics: pylab.clf() lineProps = {'color': 'y', 'linewidth': 2} SR = 3 SC = 1 pylab.subplot(SR, SC, 1) CCSegUtils.showIMG(witelsonRGB, extent = [xx[0], xx[-1], yy[0], yy[-1]]) for z in range(numThicknessNodes): pylab.text(startV[0, z], startV[1, z], str(witelsonNodeLabels[z]), horizontalalignment='center', verticalalignment='center') CCSegUtils.plotStreamlines(streamlines, lineProps = lineProps) pylab.title('Witelson parcellation') pylab.subplot(SR, SC, 2) CCSegUtils.showIMG(hoferFrahmRGB, extent = [xx[0], xx[-1], yy[0], yy[-1]]) for z in range(numThicknessNodes): pylab.text(startV[0, z], startV[1, z], str(hoferFrahmNodeLabels[z]), horizontalalignment='center', verticalalignment='center') CCSegUtils.plotStreamlines(streamlines, lineProps = lineProps) pylab.title('Hofer and Frahm parcellation') pylab.subplot(SR, SC, 3) CCSegUtils.showIMG(emsellRGB, extent = [xx[0], xx[-1], yy[0], yy[-1]]) for z in range(numThicknessNodes): pylab.text(startV[0, z], startV[1, z], str(emsellNodeLabels[z]), horizontalalignment='center', verticalalignment='center') CCSegUtils.plotStreamlines(streamlines, lineProps = lineProps) pylab.title('Emsell parcellation') parcellationPNGDirectory = os.path.join(outputDir, "parcellations") try: os.makedirs(parcellationPNGDirectory) except OSError as exc: # Python >2.5 if exc.errno == errno.EEXIST and os.path.isdir(parcellationPNGDirectory): pass else: raise Exception outputPNG = os.path.join(parcellationPNGDirectory, subjectID + "_parcellations.png") pylab.gcf().set_size_inches((20, 10), forward = True) #pylab.show() #quit() pylab.savefig(outputPNG) CCSegUtils.cropAutoWhitePNG(outputPNG) pixelArea = (xx[1] - xx[0]) * (yy[1] - yy[0]) # now do the stats witelsonStats = CCSegUtils.parcellationStats(witelsonLabels, pixelArea, thicknessProfile, witelsonNodeLabels) hoferFrahmStats = CCSegUtils.parcellationStats(hoferFrahmLabels, pixelArea, thicknessProfile, hoferFrahmNodeLabels) emsellStats = CCSegUtils.parcellationStats(emsellLabels, pixelArea, thicknessProfile, emsellNodeLabels) #print witelsonStats #print hoferFrahmStats #quit() outputMAT = outputBase + "_thickness.hdf5" FID = h5py.File(outputMAT, 'w') FID.create_dataset("xx", data = xx, compression = 'gzip') FID.create_dataset("yy", data = yy, compression = 'gzip') finalContoursGroup = FID.create_group("finalContours") finalContoursGroup.create_dataset("inner", data = scaledContours['inner'], compression = 'gzip') finalContoursGroup.create_dataset("outer", data = scaledContours['outer'], compression = 'gzip') #FID.create_dataset("startV", data = startV, compression = 'gzip') FID.create_dataset("validStreamlines", data = numpy.uint8(validStreamlines), compression = 'gzip') FID.create_dataset("thicknessProfile", data = thicknessProfile, compression = 'gzip') FID.create_dataset("registeredThicknessProfile", data = registeredThicknessProfile, compression = 'gzip') streamlinesGroup = FID.create_group("streamlines") for z in range(numThicknessNodes): streamlinesGroup.create_dataset(str(z), data = streamlines[z], compression = 'gzip') FID.create_dataset("solvedImage", data = solvedImage, compression = 'gzip') FID.create_dataset("witelsonLabels", data = witelsonLabels, compression = 'gzip') FID.create_dataset("witelsonNodeLabels", data = witelsonNodeLabels, compression = 'gzip') witelsonGroup = FID.create_group("witelsonStats") for curKey in witelsonStats.iterkeys(): witelsonGroup.create_dataset(curKey, data = witelsonStats[curKey], compression = 'gzip') FID.create_dataset("hoferFrahmLabels", data = hoferFrahmLabels, compression = 'gzip') FID.create_dataset("hoferFrahmNodeLabels", data = hoferFrahmNodeLabels, compression = 'gzip') hoferFrahmGroup = FID.create_group("hoferFrahmStats") for curKey in hoferFrahmStats.iterkeys(): hoferFrahmGroup.create_dataset(curKey, data = hoferFrahmStats[curKey], compression = 'gzip') FID.create_dataset("emsellLabels", data = emsellLabels, compression = 'gzip') FID.create_dataset("emsellNodeLabels", data = emsellNodeLabels, compression = 'gzip') emsellGroup = FID.create_group("emsellStats") for curKey in emsellStats.iterkeys(): emsellGroup.create_dataset(curKey, data = emsellStats[curKey], compression = 'gzip') FID.create_dataset("startV", data = startV, compression = 'gzip') #FID.create_dataset("maskClosed", data = maskClosed, compression = 'gzip') FID.close()
def selectSubjectsFromOpts(inputDirectory, opts = None): singleSubject = None subjectsIncludeFile = None subjectsExcludeFile = None subjectsIncludeListArg = None subjectsExcludeListArg = None for o, a in opts: if o == '--subjects-include': subjectsIncludeListArg = a.split(',') if o == '--subjects-exclude': subjectsExcludeListArg = a.split(',') if o == '--subjects-include-file': subjectsIncludeFile = a if o == '--subjects-exclude-file': subjectsExcludeFile = a if o == '--single-subject': singleSubject = a #print "inputDirectory" #print inputDirectory #print "subjectsIncludeFile" #print subjectsIncludeFile #print "subjectsExcludeFile" #print subjectsExcludeFile #print "subjectsIncludeListArg" #print subjectsIncludeListArg #print "subjectsExcludeListArg" #print subjectsExcludeListArg #print "singleSubject" #print singleSubject subjectsInclude = None if subjectsIncludeFile != None: print "using include file: " + subjectsIncludeFile if not os.path.isfile(subjectsIncludeFile): criticalError("The subjects include file was given, but the file was not found") fp = open(subjectsIncludeFile, 'r') subjectsInclude = fp.readlines() subjectsInclude = map(lambda s: s.strip(), subjectsInclude) fp.close() subjectsExclude = None if subjectsExcludeFile != None: print "using exclude file: " + subjectsExcludeFile if not os.path.isfile(subjectsExcludeFile): criticalError("The subjects exclude file was given, but the file was not found") fp = open(subjectsExcludeFile, 'r') subjectsExclude = fp.readlines() subjectsExclude = map(lambda s: s.strip(), subjectsExclude) fp.close() if subjectsIncludeListArg != None: if subjectsInclude != None: for curSubject in subjectsIncludeListArg: if curSubject in subjectsInclude: subjectsInclude.append(curSubject) else: subjectsInclude = subjectsIncludeListArg[:] if subjectsExcludeListArg != None: if subjectsExclude != None: for curSubject in subjectsExcludeListArg: if not curSubject in subjectsExclude: subjectsExclude.append(curSubject) else: subjectsExclude = subjectsExcludeListArg[:] #print "subjectsInclude = " #print subjectsInclude #print "subjectsExclude = " #print subjectsExclude # if we are using an include AND exclude lists, remove all elements of the include list that are in the exclude list if subjectsInclude != None and subjectsExclude != None: print "Warning, using both include and exclude lists, removing excluded subjects from include list" subjectsInclude = [x for x in subjectsInclude if not x in subjectsExclude] # get a list of nifti files in the input directory inputDirectoryFileList = os.listdir(inputDirectory) # contains a list of nifti file prefixes for all nii.gz files found in inputDirectory #inputNIFTIFiles = [x for x in sorted(inputDirectoryFileList) if x.endswith(".nii.gz")] # remove the .nii.gz #inputNIFTIFiles = map(lambda s: s[:-7], inputNIFTIFiles) inputDirectoryFileList = [os.path.join(inputDirectory, x) for x in inputDirectoryFileList] inputNIFTIFiles = CCSegUtils.imglob(inputDirectoryFileList) # remove None elements inputNIFTIFiles = [x for x in inputNIFTIFiles if x != None] #print "inputNIFTIFiles = " #print inputNIFTIFiles # strip the input directory for z in range(len(inputNIFTIFiles)): (head, tail) = os.path.split(inputNIFTIFiles[z]) inputNIFTIFiles[z] = tail del tail del head #inputNIFTIFiles = map(lambda s: s[:-7], inputNIFTIFiles) # replace with CCSegUtils.imglob if subjectsInclude != None: inputNIFTIFiles = [x for x in inputNIFTIFiles if x in subjectsInclude] if subjectsExclude != None: inputNIFTIFiles = [x for x in inputNIFTIFiles if x not in subjectsExclude] if singleSubject != None: if singleSubject in inputNIFTIFiles: actualInputFiles = [singleSubject] print "processing single subject: " + singleSubject else: criticalError("Single subject was given as: " + singleSubject + ", but the NIFTI file was not found in input directory") else: actualInputFiles = inputNIFTIFiles[:] return sorted(actualInputFiles)
def weightedAffineInvComp(targetIMG, templateIMG, templateWeight, initialParameters, numIterations, targetIMGMask = None): # Python port of lk_run_affine_for_comp #% [varargout] = lk_run_affine_for_comp(targetIMG, templateIMG, InitialParameters, NumIterations) #% #% LUCAS-KANADE algorithm Inverse Compositional method, affine #% transformation #% Registers the image to the template, using composition to update the #% parameters #% #% PARAMETERS #% targetIMG [M, N]: the input image #% templateIMG [TM, TN]: the target image #% InitialParameters [6, 1]: the initial transformation #% NumIterations [1]: the number of iterations to perform #% #% Copyright 2013, Chris Adamson, Murdoch Childrens Research Institute #% See LICENSE for full license information. #% displayStuff = False if displayStuff == True: pylab.clf() pylab.subplot(4, 3, 1); CCSegUtils.showIMG(targetIMG); pylab.title("Image"); pylab.subplot(4, 3, 2); CCSegUtils.showIMG(templateIMG); pylab.title("Template"); FY, FX = numpy.gradient(templateIMG) templateJacobian = jacobianAffine(templateIMG.shape) if displayStuff == True: pylab.subplot(4, 3, 3); CCSegUtils.showIMG(numpy.concatenate((FX, FY), axis = 1)); pylab.title('Template gradients'); pylab.subplot(4, 3, 4); jacobianAffineDisplay(templateJacobian, templateIMG.shape); pylab.title('Template Jacobian'); # % compute steepest descent images #[SDImages] = lk_sd_images_affine(FX, FY, Jacobian); SDImages = steepestDescentImagesAffine(FX, FY, templateJacobian) # TemplateWMatrix = spdiags(TemplateW(:), 0, numel(TemplateW), numel(TemplateW)); templateWeightMatrix = scipy.sparse.spdiags(numpy.ravel(templateWeight), numpy.array([0]), numpy.size(templateWeight), numpy.size(templateWeight)) # H = full(SDImages' * TemplateWMatrix * SDImages); Hessian = numpy.matrix(SDImages).T * templateWeightMatrix * numpy.matrix(SDImages) #print Hessian # SDImages = full(TemplateWMatrix * SDImages); SDImages = templateWeightMatrix * numpy.matrix(SDImages) #rint templateWeightMatrix if displayStuff == True: pylab.subplot(4, 3, 8); steepestDescentImagesAffineDisplay(SDImages, templateIMG.shape); pylab.title('Steepest descent images'); pylab.subplot(4, 3, 10); CCSegUtils.showIMG(Hessian); pylab.title('Hessian'); curParameters = initialParameters (targetIMGToTemplate, TX, TY, errorIMG, LKCost) = weightedAffineInvCompWarpCost(targetIMG, templateIMG, templateWeight, curParameters, displayStuff, targetIMGMask = targetIMGMask) if numpy.isinf(LKCost): return (curParameters, LKCost) del targetIMGToTemplate; del TX; del TY; #[~, ~, ~, ErrorIMG, CostValue] = lk_weighted_run_affine_inv_comp_warpcost(targetIMG, templateIMG, TemplateW, CurParameters, displayStuf f); # for CurIter = 1:NumIterations for curIter in range(numIterations): if(displayStuff == True): pylab.subplot(4, 3, 7); CCSegUtils.showIMG(errorIMG); pylab.title('Error Image'); SDUpdate = scipy.linalg.solve(Hessian, numpy.matrix(SDImages).T * numpy.matrix(numpy.atleast_2d(numpy.ravel(errorIMG))).T) if(displayStuff == True): pylab.subplot(4, 3, 11); pylab.cla() pylab.bar(numpy.arange(0, numpy.size(SDUpdate)), SDUpdate); pylab.title('SD Updates'); # compose the new warp # make the transformation matrix used to transform the coordinates curParametersMatrix = numpy.concatenate((numpy.reshape(curParameters, (2, 3), order='F'), numpy.matrix([0, 0, 1])), axis = 0) curParametersMatrix[0, 0] = curParametersMatrix[0, 0] + 1.0 curParametersMatrix[1, 1] = curParametersMatrix[1, 1] + 1.0 # CurParametersMatrix = [reshape(CurParameters, 2, 3); 0 0 1]; # CurParametersMatrix(1, 1) = CurParametersMatrix(1, 1) + 1; # CurParametersMatrix(2, 2) = CurParametersMatrix(2, 2) + 1; SDUpdateMatrix = numpy.concatenate((numpy.reshape(SDUpdate, (2, 3), order = 'F'), numpy.matrix([0, 0, 1])), axis = 0) SDUpdateMatrix[0, 0] = SDUpdateMatrix[0, 0] + 1.0 SDUpdateMatrix[1, 1] = SDUpdateMatrix[1, 1] + 1.0 #print curParameters #print curParametersMatrix #print "SDUpdateMatrix" #print SDUpdateMatrix # matrix division, solve composedMatrix * SDUpdateMatrix = curParametersMatrix for composedMatrix # numpy has no equivalent, so solve for # SDUpdateMatrix^T * composedMatrix^T = curParametersMatrix # then traspose the result composedMatrix = scipy.linalg.solve(SDUpdateMatrix.T, curParametersMatrix.T).T composedMatrix[0, 0] = composedMatrix[0, 0] - 1.0 composedMatrix[1, 1] = composedMatrix[1, 1] - 1.0 #print "Composed Matrix" #print composedMatrix composedMatrix = numpy.take(composedMatrix, [0, 1], axis = 0) curParameters = numpy.ravel(composedMatrix, order = 'F') #print curParameters if(displayStuff == True): pylab.subplot(4, 3, 12) pylab.cla() pylab.bar(numpy.arange(0, numpy.size(curParameters)), curParameters); pylab.title('Parameters'); F = pylab.gcf() F.set_size_inches((20, 10), forward = True) (targetIMGToTemplate, TX, TY, errorIMG, LKCost) = weightedAffineInvCompWarpCost(targetIMG, templateIMG, templateWeight, curParameters, displayStuff, targetIMGMask = targetIMGMask) if numpy.isinf(LKCost): #print "InfCost" return (curParameters, LKCost) if displayStuff == True: pylab.draw() pylab.show(block = False) #quit() #composedMatrix = curParametersMatrix # SDUpdateMatrix = [reshape(SDUpdate, 2, 3); 0 0 1]; # SDUpdateMatrix(1, 1) = SDUpdateMatrix(1, 1) + 1; # SDUpdateMatrix(2, 2) = SDUpdateMatrix(2, 2) + 1; # %SDUpdateMatrix = inv(SDUpdateMatrix); # # %ComposedMatrix = CurParametersMatrix * SDUpdateMatrix; # ComposedMatrix = CurParametersMatrix / SDUpdateMatrix; # ComposedMatrix = ComposedMatrix(1:2, :); # CurParameters = ComposedMatrix(:); # CurParameters(1) = CurParameters(1) - 1; # CurParameters(4) = CurParameters(4) - 1; # %CurParameters = CurParameters + SDUpdate; # # ParameterHistory(:, CurIter) = CurParameters; # # if(displayStuff == true) # subplot(4, 3, 12); # bar(CurParameters); title('Parameters'); # drawnow; # end # %disp([num2str(CurIter) ': ' num2str(ObjectiveFunction(CurIter))]); # %urParameters # %keyboard; # [~, ~, ~, ErrorIMG, CostValue] = lk_weighted_run_affine_inv_comp_warpcost(targetIMG, templateIMG, TemplateW, CurParameters, displayStuff); # end # #pylab.show() return (curParameters, LKCost)
def midsagExtract(inputBase, outputBase, MSPMethod, doGraphics = False): # check for the presence of FSLDIR in the enviornment variables assert('FSLDIR' in os.environ),"FSLDIR not set, FSL must be set up" NIFTIFileName = CCSegUtils.findNIFTIFromPrefix(inputBase) if NIFTIFileName == None: print("Something went wrong, the NIFTI file doesnt exist") quit() NII = nibabel.load(NIFTIFileName) #print NII #print inputBase # find out if we have a 2D or a 3D image NIISize = NII.get_shape() assert(len(NIISize) == 2 or len(NIISize) == 3),"The input NIFTI file is not 2D or 3D: " + inputBase if len(NIISize) == 2: #FID.create_dataset("NIIPixdims", data=NIIPixdims, compression = 'gzip') #FID.create_dataset("midSagAVW", data=midSagAVW, compression = 'gzip') #FID.create_dataset("MSPMethod", data=MSPMethod) #FID.create_dataset("originalOrientationString", data=origOrientationString) #FID.create_dataset("originalNativeFile", data=(outputBase + "_native.nii.gz")) #FID.create_dataset("skullCrop", data=skullCrop) #FID.create_dataset("originalNativeCroppedFile", data=(outputBase + "_native_cropped.nii.gz")) #FID.create_dataset("flirtMAT", data=flirtMAT) #FID.create_dataset("flirtTemplateFile", data=flirtTemplateFile) #FID.create_dataset("flirtCropZerosRows", data=flirtCropZerosRows) #FID.create_dataset("flirtCropZerosCols", data=flirtCropZerosCols) print "2D input not supported yet" quit() # 2D image, so it is already the midsagittal plane else: # 3D image outputMAT = outputBase + "_midsag.hdf5" (head, tail) = os.path.split(outputBase) if doGraphics: PNGDirectory = os.path.join(head, "midsag") try: os.makedirs(PNGDirectory) except OSError as exc: # Python >2.5 if exc.errno == errno.EEXIST and os.path.isdir(PNGDirectory): pass else: raise Exception outputPNG = os.path.join(PNGDirectory, tail + "_midsag.png") del head; del tail; # use FSLORIENT to get the RADIOLOGICAL/NEUROLOGICAL orientation of the image # we may not need this NIIPixdims = NII.get_header().get_zooms()[1:3] if MSPMethod == 'long': # testing (head, subjectID) = os.path.split(outputBase) stdMat = os.path.join(head, subjectID + "_to_std.mat") assert(os.path.isfile(stdMat)),"FLIRT MAT file not found, need to run CCSegLongPreprocess: " + stdMat flirtTemplateFile = CCSegUtils.MNI152FLIRTTemplate() flirtTemplateFileBrainMask = flirtTemplateFile[:-7] + "_brain_mask.nii.gz" NIITempDir = tempfile.mkdtemp() toStdNII = os.path.join(NIITempDir, subjectID + "_to_std.nii.gz") flirtInterp = 'trilinear' commandString = [os.path.join(os.environ['FSLDIR'], 'bin', 'flirt'), '-interp', flirtInterp, '-applyxfm', '-init', stdMat, '-ref', flirtTemplateFile, '-out', toStdNII, '-in', NIFTIFileName] #print " ".join(commandString) subprocess.call(commandString) flirtMAT = numpy.loadtxt(stdMat) #toStdNII = CCSegUtils.findNIFTIFromPrefix(os.path.join(head, subjectID + "_to_std")) #assert(toStdNII != None),"standard image not found, need to run CCSegLongPreprocess: " + os.path.join(head, subjectID + "_to_std") NIIBrainMask = nibabel.load(flirtTemplateFileBrainMask) NII = nibabel.load(toStdNII) NIIPixdims = NII.get_header().get_zooms()[1:3] NIISize = NII.get_shape() NIIData = numpy.rot90(NII.get_data(), 1) NIIBrainMaskData = numpy.rot90(NIIBrainMask.get_data(), 1) T = math.floor(NIIData.shape[1] / 2) # extract the midsagittal slice if (NIIData.shape[1] % 2 == 0): # even number of slices midSagAVW = (numpy.double(NIIData[:, T - 1]) + numpy.double(NIIData[:, T])) / 2.0 midSagAVWBrainMask = (numpy.double(NIIBrainMaskData[:, T - 1]) + numpy.double(NIIBrainMaskData[:, T])) / 2.0 else: # odd number of slices midSagAVW = numpy.double(NIIData[:, T]) midSagAVWBrainMask = numpy.double(NIIBrainMaskData[:, T]) midSagAVW[numpy.where(midSagAVWBrainMask < 0.5)] = numpy.nan midSagAVW = numpy.rot90(midSagAVW, 1) midSagAVW = numpy.array(midSagAVW[:, ::-1]) shutil.rmtree(NIITempDir) else: Transform = NII.get_sform(coded=True) if Transform[0] == None: print "Trying qform in " + inputBase Transform = NII.get_qform(coded=True) assert(Transform[0] != None),"No transformation information in NIFTI file" + inputBase det = numpy.linalg.det(Transform[0][0:3, 0:3]) (icode, jcode, kcode) = niftiOrientations(Transform[0]) del Transform if numpy.abs(det) < 1e-12: OrientationString = None elif det < 0.0: OrientationString = "RL PA IS" else: OrientationString = "LR PA IS" origOrientationString = list() pat = re.compile("NIFTI_([LRASIP])2([LRASIP])") mat = pat.match(icode) if mat != None: origOrientationString.append(mat.group(1) + mat.group(2)) mat = pat.match(jcode) if mat != None: origOrientationString.append(mat.group(1) + mat.group(2)) mat = pat.match(kcode) if mat != None: origOrientationString.append(mat.group(1) + mat.group(2)) origOrientationString = " ".join(origOrientationString) #print icode + " " + jcode + " " + kcode #assert(not (icode == "NIFTI_INVALID" or jcode == "NIFTI_INVALID" or kcode == "NIFTI_INVALID")),"Invalid NIFTI orientations in " + inputBase # if icode == "NIFTI_L2R" or jcode == "NIFTI_L2R" or kcode == "NIFTI_L2R": # OrientationString = "LR PA IS" # elif icode == "NIFTI_R2L" or jcode == "NIFTI_R2L" or kcode == "NIFTI_R2L": # OrientationString = "RL PA IS" # else: # OrientationString = None # del icode # del jcode # del kcode # assert(OrientationString != None),"Could not find RADIOLOGICAL/NEUROLOGICAL orientation in " + inputBase #print "OrientationString = " + OrientationString NIITempDir = tempfile.mkdtemp() #print NIITempDir NIIFileForMidSag = os.path.join(NIITempDir, 'in.nii.gz') os.system(os.environ['FSLDIR'] + '/bin/fslswapdim ' + inputBase + ' ' + OrientationString + ' ' + NIIFileForMidSag) NII = nibabel.load(NIIFileForMidSag) shutil.copyfile(NIIFileForMidSag, outputBase + "_native.nii.gz") NIIData = numpy.array(NII.get_data()) NIIData = numpy.rot90(NIIData, 1) NIIPixdims = NII.get_header().get_zooms() #print "pixdims: " + str(NIIPixdims) #print NII # perform 3-class otsu thresholding #print numpy.min(NIIData) #print numpy.max(NIIData) OtsuSeg = Otsu.robustOtsu(NIIData, [0.02, 0.98], NumberClasses = 2) L, NumLabels = scipy.ndimage.measurements.label(OtsuSeg, structure = numpy.ones([3, 3, 3])) LAreas = scipy.ndimage.measurements.labeled_comprehension(OtsuSeg, L, numpy.arange(1, NumLabels + 1), numpy.size, numpy.uint32, 0) MaxLabel = numpy.argmax(LAreas) + 1 OtsuSeg[numpy.where(L != MaxLabel)] = 0 del L; del MaxLabel; del NumLabels # cut off the neck, find the bounding box I = numpy.nonzero(OtsuSeg) minI = numpy.min(I[0]); maxI = numpy.max(I[0]); minJ = numpy.min(I[1]); maxJ = numpy.max(I[1]); minK = numpy.min(I[2]); maxK = numpy.max(I[2]); minK = numpy.int32(numpy.maximum(numpy.floor(maxK - 180 / NIIPixdims[2]), 0)) skullCrop = numpy.array([[minI, maxI], [minJ, maxJ], [minK, maxK]]) #print str(minI) + " " + str(maxI) + ", " + str(minJ) + " " + str(maxJ) + ", " + str(minK) + " " + str(maxK) NIIData = numpy.take(NIIData, numpy.arange(minI, maxI + 1), axis=0) NIIData = numpy.take(NIIData, numpy.arange(minJ, maxJ + 1), axis=1) NIIData = numpy.take(NIIData, numpy.arange(minK, maxK + 1), axis=2) if numpy.max(NIIData) > 32767: NIIData = numpy.double(NIIData) NIIData = (NIIData - numpy.min(NIIData)) / (numpy.max(NIIData) - numpy.min(NIIData)) NIIData = numpy.round(NIIData * 1000.0) NIIData = numpy.int16(NIIData) NIIData = numpy.rot90(NIIData, -1) NIISaving = nibabel.Nifti1Image(NIIData, NII.get_affine(), NII.get_header()) NIISaving.set_data_dtype(numpy.int16) NIIFileForART = os.path.join(NIITempDir, 'in_art.nii') NIIFileForARTOutput = os.path.join(NIITempDir, 'in_art_output.nii') nibabel.save(NIISaving, NIIFileForART) nibabel.save(NIISaving, outputBase + "_native_cropped.nii.gz") del NIISaving if MSPMethod == 'acpcdetect': scriptPath = os.path.realpath(__file__) (head, tail) = os.path.split(scriptPath) CommandString = 'ARTHOME=' + os.path.join(head, 'ART') + " " + os.path.join(head, 'ART', 'acpcdetect') + ' -i ' + NIIFileForART + ' -o ' + NIIFileForARTOutput print CommandString os.system(CommandString) inF = file(NIIFileForARTOutput, 'rb') s = inF.read() inF.close() outF = gzip.GzipFile(NIIFileForARTOutput + ".gz", 'wb') outF.write(s) outF.close() os.unlink(NIIFileForARTOutput) flirtTemplateFile = outputBase + "_template.nii.gz" shutil.copyfile(NIIFileForARTOutput + ".gz", flirtTemplateFile) # get the aligned image and register the original image to it to get the transformation flirtOutputFile = None elif MSPMethod == 'flirt': flirtTemplateFile = '***' flirtOutputFile = NIIFileForARTOutput flirtCost = 'mutualinfo' flirtInterp = 'trilinear' NIIFileARTOutputAffineMat = os.path.join(NIITempDir, 'in_art_output.mat') D = 15 if flirtTemplateFile == "***": realFlirtTemplateFile = CCSegUtils.MNI152FLIRTTemplate() else: realFlirtTemplateFile = flirtTemplateFile CommandString = os.environ['FSLDIR'] + '/bin/flirt -in ' + NIIFileForART + ' -ref ' + realFlirtTemplateFile + ' -dof 6 -searchrx ' + str(-D) + ' ' + str(D) + ' -searchry ' + str(-D) + ' ' + str(D) + ' -searchrz ' + str(-D) + ' ' + str(D) + ' -omat ' + NIIFileARTOutputAffineMat + ' -cost ' + flirtCost + " -interp " + flirtInterp # interpTypes = ['trilinear', 'nearestneighbour'] # costFns = ['mutualinfo','corratio','normcorr','normmi','leastsq'] # # for flirtInterp in interpTypes: # for flirtCost in costFns: # CommandString = os.environ['FSLDIR'] + '/bin/flirt -in ' + NIIFileForART + ' -ref ' + flirtTemplateFile + ' -dof 6 -searchrx ' + str(-D) + ' ' + str(D) + ' -searchry ' + str(-D) + ' ' + str(D) + ' -searchrz ' + str(-D) + ' ' + str(D) + ' -omat ' + NIIFileARTOutputAffineMat + ' -cost ' + flirtCost + ' -interp ' + flirtInterp # # start_time = time.time() # os.system(CommandString) # elapsed_time = time.time() - start_time # print "interp: " + flirtInterp + ", cost: " + flirtCost + ", time: " + str(elapsed_time) # quit() if flirtOutputFile != None: CommandString = CommandString + " -out " + NIIFileForARTOutput del D #print CommandString os.system(CommandString) shutil.copyfile(NIIFileForARTOutput + ".gz", outputBase + "_native_cropped_to_template.nii.gz") #flirtMAT = open(NIIFileARTOutputAffineMat, 'r') flirtMAT = numpy.loadtxt(NIIFileARTOutputAffineMat) shutil.copyfile(NIIFileARTOutputAffineMat, outputBase + "_native_cropped_to_template.mat") # find out whether the output file is a nifti or compressed nifti #print NIIFileForARTOutput NII = nibabel.load(NIIFileForARTOutput + ".gz") NIIData = NII.get_data() NIIData = numpy.rot90(NIIData, 1) T = math.floor(NIIData.shape[1] / 2) # extract the midsagittal slice if (NIIData.shape[1] % 2 == 0): # even number of slices midSagAVW = (numpy.double(NIIData[:, T - 1]) + numpy.double(NIIData[:, T])) / 2.0 else: # odd number of slices midSagAVW = numpy.double(NIIData[:, T]) midSagAVW = numpy.rot90(midSagAVW, 1) midSagAVW = numpy.array(midSagAVW[:, ::-1]) # crop out the zeros, sometimes FLIRT shrinks the image, causes problems downstream with the registration I = numpy.nonzero(midSagAVW) flirtCropZerosRows = numpy.arange(numpy.min(I[0]), numpy.max(I[0]) + 1) flirtCropZerosCols = numpy.arange(numpy.min(I[1]), numpy.max(I[1]) + 1) midSagAVW = numpy.take(midSagAVW, flirtCropZerosRows, axis=0) midSagAVW = numpy.take(midSagAVW, flirtCropZerosCols, axis=1) #print "flirtCropZerosRows: " + str(flirtCropZerosRows[0]) + " " + str(flirtCropZerosRows[-1]) #print "flirtCropZerosCols: " + str(flirtCropZerosCols[0]) + " " + str(flirtCropZerosCols[-1]) del I shutil.rmtree(NIITempDir) if MSPMethod != 'long': FID = h5py.File(outputMAT, 'w') FID.create_dataset("NIIPixdims", data=NIIPixdims, compression = 'gzip') FID.create_dataset("midSagAVW", data=midSagAVW, compression = 'gzip') FID.create_dataset("MSPMethod", data=MSPMethod) FID.create_dataset("originalOrientationString", data=origOrientationString) FID.create_dataset("originalNativeFile", data=(outputBase + "_native.nii.gz")) FID.create_dataset("skullCrop", data=skullCrop) FID.create_dataset("originalNativeCroppedFile", data=(outputBase + "_native_cropped.nii.gz")) FID.create_dataset("flirtMAT", data=flirtMAT) FID.create_dataset("flirtTemplateFile", data=flirtTemplateFile) FID.create_dataset("flirtCropZerosRows", data=flirtCropZerosRows) FID.create_dataset("flirtCropZerosCols", data=flirtCropZerosCols) FID.close() else: FID = h5py.File(outputMAT, 'w') FID.create_dataset("NIIPixdims", data=NIIPixdims, compression = 'gzip') FID.create_dataset("midSagAVW", data=midSagAVW, compression = 'gzip') FID.create_dataset("MSPMethod", data=MSPMethod) FID.create_dataset("flirtMAT", data=flirtMAT) FID.create_dataset("flirtTemplateFile", data=flirtTemplateFile) FID.close() #print NII.get_header().get_zooms() #print NIIPixdims #ylab.imshow(midSagAVW) #pylab.set_cmap(pylab.cm.gray) #pylab.show() #if len(NIISize) == 2: if doGraphics: T = numpy.double(midSagAVW) T = (T - numpy.min(T)) / (numpy.max(T) - numpy.min(T)) T = numpy.uint8(numpy.round(T * 255)) scipy.misc.imsave(outputPNG, T) del T
def segCCToNativeOneFile(segIMG, outputBase, midSagMATFile, segMATFile, dilateToParaSag = False, flirtInterpType = 'trilinear'): FID = h5py.File(segMATFile, 'r') resampledAVWShape = numpy.array(FID['resampledAVWShape']) LKCropRows = numpy.array(FID['LKCropRows']) LKCropCols = numpy.array(FID['LKCropCols']) midSagAVWxx = numpy.array(FID['midSagAVWxx']) midSagAVWyy = numpy.array(FID['midSagAVWyy']) resamplexx = numpy.array(FID['resamplexx']) resampleyy = numpy.array(FID['resampleyy']) #print seg['templatePixdims'] FID.close() #print seg['IMG'].dtype FID = h5py.File(midSagMATFile, 'r') MSPMethod = str(numpy.array(FID['MSPMethod'])) FID.close() midSagAVW = numpy.array(FID['midSagAVW']) skullCrop = numpy.array(FID["skullCrop"]) # the initial cropping indices of the background originalOrientationString = str(numpy.array(FID['originalOrientationString'])) originalNativeFile = str(numpy.array(FID['originalNativeFile'])) originalNativeCroppedFile = str(numpy.array(FID['originalNativeCroppedFile'])) flirtTemplateFile = str(numpy.array(FID['flirtTemplateFile'])) if flirtTemplateFile == "***": flirtTemplateFile = CCSegUtils.MNI152FLIRTTemplate() flirtMAT = numpy.array(FID["flirtMAT"]) # the transformation between originalNativeCroppedFile -> flirtTemplateFile flirtCropZerosRows = numpy.array(FID["flirtCropZerosRows"]) flirtCropZerosCols = numpy.array(FID["flirtCropZerosCols"]) #midSagAVW = midSagAVW[:, ::-1] #midSagAVW = numpy.rot90(midSagAVW, -1) FID.close() if not numpy.array_equal(flirtMAT.shape, (4, 4)): print "the flirt matrix should be a 4x4 array, it is not" return del FID #pylab.subplot(1, 4, 1); CCSegUtils.showIMG(seg['initialSeg']) #pylab.subplot(1, 4, 2); CCSegUtils.showIMG(seg['finalSeg']) #pylab.subplot(1, 4, 3); CCSegUtils.showIMG(seg['finalSegNoArtefacts']) #pylab.subplot(1, 4, 4); CCSegUtils.showIMG(seg['IMG']) finalSegResampledAVWSpace = numpy.zeros(resampledAVWShape, dtype = numpy.uint8) #finalSegResampledAVWSpace[LKOutput['cropRows'], LKOutput['cropCols']] = finalSeg finalSegResampledAVWSpace[LKCropRows[0]:(LKCropRows[1] + 1), LKCropCols[0]:(LKCropCols[1] + 1)] = segIMG midSagAVWX, midSagAVWY = numpy.meshgrid(midSagAVWxx, midSagAVWyy) finalSegMidSagAVWSpace = CCSegUtils.interp2q(resamplexx, resampleyy, numpy.double(finalSegResampledAVWSpace), midSagAVWX, midSagAVWY, interpmethod = 'nearest', extrapval = 0) flirtTemplateNII = nibabel.load(flirtTemplateFile) #print finalSegMidSagAVWSpace.shape finalSegTemplateSpace = numpy.zeros((flirtTemplateNII.shape[2], flirtTemplateNII.shape[1]), dtype = numpy.uint8) #print finalSegTemplateSpace.shape finalSegTemplateSpace[flirtCropZerosRows[0]:(flirtCropZerosRows[-1] + 1), flirtCropZerosCols[0]:(flirtCropZerosCols[-1] + 1)] = finalSegMidSagAVWSpace finalSegTemplateSpaceNIIData = numpy.zeros((flirtTemplateNII.shape[1], flirtTemplateNII.shape[0], flirtTemplateNII.shape[2]), dtype = numpy.uint8) #NIIData = flirtTemplateNII.get_data() #NIIData = numpy.rot90(NIIData, 1) #print "flirt template: " + flirtTemplateFile T = math.floor(flirtTemplateNII.shape[0] / 2) #print flirtTemplateNII #print finalSegTemplateSpaceNIIData.shape #print finalSegTemplateSpace.shape finalSegTemplateSpaceNIIData[:, T] = numpy.rot90(finalSegTemplateSpace[:, ::-1], -1) if dilateToParaSag == True: finalSegTemplateSpaceNIIData[:, T - 1] = numpy.rot90(finalSegTemplateSpace[:, ::-1], -1) finalSegTemplateSpaceNIIData[:, T + 1] = numpy.rot90(finalSegTemplateSpace[:, ::-1], -1) finalSegTemplateSpaceNIIData = numpy.uint8(numpy.rot90(finalSegTemplateSpaceNIIData, -1)) newNII = nibabel.Nifti1Image(finalSegTemplateSpaceNIIData, flirtTemplateNII.get_affine()) NIITempDir = tempfile.mkdtemp() nibabel.save(newNII, os.path.join(NIITempDir, 'test.nii.gz')) invFlirtMAT = numpy.linalg.inv(flirtMAT) numpy.savetxt(os.path.join(NIITempDir, 'test.mat'), invFlirtMAT, fmt = '%.18f') # run flirt to project the segmentation to native space CommandString = os.environ['FSLDIR'] + '/bin/flirt -in ' + os.path.join(NIITempDir, 'test') + ' -ref ' + originalNativeCroppedFile + ' -applyxfm -init ' + os.path.join(NIITempDir, 'test.mat') + ' -interp ' + flirtInterpType + ' -out ' + (outputBase + "_native_axial_cropped.nii.gz") #print CommandString os.system(CommandString) segNativeCroppedNII = nibabel.load((outputBase + "_native_axial_cropped.nii.gz")) originalNativeNII = nibabel.load(originalNativeFile) finalSegNativeNIIData = numpy.zeros(originalNativeNII.shape, dtype = segNativeCroppedNII.get_data().dtype) finalSegNativeNIIData = numpy.rot90(finalSegNativeNIIData, 1) finalSegNativeNIIData[skullCrop[0, 0]:(skullCrop[0, 1] + 1), skullCrop[1, 0]:(skullCrop[1, 1] + 1), skullCrop[2, 0]:(skullCrop[2, 1] + 1)] = numpy.rot90(segNativeCroppedNII.get_data(), 1) finalSegNativeNIIData = numpy.rot90(finalSegNativeNIIData, -1) #print skullCrop finalSegNativeSpaceNII = nibabel.Nifti1Image(finalSegNativeNIIData, originalNativeNII.get_affine()) nibabel.save(finalSegNativeSpaceNII, (outputBase + "_native_axial.nii.gz")) os.system(os.environ['FSLDIR'] + '/bin/fslswapdim ' + (outputBase + "_native_axial.nii.gz") + ' ' + originalOrientationString + ' ' + (outputBase + "_native.nii.gz")) shutil.rmtree(NIITempDir) del newNII del T
def segCCToNative(outputBase, doGraphics = False, dilateToParaSag = False): midSagMATFile = outputBase + "_midsag.hdf5" assert(os.path.isfile(midSagMATFile)),"midsag hdf5 file not found" segMATFile = outputBase + "_seg.hdf5" segManeditMATFile = outputBase + "_seg_manedit.hdf5" #finalSeg = numpy.array(seg['finalSeg']) assert(os.path.isfile(segMATFile)),"Seg mat file not found: " + segMATFile FID = h5py.File(segMATFile, 'r') autoFinalSeg = numpy.array(FID['finalSegNoArtefacts']) templatePixdims = numpy.array(FID['templatePixdims']) #print seg['templatePixdims'] FID.close() #print seg['IMG'].dtype #pylab.subplot(1, 4, 1); CCSegUtils.showIMG(seg['initialSeg']) #pylab.subplot(1, 4, 2); CCSegUtils.showIMG(seg['finalSeg']) #pylab.subplot(1, 4, 3); CCSegUtils.showIMG(seg['finalSegNoArtefacts']) #pylab.subplot(1, 4, 4); CCSegUtils.showIMG(seg['IMG']) #pylab.gcf().set_size_inches((20, 10), forward = True) #pylab.show() #quit() if os.path.isfile(segManeditMATFile): FID = h5py.File(segManeditMATFile, 'r') finalSeg = numpy.array(FID['finalSegManEdit']) > 0 FID.close() else: finalSeg = numpy.array(autoFinalSeg) segCCToNativeOneFile(numpy.uint8(finalSeg), outputBase + "_seg", midSagMATFile, segMATFile, dilateToParaSag = dilateToParaSag) #print finalSeg.shape thicknessMATFile = outputBase + "_thickness.hdf5" if os.path.isfile(thicknessMATFile): finalSegxx = numpy.arange(finalSeg.shape[1]) finalSegyy = numpy.arange(finalSeg.shape[0]) finalSegX, finalSegY = numpy.meshgrid(finalSegxx, finalSegyy) FID = h5py.File(thicknessMATFile, 'r') labelNames = ['witelson', 'hoferFrahm', 'emsell'] for curLabels in labelNames: curLabelIMG = numpy.array(FID[curLabels + 'Labels']) # for the parcellations, we need to get the parcellation images in the same space as the segmentation images # so we resample the parcellation image using the grid of the segmentation image, we need to reverse a scaling that was performed in the thickness part: curLabelIMG = CCSegUtils.interp2q(numpy.array(FID['xx']) / templatePixdims[0], numpy.array(FID['yy']) / templatePixdims[1], numpy.double(curLabelIMG), finalSegX, finalSegY, interpmethod = 'nearest', extrapval = 0) #SR = 1 #SC = 3 #pylab.subplot(SR, SC, 1); CCSegUtils.showIMG(finalSeg) #pylab.subplot(SR, SC, 2); CCSegUtils.showIMG(curLabelIMG) #pylab.subplot(SR, SC, 3); CCSegUtils.showIMG(T) #pylab.gcf().set_size_inches((20, 10), forward = True) #pylab.show() #quit() segCCToNativeOneFile(numpy.uint8(curLabelIMG), outputBase + "_parcellation_" + curLabels.lower(), midSagMATFile, segMATFile, flirtInterpType = 'nearestneighbour', dilateToParaSag = dilateToParaSag) FID.close()