Beispiel #1
0
def _main(argv=None):
    options = _get_parser().parse_args(argv)
    phys2bids(**vars(options))
Beispiel #2
0
def _main(argv=None):
    """
    Main workflow of phys2bids.
    Runs the parser, does some checks on input, then imports
    the right interface file to read the input. If only info is required,
    it returns a summary onscreen.
    Otherwise, it operates on the input to return a .tsv.gz file, possibily
    in BIDS format.

    """
    options = _get_parser().parse_args(argv)
    # Check options to make them internally coherent
    # #!# This can probably be done while parsing?
    options.indir = utils.check_input_dir(options.indir)
    options.outdir = utils.check_input_dir(options.outdir)
    options.filename, ftype = utils.check_input_type(options.filename,
                                                     options.indir)

    if options.heur_file:
        options.heur_file = utils.check_input_ext(options.heur_file, '.py')
        utils.check_file_exists(options.heur_file)

    infile = os.path.join(options.indir, options.filename)
    utils.check_file_exists(infile)
    outfile = os.path.join(
        options.outdir,
        os.path.splitext(os.path.basename(options.filename))[0])

    # Read file!
    if ftype == 'acq':
        from phys2bids.interfaces.acq import populate_phys_input
    elif ftype == 'txt':
        from phys2bids.interfaces.txt import populate_phys_input
    else:
        # #!# We should add a logger here.
        raise NotImplementedError('Currently unsupported file type.')

    print('Reading the file')
    phys_in = populate_phys_input(infile, options.chtrig)
    print('Reading infos')
    phys_in.print_info(options.filename)
    # #!# Here the function viz.plot_channel should be called
    # for the desired channels.

    # If only info were asked, end here.
    if options.info:
        return

    # Run analysis on trigger channel to get first timepoint and the time offset.
    # #!# Get option of no trigger! (which is wrong practice or Respiract)
    phys_in.check_trigger_amount(options.thr, options.num_timepoints_expected,
                                 options.tr)

    # Create output folder if necessary
    print('Checking that the output folder exists')
    utils.path_exists_or_make_it(options.outdir)

    # Create trigger plot. If possible, to have multiple outputs in the same
    # place, adds sub and ses label.
    print('Plot trigger')
    plot_path = deepcopy(outfile)
    if options.sub:
        plot_path += f'_sub-{options.sub}'
    if options.ses:
        plot_path += f'_sub-{options.ses}'
    viz.plot_trigger(phys_in.timeseries[0], phys_in.timeseries[1], plot_path,
                     options)

    # The next few lines remove the undesired channels from phys_in.
    if options.chsel:
        print('Dropping unselected channels')
        for i in reversed(range(0, phys_in.ch_amount)):
            if i not in options.chsel:
                phys_in.delete_at_index(i)

    # If requested, change channel names.
    if options.ch_name:
        print('Renaming channels with given names')
        phys_in.rename_channels(options.ch_name)

    # The next few lines create a dictionary of different BlueprintInput
    # objects, one for each unique frequency in phys_in
    uniq_freq_list = set(phys_in.freq)
    output_amount = len(uniq_freq_list)
    if output_amount > 1:
        print(f'Found {output_amount} different frequencies in input!')

    print(f'Preparing {output_amount} output files.')
    phys_out = {}
    for uniq_freq in uniq_freq_list:
        phys_out[uniq_freq] = deepcopy(phys_in)
        for i in reversed(phys_in.freq):
            if i != uniq_freq:
                phys_out[uniq_freq].delete_at_index(phys_in.ch_amount - i - 1)

        # Also create a BlueprintOutput object for each unique frequency found.
        # Populate it with the corresponding blueprint input and replace it
        # in the dictionary.
        phys_out[uniq_freq] = BlueprintOutput.init_from_blueprint(
            phys_out[uniq_freq])

    if options.heur_file and options.sub:
        print(f'Preparing BIDS output using {options.heur_file}')
    elif options.heur_file and not options.sub:
        print(f'While "-heur" was specified, option "-sub" was not.\n'
              f'Skipping BIDS formatting.')

    for uniq_freq in uniq_freq_list:
        # If possible, prepare bids renaming.
        if options.heur_file and options.sub:
            if output_amount > 1:
                # Add "recording-freq" to filename if more than one freq
                outfile = use_heuristic(options.heur_file, options.sub,
                                        options.ses, options.filename,
                                        options.outdir, uniq_freq)
            else:
                outfile = use_heuristic(options.heur_file, options.sub,
                                        options.ses, options.filename,
                                        options.outdir)

        elif output_amount > 1:
            # Append "freq" to filename if more than one freq
            outfile = f'outfile_{uniq_freq}'

        print(f'Exporting files for freq {uniq_freq}')
        savetxt(outfile + '.tsv.gz',
                phys_out[uniq_freq].timeseries,
                fmt='%.8e',
                delimiter='\t')
        print_json(outfile, phys_out[uniq_freq].freq,
                   phys_out[uniq_freq].start_time, phys_out[uniq_freq].ch_name)
        print_summary(options.filename, options.num_timepoints_expected,
                      phys_in.num_timepoints_found, uniq_freq,
                      phys_out[uniq_freq].start_time, outfile)