Coverage for C: \ Users \ peaco \ OneDrive \ Documents \ GitHub \ mt_metadata \ mt_metadata \ transfer_functions \ io \ tools.py: 77%

105 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-01-10 00:11 -0800

1# -*- coding: utf-8 -*- 

2""" 

3Created on Sat Dec 4 17:44:51 2021 

4 

5@author: jpeacock 

6""" 

7import json 

8 

9# ============================================================================= 

10# imports 

11# ============================================================================= 

12import urllib.request as url_request 

13 

14from loguru import logger 

15 

16 

17# ============================================================================= 

18 

19 

20def _validate_str_with_equals(input_string): 

21 """ 

22 make sure an input string is of the format {0}={1} {2}={3} {4}={5} ... 

23 Some software programs put spaces after the equals sign and that's not 

24 cool. So we make the string into a readable format 

25 

26 :param input_string: input string from an edi file 

27 :type input_string: string 

28 

29 :returns line_list: list of lines as ['key_00=value_00', 

30 'key_01=value_01'] 

31 :rtype line_list: list 

32 """ 

33 input_string = input_string.strip() 

34 # remove the first >XXXXX 

35 if ">" in input_string: 

36 input_string = input_string[input_string.find(" ") :] 

37 

38 # check if there is a // at the end of the line 

39 if input_string.find("//") > 0: 

40 input_string = input_string[0 : input_string.find("//")] 

41 

42 # split the line by = 

43 l_list = input_string.strip().split("=") 

44 

45 # split the remaining strings 

46 str_list = [] 

47 for line in l_list: 

48 s_list = line.strip().split() 

49 for l_str in s_list: 

50 str_list.append(l_str.strip()) 

51 

52 # probably not a good return 

53 if len(str_list) % 2 != 0: 

54 # _logger.info( 

55 # 'The number of entries in {0} is not even'.format(str_list)) 

56 return str_list 

57 

58 line_list = [ 

59 "{0}={1}".format(str_list[ii], str_list[ii + 1]) 

60 for ii in range(0, len(str_list), 2) 

61 ] 

62 

63 return line_list 

64 

65 

66# ============================================================================== 

67# Index finder 

68# ============================================================================== 

69class index_locator(object): 

70 def __init__(self, component_list): 

71 self.ex = None 

72 self.ey = None 

73 self.hx = None 

74 self.hy = None 

75 self.hz = None 

76 self.rhx = None 

77 self.rhy = None 

78 self.rhz = None 

79 for ii, comp in enumerate(component_list): 

80 setattr(self, comp, ii) 

81 if self.rhx is None: 

82 self.rhx = self.hx 

83 if self.rhy is None: 

84 self.rhy = self.hy 

85 

86 def __str__(self): 

87 lines = ["Index Values"] 

88 for k, v in self.__dict__.items(): 

89 if v is not None: 

90 lines.append(f"\t{k} = {v}") 

91 return "\n".join(lines) 

92 

93 def __repr__(self): 

94 return self.__str__() 

95 

96 @property 

97 def n_channels(self): 

98 count = 0 

99 for k, v in self.__dict__.items(): 

100 if "r" in k: 

101 continue 

102 if v is not None: 

103 count += 1 

104 

105 return count 

106 

107 @property 

108 def has_tipper(self): 

109 if self.hz is not None: 

110 return True 

111 return False 

112 

113 @property 

114 def has_electric(self): 

115 if self.ex != None or self.ey != None: 

116 return True 

117 return False 

118 

119 @property 

120 def input_channels(self): 

121 return [self.hx, self.hy] 

122 

123 @property 

124 def output_channels(self): 

125 if self.has_tipper: 

126 if self.has_electric: 

127 return [self.hz, self.ex, self.ey] 

128 return [self.hz] 

129 return [self.ex, self.ey] 

130 

131 @property 

132 def n_inputs(self): 

133 return len(self.input_channels) 

134 

135 @property 

136 def n_outputs(self): 

137 return len(self.output_channels) 

138 

139 

140def _validate_edi_lines(edi_lines) -> list[str]: 

141 """ 

142 check for carriage returns or hard returns 

143 

144 :param edi_lines: list of edi lines 

145 :type edi_lines: list 

146 

147 :returns: list of edi lines 

148 :rtype: list 

149 """ 

150 

151 if len(edi_lines) == 1: 

152 edi_lines = edi_lines[0].replace("\r", "\n").split("\n") 

153 if len(edi_lines) > 1: 

154 return edi_lines 

155 else: 

156 raise ValueError("*** EDI format not correct check file ***") 

157 else: 

158 return edi_lines 

159 

160 

161def get_nm_elev(latitude, longitude): 

162 """ 

163 Get national map elevation for a given lat and lon. 

164 

165 Queries the national map website for the elevation value. 

166 

167 :param lat: latitude in decimal degrees 

168 :type lat: float 

169 

170 :param lon: longitude in decimal degrees 

171 :type lon: float 

172 

173 :return: elevation (meters) 

174 :rtype: float 

175 

176 :Example: :: 

177 

178 >>> import mtpy.usgs.usgs_archive as archive 

179 >>> archive.get_nm_elev(35.467, -115.3355) 

180 >>> 809.12 

181 

182 .. note:: Needs an internet connection to work. 

183 

184 """ 

185 # nm_url = ( 

186 # r"https://nationalmap.gov/epqs/pqs.php?" 

187 # f"x={longitude:.5f}&y={latitude:.5f}&units=Meters&output=xml" 

188 # ) 

189 

190 nm_url = ( 

191 r"https://epqs.nationalmap.gov/v1/json?" 

192 f"x={longitude}&y={latitude}&units=Meters&wkid=4326&includeDate=False" 

193 ) 

194 # call the url and get the response 

195 try: 

196 response = url_request.urlopen(nm_url) 

197 except: 

198 logger.error("Could not connect to internet to get elevation data.") 

199 return 0.0 

200 

201 # read the xml response and convert to a float 

202 try: 

203 # unpack the response to a dictionary 

204 info = json.loads(response.read()) 

205 

206 except json.JSONDecodeError: 

207 logger.error( 

208 f"Input values (latitude={latitude}, longitude={longitude}) " 

209 "could not be found on US National Map." 

210 ) 

211 return 0.0 

212 try: 

213 return float(info["value"]) 

214 except KeyError: 

215 logger.warning("Could not find elevation data") 

216 return 0.0 

217 except ValueError: 

218 logger.warning(f"Could not convert elevation {info['value']} to float") 

219 return 0.0