def autoselect_windows(self, event): """ Automatically select proper time windows. """ for component in ["Z", "N", "E"]: real_trace = self.data["data"].select(component=component) synth_trace = self.data["synthetics"].select(channel=component) if not real_trace or not synth_trace: continue real_trace = real_trace[0] synth_trace = synth_trace[0] windows = select_windows( real_trace, synth_trace, self.event["latitude"], self.event["longitude"], self.event["depth_in_km"], self.data["coordinates"]["latitude"], self.data["coordinates"]["longitude"], 1.0 / self.process_parameters["lowpass"], 1.0 / self.process_parameters["highpass"]) for idx_start, idx_end in windows: window_start = self.time_axis[int(round(idx_start))] window_end = self.time_axis[int(round(idx_end))] self._onWindowSelected(window_start, window_end - window_start, axis=getattr(self, "plot_axis_%s" % component.lower()))
def select_windows_for_station(self, event, iteration, station): """ Selects windows for the given event, iteration, and station. Will delete any previously existing windows for that station if any. :param event: The event. :param iteration: The iteration. :param station: The station id in the form NET.STA. """ from lasif.utils import select_component_from_stream from lasif.window_selection import select_windows event = self.comm.events.get(event) iteration = self.comm.iterations.get(iteration) data = self.comm.query.get_matching_waveforms(event, iteration, station) process_params = iteration.get_process_params() minimum_period = 1.0 / process_params["lowpass"] maximum_period = 1.0 / process_params["highpass"] window_group_manager = self.comm.windows.get(event, iteration) # Delete the windows for this stations. window_group_manager.delete_windows_for_station(station) found_something = False for component in ["E", "N", "Z"]: try: data_tr = select_component_from_stream(data.data, component) synth_tr = select_component_from_stream(data.synthetics, component) except LASIFNotFoundError: continue found_something = True windows = select_windows(data_tr, synth_tr, event["latitude"], event["longitude"], event["depth_in_km"], data.coordinates["latitude"], data.coordinates["longitude"], minimum_period=minimum_period, maximum_period=maximum_period) if not windows: continue window_group = window_group_manager.get(data_tr.id) for starttime, endtime in windows: window_group.add_window(starttime=starttime, endtime=endtime) window_group.write() if found_something is False: raise LASIFNotFoundError( "No matching data found for event '%s', iteration '%s', and " "station '%s'." % (event["event_name"], iteration.name, station))
def test_select_windows(): """ Simple test against existing windows that are considered "good". """ data_trace = obspy.read(os.path.join(DATA, "LA.AA10..BHZ.mseed"))[0] synthetic_trace = obspy.read(os.path.join(DATA, "LA.AA10_.___.z.bz2"))[0] event_latitude = 44.87 event_longitude = 8.48 event_depth_in_km = 15.0 station_latitude = 41.3317000452 station_longitude = 2.00073761549 minimum_period = 40.0 maximum_period = 100 min_cc = 0.10 max_noise = 0.10 max_noise_window = 0.4 min_velocity = 2.4 threshold_shift = 0.30 threshold_correlation = 0.75 min_length_period = 1.5 min_peaks_troughs = 2 max_energy_ratio = 2.0 windows = select_windows( data_trace=data_trace, synthetic_trace=synthetic_trace, event_latitude=event_latitude, event_longitude=event_longitude, event_depth_in_km=event_depth_in_km, station_latitude=station_latitude, station_longitude=station_longitude, minimum_period=minimum_period, maximum_period=maximum_period, min_cc=min_cc, max_noise=max_noise, max_noise_window=max_noise_window, min_velocity=min_velocity, threshold_shift=threshold_shift, threshold_correlation=threshold_correlation, min_length_period=min_length_period, min_peaks_troughs=min_peaks_troughs, max_energy_ratio=max_energy_ratio) expected_windows = [(obspy.UTCDateTime(2000, 8, 21, 17, 15, 38), obspy.UTCDateTime(2000, 8, 21, 17, 19, 24, 800000))] assert windows == expected_windows
def lasif_plot_selected_windows(parser, args): """ Plot the selected windows. """ parser.add_argument("iteration_name", help="name of the iteration") parser.add_argument("event_name", help="name of the event") args = parser.parse_args(args) iteration_name = args.iteration_name event_name = args.event_name from lasif.window_selection import select_windows, plot_windows proj = _find_project_root(".") if event_name not in proj.events: msg = "Event '%s' not found in project." % event_name raise LASIFCommandLineException(msg) iterator = proj.data_synthetic_iterator(event_name, iteration_name) event_info = proj.events[event_name] iteration = proj._get_iteration(iteration_name) process_params = iteration.get_process_params() minimum_period = 1.0 / process_params["lowpass"] maximum_period = 1.0 / process_params["highpass"] output_folder = proj.get_output_folder( "Selected_Windows_Iteration_%s__%s" % (event_name, iteration_name)) for i in iterator: for component in ["Z", "N", "E"]: try: data = i["data"].select(component=component)[0] except IndexError: continue synthetics = i["synthetics"].select(component=component)[0] windows = select_windows( data, synthetics, event_info["latitude"], event_info["longitude"], event_info["depth_in_km"], i["coordinates"]["latitude"], i["coordinates"]["longitude"], minimum_period, maximum_period) plot_windows( data, synthetics, windows, maximum_period, filename=os.path.join(output_folder, "windows_%s.pdf" % data.id)) print "Done. Written output to folder %s." % output_folder
def window_picking_function(data_trace, synthetic_trace, event_latitude, event_longitude, event_depth_in_km, station_latitude, station_longitude, minimum_period, maximum_period, iteration, **kwargs): # NOQA """ Function that will be called every time a window is picked. This is part of the project so it can change depending on the project. Please keep in mind that you will have to manually update this file to a new version if LASIF is ever updated. You can do whatever you want in this function as long as the function signature is honored and the correct data types are returned. You could for example only tweak the window picking parameters but you could also implement your own window picking algorithm or call some other tool that picks windows. This function has to return a list of tuples of start and end times, each tuple denoting a selected window. :param data_trace: Trace containing the fully preprocessed data. :type data_trace: :class:`~obspy.core.trace.Trace` :param synthetic_trace: Trace containing the fully preprocessed synthetics. :type synthetic_trace: :class:`~obspy.core.trace.Trace` :param event_latitude: The event latitude. :type event_latitude: float :param event_longitude: The event longitude. :type event_longitude: float :param event_depth_in_km: The event depth in km. :type event_depth_in_km: float :param station_latitude: The station latitude. :type station_latitude: float :param station_longitude: The station longitude. :type station_longitude: float :param minimum_period: The minimum period of data and synthetics. :type minimum_period: float :param maximum_period: The maximum period of data and synthetics. :type maximum_period: float :param iteration: The iteration object. Use this to change behaviour based on the iteration. :type iteration: :class:`lasif.iteration-xml.Iteration` Please note that you also got the iteration object here, so if you want some parameters to change depending on the iteration, just use if/else on the iteration objects. >>> iteration.name # doctest: +SKIP '11' >>> iteration.get_process_params() # doctest: +SKIP {'dt': 0.75, 'highpass': 0.01, 'lowpass': 0.02, 'npts': 500} Use ``$ lasif shell`` to play around and figure out what the iteration objects can do. """ # Minimum normalised correlation coefficient of the complete traces. MIN_CC = 0.10 # Maximum relative noise level for the whole trace. Measured from # maximum amplitudes before and after the first arrival. MAX_NOISE = 0.10 # Maximum relative noise level for individual windows. MAX_NOISE_WINDOW = 0.4 # All arrivals later than those corresponding to the threshold velocity # [km/s] will be excluded. MIN_VELOCITY = 2.4 # Maximum allowable time shift within a window, as a fraction of the # minimum period. THRESHOLD_SHIFT = 0.30 # Minimum normalised correlation coefficient within a window. THRESHOLD_CORRELATION = 0.75 # Minimum length of the time windows relative to the minimum period. MIN_LENGTH_PERIOD = 1.5 # Minimum number of extrema in an individual time window (excluding the # edges). MIN_PEAKS_TROUGHS = 2 # Maximum energy ratio between data and synthetics within a time window. # Don't make this too small! MAX_ENERGY_RATIO = 10.0 windows = select_windows( data_trace=data_trace, synthetic_trace=synthetic_trace, event_latitude=event_latitude, event_longitude=event_longitude, event_depth_in_km=event_depth_in_km, station_latitude=station_latitude, station_longitude=station_longitude, minimum_period=minimum_period, maximum_period=maximum_period, # User adjustable parameters. min_cc=MIN_CC, max_noise=MAX_NOISE, max_noise_window=MAX_NOISE_WINDOW, min_velocity=MIN_VELOCITY, threshold_shift=THRESHOLD_SHIFT, threshold_correlation=THRESHOLD_CORRELATION, min_length_period=MIN_LENGTH_PERIOD, min_peaks_troughs=MIN_PEAKS_TROUGHS, max_energy_ratio=MAX_ENERGY_RATIO, **kwargs) return windows
def window_picking_function(data_trace, synthetic_trace, event_latitude, event_longitude, event_depth_in_km, station_latitude, station_longitude, minimum_period, maximum_period, iteration, **kwargs): # NOQA """ Function that will be called every time a window is picked. This is part of the project so it can change depending on the project. Please keep in mind that you will have to manually update this file to a new version if LASIF is ever updated. You can do whatever you want in this function as long as the function signature is honored and the correct data types are returned. You could for example only tweak the window picking parameters but you could also implement your own window picking algorithm or call some other tool that picks windows. This function has to return a list of tuples of start and end times, each tuple denoting a selected window. :param data_trace: Trace containing the fully preprocessed data. :type data_trace: :class:`~obspy.core.trace.Trace` :param synthetic_trace: Trace containing the fully preprocessed synthetics. :type synthetic_trace: :class:`~obspy.core.trace.Trace` :param event_latitude: The event latitude. :type event_latitude: float :param event_longitude: The event longitude. :type event_longitude: float :param event_depth_in_km: The event depth in km. :type event_depth_in_km: float :param station_latitude: The station latitude. :type station_latitude: float :param station_longitude: The station longitude. :type station_longitude: float :param minimum_period: The minimum period of data and synthetics. :type minimum_period: float :param maximum_period: The maximum period of data and synthetics. :type maximum_period: float :param iteration: The iteration object. Use this to change behaviour based on the iteration. :type iteration: :class:`lasif.iteration-xml.Iteration` Please note that you also got the iteration object here, so if you want some parameters to change depending on the iteration, just use if/else on the iteration objects. >>> iteration.name # doctest: +SKIP '11' >>> iteration.get_process_params() # doctest: +SKIP {'dt': 0.75, 'highpass': 0.01, 'lowpass': 0.02, 'npts': 500} Use ``$ lasif shell`` to play around and figure out what the iteration objects can do. """ # Minimum normalised correlation coefficient of the complete traces. MIN_CC = 0.10 # Maximum relative noise level for the whole trace. Measured from # maximum amplitudes before and after the first arrival. MAX_NOISE = 0.10 # Maximum relative noise level for individual windows. MAX_NOISE_WINDOW = 0.4 # All arrivals later than those corresponding to the threshold velocity # [km/s] will be excluded. MIN_VELOCITY = 2.4 # Maximum allowable time shift within a window, as a fraction of the # minimum period. THRESHOLD_SHIFT = 0.30 # Minimum normalised correlation coefficient within a window. THRESHOLD_CORRELATION = 0.75 # Minimum length of the time windows relative to the minimum period. MIN_LENGTH_PERIOD = 1.5 # Minimum number of extrema in an individual time window (excluding the # edges). MIN_PEAKS_TROUGHS = 2 # Maximum energy ratio between data and synthetics within a time window. # Don't make this too small! MAX_ENERGY_RATIO = 10.0 # The minimum similarity of the envelopes of both data and synthetics. This # essentially assures that the amplitudes of data and synthetics can not # diverge too much within a window. It is a bit like the inverse of the # ratio of both envelopes so a value of 0.2 makes sure neither amplitude # can be more then 5 times larger than the other. MIN_ENVELOPE_SIMILARITY = 0.2 windows = select_windows( data_trace=data_trace, synthetic_trace=synthetic_trace, event_latitude=event_latitude, event_longitude=event_longitude, event_depth_in_km=event_depth_in_km, station_latitude=station_latitude, station_longitude=station_longitude, minimum_period=minimum_period, maximum_period=maximum_period, # User adjustable parameters. min_cc=MIN_CC, max_noise=MAX_NOISE, max_noise_window=MAX_NOISE_WINDOW, min_velocity=MIN_VELOCITY, threshold_shift=THRESHOLD_SHIFT, threshold_correlation=THRESHOLD_CORRELATION, min_length_period=MIN_LENGTH_PERIOD, min_peaks_troughs=MIN_PEAKS_TROUGHS, max_energy_ratio=MAX_ENERGY_RATIO, min_envelope_similarity=MIN_ENVELOPE_SIMILARITY, **kwargs) return windows
def test_select_windows(cli): """ Simple test against existing windows that are considered "good". """ data_trace = obspy.read(os.path.join(DATA, "LA.AA10..BHZ.mseed"))[0] synthetic_trace = obspy.read(os.path.join(DATA, "LA.AA10_.___.z.mseed"))[0] event_latitude = 44.87 event_longitude = 8.48 event_depth_in_km = 15.0 station_latitude = 41.3317000452 station_longitude = 2.00073761549 minimum_period = 40.0 maximum_period = 100 min_cc = 0.10 max_noise = 0.10 max_noise_window = 0.4 min_velocity = 2.4 threshold_shift = 0.30 threshold_correlation = 0.75 min_length_period = 1.5 min_peaks_troughs = 2 max_energy_ratio = 2.0 stf_npts = len(data_trace) stf_delta = data_trace.stats.delta stf_freqmin = 1.0 / maximum_period stf_freqmax = 1.0 / minimum_period stf_fct = cli.comm.project.get_project_function("source_time_function") stf_trace = stf_fct( npts=stf_npts, delta=stf_delta, freqmin=stf_freqmin, freqmax=stf_freqmax, ) windows = select_windows( data_trace=data_trace, synthetic_trace=synthetic_trace, stf_trace=stf_trace, event_latitude=event_latitude, event_longitude=event_longitude, event_depth_in_km=event_depth_in_km, station_latitude=station_latitude, station_longitude=station_longitude, minimum_period=minimum_period, maximum_period=maximum_period, min_cc=min_cc, max_noise=max_noise, max_noise_window=max_noise_window, min_velocity=min_velocity, threshold_shift=threshold_shift, threshold_correlation=threshold_correlation, min_length_period=min_length_period, min_peaks_troughs=min_peaks_troughs, max_energy_ratio=max_energy_ratio, ) expected_windows = [ ( obspy.UTCDateTime(2000, 8, 21, 17, 15, 38, 300000), obspy.UTCDateTime(2000, 8, 21, 17, 19, 26, 300000), 1.0, ), ( obspy.UTCDateTime(2000, 8, 21, 17, 20, 21, 200000), obspy.UTCDateTime(2000, 8, 21, 17, 21, 44, 900000), 1.0, ), ] assert windows == expected_windows