1# http://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

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

5from __future__ import absolute_import, division, print_function 

6 

7import os.path as op 

8 

9from pyrocko import moment_tensor 

10from pyrocko.guts import Timestamp, Float, Int, Bool 

11 

12from ..base import LocationGenerator 

13from ..error import ScenarioError 

14 

15km = 1e3 

16guts_prefix = 'pf.scenario' 

17 

18 

19class SourceGenerator(LocationGenerator): 

20 

21 nevents = Int.T(default=2) 

22 avoid_water = Bool.T( 

23 default=False, 

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

25 

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

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

28 

29 magnitude_min = Float.T( 

30 default=4.0, 

31 help='minimum moment magnitude') 

32 magnitude_max = Float.T( 

33 optional=True, 

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

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

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

37 b_value = Float.T( 

38 optional=True, 

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

40 'a value of 1 is assumed.') 

41 

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

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

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

45 raise ScenarioError( 

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

47 % self.__class__.__name__) 

48 

49 def draw_magnitude(self, rstate): 

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

51 b_value = 1.0 

52 else: 

53 b_value = self.b_value 

54 

55 if b_value is None: 

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

57 else: 

58 return moment_tensor.rand_to_gutenberg_richter( 

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

60 

61 def get_sources(self): 

62 sources = [] 

63 for ievent in range(self.nevents): 

64 src = self.get_source(ievent) 

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

66 sources.append(src) 

67 

68 return sources 

69 

70 def ensure_data(self, path): 

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

72 if not op.exists(fn_sources): 

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

74 for src in self.get_sources(): 

75 f.write(src.dump()) 

76 

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

78 if not op.exists(fn_events): 

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

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

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

82 

83 def add_map_artists(self, automap): 

84 pass