Пример #1
0
def make_lookup(phase_families, h5f, st, evdp, int_3d):
    cdp = np.arange(50, 1010, 20)
    mod = TauPyModel('prem')
    for idx, tr in enumerate(st):
        name = tr.stats.network + tr.stats.station + tr.stats.location
        print name, round(float(idx) / len(f.keys()) * 100., 2), '%'
        h5f.create_group(name)
        for keys in phase_families:
            h5f[name].create_group(keys)
            arr = mod.get_ray_paths_geo(
                source_depth_in_km=evdp,
                source_latitude_in_deg=tr.stats.evla,
                source_longitude_in_deg=tr.stats.evlo,
                receiver_latitude_in_deg=tr.stats.stla,
                receiver_longitude_in_deg=tr.stats.stlo,
                phase_list=[keys])
            h5f[name][keys].create_dataset('1d_time', data=[arr[0].time])
            main_path = np.array(
                [list((i[3], -i[4], i[5])) for i in arr[0].path])
            main_trace = 1 - (int_3d(main_path)[1::] * 0.01)
            main_dt = np.diff(np.array([i[1] for i in arr[0].path]))
            time_3d = np.sum(main_dt * main_trace)
            h5f[name][keys].create_dataset('3d_time', data=[time_3d])

            for phase in phase_families[keys]:

                h5f[name][keys].create_group(phase)
                master_time = []
                master_time_3d = []
                master_depth = []

                if phase.startswith('s'):
                    for ii in cdp:
                        time_list, time_list_3d, depth_list = top_depth_times(
                            evdp, ii, phase, tr, int_3d)
                        master_time.append(time_list)
                        master_time_3d.append(time_list_3d)
                        master_depth.append(depth_list)

                elif phase.startswith('S'):
                    for ii in cdp:
                        time_list, time_list_3d, depth_list = bot_depth_times(
                            evdp, ii, phase, tr, int_3d)
                        master_time.append(time_list)
                        master_time_3d.append(time_list_3d)
                        master_depth.append(depth_list)

                master_time = np.array(master_time)
                master_time = np.vstack((0, master_time))
                master_time_3d = np.array(master_time_3d)
                master_time_3d = np.vstack((0, master_time_3d))
                master_depth = np.array(master_depth)
                master_depth = np.vstack((0, master_depth))

                h5f[name][keys][phase].create_dataset('1d_time',
                                                      data=master_time)
                h5f[name][keys][phase].create_dataset('3d_time',
                                                      data=master_time_3d)
                h5f[name][keys][phase].create_dataset('depth',
                                                      data=master_depth)
Пример #2
0
def top_depth_times(evdp,cdp,phase_list_in,stla,stlo,evla,evlo,int_3d):
    mod = TauPyModel(model='prem'+str(int(cdp)))
    phase_list = phase_list_in
    phase_list = phase_list.replace('X',str(cdp))
    depth_list = []
    time_list = []
    time_list_3d = []

    arr = mod.get_ray_paths_geo(source_depth_in_km=evdp,
                                source_latitude_in_deg=evla,
                                source_longitude_in_deg=evlo,
                                receiver_latitude_in_deg=stla,
                                receiver_longitude_in_deg=stlo,
                                phase_list=[phase_list])

    pure_depth = float(re.findall('\d+',arr[0].purist_name)[0])
    depth_list.append(pure_depth)
    time = arr[0].time
    time_list.append(time)
    rev_path = np.array([list((i[3],-i[4],i[5])) for i in arr[0].path])
    rev_trace = 1-(int_3d(rev_path)[1::]*0.01)
    rev_dt = np.diff(np.array([i[1] for i in arr[0].path]))
    time_list_3d.append(np.sum(rev_dt*rev_trace))

    return time_list,time_list_3d,depth_list
Пример #3
0
    def test_single_path_geo_iasp91(self):
        """
        Test the raypath for a single phase given geographical input.

        This tests the case when geographiclib is installed.
        """
        filename = os.path.join(DATA,
                                "taup_path_-mod_iasp91_-o_stdout_-h_10_" +
                                "-ph_P_-sta_-45_-60_evt_-80_-60")
        expected = np.genfromtxt(filename, comments='>')

        m = TauPyModel(model="iasp91")
        arrivals = m.get_ray_paths_geo(source_depth_in_km=10.0,
                                       source_latitude_in_deg=-80.0,
                                       source_longitude_in_deg=-60.0,
                                       receiver_latitude_in_deg=-45.0,
                                       receiver_longitude_in_deg=-60.0,
                                       phase_list=["P"])
        self.assertEqual(len(arrivals), 1)

        # Interpolate both paths to 100 samples and make sure they are
        # approximately equal.
        sample_points = np.linspace(0, 35, 100)

        interpolated_expected_depth = np.interp(
            sample_points,
            expected[:, 0],
            expected[:, 1])
        interpolated_expected_lat = np.interp(
            sample_points,
            expected[:, 0],
            expected[:, 2])
        interpolated_expected_lon = np.interp(
            sample_points,
            expected[:, 0],
            expected[:, 3])

        interpolated_actual_depth = np.interp(
            sample_points,
            np.round(np.degrees(arrivals[0].path['dist']), 2),
            np.round(6371 - arrivals[0].path['depth'], 2))
        interpolated_actual_lat = np.interp(
            sample_points,
            np.round(np.degrees(arrivals[0].path['dist']), 2),
            np.round(arrivals[0].path['lat'], 2))
        interpolated_actual_lon = np.interp(
            sample_points,
            np.round(np.degrees(arrivals[0].path['dist']), 2),
            np.round(arrivals[0].path['lon'], 2))

        np.testing.assert_allclose(interpolated_actual_depth,
                                   interpolated_expected_depth,
                                   rtol=1E-4, atol=0)
        np.testing.assert_allclose(interpolated_actual_lat,
                                   interpolated_expected_lat,
                                   rtol=1E-4, atol=0)
        np.testing.assert_allclose(interpolated_actual_lon,
                                   interpolated_expected_lon,
                                   rtol=1E-4, atol=0)
Пример #4
0
    def test_single_path_geo_iasp91(self):
        """
        Test the raypath for a single phase given geographical input.

        This tests the case when geographiclib is installed.
        """
        filename = os.path.join(
            DATA, "taup_path_-mod_iasp91_-o_stdout_-h_10_" +
            "-ph_P_-sta_-45_-60_evt_-80_-60")
        expected = np.genfromtxt(filename, comments='>')

        m = TauPyModel(model="iasp91")
        with warnings.catch_warnings(record=True):
            warnings.simplefilter("always")
            arrivals = m.get_ray_paths_geo(source_depth_in_km=10.0,
                                           source_latitude_in_deg=-80.0,
                                           source_longitude_in_deg=-60.0,
                                           receiver_latitude_in_deg=-45.0,
                                           receiver_longitude_in_deg=-60.0,
                                           phase_list=["P"])
        self.assertEqual(len(arrivals), 1)

        # Interpolate both paths to 100 samples and make sure they are
        # approximately equal.
        sample_points = np.linspace(0, 35, 100)

        interpolated_expected_depth = np.interp(sample_points, expected[:, 0],
                                                expected[:, 1])
        interpolated_expected_lat = np.interp(sample_points, expected[:, 0],
                                              expected[:, 2])
        interpolated_expected_lon = np.interp(sample_points, expected[:, 0],
                                              expected[:, 3])

        interpolated_actual_depth = np.interp(
            sample_points, np.round(np.degrees(arrivals[0].path['dist']), 2),
            np.round(6371 - arrivals[0].path['depth'], 2))
        np.testing.assert_allclose(interpolated_actual_depth,
                                   interpolated_expected_depth,
                                   rtol=1E-4,
                                   atol=0)

        if geodetics.GEOGRAPHICLIB_VERSION_AT_LEAST_1_34:
            interpolated_actual_lat = np.interp(
                sample_points,
                np.round(np.degrees(arrivals[0].path['dist']), 2),
                np.round(arrivals[0].path['lat'], 2))
            interpolated_actual_lon = np.interp(
                sample_points,
                np.round(np.degrees(arrivals[0].path['dist']), 2),
                np.round(arrivals[0].path['lon'], 2))
            np.testing.assert_allclose(interpolated_actual_lat,
                                       interpolated_expected_lat,
                                       rtol=1E-4,
                                       atol=0)
            np.testing.assert_allclose(interpolated_actual_lon,
                                       interpolated_expected_lon,
                                       rtol=1E-4,
                                       atol=0)
Пример #5
0
    def test_single_path_geo_fallback_iasp91(self):
        """
        Test the raypath for a single phase given geographical input.

        This version of the test checks that things still work when
        geographiclib is not installed.
        """
        has_geographiclib_real = geodetics.HAS_GEOGRAPHICLIB
        geodetics.HAS_GEOGRAPHICLIB = False
        filename = os.path.join(DATA,
                                "taup_path_-o_stdout_-h_10_-ph_P_-deg_35")
        expected = np.genfromtxt(filename, comments='>')

        m = TauPyModel(model="iasp91")
        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter("always")
            arrivals = m.get_ray_paths_geo(source_depth_in_km=10.0,
                                           source_latitude_in_deg=-80.0,
                                           source_longitude_in_deg=-60.0,
                                           receiver_latitude_in_deg=-45.0,
                                           receiver_longitude_in_deg=-60.0,
                                           phase_list=["P"])
            geodetics.HAS_GEOGRAPHICLIB = has_geographiclib_real
            self.assertTrue(issubclass(w[-1].category, UserWarning))

        self.assertEqual(len(arrivals), 1)

        # Interpolate both paths to 100 samples and make sure they are
        # approximately equal.
        sample_points = np.linspace(0, 35, 100)

        interpolated_expected = np.interp(
            sample_points,
            expected[:, 0],
            expected[:, 1])

        interpolated_actual = np.interp(
            sample_points,
            np.round(np.degrees(arrivals[0].path['dist']), 2),
            np.round(6371 - arrivals[0].path['depth'], 2))

        np.testing.assert_allclose(interpolated_actual, interpolated_expected,
                                   rtol=1E-4, atol=0)

        # NB: we do not check path['lat'] and path['lon'] here, as these
        # are not calculated when geographiclib is not installed. We check
        # that they are not present.
        with self.assertRaises(ValueError):
            arrivals[0].path["lat"]
        with self.assertRaises(ValueError):
            arrivals[0].path["lon"]
Пример #6
0
    def test_single_path_geo_fallback_iasp91(self):
        """
        Test the raypath for a single phase given geographical input.

        This version of the test checks that things still work when
        geographiclib is not installed.
        """
        has_geographiclib_real = geodetics.HAS_GEOGRAPHICLIB
        geodetics.HAS_GEOGRAPHICLIB = False
        filename = os.path.join(DATA,
                                "taup_path_-o_stdout_-h_10_-ph_P_-deg_35")
        expected = np.genfromtxt(filename, comments='>')

        m = TauPyModel(model="iasp91")
        with warnings.catch_warnings(record=True) as w:
            warnings.simplefilter("always")
            arrivals = m.get_ray_paths_geo(source_depth_in_km=10.0,
                                           source_latitude_in_deg=-80.0,
                                           source_longitude_in_deg=-60.0,
                                           receiver_latitude_in_deg=-45.0,
                                           receiver_longitude_in_deg=-60.0,
                                           phase_list=["P"])
            geodetics.HAS_GEOGRAPHICLIB = has_geographiclib_real
            assert issubclass(w[-1].category, UserWarning)

        self.assertEqual(len(arrivals), 1)

        # Interpolate both paths to 100 samples and make sure they are
        # approximately equal.
        sample_points = np.linspace(0, 35, 100)

        interpolated_expected = np.interp(
            sample_points,
            expected[:, 0],
            expected[:, 1])

        interpolated_actual = np.interp(
            sample_points,
            np.round(np.degrees(arrivals[0].path['dist']), 2),
            np.round(6371 - arrivals[0].path['depth'], 2))

        np.testing.assert_allclose(interpolated_actual, interpolated_expected,
                                   rtol=1E-4, atol=0)

        # NB: we do not check path['lat'] and path['lon'] here, as these
        # are not calculated when geographiclib is not installed. We check
        # that they are not present.
        with self.assertRaises(ValueError):
            arrivals[0].path["lat"]
        with self.assertRaises(ValueError):
            arrivals[0].path["lon"]
Пример #7
0
def calculate_ray(elat, elon, slat, slon, evdp):
    """function calculates the path along a seismic ray
    and outputs a list of lonlat values to be used in calculations
    """
    #print(elat, elon, slat, slon, evdp)
    model = TauPyModel(model="ak135")
    arrivals = model.get_ray_paths_geo(evdp, elat, elon, slat, slon, \
                                       phase_list=('S'))
    arrival = arrivals[0]
    path_array = arrival.path
    latlons = []
    print(path_array)
    for point in path_array:
        latlon = [point[4], point[5]]
        latlons.append(latlon)

    latlons = np.array(latlons)

    return latlons
Пример #8
0
print(
    c_fdsn.get_stations(network=network, station=station, format="text")[0][0])

# + {"deletable": true, "editable": true}
# Plot the ray paths just to illustrate what we are working with.
from obspy.taup import TauPyModel
m = TauPyModel("ak135")
print(
    m.get_travel_times_geo(source_depth_in_km=17.4,
                           source_latitude_in_deg=-31.130,
                           source_longitude_in_deg=-72.090,
                           receiver_latitude_in_deg=34.95,
                           receiver_longitude_in_deg=-106.46))
m.get_ray_paths_geo(source_depth_in_km=17.4,
                    source_latitude_in_deg=-31.130,
                    source_longitude_in_deg=-72.090,
                    receiver_latitude_in_deg=34.95,
                    receiver_longitude_in_deg=-106.46,
                    phase_list=["P", "pP", "sP", "PcP", "PP"]).plot()

# + {"deletable": true, "editable": true}
# Calculate distance.
from obspy.geodetics import locations2degrees

locations2degrees(lat1=-31.130, long1=-72.090, lat2=34.95, long2=-106.46)

# + {"deletable": true, "editable": true}
components = "Z"
# Varying length of databases. Use common time range.
starttime = obspy.UTCDateTime("2015-09-16T22:55:22.000000Z")
endtime = obspy.UTCDateTime("2015-09-16T23:23:46.200000Z")
Пример #9
0
def get_ray_paths(inventory,
                  catalog,
                  phase_list=['P'],
                  coordinate_system='XYZ',
                  taup_model='iasp91'):
    """
    This function returns lat, lon, depth coordinates from an event
    location to all stations in the inventory object

    :param inventory: an obspy station inventory
    :param catalog: an obspy event catalog
    :param phase_list: a list of seismic phase names that is passed to taup
    :param coordinate_system: can be either 'XYZ' or 'RTP'.
    :param taup_model: the taup model for which the greatcircle paths are
                  computed
    :returns: a list of tuples
        ``[(gcircle, phase_name, station_label, event_timestamp,
        event_magnitude, event_id, origin_id), ...]``. ``gcircle`` is an array
        of shape ``[3, npoints]`` with the path coordinates. ``phase_name`` is
        the name of the seismic phase, ``station_label`` is the name of the
        station and network that belongs to the path. ``event_timestamp``,
        ``event_magnitude``, ``event_id`` and ``origin_id`` describe the event
        that belongs to the path.
    """
    # GEOGRAPHICLIB is mandatory for this function
    if not geodetics.HAS_GEOGRAPHICLIB:
        raise ImportError('Geographiclib not found but required by ray path '
                          'routine')

    stlats = []
    stlons = []
    stlabels = []
    for network in inventory:
        for station in network:
            label_ = ".".join((network.code, station.code))
            if station.latitude is None or station.longitude is None:
                msg = ("Station '%s' does not have latitude/longitude "
                       "information and will not be plotted." % label_)
                warnings.warn(msg)
                continue
            stlats.append(station.latitude)
            stlons.append(station.longitude)
            stlabels.append(label_)

    # make a big list of event coordinates and names
    # this part should be included as a subroutine of catalog that extracts
    # a list of event properties. E.g. catalog.extract(['latitiude',
    # 'longitude', 'depth', 'mag', 'focal_mechanism') The same should be done
    # for an inventory with stations
    evlats = []
    evlons = []
    evdepths = []
    event_ids = []
    origin_ids = []
    magnitudes = []
    times = []
    for event in catalog:
        if not event.origins:
            msg = ("Event '%s' does not have an origin and will not be "
                   "plotted." % str(event.resource_id))
            warnings.warn(msg)
            continue
        if not event.magnitudes:
            msg = ("Event '%s' does not have a magnitude and will not be "
                   "plotted." % str(event.resource_id))
            warnings.warn(msg)
            continue
        origin = event.preferred_origin() or event.origins[0]
        evlats.append(origin.latitude)
        evlons.append(origin.longitude)
        if not origin.get('depth'):
            # XXX do we really want to include events without depth???
            origin.depth = 0.
        evdepths.append(origin.get('depth') * 1e-3)
        magnitude = event.preferred_magnitude() or event.magnitudes[0]
        mag = magnitude.mag
        event_ids.append(str(event.resource_id))
        origin_ids.append(str(origin.resource_id))
        magnitudes.append(mag)
        times.append(origin.time.timestamp)

    # initialize taup model if it is not provided
    if isinstance(taup_model, str):
        from obspy.taup import TauPyModel
        model = TauPyModel(model=taup_model)
    else:
        model = taup_model

    # now loop through all stations and source combinations
    r_earth = model.model.radius_of_planet
    greatcircles = []
    for stlat, stlon, stlabel in zip(stlats, stlons, stlabels):
        for evlat, evlon, evdepth_km, time, magnitude, event_id, origin_id \
                in zip(evlats, evlons, evdepths, times, magnitudes, event_ids,
                       origin_ids):
            arrivals = model.get_ray_paths_geo(evdepth_km,
                                               evlat,
                                               evlon,
                                               stlat,
                                               stlon,
                                               phase_list=phase_list,
                                               resample=True)
            if len(arrivals) == 0:
                continue

            for arr in arrivals:
                radii = (r_earth - arr.path['depth']) / r_earth
                thetas = np.radians(90. - arr.path['lat'])
                phis = np.radians(arr.path['lon'])

                if coordinate_system == 'RTP':
                    gcircle = np.array([radii, thetas, phis])

                if coordinate_system == 'XYZ':
                    gcircle = np.array([
                        radii * np.sin(thetas) * np.cos(phis),
                        radii * np.sin(thetas) * np.sin(phis),
                        radii * np.cos(thetas)
                    ])

                greatcircles.append((gcircle, arr.name, stlabel, time,
                                     magnitude, event_id, origin_id))

    return greatcircles
Пример #10
0
def mig_one_station(stream, model="ak135", earth_radius=6378137.0, depth_range=(0, 300, 1)):

    try:
        # prior to the model used to calculate traveltime
        model = stream[0].stats.model
    except AttributeError:
        model = model

    taup_model = TauPyModel(model=model)
    for tr in stream:
        evdp = tr.stats.event_depth
        evla = tr.stats.event_latitude
        evlo = tr.stats.event_longitude

        stla = tr.stats.station_latitude
        stlo = tr.stats.station_longitude
        phase = tr.stats.phase

        # tr.filter(type="bandpass", freqmin=0.05, freqmax=0.5, zerophase=True)

        arrivals = taup_model.get_ray_paths_geo(source_depth_in_km=evdp,
                                                source_latitude_in_deg=evla, source_longitude_in_deg=evlo,
                                                receiver_latitude_in_deg=stla, receiver_longitude_in_deg=stlo,
                                                phase_list=(phase,), resample=True)

        arr = arrivals[0]
        # raypath coordinates. The dataframe contains six columns, ray_p, traveltime, dist in rad, depth, lat and lon.
        df = pd.DataFrame(arr.path)

        # one-way reflection time
        time = tr.times() / 2
        data = tr.data

        # ray path information: traveltime, depth, and coordinates
        # reverse time: the maximum traveltime minus traveltime at varied depths or points
        df["time_reverse"] = df["time"].iloc[-1] - df["time"]
        # get sub-dataset with traveltime (ray path) slightly longer than the one-way reflected traveltime from acc
        # for convenience of interpolation
        df2 = df[df["time_reverse"] < time[-1] * 1.2]

        # convert the raypath information from dataframe to numpy array
        ttime = df["time_reverse"].to_numpy()
        depth = df["depth"].to_numpy()
        lat = df["lat"].to_numpy()
        lon = df["lon"].to_numpy()

        # simple migration by back projection
        fdepth = interp1d(ttime, depth)
        flat = interp1d(ttime, lat)
        flon = interp1d(ttime, lon)

        # interpolation fitting in with one-way reflection time to accomplish back projection
        depths = fdepth(time)
        lats = flat(time)
        lons = flon(time)

        # calculate the distances from pierce points to station at different depths
        # or varied radius
        dists = np.zeros_like(depths)
        for i, d in enumerate(depths):
            dists[i], az, baz = gps2dist_azimuth(lat1=tr.stats.station_latitude, lon1=tr.stats.station_longitude,
                                                 lat2=lats[i], lon2=lons[i], a=earth_radius-d)
            # convert the unit from m to km. If the piere point is to the south of the station then distance is negative.
            if lats[i] <= tr.stats.station_latitude:
                dists[i] = -dists[i]
        dists /= 1000

        # the following several lines can be commented. This was firstly written to save data with
        # irregular depth sampling intervals.
        mig1sta = pd.DataFrame(columns=["time", "depth", "dist", "lat", "lon", "data"])
        mig1sta["depth"] = depths
        mig1sta["lat"] = lats
        mig1sta["lon"] = lons
        mig1sta["time"] = time
        tr.normalize()
        mig1sta["data"] = tr.data
        mig1sta["dist"] = dists

        # second interpolation to regular depth grid. after back-projection the depth sampling is irregular.
        # depth range 0-300 km with an interval of 0.5 km.
        delta = depth_range[2]
        d = np.arange(depth_range[0], depth_range[1]+delta, delta)
        tr.stats.delta = delta
        ftime = interp1d(depths, time)
        fdist = interp1d(depths, dists)
        flat = interp1d(depths, lats)
        flon = interp1d(depths, lons)
        fdata = interp1d(depths, tr.data)

        time = ftime(d)
        dists = fdist(d)
        lats = flat(d)
        lons = flon(d)
        tr.data = fdata(d)
        depths = np.copy(d)

        mig1sta = pd.DataFrame(columns=["time", "depth", "dist", "lat", "lon", "data"])
        mig1sta["depth"] = depths
        mig1sta["lat"] = lats
        mig1sta["lon"] = lons
        mig1sta["time"] = time
        tr.normalize()
        mig1sta["data"] = tr.data
        mig1sta["dist"] = dists

        header = {"path": df2, "mig":mig1sta}
        tr.stats.update(header)

    return stream
Пример #11
0
def get_ray_paths(inventory, catalog, phase_list=['P'],
                  coordinate_system='XYZ', taup_model='iasp91'):
    """
    This function returns lat, lon, depth coordinates from an event
    location to all stations in the inventory object

    :param inventory: an obspy station inventory
    :param catalog: an obspy event catalog
    :param phase_list: a list of seismic phase names that is passed to taup
    :param coordinate_system: can be either 'XYZ' or 'RTP'.
    :param taup_model: the taup model for which the greatcircle paths are
                  computed
    :returns: a list of tuples
        ``[(gcircle, phase_name, station_label, event_timestamp,
        event_magnitude, event_id, origin_id), ...]``. ``gcircle`` is an array
        of shape ``[3, npoints]`` with the path coordinates. ``phase_name`` is
        the name of the seismic phase, ``station_label`` is the name of the
        station and network that belongs to the path. ``event_timestamp``,
        ``event_magnitude``, ``event_id`` and ``origin_id`` describe the event
        that belongs to the path.
    """
    # GEOGRAPHICLIB is mandatory for this function
    if not geodetics.HAS_GEOGRAPHICLIB:
        raise ImportError('Geographiclib not found but required by ray path '
                          'routine')

    stlats = []
    stlons = []
    stlabels = []
    for network in inventory:
        for station in network:
            label_ = ".".join((network.code, station.code))
            if station.latitude is None or station.longitude is None:
                msg = ("Station '%s' does not have latitude/longitude "
                       "information and will not be plotted." % label_)
                warnings.warn(msg)
                continue
            stlats.append(station.latitude)
            stlons.append(station.longitude)
            stlabels.append(label_)

    # make a big list of event coordinates and names
    # this part should be included as a subroutine of catalog that extracts
    # a list of event properties. E.g. catalog.extract(['latitiude',
    # 'longitude', 'depth', 'mag', 'focal_mechanism') The same should be done
    # for an inventory with stations
    evlats = []
    evlons = []
    evdepths = []
    event_ids = []
    origin_ids = []
    magnitudes = []
    times = []
    for event in catalog:
        if not event.origins:
            msg = ("Event '%s' does not have an origin and will not be "
                   "plotted." % str(event.resource_id))
            warnings.warn(msg)
            continue
        if not event.magnitudes:
            msg = ("Event '%s' does not have a magnitude and will not be "
                   "plotted." % str(event.resource_id))
            warnings.warn(msg)
            continue
        origin = event.preferred_origin() or event.origins[0]
        evlats.append(origin.latitude)
        evlons.append(origin.longitude)
        if not origin.get('depth'):
            # XXX do we really want to include events without depth???
            origin.depth = 0.
        evdepths.append(origin.get('depth') * 1e-3)
        magnitude = event.preferred_magnitude() or event.magnitudes[0]
        mag = magnitude.mag
        event_ids.append(str(event.resource_id))
        origin_ids.append(str(origin.resource_id))
        magnitudes.append(mag)
        times.append(origin.time.timestamp)

    # initialize taup model if it is not provided
    if isinstance(taup_model, str):
        from obspy.taup import TauPyModel
        model = TauPyModel(model=taup_model)
    else:
        model = taup_model

    # now loop through all stations and source combinations
    r_earth = model.model.radius_of_planet
    greatcircles = []
    for stlat, stlon, stlabel in zip(stlats, stlons, stlabels):
        for evlat, evlon, evdepth_km, time, magnitude, event_id, origin_id \
                in zip(evlats, evlons, evdepths, times, magnitudes, event_ids,
                       origin_ids):
            arrivals = model.get_ray_paths_geo(
                    evdepth_km, evlat, evlon, stlat, stlon,
                    phase_list=phase_list, resample=True)
            if len(arrivals) == 0:
                continue

            for arr in arrivals:
                radii = (r_earth - arr.path['depth']) / r_earth
                thetas = np.radians(90. - arr.path['lat'])
                phis = np.radians(arr.path['lon'])

                if coordinate_system == 'RTP':
                    gcircle = np.array([radii, thetas, phis])

                if coordinate_system == 'XYZ':
                    gcircle = np.array([radii * np.sin(thetas) * np.cos(phis),
                                        radii * np.sin(thetas) * np.sin(phis),
                                        radii * np.cos(thetas)])

                greatcircles.append((gcircle, arr.name, stlabel, time,
                                     magnitude, event_id, origin_id))

    return greatcircles