def isDirty(self): images = Images() dwi = self.getUpsamplingImage('dwi', 'upsample') if mriutil.getNbDirectionsFromDWI(dwi) <= 45 and not self.get( 'forceHardi'): if 'deterministic' in self.get('algorithm'): images.append(( self.getImage('dwi', 'tensor_det', 'trk'), "deterministic tensor connectome matrix from a streamlines" )) if 'probabilistic' in self.get('algorithm'): images.append(( self.getImage('dwi', 'tensor_prob', 'trk'), "probabilistic tensor connectome matrix from a streamlines" )) else: images.append( (self.getImage('dwi', 'hardi_prob', 'trk'), "tckgen hardi probabilistic streamlines tractography")) if self.get('sift'): images.append((self.getImage('dwi', 'tcksift', 'trk'), 'tcksift')) return images
def isDirty(self): images = Images() dwi = self.getUpsamplingImage('dwi', 'upsample') if mriutil.getNbDirectionsFromDWI(dwi) <= 45 and not self.get('forceHardi'): if 'deterministic' in self.get('algorithm'): images.append(( self.getImage('dwi', 'tensor_det', 'trk'), "deterministic tensor connectome matrix from a streamlines" )) if 'probabilistic' in self.get('algorithm'): images.append(( self.getImage('dwi', 'tensor_prob', 'trk'), "probabilistic tensor connectome matrix from a streamlines" )) else: images.append(( self.getImage('dwi', 'hardi_prob', 'trk'), "tckgen hardi probabilistic streamlines tractography" )) if self.get('sift'): images.append(( self.getImage('dwi', 'tcksift', 'trk'), 'tcksift')) return images
def __nii4dtoGif(self, inputfile, tgGif, gifSpeed=30): """ Create a animated gif from a 4d NIfTI Compulsory arguments : inputfile 4D NIfTI image tgGif : outputfile gif name Optional arguments : gifSpeed : delay between images (tens of ms), default=30 """ gifId = self.__idGenerator() # Number of volumes in the 4D image vSize = mriutil.getNbDirectionsFromDWI(inputfile) vols = [gifId + '{0:04}'.format(i) for i in range(vSize)] # Spliting 4D image cmd = 'fslsplit ' + inputfile + ' ' + gifId + ' -t' self.launchCommand(cmd) # Extracting pngs from all volumes for vol in vols: self.__slicer(vol, None, vol + '.png') # Creating .gif cmd = 'convert ' for vol in vols: cmd += '-delay ' + str(gifSpeed) + ' ' + vol + '.png ' cmd += tgGif self.launchCommand(cmd) # Cleaning temp files cmd = 'rm ' + gifId + '*' self.launchCommand(cmd)
def implement(self): dwi = self.getImage(self.dependDir, 'dwi') b0PA = self.getImage(self.dependDir, 'b0PA') b0AP = self.getImage(self.dependDir, 'b0AP') bFile = self.getImage(self.dependDir, 'grad', None, 'b') bVals = self.getImage(self.dependDir, 'grad', None, 'bval') bVecs = self.getImage(self.dependDir, 'grad', None, 'bvec') #make sure the 3 images have the same voxel size and dimension scale self.__validateSizeAndDimension(dwi, b0PA, b0AP) #make sure that the z dimension contain an odd number of slices dwiZDims = int(mriutil.getMriDimensions(dwi)[2]) if dwiZDims%2 == 1: dwi = self.__extractZVolumes(dwi, "0:{}".format(dwiZDims-2)) b0PA = self.__extractZVolumes(b0PA, "0:{}".format(dwiZDims-2)) b0AP = self.__extractZVolumes(b0AP, "0:{}".format(dwiZDims-2)) #concatenate B0 image together b0Image = self.__concatenateB0(b0PA, b0AP, os.path.join(self.workingDir, self.get('b0s_filename'))) #create an empty b02b0.cnf file #b02b0File = os.path.join(self.workingDir, self.get('b02b0_filename')) #open(b02b0File, 'a').close() #create the acquisition parameter file acqpTopup = self.__createAcquisitionParameterFile('topup') acqpEddy = self.__createAcquisitionParameterFile('eddy') #create an index file indexFile = self.__createIndexFile(mriutil.getNbDirectionsFromDWI(dwi)) #Lauch topup on concatenate B0 image [topupBaseName, topupImage] = self.__topup(b0Image, acqpTopup, self.get('b02b0_filename')) outputFieldMask = self.__fslmaths_tmean(os.path.join(self.workingDir, topupImage)) outputFieldMaskExtracted = self.__bet(outputFieldMask) outputEddyImage = self.__correction_eddy2(dwi, outputFieldMaskExtracted, topupBaseName, indexFile, acqpEddy, bVecs, bVals) self.info("Uncompressing eddy output image: {}".format(outputEddyImage)) util.gunzip(outputEddyImage) #@TODO remove the glob and use getimage eddyParameterFiles = glob.glob("{}/*.eddy_parameters".format(self.workingDir)) if len(eddyParameterFiles)>0: bCorrected = mriutil.applyGradientCorrection(bFile, eddyParameterFiles.pop(0), self.workingDir) #produce the bVal and bVec file accordingly mriutil.bEnc2BVec(bCorrected, self.workingDir) mriutil.bEnc2BVal(bCorrected, self.workingDir)
def __isValidStructure(self): """Determine if the directory is a valid structure Returns: a Boolean that represent if validation is required for that directory """ if not self.__validateImage(self.config.get('prefix', 'anat')): return False if not self.__validateImage(self.config.get('prefix', 'dwi')): return False dwi = util.getImage(self.config, self.workingDir, 'dwi') #@TODO fix data layout incomprehesion #make sure that diffusion image Z scale layout is oriented correctly #if not mriutil.isDataLayoutValid(dwiImage): # self.error("Data layout for {} image is unexpected. " # "Only data layout = [ +0 +1 +2 +3 ] could be process".format(dwiImage)) nbDirections = mriutil.getNbDirectionsFromDWI(dwi) if nbDirections <= 45: msg = "Found only {} directions into {} image. Hardi model will not be accurate with diffusion weighted image " \ "that contain less than 45 directions\n\n".format(nbDirections, self.dwi) if self.config.getboolean('arguments', 'prompt'): util.displayYesNoMessage(msg) else: self.warning(msg) bEnc = util.getImage(self.config, self.workingDir, 'grad', None, 'b') bVal = util.getImage(self.config, self.workingDir, 'grad', None, 'bval') bVec = util.getImage(self.config, self.workingDir, 'grad', None, 'bvec') if (not bEnc) and (not bVal or not bVec): self.logger.warning("No valid .b encoding or pair of .bval, .bvec" " file found in directory: {}".format( self.workingDir)) return False #@TODO uncomment and fix not all zero bvec value in the first line """ if bEnc and not self.__isValidEncoding(nbDirections, '.b'): self.logger.warning("Encoding file {} is invalid".format(bEnc)) return False if bVal and not self.__isValidEncoding(nbDirections, '.bval'): self.logger.warning("Encoding file {} is invalid".format(bEnc)) return False if bVec and not self.__isValidEncoding(nbDirections, '.bvec'): self.logger.warning("Encoding file {} is invalid".format(bVec)) return False """ return True
def __isValidStructure(self): """Determine if the directory is a valid structure Returns: a Boolean that represent if validation is required for that directory """ if not self.__validateImage(self.config.get('prefix','anat')): return False if not self.__validateImage(self.config.get('prefix','dwi')): return False dwi = util.getImage(self.config, self.workingDir,'dwi') #@TODO fix data layout incomprehesion #make sure that diffusion image Z scale layout is oriented correctly #if not mriutil.isDataLayoutValid(dwiImage): # self.error("Data layout for {} image is unexpected. " # "Only data layout = [ +0 +1 +2 +3 ] could be process".format(dwiImage)) nbDirections = mriutil.getNbDirectionsFromDWI(dwi) if nbDirections <= 45: msg = "Found only {} directions into {} image. Hardi model will not be accurate with diffusion weighted image " \ "that contain less than 45 directions\n\n".format(nbDirections, self.dwi) if self.config.getboolean('arguments', 'prompt'): util.displayYesNoMessage(msg) else: self.warning(msg) bEnc = util.getImage(self.config, self.workingDir,'grad', None, 'b') bVal = util.getImage(self.config, self.workingDir,'grad', None, 'bval') bVec = util.getImage(self.config, self.workingDir,'grad', None, 'bvec') if (not bEnc) and (not bVal or not bVec): self.logger.warning("No valid .b encoding or pair of .bval, .bvec" " file found in directory: {}".format(self.workingDir)) return False #@TODO uncomment and fix not all zero bvec value in the first line """ if bEnc and not self.__isValidEncoding(nbDirections, '.b'): self.logger.warning("Encoding file {} is invalid".format(bEnc)) return False if bVal and not self.__isValidEncoding(nbDirections, '.bval'): self.logger.warning("Encoding file {} is invalid".format(bEnc)) return False if bVec and not self.__isValidEncoding(nbDirections, '.bvec'): self.logger.warning("Encoding file {} is invalid".format(bVec)) return False """ return True
def implement(self): shutil.copy(self.queries, self.workingDir) shutil.copy(self.tq_dict, self.workingDir) dwi = self.getUpsamplingImage('dwi', 'upsample') nbDirections = mriutil.getNbDirectionsFromDWI(dwi) # Get number of directions self.tractographyTrk = self.__getTractography(nbDirections) # Load tractography atlasResample = self.__getAtlas() # Get atlas to refere to self.__tractQuerier( self.tractographyTrk, atlasResample, self.workingDir, self.queries)
def implement(self): shutil.copy(self.queriesFile, self.workingDir) shutil.copy(self.tq_dictFile, self.workingDir) dwi = self.getUpsamplingImage('dwi', 'upsample') nbDirections = mriutil.getNbDirectionsFromDWI( dwi) # Get number of directions self.tractographyTrk = self.__getTractography( nbDirections) # Load tractography atlasResample = self.__getAtlas() # Get atlas to refere to self.__tractQuerier(self.tractographyTrk, atlasResample, self.workingDir, self.queriesFile)
def implement(self): tt5 = self.getRegistrationImage("tt5", "register") seed_gmwmi = self.getMaskingImage("tt5", ["register", "5tt2gmwmi"]) norm = self.getRegistrationImage("norm", "resample") mask253 = self.getMaskingImage('aparc_aseg', ['253', 'mask']) mask1024= self.getMaskingImage('aparc_aseg', ['1024', 'mask']) dwi = self.getUpsamplingImage('dwi', 'upsample') bFile = self.getUpsamplingImage('grad', None, 'b') mask = self.getRegistrationImage('mask', 'resample') self.__nbDirections = mriutil.getNbDirectionsFromDWI(dwi) if self.__nbDirections <= 45: if 'deterministic' in self.get('algorithm'): tckDet = self.__tckgenTensor(dwi, self.buildName(dwi, 'tensor_det', 'tck'), mask, tt5, seed_gmwmi, bFile, 'Tensor_Det') tckDetRoi = self.__tckedit(tckDet, mask253, self.buildName(tckDet, 'roi','tck')) tckDetRoiTrk = mriutil.tck2trk(tckDetRoi, norm, self.buildName(tckDetRoi, None, 'trk')) tckDetTrk = mriutil.tck2trk(tckDet, norm, self.buildName(tckDet, None, 'trk')) self.__tckDetRoiTrk = tckDetRoiTrk if 'probabilistic' in self.get('algorithm'): tckProb = self.__tckgenTensor(dwi, self.buildName(dwi, 'tensor_prob', 'tck'), mask, tt5, seed_gmwmi, bFile, 'Tensor_Prob') tckProbRoi = self.__tckedit(tckProb, mask253, self.buildName(tckProb, 'roi','tck')) tckProbRoiTrk = mriutil.tck2trk(tckProbRoi, norm , self.buildName(tckProbRoi, None, 'trk')) tckProbTrk = mriutil.tck2trk(tckProb, norm , self.buildName(tckProb, None, 'trk')) self.__tckProbRoiTrk = tckProbRoiTrk else: if 'hardi' in self.get('algorithm'): csd = self.getHardimrtrixImage('dwi','csd') hardiTck = self.__tckgenHardi(csd, self.buildName(csd, 'hardi_prob', 'tck'), tt5) hardiTckRoi = self.__tckedit(hardiTck, mask253, self.buildName(hardiTck, 'roi','tck')) tckgenRoiTrk = mriutil.tck2trk(hardiTckRoi, norm , self.buildName(hardiTckRoi, None, 'trk')) hardiTrk = mriutil.tck2trk(hardiTck, norm, self.buildName(hardiTck, 'None', 'trk')) self.__tckgenRoiTrk = tckgenRoiTrk if 'sift' in self.get('algorithm'): tcksift = self.__tcksift(hardiTck, csd) tcksiftRoi = self.__tckedit(tcksift, mask253, self.buildName(tcksift, 'roi', 'tck')) tcksiftRoiTrk = mriutil.tck2trk(tcksiftRoi, norm , self.buildName(tcksiftRoi, None, 'trk')) tcksiftTrk = mriutil.tck2trk(tcksift, norm, self.buildName(tcksift, 'None', 'trk')) self.__tcksiftRoiTrk = tcksiftRoiTrk
def meetRequirement(self): """Validate if all requirements have been met prior to launch the task Returns: True if all requirement are meet, False otherwise """ images = Images() dwi = self.getUpsamplingImage('dwi', 'upsample') nbDirections = mriutil.getNbDirectionsFromDWI(dwi) # Get number of directions if nbDirections <= 45 and not self.get('tractographymrtrix', 'forceHardi'): postfixTractography = 'tensor_prob' else: postfixTractography = 'hardi_prob' Images((self.getTractographymrtrixImage('dwi', postfixTractography, 'trk'),'Tractography file'), (self.__getAtlas(),'Atlas')) # Check if tractographies are available return images
def meetRequirement(self): """Validate if all requirements have been met prior to launch the task Returns: True if all requirement are meet, False otherwise """ images = Images() dwi = self.getUpsamplingImage('dwi', 'upsample') nbDirections = mriutil.getNbDirectionsFromDWI( dwi) # Get number of directions if nbDirections <= 45 and not self.get('tractographymrtrix', 'forceHardi'): postfixTractography = 'tensor_prob' else: postfixTractography = 'hardi_prob' Images((self.getTractographymrtrixImage('dwi', postfixTractography, 'trk'), 'Tractography file'), (self.__getAtlas(), 'Atlas')) # Check if tractographies are available return images
def implement(self): tt5 = self.getRegistrationImage("tt5", "register") seed_gmwmi = self.getMaskingImage("tt5", ["register", "5tt2gmwmi"]) norm = self.getRegistrationImage("norm", "resample") mask253 = self.getMaskingImage('aparc_aseg', ['253', 'mask']) # mask1024= self.getMaskingImage('aparc_aseg', ['1024', 'mask']) dwi = self.getUpsamplingImage('dwi', 'upsample') bFile = self.getUpsamplingImage('grad', None, 'b') mask = self.getRegistrationImage('mask', 'resample') # If step is None set Step = voxelSize/2 if self.get('step') == 'None': voxelSize = [float(x) for x in self.get('methodology', 't1_voxelsize')[1:-1].split(',')] self.set('step', str(float(voxelSize[0]) * 0.5)) self.set('angle', str(90 * float(self.get('step')) / float(voxelSize[0]))) self.__nbDirections = mriutil.getNbDirectionsFromDWI(dwi) if self.__nbDirections <= 45 and not self.get('forceHardi'): self.set('methodReconstruction', 'tenseur') if 'deterministic' in self.get('algorithm'): tckDet = self.__tckgenTensor( dwi, self.buildName(dwi, 'tensor_det', 'tck'), mask, tt5, seed_gmwmi, bFile, 'Tensor_Det') tckDetTrk = mriutil.tck2trk( tckDet, norm, self.buildName(tckDet, None, 'trk')) tckDetRoi = self.__tckedit( tckDet, mask253, self.buildName(tckDet, 'roi', 'tck')) tckDetRoiTrk = mriutil.tck2trk( tckDetRoi, norm, self.buildName(tckDetRoi, None, 'trk')) self.__tckDetRoiTrk = tckDetRoiTrk self.set('algorithm', 'Determinist') # Set Method tractography Det elif 'probabilistic' in self.get('algorithm'): tckProb = self.__tckgenTensor( dwi, self.buildName(dwi, 'tensor_prob', 'tck'), mask, tt5, seed_gmwmi, bFile, 'Tensor_Prob') tckProbTrk = mriutil.tck2trk( tckProb, norm , self.buildName(tckProb, None, 'trk')) tckProbRoi = self.__tckedit( tckProb, mask253, self.buildName(tckProb, 'roi', 'tck')) tckProbRoiTrk = mriutil.tck2trk( tckProbRoi, norm , self.buildName(tckProbRoi, None, 'trk')) self.__tckProbRoiTrk = tckProbRoiTrk self.set('algorithm', 'Probabilist') # Set Method tractography Prob else: csd = self.getHardimrtrixImage('dwi', 'csd') hardiTck = self.__tckgenHardi( csd, self.buildName(csd, 'hardi_prob', 'tck'), tt5) hardiTrk = mriutil.tck2trk( hardiTck, norm, self.buildName(hardiTck, None, 'trk')) hardiTckRoi = self.__tckedit( hardiTck, mask253, self.buildName(hardiTck, 'roi', 'tck')) tckgenRoiTrk = mriutil.tck2trk( hardiTckRoi, norm , self.buildName(hardiTckRoi, None, 'trk')) self.__tckgenRoiTrk = tckgenRoiTrk self.set('methodReconstruction', 'hardi') self.set('algorithm', 'Probabilist') if self.get('sift'): tcksift = self.__tcksift(hardiTck, csd) tcksiftTrk = mriutil.tck2trk( tcksift, norm, self.buildName(tcksift, None, 'trk')) tcksiftRoi = self.__tckedit( tcksift, mask253, self.buildName(tcksift, 'roi', 'tck')) tcksiftRoiTrk = mriutil.tck2trk( tcksiftRoi, norm , self.buildName(tcksiftRoi, None, 'trk')) self.__tcksiftRoiTrk = tcksiftRoiTrk
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'))) self.info(mriutil.extractFirstB0FromDwi(dwi, b0, bVals)) 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 if self.get("phase_enc_dir") == "1" and b0PA and b0AP is False: b0AP = b0 [dwi, b0, b0AP, b0PA] = self.__oddEvenNumberOfSlices(dwi, b0, b0AP, b0PA) 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")) elif self.get("phase_enc_dir") == "1": concatenateB0Image = self.__concatenateB0( b0AP, b0PA, self.buildName("b0ap_b0pa", None, "nii.gz")) # Create the acquisition parameter file acqpTopup = self.__createAcquisitionParameterFile('topup') # Run topup on concatenate B0 image [topupBaseName, topupImage] = self.__topup(concatenateB0Image, acqpTopup, self.get('b02b0_filename')) 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 = 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) 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'))
def __isAValidStructure(self): """Determine if the directory is a valid structure Returns: a Boolean that represent if the subject integrity test pass for that directory """ #Anatomical, Dwi and gradient encoding direction are mandatory input anat = util.getImage(self.config, self.workingDir, 'anat') if not anat: if util.getImage(self.config, self.workingDir, 'anat', None, 'nii'): self.warning("Found some uncompressed nifti images into {} directory. " "Please gzip those images and resubmit the pipeline again".format(self.workingDir)) return False self.warning("No high resolution image found into {} directory".format(self.workingDir)) return False dwi = util.getImage(self.config, self.workingDir, 'dwi') if not dwi: if util.getImage(self.config, self.workingDir, 'dwi', None, 'nii'): self.warning("Found some uncompressed nifti image into {} directory. " "Please gzip those images and resubmit the pipeline again".format(self.workingDir)) return False self.warning("No diffusion weight image found into {} directory".format(self.workingDir)) return False bEnc = util.getImage(self.config, self.workingDir,'grad', None, 'b') bVals = util.getImage(self.config, self.workingDir,'grad', None, 'bvals') bVecs = util.getImage(self.config, self.workingDir,'grad', None, 'bvecs') if (not bEnc) and (not bVals or not bVecs): self.warning("No valid .b encoding or (.bvals, .bvecs) files found in directory: {}".format(self.workingDir)) return False else: nbDirections = mriutil.getNbDirectionsFromDWI(dwi) if nbDirections <= 45: msg = "Found only {} directions into {} image. Hardi model will not be accurate with diffusion weighted image " \ "that contain less than 45 directions\n\n".format(nbDirections, dwi) self.warning(msg) #return False if bEnc and not self.__isValidEncoding(nbDirections, '.b'): self.warning("Encoding file {} is invalid".format(bEnc)) return False if bVals and not self.__isValidEncoding(nbDirections, '.bvals'): self.warning("Encoding file {} is invalid".format(bEnc)) return False if bVecs and not self.__isValidEncoding(nbDirections, '.bvecs'): self.warning("Encoding file {} is invalid".format(bVecs)) return False #Validate optionnal images images = { 'anat': (anat, 'high resolution'), 'dwi': (dwi,'diffusion weighted'), 'mag': (util.getImage(self.config, self.workingDir, 'mag'), 'MR magnitude '), 'phase': (util.getImage(self.config, self.workingDir, 'phase'), 'MR phase '), 'b0_ap': (util.getImage(self.config, self.workingDir, 'b0_ap'), "posterior to anterior b0 "), 'b0_pa': (util.getImage(self.config, self.workingDir, 'b0_pa'), "anterior to posterior b0")} if self.config.get('arguments', 'debug') == 'True': self.debug("Images found into {} directory: {}".format(self.workingDir, images)) if self.config.getboolean('arguments', 'prompt'): for key, (value, description) in images.iteritems(): if value: if not mriutil.isDataStridesOrientationExpected(value, self.config.get('preparation', 'stride_orientation'))\ and self.config.getboolean("preparation", "force_realign_strides"): msg = "Data strides layout for {} is unexpected and force_realign_strides is set to True.\n \ If you continue, all unexpected images will be realign accordingly.\n\ Only a copy of the original images will be alter.".format(value) if not util.displayYesNoMessage(msg): self.warning("Remove this subject from the list?") return False else: break #if one and only one b0 image is given, make sure that the b0 image is not on same direction than the dwi. if (not (images['b0_ap'][0] and images['b0_pa'][0])) and (images['b0_ap'][0] or images['b0_pa'][0]) \ and (self.config.get("correction", "ignore") == "False"): if ((self.config.get("correction", "phase_enc_dir") == "0") and images['b0_pa'][0]) \ or ((self.config.get("correction", "phase_enc_dir") == "1") and images['b0_ap'][0]): msg = "Found only one B0 image into the subject directory and that B0 is in " \ "the same phase encoding direction than the DWI.\n" \ "We recommend to remove the B0 image so at least a motion correction will be perform" if not util.displayYesNoMessage(msg): self.warning("Remove this subject from the list?") return False if images['mag'][0] and images['phase'][0] and (images['b0_ap'][0] or images['b0_pa'][0]): msg = "Found both Fieldmap and B0 images into the subject directory\n" \ "We recommend to disabled fieldmap correction?" if not util.displayYesNoMessage(msg): self.warning("Remove this subject from the list?") return False return True
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'))) self.info(mriutil.extractFirstB0FromDwi(dwi, b0, bVals)) 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 if self.get("phase_enc_dir") == "1" and b0PA and b0AP is False: b0AP = b0 [dwi, b0, b0AP, b0PA] = self.__oddEvenNumberOfSlices(dwi, b0, b0AP, b0PA) 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")) elif self.get("phase_enc_dir") == "1": concatenateB0Image = self.__concatenateB0(b0AP, b0PA, self.buildName("b0ap_b0pa", None, "nii.gz")) # Create the acquisition parameter file acqpTopup = self.__createAcquisitionParameterFile('topup') # Run topup on concatenate B0 image [topupBaseName, topupImage] = self.__topup(concatenateB0Image, acqpTopup, self.get('b02b0_filename')) 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 = 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) 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'))
def implement(self): tt5 = self.getRegistrationImage("tt5", "register") seed_gmwmi = self.getMaskingImage("tt5", ["register", "5tt2gmwmi"]) norm = self.getRegistrationImage("norm", "resample") mask253 = self.getMaskingImage('aparc_aseg', ['253', 'mask']) # mask1024= self.getMaskingImage('aparc_aseg', ['1024', 'mask']) dwi = self.getUpsamplingImage('dwi', 'upsample') bFile = self.getUpsamplingImage('grad', None, 'b') mask = self.getRegistrationImage('mask', 'resample') # If step is None set Step = voxelSize/2 if self.get('step') == 'None': voxelSize = [ float(x) for x in self.get('methodology', 't1_voxelsize') [1:-1].split(',') ] self.set('step', str(float(voxelSize[0]) * 0.5)) self.set('angle', str(90 * float(self.get('step')) / float(voxelSize[0]))) self.__nbDirections = mriutil.getNbDirectionsFromDWI(dwi) if self.__nbDirections <= 45 and not self.get('forceHardi'): self.set('methodReconstruction', 'tenseur') if 'deterministic' in self.get('algorithm'): tckDet = self.__tckgenTensor( dwi, self.buildName(dwi, 'tensor_det', 'tck'), mask, tt5, seed_gmwmi, bFile, 'Tensor_Det') tckDetTrk = mriutil.tck2trk( tckDet, norm, self.buildName(tckDet, None, 'trk')) tckDetRoi = self.__tckedit( tckDet, mask253, self.buildName(tckDet, 'roi', 'tck')) tckDetRoiTrk = mriutil.tck2trk( tckDetRoi, norm, self.buildName(tckDetRoi, None, 'trk')) self.__tckDetRoiTrk = tckDetRoiTrk self.set('algorithm', 'Determinist') # Set Method tractography Det elif 'probabilistic' in self.get('algorithm'): tckProb = self.__tckgenTensor( dwi, self.buildName(dwi, 'tensor_prob', 'tck'), mask, tt5, seed_gmwmi, bFile, 'Tensor_Prob') tckProbTrk = mriutil.tck2trk( tckProb, norm, self.buildName(tckProb, None, 'trk')) tckProbRoi = self.__tckedit( tckProb, mask253, self.buildName(tckProb, 'roi', 'tck')) tckProbRoiTrk = mriutil.tck2trk( tckProbRoi, norm, self.buildName(tckProbRoi, None, 'trk')) self.__tckProbRoiTrk = tckProbRoiTrk self.set('algorithm', 'Probabilist') # Set Method tractography Prob else: csd = self.getHardimrtrixImage('dwi', 'csd') hardiTck = self.__tckgenHardi( csd, self.buildName(csd, 'hardi_prob', 'tck'), tt5) hardiTrk = mriutil.tck2trk(hardiTck, norm, self.buildName(hardiTck, None, 'trk')) hardiTckRoi = self.__tckedit( hardiTck, mask253, self.buildName(hardiTck, 'roi', 'tck')) tckgenRoiTrk = mriutil.tck2trk( hardiTckRoi, norm, self.buildName(hardiTckRoi, None, 'trk')) self.__tckgenRoiTrk = tckgenRoiTrk self.set('methodReconstruction', 'hardi') self.set('algorithm', 'Probabilist') if self.get('sift'): tcksift = self.__tcksift(hardiTck, csd) tcksiftTrk = mriutil.tck2trk( tcksift, norm, self.buildName(tcksift, None, 'trk')) tcksiftRoi = self.__tckedit( tcksift, mask253, self.buildName(tcksift, 'roi', 'tck')) tcksiftRoiTrk = mriutil.tck2trk( tcksiftRoi, norm, self.buildName(tcksiftRoi, None, 'trk')) self.__tcksiftRoiTrk = tcksiftRoiTrk
def __isAValidStructure(self): """Determine if the directory is a valid structure Returns: a Boolean that represent if the subject integrity test pass for that directory """ #Anatomical, Dwi and gradient encoding direction are mandatory input anat = util.getImage(self.config, self.workingDir, 'anat') if not anat: if util.getImage(self.config, self.workingDir, 'anat', None, 'nii'): self.warning( "Found some uncompressed nifti images into {} directory. " "Please gzip those images and resubmit the pipeline again". format(self.workingDir)) return False self.warning( "No high resolution image found into {} directory".format( self.workingDir)) return False dwi = util.getImage(self.config, self.workingDir, 'dwi') if not dwi: if util.getImage(self.config, self.workingDir, 'dwi', None, 'nii'): self.warning( "Found some uncompressed nifti image into {} directory. " "Please gzip those images and resubmit the pipeline again". format(self.workingDir)) return False self.warning( "No diffusion weight image found into {} directory".format( self.workingDir)) return False bEnc = util.getImage(self.config, self.workingDir, 'grad', None, 'b') bVals = util.getImage(self.config, self.workingDir, 'grad', None, 'bvals') bVecs = util.getImage(self.config, self.workingDir, 'grad', None, 'bvecs') if (not bEnc) and (not bVals or not bVecs): self.warning( "No valid .b encoding or (.bvals, .bvecs) files found in directory: {}" .format(self.workingDir)) return False else: nbDirections = mriutil.getNbDirectionsFromDWI(dwi) if nbDirections <= 45: msg = "Found only {} directions into {} image. Hardi model will not be accurate with diffusion weighted image " \ "that contain less than 45 directions\n\n".format(nbDirections, dwi) self.warning(msg) #return False if bEnc and not self.__isValidEncoding(nbDirections, '.b'): self.warning("Encoding file {} is invalid".format(bEnc)) return False if bVals and not self.__isValidEncoding(nbDirections, '.bvals'): self.warning("Encoding file {} is invalid".format(bEnc)) return False if bVecs and not self.__isValidEncoding(nbDirections, '.bvecs'): self.warning("Encoding file {} is invalid".format(bVecs)) return False #Validate optionnal images images = { 'anat': (anat, 'high resolution'), 'dwi': (dwi, 'diffusion weighted'), 'mag': (util.getImage(self.config, self.workingDir, 'mag'), 'MR magnitude '), 'phase': (util.getImage(self.config, self.workingDir, 'phase'), 'MR phase '), 'b0_ap': (util.getImage(self.config, self.workingDir, 'b0_ap'), "posterior to anterior b0 "), 'b0_pa': (util.getImage(self.config, self.workingDir, 'b0_pa'), "anterior to posterior b0") } if self.config.get('arguments', 'debug') == 'True': self.debug("Images found into {} directory: {}".format( self.workingDir, images)) if self.config.getboolean('arguments', 'prompt'): for key, (value, description) in images.iteritems(): if value: if not mriutil.isDataStridesOrientationExpected(value, self.config.get('preparation', 'stride_orientation'))\ and self.config.getboolean("preparation", "force_realign_strides"): msg = "Data strides layout for {} is unexpected and force_realign_strides is set to True.\n \ If you continue, all unexpected images will be realign accordingly.\n\ Only a copy of the original images will be alter.".format( value) if not util.displayYesNoMessage(msg): self.warning("Remove this subject from the list?") return False else: break #if one and only one b0 image is given, make sure that the b0 image is not on same direction than the dwi. if (not (images['b0_ap'][0] and images['b0_pa'][0])) and (images['b0_ap'][0] or images['b0_pa'][0]) \ and (self.config.get("correction", "ignore") == "False"): if ((self.config.get("correction", "phase_enc_dir") == "0") and images['b0_pa'][0]) \ or ((self.config.get("correction", "phase_enc_dir") == "1") and images['b0_ap'][0]): msg = "Found only one B0 image into the subject directory and that B0 is in " \ "the same phase encoding direction than the DWI.\n" \ "We recommend to remove the B0 image so at least a motion correction will be perform" if not util.displayYesNoMessage(msg): self.warning("Remove this subject from the list?") return False if images['mag'][0] and images['phase'][0] and ( images['b0_ap'][0] or images['b0_pa'][0]): msg = "Found both Fieldmap and B0 images into the subject directory\n" \ "We recommend to disabled fieldmap correction?" if not util.displayYesNoMessage(msg): self.warning("Remove this subject from the list?") return False return True