def _shebang(item): from mrtrix3 import app, utils #pylint: disable=import-outside-toplevel # If a complete path has been provided rather than just a file name, don't perform any additional file search if os.sep in item: path = item else: path = version_match(item) if path == item: path = find_executable(exe_name(item)) if not path: app.debug('File \"' + item + '\": Could not find file to query') return [] # Read the first 1024 bytes of the file with open(path, 'rb') as file_in: data = file_in.read(1024) # Try to find the shebang line for line in data.splitlines(): # Are there any non-text characters? If so, it's a binary file, so no need to looking for a shebang try: line = str(line.decode('utf-8')) except: app.debug('File \"' + item + '\": Not a text file') return [] line = line.strip() if len(line) > 2 and line[0:2] == '#!': # Need to strip first in case there's a gap between the shebang symbol and the interpreter path shebang = line[2:].strip().split(' ') # On Windows, /usr/bin/env can't be easily found, and any direct interpreter path will have a similar issue. # Instead, manually find the right interpreter to call using distutils # Also if script is written in Python, try to execute it using the same interpreter as that currently running if os.path.basename(shebang[0]) == 'env': if len(shebang) < 2: app.warn('Invalid shebang in script file \"' + item + '\" (missing interpreter after \"env\")') return [] if shebang[1] == 'python': if not sys.executable: app.warn( 'Unable to self-identify Python interpreter; file \"' + item + '\" not guaranteed to execute on same version') return [] shebang = [sys.executable] + shebang[2:] app.debug('File \"' + item + '\": Using current Python interpreter') elif utils.is_windows(): shebang = [ os.path.abspath(find_executable(exe_name(shebang[1]))) ] + shebang[2:] elif utils.is_windows(): shebang = [ os.path.abspath( find_executable(exe_name(os.path.basename( shebang[0])))) ] + shebang[1:] app.debug('File \"' + item + '\": string \"' + line + '\": ' + str(shebang)) return shebang app.debug('File \"' + item + '\": No shebang found') return []
def from_user(filename, escape=True): #pylint: disable=unused-variable from mrtrix3 import app #pylint: disable=import-outside-toplevel fullpath = os.path.abspath(os.path.join(app.WORKING_DIR, filename)) if escape: fullpath = quote(fullpath) app.debug(filename + ' -> ' + fullpath) return fullpath
def execute(): #pylint: disable=unused-variable if not find_executable('N4BiasFieldCorrection'): raise MRtrixError('Could not find ANTS program N4BiasFieldCorrection; please check installation') for key in sorted(OPT_N4_BIAS_FIELD_CORRECTION): if hasattr(app.ARGS, 'ants.' + key): val = getattr(app.ARGS, 'ants.' + key) if val is not None: OPT_N4_BIAS_FIELD_CORRECTION[key] = (val, 'user defined') ants_options = ' '.join(['-%s %s' %(k, v[0]) for k, v in OPT_N4_BIAS_FIELD_CORRECTION.items()]) # Generate a mean b=0 image run.command('dwiextract in.mif - -bzero | mrmath - mean mean_bzero.mif -axis 3') # Use the brain mask as a weights image rather than a mask; means that voxels at the edge of the mask # will have a smoothly-varying bias field correction applied, rather than multiplying by 1.0 outside the mask run.command('mrconvert mean_bzero.mif mean_bzero.nii -strides +1,+2,+3') run.command('mrconvert mask.mif mask.nii -strides +1,+2,+3') init_bias_path = 'init_bias.nii' corrected_path = 'corrected.nii' run.command('N4BiasFieldCorrection -d 3 -i mean_bzero.nii -w mask.nii -o [' + corrected_path + ',' + init_bias_path + '] ' + ants_options) # N4 can introduce large differences between subjects via a global scaling of the bias field # Estimate this scaling based on the total integral of the pre- and post-correction images within the brain mask input_integral = float(run.command('mrcalc mean_bzero.mif mask.mif -mult - | mrmath - sum - -axis 0 | mrmath - sum - -axis 1 | mrmath - sum - -axis 2 | mrdump -').stdout) output_integral = float(run.command('mrcalc ' + corrected_path + ' mask.mif -mult - | mrmath - sum - -axis 0 | mrmath - sum - -axis 1 | mrmath - sum - -axis 2 | mrdump -').stdout) multiplier = output_integral / input_integral app.debug('Integrals: Input = ' + str(input_integral) + '; Output = ' + str(output_integral) + '; resulting multiplier = ' + str(multiplier)) run.command('mrcalc ' + init_bias_path + ' ' + str(multiplier) + ' -mult bias.mif') # Common final steps for all algorithms run.command('mrcalc in.mif bias.mif -div result.mif') run.command('mrconvert result.mif ' + path.from_user(app.ARGS.output), mrconvert_keyval=path.from_user(app.ARGS.input, False), force=app.FORCE_OVERWRITE) if app.ARGS.bias: run.command('mrconvert bias.mif ' + path.from_user(app.ARGS.bias), mrconvert_keyval=path.from_user(app.ARGS.input, False), force=app.FORCE_OVERWRITE)
def shared_data_path(): #pylint: disable=unused-variable from mrtrix3 import app #pylint: disable=import-outside-toplevel result = os.path.realpath( os.path.abspath( os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir, 'share', 'mrtrix3'))) app.debug(result) return result
def to_scratch(filename, escape=True): #pylint: disable=unused-variable import os from mrtrix3 import app fullpath = os.path.abspath(os.path.join(app.SCRATCH_DIR, filename)) if escape: fullpath = quote(fullpath) app.debug(filename + ' -> ' + fullpath) return fullpath
def function(fn, *args, **kwargs): #pylint: disable=unused-variable import inspect, sys from mrtrix3 import app fnstring = fn.__module__ + '.' + fn.__name__ + \ '(' + ', '.join(['\'' + str(a) + '\'' if isinstance(a, str) else str(a) for a in args]) + \ (', ' if (args and kwargs) else '') + \ ', '.join([key+'='+str(value) for key, value in kwargs.items()]) + ')' if _lastFile: if _triggerContinue(args) or _triggerContinue(kwargs.values()): app.debug('Detected last file in function \'' + fnstring + '\'; this is the last run.command() / run.function() call that will be skipped') if app.verbosity: sys.stderr.write(app.colourExec + 'Skipping function:' + app.colourClear + ' ' + fnstring + '\n') sys.stderr.flush() return None if app.verbosity: sys.stderr.write(app.colourExec + 'Function:' + app.colourClear + ' ' + fnstring + '\n') sys.stderr.flush() # Now we need to actually execute the requested function try: if kwargs: result = fn(*args, **kwargs) else: result = fn(*args) except Exception as e: # pylint: disable=broad-except app.cleanup = False caller = inspect.getframeinfo(inspect.stack()[1][0]) error_text = str(type(e).__name__) + ': ' + str(e) script_name = os.path.basename(sys.argv[0]) app.console('') try: filename = caller.filename lineno = caller.lineno except AttributeError: filename = caller[1] lineno = caller[2] sys.stderr.write(script_name + ': ' + app.colourError + '[ERROR] Function failed: ' + fnstring + app.colourClear + app.colourDebug + ' (' + os.path.basename(filename) + ':' + str(lineno) + ')' + app.colourClear + '\n') sys.stderr.write(script_name + ': ' + app.colourConsole + 'Information from failed function:' + app.colourClear + '\n') for line in error_text.splitlines(): sys.stderr.write(' ' * (len(script_name)+2) + line + '\n') app.console('') sys.stderr.flush() if app.tempDir: with open(os.path.join(app.tempDir, 'error.txt'), 'w') as outfile: outfile.write(fnstring + '\n\n' + error_text + '\n') app.complete() sys.exit(1) # Only now do we append to the script log, since the function has completed successfully if app.tempDir: with open(os.path.join(app.tempDir, 'log.txt'), 'a') as outfile: outfile.write(fnstring + '\n') return result
def sharedDataPath(): #pylint: disable=unused-variable import os from mrtrix3 import app result = os.path.realpath( os.path.abspath( os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir, os.pardir, 'share', 'mrtrix3'))) app.debug(result) return result
def fromUser(filename, is_command): #pylint: disable=unused-variable import os from mrtrix3 import app wrapper='' if is_command and (filename.count(' ') or app.workingDir.count(' ')): wrapper='\"' path = wrapper + os.path.abspath(os.path.join(app.workingDir, filename)) + wrapper app.debug(filename + ' -> ' + path) return path
def toTemp(filename, is_command): import os from mrtrix3 import app wrapper='' if is_command and filename.count(' '): wrapper='\"' path = wrapper + os.path.abspath(os.path.join(app._tempDir, filename)) + wrapper app.debug(filename + ' -> ' + path) return path
def fromUser(filename, is_command): import os from mrtrix3 import app wrapper='' if is_command and (filename.count(' ') or app._workingDir.count(' ')): wrapper='\"' path = wrapper + os.path.abspath(os.path.join(app._workingDir, filename)) + wrapper app.debug(filename + ' -> ' + path) return path
def make_dir(path): #pylint: disable=unused-variable from mrtrix3 import app #pylint: disable=import-outside-toplevel try: os.makedirs(path) app.debug('Created directory ' + path) except OSError as exception: if exception.errno != errno.EEXIST: raise app.debug('Directory \'' + path + '\' already exists')
def makeDir(path): import errno, os from mrtrix3 import app try: os.makedirs(path) app.debug('Created directory ' + path) except OSError as exception: if exception.errno != errno.EEXIST: raise app.debug('Directory ' + path + ' already exists')
def makeDir(path): #pylint: disable=unused-variable import errno, os from mrtrix3 import app try: os.makedirs(path) app.debug('Created directory ' + path) except OSError as exception: if exception.errno != errno.EEXIST: raise app.debug('Directory \'' + path + '\' already exists')
def get_list(): #pylint: disable=unused-variable from mrtrix3 import app #pylint: disable=import-outside-toplevel algorithm_list = [ ] for filename in os.listdir(_algorithms_path()): filename = filename.split('.') if len(filename) == 2 and filename[1] == 'py' and filename[0] != '__init__': algorithm_list.append(filename[0]) algorithm_list = sorted(algorithm_list) app.debug('Found algorithms: ' + str(algorithm_list)) return algorithm_list
def toTemp(filename, is_command): #pylint: disable=unused-variable import os from mrtrix3 import app wrapper = '' if is_command and (filename.count(' ') or app.tempDir.count(' ')): wrapper = '\"' path = wrapper + os.path.abspath(os.path.join(app.tempDir, filename)) + wrapper app.debug(filename + ' -> ' + path) return path
def initialise(): #pylint: disable=unused-variable import importlib, pkgutil from mrtrix3 import app, path initlist = [ ] base_parser = app.Parser(description='Base parser for construction of subparsers', parents=[app.cmdline]) subparsers = app.cmdline.add_subparsers(title='Algorithm choices', help='Select the algorithm to be used to complete the script operation; additional details and options become available once an algorithm is nominated. Options are: ' + ', '.join(getList()), dest='algorithm') for dummy_importer, package_name, dummy_ispkg in pkgutil.iter_modules( [ _algorithmsPath() ] ): module = importlib.import_module('mrtrix3.' + path.scriptSubDirName() + '.' + package_name) module.initialise(base_parser, subparsers) initlist.extend(package_name) app.debug('Initialised algorithms: ' + str(initlist))
def delTempFile(path): import os from mrtrix3 import app if not app._cleanup: return if app._verbosity > 2: app.console('Deleting temporary file: ' + path) try: os.remove(path) except OSError: app.debug('Unable to delete temporary file ' + path)
def exe_name(name): #pylint: disable=unused-variable from mrtrix3 import app, MRtrixError from distutils.spawn import find_executable if find_executable(name): output = name elif find_executable('fsl5.0-' + name): output = 'fsl5.0-' + name else: raise MRtrixError('Could not find FSL program \"' + name + '\"; please verify FSL install') app.debug(output) return output
def delTempFolder(path): import shutil from mrtrix3 import app if not app._cleanup: return if app._verbosity > 2: app.console('Deleting temporary folder: ' + path) try: shutil.rmtree(path) except OSError: app.debug('Unable to delete temprary folder ' + path)
def waitFor(path): import os, time from mrtrix3 import app def inUse(path): import subprocess from distutils.spawn import find_executable if app.isWindows(): if not os.access(path, os.W_OK): return None try: with open(path, 'rb+') as f: pass return False except: return True if not find_executable('fuser'): return None # fuser returns zero if there IS at least one process accessing the file # A fatal error will result in a non-zero code -> inUse() = False, so waitFor() can return return not subprocess.call(['fuser', '-s', path], shell=False, stdin=None, stdout=None, stderr=None) if not os.path.exists(path): delay = 1.0 / 1024.0 app.console('Waiting for creation of new file \"' + path + '\"') while not os.path.exists(path): time.sleep(delay) delay = max(60.0, delay * 2.0) app.debug('File \"' + path + '\" appears to have been created') if not os.path.isfile(path): app.debug('Path \"' + path + '\" is not a file; not testing for finalization') return init_test = inUse(path) if init_test is None: app.debug('Unable to test for finalization of new file \"' + path + '\"') return if not init_test: app.debug('File \"' + path + '\" immediately ready') return app.console('Waiting for finalization of new file \"' + path + '\"') delay = 1.0 / 1024.0 while True: if inUse(path): time.sleep(delay) delay = max(60.0, delay * 2.0) else: app.debug('File \"' + path + '\" appears to have been finalized') return
def check3DNonunity(image_in): #pylint: disable=unused-variable from mrtrix3 import app if not isinstance(image_in, Header): if not isinstance(image_in, str): app.error('Error trying to test \'' + str(image_in) + '\': Not an image header or file path') image_in = Header(image_in) if len(image_in.size()) < 3: app.error('Image \'' + image_in.name() + '\' does not contain 3 spatial dimensions') if min(image_in.size()[:3]) == 1: app.error('Image \'' + image_in.name() + '\' does not contain 3D spatial information (has axis with size 1)') app.debug('Image \'' + image_in.name() + '\' is >= 3D, and does not contain a unity spatial dimension')
def name_temporary(suffix): #pylint: disable=unused-variable from mrtrix3 import app #pylint: disable=import-outside-toplevel dir_path = CONFIG['TmpFileDir'] if 'TmpFileDir' in CONFIG else (app.SCRATCH_DIR if app.SCRATCH_DIR else os.getcwd()) prefix = CONFIG['TmpFilePrefix'] if 'TmpFilePrefix' in CONFIG else 'mrtrix-tmp-' full_path = dir_path suffix = suffix.lstrip('.') while os.path.exists(full_path): random_string = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for x in range(6)) full_path = os.path.join(dir_path, prefix + random_string + '.' + suffix) app.debug(full_path) return full_path
def check_3d_nonunity(image_in): #pylint: disable=unused-variable from mrtrix3 import app #pylint: disable=import-outside-toplevel if not isinstance(image_in, Header): if not isinstance(image_in, STRING_TYPES): raise MRtrixError('Error trying to test \'' + str(image_in) + '\': Not an image header or file path') image_in = Header(image_in) if len(image_in.size()) < 3: raise MRtrixError('Image \'' + image_in.name() + '\' does not contain 3 spatial dimensions') if min(image_in.size()[:3]) == 1: raise MRtrixError('Image \'' + image_in.name() + '\' does not contain 3D spatial information (has axis with size 1)') app.debug('Image \'' + image_in.name() + '\' is >= 3D, and does not contain a unity spatial dimension')
def initialise(): import importlib, pkgutil from mrtrix3 import app, path initlist = [ ] base_parser = app.Parser(description='Base parser for construction of subparsers', parents=[app.cmdline]) subparsers = app.cmdline.add_subparsers(title='Algorithm choices', help='Select the algorithm to be used to complete the script operation; additional details and options become available once an algorithm is nominated. Options are: ' + ', '.join(getList()), dest='algorithm') for importer, package_name, ispkg in pkgutil.iter_modules( [ _algorithmsPath() ] ): module = importlib.import_module('mrtrix3.' + path.scriptSubDirName() + '.' + package_name) module.initialise(base_parser, subparsers) initlist.extend(package_name) app.debug('Initialised algorithms: ' + str(initlist))
def exeName(name): #pylint: disable=unused-variable from mrtrix3 import app from distutils.spawn import find_executable if find_executable('fsl5.0-' + name): output = 'fsl5.0-' + name elif find_executable(name): output = name else: app.error('Could not find FSL program \"' + name + '\"; please verify FSL install') app.debug(output) return output
def getList(): #pylint: disable=unused-variable import os from mrtrix3 import app algorithm_list = [ ] src_file_list = os.listdir(_algorithmsPath()) for filename in src_file_list: filename = filename.split('.') if len(filename) == 2 and filename[1] == 'py' and not filename[0] == '__init__': algorithm_list.append(filename[0]) algorithm_list = sorted(algorithm_list) app.debug('Found algorithms: ' + str(algorithm_list)) return algorithm_list
def find_image(name): #pylint: disable=unused-variable import os from mrtrix3 import app, MRtrixError prefix = os.path.join(os.path.dirname(name), os.path.basename(name).split('.')[0]) if os.path.isfile(prefix + suffix()): app.debug('Image at expected location: \"' + prefix + suffix() + '\"') return prefix + suffix() for suf in ['.nii', '.nii.gz', '.img']: if os.path.isfile(prefix + suf): app.debug('Expected image at \"' + prefix + suffix() + '\", but found at \"' + prefix + suf + '\"') return prefix + suf raise MRtrixError('Unable to find FSL output file for path \"' + name + '\"')
def findImage(name): import os from mrtrix3 import app basename = name.split('.')[0] if os.path.isfile(basename + suffix()): app.debug('Image at expected location: \"' + basename + suffix() + '\"') return basename + suffix() for suf in ['.nii', '.nii.gz', '.img']: if os.path.isfile(basename + suf): app.debug('Expected image at \"' + basename + suffix() + '\", but found at \"' + basename + suf + '\"') return basename + suf app.error('Unable to find FSL output file for path \"' + name + '\"')
def exe_name(name): #pylint: disable=unused-variable from mrtrix3 import app #pylint: disable=import-outside-toplevel if find_executable(name): output = name elif find_executable('fsl5.0-' + name): output = 'fsl5.0-' + name app.warn('Using FSL binary \"' + output + '\" rather than \"' + name + '\"; suggest checking FSL installation') else: raise MRtrixError('Could not find FSL program \"' + name + '\"; please verify FSL install') app.debug(output) return output
def findImage(name): #pylint: disable=unused-variable import os from mrtrix3 import app prefix = os.path.join(os.path.dirname(name), os.path.basename(name).split('.')[0]) if os.path.isfile(prefix + suffix()): app.debug('Image at expected location: \"' + prefix + suffix() + '\"') return prefix + suffix() for suf in ['.nii', '.nii.gz', '.img']: if os.path.isfile(prefix + suf): app.debug('Expected image at \"' + prefix + suffix() + '\", but found at \"' + prefix + suf + '\"') return prefix + suf app.error('Unable to find FSL output file for path \"' + name + '\"') return ''
def script_subdir_name(): #pylint: disable=unused-variable from mrtrix3 import app #pylint: disable=import-outside-toplevel frameinfo = inspect.stack()[-1] try: frame = frameinfo.frame except: # Prior to Version 3.5 frame = frameinfo[0] # If the script has been run through a softlink, we need the name of the original # script in order to locate the additional data name = os.path.basename(os.path.realpath(inspect.getfile(frame))) if not name[0].isalpha(): name = '_' + name app.debug(name) return name
def match(image_one, image_two): import math from mrtrix3 import app debug_prefix = '\'' + image_one + '\' \'' + image_two + '\'' # Image dimensions one_dim = [ int(i) for i in headerField(image_one, 'size').split() ] two_dim = [ int(i) for i in headerField(image_two, 'size').split() ] if not one_dim == two_dim: app.debug(debug_prefix + ' dimension mismatch (' + str(one_dim) + ' ' + str(two_dim) + ')') return False # Voxel size one_spacing = [ float(f) for f in headerField(image_one, 'vox').split() ] two_spacing = [ float(f) for f in headerField(image_two, 'vox').split() ] for one, two in zip(one_spacing, two_spacing): if one and two and not math.isnan(one) and not math.isnan(two): if (abs(two-one) / (0.5*(one+two))) > 1e-04: app.debug(debug_prefix + ' voxel size mismatch (' + str(one_spacing) + ' ' + str(two_spacing) + ')') return False # Image transform one_transform = [ float(f) for f in headerField(image_one, 'transform').replace('\n', ' ').replace(',', ' ').split() ] two_transform = [ float(f) for f in headerField(image_two, 'transform').replace('\n', ' ').replace(',', ' ').split() ] for one, two in zip(one_transform, two_transform): if abs(one-two) > 1e-4: app.debug(debug_prefix + ' transform mismatch (' + str(one_transform) + ' ' + str(two_transform) + ')') return False # Everything matches! app.debug(debug_prefix + ' image match') return True
def usage(cmdline): #pylint: disable=unused-variable from mrtrix3 import app, path #pylint: disable=import-outside-toplevel sys.path.insert(0, os.path.realpath(os.path.join(_algorithms_path(), os.pardir))) initlist = [ ] # Don't let Python 3 try to read incompatible .pyc files generated by Python 2 for no-longer-existent .py files pylist = get_list() base_parser = app.Parser(description='Base parser for construction of subparsers', parents=[cmdline]) subparsers = cmdline.add_subparsers(title='Algorithm choices', help='Select the algorithm to be used to complete the script operation; additional details and options become available once an algorithm is nominated. Options are: ' + ', '.join(get_list()), dest='algorithm') for dummy_importer, package_name, dummy_ispkg in pkgutil.iter_modules( [ _algorithms_path() ] ): if package_name in pylist: module = importlib.import_module(path.script_subdir_name() + '.' + package_name) module.usage(base_parser, subparsers) initlist.extend(package_name) app.debug('Initialised algorithms: ' + str(initlist))
def function(fn_to_execute, *args, **kwargs): #pylint: disable=unused-variable import os, sys from mrtrix3 import ANSI, app if not fn_to_execute: raise TypeError('Invalid input to run.function()') show = kwargs.pop('show', True) fnstring = fn_to_execute.__module__ + '.' + fn_to_execute.__name__ + \ '(' + ', '.join(['\'' + str(a) + '\'' if isinstance(a, str) else str(a) for a in args]) + \ (', ' if (args and kwargs) else '') + \ ', '.join([key+'='+str(value) for key, value in kwargs.items()]) + ')' if shared.get_continue(): if shared.trigger_continue(args) or shared.trigger_continue( kwargs.values()): app.debug( 'Detected last file in function \'' + fnstring + '\'; this is the last run.command() / run.function() call that will be skipped' ) if shared.verbosity: sys.stderr.write(ANSI.execute + 'Skipping function:' + ANSI.clear + ' ' + fnstring + '\n') sys.stderr.flush() return None if (shared.verbosity and show) or shared.verbosity > 1: sys.stderr.write(ANSI.execute + 'Function:' + ANSI.clear + ' ' + fnstring + '\n') sys.stderr.flush() # Now we need to actually execute the requested function try: if kwargs: result = fn_to_execute(*args, **kwargs) else: result = fn_to_execute(*args) except Exception as exception: # pylint: disable=broad-except raise MRtrixFnError(fnstring, str(exception)) # Only now do we append to the script log, since the function has completed successfully if shared.get_scratch_dir(): with shared.lock: with open(os.path.join(shared.get_scratch_dir(), 'log.txt'), 'a') as outfile: outfile.write(fnstring + '\n') return result
def scriptSubDirName(): #pylint: disable=unused-variable import inspect, os from mrtrix3 import app frameinfo = inspect.stack()[-1] try: frame = frameinfo.frame except: # Prior to Version 3.5 frame = frameinfo[0] # If the script has been run through a softlink, we need the name of the original # script in order to locate the additional data name = os.path.basename(os.path.realpath(inspect.getfile(frame))) if not name[0].isalpha(): name = '_' + name app.debug(name) return name
def make_temporary(suffix): #pylint: disable=unused-variable from mrtrix3 import app #pylint: disable=import-outside-toplevel is_directory = suffix in '\\/' and len(suffix) == 1 while True: temp_path = name_temporary(suffix) try: if is_directory: os.makedirs(temp_path) else: open(temp_path, 'a').close() app.debug(temp_path) return temp_path except OSError as exception: if exception.errno != errno.EEXIST: raise
def commonPostfix(inputFiles): #pylint: disable=unused-variable from mrtrix3 import app first = inputFiles[0] cursor = 0 found = False common = '' for dummy_i in reversed(first): if not found: for j in inputFiles: if j[len(j)-cursor-1] != first[len(first)-cursor-1]: found = True break if not found: common = first[len(first)-cursor-1] + common cursor += 1 app.debug('Common postfix of ' + str(len(inputFiles)) + ' is \'' + common + '\'') return common
def commonPostfix(inputFiles): from mrtrix3 import app first = inputFiles[0]; cursor = 0 found = False; common = '' for i in reversed(first): if found == False: for j in inputFiles: if j[len(j)-cursor-1] != first[len(first)-cursor-1]: found = True break if found == False: common = first[len(first)-cursor-1] + common cursor += 1 app.debug('Common postfix of ' + str(len(inputFiles)) + ' is \'' + common + '\'') return common
def axis2dir(string): #pylint: disable=unused-variable from mrtrix3 import app if string == 'i': direction = [1,0,0] elif string == 'i-': direction = [-1,0,0] elif string == 'j': direction = [0,1,0] elif string == 'j-': direction = [0,-1,0] elif string == 'k': direction = [0,0,1] elif string == 'k-': direction = [0,0,-1] else: app.error('Unrecognized NIfTI axis & direction specifier: ' + string) app.debug(string + ' -> ' + str(direction)) return direction
def getScheme(arg): #pylint: disable=unused-variable from mrtrix3 import app, image if not isinstance(arg, image.Header): if not isinstance(arg, str): app.error('Error trying to derive phase-encoding scheme from \'' + str(arg) + '\': Not an image header or file path') arg = image.Header(arg) if 'pe_scheme' in arg.keyval(): app.debug(str(arg.keyval()['pe_scheme'])) return arg.keyval()['pe_scheme'] if 'PhaseEncodingDirection' not in arg.keyval(): return None line = direction(arg.keyval()['PhaseEncodingDirection']) if 'TotalReadoutTime' in arg.keyval(): line = [ float(value) for value in line ] line.append(float(arg.keyval()['TotalReadoutTime'])) num_volumes = 1 if len(arg.size()) < 4 else arg.size()[3] app.debug(str(line) + ' x ' + str(num_volumes) + ' rows') return [ line ] * num_volumes
def getScheme(image_path): import subprocess from mrtrix3 import app, run command = [ run.versionMatch('mrinfo'), image_path, '-petable' ] if app._verbosity > 1: app.console('Command: \'' + ' '.join(command) + '\' (piping data to local storage)') proc = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=None) result, err = proc.communicate() result = result.rstrip().decode('utf-8') if result: result = [ [ float(f) for f in line.split() ] for line in result.split('\n') ] if app._verbosity > 1: if not result: app.console('Result: No phase encoding table found') else: app.console('Result: ' + str(len(result)) + ' x ' + str(len(result[0])) + ' table') app.debug(str(result)) return result
def newTempFile(suffix): import os, random, string, sys from mrtrix3 import app if 'TmpFileDir' in app.config: dir_path = app.config['TmpFileDir'] else: dir_path = app._tempDir if 'TmpFilePrefix' in app.config: prefix = app.config['TmpFilePrefix'] else: prefix = 'mrtrix-tmp-' full_path = dir_path if not suffix: suffix = 'mif' while os.path.exists(full_path): random_string = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(6)) full_path = os.path.join(dir_path, prefix + random_string + '.' + suffix) app.debug(full_path) return full_path
def direction(string): #pylint: disable=unused-variable from mrtrix3 import app pe_dir = '' try: PE_axis = abs(int(string)) if PE_axis > 2: app.error('When specified as a number, phase encode axis must be either 0, 1 or 2 (positive or negative)') reverse = (string.contains('-')) # Allow -0 pe_dir = [0,0,0] if reverse: pe_dir[PE_axis] = -1 else: pe_dir[PE_axis] = 1 except: string = string.lower() if string == 'lr': pe_dir = [1,0,0] elif string == 'rl': pe_dir = [-1,0,0] elif string == 'pa': pe_dir = [0,1,0] elif string == 'ap': pe_dir = [0,-1,0] elif string == 'is': pe_dir = [0,0,1] elif string == 'si': pe_dir = [0,0,-1] elif string == 'i': pe_dir = [1,0,0] elif string == 'i-': pe_dir = [-1,0,0] elif string == 'j': pe_dir = [0,1,0] elif string == 'j-': pe_dir = [0,-1,0] elif string == 'k': pe_dir = [0,0,1] elif string == 'k-': pe_dir = [0,0,-1] else: app.error('Unrecognized phase encode direction specifier: ' + string) app.debug(string + ' -> ' + str(pe_dir)) return pe_dir
def newTemporary(suffix): #pylint: disable=unused-variable import os.path, random, string from mrtrix3 import app if 'TmpFileDir' in app.config: dir_path = app.config['TmpFileDir'] elif app.tempDir: dir_path = app.tempDir else: dir_path = os.getcwd() if 'TmpFilePrefix' in app.config: prefix = app.config['TmpFilePrefix'] else: prefix = 'mrtrix-tmp-' full_path = dir_path suffix = suffix.lstrip('.') while os.path.exists(full_path): random_string = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(6)) full_path = os.path.join(dir_path, prefix + random_string + '.' + suffix) app.debug(full_path) return full_path
def delTemporary(path): #pylint: disable=unused-variable import shutil, os from mrtrix3 import app if not app.cleanup: return if os.path.isfile(path): temporary_type = 'file' func = os.remove elif os.path.isdir(path): temporary_type = 'directory' func = shutil.rmtree else: app.debug('Unknown target \'' + path + '\'') return if app.verbosity > 2: app.console('Deleting temporary ' + temporary_type + ': \'' + path + '\'') try: func(path) except OSError: app.debug('Unable to delete temporary ' + temporary_type + ': \'' + path + '\'')
def eddyBinary(cuda): import os from mrtrix3 import app from distutils.spawn import find_executable if cuda: if find_executable('eddy_cuda'): app.debug('Selecting CUDA version of eddy') return 'eddy_cuda' else: app.warn('CUDA version of eddy not found; running standard version') if find_executable('eddy_openmp'): path = 'eddy_openmp' elif find_executable('eddy'): path = 'eddy' elif find_executable('fsl5.0-eddy'): path = 'fsl5.0-eddy' else: app.error('Could not find FSL program eddy; please verify FSL install') app.debug(path) return path
def function(fn, *args): import os, sys from mrtrix3 import app fnstring = fn.__module__ + '.' + fn.__name__ + '(' + ', '.join(args) + ')' if app._lastFile: # Check to see if the last file produced in the previous script execution is # intended to be produced by this command; if it is, this will be the last # command that gets skipped by the -continue option # It's possible that the file might be defined in a '--option=XXX' style argument # It's also possible that the filename in the command string has the file extension omitted for entry in args: if entry.startswith('--') and '=' in entry: totest = entry.split('=')[1] else: totest = entry filetotest = [ app._lastFile, os.path.splitext(app._lastFile)[0] ] if totest in filetotest: app.debug('Detected last file \'' + app._lastFile + '\' in function \'' + fnstring + '\'; this is the last run.command() / run.function() call that will be skipped') app._lastFile = '' break if app._verbosity: sys.stderr.write(app.colourExec + 'Skipping function:' + app.colourClear + ' ' + fnstring + '\n') sys.stderr.flush() return if app._verbosity: sys.stderr.write(app.colourExec + 'Function:' + app.colourClear + ' ' + fnstring + '\n') sys.stderr.flush() # Now we need to actually execute the requested function result = fn(*args) # Only now do we append to the script log, since the function has completed successfully if app._tempDir: with open(os.path.join(app._tempDir, 'log.txt'), 'a') as outfile: outfile.write(fnstring + '\n') return result
def exeName(item): from distutils.spawn import find_executable from mrtrix3 import app global _mrtrix_bin_path if not app.isWindows(): path = item elif item.endswith('.exe'): path = item elif os.path.isfile(os.path.join(_mrtrix_bin_path, item)): path = item elif os.path.isfile(os.path.join(_mrtrix_bin_path, item + '.exe')): path = item + '.exe' elif find_executable(item) is not None: path = item elif find_executable(item + '.exe') is not None: path = item + '.exe' # If it can't be found, return the item as-is; find_executable() fails to identify Python scripts else: path = item app.debug(item + ' -> ' + path) return path
def eddyBinary(cuda): #pylint: disable=unused-variable import os from mrtrix3 import app from distutils.spawn import find_executable if cuda: if find_executable('eddy_cuda'): app.debug('Selected soft-linked CUDA version (\'eddy_cuda\')') return 'eddy_cuda' # Cuda versions are now provided with a CUDA trailing version number # Users may not necessarily create a softlink to one of these and # call it "eddy_cuda" # Therefore, hunt through PATH looking for them; if more than one, # select the one with the highest version number binaries = [ ] for directory in os.environ['PATH'].split(os.pathsep): if os.path.isdir(directory): for entry in os.listdir(directory): if entry.startswith('eddy_cuda'): binaries.append(entry) max_version = 0.0 exe_path = '' for entry in binaries: try: version = float(entry.lstrip('eddy_cuda')) if version > max_version: max_version = version exe_path = entry except: pass if exe_path: app.debug('CUDA version ' + str(max_version) + ': ' + exe_path) return exe_path app.debug('No CUDA version of eddy found') return '' for candidate in [ 'eddy_openmp', 'eddy_cpu', 'eddy', 'fsl5.0-eddy' ]: if find_executable(candidate): app.debug(candidate) return candidate app.debug('No CPU version of eddy found') return ''
def suffix(): #pylint: disable=unused-variable import os from mrtrix3 import app global _suffix if _suffix: return _suffix fsl_output_type = os.environ.get('FSLOUTPUTTYPE', '') if fsl_output_type == 'NIFTI': app.debug('NIFTI -> .nii') _suffix = '.nii' elif fsl_output_type == 'NIFTI_GZ': app.debug('NIFTI_GZ -> .nii.gz') _suffix = '.nii.gz' elif fsl_output_type == 'NIFTI_PAIR': app.debug('NIFTI_PAIR -> .img') _suffix = '.img' elif fsl_output_type == 'NIFTI_PAIR_GZ': app.error('MRtrix3 does not support compressed NIFTI pairs; please change FSLOUTPUTTYPE environment variable') elif fsl_output_type: app.warn('Unrecognised value for environment variable FSLOUTPUTTYPE (\"' + fsl_output_type + '\"): Expecting compressed NIfTIs, but FSL commands may fail') _suffix = '.nii.gz' else: app.warn('Environment variable FSLOUTPUTTYPE not set; FSL commands may fail, or script may fail to locate FSL command outputs') _suffix = '.nii.gz' return _suffix
def __init__(self, image_path): import json, os, subprocess from mrtrix3 import app, path, run filename = path.newTemporary('json') command = [ run.exeName(run.versionMatch('mrinfo')), image_path, '-json_all', filename ] if app.verbosity > 1: app.console('Loading header for image file \'' + image_path + '\'') app.debug(str(command)) result = subprocess.call(command, stdout=None, stderr=None) if result: app.error('Could not access header information for image \'' + image_path + '\'') try: with open(filename, 'r') as f: data = json.load(f) except UnicodeDecodeError: with open(filename, 'r') as f: data = json.loads(f.read().decode('utf-8', errors='replace')) os.remove(filename) try: #self.__dict__.update(data) # Load the individual header elements manually, for a couple of reasons: # - So that pylint knows that they'll be there # - Write to private members, and give read-only access self._name = data['name'] self._size = data['size'] self._spacing = data['spacing'] self._strides = data['strides'] self._format = data['format'] self._datatype = data['datatype'] self._intensity_offset = data['intensity_offset'] self._intensity_scale = data['intensity_scale'] self._transform = data['transform'] if not 'keyval' in data or not data['keyval']: self._keyval = { } else: self._keyval = data['keyval'] except: app.error('Error in reading header information from file \'' + image_path + '\'') app.debug(str(vars(self)))
def _shebang(item): import os from mrtrix3 import app from distutils.spawn import find_executable # If a complete path has been provided rather than just a file name, don't perform any additional file search if os.sep in item: path = item else: path = versionMatch(item) if path == item: path = find_executable(exeName(item)) if not path: app.debug('File \"' + item + '\": Could not find file to query') return [] # Read the first 1024 bytes of the file with open(path, 'rb') as f: data = f.read(1024) # Try to find the shebang line for line in data.splitlines(): # Are there any non-text characters? If so, it's a binary file, so no need to looking for a shebang try : line = str(line.decode('utf-8')) except: app.debug('File \"' + item + '\": Not a text file') return [] line = line.strip() if len(line) > 2 and line[0:2] == '#!': # Need to strip first in case there's a gap between the shebang symbol and the interpreter path shebang = line[2:].strip().split(' ') if app.isWindows(): # On Windows, /usr/bin/env can't be easily found, and any direct interpreter path will have a similar issue. # Instead, manually find the right interpreter to call using distutils if os.path.basename(shebang[0]) == 'env': new_shebang = [ os.path.abspath(find_executable(exeName(shebang[1]))) ] new_shebang.extend(shebang[2:]) shebang = new_shebang else: new_shebang = [ os.path.abspath(find_executable(exeName(os.path.basename(shebang[0])))) ] new_shebang.extend(shebang[1:]) shebang = new_shebang if not shebang or not shebang[0]: app.error('Malformed shebang in file \"' + item + '\": \"' + line + '\"') app.debug('File \"' + item + '\": string \"' + line + '\": ' + str(shebang)) return shebang app.debug('File \"' + item + '\": No shebang found') return []