Source code for src.cli

import sys
import argparse
import src.simulation as simulation
from pathlib import Path
import numba
import os 

import configparser
import ast

[docs] class CLI: def __init__(self, subparsers) -> None: """Initializes subparsers for input parameters :param subparsers: Parsers for each relevant module :type subparsers: str """ self.subparsers = subparsers pass
[docs] def validate_args(self, args): """Validation step for parsed user input arguments :param args: Parsed user inputs :type args: dictionary :return: Parsed and validated arguments :rtype: dictionary """ cli_args = {} assert os.path.exists(args['configuration_path']), "Configuration file path cannot be found. Please enter the absolute path to the configuration.ini file" cfg_file = configparser.ConfigParser() cfg_file.read(args['configuration_path']) # N_walkers cli_args['n_walkers'] = int(cfg_file['SIMULATION']['n_walkers']) #assert args['n_walkers']/(args['voxel_dims']**3) > 1.0," --Simulation requires spin densities > 1.0 per cubic micron" # Fiber-Fractions cli_args['fiber_fractions'] = [float(frac) for frac in str(cfg_file['FIBERS']['fiber_fractions']).split(',')] for ff in cli_args['fiber_fractions']: assert ff >= 0, "--fiber_fractions must be non-negative" assert ff < 1, "--fiber_fractions must be less than 1.0" assert sum(cli_args['fiber_fractions']) < 1, "--fiber_fractions cannot sum to more than 1.0" # Fiber-Radii cli_args['fiber_radii'] = [float(rad) for rad in str(cfg_file['FIBERS']['fiber_radii']).split(',')] for radius in cli_args['fiber_radii']: assert radius > 0, "--fiber_radii must be positive" # Thetas cli_args['thetas'] = [float(theta) for theta in str(cfg_file['FIBERS']['thetas']).split(',')] # Fiber Diffusions cli_args['fiber_diffusions'] = [float(D0) for D0 in str(cfg_file['FIBERS']['fiber_diffusions']).split(',')] for D0 in cli_args['fiber_diffusions']: assert D0 >= 0, "--fiber_diffusions must be non-negative" # Enforce self Consistent Fiber Parameters assert all([len(cli_args['fiber_fractions']) == len(param) for param in [cli_args['thetas'], cli_args['fiber_radii'], cli_args['fiber_diffusions']]]), "fiber parameters must be consistent with eachother (of equal lengths)" # Cell Fractions cli_args['cell_fractions'] = [float(fraction) for fraction in str(cfg_file['CELLS']['cell_fractions']).split(',')] for cf in cli_args['cell_fractions']: assert cf >= 0, "--cell_fractions must be non-negative" assert cf < 1, "--cell_fractions must be less than 1.0" assert sum(cli_args['cell_fractions']) < 1, "--cell_fractions cannot sum to more than 1.0" # Cell Radii cli_args['cell_radii'] = [float(rad) for rad in str(cfg_file['CELLS']['cell_radii']).split(',')] for cr in cli_args['cell_radii']: assert cr > 0, "--cell_radii must be positive" # Enforce self consistent assert len(cli_args['cell_fractions']) == len(cli_args['cell_radii']), "cell parameters must be consistent with eachother (of equal lengths)" # Water Diffusivity cli_args['water_diffusivity'] = float(cfg_file['WATER']['water_diffusivity']) assert cli_args['water_diffusivity'] >= 0.0, "--water_diffusivity must be non-negative" # Delta cli_args['Delta'] = float(cfg_file['SIMULATION']['Delta']) assert cli_args['Delta'] > 0, "--Delta must be positive" # delta / dt cli_args['dt'] = float(cfg_file['SIMULATION']['dt']) assert cli_args['dt'] > 0, "--dt must be positive" # Voxel Dims cli_args['voxel_dims'] = float(cfg_file['SIMULATION']['voxel_dims']) assert cli_args['voxel_dims'] > 0, "--voxel dims must be positive" # Void Distance cli_args['void_dist'] = float(cfg_file['SIMULATION']['void_distance']) assert cli_args['void_dist'] >= 0, "--void_dist must be non-negative" cli_args['buffer'] = int(cfg_file['SIMULATION']['buffer']) assert cli_args['buffer'] >= 0, "--buffer must be non-negative" cli_args['verbose'] = ast.literal_eval(str(cfg_file['SIMULATION']['verbose'])) assert cli_args['verbose'] == 'yes' or cli_args['verbose'] == 'no', "--verbose must be yes or no" ## Check that GPU is available assert numba.cuda.is_available(), "Trying to use Cuda device, " \ "but Cuda device is not available." ## If using custom diffusion scheme... make sure that the bval and bvec paths exist if all([ast.literal_eval(cfg_file['SIMULATION']['bvals']) != 'N/A', ast.literal_eval(cfg_file['SIMULATION']['bvecs']) != 'N/A']): cli_args['CUSTOM_DIFF_SCHEME_FLAG'] = True cli_args['input_bvals'] = ast.literal_eval(cfg_file['SIMULATION']['bvals']) cli_args['input_bvecs'] = ast.literal_eval(cfg_file['SIMULATION']['bvecs']) assert all([os.path.exists(path) for path in [cli_args['input_bvals'], cli_args['input_bvecs']]]) else: cli_args['CUSTOM_DIFF_SCHEME_FLAG'] = False cli_args['diff_scheme'] = ast.literal_eval(cfg_file['SIMULATION']['diffusion_scheme']) assert cli_args['diff_scheme'] in ['DBSI_99', 'ABCD', 'NODDI_145'] cli_args['output_directory'] = ast.literal_eval("r{}".format(cfg_file['SIMULATION']['output_directory'])) if cli_args['output_directory'] != 'N/A': assert os.path.exists(cli_args['output_directory']) else: cli_args['output_directory'] = os.getcwd() cli_args['fiber_configuration'] = 'Penetrating' cli_args['cfg_path'] = args['configuration_path'] return cli_args
[docs] def run(self, args): """Run simulation using parsed user inputs :param args: User inputs for relevant parameters :type args: dictionary """ simulation.run(args)
[docs] def add_subparser_args(self) -> argparse: """Defines subparsers for each simulation parameter. :return: argparse object containing subparsers for each simulation parameter :rtype: argparse """ subparser = self.subparsers.add_parser("simulate", description="Simulate PGSE experiment" "on custom defined biological domain", ) """ Simulation Parameters """ subparser.add_argument("--configuration", nargs = None, type = str, dest = 'configuration_path', required = True, help = "please enter the absolute path to the simulation configuration file") return self.subparsers