def main(): parser = _build_arg_parser() args = parser.parse_args() try: devnull = open(os.devnull) subprocess.call("topup", stderr=devnull) except: logging.warning( "topup not found. If executing locally, please install " "the command from the FSL library and make sure it is " "available in your path.") if args.verbose: logging.basicConfig(level=logging.INFO) required_args = [args.in_forward_b0, args.in_reverse_b0] assert_inputs_exist(parser, required_args) assert_outputs_exist(parser, args, [], args.out_b0s) assert_fsl_options_exist(parser, args.topup_options, 'topup') if os.path.splitext(args.out_prefix)[1] != '': parser.error('The prefix must not contain any extension.') b0_img = nib.load(args.in_forward_b0) b0 = b0_img.get_fdata(dtype=np.float32) if len(b0.shape) == 4 and b0.shape[3] > 1: logging.warning("B0 is 4D. To speed up Topup, we recommend " "using only one b0 in both phase encoding " "direction, unless necessary.") elif len(b0.shape) == 3: b0 = b0[..., None] rev_b0_img = nib.load(args.in_reverse_b0) rev_b0 = rev_b0_img.get_fdata(dtype=np.float32) if len(rev_b0.shape) == 4 and rev_b0.shape[3] > 1: logging.warning("Reverse B0 is 4D. To speed up Topup, we " "recommend using only one b0 in both phase " "encoding direction, unless necessary.") elif len(rev_b0.shape) == 3: rev_b0 = rev_b0[..., None] fused_b0s = np.concatenate((b0, rev_b0), axis=-1) fused_b0s_path = os.path.join(args.out_directory, args.out_b0s) nib.save(nib.Nifti1Image(fused_b0s, b0_img.affine), fused_b0s_path) acqparams = create_acqparams(args.readout, args.encoding_direction, b0.shape[-1], rev_b0.shape[-1]) if not os.path.exists(args.out_directory): os.makedirs(args.out_directory) acqparams_path = os.path.join(args.out_directory, args.out_params) np.savetxt(acqparams_path, acqparams, fmt='%1.4f', delimiter=' ') output_path = os.path.join(args.out_directory, args.out_prefix) fout_path = os.path.join(args.out_directory, "correction_field") iout_path = os.path.join(args.out_directory, "corrected_b0s") additional_args = "" if args.topup_options: additional_args = args.topup_options topup = 'topup --imain={0} --datain={1}'\ ' --config={2} --verbose --out={3}'\ ' --fout={4} --iout={5} --subsamp=1 {6}\n'\ .format(fused_b0s_path, acqparams_path, args.config, output_path, fout_path, iout_path, additional_args) if args.out_script: with open("topup.sh", 'w') as f: f.write(topup) else: print(topup)
def main(): parser = _build_arg_parser() args = parser.parse_args() try: devnull = open(os.devnull) subprocess.call(args.eddy_cmd, stderr=devnull) except: logging.warning("{} not found. If executing locally, please install " "the command from the FSL library and make sure it is " "available in your path.".format(args.eddy_cmd)) if args.verbose: logging.basicConfig(level=logging.INFO) required_args = [args.in_dwi, args.in_bvals, args.in_bvecs, args.in_mask] assert_inputs_exist(parser, required_args) assert_fsl_options_exist(parser, args.eddy_options, 'eddy') if os.path.splitext(args.out_prefix)[1] != '': parser.error('The prefix must not contain any extension.') if args.n_reverse and not args.lsr_resampling: logging.warning( 'Multiple reverse phase images supplied, but least-square ' 'resampling is disabled. If the reverse phase image was acquired ' 'with the same sampling as the forward phase image, ' 'use --lsr_resampling for better results from Eddy.') bvals, bvecs = read_bvals_bvecs(args.in_bvals, args.in_bvecs) bvals_min = bvals.min() b0_threshold = args.b0_thr if bvals_min < 0 or bvals_min > b0_threshold: raise ValueError('The minimal b-value is lesser than 0 or greater ' 'than {0}. This is highly suspicious. Please check ' 'your data to ensure everything is correct. ' 'Value found: {1}'.format(b0_threshold, bvals_min)) n_rev = args.n_reverse if args.topup_params: acqparams = np.loadtxt(args.topup_params) if acqparams.shape[0] == 2: index = create_index(bvals, n_rev=n_rev) elif acqparams.shape[0] == np.sum(bvals <= b0_threshold): index = create_multi_topup_index(bvals, 'none', n_rev, b0_threshold) else: b_mask = np.ma.array(bvals, mask=[bvals > b0_threshold]) n_b0_clusters = len(np.ma.clump_unmasked(b_mask[:n_rev])) + \ len(np.ma.clump_unmasked(b_mask[n_rev:])) if acqparams.shape[0] == n_b0_clusters: index = create_multi_topup_index(bvals, 'cluster', n_rev, b0_threshold) else: raise ValueError('Could not determine a valid index file ' 'from the provided acquisition parameters ' 'file: {}'.format(args.topup_params)) else: acqparams = create_acqparams(args.readout, args.encoding_direction, nb_rev_b0s=int(n_rev > 0)) index = create_index(bvals, n_rev=n_rev) bvecs = create_non_zero_norm_bvecs(bvecs) if not os.path.exists(args.out_directory): os.makedirs(args.out_directory) acqparams_path = os.path.join(args.out_directory, 'acqparams.txt') np.savetxt(acqparams_path, acqparams, fmt='%1.4f', delimiter=' ') index_path = os.path.join(args.out_directory, 'index.txt') np.savetxt(index_path, index, fmt='%i', newline=" ") bvecs_path = os.path.join(args.out_directory, 'non_zero_norm.bvecs') np.savetxt(bvecs_path, bvecs.T, fmt="%.8f") additional_args = "" if args.topup is not None: additional_args += "--topup={} ".format(args.topup) if args.slice_drop_correction: additional_args += "--repol " if args.fix_seed: additional_args += "--initrand " if args.lsr_resampling: if len(bvals) - n_rev == n_rev: forward_bb = bvals[:n_rev, None] * bvecs[:n_rev, :] reverse_bb = bvals[n_rev:, None] * bvecs[n_rev:, :] if np.allclose(forward_bb, reverse_bb): additional_args += "--resamp=lsr --fep=true " else: logging.warning('Least-square resampling disabled since ' 'directions in both phase directions differ.') else: logging.warning('Least-square resampling disabled since number of ' 'directions in both phase directions differ.') if args.eddy_options: additional_args += args.eddy_options output_path = os.path.join(args.out_directory, args.out_prefix) eddy = '{0} --imain={1} --mask={2} --acqp={3} --index={4}' \ ' --bvecs={5} --bvals={6} --out={7} --data_is_shelled {8}' \ .format(args.eddy_cmd, args.in_dwi, args.in_mask, acqparams_path, index_path, bvecs_path, args.in_bvals, output_path, additional_args) if args.out_script: with open("eddy.sh", 'w') as f: f.write(eddy) else: print(eddy)
def main(): parser = _build_arg_parser() args = parser.parse_args() try: devnull = open(os.devnull) subprocess.call(args.eddy_cmd, stderr=devnull) except: parser.error("Please download the {} command.".format(args.eddy_cmd)) if args.verbose: logging.basicConfig(level=logging.INFO) required_args = [args.in_dwi, args.in_bvals, args.in_bvecs, args.in_mask] assert_inputs_exist(parser, required_args) assert_fsl_options_exist(parser, args.eddy_options, 'eddy') if os.path.splitext(args.out_prefix)[1] != '': parser.error('The prefix must not contain any extension.') bvals, bvecs = read_bvals_bvecs(args.in_bvals, args.in_bvecs) bvals_min = bvals.min() b0_threshold = args.b0_thr if bvals_min < 0 or bvals_min > b0_threshold: raise ValueError('The minimal b-value is lesser than 0 or greater ' 'than {0}. This is highly suspicious. Please check ' 'your data to ensure everything is correct. ' 'Value found: {1}'.format(b0_threshold, bvals_min)) acqparams = create_acqparams(args.readout, args.encoding_direction, nb_rev_b0s=0) index = create_index(bvals) bvecs = create_non_zero_norm_bvecs(bvecs) if not os.path.exists(args.out_directory): os.makedirs(args.out_directory) acqparams_path = os.path.join(args.out_directory, 'acqparams.txt') np.savetxt(acqparams_path, acqparams, fmt='%1.4f', delimiter=' ') bvecs_path = os.path.join(args.out_directory, 'non_zero_norm.bvecs') np.savetxt(bvecs_path, bvecs.T, fmt="%.8f") index_path = os.path.join(args.out_directory, 'index.txt') np.savetxt(index_path, index, fmt='%i', newline=" ") additional_args = "" if args.topup is not None: additional_args += "--topup={} ".format(args.topup) if args.slice_drop_correction: additional_args += "--repol " if args.fix_seed: additional_args += "--initrand " if args.eddy_options: additional_args += args.eddy_options output_path = os.path.join(args.out_directory, args.out_prefix) eddy = '{0} --imain={1} --mask={2} --acqp={3} --index={4}' \ ' --bvecs={5} --bvals={6} --out={7} --data_is_shelled {8}' \ .format(args.eddy_cmd, args.in_dwi, args.in_mask, acqparams_path, index_path, bvecs_path, args.in_bvals, output_path, additional_args) if args.out_script: with open("eddy.sh", 'w') as f: f.write(eddy) else: print(eddy)
def main(): parser = _build_arg_parser() args = parser.parse_args() if args.verbose: logging.basicConfig(level=logging.INFO) required_args = [ args.in_dwi, args.in_bvals, args.in_bvecs, args.in_reverse_b0 ] assert_inputs_exist(parser, required_args) assert_outputs_exist(parser, args, [], args.out_b0s) assert_fsl_options_exist(parser, args.topup_options, 'topup') if os.path.splitext(args.out_prefix)[1] != '': parser.error('The prefix must not contain any extension.') bvals, bvecs = read_bvals_bvecs(args.in_bvals, args.in_bvecs) bvals_min = bvals.min() # TODO refactor this b0_threshold = args.b0_thr if bvals_min < 0 or bvals_min > b0_threshold: raise ValueError('The minimal b-value is lesser than 0 or greater ' 'than {0}. This is highly suspicious. Please check ' 'your data to ensure everything is correct. ' 'Value found: {1}'.format(b0_threshold, bvals_min)) rev_b0_img = nib.load(args.in_reverse_b0) rev_b0 = rev_b0_img.get_fdata(dtype=np.float32) if len(rev_b0.shape) == 4: logging.warning("Reverse B0 is 4D. To speed up Topup, the mean of all " "reverse B0 will be taken.") rev_b0 = np.mean(rev_b0, axis=3) gtab = gradient_table(bvals, bvecs, b0_threshold=b0_threshold) dwi_image = nib.load(args.in_dwi) dwi = dwi_image.get_fdata(dtype=np.float32) b0 = dwi[..., gtab.b0s_mask] if b0.shape[3] > 1: logging.warning("More than one B0 was found. To speed up Topup, " "the mean of all B0 will be taken.") b0 = np.mean(b0, axis=3) else: b0 = np.squeeze(b0, axis=3) fused_b0s = np.zeros(b0.shape + (2, )) fused_b0s[..., 0] = b0 fused_b0s[..., 1] = rev_b0 fused_b0s_path = os.path.join(args.out_directory, args.out_b0s) nib.save(nib.Nifti1Image(fused_b0s, rev_b0_img.affine), fused_b0s_path) acqparams = create_acqparams(args.readout, args.encoding_direction) if not os.path.exists(args.out_directory): os.makedirs(args.out_directory) acqparams_path = os.path.join(args.out_directory, 'acqparams.txt') np.savetxt(acqparams_path, acqparams, fmt='%1.4f', delimiter=' ') output_path = os.path.join(args.out_directory, args.out_prefix) fout_path = os.path.join(args.out_directory, "correction_field") iout_path = os.path.join(args.out_directory, "corrected_b0s") additional_args = "" if args.topup_options: additional_args = args.topup_options topup = 'topup --imain={0} --datain={1}'\ ' --config={2} --verbose --out={3}'\ ' --fout={4} --iout={5} --subsamp=1 {6}\n'\ .format(fused_b0s_path, acqparams_path, args.config, output_path, fout_path, iout_path, additional_args) if args.out_script: with open("topup.sh", 'w') as f: f.write(topup) else: print(topup)