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 

15 

16logger = logging.getLogger('volcanoes') 

17 

18citation = ''' 

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

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

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

22 

23 

24class Volcano(object): 

25 age = None 

26 

27 __fields__ = OrderedDict() 

28 __slots__ = list(__fields__.keys()) 

29 

30 def __init__(self, *args): 

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

32 if attr_type in (int, float): 

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

34 value = 0. 

35 try: 

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

37 except ValueError as e: 

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

39 raise e 

40 

41 def __str__(self): 

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

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

44 

45 

46class VolcanoHolocene(Volcano): 

47 age = 'holocene' 

48 

49 __fields__ = OrderedDict([ 

50 ('fid', str), 

51 ('volcano_number', int), 

52 ('volcano_name', str), 

53 ('primary_volcano_type', str), 

54 ('last_eruption_year', int), 

55 ('country', str), 

56 ('geological_summary', str), 

57 ('region', str), 

58 ('subregion', str), 

59 ('lat', float), 

60 ('lon', float), 

61 ('elevation', float), 

62 ('tectonic_setting', str), 

63 ('geologic_epoch', str), 

64 ('evidence_category', str), 

65 ('primary_photo_link', str), 

66 ('primary_photo_caption', str), 

67 ('primary_photo_credit', str), 

68 ('major_rock_type', str), 

69 ('geolocation', str), 

70 ]) 

71 

72 

73class VolcanoPleistocene(Volcano): 

74 age = 'pleistocene' 

75 

76 __fields__ = OrderedDict([ 

77 ('fid', str), 

78 ('volcano_number', int), 

79 ('volcano_name', str), 

80 ('primary_volcano_type', str), 

81 ('country', str), 

82 ('geological_summary', str), 

83 ('region', str), 

84 ('subregion', str), 

85 ('lat', float), 

86 ('lon', float), 

87 ('elevation', float), 

88 ('geologic_epoch', str), 

89 ('geolocation', str), 

90 ]) 

91 

92 

93class Volcanoes(object): 

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

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

96 

97 def __init__(self): 

98 self.fname_holocene = op.join( 

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

100 self.fname_pleistocene = op.join( 

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

102 

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

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

105 self.download() 

106 

107 self.volcanoes = [] 

108 self._load_volcanoes(self.fname_holocene, VolcanoHolocene) 

109 self._load_volcanoes(self.fname_pleistocene, VolcanoPleistocene) 

110 

111 def _load_volcanoes(self, fname, cls): 

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

113 next(f) # skip header 

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

115 for row in reader: 

116 volcano = cls(*row) 

117 self.volcanoes.append(volcano) 

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

119 

120 def download(self): 

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

122 util.download_file( 

123 self.URL_HOLOCENE, self.fname_holocene, 

124 status_callback=get_download_callback( 

125 'Downloading Holocene volcanoe database...')) 

126 

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

128 util.download_file( 

129 self.URL_PLEISTOCENE, self.fname_pleistocene, 

130 status_callback=get_download_callback( 

131 'Downloading Pleistocene volcanoe database...')) 

132 

133 @property 

134 def volcanoes_holocene(self): 

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

136 

137 @property 

138 def volcanoes_pleistocene(self): 

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

140 

141 @property 

142 def nvolcanoes(self): 

143 return len(self.volcanoes) 

144 

145 @property 

146 def nvolcanoes_holocene(self): 

147 return len(self.volcanoes_holocene) 

148 

149 @property 

150 def nvolcanoes_pleistocene(self): 

151 return len(self.volcanoes_pleistocene) 

152 

153 def get_coords(self): 

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

155 

156 def get_names(self): 

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

158 

159 

160if __name__ == '__main__': 

161 logging.basicConfig(level=logging.DEBUG) 

162 volc = Volcanoes() 

163 print(volc.volcanoes[0])