def __parse_req_body_json(self, data): try: parsed = json.loads(data) dta = DateTimeAttr() content = [] for items in parsed: for i in range(2, 6): if not isinstance(items[i], basestring) or len( items[i]) > 40 or " " in items[i]: raise wsgicomm.WIClientError, "invalid request body" content.append( RequestLine(start_time=dta.fromxml(items[0]), end_time=dta.fromxml(items[1]), net=str(items[2]), sta=str(items[3]), cha=str(items[4]), loc=str(items[5]), estimated_size=items[6])) except (KeyError, ValueError, IndexError): raise wsgicomm.WIClientError, "invalid request body" return content
def __parse_req_body_json(self, data): try: parsed = json.loads(data) dta = DateTimeAttr() content = [] for items in parsed: for i in range(2, 6): if not isinstance(items[i], basestring) or len(items[i]) > 40 or " " in items[i]: raise wsgicomm.WIClientError, "invalid request body" content.append(RequestLine( start_time = dta.fromxml(items[0]), end_time = dta.fromxml(items[1]), net = str(items[2]), sta = str(items[3]), cha = str(items[4]), loc = str(items[5]), estimated_size = items[6])) except (KeyError, ValueError, IndexError): raise wsgicomm.WIClientError, "invalid request body" return content
def timewindows(self, envir, params): """ <wsgi root>/metadata/query<?parameters> Metadata query for preparing request Parameters: start={datetimestring} end={datetimestring} streams=JSON Response: JSON """ if 'streams' not in params: raise wsgicomm.WIClientError, "missing streams" tw_params = ('start', 'end') ev_params = ('events', 'startphase', 'startoffset', 'endphase', 'endoffset') tw_params_count = reduce(lambda a, b: a + (b in tw_params), params, 0) ev_params_count = reduce(lambda a, b: a + (b in ev_params), params, 0) if tw_params_count == len(tw_params) and ev_params_count == 0: mode = 'tw' elif ev_params_count == len(ev_params) and tw_params_count == 0: mode = 'ev' else: raise wsgicomm.WIClientError, "invalid set of parameters" try: streams = self.__get_param(params, json.loads, 'streams') if mode == 'tw': dta = DateTimeAttr() start_time = self.__get_param(params, dta.fromxml, 'start') end_time = self.__get_param(params, dta.fromxml, 'end') else: events = self.__get_param(params, json.loads, 'events') startphase = self.__get_param(params, str, 'startphase') startoffset = self.__get_param(params, float, 'startoffset') endphase = self.__get_param(params, str, 'endphase') endoffset = self.__get_param(params, float, 'endoffset') except ValueError, e: raise wsgicomm.WIClientError, str(e)
def default(self, obj): if isinstance(obj, datetime.datetime): return DateTimeAttr.toxml(obj) return json.JSONEncoder.default(self, obj)
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