1# http://pyrocko.org - GPLv3 

2# 

3# The Pyrocko Developers, 21st Century 

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

5from __future__ import absolute_import 

6 

7import csv 

8import logging 

9import numpy as num 

10from os import path as op 

11from collections import OrderedDict 

12 

13from pyrocko import config, util 

14from .util import get_download_callback 

15 

16 

17logger = logging.getLogger('volcanoes') 

18 

19citation = ''' 

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

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

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

23 

24 

25class Volcano(object): 

26 age = None 

27 

28 __fields__ = OrderedDict() 

29 __slots__ = list(__fields__.keys()) 

30 

31 def __init__(self, *args): 

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

33 if attr_type in (int, float): 

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

35 value = 0. 

36 try: 

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

38 except ValueError as e: 

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

40 raise e 

41 

42 def __str__(self): 

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

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

45 

46 

47class VolcanoHolocene(Volcano): 

48 age = 'holocene' 

49 

50 __fields__ = OrderedDict([ 

51 ('fid', str), 

52 ('volcano_number', int), 

53 ('volcano_name', str), 

54 ('primary_volcano_type', str), 

55 ('last_eruption_year', int), 

56 ('country', str), 

57 ('geological_summary', str), 

58 ('region', str), 

59 ('subregion', str), 

60 ('lat', float), 

61 ('lon', float), 

62 ('elevation', float), 

63 ('tectonic_setting', str), 

64 ('geologic_epoch', str), 

65 ('evidence_category', str), 

66 ('primary_photo_link', str), 

67 ('primary_photo_caption', str), 

68 ('primary_photo_credit', str), 

69 ('major_rock_type', str), 

70 ('geolocation', str), 

71 ]) 

72 

73 

74class VolcanoPleistocene(Volcano): 

75 age = 'pleistocene' 

76 

77 __fields__ = OrderedDict([ 

78 ('fid', str), 

79 ('volcano_number', int), 

80 ('volcano_name', str), 

81 ('primary_volcano_type', str), 

82 ('country', str), 

83 ('geological_summary', str), 

84 ('region', str), 

85 ('subregion', str), 

86 ('lat', float), 

87 ('lon', float), 

88 ('elevation', float), 

89 ('geologic_epoch', str), 

90 ('geolocation', str), 

91 ]) 

92 

93 

94class Volcanoes(object): 

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

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

97 

98 def __init__(self): 

99 self.fname_holocene = op.join( 

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

101 self.fname_pleistocene = op.join( 

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

103 

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

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

106 self.download() 

107 

108 self.volcanoes = [] 

109 self._load_volcanoes(self.fname_holocene, VolcanoHolocene) 

110 self._load_volcanoes(self.fname_pleistocene, VolcanoPleistocene) 

111 

112 def _load_volcanoes(self, fname, cls): 

113 with open(fname, 'r') as f: 

114 next(f) # skip header 

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

116 for row in reader: 

117 volcano = cls(*row) 

118 self.volcanoes.append(volcano) 

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

120 

121 def download(self): 

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

123 util.download_file( 

124 self.URL_HOLOCENE, self.fname_holocene, 

125 status_callback=get_download_callback( 

126 'Downloading Holocene volcanoe database...')) 

127 

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

129 util.download_file( 

130 self.URL_PLEISTOCENE, self.fname_pleistocene, 

131 status_callback=get_download_callback( 

132 'Downloading Pleistocene volcanoe database...')) 

133 

134 @property 

135 def volcanoes_holocene(self): 

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

137 

138 @property 

139 def volcanoes_pleistocene(self): 

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

141 

142 @property 

143 def nvolcanoes(self): 

144 return len(self.volcanoes) 

145 

146 @property 

147 def nvolcanoes_holocene(self): 

148 return len(self.volcanoes_holocene) 

149 

150 @property 

151 def nvolcanoes_pleistocene(self): 

152 return len(self.volcanoes_pleistocene) 

153 

154 def get_coords(self): 

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

156 

157 def get_names(self): 

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

159 

160 

161if __name__ == '__main__': 

162 logging.basicConfig(level=logging.DEBUG) 

163 volc = Volcanoes() 

164 print(volc.volcanoes[0])