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()