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 __isValidEncoding(self, nbDirection, type): """Determine if an image with a prefix exists into the subject directory Args: nbDirection: number of direction into DWI image type: type of encoding file. Valid values are: .b, .bval, .bvec Returns: a Boolean that represent if the encoding file is valid """ encoding = util.getImage(self.config, self.workingDir, 'grad', None, type) if not encoding: self.logger.warning("No {} encoding file found in directory: {}" .format(type, self.workingDir)) return False f = open(encoding,'r') lines = f.readlines() f.close() if type=='.bval': for line in lines: nbElements = len(line.split()) if nbElements != nbDirection: self.logger.warning("Expecting {} elements in {} file, counting {}" .format(nbDirection, encoding, nbElements)) return False elif type=='.bvec': if len(lines) != 3: self.logger.warning("Expecting 3 vectors in {} file, counting {}".format(encoding, len(lines))) return False for line in lines: if len(line.split()) != nbDirection: self.logger.warning("Expecting {} values in {} file, counting {}" .format(nbDirection, encoding, len(line.split()))) return False elif type=='.b': if len(lines) != nbDirection: self.logger.warning("Expecting {} lines in {} file, counting {}".format(nbDirection, type, len(lines))) return False for index, line in enumerate(lines): if index == 0: for token in line.split(): if token not in "0" : self.logger.warning("Expecting only zero values in the first line of file {}, found value {}" .format(encoding, token)) return False if len(line.split()) != 4: self.logger.warning("Expecting 4 elements at line {} of file {}, counting {}" .format(index+1, encoding, len(line.split()))) return False else: self.logger.warning("Unknown encoding file type") return False return True
def isAToadSubject(self): """Determine if the directory contain all the necessary images to be consider a toad subject. Must have at least. 1 high resolution anatomical image (nii or nii.gz) 1 diffusion weighted image (nii or nii.gz) A corresponding B (.b) encoding or a pair of bvecs (.bvecs), bvals (.bvals) encoding file Returns: False if one of those file are missing, True otherwise """ result = True if os.path.exists(self.backupDir): self.info("{} directory exists, assuming validation have already done before".format(self.backupDir)) result = True else: if not (util.getImage(self.config, self.workingDir, 'anat') or util.getImage(self.config, self.workingDir, 'anat', None, 'nii')): self.warning("No high resolution image found into {} directory".format(self.workingDir)) result = False if not (util.getImage(self.config, self.workingDir, 'dwi') or util.getImage(self.config, self.workingDir, 'dwi', None, 'nii')): self.warning("No diffusion weight image found into {} directory".format(self.workingDir)) result = False if (not util.getImage(self.config, self.workingDir,'grad', None, 'b')) and \ (not util.getImage(self.config, self.workingDir,'grad', None, 'bvals') or not util.getImage(self.config, self.workingDir,'grad', None, 'bvecs')): self.warning("No valid .b encoding or (.bvals, .bvecs) files found in directory: {}".format(self.workingDir)) result = False return result
def getImage(self, dir, prefix, postfix=None, ext="nii"): """A simple utility function that return an mri image given certain criteria this is a wrapper over mriutil getImage function Args: dir: the directory where looking for the image prefix: an expression that the filename should start with postfix: an expression that the filename should end with (excluding the extension) ext: name of the extension of the filename Returns: the absolute filename if found, False otherwise """ return util.getImage(self.config, dir, prefix, postfix, ext)
def isAToadSubject(self): """Determine if the directory contain all the necessary images to be consider a toad subject. Must have at least. 1 high resolution anatomical image (nii or nii.gz) 1 diffusion weighted image (nii or nii.gz) A corresponding B (.b) encoding or a pair of bvecs (.bvecs), bvals (.bvals) encoding file Returns: False if one of those file are missing, True otherwise """ result = True if os.path.exists(self.backupDir): self.info( "{} directory exists, assuming validation have already done before" .format(self.backupDir)) result = True else: if not (util.getImage(self.config, self.workingDir, 'anat') or util.getImage(self.config, self.workingDir, 'anat', None, 'nii')): self.warning( "No high resolution image found into {} directory".format( self.workingDir)) result = False if not (util.getImage(self.config, self.workingDir, 'dwi') or util.getImage(self.config, self.workingDir, 'dwi', None, 'nii')): self.warning( "No diffusion weight image found into {} directory".format( self.workingDir)) result = False if (not util.getImage(self.config, self.workingDir, 'grad', None, 'b')) and \ (not util.getImage(self.config, self.workingDir, 'grad', None, 'bvals') or not util.getImage(self.config, self.workingDir, 'grad', None, 'bvecs')): self.warning( "No valid .b encoding or (.bvals, .bvecs) files found in directory: {}" .format(self.workingDir)) result = False return result
def wrapper(*args): arguments = [self.config, directory] + list(args) return util.getImage(*arguments)
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 __isValidEncoding(self, nbDirection, type): """Determine if an image with a prefix exists into the subject directory Args: nbDirection: number of direction into DWI image type: type of encoding file. Valid values are: .b, .bval, .bvec Returns: a Boolean that represent if the encoding file is valid """ encoding = util.getImage(self.config, self.workingDir, 'grad', None, type) if not encoding: self.logger.warning( "No {} encoding file found in directory: {}".format( type, self.workingDir)) return False f = open(encoding, 'r') lines = f.readlines() f.close() if type == '.bval': for line in lines: nbElements = len(line.split()) if nbElements != nbDirection: self.logger.warning( "Expecting {} elements in {} file, counting {}".format( nbDirection, encoding, nbElements)) return False elif type == '.bvec': if len(lines) != 3: self.logger.warning( "Expecting 3 vectors in {} file, counting {}".format( encoding, len(lines))) return False for line in lines: if len(line.split()) != nbDirection: self.logger.warning( "Expecting {} values in {} file, counting {}".format( nbDirection, encoding, len(line.split()))) return False elif type == '.b': if len(lines) != nbDirection: self.logger.warning( "Expecting {} lines in {} file, counting {}".format( nbDirection, type, len(lines))) return False for index, line in enumerate(lines): if index == 0: for token in line.split(): if token not in "0": self.logger.warning( "Expecting only zero values in the first line of file {}, found value {}" .format(encoding, token)) return False if len(line.split()) != 4: self.logger.warning( "Expecting 4 elements at line {} of file {}, counting {}" .format(index + 1, encoding, len(line.split()))) return False else: self.logger.warning("Unknown encoding file type") return False return True
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