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
def _getDistancesArrivalsSorted(self, org): # sort arrival list by distance dist_arr = [] if self.distInKM: from seiscomp3 import Math for i in xrange(org.arrivalCount()): arr = org.arrival(i) dist_arr.append((Math.deg2km(arr.distance()), arr)) else: for i in xrange(org.arrivalCount()): arr = org.arrival(i) dist_arr.append((arr.distance(), arr)) dist_arr.sort() return dist_arr
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
def _getDistancesArrivalsSorted(self, org): # sort arrival list by distance dist_arr = [] if self.distInKM: from seiscomp3 import Math for i in range(org.arrivalCount()): arr = org.arrival(i) try: dist_arr.append((Math.deg2km(arr.distance()), arr)) except ValueError: pass else: for i in range(org.arrivalCount()): arr = org.arrival(i) try: dist_arr.append((arr.distance(), arr)) except ValueError: pass return sorted(dist_arr, key=lambda a: a[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
def sh2proc(self, file): ep = DataModel.EventParameters() origin = DataModel.Origin.Create() event = DataModel.Event.Create() origin.setCreationInfo(DataModel.CreationInfo()) origin.creationInfo().setCreationTime(Core.Time.GMT()) originQuality = None originCE = None latFound = False lonFound = False depthError = None originComments = {} # variables, reset after 'end of phase' pick = None stationMag = None staCode = None compCode = None stationMagBB = None amplitudeDisp = None amplitudeVel = None amplitudeSNR = None amplitudeBB = None magnitudeMB = None magnitudeML = None magnitudeMS = None magnitudeBB = None km2degFac = 1.0 / Math.deg2km(1.0) # read file line by line, split key and value at colon iLine = 0 for line in file: iLine += 1 a = line.split(':', 1) key = a[0].strip() keyLower = key.lower() value = None # empty line if len(keyLower) == 0: continue # end of phase elif keyLower == '--- end of phase ---': if pick is None: Logging.warning('Line %i: found empty phase block' % iLine) continue if staCode is None or compCode is None: Logging.warning('Line %i: end of phase, stream code ' 'incomplete' % iLine) continue if staCode not in self.streams: Logging.warning('Line %i: end of phase, station code %s ' 'not found in inventory' % (iLine, staCode)) continue if compCode not in self.streams[staCode]: Logging.warning('Line %i: end of phase, component %s of ' 'station %s not found in inventory' % ( iLine, compCode, staCode)) continue streamID = self.streams[staCode][compCode] pick.setWaveformID(streamID) ep.add(pick) arrival.setPickID(pick.publicID()) arrival.setPhase(phase) origin.add(arrival) if amplitudeSNR is not None: amplitudeSNR.setPickID(pick.publicID()) amplitudeSNR.setWaveformID(streamID) ep.add(amplitudeSNR) if amplitudeBB is not None: amplitudeBB.setPickID(pick.publicID()) amplitudeBB.setWaveformID(streamID) ep.add(amplitudeBB) if stationMagBB is not None: stationMagBB.setWaveformID(streamID) origin.add(stationMagBB) stationMagContrib = DataModel.StationMagnitudeContribution() stationMagContrib.setStationMagnitudeID( stationMagBB.publicID()) if magnitudeBB is None: magnitudeBB = DataModel.Magnitude.Create() magnitudeBB.add(stationMagContrib) if stationMag is not None: if stationMag.type() in ['mb', 'ML'] and amplitudeDisp is not None: amplitudeDisp.setPickID(pick.publicID()) amplitudeDisp.setWaveformID(streamID) amplitudeDisp.setPeriod( DataModel.RealQuantity(ampPeriod)) amplitudeDisp.setType(stationMag.type()) ep.add(amplitudeDisp) if stationMag.type() in ['Ms(BB)'] and amplitudeVel is not None: amplitudeVel.setPickID(pick.publicID()) amplitudeVel.setWaveformID(streamID) amplitudeVel.setPeriod( DataModel.RealQuantity(ampPeriod)) amplitudeVel.setType(stationMag.type()) ep.add(amplitudeVel) stationMag.setWaveformID(streamID) origin.add(stationMag) stationMagContrib = DataModel.StationMagnitudeContribution() stationMagContrib.setStationMagnitudeID( stationMag.publicID()) magType = stationMag.type() if magType == 'ML': if magnitudeML is None: magnitudeML = DataModel.Magnitude.Create() magnitudeML.add(stationMagContrib) elif magType == 'Ms(BB)': if magnitudeMS is None: magnitudeMS = DataModel.Magnitude.Create() magnitudeMS.add(stationMagContrib) elif magType == 'mb': if magnitudeMB is None: magnitudeMB = DataModel.Magnitude.Create() magnitudeMB.add(stationMagContrib) pick = None staCode = None compCode = None stationMag = None stationMagBB = None amplitudeDisp = None amplitudeVel = None amplitudeSNR = None amplitudeBB = None continue # empty key elif len(a) == 1: Logging.warning('Line %i: key without value' % iLine) continue value = a[1].strip() if pick is None: pick = DataModel.Pick.Create() arrival = DataModel.Arrival() try: ############################################################## # station parameters # station code if keyLower == 'station code': staCode = value # pick time elif keyLower == 'onset time': pick.setTime(DataModel.TimeQuantity(self.parseTime(value))) # pick onset type elif keyLower == 'onset type': found = False for onset in [DataModel.EMERGENT, DataModel.IMPULSIVE, DataModel.QUESTIONABLE]: if value == DataModel.EPickOnsetNames_name(onset): pick.setOnset(onset) found = True break if not found: raise Exception('Unsupported onset value') # phase code elif keyLower == 'phase name': phase = DataModel.Phase() phase.setCode(value) pick.setPhaseHint(phase) # event type elif keyLower == 'event type': evttype = EventTypes[value] event.setType(evttype) originComments[key] = value # filter ID elif keyLower == 'applied filter': pick.setFilterID(value) # channel code, prepended by configured Channel prefix if only # one character is found elif keyLower == 'component': compCode = value # pick evaluation mode elif keyLower == 'pick type': found = False for mode in [DataModel.AUTOMATIC, DataModel.MANUAL]: if value == DataModel.EEvaluationModeNames_name(mode): pick.setEvaluationMode(mode) found = True break if not found: raise Exception('Unsupported evaluation mode value') # pick author elif keyLower == 'analyst': creationInfo = DataModel.CreationInfo() creationInfo.setAuthor(value) pick.setCreationInfo(creationInfo) # pick polarity # isn't tested elif keyLower == 'sign': if value == 'positive': sign = '0' # positive elif value == 'negative': sign = '1' # negative else: sign = '2' # unknown pick.setPolarity(float(sign)) # arrival weight elif keyLower == 'weight': arrival.setWeight(float(value)) # arrival azimuth elif keyLower == 'theo. azimuth (deg)': arrival.setAzimuth(float(value)) # pick theo backazimuth elif keyLower == 'theo. backazimuth (deg)': if pick.slownessMethodID() == 'corrected': Logging.debug('Line %i: ignoring parameter: %s' % ( iLine, key)) else: pick.setBackazimuth( DataModel.RealQuantity(float(value))) pick.setSlownessMethodID('theoretical') # pick beam slowness elif keyLower == 'beam-slowness (sec/deg)': if pick.slownessMethodID() == 'corrected': Logging.debug('Line %i: ignoring parameter: %s' % ( iLine, key)) else: pick.setHorizontalSlowness( DataModel.RealQuantity(float(value))) pick.setSlownessMethodID('Array Beam') # pick beam backazimuth elif keyLower == 'beam-azimuth (deg)': if pick.slownessMethodID() == 'corrected': Logging.debug('Line %i: ignoring parameter: %s' % ( iLine, key)) else: pick.setBackazimuth( DataModel.RealQuantity(float(value))) # pick epi slowness elif keyLower == 'epi-slowness (sec/deg)': pick.setHorizontalSlowness( DataModel.RealQuantity(float(value))) pick.setSlownessMethodID('corrected') # pick epi backazimuth elif keyLower == 'epi-azimuth (deg)': pick.setBackazimuth(DataModel.RealQuantity(float(value))) # arrival distance degree elif keyLower == 'distance (deg)': arrival.setDistance(float(value)) # arrival distance km, recalculates for degree elif keyLower == 'distance (km)': if isinstance(arrival.distance(), float): Logging.debug('Line %i: ignoring parameter: %s' % ( iLine-1, 'distance (deg)')) arrival.setDistance(float(value) * km2degFac) # arrival time residual elif keyLower == 'residual time': arrival.setTimeResidual(float(value)) # amplitude snr elif keyLower == 'signal/noise': amplitudeSNR = DataModel.Amplitude.Create() amplitudeSNR.setType('SNR') amplitudeSNR.setAmplitude( DataModel.RealQuantity(float(value))) # amplitude period elif keyLower.startswith('period'): ampPeriod = float(value) # amplitude value for displacement elif keyLower == 'amplitude (nm)': amplitudeDisp = DataModel.Amplitude.Create() amplitudeDisp.setAmplitude( DataModel.RealQuantity(float(value))) amplitudeDisp.setUnit('nm') # amplitude value for velocity elif keyLower.startswith('vel. amplitude'): amplitudeVel = DataModel.Amplitude.Create() amplitudeVel.setAmplitude( DataModel.RealQuantity(float(value))) amplitudeVel.setUnit('nm/s') elif keyLower == 'bb amplitude (nm/sec)': amplitudeBB = DataModel.Amplitude.Create() amplitudeBB.setAmplitude( DataModel.RealQuantity(float(value))) amplitudeBB.setType('mB') amplitudeBB.setUnit('nm/s') amplitudeBB.setPeriod(DataModel.RealQuantity(ampBBPeriod)) elif keyLower == 'bb period (sec)': ampBBPeriod = float(value) elif keyLower == 'broadband magnitude': magType = self.parseMagType('bb') stationMagBB = DataModel.StationMagnitude.Create() stationMagBB.setMagnitude( DataModel.RealQuantity(float(value))) stationMagBB.setType(magType) stationMagBB.setAmplitudeID(amplitudeBB.publicID()) # ignored elif keyLower == 'quality number': Logging.debug('Line %i: ignoring parameter: %s' % ( iLine, key)) # station magnitude value and type elif keyLower.startswith('magnitude '): magType = self.parseMagType(key[10:]) stationMag = DataModel.StationMagnitude.Create() stationMag.setMagnitude( DataModel.RealQuantity(float(value))) if len(magType) > 0: stationMag.setType(magType) if magType == 'mb': stationMag.setAmplitudeID(amplitudeDisp.publicID()) elif magType == 'MS(BB)': stationMag.setAmplitudeID(amplitudeVel.publicID()) else: Logging.debug('Line %i: Magnitude Type not known %s.' % ( iLine, magType)) ############################################################### # origin parameters # event ID, added as origin comment later on elif keyLower == 'event id': originComments[key] = value # magnitude value and type elif keyLower == 'mean bb magnitude': magType = self.parseMagType('bb') if magnitudeBB is None: magnitudeBB = DataModel.Magnitude.Create() magnitudeBB.setMagnitude( DataModel.RealQuantity(float(value))) magnitudeBB.setType(magType) elif keyLower.startswith('mean magnitude '): magType = self.parseMagType(key[15:]) if magType == 'ML': if magnitudeML is None: magnitudeML = DataModel.Magnitude.Create() magnitudeML.setMagnitude( DataModel.RealQuantity(float(value))) magnitudeML.setType(magType) elif magType == 'Ms(BB)': if magnitudeMS is None: magnitudeMS = DataModel.Magnitude.Create() magnitudeMS.setMagnitude( DataModel.RealQuantity(float(value))) magnitudeMS.setType(magType) elif magType == 'mb': if magnitudeMB is None: magnitudeMB = DataModel.Magnitude.Create() magnitudeMB.setMagnitude( DataModel.RealQuantity(float(value))) magnitudeMB.setType(magType) else: Logging.warning('Line %i: Magnitude type %s not defined yet.' % ( iLine, magType)) # latitude elif keyLower == 'latitude': origin.latitude().setValue(float(value)) latFound = True elif keyLower == 'error in latitude (km)': origin.latitude().setUncertainty(float(value)) # longitude elif keyLower == 'longitude': origin.longitude().setValue(float(value)) lonFound = True elif keyLower == 'error in longitude (km)': origin.longitude().setUncertainty(float(value)) # depth elif keyLower == 'depth (km)': origin.setDepth(DataModel.RealQuantity(float(value))) if depthError is not None: origin.depth().setUncertainty(depthError) elif keyLower == 'depth type': Logging.debug('Line %i: ignoring parameter: %s' % ( iLine, key)) elif keyLower == 'error in depth (km)': depthError = float(value) try: origin.depth().setUncertainty(depthError) except Core.ValueException: pass # time elif keyLower == 'origin time': origin.time().setValue(self.parseTime(value)) elif keyLower == 'error in origin time': origin.time().setUncertainty(float(value)) # location method elif keyLower == 'location method': origin.setMethodID(str(value)) # region table, added as origin comment later on elif keyLower == 'region table': originComments[key] = value # region table, added as origin comment later on elif keyLower == 'region id': originComments[key] = value # source region, added as origin comment later on elif keyLower == 'source region': originComments[key] = value # used station count elif keyLower == 'no. of stations used': if originQuality is None: originQuality = DataModel.OriginQuality() originQuality.setUsedStationCount(int(value)) # ignored elif keyLower == 'reference location name': Logging.debug('Line %i: ignoring parameter: %s' % ( iLine, key)) # confidence ellipsoid major axis elif keyLower == 'error ellipse major': if originCE is None: originCE = DataModel.ConfidenceEllipsoid() originCE.setSemiMajorAxisLength(float(value)) # confidence ellipsoid minor axis elif keyLower == 'error ellipse minor': if originCE is None: originCE = DataModel.ConfidenceEllipsoid() originCE.setSemiMinorAxisLength(float(value)) # confidence ellipsoid rotation elif keyLower == 'error ellipse strike': if originCE is None: originCE = DataModel.ConfidenceEllipsoid() originCE.setMajorAxisRotation(float(value)) # azimuthal gap elif keyLower == 'max azimuthal gap (deg)': if originQuality is None: originQuality = DataModel.OriginQuality() originQuality.setAzimuthalGap(float(value)) # creation info author elif keyLower == 'author': origin.creationInfo().setAuthor(value) # creation info agency elif keyLower == 'source of information': origin.creationInfo().setAgencyID(value) # earth model id elif keyLower == 'velocity model': origin.setEarthModelID(value) # standard error elif keyLower == 'rms of residuals (sec)': if originQuality is None: originQuality = DataModel.OriginQuality() originQuality.setStandardError(float(value)) # ignored elif keyLower == 'phase flags': Logging.debug('Line %i: ignoring parameter: %s' % ( iLine, key)) # ignored elif keyLower == 'location input params': Logging.debug('Line %i: ignoring parameter: %s' % ( iLine, key)) # missing keys elif keyLower == 'ampl&period source': Logging.debug('Line %i: ignoring parameter: %s' % ( iLine, key)) elif keyLower == 'location quality': Logging.debug('Line %i: ignoring parameter: %s' % ( iLine, key)) elif keyLower == 'reference latitude': Logging.debug('Line %i: ignoring parameter: %s' % ( iLine, key)) elif keyLower == 'reference longitude': Logging.debug('Line %i: ignoring parameter: %s' % ( iLine, key)) elif keyLower.startswith('amplitude time'): Logging.debug('Line %i: ignoring parameter: %s' % ( iLine, key)) # unknown key else: Logging.warning('Line %i: ignoring unknown parameter: %s' % (iLine, key)) except ValueError as ve: Logging.warning('Line %i: can not parse %s value' % ( iLine, key)) except Exception: Logging.error('Line %i: %s' % (iLine, str(traceback.format_exc()))) return None # check if not latFound: Logging.warning('could not add origin, missing latitude parameter') elif not lonFound: Logging.warning( 'could not add origin, missing longitude parameter') elif not origin.time().value().valid(): Logging.warning( 'could not add origin, missing origin time parameter') else: if magnitudeMB is not None: origin.add(magnitudeMB) if magnitudeML is not None: origin.add(magnitudeML) if magnitudeMS is not None: origin.add(magnitudeMS) if magnitudeBB is not None: origin.add(magnitudeBB) ep.add(event) ep.add(origin) if originQuality is not None: origin.setQuality(originQuality) if originCE is not None: uncertainty = DataModel.OriginUncertainty() uncertainty.setConfidenceEllipsoid(originCE) origin.setUncertainty(uncertainty) for k, v in originComments.items(): comment = DataModel.Comment() comment.setId(k) comment.setText(v) origin.add(comment) return ep
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
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
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