1# http://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

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

5 

6import os.path as op 

7 

8from pyrocko import moment_tensor 

9from pyrocko.guts import Timestamp, Float, Int, Bool, String, load_all 

10 

11from ..base import LocationGenerator 

12from ..error import ScenarioError 

13 

14km = 1e3 

15guts_prefix = 'pf.scenario' 

16 

17 

18class SourceGenerator(LocationGenerator): 

19 

20 nevents = Int.T(default=2) 

21 avoid_water = Bool.T( 

22 default=False, 

23 help='Avoid sources offshore under the ocean / lakes.') 

24 

25 time_min = Timestamp.T(default=Timestamp.D('2017-01-01 00:00:00')) 

26 time_max = Timestamp.T(default=Timestamp.D('2017-01-03 00:00:00')) 

27 

28 magnitude_min = Float.T( 

29 default=4.0, 

30 help='minimum moment magnitude') 

31 magnitude_max = Float.T( 

32 optional=True, 

33 help='if set, maximum moment magnitude for a uniform distribution. ' 

34 'If set to ``None``, magnitudes are drawn using a ' 

35 'Gutenberg-Richter distribution, see :gattr:`b_value`.') 

36 b_value = Float.T( 

37 optional=True, 

38 help='b-value for Gutenberg-Richter magnitude distribution. If unset, ' 

39 'a value of 1 is assumed.') 

40 

41 source_file = String.T( 

42 optional=True, 

43 help='Path to source file. Sources are used as scenario events') 

44 

45 def __init__(self, *args, **kwargs): 

46 super(SourceGenerator, self).__init__(*args, **kwargs) 

47 if self.b_value is not None and self.magnitude_max is not None: 

48 raise ScenarioError( 

49 '%s: b_value and magnitude_max are mutually exclusive.' 

50 % self.__class__.__name__) 

51 

52 def draw_magnitude(self, rstate): 

53 if self.b_value is None and self.magnitude_max is None: 

54 b_value = 1.0 

55 else: 

56 b_value = self.b_value 

57 

58 if b_value is None: 

59 return rstate.uniform(self.magnitude_min, self.magnitude_max) 

60 else: 

61 return moment_tensor.rand_to_gutenberg_richter( 

62 rstate.rand(), b_value, magnitude_min=self.magnitude_min) 

63 

64 def get_sources(self): 

65 sources = [] 

66 

67 if self.source_file is not None: 

68 sources = load_all(filename=self.source_file) 

69 self.nevents = len(sources) 

70 

71 for ievent in range(self.nevents): 

72 sources[ievent].name = 'scenario_ev%03d' % (ievent + 1) 

73 

74 for ievent in range(self.nevents): 

75 src = self.get_source(ievent) 

76 src.name = 'scenario_ev%03d' % (ievent + 1) 

77 sources.append(src) 

78 

79 return sources 

80 

81 def ensure_data(self, path): 

82 fn_sources = op.join(path, 'sources.yml') 

83 if not op.exists(fn_sources): 

84 with open(fn_sources, 'w') as f: 

85 for src in self.get_sources(): 

86 f.write(src.dump()) 

87 

88 fn_events = op.join(path, 'events.txt') 

89 if not op.exists(fn_events): 

90 with open(fn_events, 'w') as f: 

91 for isrc, src in enumerate(self.get_sources()): 

92 f.write(src.pyrocko_event().dump()) 

93 

94 def add_map_artists(self, automap): 

95 pass