Logo
  • Home
  • Getting Started

API Overview

  • Index
  • Read WW3 Files
  • Body Waves
  • Rayleigh Waves
  • Temporal Variations
  • Synthetic Cross-Correlation Functions
  • To noisi

User Guide

  • Tutorials
  • Site Effect
    • Rayleigh Waves Site Effect
    • Body Waves Site Effect
  • Equivalent Vertical Force Maps
    • Rayleigh Waves Equivalent Vertical Force
    • Body Waves Equivalent Vertical Force
  • Rayleigh Waves Temporal Variations
  • Synthetic Cross-Correlation Functions
    • Rayleigh Waves Synthetic Cross-correlation Functions
      • Make Nice Plots
      • Theory
        • References
      • Create Synthetic Waveforms Database
      • Tapering
      • Synthetics Computation
      • Spatial Extent
      • Station Pairs and Metadata
      • Dates
      • Open WAVEWATCHIII Equivalent Force Amplitude
      • Open Synthetics Archive
      • Synthetic Cross-correlation Computation
      • Plot
    • Body Waves Synthetics Cross-correlation Functions
  • WMSAN to noisi
  • Synthetic Spectrograms
    • Rayleigh Waves Power Spectrum of Vertical Displacement
    • Rayleigh Waves Synthetic Spectrograms

Developer Guide

  • How to contribute ?

About

  • About
WMSAN
  • User Guide
  • Synthetic Cross-Correlation Functions
  • Rayleigh Waves Synthetic Cross-correlation Functions

Rayleigh Waves Synthetic Cross-correlation Functions¶

In [1]:
Copied!
## Distributed python packages
import os
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
import xarray as xr
import datetime
import pandas as pd
import time as ttime

from cartopy import crs as ccrs
from cartopy import feature as cfeature
from math import radians, log

from wmsan.synthetics import *

%matplotlib inline
__author__ = "Lisa Tomasetto"
__copyright__ = "Copyright 2024, UGA"
__credits__ = ["Lisa Tomasetto"]
__version__ = "0.1"
__maintainer__ = "Lisa Tomasetto"
__email__ = "lisa.tomasetto@univ-grenoble-alpes.fr"
__status__ = "Developpement"
## Distributed python packages import os import numpy as np import matplotlib.pyplot as plt import matplotlib import xarray as xr import datetime import pandas as pd import time as ttime from cartopy import crs as ccrs from cartopy import feature as cfeature from math import radians, log from wmsan.synthetics import * %matplotlib inline __author__ = "Lisa Tomasetto" __copyright__ = "Copyright 2024, UGA" __credits__ = ["Lisa Tomasetto"] __version__ = "0.1" __maintainer__ = "Lisa Tomasetto" __email__ = "lisa.tomasetto@univ-grenoble-alpes.fr" __status__ = "Developpement"

Make Nice Plots¶

In [2]:
Copied!
plt.style.use("ggplot")
SMALL_SIZE = 18
MEDIUM_SIZE = 22
BIGGER_SIZE = 24

plt.rc('font', size=SMALL_SIZE)          # controls default text sizes
plt.rc('axes', titlesize=SMALL_SIZE)     # fontsize of the axes title
plt.rc('axes', labelsize=MEDIUM_SIZE)    # fontsize of the x and y labels
plt.rc('xtick', labelsize=SMALL_SIZE)    # fontsize of the tick labels
plt.rc('ytick', labelsize=SMALL_SIZE)    # fontsize of the tick labels
plt.rc('legend', fontsize=SMALL_SIZE)    # legend fontsize
plt.rc('figure', titlesize=BIGGER_SIZE)  # fontsize of the figure title
matplotlib.rcParams['pdf.fonttype'] = 42
plt.style.use("ggplot") SMALL_SIZE = 18 MEDIUM_SIZE = 22 BIGGER_SIZE = 24 plt.rc('font', size=SMALL_SIZE) # controls default text sizes plt.rc('axes', titlesize=SMALL_SIZE) # fontsize of the axes title plt.rc('axes', labelsize=MEDIUM_SIZE) # fontsize of the x and y labels plt.rc('xtick', labelsize=SMALL_SIZE) # fontsize of the tick labels plt.rc('ytick', labelsize=SMALL_SIZE) # fontsize of the tick labels plt.rc('legend', fontsize=SMALL_SIZE) # legend fontsize plt.rc('figure', titlesize=BIGGER_SIZE) # fontsize of the figure title matplotlib.rcParams['pdf.fonttype'] = 42

Theory¶

We will compute synthetic Cross-correlations between vertical components, using the formulation given in Tomasetto et al.(2024). Using the representation theorem and assuming spatially uncorrelated sources one can write the cross-correlation function between sensors A and B as:

$$ C(r_A, r_B, t) = \mathcal{FT}^{-1}\left[ \int_{\partial D} G(r_A, r, f) G^*(r_B, r, f) S(r,f) dr \right] $$

with:

  • $G(r_A, r, f)$ the Green's function between a source in $ r $ and station A in $ r_A $. Here computed in AxiSEM.
  • $S(r,f)$ the source PSD at position $ r $. Here given by the square of equivalent vertical force amplitude computed in microseismic_sources.ipynb.
  • $^*$ denotes the complex conjugate.
  • $\partial D$ the domain of potential sources, here, the ocean's surface.
  • $\mathcal{FT}^{-1}$ the Fourier transform.

References¶

  • Nissen-Meyer, T., van Driel, M., Stähler, S. C., Hosseini, K., Hempel, S., Auer, L., ... & Fournier, A. (2014). AxiSEM: broadband 3-D seismic wavefields in axisymmetric media. Solid Earth, 5(1), 425-445.

  • Tomasetto, L., Boué, P., Stehly, L., Ardhuin, F., & Nataf, H. C. (2024). On the stability of mantle‐sensitive P‐wave interference during a secondary microseismic event. Geophysical Research Letters, 51(8), e2023GL108018.

Create Synthetic Waveforms Database¶

In the following, we will use an AxiSEM archive file of seismic waveforms computed in ak135f model and sampled at 1 Hz.

First we will read and plot the archive.

[WARNING] Please download the archive before running the following cells!

Avalaible from: https://zenodo.org/records/11126562

Save in /ww3-source-maps/data/

In [3]:
Copied!
## Open Archive 
path_file_axisem = '../../data/NOISE_vertforce_dirac_0-ak135f_1.s_3600s.h5'
fe, time, N = get_synthetic_info(path_file_axisem=path_file_axisem)

distance = np.arange(0, 180.1, 0.1)
M = len(distance)
archive = np.zeros((M, N))

for i in range(M):
    archive[i,:] = open_axisem(distance[i], path_file_axisem=path_file_axisem)
## Open Archive path_file_axisem = '../../data/NOISE_vertforce_dirac_0-ak135f_1.s_3600s.h5' fe, time, N = get_synthetic_info(path_file_axisem=path_file_axisem) distance = np.arange(0, 180.1, 0.1) M = len(distance) archive = np.zeros((M, N)) for i in range(M): archive[i,:] = open_axisem(distance[i], path_file_axisem=path_file_axisem)
In [4]:
Copied!
## Plot archive
plt.figure()
plt.pcolormesh(time, distance, archive,cmap='seismic', vmin=-10, vmax = 10)
plt.colorbar()
plt.xlabel('time')
plt.ylabel('distance')
plt.xlim(0, 3600)
plt.show()
## Plot archive plt.figure() plt.pcolormesh(time, distance, archive,cmap='seismic', vmin=-10, vmax = 10) plt.colorbar() plt.xlabel('time') plt.ylabel('distance') plt.xlim(0, 3600) plt.show()
No description has been provided for this image

Tapering¶

Then we taper the synthetics waveforms between two given surface waves velocities.

In [5]:
Copied!
## Taper
Umin = 2.5
Umax = 4.2

file_name_taper = '../../data/NOISE_vertforce_dirac_0-ak135f_1.s_3600_tapered.s.h5'

if os.path.isfile(file_name_taper):
    print('Tapered archive already exists')
    ## Open tapered archive
    h5_file = h5py.File(file_name_taper, 'r')
    tapered_archive = h5_file['WAVEFORMS'][:]
    
else:
    tapered_archive = taper_axisem_archive(time, distance, archive_name=path_file_axisem, umin = Umin, umax=Umax)
## Taper Umin = 2.5 Umax = 4.2 file_name_taper = '../../data/NOISE_vertforce_dirac_0-ak135f_1.s_3600_tapered.s.h5' if os.path.isfile(file_name_taper): print('Tapered archive already exists') ## Open tapered archive h5_file = h5py.File(file_name_taper, 'r') tapered_archive = h5_file['WAVEFORMS'][:] else: tapered_archive = taper_axisem_archive(time, distance, archive_name=path_file_axisem, umin = Umin, umax=Umax)
Tapered archive already exists
In [6]:
Copied!
## Plot Tapered archive 

plt.figure(figsize=(10, 5))
plt.pcolormesh(time, distance, archive, cmap='seismic', vmin=-10, vmax = 10)
plt.plot(distance*(np.pi*6371)/180/Umin, distance, 'r')
plt.plot(distance*(np.pi*6371)/180/Umax, distance, 'g')
plt.colorbar()
plt.xlabel('time')
plt.ylabel('distance')
plt.xlim(0, 3600)
plt.savefig('GF_archive.png', dpi=300, bbox_inches='tight')
## Plot Tapered archive plt.figure(figsize=(10, 5)) plt.pcolormesh(time, distance, archive, cmap='seismic', vmin=-10, vmax = 10) plt.plot(distance*(np.pi*6371)/180/Umin, distance, 'r') plt.plot(distance*(np.pi*6371)/180/Umax, distance, 'g') plt.colorbar() plt.xlabel('time') plt.ylabel('distance') plt.xlim(0, 3600) plt.savefig('GF_archive.png', dpi=300, bbox_inches='tight')
No description has been provided for this image
In [7]:
Copied!
file_name_spectrum = '../../data/spectrum_archive_tapered.h5'

if os.path.isfile(file_name_spectrum):
    print('Spectrum archive already exists')
    ## Open Spectrum archive
    h5_file = h5py.File(file_name_spectrum, 'r')
    spectrum_archive = h5_file['SPECTRUM'][:]
    frequency = h5_file['frequency'][:]
    distance = h5_file['distance'][:]
    print(spectrum_archive.shape)
else:
    ## Create Spectrum archive from the tapered one
    create_spectrum_archive(time, distance, tapered_archive)
file_name_spectrum = '../../data/spectrum_archive_tapered.h5' if os.path.isfile(file_name_spectrum): print('Spectrum archive already exists') ## Open Spectrum archive h5_file = h5py.File(file_name_spectrum, 'r') spectrum_archive = h5_file['SPECTRUM'][:] frequency = h5_file['frequency'][:] distance = h5_file['distance'][:] print(spectrum_archive.shape) else: ## Create Spectrum archive from the tapered one create_spectrum_archive(time, distance, tapered_archive)
Spectrum archive already exists
(1801, 14400)

Synthetics Computation¶

Spatial Extent¶

In [8]:
Copied!
## Spatial Exent
lon_min = -30
lon_max = 30
lat_min = 40
lat_max = 80

extent = [lon_min, lon_max, lat_min, lat_max]
## Spatial Exent lon_min = -30 lon_max = 30 lat_min = 40 lat_max = 80 extent = [lon_min, lon_max, lat_min, lat_max]

Station Pairs and Metadata¶

In [9]:
Copied!
## Station Pairs Metadata
df = pd.read_csv('../../data/stations_pair.txt', sep=',', header=None, index_col=False, names=['idA', 'idB', 'latA', 'latB', 'lonA', 'lonB'], dtype={'idA':str, 'idB':str, 'latA':float, 'latB':float, 'lonA':float, 'lonB':float}, engine='python')
# ## Plot
fig = plt.figure(figsize=(10,10))
ax = fig.add_subplot(111, projection=ccrs.Mollweide())
ax.set_extent(extent, crs=ccrs.PlateCarree())
ax.add_feature(cfeature.COASTLINE)
ax.add_feature(cfeature.BORDERS, linestyle='-', alpha=1)
ax.add_feature(cfeature.LAKES, alpha=0.5)
ax.add_feature(cfeature.RIVERS)
ax.add_feature(cfeature.STATES)
ax.add_feature(cfeature.LAND, color='linen', zorder=0)
ax.add_feature(cfeature.OCEAN, color='lightsteelblue', zorder=0)
for i in range(len(df)):
    ax.annotate(df.idA[i], (df.lonA[i]-0.1, df.latA[i]+0.8), transform = ccrs.PlateCarree(), family = 'sans-serif')
    ax.annotate(df.idB[i], (df.lonB[i]+0.1, df.latB[i]-0.8), transform = ccrs.PlateCarree(), family = 'sans-serif')
    ax.plot((df.lonA[i], df.lonB[i]),(df.latA[i], df.latB[i]), transform = ccrs.PlateCarree(), color='k', alpha=0.5, linewidth=3)
df.plot.scatter(x='lonA', y='latA', s=30, ax=ax, c='r', transform = ccrs.PlateCarree())
df.plot.scatter(x='lonB', y='latB', s=30, ax=ax, c='r', transform = ccrs.PlateCarree())
plt.show()
## Station Pairs Metadata df = pd.read_csv('../../data/stations_pair.txt', sep=',', header=None, index_col=False, names=['idA', 'idB', 'latA', 'latB', 'lonA', 'lonB'], dtype={'idA':str, 'idB':str, 'latA':float, 'latB':float, 'lonA':float, 'lonB':float}, engine='python') # ## Plot fig = plt.figure(figsize=(10,10)) ax = fig.add_subplot(111, projection=ccrs.Mollweide()) ax.set_extent(extent, crs=ccrs.PlateCarree()) ax.add_feature(cfeature.COASTLINE) ax.add_feature(cfeature.BORDERS, linestyle='-', alpha=1) ax.add_feature(cfeature.LAKES, alpha=0.5) ax.add_feature(cfeature.RIVERS) ax.add_feature(cfeature.STATES) ax.add_feature(cfeature.LAND, color='linen', zorder=0) ax.add_feature(cfeature.OCEAN, color='lightsteelblue', zorder=0) for i in range(len(df)): ax.annotate(df.idA[i], (df.lonA[i]-0.1, df.latA[i]+0.8), transform = ccrs.PlateCarree(), family = 'sans-serif') ax.annotate(df.idB[i], (df.lonB[i]+0.1, df.latB[i]-0.8), transform = ccrs.PlateCarree(), family = 'sans-serif') ax.plot((df.lonA[i], df.lonB[i]),(df.latA[i], df.latB[i]), transform = ccrs.PlateCarree(), color='k', alpha=0.5, linewidth=3) df.plot.scatter(x='lonA', y='latA', s=30, ax=ax, c='r', transform = ccrs.PlateCarree()) df.plot.scatter(x='lonB', y='latB', s=30, ax=ax, c='r', transform = ccrs.PlateCarree()) plt.show()
No description has been provided for this image

Dates¶

In [10]:
Copied!
## Dates
start = datetime(2008, 11, 16, 0, 0, 0)
end = datetime(2008, 11, 19, 23, 59, 59)

dates = pd.date_range(start, end, freq='3h')

dates_vector = create_date_vect(dates)
## Dates start = datetime(2008, 11, 16, 0, 0, 0) end = datetime(2008, 11, 19, 23, 59, 59) dates = pd.date_range(start, end, freq='3h') dates_vector = create_date_vect(dates)

Open WAVEWATCHIII Equivalent Force Amplitude¶

In [11]:
Copied!
## Open Model
path_model = './F/'
## Open Model path_model = './F/'

Open Synthetics Archive¶

In [12]:
Copied!
## Open GF archive info
fe , freq, distance, spectrum_synth = open_archive('../../data/spectrum_archive_tapered.h5')
N_time = len(time)
## Open GF archive info fe , freq, distance, spectrum_synth = open_archive('../../data/spectrum_archive_tapered.h5') N_time = len(time)

Synthetic Cross-correlation Computation¶

In [13]:
Copied!
## Compute CCF and save it
### Station Pair Info
id_A = df.idA[0]
id_B = df.idB[0]
coords_staA = (df.lonA[0], df.latA[0])
coords_staB = (df.lonB[0], df.latB[0])

#### Keep Correlations
corr_3h = np.zeros((len(dates_vector), N_time))

### Date Info
for i, date_vect in enumerate(dates_vector):
    ### CCF
    filename_ccf = './CCF/ccf_%s_%s_%d%02d%02d%02d.nc'%(id_A, id_B, date_vect[0],date_vect[1],date_vect[2],date_vect[3]) # File Name Understandable

    if os.path.exists(filename_ccf):  # Check if file already exists
        print('%s already computed'%filename_ccf)
        corr = xr.open_dataarray(filename_ccf)
    else:  # if not, compute CCF
        t1 = ttime.perf_counter()
        corr, time_corr = ccf_computation(coords_staA, coords_staB, path_model, date_vect, spectrum_synth,extent=extent, fe=fe, N=N_time, comp='Z')
        t2 = ttime.perf_counter()
        print(" Time for station pair: ", id_A, id_B, " elapsed: ", t2-t1)
        try:
            corr.to_netcdf('./CCF/ccf_%s_%s_%d%02d%02d%02d.nc'%(id_A, id_B, date_vect[0],date_vect[1],date_vect[2],date_vect[3]))
        except:
            print("make directory")
            os.mkdir('./CCF')
            corr.to_netcdf('./CCF/ccf_%s_%s_%d%02d%02d%02d.nc'%(id_A, id_B, date_vect[0],date_vect[1],date_vect[2],date_vect[3]))
    corr_3h[i, :] = corr.values
    # TAKES 25 MIN #
## Compute CCF and save it ### Station Pair Info id_A = df.idA[0] id_B = df.idB[0] coords_staA = (df.lonA[0], df.latA[0]) coords_staB = (df.lonB[0], df.latB[0]) #### Keep Correlations corr_3h = np.zeros((len(dates_vector), N_time)) ### Date Info for i, date_vect in enumerate(dates_vector): ### CCF filename_ccf = './CCF/ccf_%s_%s_%d%02d%02d%02d.nc'%(id_A, id_B, date_vect[0],date_vect[1],date_vect[2],date_vect[3]) # File Name Understandable if os.path.exists(filename_ccf): # Check if file already exists print('%s already computed'%filename_ccf) corr = xr.open_dataarray(filename_ccf) else: # if not, compute CCF t1 = ttime.perf_counter() corr, time_corr = ccf_computation(coords_staA, coords_staB, path_model, date_vect, spectrum_synth,extent=extent, fe=fe, N=N_time, comp='Z') t2 = ttime.perf_counter() print(" Time for station pair: ", id_A, id_B, " elapsed: ", t2-t1) try: corr.to_netcdf('./CCF/ccf_%s_%s_%d%02d%02d%02d.nc'%(id_A, id_B, date_vect[0],date_vect[1],date_vect[2],date_vect[3])) except: print("make directory") os.mkdir('./CCF') corr.to_netcdf('./CCF/ccf_%s_%s_%d%02d%02d%02d.nc'%(id_A, id_B, date_vect[0],date_vect[1],date_vect[2],date_vect[3])) corr_3h[i, :] = corr.values # TAKES 25 MIN #
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111600.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111603.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111606.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111609.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111612.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111615.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111618.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111621.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111700.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111703.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111706.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111709.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111712.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111715.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111718.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111721.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111800.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111803.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111806.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111809.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111812.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111815.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111818.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111821.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111900.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111903.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111906.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111909.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111912.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111915.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111918.nc already computed
./CCF/ccf_XK.LP51.00_XK.SGF.00_2008111921.nc already computed

Plot¶

In [14]:
Copied!
## Plot stack 

plt.figure()
plt.plot(corr.time, np.mean(corr_3h, axis=0), 'k')
plt.xlim(-100, 100)
plt.xlabel('Lag Time (s)')
plt.title('%s - %s stack'%(id_A, id_B))
plt.show()

## Plot CCF
normalize_corr = np.nanmax(abs(corr_3h))
dates_corr = dates

fig, ax = plt.subplots(figsize=(10,8))
im = plt.pcolormesh(corr.time, np.arange(len(dates_vector)), corr_3h/normalize_corr, cmap='seismic', vmin= -0.8, vmax = 0.8)
#ax.plot(corr.time, corr_3h.T/normalize_corr + np.arange(len(dates_vector)), 'k') 
plt.colorbar(im)
ax.set_xlabel('Lag Time (s)')
ax.set_ylabel('Date')
ax.set_title('%s-%s CCF'%(id_A, id_B))
ax.set_xlim(-100, 100)
ax.set_ylim(0, len(dates_vector))
ax.set_yticks(np.arange(len(dates_vector))[::8])
ax.set_yticklabels(dates[::8].strftime('%Y-%m-%dT%H'))

plt.savefig('ccf_%s_%s_synth.png'%(id_A, id_B), dpi=300, bbox_inches='tight')
## Plot stack plt.figure() plt.plot(corr.time, np.mean(corr_3h, axis=0), 'k') plt.xlim(-100, 100) plt.xlabel('Lag Time (s)') plt.title('%s - %s stack'%(id_A, id_B)) plt.show() ## Plot CCF normalize_corr = np.nanmax(abs(corr_3h)) dates_corr = dates fig, ax = plt.subplots(figsize=(10,8)) im = plt.pcolormesh(corr.time, np.arange(len(dates_vector)), corr_3h/normalize_corr, cmap='seismic', vmin= -0.8, vmax = 0.8) #ax.plot(corr.time, corr_3h.T/normalize_corr + np.arange(len(dates_vector)), 'k') plt.colorbar(im) ax.set_xlabel('Lag Time (s)') ax.set_ylabel('Date') ax.set_title('%s-%s CCF'%(id_A, id_B)) ax.set_xlim(-100, 100) ax.set_ylim(0, len(dates_vector)) ax.set_yticks(np.arange(len(dates_vector))[::8]) ax.set_yticklabels(dates[::8].strftime('%Y-%m-%dT%H')) plt.savefig('ccf_%s_%s_synth.png'%(id_A, id_B), dpi=300, bbox_inches='tight')
No description has been provided for this image
No description has been provided for this image
Previous Next

Built with MkDocs using a theme provided by Read the Docs.
GitLab « Previous Next »