diff --git a/docs/source/examples_simple_2D.rst b/docs/source/examples_simple_2D.rst index 87c298e7..79ac4fc8 100644 --- a/docs/source/examples_simple_2D.rst +++ b/docs/source/examples_simple_2D.rst @@ -155,7 +155,7 @@ You should have produced 60 output files, one for each A-scan, with names ``cyli python -m tools.outputfiles_merge user_models/cylinder_Bscan_2D -You should see a combined output file ``cylinder_Bscan_2D_merged.out``. The tool will ask you if you want to delete the original single A-scan output files or keep them. +You should see a combined output file ``cylinder_Bscan_2D_merged.out``. You can add the optional argument ``--remove-files`` if you want to automatically delete the original single A-scan output files. You can now view an image of the B-scan using the command: @@ -171,9 +171,3 @@ You can now view an image of the B-scan using the command: :width: 600px B-scan of model of a metal cylinder buried in a dielectric half-space. - - - - - - diff --git a/docs/source/utils.rst b/docs/source/utils.rst index 5d479d33..799f0093 100644 --- a/docs/source/utils.rst +++ b/docs/source/utils.rst @@ -21,15 +21,16 @@ where ``inputfile`` is the name of input file including the path. outputfiles_merge.py -------------------- -gprMax produces a separate output file for each trace (A-scan) in a B-scan. This module combines the separate output files into a single file, and offers to remove the separate output files afterwards. Usage (from the top-level gprMax directory) is: +gprMax produces a separate output file for each trace (A-scan) in a B-scan. This module combines the separate output files into a single file, and can remove the separate output files afterwards. Usage (from the top-level gprMax directory) is: .. code-block:: none - python -m tools.outputfiles_merge basefilename + python -m tools.outputfiles_merge basefilename --remove-files where: * ``basefilename`` is the base name file of the output file series, e.g. for ``myoutput1.out``, ``myoutput2.out`` the base file name would be ``myoutput`` +* ``remove-files`` is an optional argument (flag) that when given will remove the separate output files after the merge. convert_png2h5.py diff --git a/tools/outputfiles_merge.py b/tools/outputfiles_merge.py index 10cb15b1..346a9a12 100644 --- a/tools/outputfiles_merge.py +++ b/tools/outputfiles_merge.py @@ -25,56 +25,101 @@ import numpy as np from gprMax._version import __version__ -"""Merges traces (A-scans) from multiple output files into one new file, then removes the series of output files.""" -# Parse command line arguments -parser = argparse.ArgumentParser(description='Merges traces (A-scans) from multiple output files into one new file, then removes the series of output files.', usage='cd gprMax; python -m tools.outputfiles_merge basefilename') -parser.add_argument('basefilename', help='base name of output file series including path') -args = parser.parse_args() +def get_output_data(filename, rxnumber, rxcomponent): + """Gets B-scan output data from a model. -basefilename = args.basefilename -outputfile = basefilename + '_merged.out' -files = glob.glob(basefilename + '*.out') -outputfiles = [filename for filename in files if '_merged' not in filename] -modelruns = len(outputfiles) -print('Found {} files to merge'.format(modelruns)) + Args: + filename (string): Filename (including path) of output file. + rxnumber (int): Receiver output number. + rxcomponent (str): Receiver output field/current component. -# Combined output file -fout = h5py.File(outputfile, 'w') + Returns: + outputdata (array): Array of A-scans, i.e. B-scan data. + dt (float): Temporal resolution of the model. + """ -# Add positional data for rxs -for model in range(modelruns): - fin = h5py.File(basefilename + str(model + 1) + '.out', 'r') - nrx = fin.attrs['nrx'] + # Open output file and read some attributes + f = h5py.File(filename, 'r') + nrx = f.attrs['nrx'] + dt = f.attrs['dt'] - # Write properties for merged file on first iteration - if model == 0: - fout.attrs['Title'] = fin.attrs['Title'] - fout.attrs['gprMax'] = __version__ - fout.attrs['Iterations'] = fin.attrs['Iterations'] - fout.attrs['dt'] = fin.attrs['dt'] - fout.attrs['nrx'] = fin.attrs['nrx'] - for rx in range(1, nrx + 1): - path = '/rxs/rx' + str(rx) - grp = fout.create_group(path) - availableoutputs = list(fin[path].keys()) - for output in availableoutputs: - grp.create_dataset(output, (fout.attrs['Iterations'], modelruns), dtype=fin[path + '/' + output].dtype) + # Check there are any receivers + if nrx == 0: + raise CmdInputError('No receivers found in {}'.format(filename)) - # For all receivers - for rx in range(1, nrx + 1): - path = '/rxs/rx' + str(rx) + '/' - availableoutputs = list(fin[path].keys()) - # For all receiver outputs - for output in availableoutputs: - fout[path + '/' + output][:, model] = fin[path + '/' + output][:] + path = '/rxs/rx' + str(rxnumber) + '/' + availableoutputs = list(f[path].keys()) - fin.close() + # Check if requested output is in file + if rxcomponent not in availableoutputs: + raise CmdInputError('{} output requested to plot, but the available output for receiver 1 is {}'.format(rxcomponent, ', '.join(availableoutputs))) -fout.close() + outputdata = f[path + '/' + rxcomponent] + outputdata = np.array(outputdata) -check = input('Do you want to remove the multiple individual output files? [y] or n:') -if not check or check == 'y': + return outputdata, dt + + +def merge_files(basefilename, removefiles=False): + """Merges traces (A-scans) from multiple output files into one new file, + then optionally removes the series of output files. + + Args: + basefilename (string): Base name of output file series including path. + outputs (boolean): Flag to remove individual output files after merge. + """ + + outputfile = basefilename + '_merged.out' + files = glob.glob(basefilename + '*.out') + outputfiles = [filename for filename in files if '_merged' not in filename] + modelruns = len(outputfiles) + + # Combined output file + fout = h5py.File(outputfile, 'w') + + # Add positional data for rxs for model in range(modelruns): - file = basefilename + str(model + 1) + '.out' - os.remove(file) + fin = h5py.File(basefilename + str(model + 1) + '.out', 'r') + nrx = fin.attrs['nrx'] + + # Write properties for merged file on first iteration + if model == 0: + fout.attrs['Title'] = fin.attrs['Title'] + fout.attrs['gprMax'] = __version__ + fout.attrs['Iterations'] = fin.attrs['Iterations'] + fout.attrs['dt'] = fin.attrs['dt'] + fout.attrs['nrx'] = fin.attrs['nrx'] + for rx in range(1, nrx + 1): + path = '/rxs/rx' + str(rx) + grp = fout.create_group(path) + availableoutputs = list(fin[path].keys()) + for output in availableoutputs: + grp.create_dataset(output, (fout.attrs['Iterations'], modelruns), dtype=fin[path + '/' + output].dtype) + + # For all receivers + for rx in range(1, nrx + 1): + path = '/rxs/rx' + str(rx) + '/' + availableoutputs = list(fin[path].keys()) + # For all receiver outputs + for output in availableoutputs: + fout[path + '/' + output][:, model] = fin[path + '/' + output][:] + + fin.close() + + fout.close() + + if removefiles: + for model in range(modelruns): + file = basefilename + str(model + 1) + '.out' + os.remove(file) + +if __name__ == "__main__": + + # Parse command line arguments + parser = argparse.ArgumentParser(description='Merges traces (A-scans) from multiple output files into one new file, then optionally removes the series of output files.', usage='cd gprMax; python -m tools.outputfiles_merge basefilename') + parser.add_argument('basefilename', help='base name of output file series including path') + parser.add_argument('--remove-files', action='store_true', default=False, help='flag to remove individual output files after merge') + args = parser.parse_args() + + merge_files(args.basefilename, removefiles=args.remove_files) diff --git a/tools/plot_Bscan.py b/tools/plot_Bscan.py index 60b5de90..e6fe4a6a 100644 --- a/tools/plot_Bscan.py +++ b/tools/plot_Bscan.py @@ -25,45 +25,7 @@ import numpy as np import matplotlib.pyplot as plt from gprMax.exceptions import CmdInputError - - -def get_output_data(filename, rxnumber, rxcomponent): - """Gets B-scan output data from a model. - - Args: - filename (string): Filename (including path) of output file. - rxnumber (int): Receiver output number. - rxcomponent (str): Receiver output field/current component. - - Returns: - outputdata (array): Array of A-scans, i.e. B-scan data. - dt (float): Temporal resolution of the model. - """ - - # Open output file and read some attributes - f = h5py.File(filename, 'r') - nrx = f.attrs['nrx'] - dt = f.attrs['dt'] - - # Check there are any receivers - if nrx == 0: - raise CmdInputError('No receivers found in {}'.format(filename)) - - path = '/rxs/rx' + str(rxnumber) + '/' - availableoutputs = list(f[path].keys()) - - # Check if requested output is in file - if rxcomponent not in availableoutputs: - raise CmdInputError('{} output requested to plot, but the available output for receiver 1 is {}'.format(rxcomponent, ', '.join(availableoutputs))) - - outputdata = f[path + '/' + rxcomponent] - outputdata = np.array(outputdata) - - # Check that there is more than one A-scan present - if outputdata.shape[1] == 1: - raise CmdInputError('{} contains only a single A-scan.'.format(filename)) - - return outputdata, dt +from .outputdata import get_output_data def mpl_plot(filename, outputdata, dt, rxnumber, rxcomponent):