66from mpi4py import MPI
77import os
88import re
9- import logging
109import itertools
1110
1211import numpy as np
3130from shutil import rmtree
3231from collections import defaultdict
3332from seismic .misc import split_list
34-
35- logging .basicConfig ()
33+ from seismic .misc import setup_logger
3634
3735paper_size_A4 = (8.27 , 11.69 ) # inches
38-
3936DEFAULT_HK_SOLN_LABEL = 'global'
4037
4138def _get_aspect (ax ):
@@ -96,7 +93,7 @@ def _rf_layout_A4(fig):
9693def _produce_hk_stacking (channel_data , Vp = rf_stacking .DEFAULT_Vp ,
9794 weighting = rf_stacking .DEFAULT_WEIGHTS ,
9895 semblance_weighted = True , labelling = DEFAULT_HK_SOLN_LABEL ,
99- depth_colour_range = (20 , 70 )):
96+ depth_colour_range = (20 , 70 ), log = None ):
10097 """Helper function to produce H-k stacking figure."""
10198
10299 k_grid , h_grid , hk_stack = rf_stacking .compute_hk_stack (channel_data ,
@@ -130,10 +127,10 @@ def _produce_hk_stacking(channel_data, Vp=rf_stacking.DEFAULT_Vp,
130127 if labelling == 'global' :
131128 h_max , k_max = rf_stacking .find_global_hk_maximum (k_grid , h_grid , hk_stack )
132129 soln = [(h_max , k_max )]
133- log .info ("Numerical solution (H, k) = ({:.3f}, {:.3f})" .format (* soln [0 ]))
130+ if ( log ): log .info ("Numerical solution (H, k) = ({:.3f}, {:.3f})" .format (* soln [0 ]))
134131 elif labelling == 'local' :
135132 soln = rf_stacking .find_local_hk_maxima (k_grid , h_grid , hk_stack )
136- log .info ("Numerical solutions (H, k) = {}" .format (soln ))
133+ if ( log ): log .info ("Numerical solutions (H, k) = {}" .format (soln ))
137134 # end if
138135
139136 # ==========================================================================
@@ -169,7 +166,7 @@ def compute_arrival_times(p, h, k):
169166# end func
170167
171168def _produce_sediment_hk_stacking (channel_data , H_c , k_c , Vp = rf_stacking .DEFAULT_Vp ,
172- labelling = DEFAULT_HK_SOLN_LABEL ):
169+ labelling = DEFAULT_HK_SOLN_LABEL , log = None ):
173170 """Helper function to produce H-k stacking figure."""
174171
175172 k_grid , h_grid , hk_stack , weighting = rf_stacking .compute_sediment_hk_stack (channel_data ,
@@ -200,10 +197,10 @@ def _produce_sediment_hk_stacking(channel_data, H_c, k_c, Vp=rf_stacking.DEFAULT
200197 if labelling == 'global' :
201198 h_max , k_max = rf_stacking .find_global_hk_maximum (k_grid , h_grid , hk_stack )
202199 soln = [(h_max , k_max )]
203- log .info ("Numerical solution (H, k) = ({:.3f}, {:.3f})" .format (* soln [0 ]))
200+ if ( log ): log .info ("Numerical solution (H, k) = ({:.3f}, {:.3f})" .format (* soln [0 ]))
204201 elif labelling == 'local' :
205202 soln = rf_stacking .find_local_hk_maxima (k_grid , h_grid , hk_stack )
206- log .info ("Numerical solutions (H, k) = {}" .format (soln ))
203+ if ( log ): log .info ("Numerical solutions (H, k) = {}" .format (soln ))
207204 # end if
208205
209206 # Plot the local maxima
@@ -254,8 +251,11 @@ def _plot_hk_solution_point(axes, k, h, idx, phase_time_dict=None):
254251@click .option ('--event-mask-folder' , type = click .Path (dir_okay = True , exists = True , file_okay = False ),
255252 help = 'Folder containing event masks to use to filter traces. Such masks are generated '
256253 'using rf_handpick_tool' )
257- @click .option ('--apply-amplitude-filter' , is_flag = True , default = False , show_default = True ,
258- help = 'Apply RF amplitude filtering to the RFs. The default filtering logic includes: '
254+ @click .option ('--relax-sanity-checks' , is_flag = True , default = False , show_default = True ,
255+ help = 'RF traces with amplitudes > 1.0 or troughs around onset time are dropped by default. '
256+ 'This option allows RF traces with amplitudes > 1.0 to pass through' )
257+ @click .option ('--apply-simple-quality-filter' , is_flag = True , default = False , show_default = True ,
258+ help = 'Apply RF snr and amplitude filtering to the RFs. The default filtering logic includes: '
259259 'Signal SNR >= 2.0 '
260260 'RMS amplitude of signal < 0.2 '
261261 'Maximum amplitude of signal < 1.0' )
@@ -291,8 +291,8 @@ def _plot_hk_solution_point(axes, k, h, idx, phase_time_dict=None):
291291@click .option ('--disable-semblance-weighting' , is_flag = True , default = False , show_default = True ,
292292 help = 'Disables default semblance-weighting applied to H-k stacks' )
293293def main (input_file , output_file , network_list = '*' , station_list = '*' , event_mask_folder = '' ,
294- apply_amplitude_filter = False , apply_similarity_filter = False , min_slope_ratio = - 1 ,
295- force_dereverberate = None , filter_by_distance = None ,
294+ relax_sanity_checks = False , apply_simple_quality_filter = False , apply_similarity_filter = False ,
295+ min_slope_ratio = - 1 , force_dereverberate = None , filter_by_distance = None ,
296296 hk_vp = rf_stacking .DEFAULT_Vp , hk_weights = rf_stacking .DEFAULT_WEIGHTS ,
297297 hk_solution_labels = DEFAULT_HK_SOLN_LABEL , depth_colour_range = (20 , 70 ),
298298 hk_hpf_freq = None , hk_hpf_after_dereverberation = False , disable_semblance_weighting = False ):
@@ -303,8 +303,13 @@ def main(input_file, output_file, network_list='*', station_list='*', event_mask
303303 OUTPUT_FILE : Output pdf file name
304304 """
305305
306+ log = setup_logger ('__func__' , log_file = os .path .splitext (output_file )[0 ] + '.log' )
306307
307- log .setLevel (logging .INFO )
308+ # check parameter compatibility
309+ if (relax_sanity_checks and apply_simple_quality_filter ):
310+ raise RuntimeError ('Options --relax-sanity-checks and --apply-simple-quality-filter '
311+ 'are mutually exclusive. Aborting..' )
312+ # end if
308313
309314 comm = MPI .COMM_WORLD
310315 nproc = comm .Get_size ()
@@ -416,8 +421,6 @@ def match_stations(sta, sta_list):
416421 total_trace_height_inches = paper_size_A4 [1 ] - fixed_stack_height_inches - y_pad_inches
417422 max_trace_height = 0.2
418423
419- log .setLevel (logging .WARNING )
420-
421424 curr_output_file = os .path .join (tempdir , '{}.pdf' .format (nsl ))
422425
423426 with PdfPages (curr_output_file ) as pdf :
@@ -443,35 +446,91 @@ def match_stations(sta, sta_list):
443446 transverse_data = station_db [t_channel ]
444447
445448 rf_stream = rf .RFStream (channel_data ).sort (['back_azimuth' ])
449+
450+
451+ ###############################################################################
452+ # Remove streams from masked events
453+ ###############################################################################
446454 if event_mask_dict and full_code in event_mask_dict :
447455 # Select events from external source
448456 event_mask = event_mask_dict [full_code ]
457+ before = len (rf_stream )
449458 rf_stream = rf .RFStream (
450459 [tr for tr in rf_stream if tr .stats .event_id in event_mask ]).sort (['back_azimuth' ])
460+ after = len (rf_stream )
461+
462+ if (before > after ):
463+ log .info ("{}: {}/{} RF traces from masked events dropped.." .
464+ format (nsl ,
465+ before - after ,
466+ before ))
467+ # end if
468+ if (after == 0 ):
469+ log .warning ("All RF traces for {} were from masked events.." .format (nsl ))
470+ # end if
471+ # end if
472+
473+ if not rf_stream : continue
474+
475+ ###############################################################################
476+ # RF amplitudes should not exceed 1.0 and should peak around onset time --
477+ # otherwise, such traces are deemed problematic and excluded while computing
478+ # H-k stacks. Only applies for P RFs.
479+ ###############################################################################
480+ if (rf_type == 'prf' ):
481+ before = len (rf_stream )
482+ rf_stream = rf_util .\
483+ filter_invalid_radial_component (rf_stream ,
484+ allow_rfs_over_unity = relax_sanity_checks )
485+ after = len (rf_stream )
486+
487+ if (before > after ):
488+ log .info ("{}: {}/{} RF traces with amplitudes > 1.0 or troughs around "
489+ "onset time dropped before computing H-k stack .." .
490+ format (nsl ,
491+ before - after ,
492+ before ))
493+ # end if
494+ if (after == 0 ):
495+ log .warning ("Sanity check filter has removed all traces for {}.." .format (nsl ))
496+ # end if
451497 # end if
452498
499+ if not rf_stream : continue
500+
453501 ###############################################################################
454502 # Restrict RFs by distance if specified
455503 ###############################################################################
456504 if st in filter_by_distance_dict .keys ():
457505 min_dist , max_dist = filter_by_distance_dict [st ]
458506
507+ before = len (rf_stream )
459508 rf_stream = rf_util .filter_by_distance (rf_stream , min_dist , max_dist )
460- if (len (rf_stream ) == 0 ):
509+ after = len (rf_stream )
510+ log .info ('{}: ({}/{}) traces dropped using distance filter..' .format (nsl ,
511+ before - after ,
512+ before ))
513+ if (after == 0 ):
461514 log .warning ("Filter-by-distance has removed all traces for {}." .format (nsl ))
462515 # end if
463516 # end if
464517
465518 ###############################################################################
466519 # Apply amplitude filter
467520 ###############################################################################
468- if apply_amplitude_filter :
521+ if apply_simple_quality_filter :
469522 # Label and filter quality
470523 rf_util .label_rf_quality_simple_amplitude (rf_rot , rf_stream )
524+ before = len (rf_stream )
471525 rf_stream = rf .RFStream (
472526 [tr for tr in rf_stream if tr .stats .predicted_quality == 'a' ]).sort (['back_azimuth' ])
473- if (len (rf_stream ) == 0 ):
474- log .warning ("Amplitude filter has removed all traces for {}. "
527+ after = len (rf_stream )
528+ log .info ('{}: ({}/{}) traces dropped using predicted quality filter..' .
529+ format (nsl ,
530+ before - after ,
531+ before ))
532+ if (after == 0 ):
533+ log .warning ("Predicted quality filter has removed all traces for {}. "
475534 "Ensure rf_quality_filter was run beforehand.." .format (nsl ))
476535 # end if
477536 # end if
@@ -480,15 +539,35 @@ def match_stations(sta, sta_list):
480539 # Apply slope-ratio filter
481540 ###############################################################################
482541 if (min_slope_ratio > 0 ):
542+ before = len (rf_stream )
483543 rf_stream = rf .RFStream ([tr for tr in rf_stream \
484544 if tr .stats .slope_ratio > min_slope_ratio ]).sort (['back_azimuth' ])
545+ after = len (rf_stream )
546+ log .info ('{}: ({}/{}) traces dropped using min-slope-ratio filter..' .
547+ format (nsl ,
548+ before - after ,
549+ before ))
550+ if (after == 0 ):
551+ log .warning ("Min-slope-ratio filter has removed all traces for {}.." .format (nsl ))
552+ # end if
485553 # end if
486554
555+ if not rf_stream : continue
556+
487557 ###############################################################################
488558 # Apply similarity filter
489559 ###############################################################################
490560 if apply_similarity_filter and len (rf_stream ) >= 3 :
561+ before = len (rf_stream )
491562 rf_stream = rf_util .filter_crosscorr_coeff (rf_stream )
563+ after = len (rf_stream )
564+ log .info ('{}: ({}/{}) traces dropped using similarity filter..' .
565+ format (nsl ,
566+ before - after ,
567+ before ))
568+ if (after == 0 ):
569+ log .warning ("Similarity filter has removed all traces for {}.." .format (nsl ))
570+ # end if
492571 # end if
493572
494573 if not rf_stream : continue
@@ -509,31 +588,11 @@ def match_stations(sta, sta_list):
509588 reverberations_removed = False
510589 # Apply reverberation filter if needed (or forced). Only applies for P RFs
511590 if ((rf_corrections .has_reverberations (rf_stream ) or st in fd_sta_list ) and
512- (rf_type == 'prf' )):
591+ (rf_type == 'prf' )):
513592 rf_stream = rf_corrections .apply_reverberation_filter (rf_stream )
514593 reverberations_removed = True
515594 # end if
516595
517- ###############################################################################
518- # RF amplitudes should not exceed 1.0 and should peak around onset time --
519- # otherwise, such traces are deemed problematic and excluded while computing
520- # H-k stacks. Only applies for P RFs.
521- ###############################################################################
522- if (rf_type == 'prf' ):
523- before = len (rf_stream )
524- rf_stream = rf_util .filter_invalid_radial_component (rf_stream )
525- after = len (rf_stream )
526-
527- if (before > after ):
528- print ("{}: {}/{} RF traces with amplitudes > 1.0 or troughs around "
529- "onset time dropped before computing H-k stack .." .format (full_code ,
530- before - after ,
531- before ))
532- # end if
533- # end if
534-
535- if not rf_stream : continue
536-
537596 ###############################################################################
538597 # Filter rf_stream if needed, after dereverberation, as requested
539598 ###############################################################################
@@ -632,7 +691,8 @@ def match_stations(sta, sta_list):
632691 fig , maxima = _produce_hk_stacking (rf_stream , Vp = hk_vp , weighting = hk_weights ,
633692 semblance_weighted = (not disable_semblance_weighting ),
634693 labelling = hk_solution_labels ,
635- depth_colour_range = depth_colour_range )
694+ depth_colour_range = depth_colour_range ,
695+ log = log )
636696 hk_soln [nsl ] = maxima
637697 station_coords [nsl ] = (channel_data [0 ].stats .station_longitude , channel_data [0 ].stats .station_latitude )
638698
@@ -647,7 +707,7 @@ def match_stations(sta, sta_list):
647707 if (len (hk_soln [nsl ])):
648708 H_c = hk_soln [nsl ][0 ][0 ]
649709 k_c = hk_soln [nsl ][0 ][1 ]
650- fig , maxima = _produce_sediment_hk_stacking (rf_stream , H_c = H_c , k_c = k_c , Vp = hk_vp )
710+ fig , maxima = _produce_sediment_hk_stacking (rf_stream , H_c = H_c , k_c = k_c , Vp = hk_vp , log = log )
651711 sediment_hk_soln [nsl ] = maxima
652712
653713 sediment_station_coords [nsl ] = (channel_data [0 ].stats .station_longitude ,
@@ -732,12 +792,11 @@ def flatten_dict_list(dict_list):
732792 if (rank == 0 ):
733793 rmtree (tempdir )
734794
735- print ("Finishing..." )
736- print ("bulk_rf_report SUCCESS!" )
795+ log . info ("Finishing..." )
796+ log . info ("bulk_rf_report SUCCESS!" )
737797 # end if
738798# end main
739799
740800if __name__ == "__main__" :
741- log = logging .getLogger (__name__ )
742801 main () # pylint: disable=no-value-for-parameter
743802# end if
0 commit comments