diff --git a/gprMax/exceptions.py b/gprMax/exceptions.py index e4d84d58..751260d8 100644 --- a/gprMax/exceptions.py +++ b/gprMax/exceptions.py @@ -17,11 +17,25 @@ # along with gprMax. If not, see . +from colorama import init, Fore +init() + + class GeneralError(ValueError): """Handles general errors. Subclasses the ValueError class.""" - pass + + def __init__(self, message, *args): + + self.message = message + super(GeneralError, self).__init__(message, *args) + print(Fore.RED) class CmdInputError(ValueError): """Handles errors in user specified commands. Subclasses the ValueError class.""" - pass + + def __init__(self, message, *args): + + self.message = message + super(CmdInputError, self).__init__(message, *args) + print(Fore.RED) \ No newline at end of file diff --git a/gprMax/gprMax.py b/gprMax/gprMax.py index e1d2dca7..05677350 100644 --- a/gprMax/gprMax.py +++ b/gprMax/gprMax.py @@ -28,6 +28,8 @@ from shutil import get_terminal_size import sys from time import perf_counter +from colorama import init, Fore, Style +init() import numpy as np from terminaltables import AsciiTable from tqdm import tqdm @@ -56,13 +58,13 @@ def main(): logo(__version__ + ' (Bowmore)') # Parse command line arguments - parser = argparse.ArgumentParser(prog='gprMax', description='Electromagnetic modelling software based on the Finite-Difference Time-Domain (FDTD) method') - parser.add_argument('inputfile', help='path to and name of inputfile') - parser.add_argument('-n', default=1, type=int, help='number of times to run the input file') + parser = argparse.ArgumentParser(prog='gprMax') + parser.add_argument('inputfile', help='path to, and name of inputfile') + parser.add_argument('-n', default=1, type=int, help='number of times to run the input file, e.g. for creating B-scans') parser.add_argument('-mpi', action='store_true', default=False, help='flag to switch on MPI task farm') parser.add_argument('-benchmark', action='store_true', default=False, help='flag to switch on benchmarking mode') parser.add_argument('--geometry-only', action='store_true', default=False, help='flag to only build model and produce geometry file(s)') - parser.add_argument('--geometry-fixed', action='store_true', default=False, help='flag to not reprocess model geometry for multiple model runs') + parser.add_argument('--geometry-fixed', action='store_true', default=False, help='flag to not reprocess model geometry, e.g. for B-scans where the geometry is fixed') parser.add_argument('--write-processed', action='store_true', default=False, help='flag to write an input file after any Python code and include commands in the original input file have been processed') parser.add_argument('--opt-taguchi', action='store_true', default=False, help='flag to optimise parameters using the Taguchi optimisation method') args = parser.parse_args() @@ -151,8 +153,8 @@ def run_std_sim(args, numbermodelruns, inputfile, usernamespace, optparams=None) modelusernamespace = usernamespace run_model(args, modelrun, numbermodelruns, inputfile, modelusernamespace) tsimend = perf_counter() - print('\n{}\nSimulation completed in [HH:MM:SS]: {}'.format('-' * get_terminal_size()[0], datetime.timedelta(seconds=int(tsimend - tsimstart)))) - print('{}\n'.format('=' * get_terminal_size()[0])) + simcompletestr = '\n== Simulation completed in [HH:MM:SS]: {}'.format(datetime.timedelta(seconds=int(tsimend - tsimstart))) + print('{} {}\n'.format(simcompletestr, '=' * (get_terminal_size()[0] - len(simcompletestr)))) def run_benchmark_sim(args, inputfile, usernamespace): @@ -184,7 +186,8 @@ def run_benchmark_sim(args, inputfile, usernamespace): threads = np.array(threads) np.savez(os.path.splitext(inputfile)[0], threads=threads, benchtimes=benchtimes, version=__version__) - print('\nSimulation completed\n{}\n'.format('=' * get_terminal_size()[0])) + simcompletestr = '\n== Simulation completed' + print('{} {}\n'.format(simcompletestr, '=' * (get_terminal_size()[0] - len(simcompletestr)))) def run_mpi_sim(args, numbermodelruns, inputfile, usernamespace, optparams=None): @@ -263,8 +266,8 @@ def run_mpi_sim(args, numbermodelruns, inputfile, usernamespace, optparams=None) comm.send(None, dest=0, tag=tags.EXIT.value) tsimend = perf_counter() - print('\n{}\nSimulation completed in [HH:MM:SS]: {}'.format('-' * get_terminal_size()[0], datetime.timedelta(seconds=int(tsimend - tsimstart)))) - print('{}\n'.format('=' * get_terminal_size()[0])) + simcompletestr = '\n== Simulation completed in [HH:MM:SS]: {}'.format(datetime.timedelta(seconds=int(tsimend - tsimstart))) + print('{} {}\n'.format(simcompletestr, '=' * (get_terminal_size()[0] - len(simcompletestr)))) def run_model(args, modelrun, numbermodelruns, inputfile, usernamespace): @@ -289,11 +292,12 @@ def run_model(args, modelrun, numbermodelruns, inputfile, usernamespace): # Normal model reading/building process; bypassed if geometry information to be reused if 'G' not in globals(): - print('{}\n\nInput file: {}\n'.format('-' * get_terminal_size()[0], inputfile)) + inputfilestr = '\nModel {} of {}, input file: {}'.format(modelrun, numbermodelruns, inputfile) + print(Fore.GREEN + '{} {}\n'.format(inputfilestr, '-' * (get_terminal_size()[0] - len(inputfilestr)))) # Add the current model run to namespace that can be accessed by user in any Python code blocks in input file usernamespace['current_model_run'] = modelrun - print('Constants/variables available for Python scripting: {}\n'.format(usernamespace)) + print(Style.RESET_ALL + 'Constants/variables available for Python scripting: {}\n'.format(usernamespace)) # Read input file and process any Python or include commands processedlines = process_python_include_code(inputfile, usernamespace) @@ -405,7 +409,7 @@ def run_model(args, modelrun, numbermodelruns, inputfile, usernamespace): raise GeneralError('No geometry views found.') elif G.geometryviews: print() - for geometryview in tqdm(G.geometryviews, desc='Writing geometry file(s)'): + for geometryview in tqdm(G.geometryviews, desc='Writing geometry file(s)', unit='file'): geometryview.write_vtk(modelrun, numbermodelruns, G) # geometryview.write_xdmf(modelrun, numbermodelruns, G) @@ -484,7 +488,7 @@ def run_model(args, modelrun, numbermodelruns, inputfile, usernamespace): write_hdf5(outputfile, G.Ex, G.Ey, G.Ez, G.Hx, G.Hy, G.Hz, G) if G.messages: - print('\nMemory (RAM) used: ~{}'.format(human_size(p.memory_info().rss))) + print('Memory (RAM) used: ~{}'.format(human_size(p.memory_info().rss))) ################################## # End - Main FDTD calculations # diff --git a/gprMax/input_cmds_geometry.py b/gprMax/input_cmds_geometry.py index edced2a0..aef59107 100644 --- a/gprMax/input_cmds_geometry.py +++ b/gprMax/input_cmds_geometry.py @@ -41,7 +41,7 @@ def process_geometrycmds(geometry, G): """ - for object in tqdm(geometry, desc='Processing geometry objects'): + for object in tqdm(geometry, desc='Processing geometry objects', unit='cmds'): tmp = object.split() if tmp[0] == '#geometry_objects_file:': diff --git a/gprMax/optimisation_taguchi.py b/gprMax/optimisation_taguchi.py index 54eb52cd..1d325f55 100644 --- a/gprMax/optimisation_taguchi.py +++ b/gprMax/optimisation_taguchi.py @@ -160,9 +160,9 @@ def run_opt_sim(args, numbermodelruns, inputfile, usernamespace): pickle.dump(fitnessvalueshist, f) pickle.dump(optparamsinit, f) - print('{}\nTaguchi optimisation completed after {} iteration(s).\nHistory of optimal parameter values {} and of fitness values {}'.format('-' * get_terminal_size()[0], iteration, dict(optparamshist), fitnessvalueshist)) - print('Simulation completed in [HH:MM:SS]: {}'.format(datetime.timedelta(seconds=int(tsimend - tsimstart)))) - print('{}\n'.format('=' * get_terminal_size()[0])) + print('\nTaguchi optimisation completed after {} iteration(s).\nHistory of optimal parameter values {} and of fitness values {}'.format(iteration, dict(optparamshist), fitnessvalueshist)) + simcompletestr = '\n== Simulation completed in [HH:MM:SS]: {}'.format(datetime.timedelta(seconds=int(tsimend - tsimstart))) + print('{} {}\n'.format(simcompletestr, '=' * (get_terminal_size()[0] - len(simcompletestr)))) def taguchi_code_blocks(inputfile, taguchinamespace): diff --git a/gprMax/utilities.py b/gprMax/utilities.py index 4badda8c..dbe0323c 100644 --- a/gprMax/utilities.py +++ b/gprMax/utilities.py @@ -34,12 +34,12 @@ def logo(version): version (str): Version number. """ - description = '"Electromagnetic modelling software based on the Finite-Difference Time-Domain (FDTD) method"' + description = 'Electromagnetic modelling software based on the Finite-Difference Time-Domain (FDTD) method' copyright = 'Copyright (C) 2015-2016: The University of Edinburgh' authors = 'Authors: Craig Warren and Antonis Giannopoulos' licenseinfo1 = 'gprMax is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.\n' licenseinfo2 = 'gprMax is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.' - licenseinfo3 = 'You should have received a copy of the GNU General Public License along with gprMax. If not, see .' + licenseinfo3 = 'You should have received a copy of the GNU General Public License along with gprMax. If not, see www.gnu.org/licenses.' logo = """ www.gprmax.com __ __ __ _ _ __ _ __| \/ | __ ___ __ @@ -49,14 +49,9 @@ def logo(version): |___/|_| v""" + version - print('\n{}'.format('=' * get_terminal_size()[0])) - - - print(Fore.MAGENTA + '{}'.format(logo)) - print(Style.RESET_ALL + '{}'.format('-' * get_terminal_size()[0])) - print(textwrap.fill(description, width=get_terminal_size()[0], initial_indent=' ')) - print() - print(textwrap.fill(copyright, width=get_terminal_size()[0], initial_indent=' ')) + print('\n== {} {}\n'.format(description, '=' * (get_terminal_size()[0] - (len(description)) - 4))) + print(Fore.CYAN + '{}\n'.format(logo)) + print(Style.RESET_ALL + textwrap.fill(copyright, width=get_terminal_size()[0], initial_indent=' ')) print(textwrap.fill(authors, width=get_terminal_size()[0], initial_indent=' ')) print() print(textwrap.fill(licenseinfo1, width=get_terminal_size()[0], initial_indent=' ', subsequent_indent=' '))