def __toStationMagnitude(parser, stat_mag_el):
    """
    Parses a given station magnitude etree element.

    :type parser: :class:`~obspy.core.util.xmlwrapper.XMLParser`
    :param parser: Open XMLParser object.
    :type stat_mag_el: etree.element
    :param stat_mag_el: station magnitude element to be parsed.
    :return: A ObsPy :class:`~obspy.core.event.StationMagnitude` object.
    """
    mag = StationMagnitude()
    mag.mag, mag.mag_errors = __toFloatQuantity(parser, stat_mag_el, "mag")
    # Use the waveform id to store station and channel(s) in the form
    # station.[channel_1, channel_2] or station.channel in the case only one
    # channel has been used.
    # XXX: This might be a violation of how this field is used within QuakeML
    channels = parser.xpath2obj('channels', stat_mag_el).split(',')
    channels = ','.join([_i.strip() for _i in channels])
    if len(channels) > 1:
        channels = '%s' % channels
    station = parser.xpath2obj('station', stat_mag_el)
    mag.waveform_id = WaveformStreamID()
    mag.waveform_id.station_code = station
    mag.waveform_id.channel_code = channels
    weight_comment = Comment(
        text="Weight from the SeisHub event file: %.3f" % \
        parser.xpath2obj("weight", stat_mag_el, float))
    mag.comments.append(weight_comment)
    return mag
def __toStationMagnitude(parser, stat_mag_el):
    """
    Parses a given station magnitude etree element.

    :type parser: :class:`~obspy.core.util.xmlwrapper.XMLParser`
    :param parser: Open XMLParser object.
    :type stat_mag_el: etree.element
    :param stat_mag_el: station magnitude element to be parsed.
    return: A ObsPy :class:`~obspy.core.event.StationMagnitude` object.
    """
    global CURRENT_TYPE
    mag = StationMagnitude()
    mag.mag, mag.mag_errors = __toFloatQuantity(parser, stat_mag_el, "mag")
    mag.resource_id = ResourceIdentifier(prefix="/".join([RESOURCE_ROOT, "station_magnitude"]))
    # Use the waveform id to store station and channel(s) in the form
    # station.[channel_1, channel_2] or station.channel in the case only one
    # channel has been used.
    # XXX: This might be a violation of how this field is used within QuakeML
    channels = parser.xpath2obj('channels', stat_mag_el).split(',')
    channels = ','.join([_i.strip() for _i in channels])
    if len(channels) > 1:
        channels = '%s' % channels
    station = fix_station_name(parser.xpath2obj('station', stat_mag_el))
    location = parser.xpath2obj('location', stat_mag_el, str) or ""
    mag.waveform_id = WaveformStreamID()
    # Map some station names.
    if station in STATION_DICT:
        station = STATION_DICT[station]
    mag.waveform_id.station_code = station
    if CURRENT_TYPE == "obspyck":
        mag.method_id = "%s/station_magnitude_method/obspyck/1" % RESOURCE_ROOT

    network = parser.xpath2obj('network', stat_mag_el)
    if network is None:
        # network id is not stored in original stationMagnitude, try to find it
        # in a pick with same station name
        for waveform in parser.xpath("pick/waveform"):
            if waveform.attrib.get("stationCode") == station:
                network = waveform.attrib.get("networkCode")
                break
    if network is None:
        network = NETWORK_DICT[station]
    if network is None:
        print "AAAAAAAAAAAAAAAAAAAAAAAAAAHHHHHHHHHHHHHHHHHHH"
        raise Exception

    if "," not in channels:
        mag.waveform_id.channel_code = channels
    mag.waveform_id.network_code = network
    mag.waveform_id.location_code = location
    return mag
示例#3
0
def __toStationMagnitude(parser, stat_mag_el):
    """
    Parses a given station magnitude etree element.

    :type parser: :class:`~obspy.core.util.xmlwrapper.XMLParser`
    :param parser: Open XMLParser object.
    :type stat_mag_el: etree.element
    :param stat_mag_el: station magnitude element to be parsed.
    return: A ObsPy :class:`~obspy.core.event.StationMagnitude` object.
    """
    global CURRENT_TYPE
    mag = StationMagnitude()
    mag.mag, mag.mag_errors = __toFloatQuantity(parser, stat_mag_el, "mag")
    mag.resource_id = ResourceIdentifier(
        prefix="/".join([RESOURCE_ROOT, "station_magnitude"]))
    # Use the waveform id to store station and channel(s) in the form
    # station.[channel_1, channel_2] or station.channel in the case only one
    # channel has been used.
    # XXX: This might be a violation of how this field is used within QuakeML
    channels = parser.xpath2obj('channels', stat_mag_el).split(',')
    channels = ','.join([_i.strip() for _i in channels])
    if len(channels) > 1:
        channels = '%s' % channels
    station = fix_station_name(parser.xpath2obj('station', stat_mag_el))
    location = parser.xpath2obj('location', stat_mag_el, str) or ""
    mag.waveform_id = WaveformStreamID()
    # Map some station names.
    if station in STATION_DICT:
        station = STATION_DICT[station]
    mag.waveform_id.station_code = station

    network = parser.xpath2obj('network', stat_mag_el)
    if network is None:
        # network id is not stored in original stationMagnitude, try to find it
        # in a pick with same station name
        for waveform in parser.xpath("pick/waveform"):
            if waveform.attrib.get("stationCode") == station:
                network = waveform.attrib.get("networkCode")
                break
    if network is None:
        network = NETWORK_DICT[station]
    if network is None:
        print "AAAAAAAAAAAAAAAAAAAAAAAAAAHHHHHHHHHHHHHHHHHHH"
        raise Exception

    if "," not in channels:
        mag.waveform_id.channel_code = channels
    mag.waveform_id.network_code = network
    mag.waveform_id.location_code = location
    return mag
示例#4
0
文件: evt.py 项目: xinzhou1006/obspy
def _mags(obj, evid, stamag=False, wid=None):
    mags = []
    pm = None
    for magtype1, magtype2 in MAG_MAP.items():
        magkey = 'mean ' * (not stamag) + 'magnitude ' + magtype1
        if magkey in obj:
            magv = obj[magkey]
            if 'inf' in magv:
                warn('invalid value for magnitude: %s (event id %s)'
                     % (magv, evid))
            else:
                magv = float(magv)
                mag = (StationMagnitude(station_magnitude_type=magtype2,
                                        mag=magv, waveform_id=wid)
                       if stamag else
                       Magnitude(magnitude_type=magtype2, mag=magv))
                mags.append(mag)
    if len(mags) == 1:
        pm = mags[0].resource_id
    return mags, pm
示例#5
0
    def _parseRecordM(self, line, event, pick):
        """
        Parses the 'surface wave record' M
        """
        #unused: Z_comp = line[7]
        Z_period = self._float(line[9:13])
        # note: according to the format documentation,
        # column 20 should be blank. However, it seems that
        # Z_amplitude includes that column
        Z_amplitude = self._float(line[13:21])  # micrometers
        #TODO: N_comp and E_comp seems to be never there
        MSZ_mag = line[49:52]
        Ms_mag = self._float(line[53:56])
        #unused: Ms_usage_flag = line[56]

        evid = event.resource_id.id.split('/')[-1]
        station_string =\
            pick.waveform_id.getSEEDString()\
            .replace(' ', '-').replace('.', '_').lower()
        amplitude = None
        if Z_amplitude is not None:
            amplitude = Amplitude()
            prefix = '/'.join((res_id_prefix, 'amp', evid, station_string))
            amplitude.resource_id = ResourceIdentifier(prefix=prefix)
            amplitude.generic_amplitude = Z_amplitude * 1E-6
            amplitude.unit = 'm'
            amplitude.period = Z_period
            amplitude.type = 'AS'
            amplitude.magnitude_hint = 'Ms'
            amplitude.pick_id = pick.resource_id
            event.amplitudes.append(amplitude)
        if MSZ_mag is not None:
            station_magnitude = StationMagnitude()
            prefix = '/'.join(
                (res_id_prefix, 'stationmagntiude', evid, station_string))
            station_magnitude.resource_id = ResourceIdentifier(prefix=prefix)
            station_magnitude.origin_id = event.origins[0].resource_id
            station_magnitude.mag = Ms_mag
            station_magnitude.station_magnitude_type = 'Ms'
            if amplitude is not None:
                station_magnitude.amplitude_id = amplitude.resource_id
            event.station_magnitudes.append(station_magnitude)
示例#6
0
文件: mchedr.py 项目: bonaime/obspy
    def _parse_record_m(self, line, event, pick):
        """
        Parses the 'surface wave record' M
        """
        # unused: Z_comp = line[7]
        z_period = self._float(line[9:13])
        # note: according to the format documentation,
        # column 20 should be blank. However, it seems that
        # z_amplitude includes that column
        z_amplitude = self._float(line[13:21])  # micrometers
        # TODO: N_comp and E_comp seems to be never there
        msz_mag = line[49:52]
        ms_mag = self._float(line[53:56])
        # unused: Ms_usage_flag = line[56]

        evid = event.resource_id.id.split('/')[-1]
        station_string = \
            pick.waveform_id.get_seed_string()\
            .replace(' ', '-').replace('.', '_').lower()
        amplitude = None
        if z_amplitude is not None:
            amplitude = Amplitude()
            prefix = '/'.join((res_id_prefix, 'amp', evid, station_string))
            amplitude.resource_id = ResourceIdentifier(prefix=prefix)
            amplitude.generic_amplitude = z_amplitude * 1E-6
            amplitude.unit = 'm'
            amplitude.period = z_period
            amplitude.type = 'AS'
            amplitude.magnitude_hint = 'Ms'
            amplitude.pick_id = pick.resource_id
            event.amplitudes.append(amplitude)
        if msz_mag is not None:
            station_magnitude = StationMagnitude()
            prefix = '/'.join((res_id_prefix, 'stationmagntiude',
                               evid, station_string))
            station_magnitude.resource_id = ResourceIdentifier(prefix=prefix)
            station_magnitude.origin_id = event.origins[0].resource_id
            station_magnitude.mag = ms_mag
            station_magnitude.station_magnitude_type = 'Ms'
            if amplitude is not None:
                station_magnitude.amplitude_id = amplitude.resource_id
            event.station_magnitudes.append(station_magnitude)
示例#7
0
文件: mchedr.py 项目: kaeufl/obspy
    def _parseRecordM(self, line, event, pick):
        """
        Parses the 'surface wave record' M
        """
        # unused: Z_comp = line[7]
        Z_period = self._float(line[9:13])
        # note: according to the format documentation,
        # column 20 should be blank. However, it seems that
        # Z_amplitude includes that column
        Z_amplitude = self._float(line[13:21])  # micrometers
        # TODO: N_comp and E_comp seems to be never there
        MSZ_mag = line[49:52]
        Ms_mag = self._float(line[53:56])
        # unused: Ms_usage_flag = line[56]

        evid = event.resource_id.id.split("/")[-1]
        station_string = pick.waveform_id.getSEEDString().replace(" ", "-").replace(".", "_").lower()
        amplitude = None
        if Z_amplitude is not None:
            amplitude = Amplitude()
            prefix = "/".join((res_id_prefix, "amp", evid, station_string))
            amplitude.resource_id = ResourceIdentifier(prefix=prefix)
            amplitude.generic_amplitude = Z_amplitude * 1e-6
            amplitude.unit = "m"
            amplitude.period = Z_period
            amplitude.type = "AS"
            amplitude.magnitude_hint = "Ms"
            amplitude.pick_id = pick.resource_id
            event.amplitudes.append(amplitude)
        if MSZ_mag is not None:
            station_magnitude = StationMagnitude()
            prefix = "/".join((res_id_prefix, "stationmagntiude", evid, station_string))
            station_magnitude.resource_id = ResourceIdentifier(prefix=prefix)
            station_magnitude.origin_id = event.origins[0].resource_id
            station_magnitude.mag = Ms_mag
            station_magnitude.station_magnitude_type = "Ms"
            if amplitude is not None:
                station_magnitude.amplitude_id = amplitude.resource_id
            event.station_magnitudes.append(station_magnitude)
示例#8
0
    def _parseRecordP(self, line, event):
        """
        Parses the 'primary phase record' P

        The primary phase is the first phase of the reading,
        regardless its type.
        """
        station = line[2:7].strip()
        phase = line[7:15]
        arrival_time = line[15:24]
        residual = self._float(line[25:30])
        #unused: residual_flag = line[30]
        distance = self._float(line[32:38])  # degrees
        azimuth = self._float(line[39:44])
        backazimuth = round(azimuth % -360 + 180, 1)
        mb_period = self._float(line[44:48])
        mb_amplitude = self._float(line[48:55])  # nanometers
        mb_magnitude = self._float(line[56:59])
        #unused: mb_usage_flag = line[59]

        origin = event.origins[0]
        evid = event.resource_id.id.split('/')[-1]
        waveform_id = WaveformStreamID()
        waveform_id.station_code = station
        #network_code is required for QuakeML validation
        waveform_id.network_code = '  '
        station_string =\
            waveform_id.getSEEDString()\
            .replace(' ', '-').replace('.', '_').lower()
        prefix = '/'.join(
            (res_id_prefix, 'waveformstream', evid, station_string))
        waveform_id.resource_uri = ResourceIdentifier(prefix=prefix)
        pick = Pick()
        prefix = '/'.join((res_id_prefix, 'pick', evid, station_string))
        pick.resource_id = ResourceIdentifier(prefix=prefix)
        date = origin.time.strftime('%Y%m%d')
        pick.time = UTCDateTime(date + arrival_time)
        #Check if pick is on the next day:
        if pick.time < origin.time:
            pick.time += timedelta(days=1)
        pick.waveform_id = waveform_id
        pick.backazimuth = backazimuth
        onset = phase[0]
        if onset == 'e':
            pick.onset = 'emergent'
            phase = phase[1:]
        elif onset == 'i':
            pick.onset = 'impulsive'
            phase = phase[1:]
        elif onset == 'q':
            pick.onset = 'questionable'
            phase = phase[1:]
        pick.phase_hint = phase.strip()
        event.picks.append(pick)
        if mb_amplitude is not None:
            amplitude = Amplitude()
            prefix = '/'.join((res_id_prefix, 'amp', evid, station_string))
            amplitude.resource_id = ResourceIdentifier(prefix=prefix)
            amplitude.generic_amplitude = mb_amplitude * 1E-9
            amplitude.unit = 'm'
            amplitude.period = mb_period
            amplitude.type = 'AB'
            amplitude.magnitude_hint = 'Mb'
            amplitude.pick_id = pick.resource_id
            amplitude.waveform_id = pick.waveform_id
            event.amplitudes.append(amplitude)
            station_magnitude = StationMagnitude()
            prefix = '/'.join(
                (res_id_prefix, 'stationmagntiude', evid, station_string))
            station_magnitude.resource_id = ResourceIdentifier(prefix=prefix)
            station_magnitude.origin_id = origin.resource_id
            station_magnitude.mag = mb_magnitude
            #station_magnitude.mag_errors['uncertainty'] = 0.0
            station_magnitude.station_magnitude_type = 'Mb'
            station_magnitude.amplitude_id = amplitude.resource_id
            station_magnitude.waveform_id = pick.waveform_id
            res_id = '/'.join(
                (res_id_prefix, 'magnitude/generic/body_wave_magnitude'))
            station_magnitude.method_id =\
                ResourceIdentifier(id=res_id)
            event.station_magnitudes.append(station_magnitude)
        arrival = Arrival()
        prefix = '/'.join((res_id_prefix, 'arrival', evid, station_string))
        arrival.resource_id = ResourceIdentifier(prefix=prefix)
        arrival.pick_id = pick.resource_id
        arrival.phase = pick.phase_hint
        arrival.azimuth = azimuth
        arrival.distance = distance
        arrival.time_residual = residual
        res_id = '/'.join((res_id_prefix, 'earthmodel/ak135'))
        arrival.earth_model_id = ResourceIdentifier(id=res_id)
        origin.arrivals.append(arrival)
        origin.quality.minimum_distance = min(
            d for d in (arrival.distance, origin.quality.minimum_distance)
            if d is not None)
        origin.quality.maximum_distance =\
            max(arrival.distance, origin.quality.minimum_distance)
        origin.quality.associated_phase_count += 1
        return pick, arrival
示例#9
0
    def _parse_arrivals(self, event, origin, origin_res_id):
        # Skip header of arrivals
        next(self.lines)

        # Stop the loop after 2 empty lines (according to the standard).
        previous_line_empty = False

        for line in self.lines:
            line_empty = not line or line.isspace()

            if not self.event_point_separator:
                # Event are separated by two empty lines
                if line_empty and previous_line_empty:
                    break
            else:
                # Event are separated by '.'
                if line.startswith('.'):
                    break

            previous_line_empty = line_empty

            if line_empty:
                # Skip empty lines when the loop should be stopped by
                # point
                continue

            magnitude_types = []
            magnitude_values = []

            fields = self.fields['arrival']

            station = line[fields['sta']].strip()
            distance = line[fields['dist']].strip()
            event_azimuth = line[fields['ev_az']].strip()
            evaluation_mode = line[fields['picktype']].strip()
            direction = line[fields['direction']].strip()
            onset = line[fields['detchar']].strip()
            phase = line[fields['phase']].strip()
            time = line[fields['time']].strip().replace('/', '-')
            time_residual = line[fields['t_res']].strip()
            arrival_azimuth = line[fields['azim']].strip()
            azimuth_residual = line[fields['az_res']].strip()
            slowness = line[fields['slow']].strip()
            slowness_residual = line[fields['s_res']].strip()
            time_defining_flag = line[fields['t_def']].strip()
            azimuth_defining_flag = line[fields['a_def']].strip()
            slowness_defining_flag = line[fields['s_def']].strip()
            snr = line[fields['snr']].strip()
            amplitude_value = line[fields['amp']].strip()
            period = line[fields['per']].strip()
            magnitude_types.append(line[fields['mag_type_1']].strip())
            magnitude_values.append(line[fields['mag_1']].strip())
            magnitude_types.append(line[fields['mag_type_2']].strip())
            magnitude_values.append(line[fields['mag_2']].strip())
            line_id = line[fields['id']].strip()

            # Don't take pick and arrival with wrong time residual
            if '*' in time_residual:
                continue

            try:
                pick = Pick()
                pick.creation_info = self._get_creation_info()
                pick.waveform_id = WaveformStreamID()
                pick.waveform_id.station_code = station
                pick.time = UTCDateTime(time)

                network_code = self.default_network_code
                location_code = self.default_location_code
                channel_code = self.default_channel_code

                try:
                    network_code, channel = self._get_channel(
                        station, pick.time)
                    if channel:
                        channel_code = channel.code
                        location_code = channel.location_code
                except TypeError:
                    pass

                pick.waveform_id.network_code = network_code
                pick.waveform_id.channel_code = channel_code
                if location_code:
                    pick.waveform_id.location_code = location_code

                try:
                    ev_mode = EVALUATION_MODES[evaluation_mode]
                    pick.evaluation_mode = ev_mode
                except KeyError:
                    pass
                try:
                    pick.polarity = PICK_POLARITIES[direction]
                except KeyError:
                    pass
                try:
                    pick.onset = PICK_ONSETS[onset]
                except KeyError:
                    pass
                pick.phase_hint = phase
                try:
                    pick.backazimuth = float(arrival_azimuth)
                except ValueError:
                    pass
                try:
                    pick.horizontal_slowness = float(slowness)
                except ValueError:
                    pass

                public_id = "pick/%s" % line_id
                pick.resource_id = self._get_res_id(public_id)
                event.picks.append(pick)
            except (TypeError, ValueError, AttributeError):
                # Can't parse pick, skip arrival and amplitude parsing
                continue

            arrival = Arrival()
            arrival.creation_info = self._get_creation_info()

            try:
                arrival.pick_id = pick.resource_id.id
            except AttributeError:
                pass
            arrival.phase = phase
            try:
                arrival.azimuth = float(event_azimuth)
            except ValueError:
                pass
            try:
                arrival.distance = float(distance)
            except ValueError:
                pass
            try:
                arrival.time_residual = float(time_residual)
            except ValueError:
                pass
            try:
                arrival.backazimuth_residual = float(azimuth_residual)
            except ValueError:
                pass
            try:
                arrival.horizontal_slowness_residual = float(slowness_residual)
            except ValueError:
                pass

            if time_defining_flag == 'T':
                arrival.time_weight = 1

            if azimuth_defining_flag == 'A':
                arrival.backazimuth_weight = 1

            if slowness_defining_flag == 'S':
                arrival.horizontal_slowness_weight = 1

            public_id = "arrival/%s" % line_id
            arrival.resource_id = self._get_res_id(public_id,
                                                   parent_res_id=origin_res_id)
            origin.arrivals.append(arrival)

            try:
                amplitude = Amplitude()
                amplitude.creation_info = self._get_creation_info()
                amplitude.generic_amplitude = float(amplitude_value)
                try:
                    amplitude.pick_id = pick.resource_id
                    amplitude.waveform_id = pick.waveform_id
                except AttributeError:
                    pass
                try:
                    amplitude.period = float(period)
                except ValueError:
                    pass
                try:
                    amplitude.snr = float(snr)
                except ValueError:
                    pass

                for i in [0, 1]:
                    if magnitude_types[i] and not magnitude_types[i].isspace():
                        amplitude.magnitude_hint = magnitude_types[i]

                public_id = "amplitude/%s" % line_id
                amplitude.resource_id = self._get_res_id(public_id)
                event.amplitudes.append(amplitude)

                for i in [0, 1]:
                    sta_mag = StationMagnitude()
                    sta_mag.creation_info = self._get_creation_info()
                    sta_mag.origin_id = origin_res_id
                    sta_mag.amplitude_id = amplitude.resource_id
                    sta_mag.station_magnitude_type = magnitude_types[i]
                    sta_mag.mag = magnitude_values[i]
                    sta_mag.waveform_id = pick.waveform_id
                    public_id = "magnitude/station/%s/%s" % (line_id, i)
                    sta_mag.resource_id = self._get_res_id(public_id)
                    event.station_magnitudes.append(sta_mag)

                    # Associate station mag with network mag of same type
                    mag = self._find_magnitude_by_type(event, origin_res_id,
                                                       magnitude_types[i])
                    if mag:
                        contrib = StationMagnitudeContribution()
                        contrib.station_magnitude_id = sta_mag.resource_id
                        contrib.weight = 1.0
                        mag.station_magnitude_contributions.append(contrib)
            except ValueError:
                pass
示例#10
0
文件: core.py 项目: znamy/obspy
    def _parse_phase(self, line):
        # since we can not identify which origin a phase line corresponds to,
        # we can not use any of the included information that would go in the
        # Arrival object, as that would have to be attached to the appropriate
        # origin..
        # for now, just append all of these items as comments to the pick
        comments = []

        # 1-5     a5      station code
        station_code = line[0:5].strip()
        # 7-12    f6.2    station-to-event distance (degrees)
        comments.append('station-to-event distance (degrees): "{}"'.format(
            line[6:12]))
        # 14-18   f5.1    event-to-station azimuth (degrees)
        comments.append('event-to-station azimuth (degrees): "{}"'.format(
            line[13:18]))
        # 20-27   a8      phase code
        phase_hint = line[19:27].strip()
        # 29-40   i2,a1,i2,a1,f6.3        arrival time (hh:mm:ss.sss)
        time = self._get_pick_time(line[28:40])
        if time is None:
            msg = ('Could not determine absolute time of pick. This phase '
                   'line will be ignored:\n{}').format(line)
            warnings.warn(msg)
            return None, None, None
        # 42-46   f5.1    time residual (seconds)
        comments.append('time residual (seconds): "{}"'.format(line[41:46]))
        # 48-52   f5.1    observed azimuth (degrees)
        comments.append('observed azimuth (degrees): "{}"'.format(line[47:52]))
        # 54-58   f5.1    azimuth residual (degrees)
        comments.append('azimuth residual (degrees): "{}"'.format(line[53:58]))
        # 60-65   f5.1    observed slowness (seconds/degree)
        comments.append('observed slowness (seconds/degree): "{}"'.format(
            line[59:65]))
        # 67-72   f5.1    slowness residual (seconds/degree)
        comments.append('slowness residual (seconds/degree): "{}"'.format(
            line[66:71]))
        # 74      a1      time defining flag (T or _)
        comments.append('time defining flag (T or _): "{}"'.format(line[73]))
        # 75      a1      azimuth defining flag (A or _)
        comments.append('azimuth defining flag (A or _): "{}"'.format(
            line[74]))
        # 76      a1      slowness defining flag (S or _)
        comments.append('slowness defining flag (S or _): "{}"'.format(
            line[75]))
        # 78-82   f5.1    signal-to-noise ratio
        comments.append('signal-to-noise ratio: "{}"'.format(line[77:82]))
        # 84-92   f9.1    amplitude (nanometers)
        amplitude = float_or_none(line[83:92])
        # 94-98   f5.2    period (seconds)
        period = float_or_none(line[93:98])
        # 100     a1      type of pick (a = automatic, m = manual)
        evaluation_mode = line[99]
        # 101     a1      direction of short period motion
        #                 (c = compression, d = dilatation, _= null)
        polarity = POLARITY[line[100].strip().lower()]
        # 102     a1      onset quality (i = impulsive, e = emergent,
        #                                q = questionable, _ = null)
        onset = ONSET[line[101].strip().lower()]
        # 104-108 a5      magnitude type (mb, Ms, ML, mbmle, msmle)
        magnitude_type = line[103:108].strip()
        # 109     a1      min max indicator (<, >, or blank)
        min_max_indicator = line[108]
        # 110-113 f4.1    magnitude value
        mag = float_or_none(line[109:113])
        # 115-122 a8      arrival identification
        phase_id = line[114:122].strip()

        # process items
        waveform_id = WaveformStreamID(station_code=station_code)
        evaluation_mode = PICK_EVALUATION_MODE[evaluation_mode.strip().lower()]
        comments = [self._make_comment(', '.join(comments))]
        if phase_id:
            resource_id = self._construct_id(['pick'], add_hash=True)
        else:
            resource_id = self._construct_id(['pick', phase_id])
        if mag:
            comment = ('min max indicator (<, >, or blank): ' +
                       min_max_indicator)
            station_magnitude = StationMagnitude(
                mag=mag,
                magnitude_type=magnitude_type,
                resource_id=self._construct_id(['station_magnitude'],
                                               add_hash=True),
                comments=[self._make_comment(comment)])
            # event init always sets an empty ResourceIdentifier, even when
            # specifying None, which is strange
            for key in ['origin_id', 'mag_errors']:
                setattr(station_magnitude, key, None)
        else:
            station_magnitude = None

        # assemble
        pick = Pick(phase_hint=phase_hint,
                    time=time,
                    waveform_id=waveform_id,
                    evaluation_mode=evaluation_mode,
                    comments=comments,
                    polarity=polarity,
                    onset=onset,
                    resource_id=resource_id)
        # event init always sets an empty QuantityError, even when specifying
        # None, which is strange
        for key in ('time_errors', 'horizontal_slowness_errors',
                    'backazimuth_errors'):
            setattr(pick, key, None)
        if amplitude:
            amplitude /= 1e9  # convert from nanometers to meters
            amplitude = Amplitude(unit='m',
                                  generic_amplitude=amplitude,
                                  period=period)
        return pick, amplitude, station_magnitude
示例#11
0
文件: bulletin.py 项目: Brtle/obspy
    def _parse_arrivals(self, event, origin, origin_res_id):
        # Skip header of arrivals
        next(self.lines)

        # Stop the loop after 2 empty lines (according to the standard).
        previous_line_empty = False

        for line in self.lines:
            line_empty = not line or line.isspace()

            if not self.event_point_separator:
                # Event are separated by two empty lines
                if line_empty and previous_line_empty:
                    break
            else:
                # Event are separated by '.'
                if line.startswith('.'):
                    break

            previous_line_empty = line_empty

            if line_empty:
                # Skip empty lines when the loop should be stopped by
                # point
                continue

            magnitude_types = []
            magnitude_values = []

            fields = self.fields['arrival']

            station = line[fields['sta']].strip()
            distance = line[fields['dist']].strip()
            event_azimuth = line[fields['ev_az']].strip()
            evaluation_mode = line[fields['picktype']].strip()
            direction = line[fields['direction']].strip()
            onset = line[fields['detchar']].strip()
            phase = line[fields['phase']].strip()
            time = line[fields['time']].strip().replace('/', '-')
            time_residual = line[fields['t_res']].strip()
            arrival_azimuth = line[fields['azim']].strip()
            azimuth_residual = line[fields['az_res']].strip()
            slowness = line[fields['slow']].strip()
            slowness_residual = line[fields['s_res']].strip()
            time_defining_flag = line[fields['t_def']].strip()
            azimuth_defining_flag = line[fields['a_def']].strip()
            slowness_defining_flag = line[fields['s_def']].strip()
            snr = line[fields['snr']].strip()
            amplitude_value = line[fields['amp']].strip()
            period = line[fields['per']].strip()
            magnitude_types.append(line[fields['mag_type_1']].strip())
            magnitude_values.append(line[fields['mag_1']].strip())
            magnitude_types.append(line[fields['mag_type_2']].strip())
            magnitude_values.append(line[fields['mag_2']].strip())
            line_id = line[fields['id']].strip()

            # Don't take pick and arrival with wrong time residual
            if '*' in time_residual:
                continue

            try:
                pick = Pick()
                pick.creation_info = self._get_creation_info()
                pick.waveform_id = WaveformStreamID()
                pick.waveform_id.station_code = station
                pick.time = UTCDateTime(time)

                network_code = self.default_network_code
                location_code = self.default_location_code
                channel_code = self.default_channel_code

                try:
                    network_code, channel = self._get_channel(station,
                                                              pick.time)
                    if channel:
                        channel_code = channel.code
                        location_code = channel.location_code
                except TypeError:
                    pass

                pick.waveform_id.network_code = network_code
                pick.waveform_id.channel_code = channel_code
                if location_code:
                    pick.waveform_id.location_code = location_code

                try:
                    ev_mode = EVALUATION_MODES[evaluation_mode]
                    pick.evaluation_mode = ev_mode
                except KeyError:
                    pass
                try:
                    pick.polarity = PICK_POLARITIES[direction]
                except KeyError:
                    pass
                try:
                    pick.onset = PICK_ONSETS[onset]
                except KeyError:
                    pass
                pick.phase_hint = phase
                try:
                    pick.backazimuth = float(arrival_azimuth)
                except ValueError:
                    pass
                try:
                    pick.horizontal_slowness = float(slowness)
                except ValueError:
                    pass

                public_id = "pick/%s" % line_id
                pick.resource_id = self._get_res_id(public_id)
                event.picks.append(pick)
            except (TypeError, ValueError, AttributeError):
                # Can't parse pick, skip arrival and amplitude parsing
                continue

            arrival = Arrival()
            arrival.creation_info = self._get_creation_info()

            try:
                arrival.pick_id = pick.resource_id.id
            except AttributeError:
                pass
            arrival.phase = phase
            try:
                arrival.azimuth = float(event_azimuth)
            except ValueError:
                pass
            try:
                arrival.distance = float(distance)
            except ValueError:
                pass
            try:
                arrival.time_residual = float(time_residual)
            except ValueError:
                pass
            try:
                arrival.backazimuth_residual = float(azimuth_residual)
            except ValueError:
                pass
            try:
                arrival.horizontal_slowness_residual = float(slowness_residual)
            except ValueError:
                pass

            if time_defining_flag == 'T':
                arrival.time_weight = 1

            if azimuth_defining_flag == 'A':
                arrival.backazimuth_weight = 1

            if slowness_defining_flag == 'S':
                arrival.horizontal_slowness_weight = 1

            public_id = "arrival/%s" % line_id
            arrival.resource_id = self._get_res_id(public_id,
                                                   parent_res_id=origin_res_id)
            origin.arrivals.append(arrival)

            try:
                amplitude = Amplitude()
                amplitude.creation_info = self._get_creation_info()
                amplitude.generic_amplitude = float(amplitude_value)
                try:
                    amplitude.pick_id = pick.resource_id
                    amplitude.waveform_id = pick.waveform_id
                except AttributeError:
                    pass
                try:
                    amplitude.period = float(period)
                except ValueError:
                    pass
                try:
                    amplitude.snr = float(snr)
                except ValueError:
                    pass

                for i in [0, 1]:
                    if magnitude_types[i] and not magnitude_types[i].isspace():
                        amplitude.magnitude_hint = magnitude_types[i]

                public_id = "amplitude/%s" % line_id
                amplitude.resource_id = self._get_res_id(public_id)
                event.amplitudes.append(amplitude)

                for i in [0, 1]:
                    sta_mag = StationMagnitude()
                    sta_mag.creation_info = self._get_creation_info()
                    sta_mag.origin_id = origin_res_id
                    sta_mag.amplitude_id = amplitude.resource_id
                    sta_mag.station_magnitude_type = magnitude_types[i]
                    sta_mag.mag = magnitude_values[i]
                    public_id = "magnitude/station/%s/%s" % (line_id, i)
                    sta_mag.resource_id = self._get_res_id(public_id)
                    event.station_magnitudes.append(sta_mag)
            except ValueError:
                pass
示例#12
0
文件: mchedr.py 项目: bonaime/obspy
    def _parse_record_p(self, line, event):
        """
        Parses the 'primary phase record' P

        The primary phase is the first phase of the reading,
        regardless its type.
        """
        station = line[2:7].strip()
        phase = line[7:15]
        arrival_time = line[15:24]
        residual = self._float(line[25:30])
        # unused: residual_flag = line[30]
        distance = self._float(line[32:38])  # degrees
        azimuth = self._float(line[39:44])
        backazimuth = round(azimuth % -360 + 180, 1)
        mb_period = self._float(line[44:48])
        mb_amplitude = self._float(line[48:55])  # nanometers
        mb_magnitude = self._float(line[56:59])
        # unused: mb_usage_flag = line[59]

        origin = event.origins[0]
        evid = event.resource_id.id.split('/')[-1]
        waveform_id = WaveformStreamID()
        waveform_id.station_code = station
        # network_code is required for QuakeML validation
        waveform_id.network_code = '  '
        station_string = \
            waveform_id.get_seed_string()\
            .replace(' ', '-').replace('.', '_').lower()
        prefix = '/'.join((res_id_prefix, 'waveformstream',
                           evid, station_string))
        waveform_id.resource_uri = ResourceIdentifier(prefix=prefix)
        pick = Pick()
        prefix = '/'.join((res_id_prefix, 'pick', evid, station_string))
        pick.resource_id = ResourceIdentifier(prefix=prefix)
        date = origin.time.strftime('%Y%m%d')
        pick.time = UTCDateTime(date + arrival_time)
        # Check if pick is on the next day:
        if pick.time < origin.time:
            pick.time += timedelta(days=1)
        pick.waveform_id = waveform_id
        pick.backazimuth = backazimuth
        onset = phase[0]
        if onset == 'e':
            pick.onset = 'emergent'
            phase = phase[1:]
        elif onset == 'i':
            pick.onset = 'impulsive'
            phase = phase[1:]
        elif onset == 'q':
            pick.onset = 'questionable'
            phase = phase[1:]
        pick.phase_hint = phase.strip()
        event.picks.append(pick)
        if mb_amplitude is not None:
            amplitude = Amplitude()
            prefix = '/'.join((res_id_prefix, 'amp', evid, station_string))
            amplitude.resource_id = ResourceIdentifier(prefix=prefix)
            amplitude.generic_amplitude = mb_amplitude * 1E-9
            amplitude.unit = 'm'
            amplitude.period = mb_period
            amplitude.type = 'AB'
            amplitude.magnitude_hint = 'Mb'
            amplitude.pick_id = pick.resource_id
            amplitude.waveform_id = pick.waveform_id
            event.amplitudes.append(amplitude)
            station_magnitude = StationMagnitude()
            prefix = '/'.join((res_id_prefix, 'stationmagntiude',
                               evid, station_string))
            station_magnitude.resource_id = ResourceIdentifier(prefix=prefix)
            station_magnitude.origin_id = origin.resource_id
            station_magnitude.mag = mb_magnitude
            # station_magnitude.mag_errors['uncertainty'] = 0.0
            station_magnitude.station_magnitude_type = 'Mb'
            station_magnitude.amplitude_id = amplitude.resource_id
            station_magnitude.waveform_id = pick.waveform_id
            res_id = '/'.join(
                (res_id_prefix, 'magnitude/generic/body_wave_magnitude'))
            station_magnitude.method_id = \
                ResourceIdentifier(id=res_id)
            event.station_magnitudes.append(station_magnitude)
        arrival = Arrival()
        prefix = '/'.join((res_id_prefix, 'arrival', evid, station_string))
        arrival.resource_id = ResourceIdentifier(prefix=prefix)
        arrival.pick_id = pick.resource_id
        arrival.phase = pick.phase_hint
        arrival.azimuth = azimuth
        arrival.distance = distance
        arrival.time_residual = residual
        res_id = '/'.join((res_id_prefix, 'earthmodel/ak135'))
        arrival.earth_model_id = ResourceIdentifier(id=res_id)
        origin.arrivals.append(arrival)
        origin.quality.minimum_distance = min(
            d for d in (arrival.distance, origin.quality.minimum_distance)
            if d is not None)
        origin.quality.maximum_distance = \
            max(arrival.distance, origin.quality.minimum_distance)
        origin.quality.associated_phase_count += 1
        return pick, arrival
示例#13
0
    def relative_magnitudes(self,
                            stream,
                            pre_processed,
                            process_cores=1,
                            ignore_bad_data=False,
                            parallel=False,
                            min_cc=0.4,
                            **kwargs):
        """
        Compute relative magnitudes for the detections.

        Works in place on events in the Family

        :type stream: obspy.core.stream.Stream
        :param stream:
            All the data needed to cut from - can be a gappy Stream.
        :type pre_processed: bool
        :param pre_processed:
            Whether the stream has been pre-processed or not to match the
            templates. See note below.
        :param parallel: Turn parallel processing on or off.
        :type process_cores: int
        :param process_cores:
            Number of processes to use for pre-processing (if different to
            `cores`).
        :type ignore_bad_data: bool
        :param ignore_bad_data:
            If False (default), errors will be raised if data are excessively
            gappy or are mostly zeros. If True then no error will be raised,
            but an empty trace will be returned (and not used in detection).
        :type min_cc: float
        :param min_cc: Minimum correlation for magnitude to be computed.
        :param kwargs:
            Keyword arguments passed to `utils.mag_calc.relative_mags`

        .. Note::
            Note on pre-processing: You can provide a pre-processed stream,
            which may be beneficial for detections over large time periods
            (the stream can have gaps, which reduces memory usage).  However,
            in this case the processing steps are not checked, so you must
            ensure that the template in the Family has the same sampling
            rate and filtering as the stream.
            If pre-processing has not be done then the data will be processed
            according to the parameters in the template.
        """
        processed_stream = self._process_streams(
            stream=stream,
            pre_processed=pre_processed,
            process_cores=process_cores,
            parallel=parallel,
            ignore_bad_data=ignore_bad_data)
        for detection in self.detections:
            event = detection.event
            if event is None:
                continue
            corr_dict = {
                p.waveform_id.get_seed_string():
                float(p.comments[0].text.split("=")[-1])
                for p in event.picks
            }
            template = self.template
            try:
                t_mag = (template.event.preferred_magnitude()
                         or template.event.magnitudes[0])
            except IndexError:
                Logger.info("No template magnitude, relative magnitudes cannot"
                            " be computed for {0}".format(event.resource_id))
                continue
            # Set the signal-window to be the template length
            signal_window = (
                -template.prepick,
                min([tr.stats.npts * tr.stats.delta
                     for tr in template.st]) - template.prepick)
            delta_mag = relative_magnitude(st1=template.st,
                                           st2=processed_stream,
                                           event1=template.event,
                                           event2=event,
                                           correlations=corr_dict,
                                           min_cc=min_cc,
                                           signal_window=signal_window,
                                           **kwargs)
            # Add station magnitudes
            sta_contrib = []
            av_mag = 0.0
            for seed_id, _delta_mag in delta_mag.items():
                sta_mag = StationMagnitude(
                    mag=t_mag.mag + _delta_mag,
                    magnitude_type=t_mag.magnitude_type,
                    method_id=ResourceIdentifier("relative"),
                    waveform_id=WaveformStreamID(seed_string=seed_id),
                    creation_info=CreationInfo(author="EQcorrscan",
                                               creation_time=UTCDateTime()))
                event.station_magnitudes.append(sta_mag)
                sta_contrib.append(
                    StationMagnitudeContribution(
                        station_magnitude_id=sta_mag.resource_id, weight=1.))
                av_mag += sta_mag.mag
            if len(delta_mag) > 0:
                av_mag /= len(delta_mag)
                # Compute average magnitude
                event.magnitudes.append(
                    Magnitude(mag=av_mag,
                              magnitude_type=t_mag.magnitude_type,
                              method_id=ResourceIdentifier("relative"),
                              station_count=len(delta_mag),
                              evaluation_mode="manual",
                              station_magnitude_contributions=sta_contrib,
                              creation_info=CreationInfo(
                                  author="EQcorrscan",
                                  creation_time=UTCDateTime())))
        return self.catalog
示例#14
0
def _read_single_event(event_file, locate_dir, units, local_mag_ph):
    """
    Parse an event file from QuakeMigrate into an obspy Event object.

    Parameters
    ----------
    event_file : `pathlib.Path` object
        Path to .event file to read.
    locate_dir : `pathlib.Path` object
        Path to locate directory (contains "events", "picks" etc. directories).
    units : {"km", "m"}
        Grid projection coordinates for QM LUT (determines units of depths and
        uncertainties in the .event files).
    local_mag_ph : {"S", "P"}
        Amplitude measurement used to calculate local magnitudes.

    Returns
    -------
    event : `obspy.Event` object
        Event object populated with all available information output by
        :class:`~quakemigrate.signal.scan.locate()`, including event locations
        and uncertainties, picks, and amplitudes and magnitudes if available.

    """

    # Parse information from event file
    event_info = pd.read_csv(event_file).iloc[0]
    event_uid = str(event_info["EventID"])

    # Set distance conversion factor (from units of QM LUT projection units).
    if units == "km":
        factor = 1e3
    elif units == "m":
        factor = 1
    else:
        raise AttributeError(f"units must be 'km' or 'm'; not {units}")

    # Create event object to store origin and pick information
    event = Event()
    event.extra = AttribDict()
    event.resource_id = str(event_info["EventID"])
    event.creation_info = CreationInfo(author="QuakeMigrate",
                                       version=quakemigrate.__version__)

    # Add COA info to extra
    event.extra.coa = {"value": event_info["COA"], "namespace": ns}
    event.extra.coa_norm = {"value": event_info["COA_NORM"], "namespace": ns}
    event.extra.trig_coa = {"value": event_info["TRIG_COA"], "namespace": ns}
    event.extra.dec_coa = {"value": event_info["DEC_COA"], "namespace": ns}
    event.extra.dec_coa_norm = {
        "value": event_info["DEC_COA_NORM"],
        "namespace": ns
    }

    # Determine location of cut waveform data - add to event object as a
    # custom extra attribute.
    mseed = locate_dir / "raw_cut_waveforms" / event_uid
    event.extra.cut_waveforms_file = {
        "value": str(mseed.with_suffix(".m").resolve()),
        "namespace": ns
    }
    if (locate_dir / "real_cut_waveforms").exists():
        mseed = locate_dir / "real_cut_waveforms" / event_uid
        event.extra.real_cut_waveforms_file = {
            "value": str(mseed.with_suffix(".m").resolve()),
            "namespace": ns
        }
    if (locate_dir / "wa_cut_waveforms").exists():
        mseed = locate_dir / "wa_cut_waveforms" / event_uid
        event.extra.wa_cut_waveforms_file = {
            "value": str(mseed.with_suffix(".m").resolve()),
            "namespace": ns
        }

    # Create origin with spline location and set to preferred event origin.
    origin = Origin()
    origin.method_id = "spline"
    origin.longitude = event_info["X"]
    origin.latitude = event_info["Y"]
    origin.depth = event_info["Z"] * factor
    origin.time = UTCDateTime(event_info["DT"])
    event.origins = [origin]
    event.preferred_origin_id = origin.resource_id

    # Create origin with gaussian location and associate with event
    origin = Origin()
    origin.method_id = "gaussian"
    origin.longitude = event_info["GAU_X"]
    origin.latitude = event_info["GAU_Y"]
    origin.depth = event_info["GAU_Z"] * factor
    origin.time = UTCDateTime(event_info["DT"])
    event.origins.append(origin)

    ouc = OriginUncertainty()
    ce = ConfidenceEllipsoid()
    ce.semi_major_axis_length = event_info["COV_ErrY"] * factor
    ce.semi_intermediate_axis_length = event_info["COV_ErrX"] * factor
    ce.semi_minor_axis_length = event_info["COV_ErrZ"] * factor
    ce.major_axis_plunge = 0
    ce.major_axis_azimuth = 0
    ce.major_axis_rotation = 0
    ouc.confidence_ellipsoid = ce
    ouc.preferred_description = "confidence ellipsoid"

    # Set uncertainties for both as the gaussian uncertainties
    for origin in event.origins:
        origin.longitude_errors.uncertainty = kilometer2degrees(
            event_info["GAU_ErrX"] * factor / 1e3)
        origin.latitude_errors.uncertainty = kilometer2degrees(
            event_info["GAU_ErrY"] * factor / 1e3)
        origin.depth_errors.uncertainty = event_info["GAU_ErrZ"] * factor
        origin.origin_uncertainty = ouc

    # Add OriginQuality info to each origin?
    for origin in event.origins:
        origin.origin_type = "hypocenter"
        origin.evaluation_mode = "automatic"

    # --- Handle picks file ---
    pick_file = locate_dir / "picks" / event_uid
    if pick_file.with_suffix(".picks").is_file():
        picks = pd.read_csv(pick_file.with_suffix(".picks"))
    else:
        return None

    for _, pickline in picks.iterrows():
        station = str(pickline["Station"])
        phase = str(pickline["Phase"])
        wid = WaveformStreamID(network_code="", station_code=station)

        for method in ["modelled", "autopick"]:
            pick = Pick()
            pick.extra = AttribDict()
            pick.waveform_id = wid
            pick.method_id = method
            pick.phase_hint = phase
            if method == "autopick" and str(pickline["PickTime"]) != "-1":
                pick.time = UTCDateTime(pickline["PickTime"])
                pick.time_errors.uncertainty = float(pickline["PickError"])
                pick.extra.snr = {
                    "value": float(pickline["SNR"]),
                    "namespace": ns
                }
            elif method == "modelled":
                pick.time = UTCDateTime(pickline["ModelledTime"])
            else:
                continue
            event.picks.append(pick)

    # --- Handle amplitudes file ---
    amps_file = locate_dir / "amplitudes" / event_uid
    if amps_file.with_suffix(".amps").is_file():
        amps = pd.read_csv(amps_file.with_suffix(".amps"))

        i = 0
        for _, ampsline in amps.iterrows():
            wid = WaveformStreamID(seed_string=ampsline["id"])
            noise_amp = ampsline["Noise_amp"] / 1000  # mm to m
            for phase in ["P_amp", "S_amp"]:
                amp = Amplitude()
                if pd.isna(ampsline[phase]):
                    continue
                amp.generic_amplitude = ampsline[phase] / 1000  # mm to m
                amp.generic_amplitude_errors.uncertainty = noise_amp
                amp.unit = "m"
                amp.type = "AML"
                amp.method_id = phase
                amp.period = 1 / ampsline[f"{phase[0]}_freq"]
                amp.time_window = TimeWindow(
                    reference=UTCDateTime(ampsline[f"{phase[0]}_time"]))
                # amp.pick_id = ?
                amp.waveform_id = wid
                # amp.filter_id = ?
                amp.magnitude_hint = "ML"
                amp.evaluation_mode = "automatic"
                amp.extra = AttribDict()
                try:
                    amp.extra.filter_gain = {
                        "value": ampsline[f"{phase[0]}_filter_gain"],
                        "namespace": ns
                    }
                    amp.extra.avg_amp = {
                        "value": ampsline[f"{phase[0]}_avg_amp"] / 1000,  # m
                        "namespace": ns
                    }
                except KeyError:
                    pass

                if phase[0] == local_mag_ph and not pd.isna(ampsline["ML"]):
                    i += 1
                    stat_mag = StationMagnitude()
                    stat_mag.extra = AttribDict()
                    # stat_mag.origin_id = ? local_mag_loc
                    stat_mag.mag = ampsline["ML"]
                    stat_mag.mag_errors.uncertainty = ampsline["ML_Err"]
                    stat_mag.station_magnitude_type = "ML"
                    stat_mag.amplitude_id = amp.resource_id
                    stat_mag.extra.picked = {
                        "value": ampsline["is_picked"],
                        "namespace": ns
                    }
                    stat_mag.extra.epi_dist = {
                        "value": ampsline["epi_dist"],
                        "namespace": ns
                    }
                    stat_mag.extra.z_dist = {
                        "value": ampsline["z_dist"],
                        "namespace": ns
                    }

                    event.station_magnitudes.append(stat_mag)

                event.amplitudes.append(amp)

        mag = Magnitude()
        mag.extra = AttribDict()
        mag.mag = event_info["ML"]
        mag.mag_errors.uncertainty = event_info["ML_Err"]
        mag.magnitude_type = "ML"
        # mag.origin_id = ?
        mag.station_count = i
        mag.evaluation_mode = "automatic"
        mag.extra.r2 = {"value": event_info["ML_r2"], "namespace": ns}

        event.magnitudes = [mag]
        event.preferred_magnitude_id = mag.resource_id

    return event
示例#15
0
def write_qml(config, sourcepar):
    if not config.options.qml_file:
        return
    qml_file = config.options.qml_file
    cat = read_events(qml_file)
    evid = config.hypo.evid
    try:
        ev = [e for e in cat if evid in str(e.resource_id)][0]
    except Exception:
        logging.warning('Unable to find evid "{}" in QuakeML file. '
                        'QuakeML output will not be written.'.format(evid))

    origin = ev.preferred_origin()
    if origin is None:
        origin = ev.origins[0]
    origin_id = origin.resource_id
    origin_id_strip = origin_id.id.split('/')[-1]
    origin_id_strip = origin_id_strip.replace(config.smi_strip_from_origin_id,
                                              '')

    # Common parameters
    ssp_version = get_versions()['version']
    method_id = config.smi_base + '/sourcespec/' + ssp_version
    cr_info = CreationInfo()
    cr_info.agency_id = config.agency_id
    if config.author is None:
        author = '{}@{}'.format(getuser(), gethostname())
    else:
        author = config.author
    cr_info.author = author
    cr_info.creation_time = UTCDateTime()

    means = sourcepar.means_weight
    errors = sourcepar.errors_weight
    stationpar = sourcepar.station_parameters

    # Magnitude
    mag = Magnitude()
    _id = config.smi_magnitude_template.replace('$SMI_BASE', config.smi_base)
    _id = _id.replace('$ORIGIN_ID', origin_id_strip)
    mag.resource_id = ResourceIdentifier(id=_id)
    mag.method_id = ResourceIdentifier(id=method_id)
    mag.origin_id = origin_id
    mag.magnitude_type = 'Mw'
    mag.mag = means['Mw']
    mag_err = QuantityError()
    mag_err.uncertainty = errors['Mw']
    mag_err.confidence_level = 68.2
    mag.mag_errors = mag_err
    mag.station_count = len([_s for _s in stationpar.keys()])
    mag.evaluation_mode = 'automatic'
    mag.creation_info = cr_info

    # Seismic moment -- It has to be stored in a MomentTensor object
    # which, in turn, is part of a FocalMechanism object
    mt = MomentTensor()
    _id = config.smi_moment_tensor_template.replace('$SMI_BASE',
                                                    config.smi_base)
    _id = _id.replace('$ORIGIN_ID', origin_id_strip)
    mt.resource_id = ResourceIdentifier(id=_id)
    mt.derived_origin_id = origin_id
    mt.moment_magnitude_id = mag.resource_id
    mt.scalar_moment = means['Mo']
    mt_err = QuantityError()
    mt_err.lower_uncertainty = errors['Mo'][0]
    mt_err.upper_uncertainty = errors['Mo'][1]
    mt_err.confidence_level = 68.2
    mt.scalar_moment_errors = mt_err
    mt.method_id = method_id
    mt.creation_info = cr_info
    # And here is the FocalMechanism object
    fm = FocalMechanism()
    _id = config.smi_focal_mechanism_template.replace('$SMI_BASE',
                                                      config.smi_base)
    _id = _id.replace('$ORIGIN_ID', origin_id_strip)
    fm.resource_id = ResourceIdentifier(id=_id)
    fm.triggering_origin_id = origin_id
    fm.method_id = ResourceIdentifier(id=method_id)
    fm.moment_tensor = mt
    fm.creation_info = cr_info
    ev.focal_mechanisms.append(fm)

    # Station magnitudes
    for statId in sorted(stationpar.keys()):
        par = stationpar[statId]
        st_mag = StationMagnitude()
        seed_id = statId.split()[0]
        _id = config.smi_station_magnitude_template.replace(
            '$SMI_MAGNITUDE_TEMPLATE', config.smi_magnitude_template)
        _id = _id.replace('$ORIGIN_ID', origin_id_strip)
        _id = _id.replace('$SMI_BASE', config.smi_base)
        _id = _id.replace('$WAVEFORM_ID', seed_id)
        st_mag.resource_id = ResourceIdentifier(id=_id)
        st_mag.origin_id = origin_id
        st_mag.mag = par['Mw']
        st_mag.station_magnitude_type = 'Mw'
        st_mag.method_id = mag.method_id
        st_mag.creation_info = cr_info
        st_mag.waveform_id = WaveformStreamID(seed_string=seed_id)
        st_mag.extra = SSPExtra()
        st_mag.extra.moment = SSPTag(par['Mo'])
        st_mag.extra.corner_frequency = SSPTag(par['fc'])
        st_mag.extra.t_star = SSPTag(par['t_star'])
        ev.station_magnitudes.append(st_mag)
        st_mag_contrib = StationMagnitudeContribution()
        st_mag_contrib.station_magnitude_id = st_mag.resource_id
        mag.station_magnitude_contributions.append(st_mag_contrib)
    ev.magnitudes.append(mag)

    # Write other average parameters as custom tags
    ev.extra = SSPExtra()
    ev.extra.corner_frequency = SSPContainerTag()
    ev.extra.corner_frequency.value.value = SSPTag(means['fc'])
    ev.extra.corner_frequency.value.lower_uncertainty =\
        SSPTag(errors['fc'][0])
    ev.extra.corner_frequency.value.upper_uncertainty =\
        SSPTag(errors['fc'][1])
    ev.extra.corner_frequency.value.confidence_level = SSPTag(68.2)
    ev.extra.t_star = SSPContainerTag()
    ev.extra.t_star.value.value = SSPTag(means['t_star'])
    ev.extra.t_star.value.uncertainty = SSPTag(errors['t_star'])
    ev.extra.t_star.value.confidence_level = SSPTag(68.2)
    ev.extra.source_radius = SSPContainerTag()
    ev.extra.source_radius.value.value = SSPTag(means['ra'])
    ev.extra.source_radius.value.lower_uncertainty =\
        SSPTag(errors['ra'][0])
    ev.extra.source_radius.value.upper_uncertainty =\
        SSPTag(errors['ra'][1])
    ev.extra.source_radius.value.confidence_level = SSPTag(68.2)
    ev.extra.stress_drop = SSPContainerTag()
    ev.extra.stress_drop.value.value = SSPTag(means['bsd'])
    ev.extra.stress_drop.value.lower_uncertainty =\
        SSPTag(errors['bsd'][0])
    ev.extra.stress_drop.value.upper_uncertainty =\
        SSPTag(errors['bsd'][1])
    ev.extra.stress_drop.value.confidence_level = SSPTag(68.2)

    if config.set_preferred_magnitude:
        ev.preferred_magnitude_id = mag.resource_id.id

    qml_file_out = os.path.join(config.options.outdir, evid + '.xml')
    ev.write(qml_file_out, format='QUAKEML')
    logging.info('QuakeML file written to: ' + qml_file_out)