def __oddEvenNumberOfSlices(self, *args): """return a list of images that will count a odd number of slices in z direction If an even number of slices is found, the upper volume will be remove Args: *args: a list of images Returns: a list of images stripped """ output = [] for image in args: if image: try: zDims = int(mriutil.getMriDimensions(image)[2]) if zDims % 2 == 1: target = self.buildName(image, "subset") mriutil.extractSubVolume(image, target, '+2', "0:{}".format(zDims - 2), self.getNTreadsMrtrix()) output.append(target) else: output.append(image) except ValueError: output.append(image) else: output.append(False) return output
def __oddEvenNumberOfSlices(self, *args): """return a list of images that will count a odd number of slices in z direction If an even number of slices is found, the upper volume will be remove Args: *args: a list of images Returns: a list of images stripped """ output = [] for image in args: if image: try: zDims = int(mriutil.getMriDimensions(image)[2]) if zDims%2 == 1: target = self.buildName(image, "subset") mriutil.extractSubVolume(image, target, '+2',"0:{}".format(zDims-2), self.getNTreadsMrtrix()) output.append(target) else: output.append(image) except ValueError: output.append(image) else: output.append(False) return output
def __extractB0SubVolumeFromDWI(self, source): """Perform an extraction of a subset of the source image Args: source: The input DWI image Returns: The resulting file name """ self.info("Launch sub volume extraction from mrtrix") target = os.path.join(self.workingDir, os.path.basename(source).replace(self.config.get("prefix",'dwi'),self.config.get("prefix",'b0'))) extractAtAxis = self.get('extract_at_axis') if extractAtAxis not in ["1", "2", "3"]: self.error('extract_at_axis must be value of 1 or 2 or 3, found {}'.format(extractAtAxis)) #make sure that we do not extract a volumes outside of the dimension self.info(mriutil.extractSubVolume(source, target, extractAtAxis, self.get("extract_at_coordinate"), self.getNTreadsMrtrix())) self.info("End extraction from mrtrix") return target
def __extractB0SubVolumeFromDWI(self, source): """Perform an extraction of a subset of the source image Args: source: The input DWI image Returns: The resulting file name """ self.info("Launch sub volume extraction from mrtrix") target = os.path.join( self.workingDir, os.path.basename(source).replace(self.config.get("prefix", 'dwi'), self.config.get("prefix", 'b0'))) extractAtAxis = self.get('extract_at_axis') if extractAtAxis not in ["1", "2", "3"]: self.error( 'extract_at_axis must be value of 1 or 2 or 3, found {}'. format(extractAtAxis)) #make sure that we do not extract a volumes outside of the dimension self.info( mriutil.extractSubVolume(source, target, extractAtAxis, self.get("extract_at_coordinate"), self.getNTreadsMrtrix())) self.info("End extraction from mrtrix") return target
def __extractWhiteMatterFrom5tt(self, source): """Extract the white matter part from the act Args: An 5tt image Returns: the resulting file filename """ target = self.buildName(source, ["wm", "mask"]) self.info( mriutil.extractSubVolume(source, target, self.get('act_extract_at_axis'), self.get("act_extract_at_coordinate"), self.getNTreadsMrtrix())) return target
def __extractWhiteMatterFrom5tt(self, source): """Extract the white matter part from the act Args: An 5tt image Returns: the resulting file filename """ target = self.buildName(source, ["wm", "mask"]) self.info(mriutil.extractSubVolume(source, target, self.get('act_extract_at_axis'), self.get("act_extract_at_coordinate"), self.getNTreadsMrtrix())) return target
def __extractB0APSubVolumeFromDWI(self, source): self.info("Launch sub volume extraction from mrtrix") #rename the file B0 target = os.path.join( self.workingDir, os.path.basename(source).replace(self.config.get("prefix", 'dwi'), self.config.get("prefix", 'b0AP'))) extractAtAxis = self.get('b0AP_extract_at_axis') if extractAtAxis not in ["1", "2", "3"]: self.error( 'extract_at_axis must be value of 1 or 2 or 3, found {}'. format(extractAtAxis)) #make sure that we do not extract a volumes outside of the dimension self.info( mriutil.extractSubVolume(source, target, extractAtAxis, self.get("b0AP_extract_at_coordinate"), self.getNTreadsMrtrix())) self.info("End extraction from mrtrix") return target
def implement(self): dwi = self.getDenoisingImage('dwi', 'denoise') if not dwi: dwi = self.getPreparationImage('dwi') b0AP = self.getPreparationImage('b0_ap') b0PA = self.getPreparationImage('b0_pa') bEnc = self.getPreparationImage('grad', None, 'b') bVals = self.getPreparationImage('grad', None, 'bvals') bVecs = self.getPreparationImage('grad', None, 'bvecs') norm = self.getParcellationImage('norm') parcellationMask = self.getParcellationImage('mask') # Fieldmap only mag = self.getPreparationImage("mag") phase = self.getPreparationImage("phase") freesurferAnat = self.getParcellationImage('anat', 'freesurfer') self.info("extract b0 image from the dwi") b0 = os.path.join(self.workingDir, os.path.basename(dwi).replace(self.get("prefix", 'dwi'), self.get("prefix", 'b0'))) # Extract first n b0s from DWI self.info(mriutil.extractFirstB0sFromDWI(dwi, b0, bVals, self.getNTreadsMrtrix())) # Get number of b0s extracted from DWI tDims = int(mriutil.getMriDimensions(b0)[3]) self.info("look if all images have the same voxel size and dimension scale") self.__validateSizeAndDimension(dwi, b0, b0AP, b0PA) # Generate a missing b0 image if we could. --> 0 = P>>A, 1 = A>>P if self.get("phase_enc_dir") == "0" and b0AP and b0PA is False: b0PA = b0 # Extract same number of volumes b0PA try: b0APDim = int(mriutil.getMriDimensions(b0AP)[3]) target = os.path.join(self.workingDir, os.path.basename(dwi).replace(self.get("prefix", 'dwi'), self.get("prefix", 'b0_ap'))) self.info(mriutil.extractSubVolume(b0AP, target, '+3', "{}:{}".format(b0APDim-tDims, b0APDim-1 ), self.getNTreadsMrtrix())) b0AP = target except: b0APDim = 1 if self.get("phase_enc_dir") == "1" and b0PA and b0AP is False: b0AP = b0 # Extract same number of volumes b0PA try: b0PADim = int(mriutil.getMriDimensions(b0PA)[3]) target = os.path.join(self.workingDir, os.path.basename(dwi).replace(self.get("prefix", 'dwi'), self.get("prefix", 'b0_pa'))) self.info(mriutil.extractSubVolume(b0PA, target, '+3', "{}:{}".format(b0PADim-tDims, b0PADim-1), self.getNTreadsMrtrix())) b0PA = target except: b0PADim = 1 topupConfigFile = self.__checkOddEvenNumberOfSlices(dwi) self.set('method', None) if b0AP is False or b0PA is False: topupBaseName = None b0Image = b0 self.set('method', 'fieldmap') else: # Concatenate B0 image together if self.get("phase_enc_dir") == "0": concatenateB0Image = self.__concatenateB0(b0PA, b0AP, self.buildName("b0pa_b0ap", None, "nii.gz")) self.dimB0s = [mriutil.getNbDirectionsFromDWI(b0PA), mriutil.getNbDirectionsFromDWI(b0AP)] elif self.get("phase_enc_dir") == "1": concatenateB0Image = self.__concatenateB0(b0AP, b0PA, self.buildName("b0ap_b0pa", None, "nii.gz")) self.dimB0s = [mriutil.getNbDirectionsFromDWI(b0AP), mriutil.getNbDirectionsFromDWI(b0PA)] if int(mriutil.getMriDimensions(dwi)[2]) % 2 == 1: # Number of slice in z axis if 'force' not in self.get('crop'): # Use odd number [dwi, b0, b0AP, b0PA, concatenateB0Image] = self.__cropNumberOfSlices(dwi, b0, b0AP, b0PA, concatenateB0Image) # Select config File for topup topupConfigFile = self.__checkOddEvenNumberOfSlices(dwi) # Create the acquisition parameter file acqpTopup = self.__createAcquisitionParameterFile('topup') # Run topup on concatenate B0 image [topupBaseName, topupImage] = self.__topup(concatenateB0Image, acqpTopup, topupConfigFile) b0Image = self.__fslmathsTmean(os.path.join(self.workingDir, topupImage)) self.set('method', 'topup') self.info("create a suitable mask for the dwi") extraArgs = " -dof 6 " # same subject if self.get("methodology", "intrasession"): extraArgs += " -usesqform " mask, _notUsed_a, _notUsed_b = mriutil.computeDwiMaskFromFreesurfer(b0Image, norm, parcellationMask, self.buildName(parcellationMask, 'temporary'), extraArgs) # Create the acquisition parameter file for eddy acqpEddy = self.__createAcquisitionParameterFile('eddy') # Create an index file indexFile = self.__createIndexFile(mriutil.getNbDirectionsFromDWI(dwi)) outputImage = self.__correctionEddy(dwi, mask, topupBaseName, indexFile, acqpEddy, bVecs, bVals, bEnc) eddyParameterFiles = self.getImage('dwi', None, 'eddy_parameters') if eddyParameterFiles: self.info("Apply eddy movement correction to gradient encodings directions") bEnc = mriutil.applyGradientCorrection(bEnc, eddyParameterFiles, self.buildName(outputImage, None, 'b')) self.info(mriutil.mrtrixToFslEncoding(outputImage, bEnc, self.buildName(outputImage, None, 'bvecs'), self.buildName(outputImage, None, 'bvals'))) # Proceed with fieldmap if provided if mag and phase and not self.__topupCorrection: # OutputImage is now used for fieldmap correction outputImage = self.__computeFieldmap(outputImage, bVals, mag, phase, norm, parcellationMask, freesurferAnat) self.set('method', 'fieldmap') # Produce a valid b0 and mask for QA b0Corrected = self.buildName(b0, 'corrected') self.info(mriutil.extractFirstB0FromDwi(outputImage, b0Corrected, bVals)) maskCorrected = mriutil.computeDwiMaskFromFreesurfer(b0Corrected, norm, parcellationMask, self.buildName(parcellationMask, 'corrected'), extraArgs) self.rename(outputImage, self.buildName(outputImage, 'corrected'))