Skip to content

Commit

Permalink
Spectrum() class redesign
Browse files Browse the repository at this point in the history
Class is redesigned so that it does not inherit anymore from ObsPy's
Trace class. This allows to have a more flexible class that can be
expanded in the future.

Also add a SpectrumStream class to handle a collection of
Spectrum objects.
  • Loading branch information
claudiodsf committed Mar 25, 2024
1 parent 6c3ec9d commit b6023a7
Show file tree
Hide file tree
Showing 10 changed files with 324 additions and 123 deletions.
17 changes: 8 additions & 9 deletions sourcespec/source_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
2013-2014 Claudio Satriano <[email protected]>,
Agnes Chounet <[email protected]>
2015-2023 Claudio Satriano <[email protected]>
2015-2024 Claudio Satriano <[email protected]>
:license:
CeCILL Free Software License Agreement v2.1
(http://www.cecill.info/licences.en.html)
Expand Down Expand Up @@ -37,10 +37,9 @@ def make_synth(config, spec_st, trace_spec=None):
spec = Spectrum()
if trace_spec:
spec.stats = deepcopy(trace_spec.stats)
spec.freq = trace_spec.freq.copy()
else:
spec.stats.begin = fmin
spec.stats.delta = fdelta
spec.stats.npts = int((fmax - fmin) / fdelta)
spec.freq = np.arange(fmin, fmax, fdelta)

if math.isnan(Mo):
Mo = mag_to_moment(mag)
Expand All @@ -53,7 +52,7 @@ def make_synth(config, spec_st, trace_spec=None):
spec.stats.par = {
'Mw': mag, 'fc': fc, 't_star': t_star, 'alpha': alpha}

freq = spec.get_freq()
freq = spec.freq
freq_logspaced = trace_spec.freq_logspaced
spec.freq_logspaced = freq_logspaced
spec.data_mag = spectral_model(freq, mag, fc, t_star, alpha)
Expand Down Expand Up @@ -89,10 +88,10 @@ def main():
}
config = configure(
options, progname='source_model', config_overrides=conf_overrides)
from sourcespec.spectrum import SpectrumStream
from sourcespec.ssp_read_traces import read_traces
from sourcespec.ssp_process_traces import process_traces
from sourcespec.ssp_build_spectra import build_spectra
from obspy.core import Stream

# We don't use weighting in source_model
config.weighting = 'no_weight'
Expand All @@ -105,16 +104,16 @@ def main():
if len(spec_st) == 0:
ssp_exit()
# We keep just horizontal component:
spec_st = Stream([x for x in spec_st.traces
if x.stats.channel[-1] == 'H'])
spec_st = SpectrumStream(
[x for x in spec_st if x.stats.channel[-1] == 'H'])

for trace_spec in spec_st:
orientation = trace_spec.stats.channel[-1]
if orientation != 'H':
continue
make_synth(config, spec_st, trace_spec)
else:
spec_st = Stream()
spec_st = SpectrumStream()
make_synth(config, spec_st)

from sourcespec.ssp_plot_spectra import plot_spectra
Expand Down
33 changes: 14 additions & 19 deletions sourcespec/source_residuals.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
2013-2014 Claudio Satriano <[email protected]>,
Agnes Chounet <[email protected]>
2015-2023 Claudio Satriano <[email protected]>
2015-2024 Claudio Satriano <[email protected]>
:license:
CeCILL Free Software License Agreement v2.1
(http://www.cecill.info/licences.en.html)
Expand All @@ -17,11 +17,10 @@
from collections import defaultdict
import pickle
from argparse import ArgumentParser
from obspy.core import Stream
import matplotlib
import matplotlib.pyplot as plt
from sourcespec.ssp_util import moment_to_mag, mag_to_moment
from sourcespec.spectrum import Spectrum
from sourcespec.spectrum import SpectrumStream
matplotlib.use('Agg') # NOQA


Expand Down Expand Up @@ -77,7 +76,7 @@ def read_residuals(resfiles_dir):
)
if not resfiles:
sys.exit(f'No residual file found in directory: {resfiles_dir}')
residual_dict = defaultdict(Stream)
residual_dict = defaultdict(SpectrumStream)
for resfile in resfiles:
print(f'Found residual file: {resfile}')
with open(resfile, 'rb') as fp:
Expand All @@ -100,34 +99,30 @@ def compute_mean_residuals(residual_dict, min_spectra=20):
Returns
-------
residual_mean : Stream
residual_mean : SpectrumStream
Stream containing mean residuals for each station.
"""
residual_mean = Stream()
residual_mean = SpectrumStream()
for stat_id in sorted(residual_dict.keys()):
if len(residual_dict[stat_id]) < min_spectra:
continue
print(f'Processing station: {stat_id}')

res = residual_dict[stat_id]

freqs_min = [spec.get_freq().min() for spec in res]
freqs_max = [spec.get_freq().max() for spec in res]
freqs_min = [spec.freq.min() for spec in res]
freqs_max = [spec.freq.max() for spec in res]
freq_min = min(freqs_min)
freq_max = max(freqs_max)

spec_mean = Spectrum()
spec_mean.id = stat_id
spec_mean.stats.begin = freq_min
spec_mean.stats.delta = res[0].stats.delta
spec_mean.data_mag = None
spec_mean = None
for spec in res:
spec_slice = spec.slice(freq_min, freq_max, pad=True,
fill_value=mag_to_moment(0))
spec_slice.data_mag = moment_to_mag(spec_slice.data)
norm = (spec_slice.data_mag != 0).astype(int)
if spec_mean.data_mag is None:
spec_mean.data_mag = spec_slice.data_mag
if spec_mean is None:
spec_mean = spec_slice
norm_mean = norm
else:
try:
Expand All @@ -150,8 +145,8 @@ def plot_residuals(residual_dict, residual_mean, outdir):
----------
residual_dict : dict
Dictionary containing residuals for each station.
residual_mean : Stream
Stream containing mean residuals for each station.
residual_mean : SpectrumStream
SpectrumStream containing mean residuals for each station.
outdir : str
Output directory.
"""
Expand All @@ -161,8 +156,8 @@ def plot_residuals(residual_dict, residual_mean, outdir):
figurefile = os.path.join(outdir, f'{stat_id}-res.png')
fig = plt.figure(dpi=160)
for spec in res:
plt.semilogx(spec.get_freq(), spec.data_mag, 'b-')
plt.semilogx(spec_mean.get_freq(), spec_mean.data_mag, 'r-')
plt.semilogx(spec.freq, spec.data_mag, 'b-')
plt.semilogx(spec_mean.freq, spec_mean.data_mag, 'r-')
plt.xlabel('frequency (Hz)')
plt.ylabel('residual amplitude (obs - synth) in magnitude units')
plt.title(f'residuals: {stat_id}{len(res)} records')
Expand Down
Loading

0 comments on commit b6023a7

Please sign in to comment.