Beispiel #1
0
        def match(self, lat, lon):
            if self.bBox is not None:
                b = self.bBox
                if b.minLat is not None and lat < b.minLat:
                    return False
                if b.maxLat is not None and lat > b.maxLat:
                    return False
                # date line crossing if minLon > maxLon
                if b.dateLineCrossing():
                    return lon >= b.minLon or lon <= b.maxLon
                if b.minLon is not None and lon < b.minLon:
                    return False
                if b.maxLon is not None and lon > b.maxLon:
                    return False
                return True
            elif self.bCircle:
                c = self.bCircle
                dist = Math.delazi(c.lat, c.lon, lat, lon)
                if c.minRad is not None and dist[0] < c.minRad:
                    return False
                if c.maxRad is not None and dist[0] > c.maxRad:
                    return False
                return True

            return False
Beispiel #2
0
		def match(self, lat, lon):
			if self.bBox:
				b = self.bBox
				if b.minLat and lat < b.minLat: return False
				if b.maxLat and lat > b.maxLat: return False
				# date line crossing if minLon > maxLon
				if b.dateLineCrossing():
					return lon >= b.minLon or lon <= b.maxLon
				if b.minLon and lon < b.minLon: return False
				if b.maxLat and lon > b.maxLon: return False
				return True
			elif self.bCircle:
				c = self.bCircle
				dist = Math.delazi(c.lat, c.lon, lat, lon)
				return dist[0] <= c.maxRad and (
				       not c.minRad or dist[0] >= c.minRad)

			return False
Beispiel #3
0
		def match(self, lat, lon):
			if self.bBox is not None:
				b = self.bBox
				if b.minLat is not None and lat < b.minLat: return False
				if b.maxLat is not None and lat > b.maxLat: return False
				# date line crossing if minLon > maxLon
				if b.dateLineCrossing():
					return lon >= b.minLon or lon <= b.maxLon
				if b.minLon is not None and lon < b.minLon: return False
				if b.maxLon is not None and lon > b.maxLon: return False
				return True
			elif self.bCircle:
				c = self.bCircle
				dist = Math.delazi(c.lat, c.lon, lat, lon)
				if c.minRad is not None and dist[0] < c.minRad: return False
				if c.maxRad is not None and dist[0] > c.maxRad: return False
				return True

			return False
Beispiel #4
0
    def getQuery(self, params):
        """Get a list of streams that satisfies the input parameters.

        This method is public and appends the necessary
        information to the streams that belong to the stations
        actually selected by __selectStations. It contains many
        columns, as it is the list to show in the construction of
        the request package.

        """

        try:
            start_year = int(params.get('start', 1980))
        except (TypeError, ValueError):
            raise wsgicomm.WIClientError, 'Error! Start year is invalid.'

        start_date = datetime.datetime(start_year, 1, 1, 0, 0, 0)

        # Build the end date in datetime format
        # Only year-wide windows are allowed here.
        try:
            end_year = int(params.get('end', datetime.datetime.now().year))
        except:
            raise wsgicomm.WIClientError, 'Error! End year is invalid.'

        end_date = datetime.datetime(end_year, 12, 31, 23, 59, 59)

        # Get the network
        # network = params.get('network')

        # Get the station
        station = params.get('station')

        # Get the sensortype
        sensortype = params.get('sensortype')
        if sensortype == 'all':
            sensortype = None

        # Get the preferred sample rate
        try:
            preferredsps = float(params.get('preferredsps'))
        except:
            preferredsps = None

        # Split the list of streams if any
        try:
            streams = params.get('streams').split(',')
        except wsgicomm.WIError:
            raise
        except:
            streams = None

        # Look at the attributes associated with every network type
        try:
            networktype = params.get('networktype')

            if (networktype == 'all') or (networktype is None):
                networktype = None
            else:
                for nettype in self.nettypes:
                    if networktype == nettype[0]:
                        break
                else:
                    raise Exception

        except:
            msg = 'Wrong value in parameter "networktype"'
            raise wsgicomm.WIClientError, msg

        # Check for latitude and longitude parameters
        try:
            latmin = float(params.get('minlat')) if 'minlat' \
                in params else None
        except (TypeError, ValueError):
            msg = 'Error: minlat must be a float number.'
            raise wsgicomm.WIClientError, msg

        try:
            latmax = float(params.get('maxlat')) if 'maxlat' \
                in params else None
        except (TypeError, ValueError):
            msg = 'Error: maxlat must be a float number.'
            raise wsgicomm.WIClientError, msg

        try:
            lonmin = float(params.get('minlon')) if 'minlon' \
                in params else None
        except (TypeError, ValueError):
            msg = 'Error: minlon must be a float number.'
            raise wsgicomm.WIClientError, msg

        try:
            lonmax = float(params.get('maxlon')) if 'maxlon' \
                in params else None
        except (TypeError, ValueError):
            msg = 'Error: maxlon must be a float number.'
            raise wsgicomm.WIClientError, msg

        # Check for radius and azimuth parameters
        try:
            minradius = float(params.get('minradius')) if 'minradius' \
                in params else None
        except (TypeError, ValueError):
            msg = 'Error: minradius must be a float number.'
            raise wsgicomm.WIClientError, msg

        try:
            maxradius = float(params.get('maxradius')) if 'maxradius' \
                in params else None
        except (TypeError, ValueError):
            msg = 'Error: maxradius must be a float number.'
            raise wsgicomm.WIClientError, msg

        try:
            minazimuth = float(params.get('minazimuth')) if 'minazimuth' \
                in params else None
        except (TypeError, ValueError):
            msg = 'Error: minazimuth must be a float number.'
            raise wsgicomm.WIClientError, msg

        try:
            maxazimuth = float(params.get('maxazimuth')) if 'maxazimuth' \
                in params else None
        except (TypeError, ValueError):
            msg = 'Error: maxazimuth must be a float number.'
            raise wsgicomm.WIClientError, msg

        try:
            events = params.get('events', None)
        except:
            events = None

        # Try to check parameters for different modes of selecting stations
        # One or all stations have been selected and also lat/lon parameters
        if station and (latmin is not None or latmax is not None
                        or lonmin is not None or lonmax is not None):
            msg = 'Error: station and lat/lon parameters are incompatible.'
            raise wsgicomm.WIClientError, msg

        # One or all stations have been selected and also radius/azimuth params
        if station and (minradius is not None or maxradius is not None
                        or minazimuth is not None or maxazimuth is not None):
            msg = 'Error: station and radius/azimuth parameters are ' + \
                'incompatible.'
            raise wsgicomm.WIClientError, msg

        # Lat/lon parameters have been selected and also radius/azimuth
        if (latmin is not None or latmax is not None or lonmin is not None
                or lonmax is not None) and (minradius is not None
                                            or maxradius is not None
                                            or minazimuth is not None
                                            or maxazimuth is not None):
            msg = 'Error: lat/lon and radius/azimuth parameters are ' + \
                'incompatible.'
            raise wsgicomm.WIClientError, msg

        # These are the two lists to return
        stats = []

        # Filter and save indexes of stations in statsOK
        statsOK = self.__selectStations(params)

        # Just to make notation shorter
        ptNets = self.networks
        ptStats = self.stations

        if ('station' in params):
            # Builds a list from the selected stations
            for st in statsOK:
                parent_net = ptStats[st][0]

                (loc_ch,
                 restricted) = self.__buildStreamsList(st, streams, sensortype,
                                                       preferredsps,
                                                       start_date, end_date)

                if len(loc_ch):
                    stats.append(
                        ('%s-%s-%s-%s%s%s' %
                         (ptNets[parent_net][0], ptNets[parent_net][4],
                          ptStats[st][4], ptStats[st][8].year,
                          ptStats[st][8].month, ptStats[st][8].day),
                         ptNets[parent_net][0], ptStats[st][4], ptStats[st][5],
                         ptStats[st][6], ptNets[parent_net][7],
                         ptNets[parent_net][8], ptNets[parent_net][9],
                         ptNets[parent_net][10], loc_ch, restricted))

        elif (latmin is not None and latmax is not None and lonmin is not None
              and lonmax is not None):

            # statsOK is a set and therefore, there will be no repetitions
            for st in statsOK:
                # Pointer to the parent network
                parent_net = ptStats[st][0]

                # Filter by latitude
                if (ptStats[st][5] < latmin) or (ptStats[st][5] > latmax):
                    continue

                # Filter by longitude
                if (lonmin <= lonmax):
                    if (ptStats[st][6] < lonmin) or (ptStats[st][6] > lonmax):
                        continue
                else:
                    if (ptStats[st][6] < lonmin) and (ptStats[st][6] > lonmax):
                        continue

                (loc_ch,
                 restricted) = self.__buildStreamsList(st, streams, sensortype,
                                                       preferredsps,
                                                       start_date, end_date)

                if len(loc_ch):
                    stats.append(
                        ('%s-%s-%s-%s%s%s' %
                         (ptNets[parent_net][0], ptNets[parent_net][4],
                          ptStats[st][4], ptStats[st][8].year,
                          ptStats[st][8].month, ptStats[st][8].day),
                         ptNets[parent_net][0], ptStats[st][4], ptStats[st][5],
                         ptStats[st][6], ptNets[parent_net][7],
                         ptNets[parent_net][8], ptNets[parent_net][9],
                         ptNets[parent_net][10], loc_ch, restricted))

        elif events is not None:

            events = json.loads(events)

            for st in statsOK:
                # Pointer to the parent network
                parent_net = ptStats[st][0]

                # Retrieve latitude and longitude of station
                slat = ptStats[st][5]
                slon = ptStats[st][6]

                for evt in events:
                    # Retrieve latitude and longitude of event
                    lat = evt[0]
                    lon = evt[1]

                    # Calculate radial distance and azimuth
                    (dist, azi, other) = Math.delazi(slat, slon, lat, lon)

                    if (minradius < dist) and (dist < maxradius) and \
                       (minazimuth < azi) and (azi < maxazimuth):
                        (loc_ch, restricted) = \
                            self.__buildStreamsList(st, streams, sensortype,
                                                    preferredsps, start_date,
                                                    end_date)

                        if len(loc_ch):
                            stats.append(
                                ('%s-%s-%s-%s%s%s' %
                                 (ptNets[parent_net][0], ptNets[parent_net][4],
                                  ptStats[st][4], ptStats[st][8].year,
                                  ptStats[st][8].month, ptStats[st][8].day),
                                 ptNets[parent_net][0], ptStats[st][4],
                                 ptStats[st][5], ptStats[st][6],
                                 ptStats[st][11], ptNets[parent_net][8],
                                 ptNets[parent_net][9], ptNets[parent_net][10],
                                 loc_ch, restricted))

                        # Stop the loop through events and go for the
                        # next station
                        break

        else:
            msg = 'Error: not enough parameters have been given.'
            raise wsgicomm.WIClientError, msg

        stats.sort()

        stats.insert(0, ('key', 'netcode', 'statcode', 'latitude', 'longitude',
                         'restricted', 'netclass', 'archive', 'netoperator',
                         'streams', 'streams_restricted'))

        return stats
Beispiel #5
0
    def __timewindows_ev(self, streams, events, startphase, startoffset,
                         endphase, endoffset):
        """Helper function to calculate time windows related to events.

        Input: streams={list of stream keys}
               events={list of events} # [[lat, lon, depth, time],..]
               startphase={string}     # 'P' or 'S'
               startoffset={int}       # time in minutes to start time window.
                                       # POSITIVE if AFTER arrival of
                                       # 'startphase' at station.
               endphase={string}       # 'P' or 'S'
               endoffset={int}         # time in minutes to end time window.
                                       # POSITIVE if AFTER arrival of
                                       # 'endphase' at station.

        Output: list of start/end times per stream, AND estimated data volume,
                (start_time, end_time, net, sta, cha, loc, streamInfo['size'])

        NOTE 1: stream is a list of [net, sta, cha, loc] instead of nslc here!
        NOTE 2: There are many redundant time window computations for multiple
        streams at the same location
        """

        result = []

        for ev in events:
            try:
                if len(ev) != 4:
                    raise wsgicomm.WIClientError, "invalid event: " + str(ev)

                ev_lat = float(ev[0])
                ev_lon = float(ev[1])
                ev_dep = float(ev[2])
                ev_time = DateTimeAttr().fromxml(ev[3])

            except (TypeError, ValueError):
                raise wsgicomm.WIClientError, "invalid event: " + str(ev)

            for nscl in streams:
                try:
                    if len(nscl) != 4:
                        msg = "Invalid stream: " + str(nscl)
                        raise wsgicomm.WIClientError, msg

                    net = str(nscl[0])
                    sta = str(nscl[1])
                    cha = str(nscl[2])
                    loc = str(nscl[3])

                except (TypeError, ValueError):
                    msg = "Invalid stream: " + str(nscl)
                    raise wsgicomm.WIClientError, msg

                # we don't have actual time window yet, just use ev_time to
                # get the coordinates
                streamInfo = self.ic.getStreamInfo(ev_time, ev_time, net, sta,
                                                   cha, loc)

                if streamInfo is None:  # stream is not available
                    continue

                st_lat = streamInfo['latitude']
                st_lon = streamInfo['longitude']
                st_alt = streamInfo['elevation']

                start_time = None
                end_time = None

                # Assumption here is that compute() returns phases sorted by
                # time. Therefore breaking after the first gives the earliest
                # phase in the set defined in __isphase().
                # FIXME: Combine startphase and endphase logic into
                # function+loop?

                # Compute in delta the distance between event and station
                delta = Math.delazi(ev_lat, ev_lon, st_lat, st_lon)[0]
                # Threshold distance in degrees at which PKP arrives earlier
                # than P and friends (see Joachim's email - 14.08.2013)
                delta_threshold = 120

                try:
                    ttlist = self.ttt.compute(ev_lat, ev_lon, ev_dep, st_lat,
                                              st_lon, st_alt)
                except Exception, e:
                    msg = "/metadata/timewindows: exception from " + \
                        "ttt.compute(): " + str(e)
                    logs.error(msg)
                    continue

                try:
                    for tt in ttlist:
                        if (startphase == 'P') and (delta >= delta_threshold):
                            if (tt.phase.startswith('PKP')
                                    or tt.phase.startswith('PKiKP')):
                                start_time = ev_time + \
                                    datetime.timedelta(seconds=tt.time +
                                                       startoffset * 60)
                                break

                        elif ((startphase == 'S')
                              or ((startphase == 'P') and
                                  (delta < delta_threshold))):
                            if self.__isphase(tt.phase, startphase):
                                start_time = ev_time + datetime.timedelta(
                                    seconds=tt.time + startoffset * 60)
                                break
                        elif (startphase == 'OT'):
                            start_time = ev_time + datetime.timedelta(
                                seconds=startoffset * 60)
                        else:
                            msg = 'Wrong startphase received! Only "P", ' + \
                                '"S" and "OT" are implemented.'
                            raise wsgicomm.WIClientError, msg

                    for tt in ttlist:
                        if (endphase == 'P') and (delta >= delta_threshold):
                            if (tt.phase.startswith('PKP')
                                    or tt.phase.startswith('PKiKP')):
                                end_time = ev_time + datetime.timedelta(
                                    seconds=tt.time + endoffset * 60)
                                break

                        elif ((endphase == 'S')
                              or ((endphase == 'P') and
                                  (delta < delta_threshold))):
                            if self.__isphase(tt.phase, endphase):
                                end_time = ev_time + datetime.timedelta(
                                    seconds=tt.time + endoffset * 60)
                                break
                        elif (endphase == 'OT'):
                            end_time = ev_time + datetime.timedelta(
                                seconds=endoffset * 60)
                        else:
                            msg = 'Wrong endphase received! Only "P", ' + \
                                '"S" and "OT" are implemented.'
                            raise wsgicomm.WIClientError, msg

                except Exception, e:
                    logs.error("/metadata/timewindows: " + str(e))
                    continue

                if start_time is None:
                    msg = "/metadata/timewindows: did not find startphase " \
                        + "'%s' for %s" % (startphase, str((ev_lat, ev_lon,
                                                            ev_dep, st_lat,
                                                            st_lon, st_alt)))
                    logs.error(msg)

                if end_time is None:
                    msg = "/metadata/timewindows: did not find endphase " \
                        + "'%s' for %s" % (endphase, str((ev_lat, ev_lon,
                                                          ev_dep, st_lat,
                                                          st_lon, st_alt)))
                    logs.error(msg)

                if start_time is not None and end_time is not None:
                    # retry with actual time window
                    streamInfo = self.ic.getStreamInfo(start_time, end_time,
                                                       net, sta, cha, loc)

                    if streamInfo:
                        result.append((start_time, end_time, net, sta, cha,
                                       loc, streamInfo['size']))

                        if len(result) > self.max_lines:
                            msg = "Maximum request size exceeded"
                            raise wsgicomm.WIClientError, msg
Beispiel #6
0
    def getQuery(self, params):
        """Get a list of streams that satisfies the input parameters.

        This method is public and appends the necessary
        information to the streams that belong to the stations
        actually selected by __selectStations. It contains many
        columns, as it is the list to show in the construction of
        the request package.

        """

        try:
            start_year = int(params.get('start', 1980))
        except (TypeError, ValueError):
            raise wsgicomm.WIClientError, 'Error! Start year is invalid.'

        start_date = datetime.datetime(start_year, 1, 1, 0, 0, 0)

        # Build the end date in datetime format
        # Only year-wide windows are allowed here.
        try:
            end_year = int(params.get('end', datetime.datetime.now().year))
        except:
            raise wsgicomm.WIClientError, 'Error! End year is invalid.'

        end_date = datetime.datetime(end_year, 12, 31, 23, 59, 59)

        # Get the network
        # network = params.get('network')

        # Get the station
        station = params.get('station')

        # Get the sensortype
        sensortype = params.get('sensortype')
        if sensortype == 'all':
            sensortype = None

        # Get the preferred sample rate
        try:
            preferredsps = float(params.get('preferredsps'))
        except:
            preferredsps = None

        # Split the list of streams if any
        try:
            streams = params.get('streams').split(',')
        except wsgicomm.WIError:
            raise
        except:
            streams = None

        # Look at the attributes associated with every network type
        try:
            networktype = params.get('networktype')

            if (networktype == 'all') or (networktype is None):
                networktype = None
            else:
                for nettype in self.nettypes:
                    if networktype == nettype[0]:
                        break
                else:
                    raise Exception

        except:
            msg = 'Wrong value in parameter "networktype"'
            raise wsgicomm.WIClientError, msg

        # Check for latitude and longitude parameters
        try:
            latmin = float(params.get('minlat')) if 'minlat' \
                in params else None
        except (TypeError, ValueError):
            msg = 'Error: minlat must be a float number.'
            raise wsgicomm.WIClientError, msg

        try:
            latmax = float(params.get('maxlat')) if 'maxlat' \
                in params else None
        except (TypeError, ValueError):
            msg = 'Error: maxlat must be a float number.'
            raise wsgicomm.WIClientError, msg

        try:
            lonmin = float(params.get('minlon')) if 'minlon' \
                in params else None
        except (TypeError, ValueError):
            msg = 'Error: minlon must be a float number.'
            raise wsgicomm.WIClientError, msg

        try:
            lonmax = float(params.get('maxlon')) if 'maxlon' \
                in params else None
        except (TypeError, ValueError):
            msg = 'Error: maxlon must be a float number.'
            raise wsgicomm.WIClientError, msg

        # Check for radius and azimuth parameters
        try:
            minradius = float(params.get('minradius')) if 'minradius' \
                in params else None
        except (TypeError, ValueError):
            msg = 'Error: minradius must be a float number.'
            raise wsgicomm.WIClientError, msg

        try:
            maxradius = float(params.get('maxradius')) if 'maxradius' \
                in params else None
        except (TypeError, ValueError):
            msg = 'Error: maxradius must be a float number.'
            raise wsgicomm.WIClientError, msg

        try:
            minazimuth = float(params.get('minazimuth')) if 'minazimuth' \
                in params else None
        except (TypeError, ValueError):
            msg = 'Error: minazimuth must be a float number.'
            raise wsgicomm.WIClientError, msg

        try:
            maxazimuth = float(params.get('maxazimuth')) if 'maxazimuth' \
                in params else None
        except (TypeError, ValueError):
            msg = 'Error: maxazimuth must be a float number.'
            raise wsgicomm.WIClientError, msg

        try:
            events = params.get('events', None)
        except:
            events = None

        # Try to check parameters for different modes of selecting stations
        # One or all stations have been selected and also lat/lon parameters
        if station and (latmin is not None or latmax is not None or lonmin is
                        not None or lonmax is not None):
            msg = 'Error: station and lat/lon parameters are incompatible.'
            raise wsgicomm.WIClientError, msg

        # One or all stations have been selected and also radius/azimuth params
        if station and (minradius is not None or maxradius is not None or
                        minazimuth is not None or maxazimuth is not None):
            msg = 'Error: station and radius/azimuth parameters are ' + \
                'incompatible.'
            raise wsgicomm.WIClientError, msg

        # Lat/lon parameters have been selected and also radius/azimuth
        if (latmin is not None or latmax is not None or lonmin is not None or
                lonmax is not None) and (minradius is not None or maxradius is
                                         not None or minazimuth is not None or
                                         maxazimuth is not None):
            msg = 'Error: lat/lon and radius/azimuth parameters are ' + \
                'incompatible.'
            raise wsgicomm.WIClientError, msg

        # These are the two lists to return
        stats = []

        # Filter and save indexes of stations in statsOK
        statsOK = self.__selectStations(params)

        # Just to make notation shorter
        ptNets = self.networks
        ptStats = self.stations

        if ('station' in params):
            # Builds a list from the selected stations
            for st in statsOK:
                parent_net = ptStats[st][0]

                (loc_ch, restricted) = self.__buildStreamsList(st, streams,
                                                               sensortype,
                                                               preferredsps,
                                                               start_date,
                                                               end_date)

                if len(loc_ch):
                    stats.append(('%s-%s-%s-%s%s%s' % (ptNets[parent_net][0],
                                  ptNets[parent_net][4], ptStats[st][4],
                                  ptStats[st][8].year, ptStats[st][8].month,
                                  ptStats[st][8].day),  ptNets[parent_net][0],
                                  ptStats[st][4], ptStats[st][5],
                                  ptStats[st][6], ptNets[parent_net][7],
                                  ptNets[parent_net][8], ptNets[parent_net][9],
                                  ptNets[parent_net][10], loc_ch, restricted))

        elif (latmin is not None and latmax is not None and lonmin is not None
              and lonmax is not None):

            # statsOK is a set and therefore, there will be no repetitions
            for st in statsOK:
                # Pointer to the parent network
                parent_net = ptStats[st][0]

                # Filter by latitude
                if(ptStats[st][5] < latmin) or (ptStats[st][5] > latmax):
                    continue

                # Filter by longitude
                if(lonmin <= lonmax):
                    if (ptStats[st][6] < lonmin) or (ptStats[st][6] > lonmax):
                        continue
                else:
                    if (ptStats[st][6] < lonmin) and (ptStats[st][6] > lonmax):
                        continue

                (loc_ch, restricted) = self.__buildStreamsList(st, streams,
                                                               sensortype,
                                                               preferredsps,
                                                               start_date,
                                                               end_date)

                if len(loc_ch):
                    stats.append(('%s-%s-%s-%s%s%s' %
                                  (ptNets[parent_net][0],
                                   ptNets[parent_net][4], ptStats[st][4],
                                   ptStats[st][8].year, ptStats[st][8].month,
                                   ptStats[st][8].day),
                                  ptNets[parent_net][0],
                                  ptStats[st][4], ptStats[st][5],
                                  ptStats[st][6], ptNets[parent_net][7],
                                  ptNets[parent_net][8], ptNets[parent_net][9],
                                  ptNets[parent_net][10], loc_ch, restricted))

        elif events is not None:

            events = json.loads(events)

            for st in statsOK:
                # Pointer to the parent network
                parent_net = ptStats[st][0]

                # Retrieve latitude and longitude of station
                slat = ptStats[st][5]
                slon = ptStats[st][6]

                for evt in events:
                    # Retrieve latitude and longitude of event
                    lat = evt[0]
                    lon = evt[1]

                    # Calculate radial distance and azimuth
                    (dist, azi, other) = Math.delazi(slat, slon, lat, lon)

                    if (minradius < dist) and (dist < maxradius) and \
                       (minazimuth < azi) and (azi < maxazimuth):
                        (loc_ch, restricted) = \
                            self.__buildStreamsList(st, streams, sensortype,
                                                    preferredsps, start_date,
                                                    end_date)

                        if len(loc_ch):
                            stats.append(('%s-%s-%s-%s%s%s' %
                                          (ptNets[parent_net][0],
                                           ptNets[parent_net][4],
                                           ptStats[st][4],
                                           ptStats[st][8].year,
                                           ptStats[st][8].month,
                                           ptStats[st][8].day),
                                          ptNets[parent_net][0],
                                          ptStats[st][4], ptStats[st][5],
                                          ptStats[st][6],
                                          ptStats[st][11],
                                          ptNets[parent_net][8],
                                          ptNets[parent_net][9],
                                          ptNets[parent_net][10], loc_ch,
                                          restricted))

                        # Stop the loop through events and go for the
                        # next station
                        break

        else:
            msg = 'Error: not enough parameters have been given.'
            raise wsgicomm.WIClientError, msg

        stats.sort()

        stats.insert(0, ('key', 'netcode', 'statcode', 'latitude', 'longitude',
                         'restricted', 'netclass', 'archive', 'netoperator',
                         'streams', 'streams_restricted'))

        return stats
Beispiel #7
0
    def __timewindows_ev(self, streams, events, startphase, startoffset,
                         endphase, endoffset):
        """Helper function to calculate time windows related to events.

        Input: streams={list of stream keys}
               events={list of events} # [[lat, lon, depth, time],..]
               startphase={string}     # 'P' or 'S'
               startoffset={int}       # time in minutes to start time window.
                                       # POSITIVE if AFTER arrival of
                                       # 'startphase' at station.
               endphase={string}       # 'P' or 'S'
               endoffset={int}         # time in minutes to end time window.
                                       # POSITIVE if AFTER arrival of
                                       # 'endphase' at station.

        Output: list of start/end times per stream, AND estimated data volume,
                (start_time, end_time, net, sta, cha, loc, streamInfo['size'])

        NOTE 1: stream is a list of [net, sta, cha, loc] instead of nslc here!
        NOTE 2: There are many redundant time window computations for multiple
        streams at the same location
        """

        result = []

        for ev in events:
            try:
                if len(ev) != 4:
                    raise wsgicomm.WIClientError, "invalid event: " + str(ev)

                ev_lat = float(ev[0])
                ev_lon = float(ev[1])
                ev_dep = float(ev[2])
                ev_time = DateTimeAttr().fromxml(ev[3])

            except (TypeError, ValueError):
                raise wsgicomm.WIClientError, "invalid event: " + str(ev)

            for nscl in streams:
                try:
                    if len(nscl) != 4:
                        msg = "Invalid stream: " + str(nscl)
                        raise wsgicomm.WIClientError, msg

                    net = str(nscl[0])
                    sta = str(nscl[1])
                    cha = str(nscl[2])
                    loc = str(nscl[3])

                except (TypeError, ValueError):
                    msg = "Invalid stream: " + str(nscl)
                    raise wsgicomm.WIClientError, msg

                # we don't have actual time window yet, just use ev_time to
                # get the coordinates
                streamInfo = self.ic.getStreamInfo(ev_time, ev_time, net, sta,
                                                   cha, loc)

                if streamInfo is None:  # stream is not available
                    continue

                st_lat = streamInfo['latitude']
                st_lon = streamInfo['longitude']
                st_alt = streamInfo['elevation']

                start_time = None
                end_time = None

                # Assumption here is that compute() returns phases sorted by
                # time. Therefore breaking after the first gives the earliest
                # phase in the set defined in __isphase().
                # FIXME: Combine startphase and endphase logic into
                # function+loop?

                # Compute in delta the distance between event and station
                delta = Math.delazi(ev_lat, ev_lon, st_lat, st_lon)[0]
                # Threshold distance in degrees at which PKP arrives earlier
                # than P and friends (see Joachim's email - 14.08.2013)
                delta_threshold = 120

                try:
                    ttlist = self.ttt.compute(ev_lat, ev_lon, ev_dep, st_lat,
                                              st_lon, st_alt)
                except Exception, e:
                    msg = "/metadata/timewindows: exception from " + \
                        "ttt.compute(): " + str(e)
                    logs.error(msg)
                    continue

                try:
                    for tt in ttlist:
                        if (startphase == 'P') and (delta >= delta_threshold):
                            if (tt.phase.startswith('PKP') or
                                    tt.phase.startswith('PKiKP')):
                                start_time = ev_time + \
                                    datetime.timedelta(seconds=tt.time +
                                                       startoffset * 60)
                                break

                        elif ((startphase == 'S') or
                              ((startphase == 'P') and
                               (delta < delta_threshold))):
                            if self.__isphase(tt.phase, startphase):
                                start_time = ev_time + datetime.timedelta(
                                    seconds=tt.time + startoffset * 60)
                                break
                        elif (startphase == 'OT'):
                            start_time = ev_time + datetime.timedelta(seconds=startoffset * 60)
                        else:
                            msg = 'Wrong startphase received! Only "P", ' + \
                                '"S" and "OT" are implemented.'
                            raise wsgicomm.WIClientError, msg

                    for tt in ttlist:
                        if (endphase == 'P') and (delta >= delta_threshold):
                            if (tt.phase.startswith('PKP') or
                                    tt.phase.startswith('PKiKP')):
                                end_time = ev_time + datetime.timedelta(
                                    seconds=tt.time + endoffset * 60)
                                break

                        elif ((endphase == 'S') or
                              ((endphase == 'P') and
                               (delta < delta_threshold))):
                            if self.__isphase(tt.phase, endphase):
                                end_time = ev_time + datetime.timedelta(
                                    seconds=tt.time + endoffset * 60)
                                break
                        elif (endphase == 'OT'):
                                end_time = ev_time + datetime.timedelta(seconds=endoffset * 60)
                        else:
                            msg = 'Wrong endphase received! Only "P", ' + \
                                '"S" and "OT" are implemented.'
                            raise wsgicomm.WIClientError, msg

                except Exception, e:
                    logs.error("/metadata/timewindows: " + str(e))
                    continue

                if start_time is None:
                    msg = "/metadata/timewindows: did not find startphase " \
                        + "'%s' for %s" % (startphase, str((ev_lat, ev_lon,
                                                            ev_dep, st_lat,
                                                            st_lon, st_alt)))
                    logs.error(msg)

                if end_time is None:
                    msg = "/metadata/timewindows: did not find endphase " \
                        + "'%s' for %s" % (endphase, str((ev_lat, ev_lon,
                                                          ev_dep, st_lat,
                                                          st_lon, st_alt)))
                    logs.error(msg)

                if start_time is not None and end_time is not None:
                    # retry with actual time window
                    streamInfo = self.ic.getStreamInfo(start_time, end_time,
                                                       net, sta, cha, loc)

                    if streamInfo:
                        result.append((start_time, end_time, net, sta, cha,
                                       loc, streamInfo['size']))

                        if len(result) > self.max_lines:
                            msg = "Maximum request size exceeded"
                            raise wsgicomm.WIClientError, msg