你已经派生过 gprMax
镜像自地址
https://gitee.com/sunhf/gprMax.git
已同步 2025-08-07 04:56:51 +08:00
First commit
这个提交包含在:
@@ -0,0 +1,56 @@
|
||||
% outputfiles_mergehdf5.m
|
||||
% Script to merge gprMax output files of A-scans (traces) into a single
|
||||
% HDF5 file
|
||||
%
|
||||
% Craig Warren
|
||||
|
||||
clear all, clc
|
||||
|
||||
[filenames, pathname] = uigetfile('*.out', 'Select gprMax A-scan output files to merge', 'MultiSelect', 'on');
|
||||
|
||||
% Combine A-scans (traces) into a single HDF5 output file
|
||||
if filenames{1} ~= 0
|
||||
[pathstr, basefilename, ext] = fileparts(filenames{1});
|
||||
outputfile = strcat(fullfile(pathname, basefilename(1:end-1)), '_all.out');
|
||||
modelruns = length(filenames);
|
||||
filename = fullfile(pathname, filenames{1});
|
||||
iterations = double(h5readatt(filename, '/', 'Iterations'));
|
||||
dt = h5readatt(filename, '/', 'dt');
|
||||
h5create(outputfile, '/rxs/rx1/Ex', [modelruns iterations]);
|
||||
h5create(outputfile, '/rxs/rx1/Ey', [modelruns iterations]);
|
||||
h5create(outputfile, '/rxs/rx1/Ez', [modelruns iterations]);
|
||||
h5create(outputfile, '/rxs/rx1/Hx', [modelruns iterations]);
|
||||
h5create(outputfile, '/rxs/rx1/Hy', [modelruns iterations]);
|
||||
h5create(outputfile, '/rxs/rx1/Hz', [modelruns iterations]);
|
||||
h5writeatt(outputfile, '/', 'Iterations', iterations);
|
||||
h5writeatt(outputfile, '/', 'dt', dt);
|
||||
Ex = zeros(iterations, modelruns);
|
||||
Ey = zeros(iterations, modelruns);
|
||||
Ez = zeros(iterations, modelruns);
|
||||
Hx = zeros(iterations, modelruns);
|
||||
Hy = zeros(iterations, modelruns);
|
||||
Hz = zeros(iterations, modelruns);
|
||||
for rx=1:modelruns
|
||||
filename = fullfile(pathname, filenames{rx});
|
||||
Ex(:, rx) = h5read(filename, '/rxs/rx1/Ex');
|
||||
Ey(:, rx) = h5read(filename, '/rxs/rx1/Ey');
|
||||
Ez(:, rx) = h5read(filename, '/rxs/rx1/Ez');
|
||||
Hx(:, rx) = h5read(filename, '/rxs/rx1/Hx');
|
||||
Hy(:, rx) = h5read(filename, '/rxs/rx1/Hy');
|
||||
Hz(:, rx) = h5read(filename, '/rxs/rx1/Hz');
|
||||
end
|
||||
h5write(outputfile, '/rxs/rx1/Ex', Ex');
|
||||
h5write(outputfile, '/rxs/rx1/Ey', Ey');
|
||||
h5write(outputfile, '/rxs/rx1/Ez', Ez');
|
||||
h5write(outputfile, '/rxs/rx1/Hx', Hx');
|
||||
h5write(outputfile, '/rxs/rx1/Hy', Hy');
|
||||
h5write(outputfile, '/rxs/rx1/Hz', Hz');
|
||||
prompt = 'Do you want to remove the multiple individual output files? [y] or n: ';
|
||||
check = input(prompt,'s');
|
||||
if isempty(check) || check == 'y'
|
||||
for f=1:length(filenames)
|
||||
filename = fullfile(pathname, filenames{f});
|
||||
delete(filename);
|
||||
end
|
||||
end
|
||||
end
|
@@ -0,0 +1,88 @@
|
||||
% plot_fields_Ascan.m
|
||||
% Script to save and plot EM fields from a gprMax A-scan
|
||||
%
|
||||
% Craig Warren
|
||||
|
||||
clear all, clc
|
||||
|
||||
[filename, pathname] = uigetfile('*.out', 'Select gprMax A-scan output file to plot');
|
||||
fullfilename = strcat(pathname, filename);
|
||||
|
||||
if filename ~= 0
|
||||
header.title = h5readatt(fullfilename, '/', 'Title');
|
||||
header.iterations = double(h5readatt(fullfilename,'/', 'Iterations'));
|
||||
tmp = h5readatt(fullfilename, '/', 'dx, dy, dz');
|
||||
header.dx = tmp(1);
|
||||
header.dy = tmp(2);
|
||||
header.dz = tmp(3);
|
||||
header.dt = h5readatt(fullfilename, '/', 'dt');
|
||||
header.ntx = h5readatt(fullfilename, '/', 'ntx');
|
||||
header.nrx = h5readatt(fullfilename, '/', 'nrx');
|
||||
|
||||
% Time vector for plotting
|
||||
time = linspace(0, (header.iterations)*(header.dt)*1E9, header.iterations);
|
||||
|
||||
% Initialise structure for field arrays
|
||||
fields.ex = zeros(header.iterations, header.nrx);
|
||||
fields.ey = zeros(header.iterations, header.nrx);
|
||||
fields.ez = zeros(header.iterations, header.nrx);
|
||||
fields.hx = zeros(header.iterations, header.nrx);
|
||||
fields.hy = zeros(header.iterations, header.nrx);
|
||||
fields.hz = zeros(header.iterations, header.nrx);
|
||||
|
||||
prompt = 'Would you like to save a PDF of the plot(s)? y or [n]: ';
|
||||
pdf = input(prompt,'s');
|
||||
|
||||
% Save and plot fields from each receiver
|
||||
for n=1:header.nrx
|
||||
path = strcat('/rxs/rx', num2str(n), '/');
|
||||
tmp = h5read(fullfilename, strcat(path, 'Position'));
|
||||
header.rx(n) = tmp(1);
|
||||
header.ry(n) = tmp(2);
|
||||
header.rz(n) = tmp(3);
|
||||
fields.ex(:,n) = h5read(fullfilename, strcat(path, 'Ex'));
|
||||
fields.ey(:,n) = h5read(fullfilename, strcat(path, 'Ey'));
|
||||
fields.ez(:,n) = h5read(fullfilename, strcat(path, 'Ez'));
|
||||
fields.hx(:,n) = h5read(fullfilename, strcat(path, 'Hx'));
|
||||
fields.hy(:,n) = h5read(fullfilename, strcat(path, 'Hy'));
|
||||
fields.hz(:,n) = h5read(fullfilename, strcat(path, 'Hz'));
|
||||
|
||||
fh1=figure('Name', strcat('rx', num2str(n)));
|
||||
ax1 = subplot(2,3,1); plot(time, fields.ex(:,n), 'r', 'LineWidth', 2), grid on, xlabel('Time [ns]'), ylabel('Field strength [V/m]'), title('E_x')
|
||||
ax2 = subplot(2,3,2); plot(time, fields.ey(:,n), 'r', 'LineWidth', 2), grid on, xlabel('Time [ns]'), ylabel('Field strength [V/m]'), title('E_y')
|
||||
ax3 = subplot(2,3,3); plot(time, fields.ez(:,n), 'r', 'LineWidth', 2), grid on, xlabel('Time [ns]'), ylabel('Field strength [V/m]'), title('E_z')
|
||||
ax4 = subplot(2,3,4); plot(time, fields.hx(:,n), 'b', 'LineWidth', 2), grid on, xlabel('Time [ns]'), ylabel('Field strength [A/m]'), title('H_x')
|
||||
ax5 = subplot(2,3,5); plot(time, fields.hy(:,n), 'b', 'LineWidth', 2), grid on, xlabel('Time [ns]'), ylabel('Field strength [A/m]'), title('H_y')
|
||||
ax6 = subplot(2,3,6); plot(time, fields.hz(:,n), 'b', 'LineWidth', 2), grid on, xlabel('Time [ns]'), ylabel('Field strength [A/m]'), title('H_z')
|
||||
ax1.FontSize = 16;
|
||||
ax2.FontSize = ax1.FontSize;
|
||||
ax3.FontSize = ax1.FontSize;
|
||||
ax4.FontSize = ax1.FontSize;
|
||||
ax5.FontSize = ax1.FontSize;
|
||||
ax6.FontSize = ax1.FontSize;
|
||||
|
||||
% Options to create a nice looking figure for display and printing
|
||||
set(fh1,'Color','white','Menubar','none');
|
||||
X = 60; % Paper size
|
||||
Y = 30; % Paper size
|
||||
xMargin = 0; % Left/right margins from page borders
|
||||
yMargin = 0; % Bottom/top margins from page borders
|
||||
xSize = X - 2*xMargin; % Figure size on paper (width & height)
|
||||
ySize = Y - 2*yMargin; % Figure size on paper (width & height)
|
||||
|
||||
% Figure size displayed on screen
|
||||
set(fh1, 'Units','centimeters', 'Position', [0 0 xSize ySize])
|
||||
movegui(fh1, 'center')
|
||||
|
||||
% Figure size printed on paper
|
||||
set(fh1,'PaperUnits', 'centimeters')
|
||||
set(fh1,'PaperSize', [X Y])
|
||||
set(fh1,'PaperPosition', [xMargin yMargin xSize ySize])
|
||||
set(fh1,'PaperOrientation', 'portrait')
|
||||
|
||||
% Export to PDF
|
||||
if pdf == 'y'
|
||||
print(fh1, '-dpdf', '-r0', strcat(fullfilename(1:end-4), '_rx', num2str(n), '.pdf'));
|
||||
end
|
||||
end
|
||||
end
|
@@ -0,0 +1,65 @@
|
||||
% plot_fields_Bscan.m
|
||||
% Script to plot EM fields from a gprMax B-scan
|
||||
%
|
||||
% Craig Warren
|
||||
|
||||
clear all, clc
|
||||
|
||||
[filename, pathname] = uigetfile('*.out', 'Select gprMax output file to plot B-scan', 'MultiSelect', 'on');
|
||||
filename = fullfile(pathname, filename);
|
||||
|
||||
% Open file and read fields
|
||||
if filename ~= 0
|
||||
iterations = double(h5readatt(filename, '/', 'Iterations'));
|
||||
dt = h5readatt(filename, '/', 'dt');
|
||||
Ex = h5read(filename, '/rxs/rx1/Ex')';
|
||||
Ey = h5read(filename, '/rxs/rx1/Ey')';
|
||||
Ez = h5read(filename, '/rxs/rx1/Ez')';
|
||||
Hx = h5read(filename, '/rxs/rx1/Hx')';
|
||||
Hy = h5read(filename, '/rxs/rx1/Hy')';
|
||||
Hz = h5read(filename, '/rxs/rx1/Hz')';
|
||||
end
|
||||
|
||||
prompt = 'Would you like to save a PDF of the plot? y or [n]: ';
|
||||
pdf = input(prompt,'s');
|
||||
|
||||
prompt = 'Which field do you want to view? Ex, Ey, or Ez: ';
|
||||
field = input(prompt,'s');
|
||||
field = eval(field);
|
||||
time = 0:dt:iterations * dt;
|
||||
traces = 0:size(field,2);
|
||||
|
||||
fh1=figure('Name', filename);
|
||||
clims = [-max(max(abs(field))) max(max(abs(field)))];
|
||||
im = imagesc(traces, time, field, clims);
|
||||
xlabel('Trace number');
|
||||
ylabel('Time [s]');
|
||||
c = colorbar;
|
||||
c.Label.String = 'Field strength [V/m]';
|
||||
ax = gca;
|
||||
ax.FontSize = 16;
|
||||
xlim([0 traces(end)]);
|
||||
|
||||
% Options to create a nice looking figure for display and printing
|
||||
set(fh1,'Color','white','Menubar','none');
|
||||
X = 60; % Paper size
|
||||
Y = 30; % Paper size
|
||||
xMargin = 0; % Left/right margins from page borders
|
||||
yMargin = 0; % Bottom/top margins from page borders
|
||||
xSize = X - 2*xMargin; % Figure size on paper (width & height)
|
||||
ySize = Y - 2*yMargin; % Figure size on paper (width & height)
|
||||
|
||||
% Figure size displayed on screen
|
||||
set(fh1, 'Units','centimeters', 'Position', [0 0 xSize ySize])
|
||||
movegui(fh1, 'center')
|
||||
|
||||
% Figure size printed on paper
|
||||
set(fh1,'PaperUnits', 'centimeters')
|
||||
set(fh1,'PaperSize', [X Y])
|
||||
set(fh1,'PaperPosition', [xMargin yMargin xSize ySize])
|
||||
set(fh1,'PaperOrientation', 'portrait')
|
||||
|
||||
% Export to PDF
|
||||
if pdf == 'y'
|
||||
print(fh1, '-dpdf', '-r0', strcat(filename(1:end-4), '.pdf'));
|
||||
end
|
@@ -0,0 +1,80 @@
|
||||
# Copyright (C) 2015: The University of Edinburgh
|
||||
# Authors: Craig Warren and Antonis Giannopoulos
|
||||
#
|
||||
# This file is part of gprMax.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with gprMax. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from paraview.simple import *
|
||||
from xml.etree import ElementTree as ET
|
||||
|
||||
# Disable automatic camera reset on 'Show'
|
||||
paraview.simple._DisableFirstRenderCameraReset()
|
||||
|
||||
# Get whatever source is loaded (should be model)
|
||||
model = GetActiveSource()
|
||||
|
||||
# Get active view
|
||||
renderview = GetActiveView()
|
||||
|
||||
# Show data in view
|
||||
Show(model, renderview)
|
||||
|
||||
# Reset view to fit data
|
||||
renderview.ResetCamera()
|
||||
|
||||
# List to hold material identifiers written in VTK file in tags <gprMax3D> <Material>
|
||||
materials = []
|
||||
with open(model.FileName[0], 'r') as f:
|
||||
for line in f:
|
||||
if line.startswith('<Material'):
|
||||
line.rstrip('\n')
|
||||
tmp = (float(ET.fromstring(line).text), ET.fromstring(line).attrib.get('name'))
|
||||
materials.append(tmp)
|
||||
|
||||
# If the geometry file does not contain any information on materials names
|
||||
if not materials:
|
||||
# Get range of data and set upper bound
|
||||
datarange = model.CellData.GetArray(0).GetRange()
|
||||
|
||||
for x in range(0, int(datarange[1]) + 1):
|
||||
threshold = Threshold(Input=model)
|
||||
threshold.ThresholdRange = [x, x]
|
||||
|
||||
if x != 1:
|
||||
# Turn on show for all materials except free_space
|
||||
thresholdDisplay = Show(threshold, renderview)
|
||||
|
||||
# Name materials
|
||||
if x == 0:
|
||||
RenameSource('pec', threshold)
|
||||
elif x == 1:
|
||||
RenameSource('free_space', threshold)
|
||||
else:
|
||||
RenameSource('material ' + str(x), threshold)
|
||||
|
||||
else:
|
||||
# Create threshold for materials (name and numeric value)
|
||||
for material in range(len(materials)):
|
||||
threshold = Threshold(Input=model)
|
||||
threshold.ThresholdRange = [materials[material][0], materials[material][0]]
|
||||
|
||||
RenameSource(materials[material][1], threshold)
|
||||
|
||||
if materials[material][0] != 1:
|
||||
# Show data in view
|
||||
thresholdDisplay = Show(threshold, renderview)
|
||||
|
||||
# Show color bar/color legend
|
||||
# thresholdDisplay.SetScalarBarVisibility(renderview, False)
|
0
tools/__init__.py
普通文件
0
tools/__init__.py
普通文件
298
tools/inputfile_new2old.py
普通文件
298
tools/inputfile_new2old.py
普通文件
@@ -0,0 +1,298 @@
|
||||
# Copyright (C) 2015: The University of Edinburgh
|
||||
# Authors: Craig Warren and Antonis Giannopoulos
|
||||
#
|
||||
# This file is part of gprMax.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with gprMax. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import argparse, os, sys
|
||||
import numpy as np
|
||||
|
||||
from gprMax.exceptions import CmdInputError
|
||||
|
||||
"""Converts new to old style input files."""
|
||||
|
||||
# Parse command line arguments
|
||||
parser = argparse.ArgumentParser(description='Converts new style input file to old style input file.', usage='cd gprMax; python -m tools.inputfile_old2new inputfile')
|
||||
parser.add_argument('inputfile', help='name of input file including path')
|
||||
args = parser.parse_args()
|
||||
|
||||
inputfile = args.inputfile
|
||||
|
||||
with open(inputfile, 'r') as f:
|
||||
# Strip out any newline characters and comments that must begin with double hashes
|
||||
inputlines = [line.rstrip() for line in f]
|
||||
|
||||
# New file name base
|
||||
try:
|
||||
newfile = inputfile.split('.')[0]
|
||||
except:
|
||||
pass
|
||||
newfile += '_oldstyle'
|
||||
|
||||
print("Attempting to convert inputfile '{}' to use old syntax...\n".format(inputfile))
|
||||
|
||||
newcommands = ['#add_dispersion_lorenz', '#add_dispersion_drude', '#fractal_box', '#soil_peplinski', '#python', '#end_python', '#add_surface_roughness', '#add_surface_water', '#add_grass', '#magnetic_dipole', '#pml_cfs', '#cylindrical_sector', '#time_step_limit_type']
|
||||
materials = {}
|
||||
debyes = []
|
||||
waveforms = []
|
||||
badwaveforms = ['gaussiandotdot', 'ricker']
|
||||
hertziandipoles = []
|
||||
voltagesources = []
|
||||
analysiscmds = []
|
||||
ompthreadscheck = False
|
||||
pmlcheck = False
|
||||
messagescheck = False
|
||||
|
||||
lindex = 0
|
||||
while(lindex < len(inputlines)):
|
||||
|
||||
if inputlines[lindex].startswith('#') and not inputlines[lindex].startswith('##'):
|
||||
cmd = inputlines[lindex].split(':')
|
||||
cmdname = cmd[0].lower()
|
||||
params = cmd[1].split()
|
||||
|
||||
if cmdname == '#domain':
|
||||
domain = (float(params[0]), float(params[1]), float(params[2]))
|
||||
lindex += 1
|
||||
|
||||
elif cmdname == '#dx_dy_dz':
|
||||
dx_dy_dz = (float(params[0]), float(params[1]), float(params[2]))
|
||||
lindex += 1
|
||||
|
||||
elif cmdname == '#time_window':
|
||||
if '.' in params[0] or 'e' in params[0].lower():
|
||||
timewindow = float(params[0])
|
||||
else:
|
||||
timewindow = int(params[0])
|
||||
lindex += 1
|
||||
|
||||
elif cmdname == '#messages':
|
||||
messagescheck = True
|
||||
|
||||
elif cmdname == '#voltage_source':
|
||||
voltagesources.append(inputlines[lindex])
|
||||
inputlines.pop(lindex)
|
||||
|
||||
elif cmdname == '#hertzian_dipole':
|
||||
hertziandipoles.append(inputlines[lindex])
|
||||
inputlines.pop(lindex)
|
||||
|
||||
elif cmdname == '#rx':
|
||||
analysiscmds.append(inputlines[lindex])
|
||||
inputlines.pop(lindex)
|
||||
|
||||
elif cmdname == '#waveform':
|
||||
waveforms.append(inputlines[lindex])
|
||||
inputlines.pop(lindex)
|
||||
|
||||
elif cmdname == '#material':
|
||||
materials[lindex] = inputlines[lindex]
|
||||
lindex += 1
|
||||
|
||||
elif cmdname == '#add_dispersion_debye':
|
||||
debyes.append(inputlines[lindex])
|
||||
inputlines.pop(lindex)
|
||||
|
||||
elif cmdname == '#triangle':
|
||||
# Syntax of command: #triangle: x1 y1 z1 x2 y2 z2 x3 y3 z3 thickness ID
|
||||
if float(params[9]) == 0:
|
||||
replacement = '#triangle: {} {} {} {} {} {} {} {} {} {}'.format(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7], params[8], params[10])
|
||||
else:
|
||||
replacement = '#wedge: {} {} {} {} {} {} {} {} {} {} {}'.format(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7], params[8], params[9], params[10])
|
||||
print("Command '{}', replaced with '{}'".format(inputlines[lindex], replacement))
|
||||
inputlines.pop(lindex)
|
||||
inputlines.insert(lindex, replacement)
|
||||
lindex += 1
|
||||
|
||||
elif cmdname == '#cylinder':
|
||||
# Syntax of command: #cylinder: x1 y1 z1 x2 y2 z2 radius ID
|
||||
replacement = '#cylinder_new: {} {} {} {} {} {} {} {}'.format(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7])
|
||||
print("Command '{}', replaced with '{}'".format(inputlines[lindex], replacement))
|
||||
inputlines.pop(lindex)
|
||||
inputlines.insert(lindex, replacement)
|
||||
lindex += 1
|
||||
|
||||
elif cmdname == '#pml_cells':
|
||||
pmlcheck = True
|
||||
# Syntax of command: #pml_cells: xminus yminus zminus xplus yplus zplus or #pml_cells: i1 (assumes latter behaviour)
|
||||
replacement = '#pml_layers: {}'.format(params[0])
|
||||
print("Command '{}', replaced with '{}'".format(inputlines[lindex], replacement))
|
||||
inputlines.pop(lindex)
|
||||
inputlines.insert(lindex, replacement)
|
||||
lindex += 1
|
||||
|
||||
elif cmdname == '#num_threads':
|
||||
ompthreadscheck = True
|
||||
# Set number of threads to number of physical CPU cores, i.e. avoid hyperthreading with OpenMP for now
|
||||
if sys.platform == 'darwin':
|
||||
nthreads = int(os.popen('sysctl hw.physicalcpu').readlines()[0].split(':')[1].strip())
|
||||
elif sys.platform == 'win32':
|
||||
# Consider using wmi tools to check hyperthreading on Windows
|
||||
nthreads = os.cpu_count()
|
||||
elif 'linux' in sys.platform:
|
||||
lscpu = os.popen('lscpu').readlines()
|
||||
cpusockets = [item for item in lscpu if item.startswith('Socket(s)')]
|
||||
cpusockets = int(cpusockets[0].split(':')[1].strip())
|
||||
corespersocket = [item for item in lscpu if item.startswith('Core(s) per socket')]
|
||||
corespersocket = int(corespersocket[0].split(':')[1].strip())
|
||||
nthreads = cpusockets * corespersocket
|
||||
else:
|
||||
nthreads = os.cpu_count()
|
||||
# Syntax of command: #num_threads: nthreads
|
||||
replacement = '#num_of_procs: {}'.format(nthreads)
|
||||
print("Command '{}', replaced with '{}'".format(inputlines[lindex], replacement))
|
||||
inputlines.pop(lindex)
|
||||
analysiscmds.append(replacement)
|
||||
lindex += 1
|
||||
|
||||
elif cmdname == '#snapshot':
|
||||
# Syntax of command: #snapshot: x1 y1 z1 x2 y2 z2 dx dy dz time filename
|
||||
replacement = '#snapshot: {} {} {} {} {} {} {} {} {} {} {} v'.format(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7], params[8], params[9], params[10])
|
||||
print("Command '{}', replaced with '{}'".format(inputlines[lindex], replacement))
|
||||
inputlines.pop(lindex)
|
||||
analysiscmds.append(replacement)
|
||||
lindex += 1
|
||||
|
||||
elif cmdname == '#geometry_view':
|
||||
# Syntax of command: #geometry_vtk: x1 y1 z1 x2 y2 z2 dx dy dz filename type
|
||||
replacement = '#geometry_vtk: {} {} {} {} {} {} {} {} {} {} {}'.format(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7], params[8], params[9], params[10])
|
||||
print("Command '{}', replaced with '{}'".format(inputlines[lindex], replacement))
|
||||
inputlines.pop(lindex)
|
||||
inputlines.insert(lindex, replacement)
|
||||
lindex += 1
|
||||
|
||||
elif cmdname in newcommands:
|
||||
print("Command '{}' cannot be used in the old version of gprMax.".format(inputlines[lindex]))
|
||||
inputlines.pop(lindex)
|
||||
|
||||
else:
|
||||
lindex += 1
|
||||
|
||||
else:
|
||||
lindex +=1
|
||||
|
||||
# If messages not found set to on
|
||||
if not messagescheck:
|
||||
cmd = '#messages: y'
|
||||
print("Command '{}' added.".format(cmd))
|
||||
inputlines.append(cmd)
|
||||
|
||||
# Detect number of CPUs/cores on machine and set OpenMP threads if not already set
|
||||
if not ompthreadscheck:
|
||||
# Set number of threads to number of physical CPU cores, i.e. avoid hyperthreading with OpenMP for now
|
||||
if sys.platform == 'darwin':
|
||||
nthreads = int(os.popen('sysctl hw.physicalcpu').readlines()[0].split(':')[1].strip())
|
||||
elif sys.platform == 'win32':
|
||||
# Consider using wmi tools to check hyperthreading on Windows
|
||||
nthreads = os.cpu_count()
|
||||
elif 'linux' in sys.platform:
|
||||
lscpu = os.popen('lscpu').readlines()
|
||||
cpusockets = [item for item in lscpu if item.startswith('Socket(s)')]
|
||||
cpusockets = int(cpusockets[0].split(':')[1].strip())
|
||||
corespersocket = [item for item in lscpu if item.startswith('Core(s) per socket')]
|
||||
corespersocket = int(corespersocket[0].split(':')[1].strip())
|
||||
nthreads = cpusockets * corespersocket
|
||||
else:
|
||||
nthreads = os.cpu_count()
|
||||
cmd = '#num_of_procs: {}'.format(nthreads)
|
||||
print("Command '{}' added.".format(cmd))
|
||||
inputlines.append(cmd)
|
||||
|
||||
# Add the default PML if not already set
|
||||
if not pmlcheck:
|
||||
cmd1 = '#abc_type: pml'
|
||||
cmd2 = '#pml_layers: 10'
|
||||
print("Commands '{}' and '{}' added.".format(cmd1, cmd2))
|
||||
inputlines.append(cmd1)
|
||||
inputlines.append(cmd2)
|
||||
|
||||
# Process materials
|
||||
for position, material in materials.items():
|
||||
params = material.split()
|
||||
debye = next((debye for debye in debyes if debye.split()[-1] == params[5]), None)
|
||||
if debye:
|
||||
if len(debye.split()) > 5:
|
||||
raise CmdInputError("Command '{}' cannot be used in the old version of gprMax as it only supports materials with a single Debye pole.".format(''.join(debye)))
|
||||
medium = '#medium: {} {} {} {} {} {} {}'.format(float(params[1]) + float(debye.split()[2]), params[1], float(debye.split()[3]), params[2], params[3], params[4], params[5])
|
||||
print("Commands '{}' and '{}', replaced with '{}'".format(material, debye, medium))
|
||||
else:
|
||||
medium = '#medium: {} 0 0 {} {} {} {}'.format(params[1], params[2], params[3], params[4], params[5])
|
||||
print("Command '{}', replaced with '{}'".format(material, medium))
|
||||
inputlines[position] = medium
|
||||
|
||||
|
||||
# Create #analysis block
|
||||
outputfile = newfile.split(os.sep)
|
||||
analysis = '#analysis: 1 {} b'.format(outputfile[-1] + '.out')
|
||||
analysiscmds.insert(0, analysis)
|
||||
|
||||
|
||||
# Convert #hertzian_dipole and #waveform to #tx and #hertzian_dipole
|
||||
for source in hertziandipoles:
|
||||
params = source.split()
|
||||
if len(params) > 6:
|
||||
ID = params[7]
|
||||
tx = '#tx: {} {} {} {} {} {} {}'.format(params[1], params[2], params[3], params[4], ID, params[5], params[6])
|
||||
else:
|
||||
ID = params[5]
|
||||
tx = '#tx: {} {} {} {} {} {} {}'.format(params[1], params[2], params[3], params[4], ID, 0, timewindow)
|
||||
|
||||
waveform = next(waveform for waveform in waveforms if waveform.split()[4] == ID)
|
||||
waveformparams = waveform.split()
|
||||
if waveformparams[1] is badwaveforms:
|
||||
raise CmdInputError("Waveform types {} are not compatible between new and old versions of gprMax.".format(''.join(badwaveforms)))
|
||||
elif waveformparams[1] == 'gaussiandotnorm':
|
||||
waveformparams[1] = 'ricker'
|
||||
hertzian = '#hertzian_dipole: {} {} {} {}'.format(waveformparams[2], waveformparams[3], waveformparams[1], waveformparams[4])
|
||||
|
||||
print("Commands '{}' and '{}', replaced with '{}' and '{}'".format(source, waveform, tx, hertzian))
|
||||
inputlines.append(hertzian)
|
||||
analysiscmds.append(tx)
|
||||
|
||||
|
||||
# Convert #voltage_source and #waveform to #tx and #voltage_source
|
||||
for source in voltagesources:
|
||||
params = source.split()
|
||||
if len(params) > 7:
|
||||
ID = params[8]
|
||||
tx = '#tx: {} {} {} {} {} {} {}'.format(params[1], params[2], params[3], params[4], ID, params[6], params[7])
|
||||
else:
|
||||
ID = params[6]
|
||||
tx = '#tx: {} {} {} {} {} {} {}'.format(params[1], params[2], params[3], params[4], ID, 0, timewindow)
|
||||
|
||||
waveform = next(waveform for waveform in waveforms if waveform.split()[4] == ID)
|
||||
waveformparams = waveform.split()
|
||||
if waveformparams[1] is badwaveforms:
|
||||
raise CmdInputError("Waveform types {} are not compatible between new and old versions of gprMax.".format(''.join(badwaveforms)))
|
||||
elif waveformparams[1] == 'gaussiandotnorm':
|
||||
waveformparams[1] = 'ricker'
|
||||
voltagesource = '#voltage_source: {} {} {} {} {}'.format(waveformparams[2], waveformparams[3], waveformparams[1], params[5], waveformparams[4])
|
||||
|
||||
print("Commands '{}' and '{}', replaced with '{}' and '{}'".format(source, waveform, tx, voltagesource))
|
||||
inputlines.append(voltagesource)
|
||||
analysiscmds.append(tx)
|
||||
|
||||
inputlines += analysiscmds
|
||||
inputlines.append('#end_analysis:')
|
||||
|
||||
|
||||
# Write new input file
|
||||
newinputfile = newfile + '.in'
|
||||
|
||||
with open(newinputfile, 'w') as f:
|
||||
for line in inputlines:
|
||||
f.write('{}\n'.format(line))
|
||||
|
||||
print("\nWritten new input file: '{}'".format(newinputfile))
|
264
tools/inputfile_old2new.py
普通文件
264
tools/inputfile_old2new.py
普通文件
@@ -0,0 +1,264 @@
|
||||
# Copyright (C) 2015: The University of Edinburgh
|
||||
# Authors: Craig Warren and Antonis Giannopoulos
|
||||
#
|
||||
# This file is part of gprMax.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with gprMax. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import argparse
|
||||
|
||||
from gprMax.exceptions import CmdInputError
|
||||
|
||||
"""Converts old to new style input files."""
|
||||
|
||||
# Parse command line arguments
|
||||
parser = argparse.ArgumentParser(description='Converts old style input file to new style input file.', usage='cd gprMax; python -m tools.inputfile_new2old inputfile')
|
||||
parser.add_argument('inputfile', help='name of input file including path')
|
||||
args = parser.parse_args()
|
||||
|
||||
inputfile = args.inputfile
|
||||
|
||||
with open(inputfile, 'r') as f:
|
||||
# Strip out any newline characters and comments that must begin with double hashes
|
||||
inputlines = [line.rstrip() for line in f]
|
||||
|
||||
# New file name base
|
||||
try:
|
||||
newfile = inputfile.split('.')[0]
|
||||
except:
|
||||
pass
|
||||
newfile += '_newstyle'
|
||||
|
||||
print("Attempting to convert inputfile '{}' to use new syntax...\n".format(inputfile))
|
||||
|
||||
txs = []
|
||||
badwaveforms = ['gaussiandot', 'gaussiandotdot']
|
||||
voltagesources = []
|
||||
hertziandipoles = []
|
||||
|
||||
lindex = 0
|
||||
while(lindex < len(inputlines)):
|
||||
|
||||
if inputlines[lindex].startswith('#') and not inputlines[lindex].startswith('##'):
|
||||
cmd = inputlines[lindex].split(':')
|
||||
cmdname = cmd[0].lower()
|
||||
params = cmd[1].split()
|
||||
|
||||
if cmdname == '#domain':
|
||||
domain = (float(params[0]), float(params[1]), float(params[2]))
|
||||
lindex += 1
|
||||
|
||||
elif cmdname == '#dx_dy_dz':
|
||||
dx_dy_dz = (float(params[0]), float(params[1]), float(params[2]))
|
||||
lindex += 1
|
||||
|
||||
elif cmdname == '#time_window':
|
||||
params = params[0].lower()
|
||||
if '.' in params[0] or 'e' in params[0].lower():
|
||||
timewindow = float(params[0])
|
||||
else:
|
||||
timewindow = int(params[0])
|
||||
lindex += 1
|
||||
|
||||
elif cmdname == '#num_of_procs':
|
||||
# Syntax of old command: #num_of_procs: nthreads
|
||||
replacement = '#num_threads: {}'.format(params[0])
|
||||
print("Command '{}', replaced with '{}'".format(inputlines[lindex], replacement))
|
||||
inputlines.pop(lindex)
|
||||
inputlines.insert(lindex, replacement)
|
||||
lindex += 1
|
||||
|
||||
elif cmdname == '#tx':
|
||||
txs.append(inputlines[lindex])
|
||||
lindex += 1
|
||||
|
||||
elif cmdname == '#voltage_source':
|
||||
voltagesources.append(inputlines[lindex])
|
||||
lindex += 1
|
||||
|
||||
elif cmdname == '#hertzian_dipole':
|
||||
hertziandipoles.append(inputlines[lindex])
|
||||
lindex += 1
|
||||
|
||||
elif cmdname == '#medium':
|
||||
# Syntax of old command: #medium: e_rs e_inf tau sig_e mu_r sig_m ID
|
||||
replacement = '#material: {} {} {} {} {}'.format(params[0], params[3], params[4], params[5], params[6])
|
||||
print("Command '{}', replaced with '{}'".format(inputlines[lindex], replacement))
|
||||
inputlines.pop(lindex)
|
||||
inputlines.insert(lindex, replacement)
|
||||
if float(params[1]) > 0:
|
||||
replacement = '#add_dispersion_debye: 1 {} {} {}'.format(float(params[0]) - float(params[1]), params[2], params[6])
|
||||
print("Command '{}' added.".format(replacement))
|
||||
inputlines.insert(lindex + 1, replacement)
|
||||
lindex += 1
|
||||
|
||||
elif cmdname == '#triangle':
|
||||
# Syntax of old command: #triangle: x1 y1 z1 x2 y2 z2 x3 y3 z3 ID
|
||||
replacement = '#triangle: {} {} {} {} {} {} {} {} {} {} {}'.format(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7], params[8], 0, params[9])
|
||||
print("Command '{}', replaced with '{}'".format(inputlines[lindex], replacement))
|
||||
inputlines.pop(lindex)
|
||||
inputlines.insert(lindex, replacement)
|
||||
lindex += 1
|
||||
|
||||
elif cmdname == '#wedge':
|
||||
# Syntax of old command: #wedge: x1 y1 z1 x2 y2 z2 x3 y3 z3 thickness ID
|
||||
replacement = '#triangle: {} {} {} {} {} {} {} {} {} {} {}'.format(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7], params[8], params[9], params[10])
|
||||
print("Command '{}', replaced with '{}'".format(inputlines[lindex], replacement))
|
||||
inputlines.pop(lindex)
|
||||
inputlines.insert(lindex, replacement)
|
||||
lindex += 1
|
||||
|
||||
elif cmdname == '#bowtie':
|
||||
print("Command '{}', is no longer supported. You can create the bowtie shape using two triangle commands.".format(inputlines[lindex], replacement))
|
||||
inputlines.pop(lindex)
|
||||
|
||||
elif cmdname == '#cylinder':
|
||||
# Syntax of old command: #cylinder: axis axis_start axis_stop f1 f2 radius ID
|
||||
if params[0] == 'x':
|
||||
replacement = '#cylinder: {} {} {} {} {} {} {} {} {} {} {}'.format(params[1], params[3], params[4], params[2], params[3], params[4], params[5], params[6])
|
||||
elif params[0] == 'y':
|
||||
replacement = '#cylinder: {} {} {} {} {} {} {} {} {} {} {}'.format(params[3], params[1], params[4], params[3], params[2], params[4], params[5], params[6])
|
||||
elif params[0] =='z':
|
||||
replacement = '#cylinder: {} {} {} {} {} {} {} {} {} {} {}'.format(params[3], params[4], params[1], params[3], params[4], params[2], params[5], params[6])
|
||||
print("Command '{}', replaced with '{}'".format(inputlines[lindex], replacement))
|
||||
inputlines.pop(lindex)
|
||||
inputlines.insert(lindex, replacement)
|
||||
lindex += 1
|
||||
|
||||
elif cmdname == '#cylinder_new':
|
||||
# Syntax of old command: #cylinder_new: x1 y1 z1 x2 y2 z2 radius ID
|
||||
replacement = '#cylinder: {} {} {} {} {} {} {} {}'.format(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7])
|
||||
print("Command '{}', replaced with '{}'".format(inputlines[lindex], replacement))
|
||||
inputlines.pop(lindex)
|
||||
inputlines.insert(lindex, replacement)
|
||||
lindex += 1
|
||||
|
||||
elif cmdname == '#cylindrical_segment':
|
||||
print("Command '{}' has been removed as it is no longer supported. You can create a cylindrical segment by using a #box to cut through a #cylinder.".format(inputlines[lindex]))
|
||||
inputlines.pop(lindex)
|
||||
|
||||
elif cmdname == '#media_file':
|
||||
print("Command '{}' has is no longer supported. Please include your materials using the #material command directly in the input file.".format(inputlines[lindex]))
|
||||
inputlines.pop(lindex)
|
||||
|
||||
elif cmdname == '#pml_layers':
|
||||
# Syntax of old command: #pml_layers: num_layers
|
||||
replacement = '#pml_cells: {}'.format(params[0])
|
||||
print("Command '{}', replaced with '{}'".format(inputlines[lindex], replacement))
|
||||
inputlines.pop(lindex)
|
||||
inputlines.insert(lindex, replacement)
|
||||
lindex += 1
|
||||
|
||||
elif cmdname in ['#abc_order', '#abc_type', 'abc_optimisation_angles', '#abc_mixing_parameters', '#abc_stability_factors']:
|
||||
print("Command '{}' has been removed as Higdon Absorbing Boundary Conditions (ABC) are no longer supported. The default ABC is the (better performing) Perfectly Matched Layer (PML).".format(inputlines[lindex]))
|
||||
inputlines.pop(lindex)
|
||||
|
||||
elif cmdname == '#analysis':
|
||||
# Syntax of old command: #analysis: num_model_runs outputfile outputfiletype
|
||||
if int(params[0]) > 1:
|
||||
extra = " To run a model multiple times use the command line option -n, e.g. gprMax {} -n {}".format(inputfile, int(params[0]))
|
||||
else:
|
||||
extra = ''
|
||||
print("Command '{}' has been removed as it is no longer required.{}".format(inputlines[lindex], extra))
|
||||
inputlines.pop(lindex)
|
||||
|
||||
elif cmdname in ['#end_analysis', '#number_of_media', '#nips_number']:
|
||||
print("Command '{}' has been removed as it is no longer required.".format(inputlines[lindex]))
|
||||
inputlines.pop(lindex)
|
||||
|
||||
elif cmdname == '#snapshot':
|
||||
# Syntax of old command: #snapshot: x1 y1 z1 x2 y2 z2 dx dy dz time filename type
|
||||
replacement = '#snapshot: {} {} {} {} {} {} {} {} {} {} {}'.format(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7], params[8], params[9], params[10])
|
||||
print("Command '{}', replaced with '{}'".format(inputlines[lindex], replacement))
|
||||
inputlines.pop(lindex)
|
||||
inputlines.insert(lindex, replacement)
|
||||
lindex += 1
|
||||
|
||||
elif cmdname == '#geometry_file':
|
||||
# Syntax of old command: #geometry_file: filename
|
||||
if params[0].endswith('.geo'):
|
||||
params = params[0].split('.')
|
||||
replacement = '#geometry_view: 0 0 0 {} {} {} {} {} {} {} n'.format(domain[0], domain[1], domain[2], dx_dy_dz[0], dx_dy_dz[1], dx_dy_dz[2], params[0])
|
||||
print("Command '{}', replaced with '{}'. This is a geometry view of the entire domain, sampled at the spatial resolution of the model, using the per Yee cell option (n). You may want to consider taking a smaller geometry view or using a coarser sampling. You may also want to use the per Yee cell edge option (f) to view finer details.".format(inputlines[lindex], replacement))
|
||||
inputlines.pop(lindex)
|
||||
inputlines.insert(lindex, replacement)
|
||||
lindex += 1
|
||||
|
||||
elif cmdname == '#geometry_vtk':
|
||||
# Syntax of old command: #geometry_vtk: x1 y1 z1 x2 y2 z2 dx dy dz filename type
|
||||
replacement = '#geometry_view: {} {} {} {} {} {} {} {} {} {} {}'.format(params[0], params[1], params[2], params[3], params[4], params[5], params[6], params[7], params[8], params[9], params[10])
|
||||
print("Command '{}', replaced with '{}'".format(inputlines[lindex], replacement))
|
||||
inputlines.pop(lindex)
|
||||
inputlines.insert(lindex, replacement)
|
||||
lindex += 1
|
||||
|
||||
elif cmdname in ['#transmission_line', '#plane_wave', '#thin_wire', '#huygens_surface']:
|
||||
raise CmdInputError("Command '{}' has not yet implemented in the new version of gprMax. For now please continue to use the old version.".format(inputlines[lindex]))
|
||||
|
||||
else:
|
||||
lindex += 1
|
||||
|
||||
else:
|
||||
lindex +=1
|
||||
|
||||
# Convert separate #hertzian_dipole and associated #tx to #waveform and #hertzian_dipole
|
||||
for source in hertziandipoles:
|
||||
params = source.split()
|
||||
if params[3] is badwaveforms:
|
||||
raise CmdInputError("Waveform types {} are not compatible between new and old versions of gprMax.".format(''.join(badwaveforms)))
|
||||
elif params[3] == 'ricker':
|
||||
params[3] = 'gaussiandotnorm'
|
||||
waveform = '#waveform: {} {} {} {}'.format(params[3], params[1], params[2], params[4])
|
||||
tx = next(tx for tx in txs if tx.split()[5] == params[4])
|
||||
hertziantx = tx.split()
|
||||
if float(hertziantx[6]) > 0 or float(hertziantx[7]) != timewindow:
|
||||
hertzian = '#hertzian_dipole: {} {} {} {} {} {} {}'.format(hertziantx[1], hertziantx[2], hertziantx[3], hertziantx[4], hertziantx[5], hertziantx[6], hertziantx[7])
|
||||
else:
|
||||
hertzian = '#hertzian_dipole: {} {} {} {} {}'.format(hertziantx[1], hertziantx[2], hertziantx[3], hertziantx[4], hertziantx[5])
|
||||
|
||||
print("Commands '{}' and '{}', replaced with '{}' and '{}'".format(source, tx, waveform, hertzian))
|
||||
inputlines.remove(source)
|
||||
inputlines.remove(tx)
|
||||
inputlines.append(waveform)
|
||||
inputlines.append(hertzian)
|
||||
|
||||
# Convert separate #voltage_source and associated #tx to #waveform and #voltage_source
|
||||
for source in voltagesources:
|
||||
params = source.split()
|
||||
if params[3] is badwaveforms:
|
||||
raise CmdInputError("Waveform types {} are not compatible between new and old versions of gprMax.".format(''.join(badwaveforms)))
|
||||
elif params[3] == 'ricker':
|
||||
params[3] = 'gaussiandotnorm'
|
||||
waveform = '#waveform: {} {} {} {}'.format(params[3], params[1], params[2], params[5])
|
||||
tx = next(tx for tx in txs if tx.split()[5] == params[5])
|
||||
voltagesourcetx = tx.split()
|
||||
if float(voltagesourcetx[6]) > 0 or float(voltagesourcetx[7]) != timewindow:
|
||||
voltagesource = '#voltage_source: {} {} {} {} {} {} {} {}'.format(voltagesourcetx[1], voltagesourcetx[2], voltagesourcetx[3], voltagesourcetx[4], params[4], voltagesourcetx[5], voltagesourcetx[6], voltagesourcetx[7])
|
||||
else:
|
||||
voltagesource = '#voltage_source: {} {} {} {} {} {}'.format(voltagesourcetx[1], voltagesourcetx[2], voltagesourcetx[3], voltagesourcetx[4], params[4], voltagesourcetx[5])
|
||||
|
||||
print("Commands '{}' and '{}', replaced with '{}' and '{}'".format(source, tx, waveform, voltagesource))
|
||||
inputlines.remove(source)
|
||||
inputlines.remove(tx)
|
||||
inputlines.append(waveform)
|
||||
inputlines.append(voltagesource)
|
||||
|
||||
# Write new input file
|
||||
newinputfile = newfile + '.in'
|
||||
|
||||
with open(newinputfile, 'w') as f:
|
||||
for line in inputlines:
|
||||
f.write('{}\n'.format(line))
|
||||
|
||||
print("\nWritten new input file: '{}'".format(newinputfile))
|
159
tools/outputfile_old2hdf5.py
普通文件
159
tools/outputfile_old2hdf5.py
普通文件
@@ -0,0 +1,159 @@
|
||||
# Copyright (C) 2015: The University of Edinburgh
|
||||
# Authors: Craig Warren and Antonis Giannopoulos
|
||||
#
|
||||
# This file is part of gprMax.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with gprMax. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os, struct, argparse
|
||||
import numpy as np
|
||||
|
||||
from gprMax.grid import FDTDGrid
|
||||
from gprMax.receivers import Rx
|
||||
from gprMax.fields_output import prepare_output_file, write_output
|
||||
|
||||
"""Converts old output file to new HDF5 format."""
|
||||
|
||||
# Parse command line arguments
|
||||
parser = argparse.ArgumentParser(description='Converts old output file to new HDF5 format.', usage='cd gprMax; python -m tools.outputfile_old2hdf5 outputfile')
|
||||
parser.add_argument('outputfile', help='name of output file including path')
|
||||
args = parser.parse_args()
|
||||
|
||||
outputfile = args.outputfile
|
||||
G = FDTDGrid()
|
||||
|
||||
print("Reading: '{}'".format(outputfile))
|
||||
|
||||
with open(outputfile, 'rb') as f:
|
||||
# Get information from file header
|
||||
f.read(2)
|
||||
filetype, = struct.unpack('h', f.read(2))
|
||||
myshort, = struct.unpack('h', f.read(2))
|
||||
myfloat, = struct.unpack('h', f.read(2))
|
||||
titlelength, = struct.unpack('h', f.read(2))
|
||||
sourcelength, = struct.unpack('h', f.read(2))
|
||||
medialength, = struct.unpack('h', f.read(2))
|
||||
reserved, = struct.unpack('h', f.read(2))
|
||||
G.title = ''
|
||||
for c in range(titlelength):
|
||||
tmp, = struct.unpack('c', f.read(1))
|
||||
G.title += tmp.decode('utf-8')
|
||||
G.iterations, = struct.unpack('f', f.read(4))
|
||||
G.iterations = int(G.iterations)
|
||||
G.dx, = struct.unpack('f', f.read(4))
|
||||
G.dy, = struct.unpack('f', f.read(4))
|
||||
G.dz, = struct.unpack('f', f.read(4))
|
||||
G.dt, = struct.unpack('f', f.read(4))
|
||||
nsteps, = struct.unpack('h', f.read(2))
|
||||
G.txstepx, = struct.unpack('h', f.read(2))
|
||||
G.txstepy, = struct.unpack('h', f.read(2))
|
||||
G.txstepz, = struct.unpack('h', f.read(2))
|
||||
G.rxstepx, = struct.unpack('h', f.read(2))
|
||||
G.rxstepy, = struct.unpack('h', f.read(2))
|
||||
G.rxstepz, = struct.unpack('h', f.read(2))
|
||||
ntx, = struct.unpack('h', f.read(2))
|
||||
nrx, = struct.unpack('h', f.read(2))
|
||||
nrxbox, = struct.unpack('h', f.read(2))
|
||||
|
||||
# Display some basic information
|
||||
print('Model title: {}'.format(G.title))
|
||||
print('Spatial discretisation: {:.3f} x {:.3f} x {:.3f} m'.format(G.dx, G.dy, G.dz))
|
||||
print('Time step: {:.3e} secs'.format(G.dt))
|
||||
print('Time window: {:.3e} secs ({} iterations)'.format(G.iterations * G.dt, G.iterations))
|
||||
|
||||
# txs
|
||||
for tx in range(ntx):
|
||||
polarisation, = struct.unpack('c', f.read(1))
|
||||
x, = struct.unpack('h', f.read(2))
|
||||
y, = struct.unpack('h', f.read(2))
|
||||
z, = struct.unpack('h', f.read(2))
|
||||
for c in range(sourcelength):
|
||||
tmp, = struct.unpack('c', f.read(1))
|
||||
start, = struct.unpack('f', f.read(4))
|
||||
stop, = struct.unpack('f', f.read(4))
|
||||
# Only want transmitter position information so store in a Rx class for ease
|
||||
t = Rx(positionx=x, positiony=y, positionz=z)
|
||||
G.txs.append(t)
|
||||
|
||||
# rxs
|
||||
for r in range(nrx):
|
||||
x, = struct.unpack('h', f.read(2))
|
||||
y, = struct.unpack('h', f.read(2))
|
||||
z, = struct.unpack('h', f.read(2))
|
||||
r = Rx(positionx=x, positiony=y, positionz=z)
|
||||
G.rxs.append(r)
|
||||
|
||||
# rxboxes
|
||||
for rxbox in range(nrxbox):
|
||||
nrxs, = struct.unpack('h', f.read(2))
|
||||
for rx in range(nrxs):
|
||||
x, = struct.unpack('h', f.read(2))
|
||||
y, = struct.unpack('h', f.read(2))
|
||||
z, = struct.unpack('h', f.read(2))
|
||||
r = Rx(positionx=x, positiony=y, positionz=z)
|
||||
G.rxs.append(r)
|
||||
|
||||
# Fields
|
||||
fieldsdata = np.fromfile(f, dtype=np.float32)
|
||||
ex = np.reshape(fieldsdata[0::9], (len(G.rxs), G.iterations, nsteps), order='F')
|
||||
ey = np.reshape(fieldsdata[1::9], (len(G.rxs), G.iterations, nsteps), order='F')
|
||||
ez = np.reshape(fieldsdata[2::9], (len(G.rxs), G.iterations, nsteps), order='F')
|
||||
hx = np.reshape(fieldsdata[3::9], (len(G.rxs), G.iterations, nsteps), order='F')
|
||||
hy = np.reshape(fieldsdata[4::9], (len(G.rxs), G.iterations, nsteps), order='F')
|
||||
hz = np.reshape(fieldsdata[5::9], (len(G.rxs), G.iterations, nsteps), order='F')
|
||||
ix = np.reshape(fieldsdata[6::9], (len(G.rxs), G.iterations, nsteps), order='F')
|
||||
iy = np.reshape(fieldsdata[7::9], (len(G.rxs), G.iterations, nsteps), order='F')
|
||||
iz = np.reshape(fieldsdata[8::9], (len(G.rxs), G.iterations, nsteps), order='F')
|
||||
|
||||
if nsteps == 1:
|
||||
ex = np.transpose(ex)
|
||||
ey = np.transpose(ey)
|
||||
ez = np.transpose(ez)
|
||||
hx = np.transpose(hx)
|
||||
hy = np.transpose(hy)
|
||||
hz = np.transpose(hz)
|
||||
ix = np.transpose(ix)
|
||||
iy = np.transpose(iy)
|
||||
iz = np.transpose(iz)
|
||||
else:
|
||||
for i in range(len(G.rxs)):
|
||||
ex[:,i,:] = ex[i,:,:]
|
||||
ey[:,i,:] = ey[i,:,:]
|
||||
ez[:,i,:] = ez[i,:,:]
|
||||
hx[:,i,:] = hx[i,:,:]
|
||||
hy[:,i,:] = hy[i,:,:]
|
||||
hz[:,i,:] = hz[i,:,:]
|
||||
ix[:,i,:] = ix[i,:,:]
|
||||
iy[:,i,:] = iy[i,:,:]
|
||||
iz[:,i,:] = iz[i,:,:]
|
||||
|
||||
# Remove any singleton dimensions
|
||||
ex = np.squeeze(ex)
|
||||
ey = np.squeeze(ey)
|
||||
ez = np.squeeze(ez)
|
||||
hx = np.squeeze(hx)
|
||||
hy = np.squeeze(hy)
|
||||
hz = np.squeeze(hz)
|
||||
ix = np.squeeze(ix)
|
||||
iy = np.squeeze(iy)
|
||||
iz = np.squeeze(iz)
|
||||
|
||||
# Create new HDF5 outputfile
|
||||
newoutputfile = os.path.splitext(outputfile)
|
||||
newoutputfile = newoutputfile[0] + '_hdf5.out'
|
||||
f = prepare_output_file(newoutputfile, G)
|
||||
write_output(f, np.s_[:], ex, ey, ez, hx, hy, hz, G)
|
||||
|
||||
print("Written: '{}'".format(newoutputfile))
|
||||
|
71
tools/outputfiles_mergehdf5.py
普通文件
71
tools/outputfiles_mergehdf5.py
普通文件
@@ -0,0 +1,71 @@
|
||||
# Copyright (C) 2015: The University of Edinburgh
|
||||
# Authors: Craig Warren and Antonis Giannopoulos
|
||||
#
|
||||
# This file is part of gprMax.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with gprMax. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os, argparse
|
||||
import h5py
|
||||
import numpy as np
|
||||
|
||||
"""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_mergehdf5 basefilename modelruns')
|
||||
parser.add_argument('basefilename', help='base name of output file series including path')
|
||||
parser.add_argument('modelruns', type=int, help='number of model runs, i.e. number of output files to merge')
|
||||
args = parser.parse_args()
|
||||
|
||||
basefilename = args.basefilename
|
||||
modelruns = args.modelruns
|
||||
outputfile = basefilename + '_all.out'
|
||||
path = '/rxs/rx1'
|
||||
|
||||
# Combined output file
|
||||
fout = h5py.File(outputfile, 'w')
|
||||
|
||||
# Add positional data for rxs
|
||||
for rx in range(modelruns):
|
||||
fin = h5py.File(basefilename + str(rx + 1) + '.out', 'r')
|
||||
if rx == 0:
|
||||
fout.attrs['Iterations'] = fin.attrs['Iterations']
|
||||
fout.attrs['dt'] = fin.attrs['dt']
|
||||
fields = fout.create_group(path)
|
||||
fields['Ex'] = np.zeros((fout.attrs['Iterations'], modelruns), dtype=fin[path + '/Ex'].dtype)
|
||||
fields['Ey'] = np.zeros((fout.attrs['Iterations'], modelruns), dtype=fin[path + '/Ex'].dtype)
|
||||
fields['Ez'] = np.zeros((fout.attrs['Iterations'], modelruns), dtype=fin[path + '/Ex'].dtype)
|
||||
fields['Hx'] = np.zeros((fout.attrs['Iterations'], modelruns), dtype=fin[path + '/Ex'].dtype)
|
||||
fields['Hy'] = np.zeros((fout.attrs['Iterations'], modelruns), dtype=fin[path + '/Ex'].dtype)
|
||||
fields['Hz'] = np.zeros((fout.attrs['Iterations'], modelruns), dtype=fin[path + '/Ex'].dtype)
|
||||
|
||||
fields[path + '/Ex'][:,rx] = fin[path + '/Ex'][:]
|
||||
fields[path + '/Ey'][:,rx] = fin[path + '/Ey'][:]
|
||||
fields[path + '/Ez'][:,rx] = fin[path + '/Ez'][:]
|
||||
fields[path + '/Hx'][:,rx] = fin[path + '/Hx'][:]
|
||||
fields[path + '/Hy'][:,rx] = fin[path + '/Hy'][:]
|
||||
fields[path + '/Hz'][:,rx] = fin[path + '/Hz'][:]
|
||||
fin.close()
|
||||
|
||||
fout.close()
|
||||
|
||||
check = input('Do you want to remove the multiple individual output files? [y] or n:')
|
||||
if not check or check == 'y':
|
||||
for rx in range(modelruns):
|
||||
file = basefilename + str(rx + 1) + '.out'
|
||||
os.remove(file)
|
||||
|
||||
|
||||
|
||||
|
55
tools/plot_fields.py
普通文件
55
tools/plot_fields.py
普通文件
@@ -0,0 +1,55 @@
|
||||
# Copyright (C) 2015: The University of Edinburgh
|
||||
# Authors: Craig Warren and Antonis Giannopoulos
|
||||
#
|
||||
# This file is part of gprMax.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with gprMax. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
def plot_Ascan(figurename, time, Ex, Ey, Ez, Hx, Hy, Hz):
|
||||
"""Plot electric and magnetic fields.
|
||||
|
||||
Args:
|
||||
figurename (str): Name of figure for titlebar
|
||||
time (float): Array containing time
|
||||
Ex, Ey, Ez, Hx, Hy, Hz (float): Arrays containing electric and magnetic field values
|
||||
|
||||
"""
|
||||
|
||||
fig, ((ax1, ax2), (ax3, ax4), (ax5, ax6)) = plt.subplots(nrows=3, ncols=2, sharex=False, sharey='col', subplot_kw=dict(xlabel='Time [ns]'), num=figurename, figsize=(20, 10), facecolor='w', edgecolor='w')
|
||||
ax1.plot(time, Ex,'r', lw=2, label='Ex')
|
||||
ax3.plot(time, Ey,'r', lw=2, label='Ey')
|
||||
ax5.plot(time, Ez,'r', lw=2, label='Ez')
|
||||
ax2.plot(time, Hx,'b', lw=2, label='Hx')
|
||||
ax4.plot(time, Hy,'b', lw=2, label='Hy')
|
||||
ax6.plot(time, Hz,'b', lw=2, label='Hz')
|
||||
|
||||
# Make subplots close to each other
|
||||
# fig.subplots_adjust(hspace=0)
|
||||
|
||||
# Set ylabels
|
||||
ylabels = ['$E_x$, field strength [V/m]', '$H_x$, field strength [A/m]', '$E_y$, field strength [V/m]', '$H_y$, field strength [A/m]', '$E_z$, field strength [V/m]', '$H_z$, field strength [A/m]']
|
||||
[ax.set_ylabel(ylabels[index]) for index, ax in enumerate(fig.axes)]
|
||||
|
||||
# Turn on grid
|
||||
[ax.grid() for ax in fig.axes]
|
||||
|
||||
# Hide x ticks for all but bottom plots
|
||||
# plt.setp([ax.get_xticklabels() for ax in fig.axes[:-2]], visible=False)
|
||||
|
||||
return fig, plt
|
||||
|
||||
|
49
tools/plot_hdf5_Ascan.py
普通文件
49
tools/plot_hdf5_Ascan.py
普通文件
@@ -0,0 +1,49 @@
|
||||
# Copyright (C) 2015: The University of Edinburgh
|
||||
# Authors: Craig Warren and Antonis Giannopoulos
|
||||
#
|
||||
# This file is part of gprMax.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with gprMax. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os, argparse
|
||||
import h5py
|
||||
import numpy as np
|
||||
from .plot_fields import plot_Ascan
|
||||
|
||||
"""Plots electric and magnetic fields from all receiver points in the given output file. Each receiver point is plotted in a new figure window."""
|
||||
|
||||
# Parse command line arguments
|
||||
parser = argparse.ArgumentParser(description='Plots electric and magnetic fields from all receiver points in the given output file. Each receiver point is plotted in a new figure window.', usage='cd gprMax; python -m tools.plot_hdf5_Ascan outputfile')
|
||||
parser.add_argument('outputfile', help='name of output file including path')
|
||||
args = parser.parse_args()
|
||||
|
||||
file = args.outputfile
|
||||
f = h5py.File(file, 'r')
|
||||
nrx = f.attrs['nrx']
|
||||
time = np.arange(0, f.attrs['dt'] * f.attrs['Iterations'], f.attrs['dt'])
|
||||
time = time / 1E-9
|
||||
|
||||
for rx in range(1, nrx + 1):
|
||||
path = '/rxs/rx' + str(rx) + '/'
|
||||
Ex = f[path + 'Ex'][:]
|
||||
Ey = f[path + 'Ey'][:]
|
||||
Ez = f[path + 'Ez'][:]
|
||||
Hx = f[path + 'Hx'][:]
|
||||
Hy = f[path + 'Hy'][:]
|
||||
Hz = f[path + 'Hz'][:]
|
||||
fig, plt = plot_Ascan('rx' + str(rx), time, Ex, Ey, Ez, Hx, Hy, Hz)
|
||||
#fig.savefig(os.path.splitext(os.path.abspath(file))[0] + '.pdf', dpi=None, format='pdf', bbox_inches='tight', pad_inches=0.1)
|
||||
plt.show()
|
||||
|
||||
f.close()
|
49
tools/plot_hdf5_Bscan.py
普通文件
49
tools/plot_hdf5_Bscan.py
普通文件
@@ -0,0 +1,49 @@
|
||||
# Copyright (C) 2015: The University of Edinburgh
|
||||
# Authors: Craig Warren and Antonis Giannopoulos
|
||||
#
|
||||
# This file is part of gprMax.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with gprMax. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os, argparse
|
||||
import h5py
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
"""Plots B-scan."""
|
||||
|
||||
# Parse command line arguments
|
||||
parser = argparse.ArgumentParser(description='Plots B-scan.', usage='cd gprMax; python -m tools.plot_hdf5_Bscan outputfile field')
|
||||
parser.add_argument('outputfile', help='name of output file including path')
|
||||
parser.add_argument('field', help='name of field to be plotted, i.e. Ex, Ey, Ez')
|
||||
args = parser.parse_args()
|
||||
|
||||
file = args.outputfile
|
||||
field = args.field
|
||||
path = '/rxs/rx1'
|
||||
|
||||
f = h5py.File(file, 'r')
|
||||
data = f[path + '/' + field]
|
||||
|
||||
# Plot B-scan image
|
||||
fig = plt.figure(num=file, figsize=(20, 10), facecolor='w', edgecolor='w')
|
||||
plt.imshow(data, extent=[0, data.shape[1], data.shape[0]*f.attrs['dt'], 0], interpolation='nearest', aspect='auto', cmap='seismic', vmin=-np.amax(np.abs(data)), vmax=np.amax(np.abs(data)))
|
||||
plt.xlabel('Trace number')
|
||||
plt.ylabel('Time [s]')
|
||||
plt.grid()
|
||||
cb = plt.colorbar()
|
||||
cb.set_label('Field strength [V/m]')
|
||||
plt.show()
|
||||
#fig.savefig(os.path.splitext(os.path.abspath(file))[0] + '.pdf', dpi=None, format='pdf', bbox_inches='tight', pad_inches=0.1)
|
||||
f.close()
|
78
tools/plot_waveform.py
普通文件
78
tools/plot_waveform.py
普通文件
@@ -0,0 +1,78 @@
|
||||
# Copyright (C) 2015: The University of Edinburgh
|
||||
# Authors: Craig Warren and Antonis Giannopoulos
|
||||
#
|
||||
# This file is part of gprMax.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with gprMax. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os, argparse
|
||||
import numpy as np
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
from gprMax.waveforms import Waveform
|
||||
|
||||
|
||||
"""Plot waveforms that can be used for sources."""
|
||||
|
||||
# Parse command line arguments
|
||||
parser = argparse.ArgumentParser(description='Plot waveforms that can be used for sources.', usage='cd gprMax; python -m tools.plot_waveform type amp freq timewindow dt')
|
||||
parser.add_argument('type', help='type of waveform, e.g. gaussian, ricker etc...')
|
||||
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', type=float, help='time window to view waveform')
|
||||
parser.add_argument('dt', type=float, help='time step to view waveform')
|
||||
args = parser.parse_args()
|
||||
|
||||
w = Waveform()
|
||||
w.type = args.type
|
||||
w.amp = args.amp
|
||||
w.freq = args.freq
|
||||
timewindow = args.timewindow
|
||||
dt = args.dt
|
||||
|
||||
time = np.arange(0, timewindow, dt)
|
||||
waveform = np.zeros(len(time))
|
||||
timeiter = np.nditer(time, flags=['c_index'])
|
||||
|
||||
while not timeiter.finished:
|
||||
waveform[timeiter.index] = w.calculate_value(timeiter[0], dt)
|
||||
timeiter.iternext()
|
||||
|
||||
# Calculate frequency spectra of waveform
|
||||
fs = 1/dt
|
||||
power = 20*np.log10(np.abs(np.fft.rfft(waveform)))
|
||||
f = np.linspace(0, fs/2, len(power))
|
||||
|
||||
# Shift powers so any spectra with negative DC component will start at zero
|
||||
power -= np.amax(power)
|
||||
|
||||
# Set plotting range to 4 * centre frequency
|
||||
pltrange = np.where(f > (4 * w.freq))[0][0]
|
||||
|
||||
# Plot waveform
|
||||
fig, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, num=w.type, figsize=(20, 10), facecolor='w', edgecolor='w')
|
||||
ax1.plot(time, waveform,'r', lw=2)
|
||||
ax1.set_xlabel('Time [ns]')
|
||||
ax1.set_ylabel('Amplitude')
|
||||
[label.set_bbox(dict(facecolor='white', edgecolor='None', alpha=0.65 )) for label in ax1.get_xticklabels() + ax1.get_yticklabels()]
|
||||
|
||||
# Plot frequency spectra
|
||||
ax2.stem(f[0:pltrange]/1e9, power[0:pltrange],'b', lw=2)
|
||||
ax2.set_xlabel('Frequency [GHz]')
|
||||
ax2.set_ylabel('Power [dB]')
|
||||
[ax.grid() for ax in fig.axes] # Turn on grid
|
||||
plt.show()
|
||||
|
||||
# Save a PDF of the figure
|
||||
#fig.savefig(os.path.dirname(os.path.abspath(__file__)) + os.sep + w.type + '.pdf', dpi=None, format='pdf', bbox_inches='tight', pad_inches=0.1)
|
在新工单中引用
屏蔽一个用户