93 lines
3.4 KiB
Python
93 lines
3.4 KiB
Python
import os
|
|
import logging
|
|
|
|
import pandas as pd
|
|
import scipy.io
|
|
|
|
from obspy.geodetics import kilometer2degrees
|
|
from obspy.taup import TauPyModel
|
|
from obspy.taup.taup_create import build_taup_model
|
|
from obspy.taup.tau import TauModel
|
|
|
|
|
|
class CustomTauPyModel(TauPyModel):
|
|
"""
|
|
Custom TauPyModel for filepath modification.
|
|
"""
|
|
def __init__(self, filepath, model="iasp91", verbose=False, planet_flattening=0.0):
|
|
super().__init__(model, verbose, planet_flattening)
|
|
self.verbose = verbose
|
|
self.planet_flattening = planet_flattening
|
|
self.model = self.read_model(filepath)
|
|
|
|
@staticmethod
|
|
def read_model(path):
|
|
return TauModel.deserialize(path, cache=None)
|
|
|
|
|
|
class TauPRayTracer:
|
|
""" Class for raytracing seismic waves using TauP """
|
|
def __init__(self, velocity_mat_file):
|
|
logging.basicConfig(filename="application.log",
|
|
filemode='a',
|
|
format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s',
|
|
datefmt='%H:%M:%S',
|
|
level=logging.INFO)
|
|
self.logger = logging.getLogger('converter')
|
|
self.path = "."
|
|
self.velocity_model = self._setup_velocity_model(velocity_mat_file)
|
|
|
|
def _setup_velocity_model(self, velocity_mat_file_name):
|
|
velocity_npz_file_path = f"{velocity_mat_file_name[:-3]}npz"
|
|
velocity_npz_file_name = velocity_npz_file_path.split('/')[-1]
|
|
nd_file = self._mat2nd(velocity_mat_file_name)
|
|
build_taup_model(nd_file, output_folder=f"{self.path}")
|
|
os.remove(nd_file)
|
|
try:
|
|
return CustomTauPyModel(filepath=f"{self.path}/{velocity_npz_file_name}")
|
|
except FileNotFoundError as er:
|
|
self.logger.warning(er)
|
|
|
|
@staticmethod
|
|
def _mat2nd(velocity_mat_file):
|
|
# Load the .mat file
|
|
mat_contents = scipy.io.loadmat(velocity_mat_file)
|
|
data = mat_contents["d"][0][0]
|
|
|
|
# Create DataFrame from the lists
|
|
data_dict = {
|
|
'depth': data[0].T[0],
|
|
'vp': data[1].T[0],
|
|
'vs': data[2].T[0],
|
|
'ro': data[3].T[0],
|
|
'qp': data[4].T[0],
|
|
'qs': data[5].T[0]
|
|
}
|
|
df = pd.DataFrame(data_dict)
|
|
|
|
# Adding two new rows to model file - required by TauP
|
|
# Get the last row of the DataFrame
|
|
last_row = df.iloc[-1].copy()
|
|
# Append the last row to the DataFrame
|
|
|
|
df = pd.concat([df, pd.DataFrame(last_row).T], ignore_index=True)
|
|
last_row['depth'] = 6178.1
|
|
# Append the modified last row to the DataFrame
|
|
df = pd.concat([df, pd.DataFrame(last_row).T], ignore_index=True)
|
|
|
|
# Specify the name of the text file to save
|
|
nd_filename = f'{velocity_mat_file[:-3]}nd'
|
|
# Save the DataFrame to a text file
|
|
df.to_csv(nd_filename, sep='\t', index=False, header=False)
|
|
|
|
return nd_filename
|
|
|
|
def calculate_arrival(self, distance_in_km, source_depth_in_km, receiver_depth_in_km, phase: str):
|
|
phase_list = [phase, phase.swapcase()]
|
|
return self.velocity_model.get_travel_times(source_depth_in_km=source_depth_in_km,
|
|
distance_in_degree=kilometer2degrees(distance_in_km),
|
|
receiver_depth_in_km=receiver_depth_in_km,
|
|
phase_list=phase_list
|
|
)[0]
|
|
|