1# http://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

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

5 

6import numpy as num 

7 

8from pyrocko.guts import Float, Int 

9from pyrocko import moment_tensor, gf, util 

10 

11from .base import SourceGenerator 

12 

13km = 1e3 

14guts_prefix = 'pf.scenario' 

15 

16 

17class RectangularSourceGenerator(SourceGenerator): 

18 depth_min = Float.T( 

19 default=0.0) 

20 depth_max = Float.T( 

21 default=5*km) 

22 decimation_factor = Int.T( 

23 default=4) 

24 

25 strike = Float.T( 

26 optional=True) 

27 dip = Float.T( 

28 optional=True) 

29 rake = Float.T( 

30 optional=True) 

31 depth = Float.T( 

32 optional=True) 

33 

34 width = Float.T( 

35 optional=True) 

36 length = Float.T( 

37 optional=True) 

38 

39 def get_source(self, ievent): 

40 rstate = self.get_rstate(ievent) 

41 time = self.time_min + rstate.uniform( 

42 0., float(self.time_max - self.time_min)) # hptime aware 

43 lat, lon = self.get_latlon(ievent) 

44 depth = rstate.uniform(self.depth_min, self.depth_max) 

45 

46 magnitude = self.draw_magnitude(rstate) 

47 moment = moment_tensor.magnitude_to_moment(magnitude) 

48 

49 # After Mai and Beroza (2000) 

50 length = num.exp(-6.27 + 0.4*num.log(moment)) 

51 width = num.exp(-4.24 + 0.32*num.log(moment)) 

52 

53 length = length if not self.length else self.length 

54 width = width if not self.width else self.width 

55 depth = depth if not self.depth else self.depth 

56 

57 if self.strike is None and self.dip is None and self.rake is None: 

58 strike, rake = rstate.uniform(-180., 180., 2) 

59 dip = rstate.uniform(0., 90.) 

60 else: 

61 if None in (self.strike, self.dip, self.rake): 

62 raise ValueError( 

63 'RectangularSourceGenerator: ' 

64 'strike, dip, rake must be used in combination.') 

65 

66 strike = self.strike 

67 dip = self.dip 

68 rake = self.rake 

69 

70 source = gf.RectangularSource( 

71 time=util.to_time_float(time), 

72 lat=float(lat), 

73 lon=float(lon), 

74 anchor='top', 

75 depth=float(depth), 

76 length=float(length), 

77 width=float(width), 

78 strike=float(strike), 

79 dip=float(dip), 

80 rake=float(rake), 

81 magnitude=magnitude, 

82 decimation_factor=self.decimation_factor) 

83 

84 return source 

85 

86 def add_map_artists(self, automap): 

87 for source in self.get_sources(): 

88 automap.gmt.psxy( 

89 in_rows=source.outline(cs='lonlat'), 

90 L='+p2p,black', 

91 W='1p,black', 

92 G='black', 

93 t=50, 

94 *automap.jxyr)