Skip to Content
ExamplesEg1 seismic tomographyResult visualization

Result visualization

Make sure the Python module Pygmt  is loaded.

This part plot the output files for result visualization. Users can directly run the following codes to plot the results automatically.

python plot_output.py

Figures are output as

  • img/model_setting.png for earthquake location (dots), station location (triangles), velocity perturbations of the initial and true models, and azimuthal anisotropy (yellow bar).

img

  • img/model_inv.png for the velocity perturbation and azimuthal anisotropy of the inversion results.

img

Here we demonstrate the plotting script step-by-step

1. Load necessary Python modules

import pygmt import os from pytomoatt.model import ATTModel from pytomoatt.data import ATTData from pytomoatt.src_rec import SrcRec import numpy as np

2. Read the initial model and the checkerboard model

Ngrid = [61,61,61] data_file = '2_models/model_init_N%d_%d_%d.h5'%(Ngrid[0],Ngrid[1],Ngrid[2]) par_file = '3_input_params/input_params_signal.yaml' model = ATTModel.read(data_file, par_file) initial_model = model.to_xarray() data_file = '2_models/model_ckb_N%d_%d_%d.h5'%(Ngrid[0],Ngrid[1],Ngrid[2]) model = ATTModel.read(data_file, par_file) ckb_model = model.to_xarray()

3. Slice profiles

Choose a horizontal profile at 10 km depth and a vertical profile from (1.25, 0) to (1.25, 2) in longitude and latitude.

depth = 10.0 vel_init = initial_model.interp_dep(depth, field='vel') vel_ckb = ckb_model.interp_dep(depth, field='vel') start = [1.25,0]; end = [1.25,2] vel_init_sec = initial_model.interp_sec(start, end, field='vel', val = 1) vel_ckb_sec = ckb_model.interp_sec(start, end, field='vel', val = 1)

4. Generate fast velocity direction arrows for the checkboard model

samp_interval = 3 # control the density of fast velocity direction arrows length = 7 width = 0.1 ani_thd = 0.02 # arrows with magnitude smaller ani_thd is ignored ani_ckb_phi = ckb_model.interp_dep(depth, field='phi', samp_interval=samp_interval) ani_ckb_epsilon = ckb_model.interp_dep(depth, field='epsilon', samp_interval=samp_interval) ani_ckb = np.hstack([ani_ckb_phi, ani_ckb_epsilon[:,2].reshape(-1, 1)*length, np.ones((ani_ckb_epsilon.shape[0],1))*width]) # lon, lat, angle, length, width idx = np.where(ani_ckb_epsilon[:,2] > ani_thd) ani_ckb = ani_ckb[idx[0],:]

The magnitude smaller 0.02 are ignored by

ani_thd = 0.02 # arrows with magnitude smaller ani_thd is ignored

5. Read earthquakes and stations

sr = SrcRec.read('1_src_rec_files/src_rec_config.dat') station = sr.receivers[['stlo','stla','stel']].values.T true_loc = sr.sources[['evlo','evla','evdp']].values.T earthquake = true_loc # categorize earthquakes ev_idx1 = [] ev_idx2 = [] ev_idx3 = [] for i in range(earthquake.shape[1]): dep = earthquake[2,i] if dep < 15: ev_idx1.append(i) elif dep < 25: ev_idx2.append(i) elif dep < 35: ev_idx3.append(i)

6. Plot perturbation of the initial and true models relative to the initial model

fig = pygmt.Figure() region = [0,2,0,2] frame = ["xa1","ya1","nSWe"] projection = "M10c" spacing = 0.04 vel_range = 20 # -------------- initial model and earthquake location -------------- fig.basemap(region=region, frame=["xa1","ya1","+tInitial model and locations"], projection=projection) # velocity perturbation pygmt.makecpt(cmap="../utils/svel13_chen.cpt", series=[-vel_range, vel_range], background=True, reverse=False) x = vel_init[:,0]; y = vel_init[:,1]; value = (vel_init[:,2] - vel_init[:,2])/vel_init[:,2] * 100 grid = pygmt.surface(x=x, y=y, z=value, spacing=spacing,region=region) fig.grdimage(grid = grid) # earthquakes fig.plot(x = true_loc[0,ev_idx1], y = true_loc[1,ev_idx1], style = "c0.1c", fill = "red") fig.plot(x = true_loc[0,ev_idx2], y = true_loc[1,ev_idx2], style = "c0.1c", fill = "green") fig.plot(x = true_loc[0,ev_idx3], y = true_loc[1,ev_idx3], style = "c0.1c", fill = "black") # stations fig.plot(x = station[0,:], y = station[1,:], style = "t0.4c", fill = "blue", pen = "black", label = "Station") # # anisotropic arrow # fig.plot(ani_ckb, style='j', fill='yellow1', pen='0.5p,black') fig.shift_origin(xshift=11) fig.basemap(region=[0,40,0,2], frame=["xa20+lDepth (km)","ya1","Nswe"], projection="X2c/10c") x = vel_init_sec[:,3]; y = vel_init_sec[:,1]; value = (vel_init_sec[:,4] - vel_init_sec[:,4])/vel_init_sec[:,4] * 100 grid = pygmt.surface(x=x, y=y, z=value, spacing="1/0.04",region=[0,40,0,2]) fig.grdimage(grid = grid) # earthquakes fig.plot(x = true_loc[2,ev_idx1], y = true_loc[1,ev_idx1], style = "c0.1c", fill = "red") fig.plot(x = true_loc[2,ev_idx2], y = true_loc[1,ev_idx2], style = "c0.1c", fill = "green") fig.plot(x = true_loc[2,ev_idx3], y = true_loc[1,ev_idx3], style = "c0.1c", fill = "black") fig.shift_origin(xshift=4) # -------------- checkerboard model -------------- fig.basemap(region=region, frame=["xa1","ya1","+tTrue model and locations"], projection=projection) # velocity perturbation pygmt.makecpt(cmap="../utils/svel13_chen.cpt", series=[-vel_range, vel_range], background=True, reverse=False) x = vel_ckb[:,0]; y = vel_ckb[:,1]; value = (vel_ckb[:,2] - vel_init[:,2])/vel_init[:,2] * 100 grid = pygmt.surface(x=x, y=y, z=value, spacing=spacing,region=region) fig.grdimage(grid = grid) # earthquakes fig.plot(x = earthquake[0,ev_idx1], y = earthquake[1,ev_idx1], style = "c0.1c", fill = "red") fig.plot(x = earthquake[0,ev_idx2], y = earthquake[1,ev_idx2], style = "c0.1c", fill = "green") fig.plot(x = earthquake[0,ev_idx3], y = earthquake[1,ev_idx3], style = "c0.1c", fill = "black") # stations # fig.plot(x = loc_st[0,:], y = loc_st[1,:], style = "t0.4c", fill = "blue", pen = "black", label = "Station") # anisotropic arrow fig.plot(ani_ckb, style='j', fill='yellow1', pen='0.5p,black') fig.shift_origin(xshift=11) fig.basemap(region=[0,40,0,2], frame=["xa20+lDepth (km)","ya1","Nswe"], projection="X2c/10c") x = vel_ckb_sec[:,3]; y = vel_ckb_sec[:,1]; value = (vel_ckb_sec[:,4] - vel_init_sec[:,4])/vel_init_sec[:,4] * 100 grid = pygmt.surface(x=x, y=y, z=value, spacing="1/0.04",region=[0,40,0,2]) fig.grdimage(grid = grid) # earthquakes fig.plot(x = earthquake[2,ev_idx1], y = earthquake[1,ev_idx1], style = "c0.1c", fill = "red") fig.plot(x = earthquake[2,ev_idx2], y = earthquake[1,ev_idx2], style = "c0.1c", fill = "green") fig.plot(x = earthquake[2,ev_idx3], y = earthquake[1,ev_idx3], style = "c0.1c", fill = "black") # ------------------- colorbar ------------------- fig.shift_origin(xshift=-11, yshift=-1.5) fig.colorbar(frame = ["a%f"%(vel_range),"x+ldlnVp (%)"], position="+e+w4c/0.3c+h") fig.shift_origin(xshift=6, yshift=-1) fig.basemap(region=[0,1,0,1], frame=["wesn"], projection="X6c/1.5c") ani = [ [0.2, 0.6, 45, 0.02*length, width], # lon, lat, phi, epsilon, size [0.5, 0.6, 45, 0.05*length, width], [0.8, 0.6, 45, 0.10*length, width], ] fig.plot(ani, style='j', fill='yellow1', pen='0.5p,black') fig.text(text=["0.02", "0.05", "0.10"], x=[0.2,0.5,0.8], y=[0.2]*3, font="16p,Helvetica", justify="CM") fig.shift_origin(xshift= 11, yshift=2.5) fig.show() fig.savefig('img/model_setting.png', dpi=300)

7. Plot output model perturbations

Similarly, we can plot the model perturbation for the imaging results

# plot the inversion result # read models tag = "inv" data_file = "OUTPUT_FILES/OUTPUT_FILES_%s/final_model.h5"%(tag) model = ATTModel.read(data_file, par_file) inv_model = model.to_xarray() vel_inv = inv_model.interp_dep(depth, field='vel') # lon = [:,0], lat = [:,1], vel = [:,2] x = vel_inv[:,0]; y = vel_inv[:,1]; value = (vel_inv[:,2] - vel_init[:,2])/vel_init[:,2] * 100 vel_inv_sec = inv_model.interp_sec(start, end, field='vel', val = 1) x_sec = vel_inv_sec[:,3]; y_sec = vel_inv_sec[:,1]; value_sec = (vel_inv_sec[:,4] - vel_init_sec[:,4])/vel_init_sec[:,4] * 100 ani_inv_phi = inv_model.interp_dep(depth, field='phi', samp_interval=samp_interval) ani_inv_epsilon = inv_model.interp_dep(depth, field='epsilon', samp_interval=samp_interval) ani_inv = np.hstack([ani_inv_phi, ani_inv_epsilon[:,2].reshape(-1, 1)*length, np.ones((ani_inv_epsilon.shape[0],1))*width]) # lon, lat, angle, length, width idx = np.where(ani_inv_epsilon[:,2] > ani_thd) ani_inv = ani_inv[idx[0],:] # plot the inversion result fig = pygmt.Figure() region = [0,2,0,2] frame = ["xa1","ya1","+tInversion results"] projection = "M10c" spacing = 0.04 vel_range = 20 # -------------- checkerboard model -------------- fig.basemap(region=region, frame=frame, projection=projection) # velocity perturbation pygmt.makecpt(cmap="../utils/svel13_chen.cpt", series=[-vel_range, vel_range], background=True, reverse=False) x = vel_inv[:,0]; y = vel_inv[:,1]; value = (vel_inv[:,2] - vel_init[:,2])/vel_init[:,2] * 100 grid = pygmt.surface(x=x, y=y, z=value, spacing=spacing,region=region) fig.grdimage(grid = grid) # anisotropic arrow fig.plot(ani_inv, style='j', fill='yellow1', pen='0.5p,black') fig.shift_origin(xshift=11) fig.basemap(region=[0,40,0,2], frame=["xa20+lDepth (km)","ya1","Nswe"], projection="X2c/10c") x = vel_inv_sec[:,3]; y = vel_inv_sec[:,1]; value = (vel_inv_sec[:,4] - vel_init_sec[:,4])/vel_init_sec[:,4] * 100 grid = pygmt.surface(x=x, y=y, z=value, spacing="1/0.04",region=[0,40,0,2]) fig.grdimage(grid = grid) # ------------------- colorbar ------------------- fig.shift_origin(xshift=-11, yshift=-1.5) fig.colorbar(frame = ["a%f"%(vel_range),"x+ldlnVp (%)"], position="+e+w4c/0.3c+h") fig.shift_origin(xshift=6, yshift=-1) fig.basemap(region=[0,1,0,1], frame=["wesn"], projection="X6c/1.5c") ani = [ [0.2, 0.6, 45, 0.02*length, width], # lon, lat, phi, epsilon, size [0.5, 0.6, 45, 0.05*length, width], [0.8, 0.6, 45, 0.10*length, width], ] fig.plot(ani, style='j', fill='yellow1', pen='0.5p,black') fig.text(text=["0.02", "0.05", "0.10"], x=[0.2,0.5,0.8], y=[0.2]*3, font="16p,Helvetica", justify="CM") fig.shift_origin(xshift= 11, yshift=2.5) fig.show() fig.savefig('img/model_%s.png'%(tag), dpi=300)
Last updated on