def __toArrival(parser, pick_el, evaluation_mode, pick): """ """ global CURRENT_TYPE arrival = Arrival() arrival.resource_id = ResourceIdentifier(prefix="/".join([RESOURCE_ROOT, "arrival"])) arrival.pick_id = pick.resource_id arrival.phase = parser.xpath2obj('phaseHint', pick_el) arrival.azimuth = parser.xpath2obj('azimuth/value', pick_el, float) arrival.distance = parser.xpath2obj('epi_dist/value', pick_el, float) if arrival.distance is not None: arrival.distance = kilometer2degrees(arrival.distance) takeoff_angle, _ = __toFloatQuantity(parser, pick_el, "incident/value") if takeoff_angle and not math.isnan(takeoff_angle): arrival.takeoff_angle = takeoff_angle arrival.time_residual = parser.xpath2obj('phase_res/value', pick_el, float) arrival.time_weight = parser.xpath2obj('phase_weight/value', pick_el, float) return arrival
def __toArrival(parser, pick_el, evaluation_mode, pick): """ """ global CURRENT_TYPE arrival = Arrival() arrival.resource_id = ResourceIdentifier( prefix="/".join([RESOURCE_ROOT, "arrival"])) arrival.pick_id = pick.resource_id arrival.phase = parser.xpath2obj('phaseHint', pick_el) arrival.azimuth = parser.xpath2obj('azimuth/value', pick_el, float) arrival.distance = parser.xpath2obj('epi_dist/value', pick_el, float) if arrival.distance is not None: arrival.distance = kilometer2degrees(arrival.distance) takeoff_angle, _ = __toFloatQuantity(parser, pick_el, "incident/value") if takeoff_angle and not math.isnan(takeoff_angle): arrival.takeoff_angle = takeoff_angle arrival.time_residual = parser.xpath2obj('phase_res/value', pick_el, float) arrival.time_weight = parser.xpath2obj('phase_weight/value', pick_el, float) return arrival
def maps(station_list, origin, strike, dip, rake, plot_file): """ Plotting a map with epicenter and possible stations according to distance and a map with with the beachball """ # sets figure's dimensions _fig_x = 10 _fig_y = 10 fig = plt.figure(figsize=(_fig_x, _fig_y)) # calculating map space _max = max(_station.distance_by_origin for _station in station_list) _max = int(round(_max * 1000 * 2)) _size = _max + int(round(_max / 7.0)) _diff = kilometer2degrees(round(_size / (2 * 2.0 * 1000))) parallels = [ round(origin.latitude, 2), round((origin.latitude - _diff), 2), round((origin.latitude + _diff), 2) ] meridians = [ round(origin.longitude, 2), round((origin.longitude - _diff), 2), round((origin.longitude + _diff), 2) ] m = Basemap(projection='laea', lat_0=origin.latitude, lon_0=origin.longitude, lat_ts=origin.latitude, resolution='i', area_thresh=0.1, width=_size, height=_size) m.drawparallels(parallels, labels=[1, 0, 0, 0], color='grey', fontsize=10) m.drawmeridians(meridians, labels=[0, 0, 0, 1], color='grey', fontsize=10) m.drawrivers(color='aqua') m.drawcoastlines(color='0.2') m.drawcountries(color='0.4') m.drawmapboundary(fill_color='aqua') m.fillcontinents(color='coral', lake_color='aqua') x, y = m(origin.longitude, origin.latitude) # epicenter m.scatter(x, y, 1, color="#FFFF00", marker="*", zorder=3, linewidths=2, edgecolor="k") # beachball ax = plt.gca() b = beach.Beach([strike, dip, rake], xy=(x, y), width=35000, linewidth=1, facecolor='r') b.set_zorder(10) ax.add_collection(b) # stations for station in station_list: x, y = m(station.longitude, station.latitude) m.scatter(x, y, 150, color="#33CC00", marker="^", zorder=3, linewidths=1, edgecolor="k") plt.text(x + 1800, y + 3000, station.code, family="monospace", fontsize=12) fig.savefig(plot_file)
def __toOrigin(parser, origin_el): """ Parses a given origin etree element. :type parser: :class:`~obspy.core.util.xmlwrapper.XMLParser` :param parser: Open XMLParser object. :type origin_el: etree.element :param origin_el: origin element to be parsed. :return: A ObsPy :class:`~obspy.core.event.Origin` object. """ global CURRENT_TYPE origin = Origin() origin.resource_id = ResourceIdentifier(prefix="/".join([RESOURCE_ROOT, "origin"])) # I guess setting the program used as the method id is fine. origin.method_id = "%s/location_method/%s/1" % (RESOURCE_ROOT, parser.xpath2obj('program', origin_el)) if str(origin.method_id).lower().endswith("none"): origin.method_id = None # Standard parameters. origin.time, origin.time_errors = \ __toTimeQuantity(parser, origin_el, "time") origin.latitude, origin_latitude_error = \ __toFloatQuantity(parser, origin_el, "latitude") origin.longitude, origin_longitude_error = \ __toFloatQuantity(parser, origin_el, "longitude") origin.depth, origin.depth_errors = \ __toFloatQuantity(parser, origin_el, "depth") if origin_longitude_error: origin_longitude_error = origin_longitude_error["uncertainty"] if origin_latitude_error: origin_latitude_error = origin_latitude_error["uncertainty"] # Figure out the depth type. depth_type = parser.xpath2obj("depth_type", origin_el) # Map Seishub specific depth type to the QuakeML depth type. if depth_type == "from location program": depth_type = "from location" if depth_type is not None: origin.depth_type = depth_type # XXX: CHECK DEPTH ORIENTATION!! if CURRENT_TYPE == "seiscomp3": origin.depth *= 1000 if origin.depth_errors.uncertainty: origin.depth_errors.uncertainty *= 1000 else: # Convert to m. origin.depth *= -1000 if origin.depth_errors.uncertainty: origin.depth_errors.uncertainty *= 1000 # Earth model. earth_mod = parser.xpath2obj('earth_mod', origin_el, str) if earth_mod: earth_mod = earth_mod.split() earth_mod = ",".join(earth_mod) origin.earth_model_id = "%s/earth_model/%s/1" % (RESOURCE_ROOT, earth_mod) if (origin_latitude_error is None or origin_longitude_error is None) and \ CURRENT_TYPE not in ["seiscomp3", "toni"]: print "AAAAAAAAAAAAA" raise Exception if origin_latitude_error and origin_latitude_error: if CURRENT_TYPE in ["baynet", "obspyck"]: uncert = OriginUncertainty() if origin_latitude_error > origin_longitude_error: uncert.azimuth_max_horizontal_uncertainty = 0 else: uncert.azimuth_max_horizontal_uncertainty = 90 uncert.min_horizontal_uncertainty, \ uncert.max_horizontal_uncertainty = \ sorted([origin_longitude_error, origin_latitude_error]) uncert.min_horizontal_uncertainty *= 1000.0 uncert.max_horizontal_uncertainty *= 1000.0 uncert.preferred_description = "uncertainty ellipse" origin.origin_uncertainty = uncert elif CURRENT_TYPE == "earthworm": uncert = OriginUncertainty() uncert.horizontal_uncertainty = origin_latitude_error uncert.horizontal_uncertainty *= 1000.0 uncert.preferred_description = "horizontal uncertainty" origin.origin_uncertainty = uncert elif CURRENT_TYPE in ["seiscomp3", "toni"]: pass else: raise Exception # Parse the OriginQuality if applicable. if not origin_el.xpath("originQuality"): return origin origin_quality_el = origin_el.xpath("originQuality")[0] origin.quality = OriginQuality() origin.quality.associated_phase_count = \ parser.xpath2obj("associatedPhaseCount", origin_quality_el, int) # QuakeML does apparently not distinguish between P and S wave phase # count. Some Seishub event files do. p_phase_count = parser.xpath2obj("P_usedPhaseCount", origin_quality_el, int) s_phase_count = parser.xpath2obj("S_usedPhaseCount", origin_quality_el, int) # Use both in case they are set. if p_phase_count is not None and s_phase_count is not None: phase_count = p_phase_count + s_phase_count # Also add two Seishub element file specific elements. origin.quality.p_used_phase_count = p_phase_count origin.quality.s_used_phase_count = s_phase_count # Otherwise the total usedPhaseCount should be specified. else: phase_count = parser.xpath2obj("usedPhaseCount", origin_quality_el, int) if p_phase_count is not None: origin.quality.setdefault("extra", AttribDict()) origin.quality.extra.usedPhaseCountP = {'value': p_phase_count, 'namespace': NAMESPACE} if s_phase_count is not None: origin.quality.setdefault("extra", AttribDict()) origin.quality.extra.usedPhaseCountS = {'value': s_phase_count, 'namespace': NAMESPACE} origin.quality.used_phase_count = phase_count associated_station_count = \ parser.xpath2obj("associatedStationCount", origin_quality_el, int) used_station_count = parser.xpath2obj("usedStationCount", origin_quality_el, int) depth_phase_count = parser.xpath2obj("depthPhaseCount", origin_quality_el, int) standard_error = parser.xpath2obj("standardError", origin_quality_el, float) azimuthal_gap = parser.xpath2obj("azimuthalGap", origin_quality_el, float) secondary_azimuthal_gap = \ parser.xpath2obj("secondaryAzimuthalGap", origin_quality_el, float) ground_truth_level = parser.xpath2obj("groundTruthLevel", origin_quality_el, str) minimum_distance = parser.xpath2obj("minimumDistance", origin_quality_el, float) maximum_distance = parser.xpath2obj("maximumDistance", origin_quality_el, float) median_distance = parser.xpath2obj("medianDistance", origin_quality_el, float) if minimum_distance is not None: minimum_distance = kilometer2degrees(minimum_distance) if maximum_distance is not None: maximum_distance = kilometer2degrees(maximum_distance) if median_distance is not None: median_distance = kilometer2degrees(median_distance) if associated_station_count is not None: origin.quality.associated_station_count = associated_station_count if used_station_count is not None: origin.quality.used_station_count = used_station_count if depth_phase_count is not None: origin.quality.depth_phase_count = depth_phase_count if standard_error is not None and not math.isnan(standard_error): origin.quality.standard_error = standard_error if azimuthal_gap is not None: origin.quality.azimuthal_gap = azimuthal_gap if secondary_azimuthal_gap is not None: origin.quality.secondary_azimuthal_gap = secondary_azimuthal_gap if ground_truth_level is not None: origin.quality.ground_truth_level = ground_truth_level if minimum_distance is not None: origin.quality.minimum_distance = minimum_distance if maximum_distance is not None: origin.quality.maximum_distance = maximum_distance if median_distance is not None and not math.isnan(median_distance): origin.quality.median_distance = median_distance return origin
def PyNASTF(**kwargs): """ PyNASTF: Python Neighbourhood Algorithm STF """ #----------------------------- input handler ----------------------------- config = ConfigParser.RawConfigParser() inputpath = 'in.na.cfg' class input_handler: def __init__(self, inputpath): self.inpath = inputpath self.config = config.read(os.path.join(os.getcwd(), self.inpath)) self.event_address = config.get('General', 'event_address') self.remote_address = config.get('General', 'remote_address') self.network = config.get('General', 'network') self.station = config.get('General', 'station') self.location = config.get('General', 'location') self.channel = config.get('General', 'channel') self.filter = eval(config.get('General', 'filter')) self.lfreq = float(config.get('General', 'lfreq')) self.hfreq = float(config.get('General', 'hfreq')) self.resample = eval(config.get('General', 'resample')) self.sampling_rate = int(config.get('General', 'sampling_rate')) self.min_dist = eval(config.get('General', 'min_dist')) self.max_dist = eval(config.get('General', 'max_dist')) self.bg_model = config.get('General', 'bg_model') self.SNR_limit = eval(config.get('General', 'SNR_limit')) self.plot_ph_no = eval(config.get('General', 'plot_phase_noise')) self.map = eval(config.get('General', 'map')) self.plot_azi = eval(config.get('General', 'plot_azi')) # create the input class inp = input_handler(inputpath) # modifying the input objects in a way to be usable in the next steps! inp.network = inp.network.split(',') for _i in xrange(len(inp.network)): inp.network[_i] = inp.network[_i].strip() inp.channel = inp.channel.split(',') for _i in xrange(len(inp.channel)): inp.channel[_i] = inp.channel[_i].strip() # s_tb: Signal time before, s_ta: Signal time after # n_tb: Noise Time before, n_ta: Noise time after s_tb=-3; s_ta=9 n_tb=-150; n_ta=-30 ev_name, ev_lat, ev_lon, ev_dp, ev_date = \ pdata_reader(address = inp.event_address, remote_address=inp.remote_address) for _i in range(len(ev_name)): ev_name[_i] = os.path.join(ev_name[_i], 'BH') for ev_enum in xrange(len(ev_name)): e_add = ev_name[ev_enum] print '\n===========' print 'Event %s/%s: \n%s' %(ev_enum+1, len(ev_name), e_add) print '===========' if not os.path.isdir(os.path.join(e_add.split('/')[-2], 'infiles')): os.makedirs(os.path.join(e_add.split('/')[-2], 'infiles')) metadata = [] msg_header = 'Event information; Lat, Lon, Depth\n' msg_header += '%.6f %.6f %.6f\n' %(ev_lat[ev_enum],ev_lon[ev_enum], ev_dp[ev_enum]) msg_p = 'P-wave data ' + 17*'*' + '\n' msg_sh = 'SH-wave data ' + 17*'*' + '\n' all_p_data = []; all_sh_data = [] all_sta_add = glob.glob(os.path.join(e_add, '*.*.*.*')) all_sta_add.sort() print len(all_sta_add) for sta_add in all_sta_add: print '.', try: tr = read(sta_add)[0] except Exception, e: print e continue if not inp.network == ['*']: if not tr.stats.network in inp.network: continue if not tr.stats.channel in inp.channel: continue #epi_dist_prev = locations2degrees(tr.stats.sac.evla, tr.stats.sac.evlo, # tr.stats.sac.stla, tr.stats.sac.stlo) epi_km = gps2DistAzimuth(tr.stats.sac.evla, tr.stats.sac.evlo, tr.stats.sac.stla, tr.stats.sac.stlo)[0] epi_dist = kilometer2degrees(epi_km/1000.) # XXX for testing! #epi_dist = tr.stats.sac.gcarc if not inp.min_dist<=epi_dist<=inp.max_dist: continue if 'Z' in tr.stats.channel: tr_tw = time_window(tr, model=inp.bg_model) ph_arr = tr_tw.arr_time(epi_dist, req_phase='P') # XXX for testing #ph_arr = tr.stats.sac.t0 if ph_arr == -12345.0: continue tr = preproc(tr, filter=inp.filter, hfreq=inp.hfreq, lfreq=inp.lfreq, resample=inp.resample, sampling_rate=inp.sampling_rate) SNR, l1_noise, l2_noise, p_data, flag_exist = \ SNR_calculator(tr, ev_date[ev_enum], ph_arr, s_tb=s_tb, s_ta=s_ta, n_tb=n_tb, n_ta=n_ta, method='squared', plot_ph_no=inp.plot_ph_no, address=os.path.join(e_add.split('/')[-2], 'infiles')) if not flag_exist: continue if SNR < inp.SNR_limit: continue innastats_str = '%s\n%.6f %.6f %.6f\n%.6f %.6f %.6f\n' %(tr.stats.station, tr.stats.sac.stla, tr.stats.sac.stlo, ph_arr+s_tb, SNR, l1_noise, l2_noise) az, ba = azbackaz(tr) all_p_data.append([tr.stats.station, tr.stats.location, SNR, az, p_data, innastats_str]) if 'N' in tr.stats.channel: try: tr_E = read(sta_add[:-1] + 'E')[0] except Exception, e: print 'Cannot read: \n%s' %(sta_add[:-1] + 'E') continue tr = preproc(tr, filter=inp.filter, hfreq=inp.hfreq, lfreq=inp.lfreq, resample=inp.resample, sampling_rate=inp.sampling_rate) tr_E = preproc(tr_E, filter=inp.filter, hfreq=inp.hfreq, lfreq=inp.lfreq, resample=inp.resample, sampling_rate=inp.sampling_rate) tr_sh = tr.copy() az, tr_sh.data = rotater(tr, tr_E) if not az: continue tr_tw = time_window(tr_sh, model=inp.bg_model) ph_arr = tr_tw.arr_time(epi_dist, req_phase='S') if ph_arr == -12345.0: continue SNR, l1_noise, l2_noise, sh_data, flag_exist = \ SNR_calculator(tr_sh, ev_date[ev_enum], ph_arr, s_tb=s_tb, s_ta=s_ta, n_tb=n_tb, n_ta=n_ta, method='squared', plot_ph_no=inp.plot_ph_no, address=os.path.join(e_add.split('/')[-2], 'infiles')) if not flag_exist: continue if SNR < inp.SNR_limit: continue innastats_str = '%s\n%.6f %.6f %.6f\n%.6f %.6f %.6f\n' %(tr_sh.stats.station, tr_sh.stats.sac.stla, tr_sh.stats.sac.stlo, ph_arr+s_tb, SNR, l1_noise, l2_noise) all_sh_data.append([tr_sh.stats.station, tr_sh.stats.location, SNR, az, sh_data, innastats_str])
def __toOrigin(parser, origin_el): """ Parses a given origin etree element. :type parser: :class:`~obspy.core.util.xmlwrapper.XMLParser` :param parser: Open XMLParser object. :type origin_el: etree.element :param origin_el: origin element to be parsed. :return: A ObsPy :class:`~obspy.core.event.Origin` object. """ global CURRENT_TYPE origin = Origin() origin.resource_id = ResourceIdentifier( prefix="/".join([RESOURCE_ROOT, "origin"])) # I guess setting the program used as the method id is fine. origin.method_id = "%s/location_method/%s/1" % ( RESOURCE_ROOT, parser.xpath2obj('program', origin_el)) if str(origin.method_id).lower().endswith("none"): origin.method_id = None # Standard parameters. origin.time, origin.time_errors = \ __toTimeQuantity(parser, origin_el, "time") origin.latitude, origin_latitude_error = \ __toFloatQuantity(parser, origin_el, "latitude") origin.longitude, origin_longitude_error = \ __toFloatQuantity(parser, origin_el, "longitude") origin.depth, origin.depth_errors = \ __toFloatQuantity(parser, origin_el, "depth") if origin_longitude_error: origin_longitude_error = origin_longitude_error["uncertainty"] if origin_latitude_error: origin_latitude_error = origin_latitude_error["uncertainty"] # Figure out the depth type. depth_type = parser.xpath2obj("depth_type", origin_el) # Map Seishub specific depth type to the QuakeML depth type. if depth_type == "from location program": depth_type = "from location" if depth_type is not None: origin.depth_type = depth_type # XXX: CHECK DEPTH ORIENTATION!! if CURRENT_TYPE == "seiscomp3": origin.depth *= 1000 if origin.depth_errors.uncertainty: origin.depth_errors.uncertainty *= 1000 else: # Convert to m. origin.depth *= -1000 if origin.depth_errors.uncertainty: origin.depth_errors.uncertainty *= 1000 # Earth model. earth_mod = parser.xpath2obj('earth_mod', origin_el, str) if earth_mod: earth_mod = earth_mod.split() earth_mod = ",".join(earth_mod) origin.earth_model_id = "%s/earth_model/%s/1" % (RESOURCE_ROOT, earth_mod) if (origin_latitude_error is None or origin_longitude_error is None) and \ CURRENT_TYPE not in ["seiscomp3", "toni"]: print "AAAAAAAAAAAAA" raise Exception if origin_latitude_error and origin_latitude_error: if CURRENT_TYPE in ["baynet", "obspyck"]: uncert = OriginUncertainty() if origin_latitude_error > origin_longitude_error: uncert.azimuth_max_horizontal_uncertainty = 0 else: uncert.azimuth_max_horizontal_uncertainty = 90 uncert.min_horizontal_uncertainty, \ uncert.max_horizontal_uncertainty = \ sorted([origin_longitude_error, origin_latitude_error]) uncert.min_horizontal_uncertainty *= 1000.0 uncert.max_horizontal_uncertainty *= 1000.0 uncert.preferred_description = "uncertainty ellipse" origin.origin_uncertainty = uncert elif CURRENT_TYPE == "earthworm": uncert = OriginUncertainty() uncert.horizontal_uncertainty = origin_latitude_error uncert.horizontal_uncertainty *= 1000.0 uncert.preferred_description = "horizontal uncertainty" origin.origin_uncertainty = uncert elif CURRENT_TYPE in ["seiscomp3", "toni"]: pass else: raise Exception # Parse the OriginQuality if applicable. if not origin_el.xpath("originQuality"): return origin origin_quality_el = origin_el.xpath("originQuality")[0] origin.quality = OriginQuality() origin.quality.associated_phase_count = \ parser.xpath2obj("associatedPhaseCount", origin_quality_el, int) # QuakeML does apparently not distinguish between P and S wave phase # count. Some Seishub event files do. p_phase_count = parser.xpath2obj("P_usedPhaseCount", origin_quality_el, int) s_phase_count = parser.xpath2obj("S_usedPhaseCount", origin_quality_el, int) # Use both in case they are set. if p_phase_count is not None and s_phase_count is not None: phase_count = p_phase_count + s_phase_count # Also add two Seishub element file specific elements. origin.quality.p_used_phase_count = p_phase_count origin.quality.s_used_phase_count = s_phase_count # Otherwise the total usedPhaseCount should be specified. else: phase_count = parser.xpath2obj("usedPhaseCount", origin_quality_el, int) if p_phase_count is not None: origin.quality.setdefault("extra", AttribDict()) origin.quality.extra.usedPhaseCountP = { 'value': p_phase_count, 'namespace': NAMESPACE } if s_phase_count is not None: origin.quality.setdefault("extra", AttribDict()) origin.quality.extra.usedPhaseCountS = { 'value': s_phase_count, 'namespace': NAMESPACE } origin.quality.used_phase_count = phase_count associated_station_count = \ parser.xpath2obj("associatedStationCount", origin_quality_el, int) used_station_count = parser.xpath2obj("usedStationCount", origin_quality_el, int) depth_phase_count = parser.xpath2obj("depthPhaseCount", origin_quality_el, int) standard_error = parser.xpath2obj("standardError", origin_quality_el, float) azimuthal_gap = parser.xpath2obj("azimuthalGap", origin_quality_el, float) secondary_azimuthal_gap = \ parser.xpath2obj("secondaryAzimuthalGap", origin_quality_el, float) ground_truth_level = parser.xpath2obj("groundTruthLevel", origin_quality_el, str) minimum_distance = parser.xpath2obj("minimumDistance", origin_quality_el, float) maximum_distance = parser.xpath2obj("maximumDistance", origin_quality_el, float) median_distance = parser.xpath2obj("medianDistance", origin_quality_el, float) if minimum_distance is not None: minimum_distance = kilometer2degrees(minimum_distance) if maximum_distance is not None: maximum_distance = kilometer2degrees(maximum_distance) if median_distance is not None: median_distance = kilometer2degrees(median_distance) if associated_station_count is not None: origin.quality.associated_station_count = associated_station_count if used_station_count is not None: origin.quality.used_station_count = used_station_count if depth_phase_count is not None: origin.quality.depth_phase_count = depth_phase_count if standard_error is not None and not math.isnan(standard_error): origin.quality.standard_error = standard_error if azimuthal_gap is not None: origin.quality.azimuthal_gap = azimuthal_gap if secondary_azimuthal_gap is not None: origin.quality.secondary_azimuthal_gap = secondary_azimuthal_gap if ground_truth_level is not None: origin.quality.ground_truth_level = ground_truth_level if minimum_distance is not None: origin.quality.minimum_distance = minimum_distance if maximum_distance is not None: origin.quality.maximum_distance = maximum_distance if median_distance is not None and not math.isnan(median_distance): origin.quality.median_distance = median_distance return origin