Exemple #1
0
def main():
    # :: handle program parameters
    arg_parser = handle_arg()
    args = arg_parser.parse_args()
    # fix verbosity in case of 'quiet'
    if args.quiet:
        args.verbose = VERB_LVL['none']
    # :: print debug info
    if args.verbose >= VERB_LVL['debug']:
        arg_parser.print_help()
        msg('\nARGS: ' + str(vars(args)), args.verbose, VERB_LVL['debug'])

    if not args.name:
        msg('Choose your playground:')
        msg('Available playgrounds: {AVAILABLES}'.format_map(globals()))
        args.name = input(': ')
    if args.name in AVAILABLES:
        numex.interactive_tk_mpl.plotting(globals()[PREFIX + args.name],
                                          PARAMS[args.name],
                                          title=TITLE_BASE + ' - ' +
                                          TITLE[args.name],
                                          about=__doc__)
        elapsed(__file__[len(PATH['base']) + 1:])
        msg(report())
    else:
        msg(fmtm('Plot `{args.name}` not valid.'))
Exemple #2
0
def dphs_to_phs(dphs_arr, tis, phs0_arr=0, time_units='ms'):
    """
    Calculate the phase variation from phase data.

    Args:
        dphs_arr (np.ndarray): The input array in rad.
            The sampling time Ti varies in the last dimension.
        tis (Iterable|int|float): The sampling times Ti in time units.
            The number of points will match the last shape size of `phs_arr`.
        phs0_arr (np.ndarray|int|float): The initial phase offset.
            If int or float, a constant offset is used.
        time_units (str|float|int): Units of measurement of Ti.
            If str, any valid SI time unit (e.g. `ms`, `ns`) will be accepted.
            If int or float, the conversion factor will be multiplied to `ti`.

    Returns:
        phs_arr (np.ndarray): The phase array in rad.
    """
    units_factor = 1
    if isinstance(time_units, str) and 's' in time_units:
        prefix, _ = time_units.split('s', 1)
        units_factor = fc.prefix_to_factor(prefix)
    elif isinstance(time_units, (int, float)):
        units_factor = time_units
    else:
        warnings.warn(fmtm('Invalid units `{time_units}`. Ignored.'))

    shape = dphs_arr.shape
    tis = np.array(fc.auto_repeat(tis, 1)) * units_factor
    tis = tis.reshape((1, ) * len(shape) + (-1, ))
    dphs_arr = dphs_arr.reshape(shape + (1, ))
    return dphs_arr * tis + phs0_arr
Exemple #3
0
def cx2_to_dphs(arr1,
                arr2,
                d_ti,
                unwrap_method='laplacian_c',
                unwrap_kws=None,
                time_units='ms'):
    """
    Calculate the phase variation from two complex data.

    Args:
        arr1 (np.ndarray): The phase array for sampling time 1 in arb. units.
            Arbitrary units are accepted, will be automatically converted to
            radians under the assumption that data is wrapped.
            Do not provide unwrapped data.
            Shape must match that of `arr2`.
        arr2 (np.ndarray): The phase array for sampling time 2 in arb. units.
            Arbitrary units are accepted, will be automatically converted to
            radians under the assumption that data is wrapped.
            Do not provide unwrapped data.
            Shape must match that of `arr1`.
        d_ti (int|float): The sampling time differenct in time units.
        unwrap_method (str|None): The unwrap method.
            See `pymrt.recipes.phs.unwrap()` for details.
        unwrap_kws (Mappable|None): Keyword arguments for `unwrap()`.
        time_units (str|float|int): Units of measurement of Ti.
            If str, any valid SI time unit (e.g. `ms`, `ns`) will be accepted.
            If int or float, the conversion factor will be multiplied to `ti`.

    Returns:
        dphs_arr (np.ndarray): The phase variation in rad/s.
    """
    units_factor = 1
    if isinstance(time_units, str) and 's' in time_units:
        prefix, _ = time_units.split('s', 1)
        units_factor = fc.prefix_to_factor(prefix)
    elif isinstance(time_units, (int, float)):
        units_factor = time_units
    else:
        warnings.warn(fmtm('Invalid units `{time_units}`. Ignored.'))

    dphs_arr = arr1 * arr2.conj()
    dphs_arr = np.arctan2(np.imag(dphs_arr), np.real(dphs_arr))

    if unwrap is not None:
        dphs_arr = unwrap(dphs_arr, unwrap_method, unwrap_kws)

    return dphs_arr / (d_ti * units_factor)
Exemple #4
0
def handle_arg():
    """
    Handle command-line application arguments.
    """
    # :: Create Argument Parser
    arg_parser = argparse.ArgumentParser(
        description=__doc__,
        epilog=fmtm('v.{version} - {author}\n{license}', INFO),
        formatter_class=argparse.RawDescriptionHelpFormatter)
    # :: Add POSIX standard arguments
    arg_parser.add_argument(
        '--ver',
        '--version',
        version=fmt(
            '%(prog)s - ver. {version}\n{}\n{copyright} {author}\n{notice}',
            next(line for line in __doc__.splitlines() if line), **INFO),
        action='version')
    arg_parser.add_argument(
        '-v',
        '--verbose',
        action='count',
        default=D_VERB_LVL,
        help='increase the level of verbosity [%(default)s]')
    arg_parser.add_argument(
        '-q',
        '--quiet',
        action='store_true',
        help='override verbosity settings to suppress output [%(default)s]')
    # :: Add additional arguments
    arg_parser.add_argument('--t1',
                            metavar='X',
                            type=float,
                            default=1000,
                            help='set the T1 value in ms [%(default)s]')
    arg_parser.add_argument('--tr',
                            metavar='X',
                            type=float,
                            default=100,
                            help='set the TR value in ms [%(default)s]')
    arg_parser.add_argument('--fa',
                            metavar='X',
                            type=float,
                            default=None,
                            help='set the FA value in deg [%(default)s]')
    return arg_parser
Exemple #5
0
def handle_arg():
    """
    Handle command-line application arguments.
    """
    # :: Create Argument Parser
    arg_parser = argparse.ArgumentParser(
        description=__doc__,
        epilog=fmtm('v.{version} - {author}\n{license}', INFO),
        formatter_class=argparse.RawDescriptionHelpFormatter)
    # :: Add POSIX standard arguments
    arg_parser.add_argument(
        '--ver',
        '--version',
        version=fmt(
            '%(prog)s - ver. {version}\n{}\n{copyright} {author}\n{notice}',
            next(line for line in __doc__.splitlines() if line), **INFO),
        action='version')
    arg_parser.add_argument(
        '-v',
        '--verbose',
        action='count',
        default=D_VERB_LVL,
        help='increase the level of verbosity [%(default)s]')
    arg_parser.add_argument(
        '-q',
        '--quiet',
        action='store_true',
        help='override verbosity settings to suppress output [%(default)s]')
    # :: Add additional arguments
    arg_parser.add_argument('-f',
                            '--force',
                            action='store_true',
                            help='force new processing [%(default)s]')
    arg_parser.add_argument('-d',
                            '--dir',
                            metavar='DIR',
                            default='.',
                            help='set working directory [%(default)s]')
    arg_parser.add_argument('-e',
                            '--extradir',
                            metavar='FOLDER',
                            default='nifti',
                            help='set output subdirectory [%(default)s]')
    return arg_parser
Exemple #6
0
def threshold_to_mask(arr, threshold, comparison='>'):
    """
    Apply the specified threshold to the array.

    Args:
        arr (np.ndarray): Input array for the masking.
        threshold (int|float): Value for the threshold.
        comparison (str): A string representing the numeric relationship
            Accepted values are: ['==', '!=', '>', '<', '>=', '<=']

    Returns:
        mask (np.ndarray[bool]): Mask for which comparison is True.
    """
    # for security reasons comparison is checked before eval
    comparisons = ('==', '!=', '>', '<', '>=', '<=')
    if comparison in comparisons:
        mask = eval('arr {c} threshold'.format(c=comparison))
    else:
        raise ValueError(
            fmtm('valid comparisons are: {comparisons} (given: {comparison})'))
    return mask
Exemple #7
0
def simple_filter_1_x(in_filepath,
                      out_basepath,
                      func,
                      out_filename_template='{base}_{name}{ext}',
                      *_args,
                      **_kws):
    """
    Interface to simplified n-m filter.
    filter(in_filepaths) -> out_filepaths

    Args:
        in_filepath (str): Input file path
            The metadata information is taken from the input.
        out_basepath (str): Base output directory path.
            Additional subdirectories can be specified through the
            `out_filename_template` parameter.
        out_filename_template (str):
            If subdirectories do not exists, they are created.
            The following substitution are valid:
             - `{path}`: the input directory path.
             - `{base}`: the input file name without extension.
             - `{ext}`: the input file extension.
             - `{name}`: the result identifier from the computing function.
        func (callable): Filtering function (arr: ndarray)
            func(list[arr], *_args, *kws) -> list[ndarray]
        *_args: Positional arguments of the filtering function
        **_kws: Keyword arguments of the filtering function

    Returns:
        None.
    """
    arr, meta = load(in_filepath, meta=True)
    results = func(arr, *_args, **_kws)
    path, base, ext = fc.split_path(in_filepath)
    for i, (name, arr) in enumerate(results.items()):
        out_filepath = os.path.join(out_basepath, fmtm(out_filename_template))
        out_dirpath = os.path.dirname(out_filepath)
        if not os.path.isdir(out_dirpath):
            os.makedirs(out_dirpath)
        save(out_filepath, arr, **meta)
Exemple #8
0
def handle_arg():
    """
    Handle command-line application arguments.
    """
    # :: Create Argument Parser
    arg_parser = argparse.ArgumentParser(
        description=__doc__,
        epilog=fmtm('v.{version} - {author}\n{license}', INFO),
        formatter_class=argparse.RawDescriptionHelpFormatter)
    # :: Add POSIX standard arguments
    arg_parser.add_argument(
        '--ver',
        '--version',
        version=fmt(
            '%(prog)s - ver. {version}\n{}\n{copyright} {author}\n{notice}',
            next(line for line in __doc__.splitlines() if line), **INFO),
        action='version')
    arg_parser.add_argument(
        '-v',
        '--verbose',
        action='count',
        default=D_VERB_LVL,
        help='increase the level of verbosity [%(default)s]')
    arg_parser.add_argument(
        '-q',
        '--quiet',
        action='store_true',
        help='override verbosity settings to suppress output [%(default)s]')
    # :: Add additional arguments
    arg_parser.add_argument(
        '-n',
        '--name',
        metavar='NAME',
        default=None,
        choices=AVAILABLES,
        help='playground selection (from: %(choices)s)  [%(default)s]')
    return arg_parser
Exemple #9
0
def noise(raw_arr,
          reco_func,
          reco_args=None,
          reco_kws=None,
          noise_level=1,
          num=64,
          verbose=D_VERB_LVL):
    """
    Estimate the noise for reco using a pseudo-multi-replica approach.

    This a Monte Carlo method, effectively consisting of computing the
    standard deviation for multiple instances of the image reconstructed after
    the addition of white noise in the complex raw data.

    This is can be used to compute the signal-to-noise (SNR) and the
    geometric noise amplification factor (g-factor).

    The SNR can be computed by:
    snr = reco_arr / noise_arr

    with:
    reco_arr = reco_func(raw_arr, *reco_args, **reco_kws)

    Args:
        raw_arr (np.ndarray): The input raw data as acquired (k-space).
        reco_func (callable): The reconstruction function.
            Must accept the raw data array as first argument.
        reco_args (Iterable|None): Positional arguments for `reco_func`.
        reco_kws (Mappable|None): Keyword arguments for `reco_func`.
        noise_level (int|float|str|None): The noise level.
            This is used to determine the st.dev of the Gaussian noise
            being added at each iteration.
            If int or float, the value is the st.dev of the Gaussian noise.
            If str and the value is a percentage, the st.dev is computed as
            the peak-to-peak value multiplied by `noise_level` percentage
            (the peak-to-peak value is the maximum of the peak-to-peak value
            for real and imaginary data separately).
            If None, the noise level is estimated using
             `pymrt.correction.estimate_noise_sigma()`.
        num (int): The number of repetitions.
        verbose (int): Set level of verbosity.

    Returns:
        result (tuple): The tuple
            contains:
            - noise_arr (np.ndarray): The st.dev. of noised reconstructions.
            - reco_arr (np.ndarray): The reco from data without extra noise.

    """
    reco_args = tuple(reco_args) if reco_args else ()
    reco_kws = dict(reco_kws) if reco_kws else {}

    # noise-less reco
    reco_arr = reco_func(raw_arr, *reco_args, **reco_kws)

    # compute desired noise std
    if noise_level is None:
        noise_std_val = mrt.correction.estimate_noise_sigma(raw_arr)
    elif isinstance(noise_level, (int, float)):
        noise_std_val = noise_level
    else:
        noise_std_val = fc.to_percent(noise_level)
        if noise_std_val:
            cx_ptp = max(np.ptp(np.real(raw_arr)), np.ptp(np.imag(raw_arr)))
            noise_std_val = cx_ptp * noise_std_val
        else:
            noise_std_val = 1
    msg(fmtm('Noise St.Dev.: {noise_std_val} (Level: {noise_level})'), verbose,
        VERB_LVL['debug'])

    mean_noised_arr = np.zeros_like(reco_arr, dtype=float)
    sosd_noised_arr = np.zeros_like(reco_arr, dtype=float)
    for i in range(num):
        msg(fmtm('Replica #{i}'), verbose, VERB_LVL['debug'])
        noise_raw_arr = np.random.normal(0, noise_std_val, raw_arr.shape)
        noised_arr = reco_func(raw_arr + noise_raw_arr, *reco_args, **reco_kws)
        mean_noised_arr, sosd_noised_arr, _ = fc.next_mean_and_sosd(
            np.real(noised_arr), mean_noised_arr, sosd_noised_arr, i)
    noise_arr = fc.sosd2stdev(sosd_noised_arr, num)
    return noise_arr, reco_arr
Exemple #10
0
def handle_arg():
    """
    Handle command-line application arguments.
    """
    # :: Create Argument Parser
    arg_parser = argparse.ArgumentParser(
        description=__doc__,
        epilog=fmtm('v.{version} - {author}\n{license}', INFO),
        formatter_class=argparse.RawDescriptionHelpFormatter)
    # :: Add POSIX standard arguments
    arg_parser.add_argument(
        '--ver',
        '--version',
        version=fmt(
            '%(prog)s - ver. {version}\n{}\n{copyright} {author}\n{notice}',
            next(line for line in __doc__.splitlines() if line), **INFO),
        action='version')
    arg_parser.add_argument(
        '-v',
        '--verbose',
        action='count',
        default=D_VERB_LVL,
        help='increase the level of verbosity [%(default)s]')
    arg_parser.add_argument(
        '-q',
        '--quiet',
        action='store_true',
        help='override verbosity settings to suppress output [%(default)s]')
    # :: Add additional arguments
    arg_parser.add_argument('-f',
                            '--force',
                            action='store_true',
                            help='force new processing [%(default)s]')
    arg_parser.add_argument('-d',
                            '--dirpath',
                            metavar='DIR',
                            default='.',
                            help='set working directory [%(default)s]')
    arg_parser.add_argument('-n',
                            '--val_name',
                            metavar='NAME',
                            default=None,
                            help='set values name ( [%(default)s]')
    arg_parser.add_argument('-a',
                            '--val_interval',
                            metavar=('MIN', 'MAX'),
                            type=float,
                            nargs=2,
                            default=None,
                            help='set interval of values [%(default)s]')
    arg_parser.add_argument('-u',
                            '--val_units',
                            metavar='UNITS',
                            default=None,
                            help='set units for values [%(default)s]')
    arg_parser.add_argument('-m',
                            '--mask_filepath',
                            metavar='FILE',
                            default=None,
                            help='set exact mask file [%(default)s]')
    arg_parser.add_argument(
        '--reg_ref_ext',
        metavar='FILE_EXT',
        default=pml.EXT['reg_ref'],
        help='file extension of registration reference flag [%(default)s]')
    arg_parser.add_argument(
        '--corr_ref_ext',
        metavar='FILE_EXT',
        default=pml.EXT['corr_ref'],
        help='file extension of correlation reference flag [%(default)s]')
    arg_parser.add_argument(
        '--tmp_dir',
        metavar='SUBDIR',
        default='tmp',
        help='subdirectory where to store temporary files [%(default)s]')
    arg_parser.add_argument(
        '--reg_dir',
        metavar='SUBDIR',
        default='reg',
        help='subdirectory where to store registration files [%(default)s]')
    arg_parser.add_argument(
        '--msk_dir',
        metavar='SUBDIR',
        default='msk',
        help='subdirectory where to store masking files [%(default)s]')
    arg_parser.add_argument(
        '--cmp_dir',
        metavar='SUBDIR',
        default='cmp',
        help='subdirectory where to store comparing files [%(default)s]')
    arg_parser.add_argument(
        '--fig_dir',
        metavar='SUBDIR',
        default='fig',
        help='subdirectory where to store figures [%(default)s]')
    return arg_parser
Exemple #11
0
def handle_arg():
    """
    Handle command-line application arguments.
    """
    # :: Create Argument Parser
    arg_parser = argparse.ArgumentParser(
        description=__doc__,
        epilog=fmtm('v.{version} - {author}\n{license}', INFO),
        formatter_class=argparse.RawDescriptionHelpFormatter)
    # :: Add POSIX standard arguments
    arg_parser.add_argument(
        '--ver',
        '--version',
        version=fmt(
            '%(prog)s - ver. {version}\n{}\n{copyright} {author}\n{notice}',
            next(line for line in __doc__.splitlines() if line), **INFO),
        action='version')
    arg_parser.add_argument(
        '-v',
        '--verbose',
        action='count',
        default=D_VERB_LVL,
        help='increase the level of verbosity [%(default)s]')
    arg_parser.add_argument(
        '-q',
        '--quiet',
        action='store_true',
        help='override verbosity settings to suppress output [%(default)s]')
    # :: Add additional arguments
    arg_parser.add_argument('-f',
                            '--force',
                            action='store_true',
                            help='force new processing [%(default)s]')
    arg_parser.add_argument(
        '-i',
        '--in_filepaths',
        metavar=('MAG_FILE', 'PHS_FILE'),
        nargs=2,
        default=('mag_coils.nii.gz', 'phs_coils.nii.gz'),
        help='set input magnitude and phase filepaths [%(default)s]')
    arg_parser.add_argument(
        '-o',
        '--out_filepaths',
        metavar=('MAG_FILE', 'PHS_FILE'),
        nargs=2,
        default=('mag.nii.gz', 'phs.nii.gz'),
        help='set output magnitude and phase filepaths [%(default)s]')
    arg_parser.add_argument(
        '-p',
        '--q_filepath',
        metavar='FILE',
        default=None,
        help='set output quality metric filepath [%(default)s]')
    arg_parser.add_argument('-m',
                            '--method',
                            metavar='STR',
                            default='block_adaptive_iter',
                            help=' [%(default)s]')
    arg_parser.add_argument(
        '-mk',
        '--method_kws',
        metavar='STR',
        default=None,
        help='Additional keyword parameters for the method [%(default)s]')
    arg_parser.add_argument('-c',
                            '--compression',
                            metavar='STR',
                            default='compress_svd',
                            help=' [%(default)s]')
    arg_parser.add_argument(
        '-ck',
        '--compression_kws',
        metavar='STR',
        default=None,
        help='Additional keyword parameters for the compression [%(default)s]')
    arg_parser.add_argument(
        '-a',
        '--coil_axis',
        metavar='N',
        default=-1,
        help='Axis along which the single coils are stored [%(default)s]')
    arg_parser.add_argument(
        '-s',
        '--split_axis',
        metavar='N',
        default=None,
        help='Axis along which input shall be split [%(default)s]')
    return arg_parser
Exemple #12
0
def batch_extract(
        dirpath,
        out_filename='niz/{scan_num}__{acq_method}_{scan_name}_{reco_flag}',
        out_dirpath=None,
        custom_reco=None,
        custom_reco_kws=None,
        fid_name='fid',
        dseq_name='2dseq',
        acqp_name='acqp',
        method_name='method',
        reco_name='reco',
        allowed_ext=('', 'gz'),
        force=False,
        verbose=D_VERB_LVL):
    """
    Extract images from experiment folder.

    EXPERIMENTAL!

    Args:
        dirpath (str):
        out_filename (str|None):
        out_dirpath (str|None):
        custom_reco (str|None):
            Determines how results will be saved.
            Accepted values are:
             - 'mag_phs': saves magnitude and phase.
             - 're_im': saves real and imaginary parts.
             - 'cx': saves the complex data.
        custom_reco_kws (Mappable|None):
        fid_name ():
        dseq_name ():
        acqp_name ():
        method_name ():
        reco_name ():
        allowed_ext ():
        force ():
        verbose ():

    Returns:

    """
    text = '\n'.join(
        ('EXPERIMENTAL!', 'Use at your own risk!', 'Known issues:',
         ' - orientation not adjusted to method (i.e. 0->RO, 1->PE, 2->SL)',
         ' - FOV is centered out', ' - voxel size is not set', ''))
    warnings.warn(text)

    if allowed_ext is None:
        allowed_ext = ''
    elif isinstance(allowed_ext, str):
        allowed_ext = (allowed_ext, )
    fid_filepaths = sorted(
        fc.flistdir(_to_patterns(fid_name, allowed_ext), dirpath))

    for fid_filepath in sorted(fid_filepaths):
        msg('FID: {}'.format(fid_filepath), verbose, D_VERB_LVL)
        fid_dirpath = os.path.dirname(fid_filepath)
        if out_dirpath is None:
            out_dirpath = dirpath
        out_filepath = os.path.join(out_dirpath, out_filename)

        acqp_filepath = _get_single(fid_dirpath, acqp_name, allowed_ext)
        method_filepath = _get_single(fid_dirpath, method_name, allowed_ext)

        dseq_filepaths = sorted(
            fc.flistdir(_to_patterns(dseq_name, allowed_ext), fid_dirpath))
        reco_filepaths = sorted(
            fc.flistdir(_to_patterns(reco_name, allowed_ext), fid_dirpath))

        acqp_s, acqp, acqp_c = jcampdx.read(acqp_filepath)
        method_s, method, method_c = jcampdx.read(method_filepath)
        scan_num, sample_id = _get_scan_num_sample_id(acqp_c)
        scan_name = fc.safe_filename(acqp['ACQ_scan_name'])
        acq_method = fc.safe_filename(acqp['ACQ_method'])
        reco_flag = mrt.naming.NEW_RECO_ID

        if custom_reco:
            load_info = _get_load_bin_info_fid(acqp, method)

            if custom_reco == 'cx':
                reco_flag = mrt.naming.ITYPES['cx']
                cx_filepath = fc.change_ext(fmtm(out_filepath),
                                            mrt.util.EXT['niz'])
                if not os.path.isdir(os.path.dirname(cx_filepath)):
                    os.makedirs(os.path.dirname(cx_filepath))

                if fc.check_redo(
                    [fid_filepath, acqp_filepath, method_filepath],
                    [cx_filepath], force):
                    arr = _load_bin(fid_filepath, **load_info)
                    arr = _reco_from_fid(arr, acqp, method, verbose=verbose)
                    mrt.input_output.save(cx_filepath, arr)
                    msg('CX:  {}'.format(os.path.basename(cx_filepath)),
                        verbose, D_VERB_LVL)

            elif custom_reco == 'mag_phs':
                reco_flag = mrt.naming.ITYPES['mag']
                mag_filepath = fc.change_ext(fmtm(out_filepath),
                                             mrt.util.EXT['niz'])
                if not os.path.isdir(os.path.dirname(mag_filepath)):
                    os.makedirs(os.path.dirname(mag_filepath))

                reco_flag = mrt.naming.ITYPES['phs']
                phs_filepath = fc.change_ext(fmtm(out_filepath),
                                             mrt.util.EXT['niz'])
                if not os.path.isdir(os.path.dirname(phs_filepath)):
                    os.makedirs(os.path.dirname(phs_filepath))

                if fc.check_redo(
                    [fid_filepath, acqp_filepath, method_filepath],
                    [mag_filepath, phs_filepath], force):
                    reco_flag = mrt.naming.ITYPES['mag']

                    arr = _load_bin(fid_filepath, **load_info)
                    arr = _reco_from_fid(arr, acqp, method, verbose=verbose)
                    mrt.input_output.save(mag_filepath, np.abs(arr))
                    msg('MAG: {}'.format(os.path.basename(mag_filepath)),
                        verbose, D_VERB_LVL)
                    mrt.input_output.save(phs_filepath, np.angle(arr))
                    msg('PHS: {}'.format(os.path.basename(phs_filepath)),
                        verbose, D_VERB_LVL)

            elif custom_reco == 're_im':
                reco_flag = mrt.naming.ITYPES['re']
                re_filepath = fc.change_ext(fmtm(out_filepath),
                                            mrt.util.EXT['niz'])
                if not os.path.isdir(os.path.dirname(re_filepath)):
                    os.makedirs(os.path.dirname(re_filepath))

                reco_flag = mrt.naming.ITYPES['im']
                im_filepath = fc.change_ext(fmtm(out_filepath),
                                            mrt.util.EXT['niz'])
                if not os.path.isdir(os.path.dirname(im_filepath)):
                    os.makedirs(os.path.dirname(im_filepath))

                if fc.check_redo(
                    [fid_filepath, acqp_filepath, method_filepath],
                    [re_filepath, im_filepath], force):
                    arr = _load_bin(fid_filepath, **load_info)
                    arr = _reco_from_fid(arr, acqp, method, verbose=verbose)
                    mrt.input_output.save(re_filepath, np.abs(arr))
                    msg('RE: {}'.format(os.path.basename(re_filepath)),
                        verbose, D_VERB_LVL)
                    mrt.input_output.save(im_filepath, np.angle(arr))
                    msg('IM: {}'.format(os.path.basename(im_filepath)),
                        verbose, D_VERB_LVL)

        else:
            text = 'Voxel data and shapes may be incorrect.'
            warnings.warn(text)
            for dseq_filepath, reco_filepath \
                    in zip(dseq_filepaths, reco_filepaths):
                reco_s, reco, reco_c = jcampdx.read(reco_filepath)
                reco_flag = _get_reco_num(reco_c)

                cx_filepath = fc.change_ext(fmtm(out_filepath),
                                            mrt.util.EXT['niz'])
                if not os.path.isdir(os.path.dirname(cx_filepath)):
                    os.makedirs(os.path.dirname(cx_filepath))

                load_info = _get_load_bin_info_reco(reco, method)

                if fc.check_redo([dseq_filepath, reco_filepath], [cx_filepath],
                                 force):
                    arr = _load_bin(dseq_filepath, **load_info)
                    arr = _reco_from_bin(arr, reco, method, verbose=verbose)
                    mrt.input_output.save(cx_filepath, arr)
                    msg('NIZ: {}'.format(os.path.basename(cx_filepath)),
                        verbose, D_VERB_LVL)
Exemple #13
0
def auto_convert(filepaths,
                 out_template='{basepath}__{name}.nii.gz',
                 save_kws=None,
                 on_exist='unique',
                 verbose=D_VERB_LVL):
    """
    Automatically convert MATLAB data to PyMRT's standard format (NIfTI).

    Args:
        filepaths (Iterable[str]): List of filepaths to convert.
            Can be combined with file listing functions from `pymrt.utils`,
            e.g. `iflistdir()`, `flistdir()`, `listdir()` (directly) or
            `iwalk2()`, `walk2()` (indirectly).
        out_template (str): Template for the output filepath.
            The following variables are available for interpolation:
             - `dirpath`: The directory of the input.
             - `base`: The input base file name without extension.
             - `ext`: The input file extension (with leading separator).
             - `basepath`: The input filepath without extension.
             - `name`: The name of the variable as stored in the MATLAB file.
        save_kws (Mappable|None): Keyword parameters for `input_output.save()`.
        on_exist (str): Determine what to do if output exists.
            Accepted values are:
             - 'unique': Generate a new unique filepath.
             - 'skip': Skip saving the data.
             - 'overwrite': Overwrites the data onto existing filepath!
        verbose (int): Set level of verbosity.

    Returns:
        None.
    """
    if save_kws is None:
        save_kws = {}
    on_exist = on_exist.lower()
    for in_filepath in filepaths:
        if os.path.isfile(in_filepath):
            msg('Loading: {}'.format(in_filepath), verbose, D_VERB_LVL)
            for name, arr in read(in_filepath, verbose=verbose).items():
                dirpath, base, ext = fc.split_path(in_filepath)
                basepath = os.path.join(dirpath, base)
                out_filepath = fmtm(out_template)
                do_save = True
                if os.path.exists(out_filepath):
                    if on_exist == 'skip':
                        do_save = False
                    elif on_exist == 'overwrite':
                        pass
                    else:
                        if on_exist != 'unique':
                            text = 'Unknown value `{}` for `on_exist`. ' \
                                   'Default to `unique`.'
                            warnings.warn(text)
                        out_filepath = fc.next_filepath(out_filepath)

                if do_save:
                    msg('Saving: {}'.format(out_filepath), verbose, D_VERB_LVL)
                    try:
                        mrt.input_output.save(out_filepath, arr, **save_kws)
                    except ValueError:
                        msg('W: Saving failed!'.format(out_filepath), verbose,
                            D_VERB_LVL)
                else:
                    msg('Skip: {}'.format(out_filepath), verbose, D_VERB_LVL)
Exemple #14
0
def phs_to_dphs(phs_arr,
                tis,
                tis_mask=None,
                unwrapping='laplacian',
                unwrapping_kws=None,
                time_units='ms'):
    """
    Calculate the phase variation from phase data.

    Args:
        phs_arr (np.ndarray): The input array in arb. units.
            The sampling time Ti varies in the last dimension.
            Arbitrary units are accepted, will be automatically converted to
            radians under the assumption that data is wrapped.
            Do not provide unwrapped data.
        tis (Iterable|int|float): The sampling times Ti in time units.
            The number of points must match the last shape size of arr.
        tis_mask (Iterable[bool]|None): Determine the sampling times Ti to use.
            If None, all will be used.
        unwrapping (str|None): The unwrap method.
            If None, no unwrap is performed.
            If str, perform unwrap using `pymrt.recipes.phs.unwrap()`.
            Accepted values are:
             - 'auto': uses the best method for the given input.
               If `len(tis) == 1`
               use `pymrt.recipes.phs.unwrap_sorting_path()`, otherwise
               use `pymrt.recipes.phs.unwrap_laplacian()`.
             - 'laplacian': use `pymrt.recipes.phs.unwrap_laplacian()`.
             - 'sorting_path': use `pymrt.recipes.phs.unwrap_sorting_path()`.
        unwrapping_kws (Mappable|None): Additional keyword arguments.
            These are passed to `pymrt.recipes.phs.unwrap()`.
        time_units (str|float|int): Units of measurement of Ti.
            If str, any valid SI time unit (e.g. `ms`, `ns`) will be accepted.
            If int or float, the conversion factor will be multiplied to `ti`.

    Returns:
        dphs_arr (np.ndarray): The phase variation in rad/s.
    """
    units_factor = 1
    if isinstance(time_units, str) and 's' in time_units:
        prefix, _ = time_units.split('s', 1)
        units_factor = fc.prefix_to_factor(prefix)
    elif isinstance(time_units, (int, float)):
        units_factor = time_units
    else:
        warnings.warn(fmtm('Invalid units `{time_units}`. Ignored.'))

    tis = np.array(fc.auto_repeat(tis, 1)) * units_factor

    if unwrapping is not None:
        phs_arr = unwrap(phs_arr, unwrapping, unwrapping_kws)

    if len(tis) == 1:
        dphs_arr = phs_arr / tis[0]
    else:
        dphs_arr = \
            phs_to_dphs_multi(
                phs_arr, tis, tis_mask, poly_deg=1, time_units='s') \
                ['dphs_1'][..., 0]

    return dphs_arr
Exemple #15
0
def handle_arg():
    """
    Handle command-line application arguments.
    """
    # :: Create Argument Parser
    arg_parser = argparse.ArgumentParser(
        description=__doc__,
        epilog=fmtm('v.{version} - {author}\n{license}', INFO),
        formatter_class=argparse.RawDescriptionHelpFormatter)
    # :: Add POSIX standard arguments
    arg_parser.add_argument(
        '--ver',
        '--version',
        version=fmt(
            '%(prog)s - ver. {version}\n{}\n{copyright} {author}\n{notice}',
            next(line for line in __doc__.splitlines() if line), **INFO),
        action='version')
    arg_parser.add_argument(
        '-v',
        '--verbose',
        action='count',
        default=D_VERB_LVL,
        help='increase the level of verbosity [%(default)s]')
    arg_parser.add_argument(
        '-q',
        '--quiet',
        action='store_true',
        help='override verbosity settings to suppress output [%(default)s]')
    # :: Add additional arguments
    arg_parser.add_argument('-f',
                            '--force',
                            action='store_true',
                            help='force new processing [%(default)s]')
    arg_parser.add_argument('-i',
                            '--input',
                            metavar='DIR',
                            default='.',
                            help='set input directory [%(default)s]')
    arg_parser.add_argument('-o',
                            '--output',
                            metavar='DIR',
                            default='.',
                            help='set output directory [%(default)s]')
    arg_parser.add_argument(
        '-r',
        '--recursive',
        action='store_true',
        help='Force descending into subdirectories [%(default)s]')
    arg_parser.add_argument('-e',
                            '--meta_subpath',
                            metavar='DIR',
                            default=pmc.META_EXT,
                            help='set extra input subdirectory [%(default)s]')
    arg_parser.add_argument('-a',
                            '--data_subpath',
                            metavar='DIR',
                            default='nii',
                            help='set extra input subdirectory [%(default)s]')
    arg_parser.add_argument(
        '-m',
        '--method',
        metavar='METHOD',
        default='generic',
        help='set computation target and method [%(default)s]')
    arg_parser.add_argument(
        '-n',
        '--options',
        metavar='OPTS',
        default='{}',
        help='set JSON-formatted options dictionary [%(default)s]')
    return arg_parser
Exemple #16
0
def to_image(html_code,
             save_filepath,
             method=None,
             html_filepath=True,
             img_type='png',
             dpi=96,
             trim=True,
             force=False,
             verbose=D_VERB_LVL):
    """
    Render a HTML page to an image.

    Args:
        html_code (str): The HTML code to render.
        save_filepath (str): The image file.
        method (str|None): The HTML-to-image method
        html_filepath (str|bool|None): The intermediate HTML file.
        img_type (str): The image type / extension of the output.
        dpi (int|float): The image density of the output.
        trim (bool): Remove borders from the image.
        force (bool): Force calculation of output.
        verbose (int): Set level of verbosity.

    Returns:
        None.
    """
    available_methods = []
    if shutil.which('wkhtmltoimage'):
        available_methods.append('webkit-png')
    if shutil.which('wkhtmltopdf'):
        available_methods.append('webkit-pdf')
    try:
        import weasyprint
    except ImportError:
        weasyprint = None
    else:
        available_methods.append('weasyprint')

    if not method:
        method = available_methods[0]

    # export intermediate HTML output
    if html_filepath is True or method.startswith('webkit-'):
        html_filepath = fc.change_ext(save_filepath, 'htm')
    if html_filepath:
        with open(html_filepath, 'wb+') as file_obj:
            file_obj.write(html_code.encode('ascii', 'xmlcharrefreplace'))

    if method.startswith('webkit-'):
        d_webkit_dpi = 96
        d_webkit_width = 1024
        zoom = dpi / d_webkit_dpi
        width = int(zoom * d_webkit_width)
        if img_type.lower() == 'png':
            webkit_cmd = 'wkhtmltoimage'
        elif img_type.lower() == 'pdf':
            webkit_cmd = 'wkhtmltopdf'
        os.system(
            fmtm('{webkit_cmd} --encoding UTF-8 --zoom {zoom} --width {width} '
                 ' "{html_filepath}" "{save_filepath}"'))
    elif method == 'weasyprint':
        html_obj = weasyprint.HTML(string=html_code)
        if img_type.lower() == 'png':
            html_obj.write_png(save_filepath)
        elif img_type.lower() == 'pdf':
            html_obj.write_pdf(save_filepath)

    if img_type.lower() == 'png' and trim:
        _trim(save_filepath)
Exemple #17
0
def phs_to_dphs_multi(phs_arr,
                      tis,
                      tis_mask=None,
                      poly_deg=1,
                      full=False,
                      time_units='s'):
    """
    Calculate the polynomial components of the phase variation from phase data.

    Args:
        phs_arr (np.ndarray): The input array in rad.
            The sampling time Ti varies in the last dimension.
            The data is assumed to be already unwrapped.
        tis (Iterable): The sampling times Ti in time units.
            The number of points must match the last shape size of arr.
        tis_mask (Iterable[bool]|None): Determine the sampling times Ti to use.
            If None, all will be used.
        poly_deg (int): The degree of the polynomial to fit.
            For monoexponential fits, use num=1.
        full (bool): Calculate additional information on the fit performance.
            If True, more information is given.
            If False, only the optimized parameters are returned.
        time_units (str|float|int): Units of measurement of Ti.
            If str, any valid SI time unit (e.g. `ms`, `ns`) will be accepted.
            If int or float, the conversion factor will be multiplied to `ti`.

    Returns:
        results (OrderedDict): The multiple components of the polynomial fit.
            The following terms are present:
             - `s0` (np.ndarray): The constant term.
             - `dphs_{i}` (np.ndarray): The monomial term(s); `i` is between
               1 and `poly_deg` (both included).
    """
    units_factor = 1
    if isinstance(time_units, str) and 's' in time_units:
        prefix, _ = time_units.split('s', 1)
        units_factor = fc.prefix_to_factor(prefix)
    elif isinstance(time_units, (int, float)):
        units_factor = time_units
    else:
        warnings.warn(fmtm('Invalid units `{time_units}`. Ignored.'))

    tis = np.array(fc.auto_repeat(tis, 1)) * units_factor
    y_arr = np.array(phs_arr).astype(float)
    x_arr = np.array(tis).astype(float)

    if tis_mask is not None:
        y_arr = y_arr[..., tis_mask]
        x_arr = x_arr[tis_mask]

    assert (x_arr.size == y_arr.shape[-1])

    p_arr = generic.voxel_curve_fit(y_arr,
                                    x_arr,
                                    fit_params=1 + poly_deg,
                                    method='poly')

    p_arrs = np.split(p_arr, poly_deg + 1, -1)

    results = collections.OrderedDict(
        ('s0' if i == 0 else 'dphs_{i}'.format(i=i), x)
        for i, x in enumerate(p_arrs[::-1]))

    if full:
        raise NotImplementedError

    return results
Exemple #18
0
def handle_arg():
    """
    Handle command-line application arguments.
    """
    # :: Create Argument Parser
    arg_parser = argparse.ArgumentParser(
        description=__doc__,
        epilog=fmtm('v.{version} - {author}\n{license}', INFO),
        formatter_class=argparse.RawDescriptionHelpFormatter)
    # :: Add POSIX standard arguments
    arg_parser.add_argument(
        '--ver',
        '--version',
        version=fmt(
            '%(prog)s - ver. {version}\n{}\n{copyright} {author}\n{notice}',
            next(line for line in __doc__.splitlines() if line), **INFO),
        action='version')
    arg_parser.add_argument(
        '-v',
        '--verbose',
        action='count',
        default=D_VERB_LVL,
        help='increase the level of verbosity [%(default)s]')
    arg_parser.add_argument(
        '-q',
        '--quiet',
        action='store_true',
        help='override verbosity settings to suppress output [%(default)s]')
    # :: Add additional arguments
    arg_parser.add_argument('-f',
                            '--force',
                            action='store_true',
                            help='force new processing [%(default)s]')
    arg_parser.add_argument('-i',
                            '--input',
                            metavar='FILE',
                            default=None,
                            required=True,
                            help='set input filepath [%(default)s]')
    arg_parser.add_argument('-o',
                            '--output',
                            metavar='FILE',
                            default=None,
                            help='set output filepath [%(default)s]')
    arg_parser.add_argument(
        '-s',
        '--smoothing',
        metavar='SIGMA',
        type=float,
        default=0.0,
        help='value of Gaussian smoothing\'s sigma [%(default)s]')
    arg_parser.add_argument('-a',
                            '--threshold',
                            metavar='METHOD|X',
                            default='otsu',
                            help='thresholding method or value [%(default)s]')
    arg_parser.add_argument('-A',
                            '--threshold_opts',
                            metavar='JSON',
                            default='{"bins":"sqrt"}',
                            help='comparison directive [%(default)s]')
    arg_parser.add_argument('-c',
                            '--comparison',
                            metavar='">"|">="|"<"|"<="|"="|"!="',
                            default='>',
                            help='comparison directive [%(default)s]')
    arg_parser.add_argument(
        '-e',
        '--erosion_iter',
        metavar='N',
        type=int,
        default=0,
        help='number of postprocess binary erosion iterations [%(default)s]')
    arg_parser.add_argument(
        '-d',
        '--dilation_iter',
        metavar='N',
        type=int,
        default=0,
        help='number of postprocess binary dilation iterations [%(default)s]')
    arg_parser.add_argument('-t',
                            '--dtype',
                            metavar='TYPE',
                            default='int',
                            help='data type of the output [%(default)s]')
    return arg_parser