def add_stations(self, stations=None, pyrocko_stations_filename=None, stationxml_filenames=None): if stations is not None: for station in stations: self.stations[station.nsl()] = station if pyrocko_stations_filename is not None: logger.debug('loading stations from file %s' % pyrocko_stations_filename) for station in model.load_stations(pyrocko_stations_filename): self.stations[station.nsl()] = station if stationxml_filenames is not None and len(stationxml_filenames) > 0: for stationxml_filename in stationxml_filenames: logger.debug('loading stations from StationXML file %s' % stationxml_filename) sx = fs.load_xml(filename=stationxml_filename) for station in sx.get_pyrocko_stations(): channels = station.get_channels() if len(channels) == 1 and channels[0].name.endswith('Z'): logger.warning( 'Station %s has vertical component' ' information only, adding mocked channels.' % station.nsl_string()) station.add_channel(model.Channel('N')) station.add_channel(model.Channel('E')) self.stations[station.nsl()] = station
def testIOStations(self): tempdir = self.make_tempdir() fn = pjoin(tempdir, 'stations.txt') ne = model.Channel('NE', azimuth=45., dip=0.) se = model.Channel('SE', azimuth=135., dip=0.) stations = [ model.Station('', sta, '', 0., 0., 0., channels=[ne, se]) for sta in ['STA1', 'STA2']] model.dump_stations(stations, fn) stations = model.load_stations(fn)
def testMissingComponents(self): ne = model.Channel('NE', azimuth=45., dip=0.) se = model.Channel('SE', azimuth=135., dip=0.) station = model.Station('', 'STA', '', 0., 0., 0., channels=[ne, se]) mat = station.projection_to_enu(('NE', 'SE', 'Z'), ('E', 'N', 'U'))[0] assertOrtho(mat[:, 0], mat[:, 1], mat[:, 2]) n = model.Channel('D', azimuth=0., dip=90.) station.set_channels([n]) mat = station.projection_to_enu(('N', 'E', 'D'), ('E', 'N', 'U'))[0] assertOrtho(mat[:, 0], mat[:, 1], mat[:, 2])
def testIOStations(self): tempdir = tempfile.mkdtemp(prefix='pyrocko-model') fn = pjoin(tempdir, 'stations.txt') ne = model.Channel('NE', azimuth=45., dip=0.) se = model.Channel('SE', azimuth=135., dip=0.) stations = [ model.Station('', sta, '', 0., 0., 0., channels=[ne, se]) for sta in ['STA1', 'STA2'] ] model.dump_stations(stations, fn) stations = model.load_stations(fn) shutil.rmtree(tempdir)
def grok_station_xml(data, tmin, tmax): stations = {} for (sta, sta_epo, cha, cha_epo) in xmlzip(data, ( 'Station', 'StationEpoch', 'Channel', 'Epoch')): sta_beg, sta_end, cha_beg, cha_end = [tdatetime(x) for x in ( sta_epo.StartDate, sta_epo.EndDate, cha_epo.StartDate, cha_epo.EndDate)] if not (sta_beg <= tmin and tmax <= sta_end and cha_beg <= tmin and tmax <= cha_end): continue nslc = tuple([str(x.strip()) for x in ( sta.net_code, sta.sta_code, cha.loc_code, cha.chan_code)]) lat, lon, ele, dep, azi, dip = [ float(cha_epo.attrs[x]) for x in 'Lat Lon Elevation Depth Azimuth Dip'.split()] nsl = nslc[:3] if nsl not in stations: stations[nsl] = model.Station( nsl[0], nsl[1], nsl[2], lat, lon, ele, dep) stations[nsl].add_channel(model.Channel(nslc[-1], azi, dip)) return stations.values()
def testProjection(self): s2 = math.sqrt(2.) ndata = num.array([s2,s2], dtype=num.float) edata = num.array([s2,0.], dtype=num.float) ddata = num.array([1.,-1.], dtype=num.float) dt = 1.0 n = trace.Trace(deltat=dt, ydata=ndata, tmin=100, channel='N') e = trace.Trace(deltat=dt, ydata=edata, tmin=100, channel='E') d = trace.Trace(deltat=dt, ydata=ddata, tmin=100, channel='D') azi = 45. cazi = math.cos(azi*d2r) sazi = math.sin(azi*d2r) rot45 = num.array([[cazi, sazi, 0],[-sazi,cazi, 0], [0,0,-1]], dtype=num.float) C = lambda x: model.Channel(x) rotated = trace.project([n,e,d], rot45, [C('N'),C('E'),C('D')], [C('R'),C('T'),C('U')]) for tr in rotated: if tr.channel == 'R': r = tr if tr.channel == 'T': t = tr if tr.channel == 'U': u = tr assert( num.all(r.get_ydata() - num.array([ 2., 1. ]) < 1.0e-6 ) ) assert( num.all(t.get_ydata() - num.array([ 0., -1 ]) < 1.0e-6 ) ) assert( num.all(u.get_ydata() - num.array([ -1., 1. ]) < 1.0e-6 ) ) deps = trace.project_dependencies(rot45, [C('N'),C('E'),C('D')], [C('R'),C('T'),C('U')]) assert( set(['N','E']) == set(deps['R']) and set(['N', 'E']) == set(deps['T']) and set(['D']) == set(deps['U']) ) # should work though no horizontals given projected = trace.project([d], rot45, [C('N'),C('E'),C('D')], [C('R'),C('T'),C('U')]) if tr.channel == 'U': u = tr assert( num.all(u.get_ydata() - num.array([ -1., 1. ]) < 1.0e-6 ) )
def add_stations(self, stations=None, pyrocko_stations_filename=None, stationxml_filenames=None): if stations is not None: for station in stations: self.stations[station.nsl()] = station if pyrocko_stations_filename is not None: logger.debug('Loading stations from file "%s"...' % pyrocko_stations_filename) for station in model.load_stations(pyrocko_stations_filename): self.stations[station.nsl()] = station if stationxml_filenames is not None and len(stationxml_filenames) > 0: for stationxml_filename in stationxml_filenames: if not op.exists(stationxml_filename): continue logger.debug('Loading stations from StationXML file "%s"...' % stationxml_filename) sx = fs.load_xml(filename=stationxml_filename) ev = self.get_event() stations = sx.get_pyrocko_stations(time=ev.time) if len(stations) == 0: logger.warning( 'No stations found for time %s in file "%s".' % (util.time_to_str(ev.time), stationxml_filename)) for station in stations: logger.debug('Adding station: %s.%s.%s' % station.nsl()) channels = station.get_channels() if len(channels) == 1 and channels[0].name.endswith('Z'): logger.warning( 'Station "%s" has vertical component' ' information only, adding mocked channels.' % station.nsl_string()) station.add_channel( model.Channel(channels[0].name[:-1] + 'N')) station.add_channel( model.Channel(channels[0].name[:-1] + 'E')) self.stations[station.nsl()] = station
def load_data_traces(datadir, stations, load_channels=[], name_prefix=None, name_suffix=None, data_format='mseed', divider='-', convert=False, no_network=False): """ Load data traces for the given stations from datadir. """ data_trcs = [] # (r)ight transverse, (a)way radial, vertical (u)p for station in stations: if not load_channels: channels = station.channels else: channels = [model.Channel(name=cha) for cha in load_channels] for channel in channels: if no_network: trace_name = divider.join( (station.station, station.location, channel.name)) else: trace_name = divider.join((station.network, station.station, station.location, channel.name)) if name_suffix: trace_name = divider.join((trace_name, name_suffix)) if name_prefix: trace_name = divider.join((name_prefix, trace_name)) tracepath = os.path.join(datadir, trace_name) try: with open(tracepath): dt = io.load(tracepath, format=data_format)[0] # [nm] convert to m if convert: dt.set_ydata(dt.ydata * m) dt.set_channel(channel.name) dt.set_station(station.station) dt.set_network(station.network) dt.set_location('0') # convert to BEAT seismic Dataset data_trcs.append( heart.SeismicDataset.from_pyrocko_trace(dt)) except IOError: logger.warn('Unable to open file: ' + trace_name) return data_trcs
def _get_channel_description_from_file(self, nslc): fnt = pjoin(self._dirpath, 'component-%s.txt' % st_nslc) fn = fnt % dict(zip( ('network', 'station', 'location', 'channel'), nslc)) if os.path.exists(fn): f = open(fn,'r') gain, azimuth, dip = [ float(x) for x in f.read().split() ] f.close() return model.Channel(nslc[3], azimuth, dip, gain=gain) else: raise FileNotFound(fn)
def pyrocko_station_from_channels(nsl, channels, inconsistencies='warn'): pos = lat, lon, elevation, depth = \ channels[0].position_values if not all(pos == x.position_values for x in channels): info = '\n'.join(' %s: %s' % (x.code, x.position_values) for x in channels) mess = 'encountered inconsistencies in channel ' \ 'lat/lon/elevation/depth ' \ 'for %s.%s.%s: \n%s' % (nsl + (info,)) if inconsistencies == 'raise': raise InconsistentChannelLocations(mess) elif inconsistencies == 'warn': logger.warn(mess) logger.warn(' -> using mean values') apos = num.array([x.position_values for x in channels], dtype=num.float) mlat, mlon, mele, mdep = num.nansum(apos, axis=0) \ / num.sum(num.isfinite(apos), axis=0) groups = {} for channel in channels: if channel.code not in groups: groups[channel.code] = [] groups[channel.code].append(channel) pchannels = [] for code in sorted(groups.keys()): data = [(channel.code, value_or_none(channel.azimuth), value_or_none(channel.dip)) for channel in groups[code]] azimuth, dip = util.consistency_merge( data, message='channel orientation values differ:', error=inconsistencies) pchannels.append(model.Channel(code, azimuth=azimuth, dip=dip)) return model.Station(*nsl, lat=mlat, lon=mlon, elevation=mele, depth=mdep, channels=pchannels)
def to_station(self): net, sta, loc, cha = self.sc_name.nslc() station = model.Station( network=net, station=sta, location=loc, lat=self.st_lat, lon=self.st_long, elevation=self.elev) station.add_channel( model.Channel( name=cha, azimuth=self.azim, dip=self.incid - 90.)) return station
def pyrocko_station_from_channels(nsl, channels, inconsistencies='warn'): pos = lat, lon, elevation, depth = \ channels[0].position_values if not all(pos == x.position_values for x in channels): info = '\n'.join(' %s: %s' % (x.code, x.position_values) for x in channels) mess = 'encountered inconsistencies in channel ' \ 'lat/lon/elevation/depth ' \ 'for %s.%s.%s: \n%s' % (nsl + (info,)) if inconsistencies == 'raise': raise InconsistentChannelLocations(mess) elif inconsistencies == 'warn': logger.warn(mess) logger.warn(' -> using mean values') apos = num.array([x.position_values for x in channels], dtype=num.float) mlat, mlon, mele, mdep = num.nansum(apos, axis=0) / num.sum( num.isfinite(apos), axis=0) pchannels = [] for channel in channels: pchannels.append( model.Channel(channel.code, azimuth=value_or_none(channel.azimuth), dip=value_or_none(channel.dip))) return model.Station(*nsl, lat=mlat, lon=mlon, elevation=mele, depth=mdep, channels=pchannels)
def read_station_header_file(fn): def m(i, *args): if len(ltoks) >= i + len(args) \ and (tuple(ltoks[i:i+len(args)]) == args): return True return False def f(i): return float(toks[i]) def s(i): if len(toks) > i: return toks[i] else: return '' with open(fn, 'r') as fi: stations = [] atsec, station, channel = None, None, None for line in fi: toks = line.split() ltoks = line.lower().split() if m(2, 'station', 'header'): atsec = 'station' station = {'channels': []} stations.append(station) continue if m(2, 'station') and m(5, 'channel'): atsec = 'channel' channel = {} station['channels'].append(channel) continue if atsec == 'station': if m(1, 'station', 'code:'): station['station'] = s(3) elif m(1, 'network', 'code:'): station['network'] = s(3) elif m(1, 'name:'): station['name'] = ' '.join(toks[2:]) if atsec == 'channel': if m(1, 'channel:'): channel['channel'] = s(2) elif m(1, 'location:'): channel['location'] = s(2) elif m(1, 'latitude:'): station['lat'] = f(2) elif m(1, 'longitude:'): station['lon'] = f(2) elif m(1, 'elevation:'): station['elevation'] = f(2) elif m(1, 'local', 'depth:'): channel['depth'] = f(3) elif m(1, 'azimuth:'): channel['azimuth'] = f(2) elif m(1, 'dip:'): channel['dip'] = f(2) nsl_stations = {} for station in stations: for channel in station['channels']: def cs(k, default=None): return channel.get(k, station.get(k, default)) nsl = station['network'], station['station'], channel['location'] if nsl not in nsl_stations: nsl_stations[nsl] = model.Station(network=station['network'], station=station['station'], location=channel['location'], lat=cs('lat'), lon=cs('lon'), elevation=cs('elevation'), depth=cs('depth', None), name=station['name']) nsl_stations[nsl].add_channel( model.Channel(channel['channel'], azimuth=channel['azimuth'], dip=channel['dip'])) return list(nsl_stations.values())
def C(x): return model.Channel(x)
from tunguska import source from tunguska import receiver from tunguska import gfdb as gfdb_mod from tunguska import seismosizer from tunguska import gridsearch import numpy as num def get_nsl(x): return x.network, x.station, x.location kiwi_channels = { 'u': model.Channel('u', azimuth=0., dip=-90.), 'd': model.Channel('d', azimuth=0., dip=90.), 'e': model.Channel('e', azimuth=90., dip=0.), 'w': model.Channel('w', azimuth=-90., dip=0.), 'n': model.Channel('n', azimuth=0., dip=0.), 's': model.Channel('s', azimuth=180., dip=0.), 'a': model.Channel('a'), 'c': model.Channel('c'), 'r': model.Channel('r'), 'l': model.Channel('l'), } kiwi_component_map_default = { 'N': 'n', 'S': 's', 'E': 'e',
def _get_channel_description_from_file(self, nslc): return model.Channel(nslc[3], None, None, 1.)
def get_pyrocko_stations(self, time=None, timespan=None, inconsistencies='warn'): tt = () if time is not None: tt = (time, ) elif timespan is not None: tt = timespan by_nsl = {} for nslc in self._content.keys(): nsl = nslc[:3] for channel in self._content[nslc]: if channel.spans(*tt): if nsl not in by_nsl: by_nsl[nsl] = [] by_nsl[nsl].append(channel) pstations = [] for nsl, channels in by_nsl.iteritems(): vals = [] for channel in channels: vals.append((channel.lat, channel.lon, channel.depth, channel.elevation)) lats, lons, depths, elevations = zip(*vals) same = station.same inconsistencies = not (same(lats) and same(lons) and same(depths) and same(elevations)) if inconsistencies == 'raise': raise InconsistentChannelLocations( 'encountered inconsistencies in channel ' 'lat/lon/elevation/depth ' 'for %s.%s.%s: \n%s' % (nsl + (info, ))) elif inconsistencies == 'warn': logger.warn('cannot create station object for ' '%s.%s.%s due to inconsistencies in ' 'channel lat/lon/elevation/depth\n%s' % (nsl + (info, ))) continue pchannels = [] for channel in channels: pchannels.append( model.Channel(channel.nslc[-1], azimuth=channel.azimuth, dip=channel.dip)) pstations.append( model.Station(*nsl, lat=num.mean(lats), lon=num.mean(lons), elevation=num.mean(elevations), depth=num.mean(depths), channels=pchannels)) return pstations