From 7d5cfa2c67a81d7ba6405382ecebb3e44bb98e2b Mon Sep 17 00:00:00 2001 From: Craig Warren Date: Thu, 6 Jan 2022 21:01:14 +0000 Subject: [PATCH] Updated macro to account for new Paraview threshold behaviour in >v.5.10 --- tools/Paraview macros/gprMax_info.py | 366 ++++++++++++++++++++++----- 1 file changed, 297 insertions(+), 69 deletions(-) diff --git a/tools/Paraview macros/gprMax_info.py b/tools/Paraview macros/gprMax_info.py index e7f120cb..fe6aa411 100644 --- a/tools/Paraview macros/gprMax_info.py +++ b/tools/Paraview macros/gprMax_info.py @@ -1,5 +1,5 @@ -# Copyright (C) 2015-2021: The University of Edinburgh -# Authors: Craig Warren and Antonis Giannopoulos +# Copyright (C) 2015-2022: The University of Edinburgh +# Authors: Craig Warren, Antonis Giannopoulos, and John Hartley # # This file is part of gprMax. # @@ -16,11 +16,146 @@ # You should have received a copy of the GNU General Public License # along with gprMax. If not, see . -from paraview.simple import * +import json +import mmap +import os from xml.etree import ElementTree as ET -# Disable automatic camera reset on 'Show' -paraview.simple._DisableFirstRenderCameraReset() +from paraview.simple import * + +# Read Paraview version number to set threshold filter method +pvv = GetParaViewVersion() +if pvv.major == 5 and pvv.minor < 10: + new_thres = False +else: + new_thres = True + +def threshold_filt(input, lt, ut, scalars): + """Create threshold filter according to Paraview version. + + Args: + input (array): input data to threshold filter + lt, ut (int): lower and upper bounds of thresholding operation + scalars (list/str): name of scalar array to perform thresholding + + Returns: + threshold (object): threshold filter + """ + + threshold = Threshold(Input=input) + threshold.Scalars = scalars + + if new_thres: + threshold.LowerThreshold = lt + threshold.UpperThreshold = ut + else: + threshold.ThresholdRange = [lt, ut] + + return threshold + + +def display_src_rx(srcs_rxs, dl): + """Display sources and receivers as Paraview box sources. + Only suitable for gprMax >= v4 + + Args: + srcs_rxs (list): source/receiver names and positions + dl (tuple): spatial discretisation + """ + + for item in srcs_rxs: + pos = item['position'] + name = item['name'] + src_rx = Box(Center=[pos[0] + dl[0]/2, + pos[1] + dl[1]/2, + pos[2] + dl[2]/2], + XLength=dl[0], YLength=dl[1], ZLength=dl[2]) + RenameSource(name, src_rx) + Show(src_rx) + + +def display_pmls(pmlthick, dx_dy_dz, nx_ny_nz): + """Display PMLs as box sources using PML thickness values. + Only suitable for gprMax >= v4 + + Args: + pmlthick (tuple): PML thickness values for each slab (cells) + dx_dy_dz (tuple): Spatial resolution (m) + nx_ny_dz (tuple): Domain size (cells) + """ + + pml_names = ['x0', 'y0', 'z0', 'xmax', 'ymax', 'zmax'] + pmls = dict.fromkeys(pml_names, None) + + if pmlthick[0] != 0: + x0 = Box(Center=[pmlthick[0] * dx_dy_dz[0] / 2, + nx_ny_nz[1] * dx_dy_dz[1] / 2, + nx_ny_nz[2] * dx_dy_dz[2] / 2], + XLength=pmlthick[0] * dx_dy_dz[0], + YLength=nx_ny_nz[1] * dx_dy_dz[1], + ZLength=nx_ny_nz[2] * dx_dy_dz[2]) + pmls['x0'] = x0 + + if pmlthick[3] != 0: + xmax = Box(Center=[dx_dy_dz[0] * (nx_ny_nz[0] - pmlthick[3] / 2), + nx_ny_nz[1] * dx_dy_dz[1] / 2, + nx_ny_nz[2] * dx_dy_dz[2] / 2], + XLength=pmlthick[3] * dx_dy_dz[0], + YLength=nx_ny_nz[1] * dx_dy_dz[1], + ZLength=nx_ny_nz[2] * dx_dy_dz[2]) + pmls['xmax'] = xmax + + if pmlthick[1] != 0: + y0 = Box(Center=[nx_ny_nz[0] * dx_dy_dz[0] / 2, + pmlthick[1] * dx_dy_dz[1] / 2, + nx_ny_nz[2] * dx_dy_dz[2] / 2], + XLength=nx_ny_nz[0] * dx_dy_dz[0], + YLength=pmlthick[1] * dx_dy_dz[1], + ZLength=nx_ny_nz[2] * dx_dy_dz[2]) + pmls['y0'] = y0 + + if pmlthick[4] != 0: + ymax = Box(Center=[nx_ny_nz[0] * dx_dy_dz[0] / 2, + dx_dy_dz[1] * (nx_ny_nz[1] - pmlthick[4] / 2), + nx_ny_nz[2] * dx_dy_dz[2] / 2], + XLength=nx_ny_nz[0] * dx_dy_dz[0], + YLength=pmlthick[4] * dx_dy_dz[1], + ZLength=nx_ny_nz[2] * dx_dy_dz[2]) + pmls['ymax'] = ymax + + if pmlthick[2] != 0: + z0 = Box(Center=[nx_ny_nz[0] * dx_dy_dz[0] / 2, + nx_ny_nz[1] * dx_dy_dz[1] / 2, + pmlthick[2] * dx_dy_dz[2] / 2], + XLength=nx_ny_nz[0] * dx_dy_dz[0], + YLength=nx_ny_nz[1] * dx_dy_dz[1], + ZLength=pmlthick[2] * dx_dy_dz[2]) + pmls['z0'] = z0 + + if pmlthick[5] != 0: + zmax = Box(Center=[nx_ny_nz[0] * dx_dy_dz[0] / 2, + nx_ny_nz[1] * dx_dy_dz[1] / 2, + dx_dy_dz[2] * (nx_ny_nz[2] - pmlthick[5] / 2)], + XLength=nx_ny_nz[0] * dx_dy_dz[0], + YLength=nx_ny_nz[1] * dx_dy_dz[1], + ZLength=pmlthick[5] * dx_dy_dz[2]) + pmls['zmax'] = zmax + + # Name PML sources and set opacity + tmp = [] + for pml in pmls: + if pmls[pml]: + RenameSource('PML - ' + pml, pmls[pml]) + Hide(pmls[pml], renderview) + tmp.append(pmls[pml]) + + # Create a group of PMLs to switch on/off easily + if tmp: + pml_gp = AppendDatasets(Input=tmp) + RenameSource('PML - All', pml_gp) + pml_view = Show(pml_gp) + pml_view.Opacity = 0.5 + # Get whatever source is loaded (should be model) model = GetActiveSource() @@ -28,91 +163,184 @@ model = GetActiveSource() # Get active view renderview = GetActiveView() -# Show data in view -Show(model, renderview) +# Show Data Axes Grid +renderview.AxesGrid.Visibility = 1 -# Reset view to fit data -renderview.ResetCamera() +# Hide display of root data +Hide(model) -# Lists to hold material and sources/receiver identifiers written in VTK file in tags and -materials = [] -srcs_pml = [] -rxs = [] -with open(model.FileName[0], 'rb') as f: - for line in f: - if line.startswith(b' tag which indicates version <4 + try: + xml_pos = mm.find(b' material_ID_max: + material_ID_max = int(elem.text) + + # Read sources + for elem in root.findall('Sources'): + srcs[elem.get('name')] = int(elem.text) + + # Read receivers + for elem in root.findall('Receivers'): + rxs[elem.get('name')] = int(elem.text) + + # Read PMLs + for elem in root.findall('PML'): + pmls[elem.get('name')] = int(elem.text) + + except: + v4 = True + # Comments () embedded in line 3 of file + f.readline() + f.readline() + c = f.readline().decode() + # Strip comment tags + c = c[5:-5] + # Model information + c = json.loads(c) + print('\ngprMax version: ' + c['gprMax_version']) + print(file) + + ################ + # Display data # + ################ + + if v4: + # Discretisation + dl = c['dx_dy_dz'] + # Number of voxels + nl = c['nx_ny_nz'] + + # Store materials + try: + mats = c['Materials'] + for i, material in enumerate(mats): + materials[material] = i + if i > material_ID_max: + material_ID_max = i + except KeyError: + print('No materials to load') + + # Display any sources + try: + srcs = c['Sources'] + display_src_rx(srcs, dl) + except KeyError: + print('No sources to load') + + # Display any receivers + try: + rxs = c['Receivers'] + display_src_rx(rxs, dl) + except KeyError: + print('No receivers to load') + + # Display any PMLs + try: + pt = c['PMLthickness'] + display_pmls(pt, dl, nl) + except KeyError: + print('No PMLs to load') + + else: + # Display any sources and PMLs + srcs_pmls = dict(srcs) + srcs_pmls.update(pmls) + if srcs_pmls: + for k, v in srcs_pmls.items(): + threshold = threshold_filt(model, v, v, 'Sources_PML') + RenameSource(k, threshold) # Show data in view thresholddisplay = Show(threshold, renderview) thresholddisplay.ColorArrayName = 'Sources_PML' - - if srcs_pml[y][0] == 1: + if v == 1: thresholddisplay.Opacity = 0.5 + threshold.UpdatePipeline() -if rxs: - # Get ranges of data - rxs_datarange = model.CellData.GetArray('Receivers').GetRange() - - # Create threshold for sources/pml (name and numeric value) - for x in range(1, int(rxs_datarange[1]) + 1): - for y in range(len(rxs)): - if rxs[y][0] == x: - threshold = Threshold(Input=model) - threshold.Scalars = 'Receivers' - threshold.ThresholdRange = [rxs[y][0], rxs[y][0]] - - RenameSource(rxs[y][1], threshold) + # Display any receivers + if rxs: + for k, v in rxs.items(): + threshold = threshold_filt(model, v, v, 'Receivers') + RenameSource(k, threshold) # Show data in view thresholddisplay = Show(threshold, renderview) thresholddisplay.ColorArrayName = 'Receivers' + threshold.UpdatePipeline() + +# Display materials +material_range = range(0, material_ID_max + 1) +for k, v in sorted(materials.items(), key=lambda x: x[1]): + if v in material_range: + threshold = threshold_filt(model, v, v, ['CELLS', 'Material']) + RenameSource(k, threshold) + + # Show data in view, except for free_space + if v != 1: + thresholddisplay = Show(threshold, renderview) + thresholddisplay.ColorArrayName = ['CELLS', 'Material'] + threshold.UpdatePipeline() + -# renderview.CameraParallelProjection = 1 RenderAllViews() +# Reset view to fit data +renderview.ResetCamera() + # Show color bar/color legend # thresholdDisplay.SetScalarBarVisibility(renderview, False)