Coverage for /usr/local/lib/python3.11/dist-packages/pyrocko/scenario/targets/gnss_campaign.py: 74%
70 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-10-04 09:52 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2023-10-04 09:52 +0000
1# http://pyrocko.org - GPLv3
2#
3# The Pyrocko Developers, 21st Century
4# ---|P------/S----------~Lg----------
6'''
7Synthetic GNSS data generator.
8'''
10import logging
11import os.path as op
12import numpy as num
14from pyrocko import gf, util
15from pyrocko.guts import Float, List
17from .base import TargetGenerator, NoiseGenerator
18from ..station import RandomStationGenerator, StationGenerator
20DEFAULT_STORE_ID = 'ak135_static'
22logger = logging.getLogger('pyrocko.scenario.targets.gnss_campaign')
23guts_prefix = 'pf.scenario'
26class GPSNoiseGenerator(NoiseGenerator):
27 measurement_duarion_days = Float.T(
28 default=2.,
29 help='Measurement duration in days')
31 def add_noise(self, campaign):
32 # https://www.nat-hazards-earth-syst-sci.net/15/875/2015/nhess-15-875-2015.pdf
33 waterlevel = 1. - (.99 + .0015 * self.measurement_duarion_days) # noqa
34 logger.warning('GPSNoiseGenerator is a work-in-progress!')
36 for ista, sta in enumerate(campaign.stations):
37 pass
38 # rstate = self.get_rstate(ista)
40 # sta.north.sigma = 8e-3
41 # sta.east.sigma = 8e-3
43 # sta.north.shift += rstate.normal(0., sta.north.sigma)
44 # sta.east.shift += rstate.normal(0., sta.east.sigma)
47class GNSSCampaignGenerator(TargetGenerator):
48 station_generators = List.T(
49 StationGenerator.T(),
50 default=[RandomStationGenerator.D(
51 network_name='GN',
52 channels=None)],
53 help='The StationGenerator.')
55 noise_generator = NoiseGenerator.T(
56 default=GPSNoiseGenerator.D(),
57 optional=True,
58 help='Add Synthetic noise to the GNSS displacements.')
60 store_id = gf.StringID.T(
61 default=DEFAULT_STORE_ID,
62 help='The GF store to use for forward-calculations.')
64 def get_stations(self):
65 stations = []
66 for station_generator in self.station_generators:
67 stations.extend(station_generator.get_stations())
68 return stations
70 def get_targets(self):
71 stations = self.get_stations()
72 lats = num.array([s.effective_lat for s in stations])
73 lons = num.array([s.effective_lon for s in stations])
75 target = gf.GNSSCampaignTarget(
76 lats=lats,
77 lons=lons,
78 store_id=self.store_id)
80 return [target]
82 def get_gnss_campaigns(self, engine, sources, tmin=None, tmax=None):
83 try:
84 resp = engine.process(
85 sources,
86 self.get_targets(),
87 nthreads=0)
88 except gf.meta.OutOfBounds:
89 logger.warning('Could not calculate GNSS displacements'
90 " - the GF store's extend is too small!")
91 return []
93 campaigns = [r.campaign for r in resp.static_results()]
95 stacked_campaign = campaigns[0]
96 stacked_campaign.name = 'Scenario Campaign'
97 for camp in campaigns[1:]:
98 for ista, sta in enumerate(camp.stations):
99 stacked_campaign.stations[ista].north.shift += sta.north.shift
100 stacked_campaign.stations[ista].east.shift += sta.east.shift
101 stacked_campaign.stations[ista].up.shift += sta.up.shift
103 for ista, sta in enumerate(stacked_campaign.stations):
104 sta.code = 'SY%02d' % (ista + 1)
106 if self.noise_generator is not None:
107 self.noise_generator.add_noise(stacked_campaign)
109 return [stacked_campaign]
111 def ensure_data(self, engine, sources, path, tmin=None, tmax=None):
112 path_gnss = op.join(path, 'gnss')
113 util.ensuredir(path_gnss)
115 networks = []
116 for sg in self.station_generators:
117 try:
118 networks.append(sg.network_name)
119 except AttributeError:
120 pass
122 fn = op.join(
123 path_gnss,
124 'campaign-%s.yml' % '_'.join(networks))
126 if op.exists(fn):
127 return
129 campaigns = self.get_gnss_campaigns(engine, sources, tmin, tmax)
131 with open(fn, 'w') as f:
132 for camp in campaigns:
133 camp.dump(stream=f)
135 def add_map_artists(self, engine, sources, automap):
136 automap.add_gnss_campaign(self.get_gnss_campaigns(engine, sources)[0])