Exemplo n.º 1
0
    def _parseRecordS(self, line, event, p_pick, p_arrival):
        """
        Parses the 'secondary phases' record S

        Secondary phases are following phases of the reading,
        and can be P-type or S-type.
        """
        arrivals = []
        phase = line[7:15].strip()
        arrival_time = line[15:24]
        if phase:
            arrivals.append((phase, arrival_time))
        phase = line[25:33].strip()
        arrival_time = line[33:42]
        if phase:
            arrivals.append((phase, arrival_time))
        phase = line[43:51].strip()
        arrival_time = line[51:60]
        if phase:
            arrivals.append((phase, arrival_time))

        evid = event.resource_id.id.split('/')[-1]
        station_string =\
            p_pick.waveform_id.getSEEDString()\
            .replace(' ', '-').replace('.', '_').lower()
        origin = event.origins[0]
        for phase, arrival_time in arrivals:
            if phase[0:2] == 'D=':
                #unused: depth = self._float(phase[2:7])
                try:
                    depth_usage_flag = phase[7]
                except IndexError:
                    #usage flag is not defined
                    depth_usage_flag = None
                #FIXME: I'm not sure that 'X' actually
                #means 'used'
                if depth_usage_flag == 'X':
                    #FIXME: is this enough to say that
                    #the event is constained by depth pahses?
                    origin.depth_type = 'constrained by depth phases'
                    origin.quality.depth_phase_count += 1
            else:
                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 = p_pick.waveform_id
                pick.backazimuth = p_pick.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)
                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 = p_arrival.azimuth
                arrival.distance = p_arrival.distance
                origin.quality.associated_phase_count += 1
                origin.arrivals.append(arrival)
Exemplo n.º 2
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
Exemplo n.º 3
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
def __toPick(parser, pick_el, evaluation_mode):
    """
    """
    pick = Pick()
    pick.resource_id = ResourceIdentifier(prefix="/".join([RESOURCE_ROOT, "pick"]))

    # Raise a warnings if there is a phase delay
    phase_delay = parser.xpath2obj("phase_delay", pick_el, float)
    if phase_delay is not None:
        msg = "The pick has a phase_delay!"
        raise Exception(msg)

    waveform = pick_el.xpath("waveform")[0]
    network = waveform.get("networkCode")
    station = fix_station_name(waveform.get("stationCode"))
    # Map some station names.
    if station in STATION_DICT:
        station = STATION_DICT[station]
    if not network:
        network = NETWORK_DICT[station]

    location = waveform.get("locationCode") or ""
    channel = waveform.get("channelCode") or ""
    pick.waveform_id = WaveformStreamID(
                                network_code=network,
                                station_code=station,
                                channel_code=channel,
                                location_code=location)
    pick.time, pick.time_errors = __toTimeQuantity(parser, pick_el, "time")
    # Picks without time are not quakeml conform
    if pick.time is None:
        print "Pick has no time and is ignored: %s" % station
        return None
    pick.phase_hint = parser.xpath2obj('phaseHint', pick_el, str)
    onset = parser.xpath2obj('onset', pick_el)
    # Fixing bad and old typo ...
    if onset == "implusive":
        onset = "impulsive"
    if onset:
        pick.onset = onset.lower()
    # Evaluation mode of a pick is global in the SeisHub Event file format.
    #pick.evaluation_mode = evaluation_mode
    # The polarity needs to be mapped.
    polarity = parser.xpath2obj('polarity', pick_el)
    pol_map_dict = {'up': 'positive', 'positive': 'positive',
                    'forward': 'positive',
                    'forwards': 'positive',
                    'right': 'positive',
                    'backward': 'negative',
                    'backwards': 'negative',
                    'left': 'negative',
                    'down': 'negative', 'negative': 'negative',
                    'undecidable': 'undecidable',
                    'poorup': 'positive',
                    'poordown': 'negative'}
    if polarity:
        if polarity.lower() in pol_map_dict:
            pick.polarity = pol_map_dict[polarity.lower()]
        else:
            pick.polarity = polarity.lower()

    pick_weight = parser.xpath2obj('weight', pick_el, int)
    if pick_weight is not None:
        pick.extra = AttribDict()
        pick.extra.weight = {'value': pick_weight, 'namespace': NAMESPACE}
    return pick
Exemplo n.º 5
0
def outputOBSPY(hp, event=None, only_fm_picks=False):
    """
    Make an Event which includes the current focal mechanism information from HASH
    
    Use the 'only_fm_picks' flag to only include the picks HASH used for the FocalMechanism.
    This flag will replace the 'picks' and 'arrivals' lists of existing events with new ones.
    
    Inputs
    -------
    hp    : hashpy.HashPype instance
    
    event : obspy.core.event.Event
    
    only_fm_picks : bool of whether to overwrite the picks/arrivals lists
    
    
    Returns
    -------
    obspy.core.event.Event
    
    Event will be new if no event was input, FocalMech added to existing event
    """
    # Returns new (or updates existing) Event with HASH solution
    n = hp.npol
    if event is None:
        event = Event(focal_mechanisms=[], picks=[], origins=[])
        origin = Origin(arrivals=[])
        origin.time = UTCDateTime(hp.tstamp)
        origin.latitude = hp.qlat
        origin.longitude = hp.qlon
        origin.depth = hp.qdep
        origin.creation_info = CreationInfo(version=hp.icusp)
        origin.resource_id = ResourceIdentifier('smi:hash/Origin/{0}'.format(
            hp.icusp))
        for _i in range(n):
            p = Pick()
            p.creation_info = CreationInfo(version=hp.arid[_i])
            p.resource_id = ResourceIdentifier('smi:nsl/Pick/{0}'.format(
                p.creation_info.version))
            p.waveform_id = WaveformStreamID(network_code=hp.snet[_i],
                                             station_code=hp.sname[_i],
                                             channel_code=hp.scomp[_i])
            if hp.p_pol[_i] > 0:
                p.polarity = 'positive'
            else:
                p.polarity = 'negative'
            a = Arrival()
            a.creation_info = CreationInfo(version=hp.arid[_i])
            a.resource_id = ResourceIdentifier('smi:nsl/Arrival/{0}'.format(
                p.creation_info.version))
            a.azimuth = hp.p_azi_mc[_i, 0]
            a.takeoff_angle = 180. - hp.p_the_mc[_i, 0]
            a.pick_id = p.resource_id
            origin.arrivals.append(a)
            event.picks.append(p)
        event.origins.append(origin)
        event.preferred_origin_id = origin.resource_id.resource_id
    else:  # just update the changes
        origin = event.preferred_origin()
        picks = []
        arrivals = []
        for _i in range(n):
            ind = hp.p_index[_i]
            a = origin.arrivals[ind]
            p = a.pick_id.getReferredObject()
            a.takeoff_angle = hp.p_the_mc[_i, 0]
            picks.append(p)
            arrivals.append(a)
        if only_fm_picks:
            origin.arrivals = arrivals
            event.picks = picks
    # Use me double couple calculator and populate planes/axes etc
    x = hp._best_quality_index
    # Put all the mechanisms into the 'focal_mechanisms' list, mark "best" as preferred
    for s in range(hp.nmult):
        dc = DoubleCouple([hp.str_avg[s], hp.dip_avg[s], hp.rak_avg[s]])
        ax = dc.axis
        focal_mech = FocalMechanism()
        focal_mech.creation_info = CreationInfo(creation_time=UTCDateTime(),
                                                author=hp.author)
        focal_mech.triggering_origin_id = origin.resource_id
        focal_mech.resource_id = ResourceIdentifier(
            'smi:hash/FocalMechanism/{0}/{1}'.format(hp.icusp, s + 1))
        focal_mech.method_id = ResourceIdentifier('HASH')
        focal_mech.nodal_planes = NodalPlanes()
        focal_mech.nodal_planes.nodal_plane_1 = NodalPlane(*dc.plane1)
        focal_mech.nodal_planes.nodal_plane_2 = NodalPlane(*dc.plane2)
        focal_mech.principal_axes = PrincipalAxes()
        focal_mech.principal_axes.t_axis = Axis(azimuth=ax['T']['azimuth'],
                                                plunge=ax['T']['dip'])
        focal_mech.principal_axes.p_axis = Axis(azimuth=ax['P']['azimuth'],
                                                plunge=ax['P']['dip'])
        focal_mech.station_polarity_count = n
        focal_mech.azimuthal_gap = hp.magap
        focal_mech.misfit = hp.mfrac[s]
        focal_mech.station_distribution_ratio = hp.stdr[s]
        focal_mech.comments.append(
            Comment(
                hp.qual[s],
                resource_id=ResourceIdentifier(
                    focal_mech.resource_id.resource_id + '/comment/quality')))
        #----------------------------------------
        event.focal_mechanisms.append(focal_mech)
        if s == x:
            event.preferred_focal_mechanism_id = focal_mech.resource_id.resource_id
    return event
Exemplo n.º 6
0
    def _parse_record_s(self, line, event, p_pick, p_arrival):
        """
        Parses the 'secondary phases' record S

        Secondary phases are following phases of the reading,
        and can be P-type or S-type.
        """
        arrivals = []
        phase = line[7:15].strip()
        arrival_time = line[15:24]
        if phase:
            arrivals.append((phase, arrival_time))
        phase = line[25:33].strip()
        arrival_time = line[33:42]
        if phase:
            arrivals.append((phase, arrival_time))
        phase = line[43:51].strip()
        arrival_time = line[51:60]
        if phase:
            arrivals.append((phase, arrival_time))

        evid = event.resource_id.id.split('/')[-1]
        station_string = \
            p_pick.waveform_id.get_seed_string()\
            .replace(' ', '-').replace('.', '_').lower()
        origin = event.origins[0]
        for phase, arrival_time in arrivals:
            if phase[0:2] == 'D=':
                # unused: depth = self._float(phase[2:7])
                try:
                    depth_usage_flag = phase[7]
                except IndexError:
                    # usage flag is not defined
                    depth_usage_flag = None
                # FIXME: I'm not sure that 'X' actually
                # means 'used'
                if depth_usage_flag == 'X':
                    # FIXME: is this enough to say that
                    # the event is constrained by depth phases?
                    origin.depth_type = 'constrained by depth phases'
                    origin.quality.depth_phase_count += 1
            else:
                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 = p_pick.waveform_id
                pick.backazimuth = p_pick.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)
                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 = p_arrival.azimuth
                arrival.distance = p_arrival.distance
                origin.quality.associated_phase_count += 1
                origin.arrivals.append(arrival)
Exemplo n.º 7
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]
                    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
Exemplo n.º 8
0
    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
Exemplo n.º 9
0
def outputOBSPY(hp, event=None, only_fm_picks=False):
    """
    Make an Event which includes the current focal mechanism information from HASH
    
    Use the 'only_fm_picks' flag to only include the picks HASH used for the FocalMechanism.
    This flag will replace the 'picks' and 'arrivals' lists of existing events with new ones.
    
    Inputs
    -------
    hp    : hashpy.HashPype instance
    
    event : obspy.core.event.Event
    
    only_fm_picks : bool of whether to overwrite the picks/arrivals lists
    
    
    Returns
    -------
    obspy.core.event.Event
    
    Event will be new if no event was input, FocalMech added to existing event
    """
    # Returns new (or updates existing) Event with HASH solution
    n = hp.npol
    if event is None:
	event = Event(focal_mechanisms=[], picks=[], origins=[])
	origin = Origin(arrivals=[])
	origin.time = UTCDateTime(hp.tstamp)
	origin.latitude = hp.qlat
	origin.longitude = hp.qlon
	origin.depth = hp.qdep
	origin.creation_info = CreationInfo(version=hp.icusp)
	origin.resource_id = ResourceIdentifier('smi:hash/Origin/{0}'.format(hp.icusp))
	for _i in range(n):
	    p = Pick()
	    p.creation_info = CreationInfo(version=hp.arid[_i])
	    p.resource_id = ResourceIdentifier('smi:hash/Pick/{0}'.format(p.creation_info.version))
	    p.waveform_id = WaveformStreamID(network_code=hp.snet[_i], station_code=hp.sname[_i], channel_code=hp.scomp[_i])
	    if hp.p_pol[_i] > 0:
		p.polarity = 'positive'
	    else:
		p.polarity = 'negative'
	    a = Arrival()
	    a.creation_info = CreationInfo(version=hp.arid[_i])
	    a.resource_id = ResourceIdentifier('smi:hash/Arrival/{0}'.format(p.creation_info.version))
	    a.azimuth = hp.p_azi_mc[_i,0]
	    a.takeoff_angle = 180. - hp.p_the_mc[_i,0]
	    a.pick_id = p.resource_id
	    origin.arrivals.append(a)
	    event.picks.append(p)
	event.origins.append(origin)
	event.preferred_origin_id = str(origin.resource_id)
    else: # just update the changes
	origin = event.preferred_origin()
	picks = []
	arrivals = []
	for _i in range(n):
	    ind = hp.p_index[_i]
	    a = origin.arrivals[ind]
	    p = a.pick_id.getReferredObject()
	    a.takeoff_angle = hp.p_the_mc[_i,0]
	    picks.append(p)
	    arrivals.append(a)
	if only_fm_picks:
	    origin.arrivals = arrivals
	    event.picks = picks
    # Use me double couple calculator and populate planes/axes etc
    x = hp._best_quality_index
    # Put all the mechanisms into the 'focal_mechanisms' list, mark "best" as preferred
    for s in range(hp.nmult):
        dc = DoubleCouple([hp.str_avg[s], hp.dip_avg[s], hp.rak_avg[s]])
        ax = dc.axis
        focal_mech = FocalMechanism()
        focal_mech.creation_info = CreationInfo(creation_time=UTCDateTime(), author=hp.author)
        focal_mech.triggering_origin_id = origin.resource_id
        focal_mech.resource_id = ResourceIdentifier('smi:hash/FocalMechanism/{0}/{1}'.format(hp.icusp, s+1))
        focal_mech.method_id = ResourceIdentifier('HASH')
        focal_mech.nodal_planes = NodalPlanes()
        focal_mech.nodal_planes.nodal_plane_1 = NodalPlane(*dc.plane1)
        focal_mech.nodal_planes.nodal_plane_2 = NodalPlane(*dc.plane2)
        focal_mech.principal_axes = PrincipalAxes()
        focal_mech.principal_axes.t_axis = Axis(azimuth=ax['T']['azimuth'], plunge=ax['T']['dip'])
        focal_mech.principal_axes.p_axis = Axis(azimuth=ax['P']['azimuth'], plunge=ax['P']['dip'])
        focal_mech.station_polarity_count = n
        focal_mech.azimuthal_gap = hp.magap
        focal_mech.misfit = hp.mfrac[s]
        focal_mech.station_distribution_ratio = hp.stdr[s]
        focal_mech.comments.append(
            Comment(hp.qual[s], resource_id=ResourceIdentifier(str(focal_mech.resource_id) + '/comment/quality'))
            )
        #----------------------------------------
        event.focal_mechanisms.append(focal_mech)
        if s == x:
            event.preferred_focal_mechanism_id = str(focal_mech.resource_id)
    return event
Exemplo n.º 10
0
    weight=float(line[14:18])
    _phase_hint=line[19:21].strip()
    
    abs_time=time_origin+tt
    
    _waveform_id = WaveformStreamID(station_code=_station_code)
    
    ### Put into Pick object
    
    pick=Pick(waveform_id=_waveform_id, phase_hint=_phase_hint,
                   time=abs_time, method_id=_method_id, evaluation_mode=_evaluation_mode)
    
    ### Rename pick ID
    
    _pick_id=pick.time.isoformat()+'-'+str(pick.method_id)+'-'+pick.phase_hint+'-'+\
    pick.waveform_id.get_seed_string()
    pick.resource_id=_pick_id
    
    ### Put into Arrival object
    
    arrival=Arrival(pick_id=pick.resource_id, phase=pick.phase_hint)
    arrival.time_weight=weight
    
    ### Append to event
    

    new_event.picks.append(pick)
    
#    return new_event
    
Exemplo n.º 11
0
def __toPick(parser, pick_el, evaluation_mode):
    """
    """
    pick = Pick()
    pick.resource_id = ResourceIdentifier(
        prefix="/".join([RESOURCE_ROOT, "pick"]))

    # Raise a warnings if there is a phase delay
    phase_delay = parser.xpath2obj("phase_delay", pick_el, float)
    if phase_delay is not None:
        msg = "The pick has a phase_delay!"
        raise Exception(msg)

    waveform = pick_el.xpath("waveform")[0]
    network = waveform.get("networkCode")
    station = fix_station_name(waveform.get("stationCode"))
    # Map some station names.
    if station in STATION_DICT:
        station = STATION_DICT[station]
    if not network:
        network = NETWORK_DICT[station]

    location = waveform.get("locationCode") or ""
    channel = waveform.get("channelCode") or ""
    pick.waveform_id = WaveformStreamID(network_code=network,
                                        station_code=station,
                                        channel_code=channel,
                                        location_code=location)
    pick.time, pick.time_errors = __toTimeQuantity(parser, pick_el, "time")
    # Picks without time are not quakeml conform
    if pick.time is None:
        print "Pick has no time and is ignored: %s" % station
        return None
    pick.phase_hint = parser.xpath2obj('phaseHint', pick_el, str)
    onset = parser.xpath2obj('onset', pick_el)
    # Fixing bad and old typo ...
    if onset == "implusive":
        onset = "impulsive"
    if onset:
        pick.onset = onset.lower()
    # Evaluation mode of a pick is global in the SeisHub Event file format.
    #pick.evaluation_mode = evaluation_mode
    # The polarity needs to be mapped.
    polarity = parser.xpath2obj('polarity', pick_el)
    pol_map_dict = {
        'up': 'positive',
        'positive': 'positive',
        'forward': 'positive',
        'forwards': 'positive',
        'right': 'positive',
        'backward': 'negative',
        'backwards': 'negative',
        'left': 'negative',
        'down': 'negative',
        'negative': 'negative',
        'undecidable': 'undecidable',
        'poorup': 'positive',
        'poordown': 'negative'
    }
    if polarity:
        if polarity.lower() in pol_map_dict:
            pick.polarity = pol_map_dict[polarity.lower()]
        else:
            pick.polarity = polarity.lower()

    pick_weight = parser.xpath2obj('weight', pick_el, int)
    if pick_weight is not None:
        pick.extra = AttribDict()
        pick.extra.weight = {'value': pick_weight, 'namespace': NAMESPACE}
    return pick
Exemplo n.º 12
0
    def _map_join2phase(self, db):
        """
        Return an obspy Arrival and Pick from an dict of CSS key/values
        corresponding to one record. See the 'Join' section for the implied
        database table join expected.
        
        Inputs
        ======
        db : dict of key/values of CSS fields related to the phases (see Join)

        Returns
        =======
        obspy.core.event.Pick, obspy.core.event.Arrival

        Notes
        =====
        Any object that supports the dict 'get' method can be passed as
        input, e.g. OrderedDict, custom classes, etc.
        
        Join
        ----
        assoc <- arrival <- affiliation (outer) <- schanloc [sta chan] (outer)
        
        """
        p = Pick()
        p.time = _utc(db.get('time'))
        def_net = self.agency[:2].upper()
        css_sta = db.get('sta')
        css_chan = db.get('chan')
        p.waveform_id = WaveformStreamID(
            station_code = db.get('fsta') or css_sta, 
            channel_code = db.get('fchan') or css_chan,
            network_code = db.get('snet') or def_net,
            location_code = db.get('loc'),
            )
        p.horizontal_slowness = db.get('slow')
        #p.horizontal_slowness_errors = self._create_dict(db, 'delslo')
        p.backazimuth = db.get('azimuth')
        #p.backazimuth_errors = self._create_dict(db, 'delaz')
        
        on_qual = _str(db.get('qual')).lower()
        if 'i' in on_qual:
            p.onset = "impulsive"
        elif 'e' in on_qual:
            p.onset = "emergent"
        elif 'w' in on_qual:
            p.onset = "questionable"
        else:
            p.onset =  None
        
        p.phase_hint = db.get('iphase')
        
        pol = _str(db.get('fm')).lower()
        if 'c' in pol or 'u' in pol:
            p.polarity = "positive"
        elif 'd' in pol or 'r' in pol:
            p.polarity = "negative"
        elif '.' in pol:
            p.polarity = "undecidable"
        else:
            p.polarity = None
        
        p.evaluation_mode = "automatic"
        if 'orbassoc' not in _str(db.get('auth')):
            p.evaluation_mode = "manual"
        
        p.evaluation_status = "preliminary"
        if p.evaluation_mode is "manual":
            p.evaluation_status = "reviewed"
        
        p.creation_info = CreationInfo(
            version = db.get('arid'), 
            creation_time = _utc(db.get('arrival.lddate')), 
            agency_id = self.agency, 
            author = db.get('auth'),
            )

        p.resource_id = self._rid(p)

        a = Arrival()
        a.pick_id = ResourceIdentifier(str(p.resource_id), referred_object=p)
        a.phase = db.get('phase')
        a.azimuth = db.get('esaz')
        a.distance = db.get('delta')
        a.takeoff_angle = db.get('ema')
        #a.takeoff_angle_errors = self._create_dict(db, 'emares')
        a.time_residual = db.get('timeres')
        a.horizontal_slowness_residual = db.get('slores')
        a.time_weight = db.get('wgt')
        a.earth_model_id = ResourceIdentifier(self._prefix+'/VelocityModel/'+_str(db.get('vmodel')))
        a.creation_info = CreationInfo(
            version = db.get('arid'), 
            creation_time = _utc(db.get('lddate')),
            agency_id = self.agency,
            )
        a.extra = {}
        a.extra['timedef'] = {
            'value': _str(db.get('timedef')), 
            'namespace': CSS_NAMESPACE
            }
        a.resource_id = self._rid(a)
        return p, a