forked from pyrocko/grond
1
0
Fork 0

initial version

whitelist
Sebastian Heimann 7 years ago
commit 91397f7ca8

2
.gitignore vendored

@ -0,0 +1,2 @@
build
*.pyc

@ -0,0 +1,277 @@
#!/usr/bin/env python
import math
import sys
import logging
from optparse import OptionParser
from pyrocko import util
from pyrocko.gf import Range
import grond
from grond import plot
logger = logging.getLogger('main')
km = 1000.
def d2u(d):
if isinstance(d, dict):
return dict((k.replace('-', '_'), v) for (k, v) in d.iteritems())
else:
return d.replace('-', '_')
subcommand_descriptions = {
'init': 'print example configuration',
'go': 'run Grond optimization',
'forward': 'run forward modelling',
'harvest': 'manually run harvesting',
'map-geometry': 'make station map',
'plot': 'plot optimization result',
'export': 'export results',
}
subcommand_usages = {
'init': 'init [options]',
'go': 'go <configfile> [options]',
'forward': 'forward <rundir> [options]',
'harvest': 'harvest <rundir> [options]',
'map-geometry': 'map-geometry <configfile> [options]',
'plot': 'plot <plotnames> <rundir> [options]',
'export': 'export <rundir> <outputfile> [options]',
}
subcommands = subcommand_descriptions.keys()
program_name = 'grond'
usage_tdata = d2u(subcommand_descriptions)
usage_tdata['program_name'] = program_name
usage = '''%(program_name)s <subcommand> [options] [--] <arguments> ...
Subcommands:
init %(init)s
go %(go)s
forward %(forward)s
harvest %(harvest)s
map-geometry %(map_geometry)s
plot %(plot)s
export %(export)s
To get further help and a list of available options for any subcommand run:
%(program_name)s <subcommand> --help
''' % usage_tdata
def add_common_options(parser):
parser.add_option(
'--loglevel',
action='store',
dest='loglevel',
type='choice',
choices=('critical', 'error', 'warning', 'info', 'debug'),
default='info',
help ='set logger level to '
'"critical", "error", "warning", "info", or "debug". '
'Default is "%default".')
def process_common_options(options):
util.setup_logging(program_name, options.loglevel)
def cl_parse(command, args, setup=None):
usage = subcommand_usages[command]
descr = subcommand_descriptions[command]
if isinstance(usage, basestring):
usage = [usage]
susage = '%s %s' % (program_name, usage[0])
for s in usage[1:]:
susage += '\n%s%s %s' % (' '*7, program_name, s)
parser = OptionParser(
usage=susage,
description=descr[0].upper() + descr[1:] + '.')
if setup:
setup(parser)
add_common_options(parser)
(options, args) = parser.parse_args(args)
process_common_options(options)
return parser, options, args
def die(message, err=''):
if err:
sys.exit('%s: error: %s \n %s' % (program_name, message, err))
else:
sys.exit('%s: error: %s' % (program_name, message))
def help_and_die(parser, message):
parser.print_help(sys.stderr)
sys.stderr.write('\n')
die(message)
def command_init(args):
dataset_config = grond.DatasetConfig(
stations_path='stations.txt',
events_path='events.txt',
waveform_paths=['data'])
target_configs = [grond.TargetConfig(
distance_min=10*km,
distance_max=1000*km,
channels=['Z', 'R', 'T'],
interpolation='multilinear',
store_id='global_2s',
inner_misfit_config=grond.InnerMisfitConfig(
fmin=0.01,
fmax=0.1))]
s2 = math.sqrt(2.0)
problem_config = grond.CMTProblemConfig(
name_template='cmt_%(event_name)s',
distance_min=2.*km,
nbootstrap=100,
mt_type='deviatoric',
ranges=dict(
time=Range(0, 10.0, relative='add'),
north_shift=Range(-16*km, 16*km),
east_shift=Range(-16*km, 16*km),
depth=Range(1*km, 11*km),
magnitude=Range(4.0, 6.0),
rmnn=Range(-s2, s2),
rmee=Range(-s2, s2),
rmdd=Range(-s2, s2),
rmne=Range(-1.0, 1.0),
rmnd=Range(-1.0, 1.0),
rmed=Range(-1.0, 1.0),
duration=Range(1.0, 15.0)))
config = grond.Config(
dataset_config=dataset_config,
target_configs=target_configs,
problem_config=problem_config)
print config
def command_go(args):
def setup(parser):
parser.add_option(
'--force', dest='force', action='store_true',
help='overwrite existing run directory')
parser.add_option(
'--status', dest='status', default='state',
help='status output selection (choices: state, matrix)')
parser, options, args = cl_parse('go', args, setup)
if len(args) != 1:
help_and_die(parser, 'no config file given')
config_path = args[0]
config = grond.read_config(config_path)
if options.status == 'quiet':
status = ()
else:
status = tuple(options.status.split(','))
grond.go(config, force=options.force, status=status)
def command_forward(args):
parser, options, args = cl_parse('forward', args)
if len(args) != 1:
help_and_die(parser, 'incorrect number of arguments')
run_path, = args
grond.forward(run_path)
def command_harvest(args):
def setup(parser):
parser.add_option(
'--force', dest='force', action='store_true',
help='overwrite existing harvest directory')
parser.add_option(
'--neach', dest='neach', type=int, default=10,
help='take NEACH best samples from each chain (default: 10)')
parser, options, args = cl_parse('harvest', args, setup)
if len(args) != 1:
help_and_die(parser, 'no rundir')
run_path, = args
grond.harvest(run_path, force=options.force, nbest=options.neach)
def command_map_geometry(args):
parser, options, args = cl_parse('map-geometry', args)
if len(args) != 2:
help_and_die(parser, 'two arguments required')
config_path = args[0]
output_path = args[1]
config = grond.read_config(config_path)
plot.map_geometry(config, output_path)
def command_plot(args):
parser, options, args = cl_parse('plot', args)
if len(args) != 2:
help_and_die(parser, 'two arguments required')
plotnames = args[0].split(',')
dirname = args[1]
plot.plot_result(dirname, plotnames)
def command_export(args):
parser, options, args = cl_parse('export', args)
if len(args) not in (1, 2):
help_and_die(parser, 'one or two arguments required')
dirname = args[0]
if len(args) == 2:
filename = args[1]
else:
filename = None
grond.export(dirname, filename)
if __name__ == '__main__':
if len(sys.argv) < 2:
sys.exit('Usage: %s' % usage)
args = list(sys.argv)
args.pop(0)
command = args.pop(0)
if command in subcommands:
globals()['command_' + d2u(command)](args)
elif command in ('--help', '-h', 'help'):
if command == 'help' and args:
acommand = args[0]
if acommand in subcommands:
globals()['command_' + acommand](['--help'])
sys.exit('Usage: %s' % usage)
else:
die('no such subcommand: %s' % command)

@ -0,0 +1,13 @@
#!/usr/bin/env python
from distutils.core import setup
setup(
name='grond',
description='What do you want to bust today?!',
author='Sebastian Heimann',
author_email='sebastian.heimann@gfz-potsdam.de',
packages=['grond'],
package_dir={'grond': 'src'},
scripts=['apps/grond'],
package_data={'grond': []})

@ -0,0 +1,3 @@
from core import * # noqa
from cmt import * # noqa
from dataset import * # noqa

@ -0,0 +1,283 @@
import math
import logging
import numpy as num
from pyrocko import gf, moment_tensor as mtm, util
from pyrocko.guts import Float, String, Dict, List, Int, StringChoice
from grond import core
guts_prefix = 'grond'
logger = logging.getLogger('grond.cmt')
km = 1000.
as_km = dict(scale_factor=km, scale_unit='km')
class CMTProblem(core.Problem):
parameters = [
core.Parameter('time', 's'),
core.Parameter('north_shift', 'm', **as_km),
core.Parameter('east_shift', 'm', **as_km),
core.Parameter('depth', 'm', **as_km),
core.Parameter('magnitude'),
core.Parameter('rmnn'),
core.Parameter('rmee'),
core.Parameter('rmdd'),
core.Parameter('rmne'),
core.Parameter('rmnd'),
core.Parameter('rmed'),
core.Parameter('duration')]
dependants = [
core.Parameter('rel_moment_iso'),
core.Parameter('rel_moment_clvd')]
base_source = gf.Source.T()
targets = List.T(core.MisfitTarget.T())
ranges = Dict.T(String.T(), gf.Range.T())
distance_min = Float.T(default=0.0)
nbootstrap = Int.T(default=10)
mt_type = StringChoice.T(choices=['full', 'deviatoric'])
def unpack(self, x):
d = self.parameter_dict(x)
rm6 = num.array([d.rmnn, d.rmee, d.rmdd, d.rmne, d.rmnd, d.rmed],
dtype=num.float)
m0 = mtm.magnitude_to_moment(d.magnitude)
m6 = rm6 * m0
p = {}
for k in self.base_source.keys():
if k in d:
p[k] = float(
self.ranges[k].make_relative(self.base_source[k], d[k]))
stf = gf.HalfSinusoidSTF(duration=float(d.duration))
source = self.base_source.clone(m6=m6, stf=stf, **p)
return source
def make_dependant(self, xs, pname):
if xs.ndim == 1:
return self.make_dependant(xs[num.newaxis, :], pname)[0]
if pname in ('rel_moment_iso', 'rel_moment_clvd'):
y = num.zeros(xs.shape[0])
for i, x in enumerate(xs):
source = self.unpack(x)
mt = source.pyrocko_moment_tensor()
res = mt.standard_decomposition()
if pname == 'rel_moment_iso':
ratio_iso, m_iso = res[0][1:3]
y[i] = ratio_iso * num.sign(m_iso[0, 0])
else:
ratio_clvd, m_clvd = res[2][1:3]
evals, evecs = mtm.eigh_check(m_clvd)
ii = num.argmax(num.abs(evals))
y[i] = ratio_clvd * num.sign(evals[ii])
return y
else:
raise KeyError(pname)
def extract(self, xs, i):
if xs.ndim == 1:
return self.extract(xs[num.newaxis, :], i)[0]
if i < self.nparameters:
return xs[:, i]
else:
return self.make_dependant(
xs, self.dependants[i-self.nparameters].name)
def pack(self, source):
m6 = source.m6
mt = source.pyrocko_moment_tensor()
rm6 = m6 / mt.scalar_moment()
x = num.array([
source.time,
source.north_shift,
source.east_shift,
source.depth,
mt.moment_magnitude(),
] + rm6.tolist() + [source.stf.duration], dtype=num.float)
return x
def preconstrain(self, x):
d = self.parameter_dict(x)
m6 = num.array([d.rmnn, d.rmee, d.rmdd, d.rmne, d.rmnd, d.rmed],
dtype=num.float)
m9 = mtm.symmat6(*m6)
if self.mt_type == 'deviatoric':
trace_m = num.trace(m9)
m_iso = num.diag([trace_m / 3., trace_m / 3., trace_m / 3.])
m9 -= m_iso
m0_unscaled = math.sqrt(num.sum(m9.A**2)) / math.sqrt(2.)
m9 /= m0_unscaled
m6 = mtm.to6(m9)
d.rmnn, d.rmee, d.rmdd, d.rmne, d.rmnd, d.rmed = m6
x = self.parameter_array(d)
source = self.unpack(x)
if any(self.distance_min > source.distance_to(t)
for t in self.targets):
raise core.Forbidden()
return x
def bounds(self):
out = []
for p in self.parameters:
r = self.ranges[p.name]
out.append((r.start, r.stop))
return out
def dependant_bounds(self):
out = [
(-1., 1.),
(-1., 1.)]
return out
def evaluate(self, x, return_traces=False):
source = self.unpack(x)
engine = gf.get_engine()
for target in self.targets:
target.set_return_traces(return_traces)
resp = engine.process(source, self.targets)
data = []
results = []
for source, target, result in resp.iter_results('results'):
if isinstance(result, gf.SeismosizerError):
logger.debug(
'%s.%s.%s.%s: %s' % (target.codes + (str(result),)))
data.append((None, None))
if return_traces:
results.append(None)
else:
data.append((result.misfit_value, result.misfit_norm))
if return_traces:
results.append(result)
ms, ns = num.array(data, dtype=num.float).T
if return_traces:
return ms, ns, results
else:
return ms, ns
def forward(self, x):
source = self.unpack(x)
engine = gf.get_engine()
plain_targets = [target.get_plain_target() for target in self.targets]
resp = engine.process(source, plain_targets)
results = []
for source, target, result in resp.iter_results('results'):
if isinstance(result, gf.SeismosizerError):
logger.debug(
'%s.%s.%s.%s: %s' % (target.codes + (str(result),)))
results.append(None)
else:
results.append(result)
return results
def get_target_weights(self):
if self._target_weights is None:
self._target_weights = num.array(
[target.get_combined_weight(
apply_balancing_weights=self.apply_balancing_weights)
for target in self.targets], dtype=num.float)
return self._target_weights
def bootstrap_misfit(self, ms, ns, ibootstrap=None):
w = self.get_bootstrap_weights(ibootstrap) * self.get_target_weights()
if ibootstrap is None:
return num.sqrt(
num.nansum((w*ms[num.newaxis, :])**2, axis=1) /
num.nansum((w*ns[num.newaxis, :])**2, axis=1))
else:
return num.sqrt(num.nansum((w*ms)**2) / num.nansum((w*ns)**2))
def bootstrap_misfits(self, misfits, ibootstrap):
w = self.get_bootstrap_weights(ibootstrap)[num.newaxis, :] * \
self.get_target_weights()[num.newaxis, :]
bms = num.sqrt(num.nansum((w*misfits[:, :, 0])**2, axis=1) /
num.nansum((w*misfits[:, :, 1])**2, axis=1))
return bms
def global_misfit(self, ms, ns):
ws = self.get_target_weights()
m = num.sqrt(num.nansum((ws*ms)**2) / num.nansum((ws*ns)**2))
return m
def global_misfits(self, misfits):
ws = self.get_target_weights()[num.newaxis, :]
gms = num.sqrt(num.nansum((ws*misfits[:, :, 0])**2, axis=1) /
num.nansum((ws*misfits[:, :, 1])**2, axis=1))
return gms
def global_contributions(self, misfits):
ws = self.get_target_weights()[num.newaxis, :]
gcms = (ws*misfits[:, :, 0])**2 / \
num.nansum((ws*misfits[:, :, 1])**2, axis=1)[:, num.newaxis]
return gcms
class CMTProblemConfig(core.ProblemConfig):
ranges = Dict.T(String.T(), gf.Range.T())
distance_min = Float.T(default=0.0)
nbootstrap = Int.T(default=10)
mt_type = StringChoice.T(choices=['full', 'deviatoric'])
def get_problem(self, event, targets):
if event.depth is None:
event.depth = 0.
base_source = gf.MTSource.from_pyrocko_event(event)
base_source.stf = gf.HalfSinusoidSTF(duration=1.0)
subs = dict(
event_name=event.name,
event_time=util.time_to_str(event.time))
problem = CMTProblem(
name=self.name_template % subs,
apply_balancing_weights=self.apply_balancing_weights,
base_source=base_source,
targets=targets,
ranges=self.ranges,
distance_min=self.distance_min,
nbootstrap=self.nbootstrap,
mt_type=self.mt_type)
return problem
__all__ = [
'CMTProblem',
'CMTProblemConfig',
]

File diff suppressed because it is too large Load Diff

@ -0,0 +1,475 @@
import logging
from collections import defaultdict
import numpy as num
from pyrocko import util, pile, model, config, trace, snuffling
from pyrocko.fdsn import enhanced_sacpz, station as fs
from pyrocko.guts import Object, Tuple, String, Float, dump_all, load_all
logger = logging.getLogger('grond.dataset')
class InvalidObject(Exception):
pass
class NotFound(Exception):
pass
class StationCorrection(Object):
codes = Tuple.T(4, String.T())
delay = Float.T()
factor = Float.T()
def load_station_corrections(filename):
scs = load_all(filename=filename)
for sc in scs:
assert isinstance(sc, StationCorrection)
return scs
def dump_station_corrections(station_corrections, filename):
return dump_all(station_corrections, filename=filename)
class Dataset(object):
def __init__(self):
self.events = []
self.pile = pile.Pile()
self.stations = {}
self.responses = defaultdict(list)
self.responses_stationxml = []
self.clippings = {}
self.blacklist = set()
self.whitelist_nslc = None
self.whitelist_nsl = None
self.station_corrections = {}
self.station_factors = {}
self.apply_correction_delays = True
self.apply_correction_factors = True
self.clip_handling = 'by_nsl'
self.synthetic_test = None
self._cache = {}
def empty_cache(self):
self._cache = {}
def set_synthetic_test(self, synthetic_test):
self.synthetic_test = synthetic_test
def add_stations(self, stations=None, filename=None):
if stations is not None:
for station in stations:
self.stations[station.nsl()] = station
if filename is not None:
for station in model.load_stations(filename):
self.stations[station.nsl()] = station
def add_events(self, events=None, filename=None):
if events is not None:
self.events.extend(events)
if filename is not None:
self.events.extend(model.load_events(filename))
def add_waveforms(self, paths, regex=None, fileformat='detect',
show_progress=True):
cachedirname = config.config().cache_dir
fns = util.select_files(paths, regex=regex,
show_progress=show_progress)
cache = pile.get_cache(cachedirname)
self.pile.load_files(sorted(fns), cache=cache,
fileformat=fileformat,
show_progress=show_progress)
def add_responses(self, sacpz_dirname=None, stationxml_filenames=None):
if sacpz_dirname:
for x in enhanced_sacpz.iload_dirname(sacpz_dirname):
self.responses[x.codes].append(x)
if stationxml_filenames:
for stationxml_filename in stationxml_filenames:
self.responses_stationxml.append(
fs.load_xml(filename=stationxml_filename))
def add_clippings(self, markers_filename):
markers = snuffling.load_markers(markers_filename)
clippings = {}
for marker in markers:
nslc = marker.one_nslc()
nsl = nslc[:3]
if nsl not in clippings:
clippings[nsl] = []
if nslc not in clippings:
clippings[nslc] = []
clippings[nsl].append(marker.tmin)
clippings[nslc].append(marker.tmin)
for k, times in clippings.iteritems():
atimes = num.array(times, dtype=num.float)
if k not in self.clippings:
self.clippings[k] = atimes
else:
self.clippings[k] = num.concatenate(self.clippings, atimes)
def add_blacklist(self, blacklist):
for x in blacklist:
if isinstance(x, basestring):
x = tuple(x.split('.'))
self.blacklist.add(x)
def add_whitelist(self, whitelist):
if self.whitelist_nslc is None:
self.whitelist_nslc = set()
self.whitelist_nsl = set()
self.whitelist_nsl_xx = set()
for x in whitelist:
if isinstance(x, basestring):
x = tuple(x.split('.'))
assert len(x) in (3, 4)
if len(x) == 4:
self.whitelist_nslc.add(x)
self.whitelist_nsl_xx.add(x[:3])
if len(x) == 3:
self.whitelist_nsl.add(x)
def add_station_corrections(self, filename):
self.station_corrections.update(
(sc.codes, sc) for sc in load_station_corrections(filename))
def is_blacklisted(self, obj):
try:
nslc = self.get_nslc(obj)
if nslc in self.blacklist:
return True
except InvalidObject:
pass
nsl = self.get_nsl(obj)
return (
nsl in self.blacklist or
nsl[1:2] in self.blacklist or
nsl[:2] in self.blacklist)
def is_whitelisted(self, obj):
if self.whitelist_nslc is None:
return True
nsl = self.get_nsl(obj)
try:
nslc = self.get_nslc(obj)
if nslc in self.whitelist_nslc:
return True
return nsl in self.whitelist_nsl
except InvalidObject:
return nsl in self.whitelist_nsl_xx or nsl in self.whitelist_nsl
def has_clipping(self, nsl_or_nslc, tmin, tmax):
if nsl_or_nslc not in self.clippings:
return False
atimes = self.clippings[nsl_or_nslc]
return num.any(num.logical_and(tmin < atimes, atimes <= tmax))
def get_nsl(self, obj):
if isinstance(obj, trace.Trace):
net, sta, loc, _ = obj.nslc_id
elif isinstance(obj, model.Station):
net, sta, loc = obj.nsl()
elif isinstance(obj, tuple) and len(obj) in (3, 4):
net, sta, loc = obj[:3]
else:
raise InvalidObject(
'cannot get nsl code from given object of type %s' % type(obj))
return net, sta, loc
def get_nslc(self, obj):
if isinstance(obj, trace.Trace):
return obj.nslc_id
elif isinstance(obj, tuple) and len(obj) == 4:
return obj
else:
raise InvalidObject(
'cannot get nslc code from given object %s' % type(obj))
def get_tmin_tmax(self, obj):
if isinstance(obj, trace.Trace):
return obj.tmin, obj.tmax
else:
raise InvalidObject(
'cannot get tmin and tmax from given object of type %s' %
type(obj))
def get_station(self, obj):
if self.is_blacklisted(obj):
raise NotFound('station is blacklisted', self.get_nsl(obj))
if not self.is_whitelisted(obj):
raise NotFound('station is not on whitelist', self.get_nsl(obj))
if isinstance(obj, model.Station):
return obj
net, sta, loc = self.get_nsl(obj)
keys = [(net, sta, loc), (net, sta, ''), ('', sta, '')]
for k in keys:
if k in self.stations:
return self.stations[k]
raise NotFound('station', keys)
def get_stations(self):
return [self.stations[k] for k in sorted(self.stations)
if not self.is_blacklisted(self.stations[k])
and self.is_whitelisted(self.stations[k])]
def get_response(self, obj):
if self.is_blacklisted(obj):
raise NotFound('response is blacklisted', self.get_nslc(obj))
if not self.is_whitelisted(obj):
raise NotFound('response is not on whitelist', self.get_nslc(obj))
net, sta, loc, cha = self.get_nslc(obj)
tmin, tmax = self.get_tmin_tmax(obj)
keys_x = [
(net, sta, loc, cha), (net, sta, '', cha), ('', sta, '', cha)]
keys = []
for k in keys_x:
if k not in keys:
keys.append(k)
candidates = []
for k in keys:
if k in self.responses:
for x in self.responses[k]:
if x.tmin < tmin and (x.tmax is None or tmax < x.tmax):
candidates.append(x.response)
for sx in self.responses_stationxml:
try:
candidates.append(
sx.get_pyrocko_response(
(net, sta, loc, cha),
timespan=(tmin, tmax),
fake_input_units='M'))
except fs.NoResponseInformation, fs.MultipleResponseInformation:
pass
if len(candidates) == 1:
return candidates[0]
elif len(candidates) == 0:
raise NotFound('no response', (net, sta, loc, cha))
else:
raise NotFound('multiple responses', (net, sta, loc, cha))
def get_waveforms_raw(self, obj, tmin=None, tmax=None, tpad=0.):
net, sta, loc = self.get_nsl(obj)
trs = self.pile.all(
tmin=tmin, tmax=tmax, tpad=tpad,
trace_selector=lambda tr: tr.nslc_id[:3] == (net, sta, loc),
want_incomplete=False)
return trs
def get_waveform_raw(self, obj, tmin=None, tmax=None, tpad=0.):
net, sta, loc, cha = self.get_nslc(obj)
if self.is_blacklisted((net, sta, loc, cha)):
raise NotFound(
'waveform is blacklisted', (net, sta, loc, cha))
if not self.is_whitelisted((net, sta, loc, cha)):
raise NotFound(
'waveform is not on whitelist', (net, sta, loc, cha))
if self.clip_handling == 'by_nsl':
if self.has_clipping((net, sta, loc), tmin, tmax):
raise NotFound(
'waveform clipped', (net, sta, loc))
elif self.clip_handling == 'by_nslc':
if self.has_clipping((net, sta, loc, cha), tmin, tmax):
raise NotFound(
'waveform clipped', (net, sta, loc, cha))
trs = self.pile.all(
tmin=tmin, tmax=tmax, tpad=tpad,
trace_selector=lambda tr: tr.nslc_id == (net, sta, loc, cha),
want_incomplete=False)
if len(trs) == 1:
return trs[0]
else:
raise NotFound(
'waveform missing or incomplete', (net, sta, loc, cha))
def get_waveform_restituted(
self,
obj, quantity='displacement',
tmin=None, tmax=None, tpad=0.,
tfade=0., freqlimits=None, deltat=None):
tr = self.get_waveform_raw(obj, tmin=tmin, tmax=tmax, tpad=tpad+tfade)
if deltat is not None:
tr.downsample_to(deltat, snap=True)
resp = self.get_response(tr)
return tr.transfer(tfade=tfade, freqlimits=freqlimits,
transfer_function=resp, invert=True)
def get_waveform(
self,
obj, quantity='displacement',
tmin=None, tmax=None, tpad=0.,
tfade=0., freqlimits=None, deltat=None, cache=None,
backazimuth=None,
source=None,
target=None):
if cache is True:
cache = self._cache
_, _, _, channel = self.get_nslc(obj)
station = self.get_station(self.get_nsl(obj))
nslc = station.nsl() + (channel,)
if tmin is not None:
tmin = float(tmin)
if tmax is not None:
tmax = float(tmax)
if cache is not None and (nslc, tmin, tmax) in cache:
obj = cache[nslc, tmin, tmax]
if isinstance(obj, Exception):
raise obj
else:
return obj
if self.synthetic_test:
tr = self.synthetic_test.get_waveform(
nslc, tmin, tmax,
tfade=tfade, freqlimits=freqlimits)
if cache is not None:
cache[tr.nslc_id, tmin, tmax] = tr
return tr
abs_delays = []
for ocha in 'ENZRT':
sc = self.station_corrections.get(station.nsl() + (channel,), None)
if sc:
abs_delays.append(abs(sc.delay))
if abs_delays:
abs_delay_max = max(abs_delays)
else:
abs_delay_max = 0.0
mios = []
mios.extend(station.guess_projections_to_enu(
out_channels=('E', 'N', 'Z')))
if source is not None and target is not None:
backazimuth = source.azibazi_to(target)[1]
if backazimuth is not None:
mios.extend(station.guess_projections_to_rtu(
out_channels=('R', 'T', 'Z'),
backazimuth=backazimuth))
try:
trs_projected = []
for matrix, in_channels, out_channels in mios:
deps = trace.project_dependencies(
matrix, in_channels, out_channels)
trs = []
if channel in deps:
for cha in deps[channel]:
trs.append(self.get_waveform_restituted(
station.nsl() + (cha,),
tmin=tmin, tmax=tmax, tpad=tpad+abs_delay_max,
tfade=tfade, freqlimits=freqlimits, deltat=deltat))
trs_projected.extend(
trace.project(trs, matrix, in_channels, out_channels))
for tr in trs_projected:
sc = self.station_corrections.get(tr.nslc_id, None)
if sc:
if self.apply_correction_factors:
tr.ydata /= sc.factor
if self.apply_correction_delays:
tr.shift(-sc.delay)
if tmin is not None and tmax is not None:
tr.chop(tmin, tmax)
if cache is not None:
for tr in trs_projected:
cache[tr.nslc_id, tmin, tmax] = tr
for tr in trs_projected:
if tr.channel == channel:
return tr
raise NotFound('waveform', station.nsl() + (channel,))
except NotFound, e:
cache[nslc, tmin, tmax] = e
raise
def get_events(self, magmin=None):
evs = []
for ev in self.events:
if magmin is None or ev.magnitude >= magmin:
evs.append(ev)
return evs
def get_event(self, t, magmin=None):
evs = self.get_events(magmin=magmin)
ev_x = None
for ev in evs:
if ev_x is None or abs(ev.time - t) < abs(ev_x.time - t):
ev_x = ev
if not ev_x:
raise NotFound
return ev_x
__all__ = '''
InvalidObject
NotFound
StationCorrection
Dataset
load_station_corrections
dump_station_corrections
'''.split()

File diff suppressed because it is too large Load Diff

@ -0,0 +1,49 @@
import unittest
from pyrocko import util
from grond import HasPaths, Path
class PathTestCase(unittest.TestCase):
def test_pathstuff(self):
class B(HasPaths):
p1 = Path.T()
p2 = Path.T()
class A(HasPaths):
p1 = Path.T()
p2 = Path.T()
b = B.T()
for path_prefix_a in (
None, 'relative_prefix_a', '/absolute_prefix_a'):
for path_prefix_b in (
None, 'relative_prefix_b', '/absolute_prefix_b'):
a = A(
path_prefix=path_prefix_a,
p1='abc/x.txt',
p2='/absolute/x.txt',
b=B(
path_prefix=path_prefix_b,
p1='abc/y.txt',
p2='/absolute/y.txt'))
a.set_basepath('rundir')
t1 = a.expand_path(a.p1)
t2 = a.expand_path(a.p2)
t3 = a.b.expand_path(a.b.p1)
t4 = a.b.expand_path(a.b.p2)
a.change_basepath('resultdir')
assert t1 == a.expand_path(a.p1)
assert t2 == a.expand_path(a.p2)
assert t3 == a.b.expand_path(a.b.p1)
assert t4 == a.b.expand_path(a.b.p2)
if __name__ == '__main__':
util.setup_logging('test_path', 'warning')
unittest.main()
Loading…
Cancel
Save