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-23 12:34 +0000

1# http://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

4# ---|P------/S----------~Lg---------- 

5 

6''' 

7Synthetic GNSS data generator. 

8''' 

9 

10import logging 

11import os.path as op 

12import numpy as num 

13 

14from pyrocko import gf, util 

15from pyrocko.guts import Float, List 

16 

17from .base import TargetGenerator, NoiseGenerator 

18from ..station import RandomStationGenerator, StationGenerator 

19 

20DEFAULT_STORE_ID = 'ak135_static' 

21 

22logger = logging.getLogger('pyrocko.scenario.targets.gnss_campaign') 

23guts_prefix = 'pf.scenario' 

24 

25 

26class GPSNoiseGenerator(NoiseGenerator): 

27 measurement_duarion_days = Float.T( 

28 default=2., 

29 help='Measurement duration in days') 

30 

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!') 

35 

36 for ista, sta in enumerate(campaign.stations): 

37 pass 

38 # rstate = self.get_rstate(ista) 

39 

40 # sta.north.sigma = 8e-3 

41 # sta.east.sigma = 8e-3 

42 

43 # sta.north.shift += rstate.normal(0., sta.north.sigma) 

44 # sta.east.shift += rstate.normal(0., sta.east.sigma) 

45 

46 

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.') 

54 

55 noise_generator = NoiseGenerator.T( 

56 default=GPSNoiseGenerator.D(), 

57 optional=True, 

58 help='Add Synthetic noise to the GNSS displacements.') 

59 

60 store_id = gf.StringID.T( 

61 default=DEFAULT_STORE_ID, 

62 help='The GF store to use for forward-calculations.') 

63 

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 

69 

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]) 

74 

75 target = gf.GNSSCampaignTarget( 

76 lats=lats, 

77 lons=lons, 

78 store_id=self.store_id) 

79 

80 return [target] 

81 

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 [] 

92 

93 campaigns = [r.campaign for r in resp.static_results()] 

94 

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 

102 

103 for ista, sta in enumerate(stacked_campaign.stations): 

104 sta.code = 'SY%02d' % (ista + 1) 

105 

106 if self.noise_generator is not None: 

107 self.noise_generator.add_noise(stacked_campaign) 

108 

109 return [stacked_campaign] 

110 

111 def ensure_data(self, engine, sources, path, tmin=None, tmax=None): 

112 path_gnss = op.join(path, 'gnss') 

113 util.ensuredir(path_gnss) 

114 

115 networks = [] 

116 for sg in self.station_generators: 

117 try: 

118 networks.append(sg.network_name) 

119 except AttributeError: 

120 pass 

121 

122 fn = op.join( 

123 path_gnss, 

124 'campaign-%s.yml' % '_'.join(networks)) 

125 

126 if op.exists(fn): 

127 return 

128 

129 campaigns = self.get_gnss_campaigns(engine, sources, tmin, tmax) 

130 

131 with open(fn, 'w') as f: 

132 for camp in campaigns: 

133 camp.dump(stream=f) 

134 

135 def add_map_artists(self, engine, sources, automap): 

136 automap.add_gnss_campaign(self.get_gnss_campaigns(engine, sources)[0])