def test_inside_geobounds(self): obj = AttribDict() obj.latitude = 48.8566 obj.longitude = 2.3522 ret = inside_geobounds(obj, minlatitude=48, maxlatitude=49, minlongitude=2, maxlongitude=3) self.assertTrue(ret) ret = inside_geobounds(obj, latitude=48, longitude=2, minradius=1, maxradius=2) self.assertFalse(ret) # Test for wrapping around longitude +/- 180° obj.latitude = -41.2865 obj.longitude = 174.7762 ret = inside_geobounds(obj, minlongitude=170, maxlongitude=-170) self.assertTrue(ret) obj.longitude = -175. ret = inside_geobounds(obj, minlongitude=170, maxlongitude=-170) self.assertTrue(ret) ret = inside_geobounds(obj, minlongitude=170, maxlongitude=190) self.assertTrue(ret)
def select(self, location=None, channel=None, time=None, starttime=None, endtime=None, sampling_rate=None, minlatitude=None, maxlatitude=None, minlongitude=None, maxlongitude=None, latitude=None, longitude=None, minradius=None, maxradius=None): r""" Returns the :class:`Station` object with only the :class:`~obspy.core.inventory.channel.Channel`\ s that match the given criteria (e.g. all channels with ``channel="EHZ"``). .. warning:: The returned object is based on a shallow copy of the original object. That means that modifying any mutable child elements will also modify the original object (see https://docs.python.org/2/library/copy.html). Use :meth:`copy()` afterwards to make a new copy of the data in memory. .. rubric:: Example >>> from obspy import read_inventory, UTCDateTime >>> sta = read_inventory()[0][0] >>> t = UTCDateTime(2008, 7, 1, 12) >>> sta = sta.select(channel="[LB]HZ", time=t) >>> print(sta) # doctest: +NORMALIZE_WHITESPACE Station FUR (Fuerstenfeldbruck, Bavaria, GR-Net) Station Code: FUR Channel Count: None/None (Selected/Total) 2006-12-16T00:00:00.000000Z - Access: None Latitude: 48.16, Longitude: 11.28, Elevation: 565.0 m Available Channels: FUR..BHZ, FUR..LHZ The `location` and `channel` selection criteria may also contain UNIX style wildcards (e.g. ``*``, ``?``, ...; see :func:`~fnmatch.fnmatch`). :type location: str :param location: Potentially wildcarded location code. If not given, all location codes will be accepted. :type channel: str :param channel: Potentially wildcarded channel code. If not given, all channel codes will be accepted. :type time: :class:`~obspy.core.utcdatetime.UTCDateTime` :param time: Only include channels active at given point in time. :type starttime: :class:`~obspy.core.utcdatetime.UTCDateTime` :param starttime: Only include channels active at or after given point in time (i.e. channels ending before given time will not be shown). :type endtime: :class:`~obspy.core.utcdatetime.UTCDateTime` :param endtime: Only include channels active before or at given point in time (i.e. channels starting after given time will not be shown). :type sampling_rate: float :param sampling_rate: Only include channels whose sampling rate matches the given sampling rate, in Hz (within absolute tolerance of 1E-8 Hz and relative tolerance of 1E-5) :type minlatitude: float :param minlatitude: Only include channels with a latitude larger than the specified minimum. :type maxlatitude: float :param maxlatitude: Only include channels with a latitude smaller than the specified maximum. :type minlongitude: float :param minlongitude: Only include channels with a longitude larger than the specified minimum. :type maxlongitude: float :param maxlongitude: Only include channels with a longitude smaller than the specified maximum. :type latitude: float :param latitude: Specify the latitude to be used for a radius selection. :type longitude: float :param longitude: Specify the longitude to be used for a radius selection. :type minradius: float :param minradius: Only include channels within the specified minimum number of degrees from the geographic point defined by the latitude and longitude parameters. :type maxradius: float :param maxradius: Only include channels within the specified maximum number of degrees from the geographic point defined by the latitude and longitude parameters. """ channels = [] for cha in self.channels: # skip if any given criterion is not matched if location is not None: if not fnmatch.fnmatch(cha.location_code.upper(), location.upper()): continue if channel is not None: if not fnmatch.fnmatch(cha.code.upper(), channel.upper()): continue if sampling_rate is not None: if cha.sample_rate is None: msg = ("Omitting channel that has no sampling rate " "specified.") warnings.warn(msg) continue if not np.allclose(float(sampling_rate), cha.sample_rate, rtol=1E-5, atol=1E-8): continue if any([t is not None for t in (time, starttime, endtime)]): if not cha.is_active(time=time, starttime=starttime, endtime=endtime): continue geo_filters = dict( minlatitude=minlatitude, maxlatitude=maxlatitude, minlongitude=minlongitude, maxlongitude=maxlongitude, latitude=latitude, longitude=longitude, minradius=minradius, maxradius=maxradius) if any(value is not None for value in geo_filters.values()): if not inside_geobounds(cha, **geo_filters): continue channels.append(cha) sta = copy.copy(self) sta.channels = channels return sta
def select(self, station=None, location=None, channel=None, time=None, starttime=None, endtime=None, sampling_rate=None, keep_empty=False, minlatitude=None, maxlatitude=None, minlongitude=None, maxlongitude=None, latitude=None, longitude=None, minradius=None, maxradius=None): r""" Returns the :class:`Network` object with only the :class:`~obspy.core.inventory.station.Station`\ s / :class:`~obspy.core.inventory.channel.Channel`\ s that match the given criteria (e.g. all channels with ``channel="EHZ"``). .. warning:: The returned object is based on a shallow copy of the original object. That means that modifying any mutable child elements will also modify the original object (see https://docs.python.org/2/library/copy.html). Use :meth:`copy()` afterwards to make a new copy of the data in memory. .. rubric:: Example >>> from obspy import read_inventory, UTCDateTime >>> net = read_inventory()[0] >>> t = UTCDateTime(2008, 7, 1, 12) >>> net = net.select(channel="[LB]HZ", time=t) >>> print(net) # doctest: +NORMALIZE_WHITESPACE Network GR (GRSN) Station Count: None/None (Selected/Total) -- - -- Access: UNKNOWN Contains: Stations (2): GR.FUR (Fuerstenfeldbruck, Bavaria, GR-Net) GR.WET (Wettzell, Bavaria, GR-Net) Channels (4): GR.FUR..BHZ, GR.FUR..LHZ, GR.WET..BHZ, GR.WET..LHZ The `station`, `location` and `channel` selection criteria may also contain UNIX style wildcards (e.g. ``*``, ``?``, ...; see :func:`~fnmatch.fnmatch`). :type station: str :param station: Potentially wildcarded station code. If not given, all station codes will be accepted. :type location: str :param location: Potentially wildcarded location code. If not given, all location codes will be accepted. :type channel: str :param channel: Potentially wildcarded channel code. If not given, all channel codes will be accepted. :type time: :class:`~obspy.core.utcdatetime.UTCDateTime` :param time: Only include stations/channels active at given point in time. :type starttime: :class:`~obspy.core.utcdatetime.UTCDateTime` :param starttime: Only include stations/channels active at or after given point in time (i.e. channels ending before given time will not be shown). :type endtime: :class:`~obspy.core.utcdatetime.UTCDateTime` :param endtime: Only include stations/channels active before or at given point in time (i.e. channels starting after given time will not be shown). :type sampling_rate: float :param sampling_rate: Only include channels whose sampling rate matches the given sampling rate, in Hz (within absolute tolerance of 1E-8 Hz and relative tolerance of 1E-5) :type minlatitude: float :param minlatitude: Only include stations/channels with a latitude larger than the specified minimum. :type maxlatitude: float :param maxlatitude: Only include stations/channels with a latitude smaller than the specified maximum. :type minlongitude: float :param minlongitude: Only include stations/channels with a longitude larger than the specified minimum. :type maxlongitude: float :param maxlongitude: Only include stations/channels with a longitude smaller than the specified maximum. :type latitude: float :param latitude: Specify the latitude to be used for a radius selection. :type longitude: float :param longitude: Specify the longitude to be used for a radius selection. :type minradius: float :param minradius: Only include stations/channels within the specified minimum number of degrees from the geographic point defined by the latitude and longitude parameters. :type maxradius: float :param maxradius: Only include stations/channels within the specified maximum number of degrees from the geographic point defined by the latitude and longitude parameters. :type keep_empty: bool :param keep_empty: If set to `True`, stations that match themselves but have no matching child elements (channels) will be included in the result. This flag has no effect for initially empty stations which will always be retained if they are matched by the other parameters. """ stations = [] for sta in self.stations: # skip if any given criterion is not matched if station is not None: if not fnmatch.fnmatch(sta.code.upper(), station.upper()): continue if any([t is not None for t in (time, starttime, endtime)]): if not sta.is_active( time=time, starttime=starttime, endtime=endtime): continue geo_filters = dict(minlatitude=minlatitude, maxlatitude=maxlatitude, minlongitude=minlongitude, maxlongitude=maxlongitude, latitude=latitude, longitude=longitude, minradius=minradius, maxradius=maxradius) if any(value is not None for value in geo_filters.values()): if not inside_geobounds(sta, **geo_filters): continue has_channels = bool(sta.channels) sta_ = sta.select(location=location, channel=channel, time=time, starttime=starttime, endtime=endtime, sampling_rate=sampling_rate, minlatitude=minlatitude, maxlatitude=maxlatitude, minlongitude=minlongitude, maxlongitude=maxlongitude, latitude=latitude, longitude=longitude, minradius=minradius, maxradius=maxradius) # If the station previously had channels but no longer has any # and keep_empty is False: Skip the station. if has_channels and not keep_empty and not sta_.channels: continue stations.append(sta_) net = copy.copy(self) net.stations = stations return net