def align_phases(stream, event, inventory, phase_name, method="simple"):
    """
    Aligns the waveforms with the theoretical travel times for some phase. The
    theoretical travel times are calculated with obspy.taup.

    :param stream: Waveforms for the array processing.
    :type stream: :class:`obspy.core.stream.Stream`
    :param event: The event for which to calculate phases.
    :type event: :class:`obspy.core.event.Event`
    :param inventory: Station metadata.
    :type inventory: :class:`obspy.station.inventory.Inventory`
    :param phase_name: The name of the phase you want to align. Must be
        contained in all traces. Otherwise the behaviour is undefined.
    :type phase_name: str
    :param method: Method is either `simple` or `fft`. Simple will just shift
     the starttime of Trace, while 'fft' will do the shift in the frequency
     domain. Defaults to `simple`.
    :type method: str
    """
    method = method.lower()
    if method not in ['simple', 'fft']:
        msg = "method must be 'simple' or 'fft'"
        raise ValueError(msg)

    stream = stream.copy()
    attach_coordinates_to_traces(stream, inventory, event)

    stream.traces = sorted(stream.traces, key=lambda x: x.stats.distance)[::-1]

    tr_1 = stream[-1]
    tt_1 = getTravelTimes(tr_1.stats.distance, event.origins[0].depth / 1000.0,
                          "ak135")

    cont = 0.
    for tt in tt_1:
        if tt["phase_name"] != phase_name:
            continue
        if tt["phase_name"] == phase_name:
            cont = 1.
        tt_1 = tt["time"]
        break

    if cont == 0:
        msg = "The selected phase is not present in your seismograms!!!"
        raise ValueError(msg)

    for tr in stream:
        tt = getTravelTimes(tr.stats.distance, event.origins[0].depth / 1000.0,
                            "ak135")
        for t in tt:
            if t["phase_name"] != phase_name:
                continue
            tt = t["time"]
            break
        if method == "simple":
            tr.stats.starttime -= (tt - tt_1)
        else:
            shifttrace_freq(Stream(traces=[tr]), [-((tt - tt_1))])
    return stream
def align_phases(stream, event, inventory, phase_name, method="simple"):
    """
    Aligns the waveforms with the theoretical travel times for some phase. The
    theoretical travel times are calculated with obspy.taup.

    :param stream: Waveforms for the array processing.
    :type stream: :class:`obspy.core.stream.Stream`
    :param event: The event for which to calculate phases.
    :type event: :class:`obspy.core.event.Event`
    :param inventory: Station metadata.
    :type inventory: :class:`obspy.station.inventory.Inventory`
    :param phase_name: The name of the phase you want to align. Must be
        contained in all traces. Otherwise the behaviour is undefined.
    :type phase_name: str
    :param method: Method is either `simple` or `fft`. Simple will just shift
     the starttime of Trace, while 'fft' will do the shift in the frequency
     domain. Defaults to `simple`.
    :type method: str
    """
    method = method.lower()
    if method not in ["simple", "fft"]:
        msg = "method must be 'simple' or 'fft'"
        raise ValueError(msg)

    stream = stream.copy()
    attach_coordinates_to_traces(stream, inventory, event)

    stream.traces = sorted(stream.traces, key=lambda x: x.stats.distance)[::-1]

    tr_1 = stream[-1]
    tt_1 = getTravelTimes(tr_1.stats.distance, event.origins[0].depth / 1000.0, "ak135")

    cont = 0.0
    for tt in tt_1:
        if tt["phase_name"] != phase_name:
            continue
        if tt["phase_name"] == phase_name:
            cont = 1.0
        tt_1 = tt["time"]
        break

    if cont == 0:
        msg = "The selected phase is not present in your seismograms!!!"
        raise ValueError(msg)

    for tr in stream:
        tt = getTravelTimes(tr.stats.distance, event.origins[0].depth / 1000.0, "ak135")
        for t in tt:
            if t["phase_name"] != phase_name:
                continue
            tt = t["time"]
            break
        if method == "simple":
            tr.stats.starttime -= tt - tt_1
        else:
            shifttrace_freq(Stream(traces=[tr]), [-((tt - tt_1))])
    return stream
示例#3
0
def calculate_time_phase(event, sta):
    """
    calculate arrival time of the requested phase to use in retrieving
    waveforms.
    :param event:
    :param sta:
    :return:
    """

    ev_lat = event['latitude']
    ev_lon = event['longitude']
    ev_dp = abs(float(event['depth']))
    sta_lat = float(sta[4])
    sta_lon = float(sta[5])
    delta = locations2degrees(ev_lat, ev_lon, sta_lat, sta_lon)
    tt = getTravelTimes(delta, ev_dp)
    phase_list = ['P', 'Pdiff', 'PKIKP']

    time_ph = 0
    flag = False
    for ph in phase_list:
        for i in range(len(tt)):
            if tt[i]['phase_name'] == ph:
                flag = True
                time_ph = tt[i]['time']
                break
            else:
                continue
        if flag:
            print 'Phase: %s' % ph
            break
    t_start = event['t1'] + time_ph
    t_end = event['t2'] + time_ph
    return t_start, t_end
示例#4
0
def calculate_time_phase(event, sta):
    """
    calculate arrival time of the requested phase to use in retrieving
    waveforms.
    :param event:
    :param sta:
    :return:
    """

    ev_lat = event['latitude']
    ev_lon = event['longitude']
    ev_dp = abs(float(event['depth']))
    sta_lat = float(sta[4])
    sta_lon = float(sta[5])
    delta = locations2degrees(ev_lat, ev_lon, sta_lat, sta_lon)
    tt = getTravelTimes(delta, ev_dp)
    phase_list = ['P', 'Pdiff', 'PKIKP']

    time_ph = 0
    flag = False
    for ph in phase_list:
        for i in range(len(tt)):
            if tt[i]['phase_name'] == ph:
                flag = True
                time_ph = tt[i]['time']
                break
            else:
                continue
        if flag:
            print 'Phase: %s' % ph
            break
    t_start = event['t1'] + time_ph
    t_end = event['t2'] + time_ph
    return t_start, t_end
示例#5
0
def calculate_time_phase(event, sta, bg_model='iasp91'):
    """
    calculate arrival time of the requested phase
    :param event:
    :param sta:
    :param bg_model:
    :return:
    """
    phase_list = ['P', 'Pdiff', 'PKIKP']

    time_ph = 0
    ev_lat = event['latitude']
    ev_lon = event['longitude']
    evdp = abs(float(event['depth']))
    sta_lat = float(sta[4])
    sta_lon = float(sta[5])
    dist = locations2degrees(ev_lat, ev_lon, sta_lat, sta_lon)

    try:
        from obspy.taup import tau
        tau_bg = tau.TauPyModel(model=bg_model)
    except:
        tau_bg = False

    if not tau_bg:
        try:
            tt = getTravelTimes(dist, evdp)
            flag = False
            for ph in phase_list:
                for i in range(len(tt)):
                    if tt[i]['phase_name'] == ph:
                        flag = True
                        time_ph = tt[i]['time']
                        break
                    else:
                        continue
            if not flag:
                time_ph = 0
        except:
            time_ph = 0
    else:
        try:
            for ph in phase_list:
                tt = tau_bg.get_travel_times(evdp, dist,
                                             phase_list=[ph])[0].time
                if not tt:
                    time_ph = 0
                    continue
                else:
                    time_ph = tt
                    break
        except:
            time_ph = 0

    t_start = event['t1'] + time_ph
    t_end = event['t2'] + time_ph
    return t_start, t_end
示例#6
0
 def calculate_ttimes(self):
     """
     Calculate theoretical travel times. Only call if station and event
     information is available!
     """
     dist_in_deg = geodetics.locations2degrees(
         self.station.latitude, self.station.longitude,
         self.event.latitude, self.event.longitude)
     tts = getTravelTimes(dist_in_deg, self.event.depth_in_m / 1000.0,
                          model=self.config.earth_model)
     self.ttimes = sorted(tts, key=lambda x: x["time"])
     logger.info("Calculated travel times.")
示例#7
0
 def calculate_ttimes(self):
     """
     Calculate theoretical travel times. Only call if station and event
     information is available!
     """
     dist_in_deg = geodetics.locations2degrees(self.station.latitude,
                                               self.station.longitude,
                                               self.event.latitude,
                                               self.event.longitude)
     tts = getTravelTimes(dist_in_deg,
                          self.event.depth_in_m / 1000.0,
                          model=self.config.earth_model)
     self.ttimes = sorted(tts, key=lambda x: x["time"])
     logger.info("Calculated travel times.")
示例#8
0
def travel_time_calc(evla, evlo, stla, stlo, evdp, bg_model):
    """
    calculate arrival time of different seismic phases
    :param evla:
    :param evlo:
    :param stla:
    :param stlo:
    :param evdp:
    :param bg_model:
    :return:
    """
    # --------------- TAUP
    dist = locations2degrees(evla, evlo, stla, stlo)
    try:
        tt = [_i for _i in getTravelTimes(dist, evdp, bg_model)
              if 'Pdiff' == _i['phase_name']][0]['time']
    except Exception, e:
        tt = False
示例#9
0
def travel_time_calc(evla, evlo, stla, stlo, evdp, bg_model):
    """
    calculate arrival time of different seismic phases
    :param evla:
    :param evlo:
    :param stla:
    :param stlo:
    :param evdp:
    :param bg_model:
    :return:
    """
    # --------------- TAUP
    dist = locations2degrees(evla, evlo, stla, stlo)
    try:
        tt = [
            _i for _i in getTravelTimes(dist, evdp, bg_model)
            if 'Pdiff' == _i['phase_name']
        ][0]['time']
    except Exception, e:
        tt = False
示例#10
0
import numpy as np
from obspy import taup

seismic_phase = ['P', 'Pdiff']
min_degree = 90.
max_degree = 180.
step_degree = 1.
evdepth = 0.

dist_pdiff = []
dist_all = []
take_off = []

for dist in np.arange(min_degree, max_degree, step_degree):
    flag = False
    tt = taup.getTravelTimes(delta=dist, depth=evdepth)
    for i in range(len(tt)):
        if tt[i]['phase_name'] in seismic_phase:
            flag = True
            take_off_tmp = tt[i]['take-off angle']
            time_tmp = tt[i]['time']
            if tt[i]['phase_name'] == 'Pdiff':
                dist_pdiff.append(dist)
            break
    if flag:
        take_off.append(take_off_tmp)
        dist_all.append(dist)

plt.plot(dist_all, take_off, lw=3)
plt.xlabel('Distance (deg)', size='large', weight='bold')
plt.ylabel('Take-off angle', size='large', weight='bold')
示例#11
0
def select_windows(data_trace, synthetic_trace, ev_lat, ev_lng, ev_depth_in_km,
                   st_lat, st_lng, minimum_period, maximum_period):
    """
    Window selection algorithm for picking windows suitable for misfit
    calculation based on phase differences.

    :param data_trace:
    :param synthetic_trace:
    :param ev_lat:
    :param ev_lng:
    :param ev_depth_in_km:
    :param st_lat:
    :param st_lng:
    :param minimum_period:
    :param maximum_period:
    """

    print "* ---------------------------"
    print "* autoselect " + data_trace.stats.channel

    # =========================================================================
    # set a couple of selection parameters - might become part of the input in
    # future versions
    # =========================================================================

    # Minimum normalised correlation coefficient of the complete traces.
    min_cc = 0.0
    # Maximum relative noise level for the whole trace. Measured from maximum
    # amplitudes before and after the first arrival.
    max_noise = 0.3
    # 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.
    threshold_velocity = 2.4
    # Maximum allowable time shift within a window, as a fraction of the
    # minimum period.
    threshold_shift = 0.2
    # Minimum normalised correlation coeficient within a window.
    threshold_correlation = 0.5
    # Minimum length of the time windows relative to the minimum period.
    min_length_period = 1.5
    # Minimum number of extreme in an individual time window (excluding the
    # edges).
    min_peaks_troughs = 2
    # Maximum energy ratio between data and synthetics within a time window.
    max_energy_ratio = 3.0

    # =========================================================================
    # initialisations
    # =========================================================================

    dt = synthetic_trace.stats.delta
    npts = synthetic_trace.stats.npts
    dist_in_deg = geodetics.locations2degrees(st_lat, st_lng, ev_lat, ev_lng)
    dist_in_km = geodetics.calcVincentyInverse(
        st_lat, st_lng, ev_lat, ev_lng)[0] / 1000.0
    tts = getTravelTimes(dist_in_deg, ev_depth_in_km, model="ak135")
    first_tt_arrival = min([_i["time"] for _i in tts])

    # Number of samples in the sliding window. Currently, the length of the
    # window is set to a multiple of the dominant period of the synthetics.
    # Make sure it is an uneven number; just to have an easy midpoint
    # definition.
    window_length = int(round(float(2 * minimum_period) / dt))

    if not window_length % 2:
        window_length += 1

    # Allocate arrays to collect the time dependent values.
    sliding_time_shift = np.zeros(npts, dtype="float32")
    max_cc_coeff = np.zeros(npts, dtype="float32")

    taper = np.hanning(window_length)

    # =========================================================================
    # check if whole seismograms are sufficiently correlated and estimate noise
    # level
    # =========================================================================

    synth = synthetic_trace.data
    data = data_trace.data

    #  compute correlation coefficient
    norm = np.sqrt(np.sum(data ** 2)) * np.sqrt(np.sum(synth ** 2))
    cc = np.sum(data * synth) / norm
    print "** correlation coefficient: " + str(cc)

    #  estimate noise level from waveforms prior to the first arrival
    idx = int(np.ceil((first_tt_arrival - minimum_period * 0.5) / dt))
    noise_absolute = data[50:idx].ptp()
    noise_relative = noise_absolute / data.ptp()
    print "** absolute noise level: " + str(noise_absolute) + " m/s"
    print "** relative noise level: " + str(noise_relative)

    #  rejection criteria
    accept = True
    if cc < min_cc:
        print "** no windows selected, correlation " + str(cc) + \
            " is below threshold value of " + str(min_cc)
        accept = False
    if noise_relative > max_noise:
        print "** no windows selected, noise level " + str(noise_relative) + \
            " is above threshold value of " + str(max_noise)
        accept = False

    if accept is False:
        print "* autoselect done"
        return []

    # =========================================================================
    # compute sliding time shifts and correlation coefficients
    # =========================================================================

    for start_idx, end_idx, midpoint_idx in _window_generator(npts,
                                                              window_length):

        # Slice windows. Create a copy to be able to taper without affecting
        # the original time series.
        data_window = data_trace.data[start_idx: end_idx].copy() * taper
        synthetic_window = \
            synthetic_trace.data[start_idx: end_idx].copy() * taper

        # Skip windows that have essentially no energy to avoid instabilities.
        if synthetic_window.ptp() < synthetic_trace.data.ptp() * 0.001:
            continue

        # Calculate the time shift. Here this is defined as the shift of the
        # synthetics relative to the data. So a value of 2, for instance, means
        # that the synthetics are 2 timesteps later then the data.
        cc = np.correlate(data_window, synthetic_window, mode="full")

        time_shift = cc.argmax() - window_length + 1
        # Express the time shift in fraction of the minimum period.
        sliding_time_shift[midpoint_idx] = (time_shift * dt) / minimum_period

        # Normalized cross correlation.
        max_cc_value = cc.max() / np.sqrt((synthetic_window ** 2).sum() *
                                          (data_window ** 2).sum())
        max_cc_coeff[midpoint_idx] = max_cc_value

    # =========================================================================
    # compute the initial mask, i.e. intervals (windows) where no measurements
    # are made.
    # =========================================================================

    # Step 1: Initialise masked arrays. The mask will be set to True where no
    # windows are chosen.
    time_windows = np.ma.ones(npts)
    time_windows.mask = np.zeros(npts)

    # Step 2: Mark everything more then half a dominant period before the first
    # theoretical arrival as positive.
    time_windows.mask[:int(np.ceil(
                      (first_tt_arrival - minimum_period * 0.5) / dt))] = True

    # Step 3: Mark everything more then half a dominant period after the
    # threshold arrival time - computed from the threshold velocity - as
    # negative.
    time_windows.mask[int(np.floor(dist_in_km / threshold_velocity / dt)):] = \
        True

    # Step 4: Mark everything with an absolute travel time shift of more than
    # threshold_shift times the dominant period as negative
    time_windows.mask[np.abs(sliding_time_shift) > threshold_shift] = True

    # Step 5: Mark the area around every "travel time shift jump" (based on
    # the traveltime time difference) negative. The width of the area is
    # currently chosen to be a tenth of a dominant period to each side.
    sample_buffer = int(np.ceil(minimum_period / dt * 0.1))
    indices = np.ma.where(np.abs(np.diff(sliding_time_shift)) > 0.1)[0]
    for index in indices:
        time_windows.mask[index - sample_buffer: index + sample_buffer] = True

    # Step 6: Mark all areas where the normalized cross correlation coefficient
    # is under threshold_correlation as negative
    time_windows.mask[max_cc_coeff < threshold_correlation] = True

    # =========================================================================
    #  Make the final window selection.
    # =========================================================================

    min_length = min(
        minimum_period / dt * min_length_period, maximum_period / dt)
    final_windows = []

    #  loop through all the time windows
    for i in np.ma.flatnotmasked_contiguous(time_windows):

        window_npts = i.stop - i.start
        synthetic_window = synthetic_trace.data[i.start: i.stop]
        data_window = data_trace.data[i.start: i.stop]

        # Step 7: Throw away all windows with a length of less then
        # min_length_period the dominant period.
        if (i.stop - i.start) < min_length:
            continue

        # Step 8: Exclude windows without a real peak or trough (except for the
        # edges).
        data_p, data_t, data_extrema = find_local_extrema(data_window, 0)
        synth_p, synth_t, synth_extrema = find_local_extrema(synthetic_window,
                                                             0)
        if np.min([len(synth_p), len(synth_t), len(data_p), len(data_t)]) < \
                min_peaks_troughs:
            continue

        # Step 9: Peak and trough matching algorithm
        window_mask = np.ones(window_npts, dtype="bool")

        closest_peaks = find_closest(data_p, synth_p)
        diffs = np.diff(closest_peaks)

        for idx in np.where(diffs == 1)[0]:
            if idx > 0:
                start = synth_p[idx - 1]
            else:
                start = 0
            if idx < (len(synth_p) - 1):
                end = synth_p[idx + 1]
            else:
                end = -1
            window_mask[start: end] = False

        closest_troughs = find_closest(data_t, synth_t)
        diffs = np.diff(closest_troughs)

        for idx in np.where(diffs == 1)[0]:
            if idx > 0:
                start = synth_t[idx - 1]
            else:
                start = 0
            if idx < (len(synth_t) - 1):
                end = synth_t[idx + 1]
            else:
                end = -1
            window_mask[start: end] = False

        window_mask = np.ma.masked_array(window_mask, mask=window_mask)
        if window_mask.mask.all():
            continue

        # Step 10: Check if the time windows have sufficiently similar energy
        # and are above the noise
        for j in np.ma.flatnotmasked_contiguous(window_mask):

            # Again assert a certain minimal length.
            if (j.stop - j.start) < min_length:
                continue

            # Compare the energy in the data window and the synthetic window.
            data_energy = (data_window[j.start: j.stop] ** 2).sum()
            synth_energy = (synthetic_window[j.start: j.stop] ** 2).sum()
            energies = sorted([data_energy, synth_energy])
            if energies[1] > max_energy_ratio * energies[0]:
                continue

            # Check that amplitudes in the data are above the noise
            if noise_absolute / data_window[j.start: j.stop].ptp() > \
                    max_noise_window:
                continue

            final_windows.append((i.start + j.start, i.start + j.stop))

    print "* autoselect done"

    return final_windows
示例#12
0
def vespagram(stream, ev, inv, method, frqlow, frqhigh, baz, scale, nthroot=4,
              filter=True, static3D=False, vel_corr=4.8, sl=(0.0, 10.0, 0.5),
              align=False, align_phase=['P', 'Pdiff'], plot_trace=True):
    """
    vespagram wrapper routine for MESS 2014.

    :param stream: Waveforms for the array processing.
    :type stream: :class:`obspy.core.stream.Stream`
    :param inventory: Station metadata for waveforms
    :type inventory: :class:`obspy.station.inventory.Inventory`
    :param method: Method used for the array analysis
        (one of "DLS": Delay and Sum, "PWS": Phase Weighted Stack).
    :type method: str
    :param frqlow: Low corner of frequency range for array analysis
    :type frqlow: float
    :param frqhigh: High corner of frequency range for array analysis
    :type frqhigh: float
    :param baz: pre-defined (theoretical or calculated) backazimuth used for calculation
    :type baz_plot: float
    :param scale: scale for plotting
    :type scale: float
    :param nthroot: estimating the nthroot for calculation of the beam
    :type nthroot: int
    :param filter: Whether to bandpass data to selected frequency range
    :type filter: bool
    :param static3D: static correction of topography using `vel_corr` as
        velocity (slow!)
    :type static3D: bool
    :param vel_corr: Correction velocity for static topography correction in
        km/s.
    :type vel_corr: float
    :param sl: Min/Max and stepwidthslowness for analysis
    :type sl: (float, float,float)
    :param align: whether to align the vespagram to a certain phase
    :type align: bool
    :param align_phase: phase to be aligned with (might be a list if simulateneous arivials are expected (P,PcP,Pdif)
    :type align: str
    :param plot_trace: if True plot the vespagram as wiggle plot, if False as density map
    :type align: bool
    """

    starttime = max([tr.stats.starttime for tr in stream])
    endtime = min([tr.stats.endtime for tr in stream])
    stream.trim(starttime, endtime)

    org = ev.preferred_origin() or ev.origins[0]
    ev_lat = org.latitude
    ev_lon = org.longitude
    ev_depth = org.depth/1000.  # in km
    ev_otime = org.time

    sll, slm, sls = sl
    sll /= KM_PER_DEG
    slm /= KM_PER_DEG
    sls /= KM_PER_DEG
    center_lon = 0.
    center_lat = 0.
    center_elv = 0.
    seismo = stream
    seismo.attach_response(inv)
    seismo.merge()
    sz = Stream()
    i = 0
    for tr in seismo:
        for station in inv[0].stations:
            if tr.stats.station == station.code:
                tr.stats.coordinates = \
                    AttribDict({'latitude': station.latitude,
                                'longitude': station.longitude,
                                'elevation': station.elevation})
                center_lon += station.longitude
                center_lat += station.latitude
                center_elv += station.elevation
                i += 1
        sz.append(tr)

    center_lon /= float(i)
    center_lat /= float(i)
    center_elv /= float(i)

    starttime = max([tr.stats.starttime for tr in stream])
    stt = starttime
    endtime = min([tr.stats.endtime for tr in stream])
    e = endtime
    stream.trim(starttime, endtime)

    #nut = 0
    max_amp = 0.
    sz.trim(stt, e)
    sz.detrend('simple')

    print sz
    fl, fh = frqlow, frqhigh
    if filter:
        sz.filter('bandpass', freqmin=fl, freqmax=fh, zerophase=True)

    if align:
        deg = []
        shift = []
        res = gps2DistAzimuth(center_lat, center_lon, ev_lat, ev_lon)
        deg.append(kilometer2degrees(res[0]/1000.))
        tt = getTravelTimes(deg[0], ev_depth, model='ak135')
        for item in tt:
            phase = item['phase_name']
            if phase in align_phase:
                try:
                    travel = item['time']
                    travel = ev_otime.timestamp + travel
                    dtime = travel - stt.timestamp
                    shift.append(dtime)
                except:
                    break
        for i, tr in enumerate(sz):
            res = gps2DistAzimuth(tr.stats.coordinates['latitude'],
                                  tr.stats.coordinates['longitude'],
                                  ev_lat, ev_lon)
            deg.append(kilometer2degrees(res[0]/1000.))
            tt = getTravelTimes(deg[i+1], ev_depth, model='ak135')
            for item in tt:
                phase = item['phase_name']
                if phase in align_phase:
                    try:
                        travel = item['time']
                        travel = ev_otime.timestamp + travel
                        dtime = travel - stt.timestamp
                        shift.append(dtime)
                    except:
                        break
        shift = np.asarray(shift)
        shift -= shift[0]
        AA.shifttrace_freq(sz, -shift)

    baz += 180.
    nbeam = int((slm - sll)/sls + 0.5) + 1
    kwargs = dict(
        # slowness grid: X min, X max, Y min, Y max, Slow Step
        sll=sll, slm=slm, sls=sls, baz=baz, stime=stt, method=method,
        nthroot=nthroot, etime=e, correct_3dplane=False, static_3D=static3D,
        vel_cor=vel_corr)

    start = UTCDateTime()
    slow, beams, max_beam, beam_max = AA.vespagram_baz(sz, **kwargs)
    print "Total time in routine: %f\n" % (UTCDateTime() - start)

    df = sz[0].stats.sampling_rate
    # Plot the seismograms
    npts = len(beams[0])
    print npts
    T = np.arange(0, npts/df, 1/df)
    sll *= KM_PER_DEG
    slm *= KM_PER_DEG
    sls *= KM_PER_DEG
    slow = np.arange(sll, slm, sls)
    max_amp = np.max(beams[:, :])
    #min_amp = np.min(beams[:, :])
    scale *= sls

    fig = plt.figure(figsize=(12, 8))

    if plot_trace:
        ax1 = fig.add_axes([0.1, 0.1, 0.85, 0.85])
        for i in xrange(nbeam):
            if i == max_beam:
                ax1.plot(T, sll + scale*beams[i]/max_amp + i*sls, 'r',
                         zorder=1)
            else:
                ax1.plot(T, sll + scale*beams[i]/max_amp + i*sls, 'k',
                         zorder=-1)
        ax1.set_xlabel('Time [s]')
        ax1.set_ylabel('slowness [s/deg]')
        ax1.set_xlim(T[0], T[-1])
        data_minmax = ax1.yaxis.get_data_interval()
        minmax = [min(slow[0], data_minmax[0]), max(slow[-1], data_minmax[1])]
        ax1.set_ylim(*minmax)
    #####
    else:
        #step = (max_amp - min_amp)/100.
        #level = np.arange(min_amp, max_amp, step)
        #beams = beams.transpose()
        #cmap = cm.hot_r
        cmap = cm.rainbow

        ax1 = fig.add_axes([0.1, 0.1, 0.85, 0.85])
        #ax1.contour(slow,T,beams,level)
        #extent = (slow[0], slow[-1], \
        #               T[0], T[-1])
        extent = (T[0], T[-1], slow[0] - sls * 0.5, slow[-1] + sls * 0.5)

        ax1.set_ylabel('slowness [s/deg]')
        ax1.set_xlabel('T [s]')
        beams = np.flipud(beams)
        ax1.imshow(beams, cmap=cmap, interpolation="nearest",
                   extent=extent, aspect='auto')

    ####
    result = "BAZ: %.2f Time %s" % (baz-180., stt)
    ax1.set_title(result)

    plt.show()
    return slow, beams, max_beam, beam_max
示例#13
0
def show_distance_plot(stream, event, inventory, starttime, endtime,
                       plot_travel_times=True):
    """
    Plots distance dependent seismogramm sections.

    :param stream: The waveforms.
    :type stream: :class:`obspy.core.stream.Stream`
    :param event: The event.
    :type event: :class:`obspy.core.event.Event`
    :param inventory: The station information.
    :type inventory: :class:`obspy.station.inventory.Inventory`
    :param starttime: starttime of traces to be plotted
    :type starttime: UTCDateTime
    :param endttime: endttime of traces to be plotted
    :type endttime: UTCDateTime
    :param plot_travel_times: flag whether phases are marked as traveltime plots
     in the section obspy.taup is used to calculate the phases
    :type pot_travel_times: bool
    """
    stream = stream.slice(starttime=starttime, endtime=endtime).copy()
    event_depth_in_km = event.origins[0].depth / 1000.0
    event_time = event.origins[0].time

    attach_coordinates_to_traces(stream, inventory, event=event)

    cm = plt.cm.jet

    stream.traces = sorted(stream.traces, key=lambda x: x.stats.distance)[::-1]

    # One color for each trace.
    colors = [cm(_i) for _i in np.linspace(0, 1, len(stream))]

    # Relative event times.
    times_array = stream[0].times() + (stream[0].stats.starttime - event_time)

    distances = [tr.stats.distance for tr in stream]
    min_distance = min(distances)
    max_distance = max(distances)
    distance_range = max_distance - min_distance
    stream_range = distance_range / 10.0

    # Normalize data and "shift to distance".
    stream.normalize()
    for tr in stream:
        tr.data *= stream_range
        tr.data += tr.stats.distance

    plt.figure(figsize=(18, 10))
    for _i, tr in enumerate(stream):
        plt.plot(times_array, tr.data, label="%s.%s" % (tr.stats.network,
                 tr.stats.station), color=colors[_i])
    plt.grid()
    plt.ylabel("Distance in degree to event")
    plt.xlabel("Time in seconds since event")
    plt.legend()

    dist_min, dist_max = plt.ylim()

    if plot_travel_times:

        distances = defaultdict(list)
        ttimes = defaultdict(list)

        for i in np.linspace(dist_min, dist_max, 1000):
            tts = getTravelTimes(i, event_depth_in_km, "ak135")
            for phase in tts:
                name = phase["phase_name"]
                distances[name].append(i)
                ttimes[name].append(phase["time"])

        for key in distances.iterkeys():
            min_distance = min(distances[key])
            max_distance = max(distances[key])
            min_tt_time = min(ttimes[key])
            max_tt_time = max(ttimes[key])

            if min_tt_time >= times_array[-1] or \
                    max_tt_time <= times_array[0] or \
                    (max_distance - min_distance) < 0.8 * (dist_max - dist_min):
                continue
            ttime = ttimes[key]
            dist = distances[key]
            if max(ttime) > times_array[0] + 0.9 * times_array.ptp():
                continue
            plt.scatter(ttime, dist, s=0.5, zorder=-10, color="black", alpha=0.8)
            plt.text(max(ttime) + 0.005 * times_array.ptp(),
                     dist_max - 0.02 * (dist_max - dist_min),
                     key)

    plt.ylim(dist_min, dist_max)
    plt.xlim(times_array[0], times_array[-1])

    plt.title(event.short_str())

    plt.show()
示例#14
0
import numpy as np
from obspy import taup

seismic_phase = ['P', 'Pdiff']
min_degree = 90.
max_degree = 180.
step_degree = 1.
evdepth = 0.

dist_pdiff = []
dist_all = []
take_off = []

for dist in np.arange(min_degree, max_degree, step_degree):
    flag = False
    tt = taup.getTravelTimes(delta=dist, depth=evdepth)
    for i in range(len(tt)):
        if tt[i]['phase_name'] in seismic_phase:
            flag = True
            take_off_tmp = tt[i]['take-off angle']
            time_tmp = tt[i]['time']
            if tt[i]['phase_name'] == 'Pdiff':
                dist_pdiff.append(dist)
            break
    if flag: 
        take_off.append(take_off_tmp)
        dist_all.append(dist)

plt.plot(dist_all, take_off, lw=3)
plt.xlabel('Distance (deg)', size='large', weight='bold')
plt.ylabel('Take-off angle', size='large', weight='bold')
def show_distance_plot(stream,
                       event,
                       inventory,
                       starttime,
                       endtime,
                       plot_travel_times=True):
    """
    Plots distance dependent seismogramm sections.

    :param stream: The waveforms.
    :type stream: :class:`obspy.core.stream.Stream`
    :param event: The event.
    :type event: :class:`obspy.core.event.Event`
    :param inventory: The station information.
    :type inventory: :class:`obspy.station.inventory.Inventory`
    :param starttime: starttime of traces to be plotted
    :type starttime: UTCDateTime
    :param endttime: endttime of traces to be plotted
    :type endttime: UTCDateTime
    :param plot_travel_times: flag whether phases are marked as traveltime plots
     in the section obspy.taup is used to calculate the phases
    :type pot_travel_times: bool
    """
    stream = stream.slice(starttime=starttime, endtime=endtime).copy()
    event_depth_in_km = event.origins[0].depth / 1000.0
    event_time = event.origins[0].time

    attach_coordinates_to_traces(stream, inventory, event=event)

    cm = plt.cm.jet

    stream.traces = sorted(stream.traces, key=lambda x: x.stats.distance)[::-1]

    # One color for each trace.
    colors = [cm(_i) for _i in np.linspace(0, 1, len(stream))]

    # Relative event times.
    times_array = stream[0].times() + (stream[0].stats.starttime - event_time)

    distances = [tr.stats.distance for tr in stream]
    min_distance = min(distances)
    max_distance = max(distances)
    distance_range = max_distance - min_distance
    stream_range = distance_range / 10.0

    # Normalize data and "shift to distance".
    stream.normalize()
    for tr in stream:
        tr.data *= stream_range
        tr.data += tr.stats.distance

    plt.figure(figsize=(18, 10))
    for _i, tr in enumerate(stream):
        plt.plot(times_array,
                 tr.data,
                 label="%s.%s" % (tr.stats.network, tr.stats.station),
                 color=colors[_i])
    plt.grid()
    plt.ylabel("Distance in degree to event")
    plt.xlabel("Time in seconds since event")
    plt.legend()

    dist_min, dist_max = plt.ylim()

    if plot_travel_times:

        distances = defaultdict(list)
        ttimes = defaultdict(list)

        for i in np.linspace(dist_min, dist_max, 1000):
            tts = getTravelTimes(i, event_depth_in_km, "ak135")
            for phase in tts:
                name = phase["phase_name"]
                distances[name].append(i)
                ttimes[name].append(phase["time"])

        for key in distances.iterkeys():
            min_distance = min(distances[key])
            max_distance = max(distances[key])
            min_tt_time = min(ttimes[key])
            max_tt_time = max(ttimes[key])

            if min_tt_time >= times_array[-1] or \
                    max_tt_time <= times_array[0] or \
                    (max_distance - min_distance) < 0.8 * (dist_max - dist_min):
                continue
            ttime = ttimes[key]
            dist = distances[key]
            if max(ttime) > times_array[0] + 0.9 * times_array.ptp():
                continue
            plt.scatter(ttime,
                        dist,
                        s=0.5,
                        zorder=-10,
                        color="black",
                        alpha=0.8)
            plt.text(
                max(ttime) + 0.005 * times_array.ptp(),
                dist_max - 0.02 * (dist_max - dist_min), key)

    plt.ylim(dist_min, dist_max)
    plt.xlim(times_array[0], times_array[-1])

    plt.title(event.short_str())

    plt.show()