Coverage for /usr/local/lib/python3.11/dist-packages/grond/targets/waveform_oac/target.py: 43%

70 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-10-26 16:25 +0000

1import logging 

2 

3import numpy as num 

4 

5from pyrocko.guts import Float, Int 

6from pyrocko import gf 

7 

8from ..base import ( 

9 MisfitTarget, TargetGroup, MisfitResult) 

10 

11from ..waveform.target import WaveformPiggybackSubtarget, \ 

12 WaveformPiggybackSubresult 

13 

14guts_prefix = 'grond' 

15logger = logging.getLogger('grond.targets.waveform_piggyback.target') 

16 

17 

18class WOACSubtarget(WaveformPiggybackSubtarget): 

19 

20 def evaluate( 

21 self, tr_proc_obs, trspec_proc_obs, tr_proc_syn, trspec_proc_syn): 

22 

23 a_obs = num.sqrt(num.mean(num.abs(tr_proc_obs.ydata**2))) 

24 a_syn = num.sqrt(num.mean(num.abs(tr_proc_syn.ydata**2))) 

25 

26 res = WOACSubresult( 

27 piggy_id=self.piggy_id, 

28 amplitude_obs=float(a_obs), 

29 amplitude_syn=float(a_syn)) 

30 

31 return res 

32 

33 

34class WOACSubresult(WaveformPiggybackSubresult): 

35 amplitude_obs = Float.T() 

36 amplitude_syn = Float.T() 

37 

38 

39class WaveformOverallAmplitudeConstraint(TargetGroup): 

40 associated_path = gf.StringID.T() 

41 norm_exponent = Int.T(default=2) 

42 

43 def get_targets(self, ds, event, default_path='none'): 

44 logger.debug('Selecting waveform piggyback targets...') 

45 

46 target = WOACTarget( 

47 path=self.path, 

48 norm_exponent=self.norm_exponent, 

49 associated_path=self.associated_path) 

50 

51 return [target] 

52 

53 

54class WOACTarget(MisfitTarget): 

55 associated_path = gf.StringID.T() 

56 norm_exponent = Int.T(default=2) 

57 

58 can_bootstrap_weights = True 

59 

60 def __init__(self, **kwargs): 

61 MisfitTarget.__init__(self, **kwargs) 

62 self.piggy_ids = set() 

63 

64 def string_id(self): 

65 return self.path 

66 

67 def get_plain_targets(self, engine, source): 

68 return [] 

69 

70 def distance_to(self, other): 

71 return num.array([], dtype=float) 

72 

73 def prepare_modelling(self, engine, source, targets): 

74 from ..waveform.target import WaveformMisfitTarget 

75 relevant = [] 

76 for target in targets: 

77 if isinstance(target, WaveformMisfitTarget) \ 

78 and target.path == self.associated_path: 

79 

80 st = WOACSubtarget() 

81 self.piggy_ids.add(st.piggy_id) 

82 target.add_piggyback_subtarget(st) 

83 relevant.append(target) 

84 

85 return relevant 

86 

87 def finalize_modelling( 

88 self, engine, source, modelling_targets, modelling_results): 

89 

90 from ..waveform.target import WaveformMisfitResult 

91 amps = [] 

92 for mtarget, mresult in zip(modelling_targets, modelling_results): 

93 if isinstance(mresult, WaveformMisfitResult): 

94 for sr in list(mresult.piggyback_subresults): 

95 try: 

96 self.piggy_ids.remove(sr.piggy_id) 

97 amps.append((sr.amplitude_obs, sr.amplitude_syn)) 

98 mresult.piggyback_subresults.remove(sr) 

99 except KeyError: 

100 logger.error( 

101 'Found inconsistency while gathering piggyback ' 

102 'results.') 

103 pass 

104 

105 amps = num.array(amps, dtype=float) 

106 mask = num.all(num.isfinite(amps), axis=1) 

107 

108 amp_obs = num.median(amps[mask, 0]) 

109 amp_syn = num.median(amps[mask, 1]) 

110 m = num.abs(num.log(amp_obs / amp_syn))**self.norm_exponent 

111 

112 result = WOACMisfitResult( 

113 misfits=num.array([[m, 1.]], dtype=float)) 

114 

115 return result 

116 

117 

118class WOACMisfitResult(MisfitResult): 

119 pass 

120 

121 

122__all__ = ''' 

123 WOACSubtarget 

124 WOACSubresult 

125 WaveformOverallAmplitudeConstraint 

126 WOACTarget 

127 WOACMisfitResult 

128'''.split()