Coverage for pyrdnap / v_grids.py: 100%

72 statements  

« prev     ^ index     » next       coverage.py v7.14.0, created at 2026-06-14 13:03 -0400

1 

2# -*- coding: utf-8 -*- 

3 

4u'''(INTERNAL) C{RDNAPTRANS(tm)2018_v220627} v#grid utilities. 

5''' 

6from pyrdnap import pyrdnap_abspath # pyrdnap 1st 

7from pyrdnap.__pygeodesy import _0_0s, import_module, _ValueError 

8from pygeodesy import print_, property_RO 

9 

10from array import array 

11import os.path as os_path 

12import sys 

13from zipfile import ZipFile 

14 

15__all__ = () 

16__version__ = '26.06.14' 

17 

18_R_C = 481, 301 # shape: rows, cols 

19_RxC = 144781 # total, in .v1grid, .v2grid 

20 

21 

22class RDNAPError(_ValueError): # exported by rdnap2018 

23 '''Error raised for C{RD}, C{NAP} and unzip issues. 

24 ''' 

25 pass 

26 

27 

28class _V_grid(tuple): 

29 '''(INTERNAL) V_grid, a row-order matrix stored as 

30 an R-tuple of C-arrays of C{floats}. 

31 ''' 

32 

33 def __call__(self, i, j): 

34 # return item (i, j) of this grid 

35 # R, C = _R_C 

36 # assert isinstance(i, int) and 0 <= i < R 

37 # assert isinstance(j, int) and 0 <= j < C 

38 return self[i][j] 

39 

40 def _assert(self, _0s=0): 

41 z, Z = self._assert2(*_R_C) 

42 _v_assert(z, _0s) 

43 _v_assert(Z, 197 if _0s else 0) 

44 _v_assert(self._RxC, _RxC) 

45 return self 

46 

47 def _assert2(self, R, C): 

48 _v_assert(len(self), R) 

49 _v_assert(len(_ZEROW), C) 

50 z = Z = 0 # count zeros and _ZEROSWs 

51 try: 

52 for i, r in enumerate(self): 

53 _v_assert(type(r), array) 

54 _v_assert(len(r), C) 

55 if r is _ZEROW: 

56 Z += 1 

57 z += C 

58 else: 

59 z += sum((0 if f else 1) for f in r) 

60 except AssertionError as x: 

61 raise AssertionError('row %s: %s' % (i, x)) 

62 return z, Z 

63 

64 @property_RO 

65 def _RxC(self): 

66 return sum(map(len, self)) 

67 

68# def _round(self, _op, ndigits): 

69# # round(_op(f for a in self 

70# # for f in a), ndigits) 

71# return round(_op(map(_op, self)), ndigits) 

72 

73 

74def _d_array(floats): # lat_/lon_corr_ 

75 return array('d', floats) 

76 

77 

78def _f_array(floats): # _NAP_h, _ZEROW 

79 return array('f', floats) 

80 

81_ZEROW = _f_array(_0_0s(301)) # PYCHOK singleton, _R_C[1] 

82 

83 

84def _v_assert(value, valid=_R_C): # in .rd0 

85 if value != valid: 

86 raise AssertionError('%r not %r' % (value, valid)) 

87 return True 

88 

89 

90def _v_grid(v): 

91 '''(INTERNAL) Return "v#grid" variant C{v} as C{str}. 

92 ''' 

93 return 'v%sgrid' % (v,) 

94 

95 

96def _v_grid_txt(v, name, col2or3, _array, **_0s): 

97 '''(INTERNAL) Return a C{_V_grid} for column C{col2or3} of 

98 compressed, variant C{v} grid file C{<name>2018.txt.zip}. 

99 ''' 

100 v = _V_grid(_v_txt_unzip(v, name, col2or3, _array)) 

101 return v._assert(**_0s) 

102 

103 

104def _v_gridz3(v): # PHYCOK no cover 

105 '''(INTERNAL) Return the fully-qualified path, directory 

106 and module of C{v#grid} variant C{v}. 

107 ''' 

108 m = _v_grid(v) 

109 d = pyrdnap_abspath 

110 p = os_path.join(d, m + 'z.zip') 

111 return p, d, m 

112 

113 

114def _v_gridz_import(v): # PHYCOK no cover 

115 '''(INTERNAL) Try "from v#gridz.zip import v#grid" for variant C{v} 

116 ''' 

117 v_grid = None 

118 p, _, m = _v_gridz3(v) 

119 try: # Py 3.4+ 

120 # <https://RealPython.com/python-zip-import/ 

121 # #explore-pythons-zipimport-the-tool-behind-zip-imports> 

122 from zipimport import zipimporter as Z # ZipImportError 

123 # get an importer for zip file p and load module m 

124 v_grid = Z(p).load_module(m) # Py3.14- 

125 # XXX should use .exec_module but that fails and/or 

126 # XXX needs .create_module, .find_spec, etc??? 

127 except (AttributeError, ImportError): 

128 try: # trusted old-fashion way 

129 sys.path.insert(0, p) 

130 v_grid = import_module(m) 

131# except ImportError: 

132# v_grid = None 

133 finally: 

134 try: 

135 sys.path.remove(p) 

136 except ValueError: 

137 pass # AssertionError 

138# if v_grid: 

139# sys.modules[m] = v_grid 

140 return v_grid 

141 

142 

143def _v_gridz_unzip(v, force=False, verbose=False): # PHYCOK no cover 

144 '''(INTERNAL) Unzip a C{v#gridz.zip} file into the "pyrdnap" directory. 

145 ''' 

146 p, d, m = _v_gridz3(v) 

147 t = os_path.join(d, m) 

148 if (not force) and os_path.exists(t): 

149 t = '%r exists: %r' % (m, t) 

150 raise RDNAPError(t) 

151 try: 

152 with ZipFile(p) as z: 

153 z.extractall(d) 

154 except Exception as x: 

155 raise RDNAPError(m, cause=x) 

156 if verbose: 

157 print_('unzipped', repr(p)) 

158 print_(' into', repr(t)) 

159 

160 

161def _v_txt_unzip(v, name, col2or3, _array): 

162 '''(INTERNAL) Open grid file C{<name>2018.txt} or unzip C{<name>2018.txt.zip} 

163 of variant C{v}, extract column C{col2or3} (0-origin) and yield 481 rows, 

164 each a 301-C{_array} of floats or a _ZEROW of all zeros. 

165 ''' 

166 r = [] 

167 try: 

168 n = name + '2018.txt' 

169 p = pyrdnap_abspath 

170 p = os_path.join(p, _v_grid(v), n) 

171 with (open(p, 'rb') if os_path.exists(p) else 

172 ZipFile(p + '.zip').open(n)) as f: 

173 _, C = _R_C 

174 _r = r.append 

175 t = f.readline() # ignore 1st line 

176 while t: 

177 for _ in range(C * 3): 

178 t = f.readline() 

179 if t: 

180 _r(t.strip().split()[col2or3]) 

181 else: 

182 break 

183 while len(r) >= C: 

184 y = _array(map(float, r[:C])) 

185 yield y if any(y) else _ZEROW 

186 r[:] = r[C:] 

187 except Exception as x: 

188 raise RDNAPError(n, cause=x) 

189 _v_assert(len(r), 0) 

190 

191 

192# __all__ += _ALL_OTHER(RDNAPError) # in .rdnap2018 

193 

194# **) MIT License 

195# 

196# Copyright (C) 2026-2026 -- mrJean1 at Gmail -- All Rights Reserved. 

197# 

198# Permission is hereby granted, free of charge, to any person obtaining a 

199# copy of this software and associated documentation files (the "Software"), 

200# to deal in the Software without restriction, including without limitation 

201# the rights to use, copy, modify, merge, publish, distribute, sublicense, 

202# and/or sell copies of the Software, and to permit persons to whom the 

203# Software is furnished to do so, subject to the following conditions: 

204# 

205# The above copyright notice and this permission notice shall be included 

206# in all copies or substantial portions of the Software. 

207# 

208# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 

209# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 

210# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 

211# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 

212# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 

213# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 

214# OTHER DEALINGS IN THE SOFTWARE.