def calculate_phase_delays(self, slowness, phase='Ps', ref=6.4): """ Calculate travel time delays for slowness and reference slowness. Travel time delays are calculated between the direct wave and the converted phase or multiples. :param slowness: ray parameter in s/deg :param phase: 'Ps', 'Sp' or multiples :param ref: reference ray parameter in s/deg :return: original times, times stretched to reference slowness """ if len(phase) % 2 == 1: msg = 'Length of phase (%s) should be divisible by two' raise ValueError(msg % phase) slowness = slowness * kilometer2degrees(1) ref = ref * kilometer2degrees(1) phase = phase.upper() try: t_ref = self.t_ref[phase] except KeyError: self.t_ref[phase] = t_ref = self._calc_phase_delay(ref, phase) t = self._calc_phase_delay(slowness, phase) if phase[0] == 'S': t_ref = -t_ref t = -t try: index = np.nonzero(np.isnan(t))[0][0] - 1 except IndexError: index = len(t) t = t[:index] t_ref = t_ref[:index] return (np.hstack((-t[1:10][::-1], t)), np.hstack((-t_ref[1:10][::-1], t_ref)))
def calculate_phase_delays(self, slowness, phase='Ps', ref=6.4): """ Calculate travel time delays for slowness and reference slowness. Travel time delays are calculated between the direct wave and the converted phase or multiples. :param slowness: ray parameter in s/deg :param phase: 'Ps', 'Sp' or multiples :param ref: reference ray parameter in s/deg :return: original times, times stretched to reference slowness """ if len(phase) % 2 == 1: msg = 'Length of phase (%s) should be divisible by two' raise ValueError(msg % phase) slowness = slowness * kilometer2degrees(1) ref = ref * kilometer2degrees(1) phase = phase.upper() try: t_ref = self.t_ref[phase] except KeyError: self.t_ref[phase] = t_ref = self._calc_phase_delay(ref, phase) t = self._calc_phase_delay(slowness, phase) if phase[0] == 'S': t_ref = -t_ref t = -t try: index = np.nonzero(np.isnan(t))[0][0] - 1 except IndexError: index = len(t) t = t[:index] t_ref = t_ref[:index] return (np.hstack( (-t[1:10][::-1], t)), np.hstack((-t_ref[1:10][::-1], t_ref)))
def test_kilometer2degrees(self): """ Simple test of the convenience function. """ # Test if it works. self.assertEqual(kilometer2degrees(111.19492664455873, radius=6371), 1.0) # Test if setting the radius actually does something. Round to avoid # some precision problems on different machines. self.assertEqual(round(kilometer2degrees(111.19492664455873, radius=6381), 5), round(0.99843284751606332, 5))
def test_kilometer2degrees(self): """ Simple test of the convenience function. """ # Test if it works. self.assertEqual(kilometer2degrees(111.19492664455873, radius=6371), 1.0) # Test if setting the radius actually does something. Round to avoid # some precision problems on different machines. self.assertEqual( round(kilometer2degrees(111.19492664455873, radius=6381), 5), round(0.99843284751606332, 5))
def ppoint_distance(self, depth, slowness, phase='S'): """ Calculate horizontal distance of piercing point to station. :param depth: depth of interface in km :param slowness: ray parameter in s/deg :param phase: 'P' or 'S' for P wave or S wave. Multiples are possible. :return: horizontal distance in km """ if len(phase) % 2 == 0: msg = 'Length of phase (%s) should be even' raise ValueError(msg % phase) phase = phase.upper() slowness = slowness * kilometer2degrees(1) xp, xs = 0., 0. qp, qs = self._calc_vertical_slowness(slowness, phase=phase) if 'P' in phase: xp = np.cumsum(self.dz * slowness / qp) if 'S' in phase: xs = np.cumsum(self.dz * slowness / qs) x = xp * phase.count('P') + xs * phase.count('S') z = self.z index = np.nonzero(depth < z)[0][0] - 1 return x[index] + ((x[index + 1] - x[index]) * (depth - z[index]) / (z[index + 1] - z[index]))
def __init__(self, ses3d_seismogram): #inherit information from instance of ses3d_seismogram() self.ses3d_seismogram = ses3d_seismogram self.eq_depth = ses3d_seismogram.sz/1000.0 #initialize receiver function specific information dist_az = gps2dist_azimuth((90.0-self.ses3d_seismogram.rx), self.ses3d_seismogram.ry, (90.0-self.ses3d_seismogram.sx), self.ses3d_seismogram.sy, a = 6371000.0, f = 0.0) self.back_az = dist_az[1] self.az = dist_az[2] self.delta_deg = kilometer2degrees(dist_az[0]/1000.0) self.time = np.zeros(100) self.prf = np.zeros(100) self.srf = np.zeros(100) self.r = np.zeros(100) self.t = np.zeros(100) self.z = np.zeros(100) self.slowness = 0.0 self.pierce_dict = [] self.window_start = 0.0 self.window_end = 0.0
def __init__(self, ses3d_seismogram): #inherit information from instance of ses3d_seismogram() self.ses3d_seismogram = ses3d_seismogram self.eq_depth = ses3d_seismogram.sz / 1000.0 #initialize receiver function specific information dist_az = gps2dist_azimuth((90.0 - self.ses3d_seismogram.rx), self.ses3d_seismogram.ry, (90.0 - self.ses3d_seismogram.sx), self.ses3d_seismogram.sy, a=6371000.0, f=0.0) self.back_az = dist_az[1] self.az = dist_az[2] self.delta_deg = kilometer2degrees(dist_az[0] / 1000.0) self.time = np.zeros(100) self.prf = np.zeros(100) self.srf = np.zeros(100) self.r = np.zeros(100) self.t = np.zeros(100) self.z = np.zeros(100) self.slowness = 0.0 self.pierce_dict = [] self.window_start = 0.0 self.window_end = 0.0
def rfstats(stats=None, event=None, station=None, stream=None, phase='P', dist_range=None): """ Calculate ray specific values like slowness for given event and station. :param stats: stats object with event and/or station attributes. Can be None if both event and station are given. :param event: ObsPy :class:`~obspy.core.event.Event` object :param station: station object with attributes latitude, longitude and elevation :param stream: If a stream is given, stats has to be None. In this case rfstats will be called for every stats object in the stream. :param phase: string with phase to look for in result of :func:`~obspy.taup.taup.getTravelTimes`. Usually this will be 'P' or 'S' for P and S receiver functions, respectively. :type dist_range: tuple of length 2 :param dist_range: if epicentral of event is not in this intervall, None is returned by this function,\n if phase == 'P' defaults to (30, 90),\n if phase == 'S' defaults to (50, 85) :return: ``stats`` object with event and station attributes, distance, back_azimuth, inclination, onset and slowness or None if epicentral distance is not in the given intervall """ if stream is not None: assert stats is None for tr in stream: rfstats(tr.stats, event, station, None, phase, dist_range) return phase = phase.upper() if dist_range is None and phase in 'PS': dist_range = (30, 90) if phase == 'P' else (50, 85) if stats is None: stats = AttribDict({}) stats.update(obj2stats(event=event, station=station)) dist, baz, _ = gps2DistAzimuth(stats.station_latitude, stats.station_longitude, stats.event_latitude, stats.event_longitude) dist = kilometer2degrees(dist / 1000) if dist_range and not dist_range[0] <= dist <= dist_range[1]: return tts = getTravelTimes(dist, stats.event_depth) tts2 = getTravelTimes(dist, 0) tts = [tt for tt in tts if tt['phase_name'] == phase] tts2 = [tt for tt in tts2 if tt['phase_name'] == phase] if len(tts) == 0 or len(tts2) == 0: raise Exception('Taup does not return phase %s at event distance %s' % (phase, dist)) onset = stats.event_time + tts[0]['time'] inc = tts2[0]['take-off angle'] # approximation v = 5.8 if 'P' in phase else 3.36 # iasp91 slowness = 6371. * sin(pi / 180. * inc) / v / 180 * pi stats.update({'distance': dist, 'back_azimuth': baz, 'inclination': inc, 'onset': onset, 'slowness': slowness}) return stats
def get_event_params(eq_lat,eq_lon): dist_az = gps2dist_azimuth(eq_lat,eq_lon,0,0,a=6371000.0,f=0.0) dist_km = dist_az[0]/1000.0 dist_deg = kilometer2degrees(dist_km) az = dist_az[1] baz = dist_az[2] rotation_angle = -1.0*((baz-180) -90.0) #rotation_angle = -1.0*(az-90.0) return dist_deg,rotation_angle
def get_event_params(eq_lat, eq_lon): dist_az = gps2dist_azimuth(eq_lat, eq_lon, 0, 0, a=6371000.0, f=0.0) dist_km = dist_az[0] / 1000.0 dist_deg = kilometer2degrees(dist_km) az = dist_az[1] baz = dist_az[2] rotation_angle = -1.0 * ((baz - 180) - 90.0) #rotation_angle = -1.0*(az-90.0) return dist_deg, rotation_angle
def event2stats(lat, lon, event, phase='P', dist_range=(30, 90)): phase = phase.upper() ori = event.origins[0] dist, baz, _ = gps2DistAzimuth(lat, lon, ori.latitude, ori.longitude) dist = kilometer2degrees(dist / 1000) if not dist_range[0] <= dist <= dist_range[1]: return tts = getTravelTimes(dist, ori.depth) tts2 = getTravelTimes(dist, 0) tts = [tt for tt in tts if tt['phase_name'] == phase] tts2 = [tt for tt in tts2 if tt['phase_name'] == phase] if len(tts) == 0 or len(tts2) == 0: raise Exception('Taup does not return phase %s at event distance %s' % (phase, dist)) onset = event.origins[0].time + tts[0]['time'] inc = tts2[0]['take-off angle'] # approximation return AttribDict({'dist':dist, 'back_azimuth':baz, 'inclination': inc, 'onset':onset})
def plot_all(self, directory, sf=1e5, component='x'): import seismograms as s import matplotlib.pylab as plt from obspy.core.util.geodetics import gps2DistAzimuth from obspy.core.util.geodetics import kilometer2degrees for i in range(0, self.n_recs): a = s.ses3d_seismogram() a.read(directory, self.recs[i]) #determine epicentral distance dist_az = gps2DistAzimuth((90.0 - a.rx), a.ry, (90.0 - a.sx), a.sy) back_az = dist_az[1] delta_deg = kilometer2degrees(dist_az[0] / 1000.0) if (component == 'x'): plt.plot(a.trace_x * sf + delta_deg, a.t, 'k') elif (component == 'y'): plt.plot(a.trace_y * sf + delta_deg, a.t, 'k') elif (component == 'z'): plt.plot(a.trace_z * sf + delta_deg, a.t, 'k') plt.show()
def plot_all(self,directory,sf=1e5,component='x'): import seismograms as s import matplotlib.pylab as plt from obspy.core.util.geodetics import gps2DistAzimuth from obspy.core.util.geodetics import kilometer2degrees for i in range(0,self.n_recs): a = s.ses3d_seismogram() a.read(directory,self.recs[i]) #determine epicentral distance dist_az = gps2DistAzimuth((90.0-a.rx),a.ry,(90.0-a.sx),a.sy) back_az = dist_az[1] delta_deg = kilometer2degrees(dist_az[0]/1000.0) if (component == 'x'): plt.plot(a.trace_x*sf + delta_deg, a.t,'k') elif (component == 'y'): plt.plot(a.trace_y*sf + delta_deg, a.t,'k') elif (component == 'z'): plt.plot(a.trace_z*sf + delta_deg, a.t,'k') plt.show()
def read_nlloc_hyp(filename, coordinate_converter=None, picks=None, **kwargs): """ Reads a NonLinLoc Hypocenter-Phase file to a :class:`~obspy.core.event.Catalog` object. .. note:: Coordinate conversion from coordinate frame of NonLinLoc model files / location run to WGS84 has to be specified explicitly by the user if necessary. .. note:: An example can be found on the :mod:`~obspy.nlloc` submodule front page in the documentation pages. :param filename: File or file-like object in text mode. :type coordinate_converter: func :param coordinate_converter: Function to convert (x, y, z) coordinates of NonLinLoc output to geographical coordinates and depth in meters (longitude, latitude, depth in kilometers). If left `None` NonLinLoc (x, y, z) output is left unchanged (e.g. if it is in geographical coordinates already like for NonLinLoc in global mode). The function should accept three arguments x, y, z and return a tuple of three values (lon, lat, depth in kilometers). :type picks: list of :class:`~obspy.core.event.Pick` :param picks: Original picks used to generate the NonLinLoc location. If provided, the output event will include the original picks and the arrivals in the output origin will link to them correctly (with their `pick_id` attribute). If not provided, the output event will include (the rather basic) pick information that can be reconstructed from the NonLinLoc hypocenter-phase file. :rtype: :class:`~obspy.core.event.Catalog` """ if not hasattr(filename, "read"): # Check if it exists, otherwise assume its a string. try: with open(filename, "rt") as fh: data = fh.read() except: try: data = filename.decode() except: data = str(filename) data = data.strip() else: data = filename.read() if hasattr(data, "decode"): data = data.decode() lines = data.splitlines() # remember picks originally used in location, if provided original_picks = picks if original_picks is None: original_picks = [] # determine indices of block start/end of the NLLOC output file indices_hyp = [None, None] indices_phases = [None, None] for i, line in enumerate(lines): if line.startswith("NLLOC "): indices_hyp[0] = i elif line.startswith("END_NLLOC"): indices_hyp[1] = i elif line.startswith("PHASE "): indices_phases[0] = i elif line.startswith("END_PHASE"): indices_phases[1] = i if any([i is None for i in indices_hyp]): msg = ("NLLOC HYP file seems corrupt," " could not detect 'NLLOC' and 'END_NLLOC' lines.") raise RuntimeError(msg) # strip any other lines around NLLOC block lines = lines[indices_hyp[0]:indices_hyp[1]] # extract PHASES lines (if any) if any(indices_phases): if not all(indices_phases): msg = ("NLLOC HYP file seems corrupt, 'PHASE' block is corrupt.") raise RuntimeError(msg) i1, i2 = indices_phases lines, phases_lines = lines[:i1] + lines[i2 + 1:], lines[i1 + 1:i2] else: phases_lines = [] lines = dict([line.split(None, 1) for line in lines]) line = lines["SIGNATURE"] line = line.rstrip().split('"')[1] signature, version, date, time = line.rsplit(" ", 3) creation_time = UTCDateTime().strptime(date + time, str("%d%b%Y%Hh%Mm%S")) # maximum likelihood origin location info line line = lines["HYPOCENTER"] x, y, z = map(float, line.split()[1:7:2]) if coordinate_converter: x, y, z = coordinate_converter(x, y, z) # origin time info line line = lines["GEOGRAPHIC"] year, month, day, hour, minute = map(int, line.split()[1:6]) seconds = float(line.split()[6]) time = UTCDateTime(year, month, day, hour, minute, seconds) # distribution statistics line line = lines["STATISTICS"] covariance_XX = float(line.split()[7]) covariance_YY = float(line.split()[13]) covariance_ZZ = float(line.split()[17]) stats_info_string = str( "Note: Depth/Latitude/Longitude errors are calculated from covariance " "matrix as 1D marginal (Lon/Lat errors as great circle degrees) " "while OriginUncertainty min/max horizontal errors are calculated " "from 2D error ellipsoid and are therefore seemingly higher compared " "to 1D errors. Error estimates can be reconstructed from the " "following original NonLinLoc error statistics line:\nSTATISTICS " + lines["STATISTICS"]) # goto location quality info line line = lines["QML_OriginQuality"].split() (assoc_phase_count, used_phase_count, assoc_station_count, used_station_count, depth_phase_count) = map(int, line[1:11:2]) stderr, az_gap, sec_az_gap = map(float, line[11:17:2]) gt_level = line[17] min_dist, max_dist, med_dist = map(float, line[19:25:2]) # goto location quality info line line = lines["QML_OriginUncertainty"] hor_unc, min_hor_unc, max_hor_unc, hor_unc_azim = \ map(float, line.split()[1:9:2]) # assign origin info event = Event() cat = Catalog(events=[event]) o = Origin() event.origins = [o] o.origin_uncertainty = OriginUncertainty() o.quality = OriginQuality() ou = o.origin_uncertainty oq = o.quality o.comments.append(Comment(text=stats_info_string)) cat.creation_info.creation_time = UTCDateTime() cat.creation_info.version = "ObsPy %s" % __version__ event.creation_info = CreationInfo(creation_time=creation_time, version=version) event.creation_info.version = version o.creation_info = CreationInfo(creation_time=creation_time, version=version) # negative values can appear on diagonal of covariance matrix due to a # precision problem in NLLoc implementation when location coordinates are # large compared to the covariances. o.longitude = x try: o.longitude_errors.uncertainty = kilometer2degrees(sqrt(covariance_XX)) except ValueError: if covariance_XX < 0: msg = ("Negative value in XX value of covariance matrix, not " "setting longitude error (epicentral uncertainties will " "still be set in origin uncertainty).") warnings.warn(msg) else: raise o.latitude = y try: o.latitude_errors.uncertainty = kilometer2degrees(sqrt(covariance_YY)) except ValueError: if covariance_YY < 0: msg = ("Negative value in YY value of covariance matrix, not " "setting longitude error (epicentral uncertainties will " "still be set in origin uncertainty).") warnings.warn(msg) else: raise o.depth = z * 1e3 # meters! o.depth_errors.uncertainty = sqrt(covariance_ZZ) * 1e3 # meters! o.depth_errors.confidence_level = 68 o.depth_type = str("from location") o.time = time ou.horizontal_uncertainty = hor_unc ou.min_horizontal_uncertainty = min_hor_unc ou.max_horizontal_uncertainty = max_hor_unc # values of -1 seem to be used for unset values, set to None for field in ("horizontal_uncertainty", "min_horizontal_uncertainty", "max_horizontal_uncertainty"): if ou.get(field, -1) == -1: ou[field] = None else: ou[field] *= 1e3 # meters! ou.azimuth_max_horizontal_uncertainty = hor_unc_azim ou.preferred_description = str("uncertainty ellipse") ou.confidence_level = 68 # NonLinLoc in general uses 1-sigma (68%) level oq.standard_error = stderr oq.azimuthal_gap = az_gap oq.secondary_azimuthal_gap = sec_az_gap oq.used_phase_count = used_phase_count oq.used_station_count = used_station_count oq.associated_phase_count = assoc_phase_count oq.associated_station_count = assoc_station_count oq.depth_phase_count = depth_phase_count oq.ground_truth_level = gt_level oq.minimum_distance = kilometer2degrees(min_dist) oq.maximum_distance = kilometer2degrees(max_dist) oq.median_distance = kilometer2degrees(med_dist) # go through all phase info lines for line in phases_lines: line = line.split() arrival = Arrival() o.arrivals.append(arrival) station = str(line[0]) phase = str(line[4]) arrival.phase = phase arrival.distance = kilometer2degrees(float(line[21])) arrival.azimuth = float(line[23]) arrival.takeoff_angle = float(line[24]) arrival.time_residual = float(line[16]) arrival.time_weight = float(line[17]) pick = Pick() wid = WaveformStreamID(station_code=station) date, hourmin, sec = map(str, line[6:9]) t = UTCDateTime().strptime(date + hourmin, "%Y%m%d%H%M") + float(sec) pick.waveform_id = wid pick.time = t pick.time_errors.uncertainty = float(line[10]) pick.phase_hint = phase pick.onset = ONSETS.get(line[3].lower(), None) pick.polarity = POLARITIES.get(line[5].lower(), None) # try to determine original pick for each arrival for pick_ in original_picks: wid = pick_.waveform_id if station == wid.station_code and phase == pick_.phase_hint: pick = pick_ break else: # warn if original picks were specified and we could not associate # the arrival correctly if original_picks: msg = ("Could not determine corresponding original pick for " "arrival. " "Falling back to pick information in NonLinLoc " "hypocenter-phase file.") warnings.warn(msg) event.picks.append(pick) arrival.pick_id = pick.resource_id return cat
def make_earthquake_list(param_dict, **kwargs): ''' Generate earthquakes to be used in tomographic inversion. Earthquake locations can be generated randomly within the distance range (deltamin, deltamax), or alternatively a ring of earthquakes at a fixed distance from the point (0,0) can be generated. In the futures, events may be given as an obspy event catalog. args-------------------------------------------------------------------------- param_dict: parameter dictionary (read from file 'inparam_tomo') kwargs------------------------------------------------------------------------ nevents: number of earthquakes (only use if geometry is 'random') deltamin = minimum earthquake distance from (0,0) (only if geometry is 'random') deltamax = maximum earthquake distance from (0,0) (only if geometry is 'random') ringdist = distance of ring from (0,0). Can be tuple for multiple rings. (only if geometry is 'ring') dtheta = spacing between earthquakes in ring, given in degrees. Default = 30. ''' geometry = param_dict['event_geometry'] nevents = param_dict['nevents'] depth = param_dict['depth'] deltamin = param_dict['deltamin'] deltamax = param_dict['deltamax'] ringdist = param_dict['ringdist'] dtheta = param_dict['dtheta'] lat0 = kwargs.get('lat0', 0.0) lon0 = kwargs.get('lon0', 0.0) eq_list = [] n = 1 if geometry == 'random': while len(eq_list) < nevents: lon = (2.0 * deltamax * np.random.random(1)) - deltamax lat = (2.0 * deltamax * np.random.random(1)) - deltamax dist_az = gps2dist_azimuth(lat, lon, lat0, lon0, a=6371000.0, f=0.0) dist_km = dist_az[0] / 1000.0 dist_deg = kilometer2degrees(dist_km) if dist_deg >= deltamin and dist_deg <= deltamax: eq_list.append((n, lon[0], lat[0], depth)) n += 1 elif geometry == 'ring': theta = np.arange(0, 360, dtheta) origin = geopy.Point(0, 0) eq_list = [] if type(ringdist) == int or type(ringdist) == float: d_km = ringdist * ((6371.0 * 2 * np.pi) / 360.0) for i in range(0, len(theta)): bearing = theta[i] destination = VincentyDistance(kilometers=d_km).destination( origin, bearing) lat = destination[0] lon = destination[1] eq_list.append((n, lon, lat, depth)) n += 1 elif type(ringdist == tuple): for r in ringdist: d_km = r * ((6371.0 * 2 * np.pi) / 360.0) for i in range(0, len(theta)): bearing = theta[i] destination = VincentyDistance( kilometers=d_km).destination(origin, bearing) lat = destination[0] lon = destination[1] eq_list.append((n, lon, lat, depth)) n += 1 np.savetxt('earthquake_list', eq_list, fmt=['%d', '%5.5f', '%5.5f', '%5.5f']) return eq_list
def calculate_ray_coverage(earthquake_list,stations_list,depth_range,phase='S',**kwargs): ''' args: earthquake_list: earthquakes file (same format as used in synth tomo) stations_list: stations file (same format as used in synth tomo) depth_range: tuple (mindepth,maxdepth) kwargs: savefig: True or False figname: str, name of figure (defaults to fig.pdf) plot_title: str, title at the top of the plot (default no title) ''' #the earthquake list format is: eq num, eq lon, eq lat, eq dep #the stations list format is: st lon, st lat savefig = kwargs.get('savefig',True) fig_name = kwargs.get('fig_name','fig.pdf') plot_title = kwargs.get('plot_title','None') fout_name = kwargs.get('fout_name','None') prem = TauPyModel('prem_50km') stations_file = np.loadtxt(stations_list) quakes_file = np.loadtxt(earthquake_list) n_quakes = len(quakes_file) n_stats = len(stations_file) st_lons = stations_file[:,0] st_lats = stations_file[:,1] eq_lons = quakes_file[:,1] eq_lats = quakes_file[:,2] eq_deps = quakes_file[:,3] if phase=='S' or phase=='P': delta_min = 30.0 delta_max = 100.0 elif phase == 'SKS': delta_min = 70.0 delta_max = 140.0 m = Basemap(projection='hammer',lon_0=204) fout = open(fout_name,'w') for i in range(0,n_quakes): #print 'working on earthquake', i for j in range(0,n_stats): geodet = gps2dist_azimuth(eq_lats[i], eq_lons[i], st_lats[j], st_lons[j]) dist_m = geodet[0] dist_deg = kilometer2degrees((dist_m/1000.)) if dist_deg < delta_min: continue elif dist_deg > delta_max: continue az = geodet[1] #print 'eq_lat, eq_lon, st_lat, st_lon, dist_deg', eq_lats[i],eq_lons[i],st_lats[j],st_lons[j],dist_deg arrs = prem.get_pierce_points(source_depth_in_km=eq_deps[i], distance_in_degree=dist_deg, phase_list=[phase]) #print arrs arr = arrs[0] pierce_dict = arr.pierce #items in pierce_dict: 'p' (slowness), 'time' (time in s), 'dist', (distance in rad), 'depth' (depth in km) origin = geopy.Point(eq_lats[i],eq_lons[i]) bearing = az geo_path = [] cross_pt1 = 0 cross_pt2 = 0 dist_max = pierce_dict['dist'][::-1][0] for ds in pierce_dict: #only add points that are past turning depth dist_here = ds[2] if dist_here >= dist_max / 2: time_here = ds[1] depth_here = ds[3] if depth_here == depth_range[1]: dist_deg = np.degrees(ds[2]) dist_km = dist_deg * ((2*np.pi*6371.0/360.0)) geo_pt = VincentyDistance(kilometers=dist_km).destination(origin,bearing) lat_pt = geo_pt[0] lon_pt = geo_pt[1] cross_pt1 = (lon_pt,lat_pt) if depth_here == depth_range[0]: dist_deg = np.degrees(ds[2]) dist_km = dist_deg * ((2*np.pi*6371.0/360.0)) geo_pt = VincentyDistance(kilometers=dist_km).destination(origin,bearing) lat_pt = geo_pt[0] lon_pt = geo_pt[1] cross_pt2 = (lon_pt,lat_pt) if cross_pt1 != 0 and cross_pt2 != 0: m.drawgreatcircle(cross_pt1[0],cross_pt1[1],cross_pt2[0],cross_pt2[1],linewidth=1,alpha=0.15,color='k') fout.write('{} {} {} {}'.format(cross_pt1[0],cross_pt1[1],cross_pt2[0],cross_pt2[1])+'\n') m.drawcoastlines() m.fillcontinents(color='lightgrey') #m.drawparallels(np.arange(-90.,120.,30.)) #m.drawmeridians(np.arange(0.,360.,60.)) if plot_title != 'None': plt.title(plot_title) if savefig: plt.savefig(fig_name) plt.clf() else: plt.show()
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
def write_input(eq_lat,eq_lon,eq_dep,ievt,stations,phase,delays_file,Tmin,taup_model,filename,raytheory=False,tt_from_raydata=True,**kwargs): ''' write an input file for globalseis finite frequency tomography software. each earthquake and datatype (P,S,etc...) has it's own input file args-------------------------------------------------------------------------- eq_lat: earthquake latitude (deg) eq_lon: earthquake longitude (deg) eq_dep: earthquake depth (km) stations: stations array (lons,lats) delays_file: h5py datafile containing cross correlation delay times Tmin: minimum period at which cross correlation measurements were made taup_model: name of TauPyModel used to calculate 1D travel times filename: raytheory: True or False tt_from_raydata: If True, writes cross correlation times to 'xcor*', which will then be added to 1D travel times from raydata kwargs------------------------------------------------------------------------ plot_figure: plot a figure showing source receiver geometry and delay map t_sig: estimated standard error in cross correlation measurement. add_noise: add gaussian noise to traveltime measurements of magnitude t_sig fake_SKS_header: test the SKS header ''' #define variables used in finite frequency tomography (kwargs)---------------- idate = kwargs.get('idate','15001') #event date YYDDD where DDD is between 1 and 365 iotime = kwargs.get('iotime','010101') #vent origin time (HHMMSS) kluster = kwargs.get('kluster','0') #0 if no clustering used stationcode = kwargs.get('stationcode','XXXX') #station code (no more than 16 chars) netw = kwargs.get('netw','PLUMENET ') #network code nobst = kwargs.get('nobst','1') #number of travel time measurements nobsa = kwargs.get('nobsa','0') #number of amplitude measurements kpole = kwargs.get('kpole','0') #number of polar crossings (0 for P and S) sampling_rate = kwargs.get('sampling_rate',10.0) n_bands = kwargs.get('n_bands',1) # spectral bands used (TODO setup more than one) kunit = kwargs.get('kunit',1) #unit of noise (1 = nm) rms0 = kwargs.get('rms0',0) #don't know what this is plot_figure = kwargs.get('plot_figure',False) dist_min = kwargs.get('dist_min',30.0) dist_max = kwargs.get('dist_max',90.0) t_sig = kwargs.get('t_sig',0.0) add_noise = kwargs.get('add_noise',False) fake_SKS_header = kwargs.get('fake_SKS_header',False) filter_type = kwargs.get('filter_type','none') ievt=int(ievt) #double check ievt is an integer (in case it was read from a file) debug = False #create taup model------------------------------------------------------------ tt_model = TauPyModel(taup_model) #get filter parameters-------------------------------------------------------- print 'Tmin = ', Tmin omega_list = [] amp_list = [] for T0 in Tmin: filter_type, freqmin,freqmax, window = get_filter_params(delays_file,phase,T0,filter_type=filter_type) omega,amp = get_filter_freqs(filter_type,freqmin,freqmax,sampling_rate) omega_list.append(omega) amp_list.append(amp) window_len = window[1] - window[0] #write header----------------------------------------------------------------- f = open(filename,'w') f.write('{}'.format(filename)+'\n') f.write('{}'.format('None'+'\n')) fdelays = open('xcor_{}'.format(filename),'w') #ray information-------------------------------------------------------------- if phase == 'P': gm_component = 'BHZ ' #ground motion component f.write('P'+'\n') f.write('P'+'\n') f.write('6371 1 1'+'\n') f.write('3482 2 1'+'\n') f.write('6371 5 0'+'\n') elif phase == 'S' and fake_SKS_header == False: gm_component = 'BHT ' #ground motion component f.write('S'+'\n') f.write('S'+'\n') f.write('6371 1 2'+'\n') f.write('3482 2 2'+'\n') f.write('6371 5 0'+'\n') elif phase == 'SKS' or fake_SKS_header == True: gm_component = 'BHR ' #ground motion component f.write('SKS'+'\n') f.write('SKS'+'\n') f.write('6371 1 2'+'\n') f.write('3482 4 1'+'\n') f.write('1217.1 2 1'+'\n') f.write('3482 4 2'+'\n') f.write('6371 5 0'+'\n') #this is hardwired for now (based on range of rays found with ray tracing software) if phase == 'P': dist_min = 30.0 #dist_max = 98.3859100 dist_max = 97.0 elif phase == 'S': dist_min = 30.0 #dist_max = 99.0557175 dist_max = 97.0 elif phase == 'SKS': #dist_min = 66.0320663 #dist_max = 144.349365 dist_min = 68.0 dist_max = 142.0 #write spectral band information----------------------------------------------- if raytheory: n_bands=0 f.write('{}'.format(n_bands)+'\n') else: f.write('{}'.format(n_bands)+'\n') for i in range(0,n_bands): f.write('{}'.format(len(omega_list[i]))+'\n') for j in range(0,len(omega)): f.write('{} {}'.format(omega_list[i][j],amp_list[i][j])+'\n') #event delay map-------------------------------------------------------------- #lats_i = np.arange(-30.0,30.0,0.1) #lons_i = np.arange(-30.0,30.0,0.1) lats_i = np.arange(-45.0,45.0,0.1) lons_i = np.arange(-45.0,45.0,0.1) event_maps = [] station_delays_list = [] if plot_figure: event_map,figure_axis = make_event_delay_map(eq_lat,eq_lon,phase,delays_file,Tmin,lats_i=lats_i,lons_i=lons_i,plot=True,return_axis=False,nevent=ievt) else: if debug: print 'func:write_input- making event delay map for', phase #print 'eq_lat,eq_lon,phase,Tmin lats_i,lons_i',eq_lat,eq_lon,phase,Tmin,lats_i,lons_i for i in range(0,n_bands): event_map = make_event_delay_map(eq_lat,eq_lon,phase,delays_file,Tmin[i],lats_i=lats_i, lons_i=lons_i,return_axis=False,plot=True,nevent=ievt) event_maps.append(event_map) #find delays at stations------------------------------------------------------ if plot_figure: station_delays = get_station_delays(event_map,stations,lats_i,lons_i,pass_figure_axis=True,figure_axis=figure_axis) else: for i in range(0,n_bands): station_delays = get_station_delays(event_maps[i],stations,lats_i,lons_i) station_delays_list.append(station_delays) #add noise (optional)--------------------------------------------------------- if t_sig != 0: noise = np.random.normal(0,t_sig,len(station_delays)) if add_noise: for i in range(0,len(station_delays_list)): station_delays_list[i] += noise station_lons = stations[0,:] station_lats = stations[1,:] n_stations = len(station_lats) station_elevation = 0.0 for i in range(0,n_stations): dist_deg, rotation_angle = get_event_params(eq_lat,eq_lon) #find event distance event_distaz = gps2dist_azimuth(eq_lat,eq_lon,station_lats[i],station_lons[i],a=6371000.0,f=0.0) event_dist_deg = kilometer2degrees((event_distaz[0]/1000.0)) #skip station if too close or too far from source if event_dist_deg <= dist_min or event_dist_deg >= dist_max: continue #get ray theoretical travel time #if phase == 'S': # phase_list = ['s','S','Sdiff'] #elif phase == 'P': # phase_list = ['p','P','Pdiff'] ray_theory_arr = tt_model.get_travel_times(eq_dep,event_dist_deg,phase_list=[phase]) ### TRY TO GET TRAVEL TIME IN CORE ######################################################### ray_theory_path = tt_model.get_ray_paths(eq_dep,event_dist_deg,phase_list=[phase]) phase_path = ray_theory_path[0] path_time = phase_path.path['time'] path_dt = np.diff(path_time) path_depth = phase_path.path['depth'] time_in_core = 0 for p_i in range(0,len(path_dt)): if path_depth[p_i] >= 2889.0: time_in_core += path_dt[p_i] ############################################################################################ if debug: print '_________________________________________________________________________________' print 'arrivals from taup_get_travel_time for event parameters [depth,delta(deg),phase]:' print '[{},{},{}]'.format(eq_dep,event_dist_deg,phase),ray_theory_arr print 'time in core: ', time_in_core print '_________________________________________________________________________________' if debug: print 'distance, phase, raytheory travel time, observed delay:', event_dist_deg,phase,ray_theory_travel_time,delay_time print 'the travel time observation is ', tobs #fdelays.write('{}'.format(delay_time)+'\n') if raytheory: n_bands = 0 nbt = 0 #spectral band number (must be 0 if ray theory) window_len = 0 kunit = 0 corcoeft=0 else: nbt = 1 #spectral band number #write line 1 (header - doesn't repeat for each spectral band)---------------- f.write('{} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {}'.format(idate, iotime,ievt,kluster,stationcode,netw,gm_component,eq_lat,eq_lon,eq_dep, station_lats[i],station_lons[i],station_elevation,nobst,nobsa,kpole)+'\n') #write line 2-------------------------------------------------------------- f.write('{} {} '.format(kunit,rms0)) for j in range(0,n_bands): f.write('0 ') #used to be 0.0 f.write('\n') #write line 3--------------------------------------------------------------- if raytheory: f.write('{}'.format(1)+'\n') else: f.write('{}'.format(n_bands)+'\n') #write line 4--------------------------------------------------------------- #find delays for each band for j in range(0,n_bands): ray_theory_travel_time = ray_theory_arr[0].time delay_time = station_delays_list[j][i] tobs = ray_theory_travel_time - delay_time corcoeft = 1.0 # cross correlation coefficient nbt = j+1 f.write('{} {} {} {} {} {} {}'.format(tobs,t_sig,corcoeft,nbt,window_len,time_in_core,'#tobs,tsig,corcoeft,nbt,window,tincore')+'\n') #write line 5-------------------------------------------------------------- f.write('{}'.format(0)+'\n') # no amplitude info?
def _metadata_handler(self): sel_indices = self.index_datasource.metadata.get("selections", []) if len(sel_indices) != 0: self.index_datasource.metadata.clear() # ~ print sel_indices[0] # ~ print self.entries[sel_indices[0]] edate, etime, elat, elon, edep, eunit, estatus = self.entries[sel_indices[0]]["summary"].split() elat = float(elat) elon = float(elon) edep = float(edep) ex, ey = self.toxy(elon, elat) greats = self.great(elon, elat) for i, great in enumerate(greats): lons, lats = great x, y = self.toxy(lons, lats) self.plotData.set_data("EQX%i" % i, x) self.plotData.set_data("EQY%i" % i, y) self.backImg.plot(("EQX%i" % i, "EQY%i" % i), type="line", color="red", linewidth=5.0) if len(greats) == 1: self.plotData.set_data("EQX1", []) self.plotData.set_data("EQY1", []) self.backImg.plot(("EQX1", "EQY1"), type="line", color="red", linewidth=5.0) # lon_ij, lat_ij = [(114 + 14.0/60.0 + 22.19/3600.0) , -( 8.0 + 3.0/60. + 43.92/3600.0)] lon_ij, lat_ij = [(-46.61), -(23.50)] # Sao Paulo ijx, ijy = self.toxy(lon_ij, lat_ij) delta = gps2DistAzimuth(elat, elon, lat_ij, lon_ij)[0] delta = kilometer2degrees(delta / 1000.0) tt = getTravelTimes(delta, edep, model="iasp91") text = "FIRST ARRIVAL\n" first = tt[0] text += "%s: %.1f\n" % (first["phase_name"], first["time"]) arriv = datetime.datetime.strptime("%s %s" % (edate, etime), "%Y-%m-%d %H:%M:%S") + datetime.timedelta( seconds=int(first["time"]) ) text += "UTC: %s\n" % arriv text += "WIB: %s" % (arriv + datetime.timedelta(hours=-3)) f = Font(size=16) del self.backImg.overlays[:] label1 = DataLabel( component=self.backImg, data_point=(ijx, ijy), label_text=text, show_label_coords=False, text_color="red", font=f, label_position="bottom right", border_visible=False, bgcolor="white", marker_color="blue", marker_line_color="transparent", marker="diamond", arrow_visible=False, ) self.backImg.overlays.append(label1) event = self.entries[sel_indices[0]]["title"] + "\n" event += "%s %s" % (edate, etime) label2 = DataLabel( component=self.backImg, data_point=(ex, ey), label_text=event, show_label_coords=False, text_color="red", font=f, label_position="bottom right", border_visible=False, bgcolor="white", marker_color="blue", marker_line_color="transparent", marker="diamond", arrow_visible=False, ) self.backImg.overlays.append(label2)
def make_earthquake_list(param_dict,**kwargs): ''' Generate earthquakes to be used in tomographic inversion. Earthquake locations can be generated randomly within the distance range (deltamin, deltamax), or alternatively a ring of earthquakes at a fixed distance from the point (0,0) can be generated. In the futures, events may be given as an obspy event catalog. args-------------------------------------------------------------------------- param_dict: parameter dictionary (read from file 'inparam_tomo') kwargs------------------------------------------------------------------------ nevents: number of earthquakes (only use if geometry is 'random') deltamin = minimum earthquake distance from (0,0) (only if geometry is 'random') deltamax = maximum earthquake distance from (0,0) (only if geometry is 'random') ringdist = distance of ring from (0,0). Can be tuple for multiple rings. (only if geometry is 'ring') dtheta = spacing between earthquakes in ring, given in degrees. Default = 30. ''' geometry = param_dict['event_geometry'] nevents = param_dict['nevents'] depth = param_dict['depth'] deltamin = param_dict['deltamin'] deltamax = param_dict['deltamax'] ringdist = param_dict['ringdist'] dtheta = param_dict['dtheta'] lat0 = kwargs.get('lat0',0.0) lon0 = kwargs.get('lon0',0.0) eq_list = [] n = 1 if geometry=='random': while len(eq_list) < nevents: lon = (2.0*deltamax*np.random.random(1)) - deltamax lat = (2.0*deltamax*np.random.random(1)) - deltamax dist_az = gps2dist_azimuth(lat,lon,lat0,lon0,a=6371000.0,f=0.0) dist_km = dist_az[0]/1000.0 dist_deg = kilometer2degrees(dist_km) if dist_deg >= deltamin and dist_deg <= deltamax: eq_list.append((n,lon[0],lat[0],depth)) n += 1 elif geometry=='ring': theta = np.arange(0,360,dtheta) origin = geopy.Point(0,0) eq_list = [] if type(ringdist)==int or type(ringdist)==float: d_km = ringdist * ((6371.0*2*np.pi)/360.0) for i in range(0,len(theta)): bearing = theta[i] destination = VincentyDistance(kilometers=d_km).destination(origin,bearing) lat = destination[0] lon = destination[1] eq_list.append((n,lon,lat,depth)) n += 1 elif type(ringdist==tuple): for r in ringdist: d_km = r * ((6371.0*2*np.pi)/360.0) for i in range(0,len(theta)): bearing = theta[i] destination = VincentyDistance(kilometers=d_km).destination(origin,bearing) lat = destination[0] lon = destination[1] eq_list.append((n,lon,lat,depth)) n += 1 np.savetxt('earthquake_list',eq_list,fmt=['%d','%5.5f','%5.5f','%5.5f']) return eq_list
def processing(self): from telef import * from obspy.core.util.geodetics import gps2DistAzimuth, kilometer2degrees from obspy.taup.taup import getTravelTimes filename_out, ok = QtGui.QInputDialog.getText(QtGui.QWidget(),"Arquivo de saida", "Entre com o nome: ") output = open(filename_out,'w') oheader1 = ['Estacao', 'Dia', 'H.Chegada', 'H. Origem','Latitude', ' Longitude', 'H', ' Mag', 'Tipo','Dist. Az.', 'Residuo','Regiao'.ljust(30)] oheader2 = [' ',' ', ' hh:mm:ss ','hh:mm:ss ', ' (graus)', ' (graus) ', ' km', ' ',' ',' (graus)', ' (s) ',' ' ] output.write(self.lines_obsis[0][1:6]) output.write('\n\n\n') line=oheader1 output.write('%7s %2s %7s %6s %6s %7s %3s %4s %2s %4s %3s %6s\n'%(line[0],line[1],line[2],line[3],line[4],line[5],line[6], line[7],line[8],line[9],line[10],line[11])) line=oheader2 output.write('%7s %2s %7s %6s %6s %7s %3s %4s %2s %4s %3s %6s\n'%(line[0],line[1],line[2],line[3],line[4],line[5],line[6], line[7],line[8],line[9],line[10],line[11])) output.write('\n') cnt=0; lres=[]; lcnt=[]; elats=[]; elons=[]; emags=[] stlats=[]; stlons=[]; edeps=[] lines_usgs = open(self.filename_usgs, 'r').readlines() for line_obsis in self.lines_obsis[1:]: hdr_obsis=self.lines_obsis[0] iOBSIS = getObSis(line_obsis,hdr_obsis) coords = getCoord(self.filename_coord, iOBSIS[0]) stlats.append(coords[0]) stlons.append(coords[1]) for line in lines_usgs[1:]: l = line.split(',') otime = UTCDateTime(l[0]) ootime = l[0] if otime < iOBSIS[6]: elat = float(l[1]) elon = float(l[2]) if l[3] == "": dep = 0.0 else: dep = float(l[3]) mag = float(l[4]) magType = l[5] net = l[10] elats.append(elat) elons.append(elon) emags.append(mag) edeps.append(dep) place = [l[13],l[14]] delta = gps2DistAzimuth(elat,elon,coords[0],coords[1])[0] delta = kilometer2degrees(delta/1000.) tt = getTravelTimes(delta, dep, model='iasp91') text = "FIRST ARRIVAL\n" first = tt[0] if first['phase_name'] == 'P': text += "%s: %.1f\n" % (first['phase_name'],first['time']) arriv = UTCDateTime(otime) + first['time'] res = arriv-iOBSIS[6] cnt += 1 lcnt.append(cnt) lres.append(res) hc=str(iOBSIS[2]).zfill(2)+':'+str(iOBSIS[3]).zfill(2)+':'+str(iOBSIS[4]).zfill(2) ho=str(otime.time) delta=str(delta) res=str(res) final = [iOBSIS[0],str(iOBSIS[1]).zfill(2),hc,ho[:10].zfill(8),str(elat).zfill(8),str(elon).zfill(9),str(dep).ljust(6),str(mag).ljust(3),str(magType).ljust(3),str(delta)[:5],res[:8].ljust(8),str(place).ljust(50)] line=final output.write('%7s %2s %7s %6s %6s %7s %3s %4s %2s %4s %3s %6s\n'%(line[0],line[1],line[2],line[3],line[4],line[5],line[6],line[7],line[8],line[9],line[10],line[11])) temp = [elat, elon, mag, str(iOBSIS[0]), coords[0], coords[1]] break output.close() ares = np.array(lres) acnt = np.array(lcnt) graphics2.scatter(acnt,ares) if self.mapfull.checkState() == QtCore.Qt.Checked: graphics2.plt_map_marble(elats,elons,emags,edeps,stlats,stlons) else: graphics2.plt_map(elats,elons,emags,edeps,stlats,stlons)
def processing(self): from telef import * from obspy.core.util.geodetics import gps2DistAzimuth, kilometer2degrees from obspy.taup.taup import getTravelTimes filename_out, ok = QtGui.QInputDialog.getText(QtGui.QWidget(), "Arquivo de saida", "Entre com o nome: ") output = open(filename_out, 'w') oheader1 = [ 'Estacao', 'Dia', 'H.Chegada', 'H. Origem', 'Latitude', ' Longitude', 'H', ' Mag', 'Tipo', 'Dist. Az.', 'Residuo', 'Regiao'.ljust(30) ] oheader2 = [ ' ', ' ', ' hh:mm:ss ', 'hh:mm:ss ', ' (graus)', ' (graus) ', ' km', ' ', ' ', ' (graus)', ' (s) ', ' ' ] output.write(self.lines_obsis[0][1:6]) output.write('\n\n\n') line = oheader1 output.write('%7s %2s %7s %6s %6s %7s %3s %4s %2s %4s %3s %6s\n' % (line[0], line[1], line[2], line[3], line[4], line[5], line[6], line[7], line[8], line[9], line[10], line[11])) line = oheader2 output.write('%7s %2s %7s %6s %6s %7s %3s %4s %2s %4s %3s %6s\n' % (line[0], line[1], line[2], line[3], line[4], line[5], line[6], line[7], line[8], line[9], line[10], line[11])) output.write('\n') cnt = 0 lres = [] lcnt = [] elats = [] elons = [] emags = [] stlats = [] stlons = [] edeps = [] lines_usgs = open(self.filename_usgs, 'r').readlines() for line_obsis in self.lines_obsis[1:]: hdr_obsis = self.lines_obsis[0] iOBSIS = getObSis(line_obsis, hdr_obsis) coords = getCoord(self.filename_coord, iOBSIS[0]) stlats.append(coords[0]) stlons.append(coords[1]) for line in lines_usgs[1:]: l = line.split(',') otime = UTCDateTime(l[0]) ootime = l[0] if otime < iOBSIS[6]: elat = float(l[1]) elon = float(l[2]) if l[3] == "": dep = 0.0 else: dep = float(l[3]) mag = float(l[4]) magType = l[5] net = l[10] elats.append(elat) elons.append(elon) emags.append(mag) edeps.append(dep) place = [l[13], l[14]] delta = gps2DistAzimuth(elat, elon, coords[0], coords[1])[0] delta = kilometer2degrees(delta / 1000.) tt = getTravelTimes(delta, dep, model='iasp91') text = "FIRST ARRIVAL\n" first = tt[0] if first['phase_name'] == 'P': text += "%s: %.1f\n" % (first['phase_name'], first['time']) arriv = UTCDateTime(otime) + first['time'] res = arriv - iOBSIS[6] cnt += 1 lcnt.append(cnt) lres.append(res) hc = str(iOBSIS[2]).zfill(2) + ':' + str( iOBSIS[3]).zfill(2) + ':' + str(iOBSIS[4]).zfill(2) ho = str(otime.time) delta = str(delta) res = str(res) final = [ iOBSIS[0], str(iOBSIS[1]).zfill(2), hc, ho[:10].zfill(8), str(elat).zfill(8), str(elon).zfill(9), str(dep).ljust(6), str(mag).ljust(3), str(magType).ljust(3), str(delta)[:5], res[:8].ljust(8), str(place).ljust(50) ] line = final output.write( '%7s %2s %7s %6s %6s %7s %3s %4s %2s %4s %3s %6s\n' % (line[0], line[1], line[2], line[3], line[4], line[5], line[6], line[7], line[8], line[9], line[10], line[11])) temp = [ elat, elon, mag, str(iOBSIS[0]), coords[0], coords[1] ] break output.close() ares = np.array(lres) acnt = np.array(lcnt) graphics2.scatter(acnt, ares) if self.mapfull.checkState() == QtCore.Qt.Checked: graphics2.plt_map_marble(elats, elons, emags, edeps, stlats, stlons) else: graphics2.plt_map(elats, elons, emags, edeps, stlats, stlons)
def write_input(eq_lat, eq_lon, eq_dep, ievt, stations, phase, delays_file, Tmin, taup_model, filename, raytheory=False, tt_from_raydata=True, **kwargs): ''' write an input file for globalseis finite frequency tomography software. each earthquake and datatype (P,S,etc...) has it's own input file args-------------------------------------------------------------------------- eq_lat: earthquake latitude (deg) eq_lon: earthquake longitude (deg) eq_dep: earthquake depth (km) stations: stations array (lons,lats) delays_file: h5py datafile containing cross correlation delay times Tmin: minimum period at which cross correlation measurements were made taup_model: name of TauPyModel used to calculate 1D travel times filename: raytheory: True or False tt_from_raydata: If True, writes cross correlation times to 'xcor*', which will then be added to 1D travel times from raydata kwargs------------------------------------------------------------------------ plot_figure: plot a figure showing source receiver geometry and delay map t_sig: estimated standard error in cross correlation measurement. add_noise: add gaussian noise to traveltime measurements of magnitude t_sig fake_SKS_header: test the SKS header ''' #define variables used in finite frequency tomography (kwargs)---------------- idate = kwargs.get( 'idate', '15001') #event date YYDDD where DDD is between 1 and 365 iotime = kwargs.get('iotime', '010101') #vent origin time (HHMMSS) kluster = kwargs.get('kluster', '0') #0 if no clustering used stationcode = kwargs.get('stationcode', 'XXXX') #station code (no more than 16 chars) netw = kwargs.get('netw', 'PLUMENET ') #network code nobst = kwargs.get('nobst', '1') #number of travel time measurements nobsa = kwargs.get('nobsa', '0') #number of amplitude measurements kpole = kwargs.get('kpole', '0') #number of polar crossings (0 for P and S) sampling_rate = kwargs.get('sampling_rate', 20.0) n_bands = kwargs.get('n_bands', 1) # spectral bands used (TODO setup more than one) kunit = kwargs.get('kunit', 1) #unit of noise (1 = nm) rms0 = kwargs.get('rms0', 0) #don't know what this is plot_figure = kwargs.get('plot_figure', False) dist_min = kwargs.get('dist_min', 30.0) dist_max = kwargs.get('dist_max', 90.0) t_sig = kwargs.get('t_sig', 0.0) add_noise = kwargs.get('add_noise', False) fake_SKS_header = kwargs.get('fake_SKS_header', False) ievt = int( ievt ) #double check ievt is an integer (in case it was read from a file) debug = False #create taup model------------------------------------------------------------ tt_model = TauPyModel(taup_model) #get filter parameters-------------------------------------------------------- print 'Tmin = ', Tmin filter_type, freqmin, freqmax, window = get_filter_params( delays_file, phase, Tmin) omega, amp = get_filter_freqs(filter_type, freqmin, freqmax, sampling_rate) window_len = window[1] - window[0] #write header----------------------------------------------------------------- f = open(filename, 'w') f.write('{}'.format(filename) + '\n') f.write('{}'.format('None' + '\n')) fdelays = open('xcor_{}'.format(filename), 'w') #ray information-------------------------------------------------------------- if phase == 'P': gm_component = 'BHZ ' #ground motion component f.write('P' + '\n') f.write('P' + '\n') f.write('6371 1 1' + '\n') f.write('3482 2 1' + '\n') f.write('6371 5 0' + '\n') elif phase == 'S' and fake_SKS_header == False: gm_component = 'BHT ' #ground motion component f.write('S' + '\n') f.write('S' + '\n') f.write('6371 1 2' + '\n') f.write('3482 2 2' + '\n') f.write('6371 5 0' + '\n') elif phase == 'SKS' or fake_SKS_header == True: gm_component = 'BHR ' #ground motion component f.write('SKS' + '\n') f.write('SKS' + '\n') f.write('6371 1 2' + '\n') f.write('3482 4 1' + '\n') f.write('1217.1 2 1' + '\n') f.write('3482 4 2' + '\n') f.write('6371 5 0' + '\n') #this is hardwired for now (based on range of rays found with ray tracing software) #TODO make distance range more adaptable if phase == 'P': dist_min = 30.0 #dist_max = 98.3859100 dist_max = 97.0 elif phase == 'S': dist_min = 30.0 #dist_max = 99.0557175 dist_max = 97.0 elif phase == 'SKS': #dist_min = 66.0320663 #dist_max = 144.349365 dist_min = 68.0 dist_max = 142.0 #write spectral band information----------------------------------------------- if raytheory: n_bands = 0 f.write('{}'.format(n_bands) + '\n') else: f.write('{}'.format(n_bands) + '\n') f.write('{}'.format(len(omega)) + '\n') for i in range(0, len(omega)): f.write('{} {}'.format(omega[i], amp[i]) + '\n') #event delay map-------------------------------------------------------------- #lats_i = np.arange(-30.0,30.0,0.1) #lons_i = np.arange(-30.0,30.0,0.1) lats_i = np.arange(-45.0, 45.0, 0.1) lons_i = np.arange(-45.0, 45.0, 0.1) if plot_figure: event_map, figure_axis = make_event_delay_map(eq_lat, eq_lon, phase, delays_file, Tmin, lats_i=lats_i, lons_i=lons_i, plot=True, return_axis=False, nevent=ievt) else: if debug: print 'func:write_input- making event delay map for', phase #print 'eq_lat,eq_lon,phase,Tmin lats_i,lons_i',eq_lat,eq_lon,phase,Tmin,lats_i,lons_i event_map = make_event_delay_map(eq_lat, eq_lon, phase, delays_file, Tmin, lats_i=lats_i, lons_i=lons_i, return_axis=False, plot=True, nevent=ievt) #find delays at stations------------------------------------------------------ if plot_figure: station_delays = get_station_delays(event_map, stations, lats_i, lons_i, pass_figure_axis=True, figure_axis=figure_axis) else: station_delays = get_station_delays(event_map, stations, lats_i, lons_i) #add noise (optional)--------------------------------------------------------- if t_sig != 0: noise = np.random.normal(0, t_sig, len(station_delays)) if add_noise: station_delays += noise station_lons = stations[0, :] station_lats = stations[1, :] n_stations = len(station_lats) station_elevation = 0.0 for i in range(0, n_stations): dist_deg, rotation_angle = get_event_params(eq_lat, eq_lon) #find event distance event_distaz = gps2dist_azimuth(eq_lat, eq_lon, station_lats[i], station_lons[i], a=6371000.0, f=0.0) event_dist_deg = kilometer2degrees((event_distaz[0] / 1000.0)) #skip station if too close or too far from source if event_dist_deg <= dist_min or event_dist_deg >= dist_max: continue #get ray theoretical travel time #if phase == 'S': # phase_list = ['s','S','Sdiff'] #elif phase == 'P': # phase_list = ['p','P','Pdiff'] ray_theory_arr = tt_model.get_travel_times(eq_dep, event_dist_deg, phase_list=[phase]) if debug: print '_________________________________________________________________________________' print 'arrivals from taup_get_travel_time for event parameters [depth,delta(deg),phase]:' print '[{},{},{}]'.format(eq_dep, event_dist_deg, phase), ray_theory_arr print '_________________________________________________________________________________' ray_theory_travel_time = ray_theory_arr[0].time delay_time = station_delays[i] tobs = ray_theory_travel_time - delay_time if debug: print 'distance, phase, raytheory travel time, observed delay:', event_dist_deg, phase, ray_theory_travel_time, delay_time print 'the travel time observation is ', tobs fdelays.write('{}'.format(delay_time) + '\n') if raytheory: n_bands = 0 nbt = 0 #spectral band number (must be 0 if ray theory) window_len = 0 kunit = 0 corcoeft = 0 else: nbt = 1 #spectral band number #write line 1-------------------------------------------------------------- f.write('{} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {}'.format( idate, iotime, ievt, kluster, stationcode, netw, gm_component, eq_lat, eq_lon, eq_dep, station_lats[i], station_lons[i], station_elevation, nobst, nobsa, kpole) + '\n') #write line 2-------------------------------------------------------------- f.write('{} {} '.format(kunit, rms0)) for j in range(0, n_bands + 1): f.write('0') #used to be 0.0 f.write('\n') #write line 3--------------------------------------------------------------- if raytheory: f.write('{}'.format(1) + '\n') else: f.write('{}'.format(n_bands) + '\n') #write line 4--------------------------------------------------------------- corcoeft = 1.0 # cross correlation coefficient f.write( '{} {} {} {} {} {}'.format(tobs, t_sig, corcoeft, nbt, window_len, '#tobs,tsig,corcoeft,nbt,window') + '\n') #write line 5-------------------------------------------------------------- f.write('{}'.format(0) + '\n')
ff_tomo.plot_geo_config(stations=stations, events=events) #write input files--------------------------------------------------------------- ievt = 1 #event number nP = 0 #number of P observations nS = 0 #number of S observations nSKS = 0 #number of SKS observations for event in events: ievt = event[0] eq_lon = event[1] eq_lat = event[2] eq_dep = event[3] dist_az = gps2dist_azimuth(eq_lat, eq_lon, 0, 0, a=6371000.0, f=0.0) event_dist_deg = kilometer2degrees((dist_az[0] / 1000.0)) for phase in param_dict['phases_list']: if phase == 'SKS': if event_dist_deg < 70.0 or event_dist_deg > 120.0: print 'skipping event for phase SKS at distance', event_dist_deg continue else: nSKS += 1 filename = '{}_{}'.format(param_dict['run_name'] + '.SKS', nSKS) elif phase == 'S': if event_dist_deg < 30.0 or event_dist_deg > 90.0: print 'skipping event for phase ', phase, 'at distance', event_dist_deg continue
def rfstats(stats=None, event=None, station=None, stream=None, phase='P', dist_range=None, tt_model='iasp91', pp_depth=None, pp_phase=None, model='iasp91'): """ Calculate ray specific values like slowness for given event and station. :param stats: stats object with event and/or station attributes. Can be None if both event and station are given. :param event: ObsPy :class:`~obspy.core.event.Event` object :param station: station object with attributes latitude, longitude and elevation :param stream: If a stream is given, stats has to be None. In this case rfstats will be called for every stats object in the stream. :param phase: string with phase. Usually this will be 'P' or 'S' for P and S receiver functions, respectively. :type dist_range: tuple of length 2 :param dist_range: if epicentral of event is not in this intervall, None is returned by this function,\n if phase == 'P' defaults to (30, 90),\n if phase == 'S' defaults to (50, 85) :param tt_model: model for travel time calculation. (see the :mod:`obspy.taup` module, default: iasp91) :param pp_depth: Depth for piercing point calculation (in km, default: None -> No calculation) :param pp_phase: Phase for pp calculation (default: 'S' for P-receiver function and 'P' for S-receiver function) :param model': Path to model file for pp calculation (see :class:`~rf.simple_model.SimpleModel`, default: iasp91) :return: ``stats`` object with event and station attributes, distance, back_azimuth, inclination, onset and slowness or None if epicentral distance is not in the given intervall """ if stream is not None: assert stats is None kwargs = {'event': event, 'station': station, 'stream':None, 'phase': phase, 'dist_range': dist_range, 'tt_model':tt_model, 'pp_depth': pp_depth, 'pp_phase': pp_phase, 'model': model} for tr in stream: rfstats(stats=tr.stats, **kwargs) return phase = phase.upper() if dist_range is None and phase in 'PS': dist_range = (30, 90) if phase == 'P' else (50, 85) if stats is None: stats = AttribDict({}) if event is not None and station is not None: stats.update(obj2stats(event=event, station=station)) dist, baz, _ = gps2DistAzimuth(stats.station_latitude, stats.station_longitude, stats.event_latitude, stats.event_longitude) dist = kilometer2degrees(dist / 1000) if dist_range and not dist_range[0] <= dist <= dist_range[1]: return tt_model = TauPyModel(model=tt_model) arrivals = tt_model.get_travel_times(stats.event_depth, dist, (phase,)) if len(arrivals) == 0: raise Exception('TauPy does not return phase %s at distance %s' % (phase, dist)) if len(arrivals) > 1: from warnings import warn msg = ('TauPy returns more than one arrival for phase %s at ' 'distance -> take first arrival' ) warn(msg % (phase, dist)) arrival = arrivals[0] onset = stats.event_time + arrival.time inc = arrival.incident_angle slowness = arrival.ray_param_sec_degree stats.update({'distance': dist, 'back_azimuth': baz, 'inclination': inc, 'onset': onset, 'slowness': slowness}) if pp_depth is not None: model = load_model(model) if pp_phase is None: pp_phase = 'S' if phase.upper().endswith('P') else 'P' model.ppoint(stats, pp_depth, phase=pp_phase) return stats