def flex_read_stations(filenames: str or list): """ Takes in a list of strings and tries to read them as inventories Creates a single inventory, not an aggregate of inventories :param filename: station file(s). wildcards permitted. :return: `obspy.Inventory` """ if type(filenames) is str: filenames = [filenames] inv = Inventory() for _file in filenames: try: add_inv = read_inventory(_file) for network in add_inv: if len(inv.select(network=network.code)) == 0: inv.networks.append(network) else: new_network = inv.select(network=network.code)[0] # print(new_network) for station in network: if len(new_network.select(station=station.code)) == 0: new_network.stations.append(station) inv = inv.remove(network=network.code) inv.networks.append(new_network) except Exception as e: print("%s could not be read. Error: %s" % (_file, e)) return inv
def get_inventory( client, tribe: Union[RealTimeTribe, Tribe], triggering_event: Event = None, location: dict = None, starttime: UTCDateTime = None, max_distance: float = 1000., n_stations: int = 10, duration: float = 10, level: str = "channel", channel_list: Union[list, tuple] = ("EH?", "HH?"), ) -> Inventory: """ Get a suitable inventory for a tribe - selects the most used, closest stations. Parameters ---------- client: Obspy client with a get_stations service. tribe: Tribe or RealTimeTribe of templates to query for stations. triggering_event: Event with at least an origin to calculate distances from - if not specified will use `location` location: Dictionary with "latitude" and "longitude" keys - only used if `triggering event` is not specified. starttime: Start-time for station search - only used if `triggering_event` is not specified. max_distance: Maximum distance from `triggering_event.preferred_origin` or `location` to find stations. Units: km n_stations: Maximum number of stations to return duration: Duration stations must be active for. Units: days level: Level for inventory parsable by `client.get_stations`. channel_list List of channel-codes to be acquired. If `None` then all channels will be searched. Returns ------- Inventory of the most used, closest stations. """ inv = Inventory(networks=[], source=None) if triggering_event is not None: try: origin = ( triggering_event.preferred_origin() or triggering_event.origins[0]) except IndexError: Logger.error("Triggering event has no origin") return inv lat = origin.latitude lon = origin.longitude _starttime = origin.time else: lat = location["latitude"] lon = location["longitude"] _starttime = starttime for channel_str in channel_list or ["*"]: try: inv += client.get_stations( startbefore=_starttime, endafter=_starttime + (duration * 86400), channel=channel_str, latitude=lat, longitude=lon, maxradius=kilometer2degrees(max_distance), level=level) except FDSNNoDataException: continue if len(inv) == 0: return inv # Calculate distances station_count = Counter( [pick.waveform_id.station_code for template in tribe for pick in template.event.picks]) sta_dist = [] for net in inv: for sta in net: dist = locations2degrees( lat1=lat, long1=lon, lat2=sta.latitude, long2=sta.longitude) sta_dist.append((sta.code, dist, station_count[sta.code])) sta_dist.sort(key=lambda _: (-_[2], _[1])) inv_out = inv.select(station=sta_dist[0][0]) for sta in sta_dist[1:n_stations]: inv_out += inv.select(station=sta[0]) return inv_out