Docstrings updates

这个提交包含在:
Craig Warren
2022-11-26 16:52:36 +00:00
父节点 e77a4b01f5
当前提交 1a8a65960b
共有 4 个文件被更改,包括 132 次插入81 次删除

查看文件

@@ -0,0 +1,18 @@
Toolboxes is a sub-package where useful Python modules contributed by users are stored.
********
Plotting
********
Information
===========
This package is intended to provide some basic scripts to get started with plotting outputs from simulations.
Package contents
================
* ``plot_antenna_params.py`` plots antenna parameters - incident, reflected and total voltages and currents; s11, (s21) and input impedance from an output file containing a transmission line source.
* ``plot_Ascan.py`` plots electric and magnetic fields and currents from all receiver points in the given output file. Each receiver point is plotted in a new figure window.
* ``plot_Bscan.py`` plots a B-scan (multiple A-scans) image.
* ``plot_source_wave.py`` plot built-in waveforms that can be used for sources.

查看文件

@@ -30,7 +30,7 @@ logger = logging.getLogger(__name__)
def mpl_plot(filename, outputdata, dt, rxnumber, rxcomponent, save=False):
"""Creates a plot (with matplotlib) of the B-scan.
"""Creates a plot of the B-scan.
Args:
filename: string of filename (including path) of output file.
@@ -101,28 +101,19 @@ if __name__ == "__main__":
logger.exception(f'No receivers found in {args.outputfile}')
raise ValueError
rxsgather = []
for rx in range(1, nrx + 1):
outputdata, dt = get_output_data(args.outputfile, rx, args.rx_component)
print(outputdata.shape)
if args.gather:
rxsgather.append(outputdata)
if rx == 1:
rxsgather = outputdata
rxsgather = np.column_stack((rxsgather, outputdata))
else:
plthandle = mpl_plot(args.outputfile, outputdata, dt, rx,
args.rx_component, save=args.save)
# Plot all receivers from single output file together if required
if args.gather:
rxsgather = np.array(rxsgather).transpose()
plthandle = mpl_plot(args.outputfile, rxsgather, dt, rx,
args.rx_component, save=args.save)
if args.save:
# Save a PDF of the figure
plthandle.savefig(args.outputfile[:-3] + '.pdf', dpi=None,
format='pdf', bbox_inches='tight', pad_inches=0.1)
# # Save a PNG of the figure
# plthandle.savefig(args.outputfile[:-3] + '.png', dpi=150,
# format='png', bbox_inches='tight', pad_inches=0.1)
else:
plthandle.show()
plthandle.show()

查看文件

@@ -33,14 +33,14 @@ def calculate_antenna_params(filename, tltxnumber=1, tlrxnumber=None, rxnumber=N
and currents; s11, (s21) and input impedance.
Args:
filename (string): Filename (including path) of output file.
tltxnumber (int): Transmitter antenna - transmission line number
tlrxnumber (int): Receiver antenna - transmission line number
rxnumber (int): Receiver antenna - output number
rxcomponent (str): Receiver antenna - output electric field component
filename: string of filename (including path) of output file.
tltxnumber: int for transmitter antenna - transmission line number
tlrxnumber: int for receiver antenna - transmission line number
rxnumber: int for receiver antenna - output number
rxcomponent: in for receiver antenna - output electric field component
Returns:
antennaparams (dict): Antenna parameters.
antennaparams: dict of antenna parameters.
"""
# Open output file and read some attributes
@@ -73,7 +73,8 @@ def calculate_antenna_params(filename, tltxnumber=1, tlrxnumber=None, rxnumber=N
Vref = Vtotal - Vinc
Iref = Itotal - Iinc
# If a receiver antenna is used (with a transmission line or receiver), get received voltage for s21
# If a receiver antenna is used (with a transmission line or receiver),
# get received voltage for s21
if tlrxnumber:
tlrxpath = '/tls/tl' + str(tlrxnumber) + '/'
Vrec = f[tlrxpath + 'Vtotal'][:]
@@ -83,7 +84,9 @@ def calculate_antenna_params(filename, tltxnumber=1, tlrxnumber=None, rxnumber=N
availableoutputs = list(f[rxpath].keys())
if rxcomponent not in availableoutputs:
logger.exception(f"{rxcomponent} output requested, but the available output for receiver {rxnumber} is {', '.join(availableoutputs)}")
logger.exception(f"{rxcomponent} output requested, but the available " +
f"output for receiver {rxnumber} is " +
f"{', '.join(availableoutputs)}")
raise ValueError
rxpath += rxcomponent
@@ -100,7 +103,8 @@ def calculate_antenna_params(filename, tltxnumber=1, tlrxnumber=None, rxnumber=N
# Frequency bins
freqs = np.fft.fftfreq(Vinc.size, d=dt)
# Delay correction - current lags voltage, so delay voltage to match current timestep
# Delay correction - current lags voltage, so delay voltage to match
# current timestep
delaycorrection = np.exp(1j * 2 * np.pi * freqs * (dt / 2))
# Calculate s11 and (optionally) s21
@@ -134,9 +138,10 @@ def calculate_antenna_params(filename, tltxnumber=1, tlrxnumber=None, rxnumber=N
s11[np.invert(np.isfinite(s11))] = 0
# Create dictionary of antenna parameters
antennaparams = {'time': time, 'freqs': freqs, 'Vinc': Vinc, 'Vincp': Vincp, 'Iinc': Iinc, 'Iincp': Iincp,
'Vref': Vref, 'Vrefp': Vrefp, 'Iref': Iref, 'Irefp': Irefp,
'Vtotal': Vtotal, 'Vtotalp': Vtotalp, 'Itotal': Itotal, 'Itotalp': Itotalp,
antennaparams = {'time': time, 'freqs': freqs, 'Vinc': Vinc, 'Vincp': Vincp,
'Iinc': Iinc, 'Iincp': Iincp, 'Vref': Vref, 'Vrefp': Vrefp,
'Iref': Iref, 'Irefp': Irefp, 'Vtotal': Vtotal,
'Vtotalp': Vtotalp, 'Itotal': Itotal, 'Itotalp': Itotalp,
's11': s11, 'zin': zin, 'yin': yin}
if tlrxnumber or rxnumber:
with np.errstate(divide='ignore'): # Ignore warning from taking a log of any zero values
@@ -147,22 +152,31 @@ def calculate_antenna_params(filename, tltxnumber=1, tlrxnumber=None, rxnumber=N
return antennaparams
def mpl_plot(filename, time, freqs, Vinc, Vincp, Iinc, Iincp, Vref, Vrefp, Iref, Irefp, Vtotal, Vtotalp, Itotal, Itotalp, s11, zin, yin, s21=None):
"""Plots antenna parameters - incident, reflected and total volatges and
def mpl_plot(filename, time, freqs, Vinc, Vincp, Iinc, Iincp, Vref, Vrefp,
Iref, Irefp, Vtotal, Vtotalp, Itotal, Itotalp, s11, zin, yin,
s21=None, save=False):
"""Plots antenna parameters - incident, reflected and total voltages and
currents; s11, (s21) and input impedance.
Args:
filename (string): Filename (including path) of output file.
time (array): Simulation time.
freq (array): Frequencies for FFTs.
Vinc, Vincp, Iinc, Iincp (array): Time and frequency domain representations of incident voltage and current.
Vref, Vrefp, Iref, Irefp (array): Time and frequency domain representations of reflected voltage and current.
Vtotal, Vtotalp, Itotal, Itotalp (array): Time and frequency domain representations of total voltage and current.
s11, s21 (array): s11 and, optionally, s21 parameters.
zin, yin (array): Input impedance and input admittance parameters.
filename: string of filename (including path) of output file.
time: array of simulation time.
freq: array of frequencies for FFTs.
Vinc, Vincp, Iinc, Iincp: arrays of time and frequency domain
representations of incident voltage and
current.
Vref, Vrefp, Iref, Irefp: arrays of time and frequency domain
representations of reflected voltage and
current.
Vtotal, Vtotalp, Itotal, Itotalp: arrays of time and frequency domain
representations of total voltage and
current.
s11, s21: array(s) of s11 and, optionally, s21 parameters.
zin, yin: arrays of input impedance and input admittance parameters.
save: boolean flag to save plot to file.
Returns:
plt (object): matplotlib plot object.
plt: matplotlib plot object.
"""
# Set plotting range
@@ -175,9 +189,11 @@ def mpl_plot(filename, time, freqs, Vinc, Vincp, Iinc, Iincp, Vref, Vrefp, Iref,
# Print some useful values from s11, and input impedance
s11minfreq = np.where(s11[pltrange] == np.amin(s11[pltrange]))[0][0]
logger.info(f's11 minimum: {np.amin(s11[pltrange]):g} dB at {freqs[s11minfreq + pltrangemin]:g} Hz')
logger.info(f's11 minimum: {np.amin(s11[pltrange]):g} dB at ' +
f'{freqs[s11minfreq + pltrangemin]:g} Hz')
logger.info(f'At {freqs[s11minfreq + pltrangemin]:g} Hz...')
logger.info(f'Input impedance: {np.abs(zin[s11minfreq + pltrangemin]):.1f}{zin[s11minfreq + pltrangemin].imag:+.1f}j Ohms')
logger.info(f'Input impedance: {np.abs(zin[s11minfreq + pltrangemin]):.1f}' +
f'{zin[s11minfreq + pltrangemin].imag:+.1f}j Ohms')
# logger.info(f'Input admittance (mag): {np.abs(yin[s11minfreq + pltrangemin]):g} S')
# logger.info(f'Input admittance (phase): {np.angle(yin[s11minfreq + pltrangemin], deg=True):.1f} deg')
@@ -413,19 +429,21 @@ def mpl_plot(filename, time, freqs, Vinc, Vincp, Iinc, Iincp, Vref, Vrefp, Iref,
# ax.set_ylim([-40, 100])
# ax.grid(which='both', axis='both', linestyle='-.')
# Save a PDF/PNG of the figure
savename1 = filename.stem + '_tl_params'
savename1 = filename.parent / savename1
savename2 = filename.stem + '_ant_params'
savename2 = filename.parent / savename2
# fig1.savefig(savename1.with_suffix('.png'), dpi=150, format='png',
# bbox_inches='tight', pad_inches=0.1)
# fig2.savefig(savename2.with_suffix('.png'), dpi=150, format='png',
# bbox_inches='tight', pad_inches=0.1)
# fig1.savefig(savename1.with_suffix('.pdf'), dpi=None, format='pdf',
# bbox_inches='tight', pad_inches=0.1)
# fig2.savefig(savename2.with_suffix('.pdf'), dpi=None, format='pdf',
# bbox_inches='tight', pad_inches=0.1)
if save:
savename1 = filename.stem + '_tl_params'
savename1 = filename.parent / savename1
savename2 = filename.stem + '_ant_params'
savename2 = filename.parent / savename2
# Save a PDF of the figure
fig1.savefig(savename1.with_suffix('.pdf'), dpi=None, format='pdf',
bbox_inches='tight', pad_inches=0.1)
fig2.savefig(savename2.with_suffix('.pdf'), dpi=None, format='pdf',
bbox_inches='tight', pad_inches=0.1)
# Save a PNG of the figure
# fig1.savefig(savename1.with_suffix('.png'), dpi=150, format='png',
# bbox_inches='tight', pad_inches=0.1)
# fig2.savefig(savename2.with_suffix('.png'), dpi=150, format='png',
# bbox_inches='tight', pad_inches=0.1)
return plt
@@ -433,14 +451,28 @@ def mpl_plot(filename, time, freqs, Vinc, Vincp, Iinc, Iincp, Vref, Vrefp, Iref,
if __name__ == "__main__":
# Parse command line arguments
parser = argparse.ArgumentParser(description='Plots antenna parameters (s11, s21 parameters and input impedance) from an output file containing a transmission line source.', usage='cd gprMax; python -m tools.plot_antenna_params outputfile')
parser = argparse.ArgumentParser(description='Plots antenna parameters - ' +
'incident, reflected and total voltages ' +
'and currents; s11, (s21) and input impedance ' +
'from an output file containing a transmission ' +
'line source.',
usage='cd gprMax; python -m toolboxes.Plotting.plot_antenna_params outputfile')
parser.add_argument('outputfile', help='name of output file including path')
parser.add_argument('--tltx-num', default=1, type=int, help='transmitter antenna - transmission line number')
parser.add_argument('--tlrx-num', type=int, help='receiver antenna - transmission line number')
parser.add_argument('--rx-num', type=int, help='receiver antenna - output number')
parser.add_argument('--rx-component', type=str, help='receiver antenna - output electric field component', choices=['Ex', 'Ey', 'Ez'])
parser.add_argument('--tltx-num', default=1, type=int,
help='transmitter antenna - transmission line number')
parser.add_argument('--tlrx-num', type=int,
help='receiver antenna - transmission line number')
parser.add_argument('--rx-num', type=int,
help='receiver antenna - output number')
parser.add_argument('--rx-component', type=str,
help='receiver antenna - output electric field component',
choices=['Ex', 'Ey', 'Ez'])
parser.add_argument('-save', action='store_true', default=False,
help='save plot directly to file, i.e. do not display')
args = parser.parse_args()
antennaparams = calculate_antenna_params(args.outputfile, args.tltx_num, args.tlrx_num, args.rx_num, args.rx_component)
plthandle = mpl_plot(args.outputfile, **antennaparams)
antennaparams = calculate_antenna_params(args.outputfile, args.tltx_num,
args.tlrx_num, args.rx_num,
args.rx_component)
plthandle = mpl_plot(args.outputfile, **antennaparams, save=args.save)
plthandle.show()

查看文件

@@ -32,12 +32,12 @@ def check_timewindow(timewindow, dt):
"""Checks and sets time window and number of iterations.
Args:
timewindow (float): Time window.
dt (float): Time discretisation.
timewindow: float of time window.
dt: flost of time discretisation.
Returns:
timewindow (float): Time window.
iterations (int): Number of interations.
timewindow: float of time window.
iterations: int of number of interations.
"""
# Time window could be a string, float or int, so convert to string then check
@@ -59,18 +59,19 @@ def check_timewindow(timewindow, dt):
return timewindow, iterations
def mpl_plot(w, timewindow, dt, iterations, fft=False):
def mpl_plot(w, timewindow, dt, iterations, fft=False, save=False):
"""Plots waveform and prints useful information about its properties.
Args:
w (class): Waveform class instance.
timewindow (float): Time window.
dt (float): Time discretisation.
iterations (int): Number of iterations.
fft (boolean): Plot FFT switch.
w: Waveform class instance.
timewindow: float of time window.
dt: float of time discretisation.
iterations: int of number of iterations.
fft: boolean flag to plot FFT.
save: boolean flag to save plot to file.
Returns:
plt (object): matplotlib plot object.
plt: matplotlib plot object.
"""
time = np.linspace(0, (iterations - 1) * dt, num=iterations)
@@ -143,12 +144,14 @@ def mpl_plot(w, timewindow, dt, iterations, fft=False):
# Turn on grid
[ax.grid(which='both', axis='both', linestyle='-.') for ax in fig.axes]
# Save a PDF/PNG of the figure
savefile = Path(__file__).parent / w.type
# fig.savefig(savefile.with_suffix('.pdf'), dpi=None, format='pdf',
# bbox_inches='tight', pad_inches=0.1)
# fig.savefig(savefile.with_suffix('.png'), dpi=150, format='png',
# bbox_inches='tight', pad_inches=0.1)
if save:
savefile = Path(__file__).parent / w.type
# Save a PDF of the figure
fig.savefig(savefile.with_suffix('.pdf'), dpi=None, format='pdf',
bbox_inches='tight', pad_inches=0.1)
# Save a PNG of the figure
# fig.savefig(savefile.with_suffix('.png'), dpi=150, format='png',
# bbox_inches='tight', pad_inches=0.1)
return plt
@@ -156,21 +159,27 @@ def mpl_plot(w, timewindow, dt, iterations, fft=False):
if __name__ == "__main__":
# Parse command line arguments
parser = argparse.ArgumentParser(description='Plot built-in waveforms that can be used for sources.', usage='cd gprMax; python -m tools.plot_source_wave type amp freq timewindow dt')
parser = argparse.ArgumentParser(description='Plot built-in waveforms that can be used for sources.',
usage='cd gprMax; python -m toolboxes.Plotting.plot_source_wave type amp freq timewindow dt')
parser.add_argument('type', help='type of waveform', choices=Waveform.types)
parser.add_argument('amp', type=float, help='amplitude of waveform')
parser.add_argument('freq', type=float, help='centre frequency of waveform')
parser.add_argument('timewindow', help='time window to view waveform')
parser.add_argument('dt', type=float, help='time step to view waveform')
parser.add_argument('-fft', action='store_true', help='plot FFT of waveform', default=False)
parser.add_argument('-fft', action='store_true', default=False,
help='plot FFT of waveform')
parser.add_argument('-save', action='store_true', default=False,
help='save plot directly to file, i.e. do not display')
args = parser.parse_args()
# Check waveform parameters
if args.type.lower() not in Waveform.types:
logger.exception(f"The waveform must have one of the following types {', '.join(Waveform.types)}")
logger.exception(f"The waveform must have one of the following types " +
f"{', '.join(Waveform.types)}")
raise ValueError
if args.freq <= 0:
logger.exception('The waveform requires an excitation frequency value of greater than zero')
logger.exception('The waveform requires an excitation frequency value of ' +
'greater than zero')
raise ValueError
# Create waveform instance
@@ -180,5 +189,6 @@ if __name__ == "__main__":
w.freq = args.freq
timewindow, iterations = check_timewindow(args.timewindow, args.dt)
plthandle = mpl_plot(w, timewindow, args.dt, iterations, args.fft)
plthandle = mpl_plot(w, timewindow, args.dt, iterations, fft=args.fft,
save=args.save)
plthandle.show()