def gradient_affine(self): """Gradient of L2 norm for affine matrices only""" numTransforms = len(self.centers) gradA_list = [] Phi = DeformationCL(self.fixedCL) Phi.set_identity() CoordCL = [Phi.hx, Phi.hy, Phi.hz] for q in range(numTransforms): C = self.centers[q] r = self.radii[q] A = self.affines[q] T = self.translations[q] F = self.fixedCL.getROI(C, r) M = self.movingCL.getROI(C, r) XList = [] for d in range(3): XList.append(CoordCL[d].getROI(C, r)) DiffFM = F.subtract(M) GList = M.gradient() CF = numpy.array(F.shape, dtype=numpy.single) / 2.0 if self.normalizeWeights: W = self.weights[q].divide(self.sum_weights.getROI(C, r)) else: W = self._get_weights(F.shape, CF, r) #W = self.weights[q] #W = self._get_weights(F.shape, C, r) WD = W.multiply(DiffFM) gradA = numpy.zeros((3,3), dtype=numpy.single) for i in range(3): for j in range(3): GX = GList[i].multiply(XList[j]) gradA[i,j] = -2.0 * WD.multiply(GX).sum() gradA_list.append(gradA) return gradA_list
def gradient_anchor(self): """Gradient of L2 norm for anchor positions only""" numTransforms = len(self.centers) gradC_list = [] Phi = DeformationCL(self.fixedCL) Phi.set_identity() CoordCL = [Phi.hx, Phi.hy, Phi.hz] for q in range(numTransforms): C = self.centers[q] r = self.radii[q] A = self.affines[q] T = self.translations[q] F = self.fixedCL.getROI(C, r) M = self.movingCL.getROI(C, r) XList = [] for d in range(3): XList.append(CoordCL[d].getROI(C, r)) DiffFM = F.subtract(M) GList = M.gradient() CF = numpy.array(F.shape, dtype=numpy.single) / 2.0 if self.normalizeWeights: W = self.weights[q].divide(self.sum_weights.getROI(C, r)) else: W = self._get_weights(F.shape, CF, r) #W = self.weights[q] #W = self._get_weights(F.shape, C, r) WD = W.multiply(DiffFM) gradC = numpy.zeros((3,), dtype=numpy.single) dot_G_XC = F.clone() dot_G_XC.fill(0.0) ATList = [] for d in range(3): AT = F.clone() AT.fill(0.0) for j in range(3): Y = XList[d].clone() Y.scale(A[d,j]) AT.add_inplace(Y) AT.shift(T[d]) ATList.append(AT) XC = XList[d].clone() XC.shift(-C[d]) XC.scale(2.0 / r[d]**2) dot_G_XC.add_inplace(GList[d].multiply(XC)) for d in range(3): gradC[d] = -WD.multiply(ATList[d].multiply(dot_G_XC)).sum() gradC_list.append(gradC) return gradC_list
def gradient(self): """Gradient of L2 norm""" numTransforms = len(self.centers) gradA_list = [] gradT_list = [] gradC_list = [] gradR_list = [] Phi = DeformationCL(self.fixedCL) Phi.set_identity() CoordCL = [Phi.hx, Phi.hy, Phi.hz] for q in range(numTransforms): C = self.centers[q] r = self.radii[q] A = self.affines[q] T = self.translations[q] F = self.fixedCL.getROI(C, r) M = self.movingCL.getROI(C, r) XList = [] for d in range(3): XList.append(CoordCL[d].getROI(C, r)) DiffFM = F.subtract(M) GList = M.gradient() CF = numpy.array(F.shape, dtype=numpy.single) / 2.0 if self.normalizeWeights: W = self.weights[q].divide(self.sum_weights.getROI(C, r)) else: W = self._get_weights(F.shape, CF, r) #W = self.weights[q] #W = self._get_weights(F.shape, C, r) WD = W.multiply(DiffFM) gradA = numpy.zeros((3,3), dtype=numpy.single) for i in range(3): for j in range(3): GX = GList[i].multiply(XList[j]) gradA[i,j] = -2.0 * WD.multiply(GX).sum() gradT = numpy.zeros((3,), dtype=numpy.single) for d in range(3): gradT[d] = -2.0 * WD.multiply(GList[d]).sum() gradC = numpy.zeros((3,), dtype=numpy.single) gradR = numpy.zeros((3,), dtype=numpy.single) dot_AT_XC = F.clone() dot_AT_XC.fill(0.0) dot_AT_XR = F.clone() dot_AT_XR.fill(0.0) for d in range(3): AT = F.clone() AT.fill(0.0) for j in range(3): Y = XList[d].clone() Y.scale(A[d,j]) AT.add_inplace(Y) AT.shift(T[d]) XC = XList[d].clone() XC.shift(-C[d]) XC.scale(2.0 / r[d]**2) dot_AT_XC.add_inplace(AT.multiply(XC)) XR = XList[d].clone() XR.shift(-C[d]) XR.scale(4.0 / r[d]**3) dot_AT_XR.add_inplace(AT.multiply(XR)) for d in range(3): gradC[d] = -WD.multiply(GList[d].multiply(dot_AT_XC)).sum() gradR[d] = WD.multiply(GList[d].multiply(dot_AT_XR)).sum() gradA_list.append(gradA) gradT_list.append(gradT) gradC_list.append(gradC) gradR_list.append(gradR) return gradA_list, gradT_list, gradC_list, gradR_list