1# http://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

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

5 

6import csv 

7import logging 

8import numpy as num 

9from os import path as op 

10from collections import OrderedDict 

11 

12from pyrocko import config, util 

13from .util import get_download_callback 

14 

15logger = logging.getLogger('volcanoes') 

16 

17citation = ''' 

18Global Volcanism Program, 2013. Volcanoes of the World, 

19v. 4.8.5. Venzke, E (ed.). Smithsonian Institution. Downloaded 29 Jan 2020. 

20https://doi.org/10.5479/si.GVP.VOTW4-2013 ''' 

21 

22 

23class Volcano(object): 

24 age = None 

25 

26 __fields__ = OrderedDict() 

27 __slots__ = list(__fields__.keys()) 

28 

29 def __init__(self, *args): 

30 for (attr, attr_type), value in zip(self.__fields__.items(), args): 

31 if attr_type in (int, float): 

32 if not value or value == '?': 

33 value = 0. 

34 try: 

35 setattr(self, attr, attr_type(value)) 

36 except ValueError as e: 

37 print(list(zip(self.__fields__.keys(), args))) 

38 raise e 

39 

40 def __str__(self): 

41 d = {attr: getattr(self, attr) for attr in self.__fields__.keys()} 

42 return '\n'.join(['%s: %s' % (attr, val) for attr, val in d.items()]) 

43 

44 

45class VolcanoHolocene(Volcano): 

46 age = 'holocene' 

47 

48 __fields__ = OrderedDict([ 

49 ('fid', str), 

50 ('volcano_number', int), 

51 ('volcano_name', str), 

52 ('primary_volcano_type', str), 

53 ('last_eruption_year', int), 

54 ('country', str), 

55 ('geological_summary', str), 

56 ('region', str), 

57 ('subregion', str), 

58 ('lat', float), 

59 ('lon', float), 

60 ('elevation', float), 

61 ('tectonic_setting', str), 

62 ('geologic_epoch', str), 

63 ('evidence_category', str), 

64 ('primary_photo_link', str), 

65 ('primary_photo_caption', str), 

66 ('primary_photo_credit', str), 

67 ('major_rock_type', str), 

68 ('geolocation', str), 

69 ]) 

70 

71 

72class VolcanoPleistocene(Volcano): 

73 age = 'pleistocene' 

74 

75 __fields__ = OrderedDict([ 

76 ('fid', str), 

77 ('volcano_number', int), 

78 ('volcano_name', str), 

79 ('primary_volcano_type', str), 

80 ('country', str), 

81 ('geological_summary', str), 

82 ('region', str), 

83 ('subregion', str), 

84 ('lat', float), 

85 ('lon', float), 

86 ('elevation', float), 

87 ('geologic_epoch', str), 

88 ('geolocation', str), 

89 ]) 

90 

91 

92class Volcanoes(object): 

93 URL_HOLOCENE = 'https://mirror.pyrocko.org/smithsonian/smithsonian-holocene.csv' # noqa 

94 URL_PLEISTOCENE = 'https://mirror.pyrocko.org/smithsonian/smithsonian-pleistocene.csv' # noqa 

95 

96 def __init__(self): 

97 self.fname_holocene = op.join( 

98 config.config().volcanoes_dir, 'smithsonian-holocene.csv') 

99 self.fname_pleistocene = op.join( 

100 config.config().volcanoes_dir, 'smithsonian-pleistocene.csv') 

101 

102 if not op.exists(self.fname_holocene) \ 

103 or not op.exists(self.fname_pleistocene): 

104 self.download() 

105 

106 self.volcanoes = [] 

107 self._load_volcanoes(self.fname_holocene, VolcanoHolocene) 

108 self._load_volcanoes(self.fname_pleistocene, VolcanoPleistocene) 

109 

110 def _load_volcanoes(self, fname, cls): 

111 with open(fname, 'r', encoding='utf8') as f: 

112 next(f) # skip header 

113 reader = csv.reader(f, dialect='unix') 

114 for row in reader: 

115 volcano = cls(*row) 

116 self.volcanoes.append(volcano) 

117 logger.debug('loaded %d volcanoes', self.nvolcanoes) 

118 

119 def download(self): 

120 logger.info('Downloading Holocene volcanoes...') 

121 util.download_file( 

122 self.URL_HOLOCENE, self.fname_holocene, 

123 status_callback=get_download_callback( 

124 'Downloading Holocene volcanoe database...')) 

125 

126 logger.info('Downloading Pleistocene volcanoes...') 

127 util.download_file( 

128 self.URL_PLEISTOCENE, self.fname_pleistocene, 

129 status_callback=get_download_callback( 

130 'Downloading Pleistocene volcanoe database...')) 

131 

132 @property 

133 def volcanoes_holocene(self): 

134 return [v for v in self.volcanoes if isinstance(v, VolcanoHolocene)] 

135 

136 @property 

137 def volcanoes_pleistocene(self): 

138 return [v for v in self.volcanoes if isinstance(v, VolcanoPleistocene)] 

139 

140 @property 

141 def nvolcanoes(self): 

142 return len(self.volcanoes) 

143 

144 @property 

145 def nvolcanoes_holocene(self): 

146 return len(self.volcanoes_holocene) 

147 

148 @property 

149 def nvolcanoes_pleistocene(self): 

150 return len(self.volcanoes_pleistocene) 

151 

152 def get_coords(self): 

153 return num.array([(v.lat, v.lon) for v in self.volcanoes]) 

154 

155 def get_names(self): 

156 return [v.volcano_name for v in self.volcanoes] 

157 

158 

159if __name__ == '__main__': 

160 logging.basicConfig(level=logging.DEBUG) 

161 volc = Volcanoes() 

162 print(volc.volcanoes[0])