Source code for sovabids.convert

"""Module to perform the conversions.
"""
import argparse
import os
import sys

import logging
from sovabids.dicts import deep_get
from sovabids.rules import load_rules,apply_rules_to_single_file
from sovabids.bids import update_dataset_description
from sovabids.loggers import setup_logging
from sovabids.settings import SECTION_STRING

LOGGER = logging.getLogger(__name__)

[docs] def convert_them(mappings_input): """Convert eeg files to bids according to the mappings given. Parameters ---------- mappings_input : str | pathlib.Path | dict The path to the mapping file or the mapping dictionary: { 'General': dict with the general rules, 'Individual': list of dicts with the individual mappings of each file. } Returns ------- dict ``{'succeeded': [str, ...], 'skipped': [str, ...], 'failed': [str, ...]}`` — source paths of files that were newly converted, skipped because their BIDS output already existed, and those that raised an error. """ if isinstance(mappings_input, os.PathLike): mappings_input = os.fspath(mappings_input) # Loading Mappings mappings = load_rules(mappings_input) mapping_file = mappings_input if isinstance(mappings_input,str) else None # Verifying Mappings assert 'Individual' in mappings,f'`Individual` does not exist in the mapping dictionary' assert 'General' in mappings,f'`General` does not exist in the mapping dictionary' # Getting input,output and log path bids_path = mappings['General']['IO']['target'] source_path = mappings['General']['IO']['source'] log_file = os.path.join(bids_path,'code','sovabids','sovabids.log') # Setup the logging setup_logging(log_file) LOGGER.info('') LOGGER.info(SECTION_STRING + ' START CONVERT_THEM ' + SECTION_STRING) LOGGER.info(f"source_path={source_path} bids_path={bids_path} mapping_file={str(mapping_file)} ") LOGGER.info(f"Converting Individual Mappings") num_files = len(mappings['Individual']) succeeded = [] skipped = [] failed = [] for i,mapping in enumerate(mappings['Individual']): input_file=deep_get(mapping,'IO.source',None) output_file=deep_get(mapping,'IO.target',None) try: LOGGER.info(f"File {i+1} of {num_files} ({(i+1)*100/num_files}%) : {input_file}") if not os.path.isfile(output_file): apply_rules_to_single_file(input_file,mapping,bids_path,write=True) succeeded.append(input_file) else: LOGGER.warning(f'SKIPPED (already converted): {input_file}') skipped.append(input_file) except Exception: LOGGER.exception(f'Error converting {input_file}') failed.append(input_file) LOGGER.info( f"Conversion Done! {len(succeeded)} converted, " f"{len(skipped)} skipped, {len(failed)} failed " f"(total {num_files})." ) if skipped: LOGGER.warning(f"{len(skipped)} file(s) skipped (output already exists — delete to re-convert).") if failed: LOGGER.warning(f"{len(failed)} file(s) failed conversion:") for f in failed: LOGGER.warning(f" FAILED: {f}") LOGGER.info(f"Updating Dataset Description") # Grab the info from the last file to make the dataset description if 'dataset_description' in mappings['General']: dataset_description = mappings['General']['dataset_description'] update_dataset_description(dataset_description,bids_path) LOGGER.info(f"Dataset Description Updated!") LOGGER.info(SECTION_STRING + ' END CONVERT_THEM ' + SECTION_STRING) return {'succeeded': succeeded, 'skipped': skipped, 'failed': failed}
[docs] def sovaconvert(): """Console script usage for conversion.""" # see https://github.com/Donders-Institute/bidscoin/blob/master/bidscoin/bidsmapper.py for example of how to make this logging.basicConfig(format="%(message)s") LOGGER.setLevel(logging.WARN) from sovabids.misc import handle_unicode_dashes handle_unicode_dashes() parser = argparse.ArgumentParser() subparsers = parser.add_subparsers() parser = subparsers.add_parser('convert_them') parser.add_argument('mappings',help='The mapping file of the conversion.') parser.add_argument('-v','--verbose', action="store_true", help='Make the output more verbose.') args = parser.parse_args() if args.verbose: LOGGER.setLevel(logging.INFO) result = convert_them(args.mappings) if result['failed']: sys.exit(1)
if __name__ == "__main__": sovaconvert()