Skip to content

Commit 16ab85e

Browse files
committed
Added a parameter to better control time-domain normalization
1 parent 3c9d109 commit 16ab85e

File tree

3 files changed

+39
-50
lines changed

3 files changed

+39
-50
lines changed

seismic/xcorqc/correlator.py

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ def process(data_source1, data_source2, output_path,
4343
fmin=None, fmax=None, netsta_list1='*', netsta_list2='*', pairs_to_compute=None,
4444
start_time='1970-01-01T00:00:00', end_time='2100-01-01T00:00:00',
4545
instrument_response_inventory=None, instrument_response_output='vel', water_level=50,
46-
clip_to_2std=False, whitening=False, whitening_window_frequency=0,
47-
one_bit_normalize=False, location_preferences=None, ds1_zchan=None, ds1_nchan=None,
46+
time_domain_norm='zero_mean_one_std', whitening=False, whitening_window_frequency=0,
47+
location_preferences=None, ds1_zchan=None, ds1_nchan=None,
4848
ds1_echan=None, ds2_zchan=None, ds2_nchan=None, ds2_echan=None, corr_chan=None,
4949
envelope_normalize=False, ensemble_stack=False, subset_stacker=None, apply_simple_stacking=True,
5050
restart=False, dry_run=False, no_tracking_tag=False, scratch_folder=None):
@@ -113,8 +113,7 @@ def outputConfigParameters():
113113
f.write('%35s\t\t\t: %s\n' % ('--instrument-response-output', instrument_response_output))
114114
f.write('%35s\t\t\t: %s\n' % ('--corr-chan', corr_chan))
115115
f.write('%35s\t\t\t: %s\n' % ('--water-level', water_level))
116-
f.write('%35s\t\t\t: %s\n' % ('--clip-to-2std', clip_to_2std))
117-
f.write('%35s\t\t\t: %s\n' % ('--one-bit-normalize', one_bit_normalize))
116+
f.write('%35s\t\t\t: %s\n' % ('--time-domain-norm', time_domain_norm))
118117
f.write('%35s\t\t\t: %s\n' % ('--envelope-normalize', envelope_normalize))
119118
f.write('%35s\t\t\t: %s\n' % ('--whitening', whitening))
120119
if(whitening):
@@ -309,8 +308,8 @@ def get_loccha(cha1, cha2):
309308
baz_netsta1, baz_netsta2,
310309
resample_rate, taper_length, read_ahead_window_seconds,
311310
interval_seconds, window_seconds, window_overlap,
312-
window_buffer_length, fmin, fmax, clip_to_2std, whitening,
313-
whitening_window_frequency, one_bit_normalize, envelope_normalize,
311+
window_buffer_length, fmin, fmax, time_domain_norm, whitening,
312+
whitening_window_frequency, envelope_normalize,
314313
ensemble_stack, subset_stacker, apply_simple_stacking, output_path, 2,
315314
time_tag, scratch_folder, git_hash)
316315
# end for
@@ -389,19 +388,21 @@ def get_loccha(cha1, cha2):
389388
help="Water-level in dB to limit amplification during instrument response correction "
390389
"to a certain cut-off value. Note, this parameter has no effect if instrument "
391390
"response correction is not performed.")
392-
@click.option('--clip-to-2std', is_flag=True,
393-
help="Clip data in each window to +/- 2 standard deviations. Note that the default time-domain normalization "
394-
"is N(0,1), i.e. 0-mean and unit variance")
391+
@click.option('--time-domain-norm', type=click.Choice(['zero_mean_one_std', 'clip_to_two_std',
392+
'one_bit_norm', 'none']),
393+
default='zero_mean_one_std',
394+
help="Time domain normalization: "
395+
"zero_mean_one_std: the default time-domain normalization, N(0,1), i.e. 0-mean and unit variance"
396+
"clip_to_two_std: clips data in each window to +/- 2 standard deviations. "
397+
"one_bit_norm: apply one-bit normalization to data in each window"
398+
"none: no time domain normalization")
395399
@click.option('--whitening', is_flag=True,
396400
help="Apply spectral whitening")
397401
@click.option('--whitening-window-frequency', type=float, default=0,
398402
help="Window frequency (Hz) determines the half-window length (of averaging window) used for smoothing weights "
399403
"that scale the spectral amplitudes of the waveform being spectrally whitened. The default value of 0 "
400404
"implies no smoothing of weights. Note that this parameter has no effect unless whitening is activated with "
401405
"'--whitening'")
402-
@click.option('--one-bit-normalize', is_flag=True,
403-
help="Apply one-bit normalization to data in each window. Note that the default time-domain normalization "
404-
"is N(0,1), i.e. 0-mean and unit variance")
405406
@click.option('--location-preferences', default=None,
406407
type=click.Path(exists=True),
407408
help="A comma-separated two-columned text file containing location code preferences for "
@@ -465,7 +466,7 @@ def main(data_source1, data_source2, output_path, window_seconds, window_overlap
465466
stacking_interval_seconds, window_buffer_length, resample_rate, taper_length, nearest_neighbours,
466467
pair_min_dist, pair_max_dist, fmin, fmax, station_names1, station_names2, pairs_to_compute,
467468
start_time, end_time, instrument_response_inventory, instrument_response_output, water_level,
468-
clip_to_2std, whitening, whitening_window_frequency, one_bit_normalize, location_preferences,
469+
time_domain_norm, whitening, whitening_window_frequency, location_preferences,
469470
ds1_zchan, ds1_nchan, ds1_echan, ds2_zchan, ds2_nchan, ds2_echan, corr_chan, envelope_normalize,
470471
ensemble_stack, subset_stack, restart, dry_run, no_tracking_tag, scratch_folder):
471472
"""
@@ -538,7 +539,7 @@ def main(data_source1, data_source2, output_path, window_seconds, window_overlap
538539
window_buffer_length, read_ahead_window_seconds, resample_rate, taper_length, nearest_neighbours,
539540
pair_min_dist, pair_max_dist, fmin, fmax, station_names1, station_names2, pairs_to_compute,
540541
start_time, end_time, instrument_response_inventory, instrument_response_output, water_level,
541-
clip_to_2std, whitening, whitening_window_frequency, one_bit_normalize, location_preferences,
542+
time_domain_norm, whitening, whitening_window_frequency, location_preferences,
542543
ds1_zchan, ds1_nchan, ds1_echan, ds2_zchan, ds2_nchan, ds2_echan, corr_chan, envelope_normalize,
543544
ensemble_stack, subset_stacker, apply_simple_stacking, restart, dry_run, no_tracking_tag,
544545
scratch_folder)

seismic/xcorqc/xcorqc.py

Lines changed: 21 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,8 @@ def xcorr2(tr1, tr2, sta1_inv=None, sta2_inv=None,
115115
instrument_response_output='vel', water_level=50.,
116116
window_seconds=3600, window_overlap=0.1, window_buffer_length=0,
117117
interval_seconds=86400, taper_length=0.05, resample_rate=None,
118-
flo=None, fhi=None, clip_to_2std=False, whitening=False,
119-
whitening_window_frequency=0, one_bit_normalize=False, envelope_normalize=False,
118+
flo=None, fhi=None, time_domain_norm='zero_mean_one_std', whitening=False,
119+
whitening_window_frequency=0, envelope_normalize=False,
120120
apply_simple_stacking=True, verbose=1, logger=None):
121121

122122
# Length of window_buffer in seconds
@@ -346,34 +346,30 @@ def xcorr2(tr1, tr2, sta1_inv=None, sta2_inv=None,
346346
# end if
347347

348348
# STEP 7: time-domain normalization
349+
# Apply Rhys Hawkins-style default time domain normalization
350+
if (time_domain_norm == 'zero_mean_one_std'):
351+
# 0-mean
352+
tr1_d -= np.mean(tr1_d)
353+
tr2_d -= np.mean(tr2_d)
354+
355+
# unit-std
356+
tr1_d /= np.std(tr1_d)
357+
tr2_d /= np.std(tr2_d)
349358
# clip to +/- 2*std
350-
if clip_to_2std:
359+
elif time_domain_norm == 'clip_to_two_std':
351360
std_tr1 = np.std(tr1_d)
352361
std_tr2 = np.std(tr2_d)
353362
clip_indices_tr1 = np.fabs(tr1_d) > 2 * std_tr1
354363
clip_indices_tr2 = np.fabs(tr2_d) > 2 * std_tr2
355364

356365
tr1_d[clip_indices_tr1] = 2 * std_tr1 * np.sign(tr1_d[clip_indices_tr1])
357366
tr2_d[clip_indices_tr2] = 2 * std_tr2 * np.sign(tr2_d[clip_indices_tr2])
358-
# end if
359-
360367
# 1-bit normalization
361-
if one_bit_normalize:
368+
elif time_domain_norm == 'one_bit_norm':
362369
tr1_d = np.sign(tr1_d)
363370
tr2_d = np.sign(tr2_d)
364371
# end if
365372

366-
# Apply Rhys Hawkins-style default time domain normalization
367-
if (clip_to_2std == 0) and (one_bit_normalize == 0):
368-
# 0-mean
369-
tr1_d -= np.mean(tr1_d)
370-
tr2_d -= np.mean(tr2_d)
371-
372-
# unit-std
373-
tr1_d /= np.std(tr1_d)
374-
tr2_d /= np.std(tr2_d)
375-
# end if
376-
377373
# STEP 8: taper
378374
if adjusted_taper_length > 0:
379375
tr1_d = taper(tr1_d, int(np.round(adjusted_taper_length*tr1_d.shape[0])))
@@ -520,8 +516,9 @@ def IntervalStackXCorr(refds, tempds,
520516
read_ahead_window_seconds=864000, interval_seconds=86400,
521517
window_seconds=3600, window_overlap=0.1, window_buffer_length=0,
522518
flo=None, fhi=None,
523-
clip_to_2std=False, whitening=False, whitening_window_frequency=0,
524-
one_bit_normalize=False, envelope_normalize=False,
519+
time_domain_norm='zero_mean_one_std',
520+
whitening=False, whitening_window_frequency=0,
521+
envelope_normalize=False,
525522
ensemble_stack=False,
526523
subset_stacker: SubsetStacker=None,
527524
apply_simple_stacking=True,
@@ -584,15 +581,14 @@ def IntervalStackXCorr(refds, tempds,
584581
:param flo: Lower frequency for Butterworth bandpass filter
585582
:type fhi: float
586583
:param fhi: Upper frequency for Butterworth bandpass filter
587-
:type clip_to_2std: bool
588-
:param clip_to_2std: Clip data in each window to +/- 2 standard deviations
584+
:type time_domain_norm: str
585+
:param time_domain_norm: type of time domain normalization: 'zero_mean_one_std', 'clip_to_two_std',
586+
'one_bit_norm', 'none'
589587
:type whitening: bool
590588
:param whitening: Apply spectral whitening
591589
:type whitening_window_frequency: float
592590
:param whitening_window_frequency: Window frequency (Hz) used to determine length of averaging window \
593591
for smoothing spectral amplitude
594-
:type one_bit_normalize: bool
595-
:param one_bit_normalize: Apply one-bit normalization to data in each window
596592
:type envelope_normalize: bool
597593
:param envelope_normalize: Envelope via Hilbert transforms and normalize
598594
:type ensemble_stack: bool
@@ -628,11 +624,6 @@ def IntervalStackXCorr(refds, tempds,
628624
if resample_rate < 2*fhi:
629625
raise ValueError('Resample-rate should be >= 2*fmax')
630626

631-
if clip_to_2std and one_bit_normalize:
632-
raise ValueError('Mutually exclusive parameterization: clip_to_2std and one-bit-normalizations'
633-
'together is redundant')
634-
# end if
635-
636627
# get preferred location codes, or use the first available
637628
ref_loc, ref_cha = ref_loc_cha.split('.')
638629
temp_loc, temp_cha = temp_loc_cha.split('.')
@@ -778,10 +769,9 @@ def IntervalStackXCorr(refds, tempds,
778769
resample_rate=resample_rate,
779770
taper_length=taper_length,
780771
flo=flo, fhi=fhi,
781-
clip_to_2std=clip_to_2std,
772+
time_domain_norm=time_domain_norm,
782773
whitening=whitening,
783774
whitening_window_frequency=whitening_window_frequency,
784-
one_bit_normalize=one_bit_normalize,
785775
envelope_normalize=envelope_normalize,
786776
apply_simple_stacking=apply_simple_stacking,
787777
verbose=verbose, logger=logger)
@@ -975,9 +965,7 @@ def IntervalStackXCorr(refds, tempds,
975965
'window_buffer_length': window_buffer_length,
976966
'bandpass_fmin': flo if flo else -999,
977967
'bandpass_fmax': fhi if fhi else -999,
978-
'clip_to_2std': int(clip_to_2std),
979-
'one_bit_normalize': int(one_bit_normalize),
980-
'zero_mean_1std_normalize': int(clip_to_2std is False and one_bit_normalize is False),
968+
'time_domain_norm': time_domain_norm,
981969
'spectral_whitening': int(whitening),
982970
'envelope_normalize': int(envelope_normalize),
983971
'ensemble_stack': int(ensemble_stack),

tests/test_seismic/xcorqc/test_correlator.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,9 @@ def test_correlator():
7474
86400, 3600, 0.1,
7575
0.05, 86400, 4, 0.05, -1, None, None, 0.002, 2, netsta1,
7676
netsta2, None, start_time, end_time, None, 'vel',
77-
50, False, True, 0.02, True, loc_pref,
77+
50, 'one_bit_norm', True, 0.02, loc_pref,
7878
'*Z', '*N', '*E', '*Z', '*N', '*E', 'z', False, False,
79-
None, True, False, False, True, None)
79+
None, True, False, False, True)
8080

8181

8282
# Read result
@@ -107,7 +107,7 @@ def test_correlator():
107107
86400, 3600, 0.1,
108108
0.05, 86400, 4, 0.05, -1, None, None, 0.002, 2, netsta1,
109109
netsta2, None, start_time, end_time, None, 'vel',
110-
50, False, True, 0.02, True, loc_pref,
110+
50, 'one_bit_norm', True, 0.02, loc_pref,
111111
'*Z', '*N', '*E', '*Z', '*N', '*E', 'z', False, False,
112112
None, False, False, False, True, None)
113113

0 commit comments

Comments
 (0)