def getListForStationAndEvent(self, event_id, station_id, request): split_station = station_id.split(".") if len(split_station) != 2: msg = "'station_id' has to be of the form NET.STA" raise InvalidParameterError(msg) network, station = split_station print network, station session = self.env.db.session(bind=self.env.db.engine) stat_id = get_station_id(network, station, session) if stat_id is False: msg = "Could not find station '%s'" % station_id raise InvalidParameterError(msg) query = session.query(WaveformChannelObject)\ .join(ChannelObject)\ .filter(WaveformChannelObject.event_resource_id == event_id)\ .filter(ChannelObject.station_id == stat_id).all() result = [] for q in query: chan = q.channel stat = chan.station result.append({ "network": stat.network, "station": stat.station, "location": chan.location, "channel": chan.channel, "filepath_id": q.filepath_id, "tag": q.tag, "starttime": q.starttime.isoformat(), "endtime": q.endtime.isoformat(), "sampling_rate": q.sampling_rate, "format": q.format, "is_synthetic": q.is_synthetic}) result = formatResults(request, result) return result
def process_GET(self, request): """ Function that will be called upon receiving a GET request for the aforementioned URL. """ # Parse the given parameters. event_id = request.args0.get("event", None) channel_id = request.args0.get("channel_id", None) station_id = request.args0.get("station_id", None) tag = request.args0.get("tag", "") format = request.args0.get("format", None) # An event id is obviously needed. if event_id is None: msg = ("No event parameter passed. Every waveform " "is bound to an existing event.") raise InvalidParameterError(msg) if event_id is not None and not event_exists(event_id, self.env): msg = "The given event resource name '%s' " % event_id msg += "is not known to SeisHub." raise InvalidParameterError(msg) # Returns different things based on parameter combinations. # Return all waveforms available for a given event. if channel_id is None and station_id is None and event_id is not None: return self.getListForEvent(event_id, request) # Return all waveforms available for a given event and station id. elif station_id is not None and event_id is not None: return self.getListForStationAndEvent(event_id, station_id, request) # At this step format will mean a waveform output format. acceptable_formats = ["mseed", "sac", "gse2", "segy", "raw", "json"] if format and format.lower() not in acceptable_formats: msg = "'%s' is an unsupported format. Supported formats: %s" % \ (format, ", ".join(acceptable_formats)) raise InvalidParameterError(msg) if channel_id is None: msg = ("To download a waveform, 'channel_id' to be specified.") raise InvalidParameterError(msg) split_channel = channel_id.split(".") if len(split_channel) != 4: msg = "Invalid 'channel_id'. Needs to be NET.STA.LOC.CHAN." raise InvalidParameterError(msg) network, station, location, channel = split_channel session = self.env.db.session(bind=self.env.db.engine) station_id = get_station_id(network, station, session) if station_id is False: session.close() msg = "Could not find station %s.%s in the database" % \ (network, station) raise InvalidParameterError(msg) query = session.query(WaveformChannelObject)\ .join(ChannelObject)\ .filter(WaveformChannelObject.event_resource_id == event_id)\ .filter(WaveformChannelObject.tag == tag)\ .filter(ChannelObject.location == location)\ .filter(ChannelObject.channel == channel)\ .filter(ChannelObject.station_id == station_id) try: result = query.one() except sqlalchemy.orm.exc.NoResultFound: session.close() msg = "No matching data found in the database." raise NotFoundError(msg) if format and format.lower() == "raw": with open(result.filepath.filepath, "rb") as open_file: data = open_file.read() # Set the corresponding headers. request.setHeader("content-type", "application/octet-stream") filename = os.path.basename(result.filepath.filepath)\ .encode("utf-8") request.setHeader("content-disposition", "attachment; filename=%s" % filename) return data chan = result.channel stat = chan.station network = stat.network station = stat.station location = chan.location channel = chan.channel starttime = UTCDateTime(result.starttime) if result.starttime else None endtime = UTCDateTime(result.endtime) if result.endtime else None default_format = result.format # Read and filter the file. st = read(result.filepath.filepath).select(network=network, station=station, location=location, channel=channel) session.close() # Now attempt to find the correct trace in case of more then one trace. # This should enable multicomponent files. selected_trace = None for tr in st: if (starttime and abs(tr.stats.starttime - starttime) > 1) or \ (endtime and abs(tr.stats.endtime - endtime) > 1): continue selected_trace = tr break if selected_trace is None: msg = "Could not find the corresponding waveform file." raise InternalServerError(msg) # Deal with json format conversion. if format and format == "json": output = { "channel": selected_trace.id, "sampling_rate": selected_trace.stats.sampling_rate, "npts": selected_trace.stats.npts, "data": [] } time = selected_trace.stats.starttime delta = selected_trace.stats.delta for value in selected_trace.data: output["data"].append([time.isoformat(), float(value)]) time += delta request.setHeader('content-type', 'application/json; charset=UTF-8') return json.dumps(output) # XXX: Fix some ObsPy modules to be able to write to memory files. tempfile = NamedTemporaryFile() if format: default_format = format selected_trace.write(tempfile.name, format=default_format) with open(tempfile.name, "rb") as open_file: data = open_file.read() tempfile.close() os.remove(tempfile.name) # Set the corresponding headers. request.setHeader("content-type", "application/octet-stream") filename = "%s.%s" % (selected_trace.id, default_format.lower()) filename = filename.encode("utf-8") request.setHeader("content-disposition", "attachment; filename=%s" % filename) return data