Coverage for pyrdnap / v_grids.py: 100%

70 statements  

« prev     ^ index     » next       coverage.py v7.14.0, created at 2026-06-26 11:46 -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, RDNAPError 

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.17' 

17 

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

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

20 

21 

22class _V_grid(tuple): 

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

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

25 ''' 

26 

27 def __call__(self, i, j): 

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

29 # R, C = _R_C 

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

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

32 return self[i][j] 

33 

34 def _assert(self, _0s=0): 

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

36 _v_assert(z, _0s) 

37 _v_assert(Z, 197 if _0s else 0) 

38 _v_assert(self._RxC, _RxC) 

39 return self 

40 

41 def _assert2(self, R, C): 

42 _v_assert(len(self), R) 

43 _v_assert(len(_ZEROW), C) 

44 z = Z = 0 # count zeros and _ZEROSWs 

45 try: 

46 for i, r in enumerate(self): 

47 _v_assert(type(r), array) 

48 _v_assert(len(r), C) 

49 if r is _ZEROW: 

50 Z += 1 

51 z += C 

52 else: 

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

54 except AssertionError as x: 

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

56 return z, Z 

57 

58 @property_RO 

59 def _RxC(self): 

60 return sum(map(len, self)) 

61 

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

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

64# # for f in a), ndigits) 

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

66 

67 

68def _d_array(floats): # lat_/lon_corr_ 

69 return array('d', floats) 

70 

71 

72def _f_array(floats): # _NAP_h, _ZEROW 

73 return array('f', floats) 

74 

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

76 

77 

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

79 if value != valid: 

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

81 return True 

82 

83 

84def _v_grid(v): # in .rdnap2018 

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

86 ''' 

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

88 

89 

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

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

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

93 ''' 

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

95 return v._assert(**_0s) 

96 

97 

98def _v_gridz3(v): # PHYCOK no cover 

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

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

101 ''' 

102 m = _v_grid(v) 

103 d = pyrdnap_abspath 

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

105 return p, d, m 

106 

107 

108def _v_gridz_import(v): # PHYCOK no cover 

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

110 ''' 

111 v_grid = None 

112 p, _, m = _v_gridz3(v) 

113 try: # Py 3.4+ 

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

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

116 from zipimport import zipimporter as Z # ZipImportError 

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

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

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

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

121 except (AttributeError, ImportError): 

122 try: # trusted old-fashion way 

123 sys.path.insert(0, p) 

124 v_grid = import_module(m) 

125# except ImportError: 

126# v_grid = None 

127 finally: 

128 try: 

129 sys.path.remove(p) 

130 except ValueError: 

131 pass # AssertionError 

132# if v_grid: 

133# sys.modules[m] = v_grid 

134 return v_grid 

135 

136 

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

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

139 ''' 

140 p, d, m = _v_gridz3(v) 

141 t = os_path.join(d, m) 

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

143 t = 'exists: %r' % (t,) 

144 raise RDNAPError(m, txt=t) 

145 try: 

146 with ZipFile(p) as z: 

147 z.extractall(d) 

148 except Exception as x: 

149 raise RDNAPError(m, cause=x) 

150 if verbose: 

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

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

153 

154 

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

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

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

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

159 ''' 

160 r = [] 

161 try: 

162 n = name + '2018.txt' 

163 p = pyrdnap_abspath 

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

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

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

167 _, C = _R_C 

168 _r = r.append 

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

170 while t: 

171 for _ in range(C * 3): 

172 t = f.readline() 

173 if t: 

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

175 else: 

176 break 

177 while len(r) >= C: 

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

179 yield y if any(y) else _ZEROW 

180 r[:] = r[C:] 

181 except Exception as x: 

182 raise RDNAPError(n, cause=x) 

183 _v_assert(len(r), 0) 

184 

185# **) MIT License 

186# 

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

188# 

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

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

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

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

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

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

195# 

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

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

198# 

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

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

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

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

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

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

205# OTHER DEALINGS IN THE SOFTWARE.