resqpy 4.17.0__py3-none-any.whl → 4.17.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,7 +14,7 @@ import math as maths
14
14
  import numpy as np
15
15
  import numba # type: ignore
16
16
  from numba import njit, prange # type: ignore
17
- from typing import Tuple, Optional
17
+ from typing import Tuple, Optional, List
18
18
 
19
19
 
20
20
  def radians_from_degrees(deg):
@@ -1013,6 +1013,47 @@ def vertical_intercept_nan(x: float, x_value_0: float, x_value_1: float, y_value
1013
1013
  return y
1014
1014
 
1015
1015
 
1016
+ @njit
1017
+ def vertical_intercept_nan_yz(x: float, x_0: float, x_1: float, y_0: float, y_1: float, z_0: float,
1018
+ z_1: float) -> Tuple[float, float]: # pragma: no cover
1019
+ """Finds the y & z values of a straight line between two points at a given x.
1020
+
1021
+ If the x value given is not within the x values of the points, returns NaN.
1022
+
1023
+ arguments:
1024
+ x (float): x value at which to determine the y value
1025
+ x_0 (float): the x coordinate of point a
1026
+ x_1 (float): the x coordinate of point b
1027
+ y_0 (float): the y coordinate of point a
1028
+ y_1 (float): the y coordinate of point b
1029
+ z_0 (float): the z coordinate of point a
1030
+ z_1 (float): the z coordinate of point b
1031
+
1032
+ returns:
1033
+ y, z (float, float): y & z values of the straight line segment between point a and point b,
1034
+ evaluated at x; if x is outside the x values range, y & z are NaN
1035
+ """
1036
+ y = np.nan
1037
+ z = np.nan
1038
+ if x_1 < x_0:
1039
+ x_0, x_1 = x_1, x_0
1040
+ y_0, y_1 = y_1, y_0
1041
+ z_0, z_1 = z_1, z_0
1042
+ if x >= x_0 and x <= x_1:
1043
+ if x_0 == x_1:
1044
+ y = y_0
1045
+ z = z_0
1046
+ else:
1047
+ xr = x_1 - x_0
1048
+ m = (y_1 - y_0) / xr
1049
+ c = y_1 - m * x_1
1050
+ y = m * x + c
1051
+ m = (z_1 - z_0) / xr
1052
+ c = z_1 - m * x_1
1053
+ z = m * x + c
1054
+ return (y, z)
1055
+
1056
+
1016
1057
  @njit
1017
1058
  def points_in_triangles_aligned_optimised_old(nx: int, ny: int, dx: float, dy: float,
1018
1059
  triangles: np.ndarray) -> np.ndarray: # pragma: no cover
@@ -1138,6 +1179,56 @@ def points_in_triangles_aligned_optimised(nx: int,
1138
1179
  return collated
1139
1180
 
1140
1181
 
1182
+ @njit(parallel = True)
1183
+ def points_in_triangles_aligned_unified(nx: int,
1184
+ ny: int,
1185
+ ax: int,
1186
+ ay: int,
1187
+ az: int,
1188
+ triangles: np.ndarray,
1189
+ n_batches: int = 20) -> Tuple[np.ndarray, np.ndarray]: # pragma: no cover
1190
+ """Calculates which points are within which triangles in 2D for a regular mesh of aligned points.
1191
+
1192
+ arguments:
1193
+ - nx (int): number of points in x axis
1194
+ - ny (int): number of points in y axis
1195
+ - ax (int): 'x' axis selection (0, 1, or 2)
1196
+ - ay (int): 'y' axis selection (0, 1, or 2)
1197
+ - az (int): 'z' axis selection (0, 1, or 2)
1198
+ - triangles (np.ndarray): float array of each triangles' normalised vertices in 3D, shape (N, 3, 3)
1199
+ - n_batches (int, default 20): number of parallel batches
1200
+
1201
+ returns:
1202
+ list like int array with each row being (tri number, axis 'y' int, axis 'x' int), and
1203
+ corresponding list like float array being axis 'z' sampled at point on triangle
1204
+
1205
+ notes:
1206
+ - actual axes to use for x, y, & z are determined by the ax, ay, & az arguments
1207
+ - 0, 1, & 2 must appear once each amongst the ax, ay, & az arguments
1208
+ - triangles points have already been normalised to a unit grid spacing and offset by half a cell
1209
+ - returned 'z' values are in normalised form
1210
+ - to denormalize 'z' values, add 0.5 and multiply by the actual cell length in the corresponding axis
1211
+ """
1212
+ n_triangles = len(triangles)
1213
+ if n_triangles == 0:
1214
+ return np.empty((0, 3), dtype = np.int32), np.empty((0,), dtype = np.float64)
1215
+ n_batches = min(n_triangles, n_batches)
1216
+ batch_size = (n_triangles - 1) // n_batches + 1
1217
+ tp = [np.empty((0, 3), dtype = np.int32)] * n_batches
1218
+ tz = [np.empty((0,), dtype = np.float64)] * n_batches
1219
+ for batch in prange(n_batches):
1220
+ base = batch * batch_size
1221
+ tp[batch], tz[batch] = _points_in_triangles_aligned_unified_batch(nx, ny, base,
1222
+ triangles[base:(batch + 1) * batch_size], ax,
1223
+ ay, az)
1224
+ collated = np.empty((0, 3), dtype = np.int32)
1225
+ collated_z = np.empty((0,), dtype = np.float64)
1226
+ for batch in range(n_batches):
1227
+ collated = np.concatenate((collated, tp[batch]), axis = 0)
1228
+ collated_z = np.concatenate((collated_z, tz[batch]), axis = 0)
1229
+ return collated, collated_z
1230
+
1231
+
1141
1232
  @njit
1142
1233
  def _points_in_triangles_aligned_optimised_batch(nx: int, ny: int, base_triangle: int,
1143
1234
  triangles: np.ndarray) -> np.ndarray: # pragma: no cover
@@ -1165,6 +1256,89 @@ def _points_in_triangles_aligned_optimised_batch(nx: int, ny: int, base_triangle
1165
1256
  return triangles_points
1166
1257
 
1167
1258
 
1259
+ @njit
1260
+ def _points_in_triangles_aligned_unified_batch(nx: int, ny: int, base_triangle: int, tp: np.ndarray, ax: int, ay: int,
1261
+ az: int) -> Tuple[np.ndarray, np.ndarray]: # pragma: no cover
1262
+ # returns list like int array with each row being (tri number, axis y int, axis x int), and
1263
+ # corresponding list like float array being axis z sampled at point on triangle
1264
+ # todo: add type subscripting once support for python 3.8 is dropped
1265
+ int_list = []
1266
+ sampled_z_list = []
1267
+
1268
+ for triangle_num in range(len(tp)):
1269
+ tri = tp[triangle_num]
1270
+ min_x = np.min(tri[:, ax])
1271
+ max_x = np.max(tri[:, ax])
1272
+ min_y = np.min(tri[:, ay])
1273
+ max_y = np.max(tri[:, ay])
1274
+ for xi in range(max(maths.ceil(min_x), 0), min(maths.floor(max_x) + 1, nx)):
1275
+ x = float(xi)
1276
+ e0_y, e0_z = vertical_intercept_nan_yz(x, tri[1, ax], tri[2, ax], tri[1, ay], tri[2, ay], tri[1, az],
1277
+ tri[2, az])
1278
+ e1_y, e1_z = vertical_intercept_nan_yz(x, tri[0, ax], tri[1, ax], tri[0, ay], tri[1, ay], tri[0, az],
1279
+ tri[1, az])
1280
+ e2_y, e2_z = vertical_intercept_nan_yz(x, tri[0, ax], tri[2, ax], tri[0, ay], tri[2, ay], tri[0, az],
1281
+ tri[2, az])
1282
+ floor_y = np.nan
1283
+ ceil_y = np.nan
1284
+ floor_z = np.nan
1285
+ ceil_z = np.nan
1286
+ if not np.isnan(e0_y):
1287
+ floor_y = e0_y
1288
+ ceil_y = e0_y
1289
+ floor_z = e0_z
1290
+ ceil_z = e0_z
1291
+ if not np.isnan(e1_y):
1292
+ if np.isnan(floor_y):
1293
+ floor_y = e1_y
1294
+ ceil_y = e1_y
1295
+ floor_z = e1_z
1296
+ ceil_z = e1_z
1297
+ else:
1298
+ if e1_y < floor_y:
1299
+ floor_y = e1_y
1300
+ floor_z = e1_z
1301
+ else:
1302
+ ceil_y = e1_y
1303
+ ceil_z = e1_z
1304
+ if not np.isnan(e2_y):
1305
+ if np.isnan(floor_y):
1306
+ floor_y = e2_y
1307
+ ceil_y = e2_y
1308
+ floor_z = e2_z
1309
+ ceil_z = e2_z
1310
+ else:
1311
+ if e2_y < floor_y:
1312
+ floor_y = e2_y
1313
+ floor_z = e2_z
1314
+ elif e2_y > ceil_y:
1315
+ ceil_y = e2_y
1316
+ ceil_z = e2_z
1317
+ y_range = ceil_y - floor_y
1318
+ z_range = ceil_z - floor_z
1319
+ t = triangle_num + base_triangle
1320
+ extend_int_list = []
1321
+ extend_z_list = []
1322
+ for y in range(max(maths.ceil(floor_y), 0), min(maths.floor(ceil_y) + 1, ny)):
1323
+ yf = float(y) - floor_y
1324
+ if y_range > 0.0:
1325
+ yf /= y_range
1326
+ z = floor_z + yf * z_range
1327
+ extend_int_list.append([triangle_num + base_triangle, y, xi])
1328
+ extend_z_list.append(z)
1329
+ int_list.extend(extend_int_list)
1330
+ sampled_z_list.extend(extend_z_list)
1331
+
1332
+ if len(int_list) == 0:
1333
+ int_array = np.empty((0, 3), dtype = np.int32)
1334
+ z_array = np.empty((0,), dtype = np.float64)
1335
+ else:
1336
+ int_array = np.array(int_list, dtype = np.int32)
1337
+ z_array = np.array(sampled_z_list, dtype = np.float64)
1338
+
1339
+ return (int_array, z_array)
1340
+
1341
+
1168
1342
  def triangle_normal_vector(p3):
1169
1343
  """For a triangle in 3D space, defined by 3 vertex points, returns a unit vector normal to the plane of the triangle.
1170
1344
 
@@ -279,11 +279,13 @@ class Surface(rqsb.BaseSurface):
279
279
  self.extract_patches(self.root)
280
280
  return len(self.patch_list)
281
281
 
282
- def triangles_and_points(self, patch = None):
282
+ def triangles_and_points(self, patch = None, copy = False):
283
283
  """Returns arrays representing one patch or a combination of all the patches in the surface.
284
284
 
285
285
  arguments:
286
286
  patch (int, optional): patch index; if None, combined arrays for all patches are returned
287
+ copy (bool, default False): if True, a copy of the arrays is returned; if False, the cached
288
+ arrays are returned
287
289
 
288
290
  returns:
289
291
  tuple (triangles, points):
@@ -296,21 +298,30 @@ class Surface(rqsb.BaseSurface):
296
298
 
297
299
  self.extract_patches(self.root)
298
300
  if patch is None:
299
- if self.triangles is None:
300
- points_offset = 0
301
- for triangulated_patch in self.patch_list:
302
- (t, p) = triangulated_patch.triangles_and_points()
303
- if points_offset == 0:
304
- self.triangles = t.copy()
305
- self.points = p.copy()
306
- else:
307
- self.triangles = np.concatenate((self.triangles, t.copy() + points_offset))
308
- self.points = np.concatenate((self.points, p.copy()))
309
- points_offset += p.shape[0]
310
- return (self.triangles, self.points)
301
+ if self.triangles is None or self.points is None:
302
+ if self.triangles is None:
303
+ points_offset = 0
304
+ for triangulated_patch in self.patch_list:
305
+ (t, p) = triangulated_patch.triangles_and_points()
306
+ if points_offset == 0:
307
+ self.triangles = t
308
+ self.points = p
309
+ else:
310
+ self.triangles = np.concatenate((self.triangles, t.copy() + points_offset))
311
+ self.points = np.concatenate((self.points, p))
312
+ points_offset += p.shape[0]
313
+ if copy:
314
+ return (self.triangles.copy(), self.points.copy())
315
+ else:
316
+ return (self.triangles, self.points)
311
317
  assert 0 <= patch < len(self.patch_list), \
312
318
  ValueError(f'patch index {patch} out of range for surface with {len(self.patch_list)} patches')
313
- return self.patch_list[patch].triangles_and_points()
319
+ return self.patch_list[patch].triangles_and_points(copy = copy)
320
+
321
+ def decache_triangles_and_points(self):
322
+ """Removes the cached composite triangles and points arrays."""
323
+ self.points = None
324
+ self.triangles = None
314
325
 
315
326
  def triangle_count(self, patch = None):
316
327
  """Return the numner of triangles in this surface, or in one patch.
@@ -57,53 +57,61 @@ class TriangulatedPatch:
57
57
  crs_root = self.model.root_for_uuid(self.crs_uuid)
58
58
  return crs_root, self.crs_uuid
59
59
 
60
- def triangles_and_points(self):
60
+ def triangles_and_points(self, copy = False):
61
61
  """Returns arrays representing the patch.
62
62
 
63
- Returns:
63
+ arguments:
64
+ copy (bool, default False): if True, a copy of the arrays is returned; if False, the cached
65
+ arrays are returned
66
+
67
+ returns:
64
68
  Tuple (triangles, points):
65
69
 
66
70
  * triangles (int array of shape[:, 3]): integer indices into points array,
67
71
  being the nodes of the corners of the triangles
68
72
  * points (float array of shape[:, 3]): flat array of xyz points, indexed by triangles
69
73
  """
70
- if self.triangles is not None:
74
+ if self.triangles is None:
75
+
76
+ assert self.triangle_count is not None and self.node_count is not None
77
+
78
+ geometry_node = rqet.find_tag(self.node, 'Geometry')
79
+ assert geometry_node is not None
80
+ p_root = rqet.find_tag(geometry_node, 'Points')
81
+ assert p_root is not None, 'Points xml node not found for triangle patch'
82
+ assert rqet.node_type(p_root) == 'Point3dHdf5Array'
83
+ h5_key_pair = self.model.h5_uuid_and_path_for_node(p_root, tag = 'Coordinates')
84
+ if h5_key_pair is None:
85
+ return (None, None)
86
+ try:
87
+ self.model.h5_array_element(h5_key_pair,
88
+ cache_array = True,
89
+ object = self,
90
+ array_attribute = 'points',
91
+ dtype = 'float')
92
+ except Exception:
93
+ log.error('hdf5 points failure for triangle patch ' + str(self.patch_index))
94
+ raise
95
+ self._set_t_type()
96
+ triangles_node = rqet.find_tag(self.node, 'Triangles')
97
+ h5_key_pair = self.model.h5_uuid_and_path_for_node(triangles_node)
98
+ if h5_key_pair is None:
99
+ log.warning('No Triangles found in xml for patch index: ' + str(self.patch_index))
100
+ return (None, None)
101
+ try:
102
+ self.model.h5_array_element(h5_key_pair,
103
+ cache_array = True,
104
+ object = self,
105
+ array_attribute = 'triangles',
106
+ dtype = self.t_type)
107
+ except Exception:
108
+ log.error('hdf5 triangles failure for triangle patch ' + str(self.patch_index))
109
+ raise
110
+
111
+ if copy:
112
+ return (self.triangles.copy(), self.points.copy())
113
+ else:
71
114
  return (self.triangles, self.points)
72
- assert self.triangle_count is not None and self.node_count is not None
73
-
74
- geometry_node = rqet.find_tag(self.node, 'Geometry')
75
- assert geometry_node is not None
76
- p_root = rqet.find_tag(geometry_node, 'Points')
77
- assert p_root is not None, 'Points xml node not found for triangle patch'
78
- assert rqet.node_type(p_root) == 'Point3dHdf5Array'
79
- h5_key_pair = self.model.h5_uuid_and_path_for_node(p_root, tag = 'Coordinates')
80
- if h5_key_pair is None:
81
- return (None, None)
82
- try:
83
- self.model.h5_array_element(h5_key_pair,
84
- cache_array = True,
85
- object = self,
86
- array_attribute = 'points',
87
- dtype = 'float')
88
- except Exception:
89
- log.error('hdf5 points failure for triangle patch ' + str(self.patch_index))
90
- raise
91
- self._set_t_type()
92
- triangles_node = rqet.find_tag(self.node, 'Triangles')
93
- h5_key_pair = self.model.h5_uuid_and_path_for_node(triangles_node)
94
- if h5_key_pair is None:
95
- log.warning('No Triangles found in xml for patch index: ' + str(self.patch_index))
96
- return (None, None)
97
- try:
98
- self.model.h5_array_element(h5_key_pair,
99
- cache_array = True,
100
- object = self,
101
- array_attribute = 'triangles',
102
- dtype = self.t_type)
103
- except Exception:
104
- log.error('hdf5 triangles failure for triangle patch ' + str(self.patch_index))
105
- raise
106
- return (self.triangles, self.points)
107
115
 
108
116
  def set_to_trimmed_patch(self, larger_patch, xyz_box = None, xy_polygon = None, internal = False):
109
117
  """Populate this (empty) patch with triangles and points that overlap with a trimming volume.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: resqpy
3
- Version: 4.17.0
3
+ Version: 4.17.2
4
4
  Summary: Python API for working with RESQML models
5
5
  Home-page: https://github.com/bp/resqpy
6
6
  License: MIT
@@ -1,4 +1,4 @@
1
- resqpy/__init__.py,sha256=nVSvwgDXt9osivrFSA1nCeNxqqKRmGyYX4oG-Lfr1xQ,556
1
+ resqpy/__init__.py,sha256=oaXzrJ3znGh09f_UOkvMYW4bc7G2CG9pIWjbSpDIKiM,556
2
2
  resqpy/crs.py,sha256=R7DfcTP5xGv5pu9Y8RHA2WVM9DjBCSVMoHcz4RmQ7Yw,27646
3
3
  resqpy/derived_model/__init__.py,sha256=NFvMSOKI3cxmH7lAbddV43JjoUj-r2G7ExEfOqinD1I,1982
4
4
  resqpy/derived_model/_add_edges_per_column_property_array.py,sha256=cpW3gwp6MSYIrtvFmCjoJXcyUsgGuCDbgmwlJCJebUs,6410
@@ -25,7 +25,7 @@ resqpy/derived_model/_zonal_grid.py,sha256=H-IGMudUV-tiRHZqvl9B1wxMQNjeAM2zHvTll
25
25
  resqpy/derived_model/_zone_layer_ranges_from_array.py,sha256=4pHkp7yqvkif_pC59VEK0g0JeFx7kt8mqhqADTOcucI,4358
26
26
  resqpy/fault/__init__.py,sha256=IStX_EhPnppIExf_mgYrBddC4KP26VcqblcfXiBT614,996
27
27
  resqpy/fault/_gcs_functions.py,sha256=NRyhKkYChRaKDUIQ6pfVQiD67e4TTm3LnBvWEPtpkDU,29569
28
- resqpy/fault/_grid_connection_set.py,sha256=zvHMSuQ10hd8KRc0NldYDziKlLkuw8u2-tSTFDJ36-A,119064
28
+ resqpy/fault/_grid_connection_set.py,sha256=xStOkWHsbh9m6lql7f2PDURnoFOIM1mFmx-QG6yPaKo,126124
29
29
  resqpy/grid/__init__.py,sha256=WsfOnR5lHcnpJEx8ZZ3lhd4dImEiieJLM7eFPxMi3u8,692
30
30
  resqpy/grid/_cell_properties.py,sha256=pbyAK2eV9n4teOxm2q5hyBinohEbevFPrCfMcpGiqUU,20689
31
31
  resqpy/grid/_connection_sets.py,sha256=-277bh9pMoeESSzy9oZehL-vc82aMGZuSLQs2KJ4Wfg,10120
@@ -46,9 +46,9 @@ resqpy/grid/_transmissibility.py,sha256=cLtuVaLgBQqRXa-_YQ5mjR_QC842Jxn2d-Hl6171
46
46
  resqpy/grid/_write_hdf5_from_caches.py,sha256=s3gcoilsFCCSw_wjnTjWe1xMHEWr_cessoGVgzqiqVI,9707
47
47
  resqpy/grid/_write_nexus_corp.py,sha256=yEVfiObsedEAXX6UG6ZTf56kZnQVkd3lLqE2NpL-KBM,6147
48
48
  resqpy/grid/_xyz.py,sha256=RLQWOdM_DRoCj4JypwB5gUJ78HTdk5JnZHSeAzuU634,13087
49
- resqpy/grid_surface/__init__.py,sha256=iyK3_Vlg9mXffc_1gjvRdKwQE0zicbNXya0tryHkr04,2593
49
+ resqpy/grid_surface/__init__.py,sha256=rPr5zFFRmUDbMEhnCYsweSC3xugtQ8LnhZOf8JLIqIc,2765
50
50
  resqpy/grid_surface/_blocked_well_populate.py,sha256=Lme1AR-nLWOUlNnmHMVThk6jEg_lAZxWWtL82Yksppw,35867
51
- resqpy/grid_surface/_find_faces.py,sha256=04j5Qt61XWwHOJFrGmz0OB1ieivFbjDl2JxD1DXF0Wo,65620
51
+ resqpy/grid_surface/_find_faces.py,sha256=FeKfpGyUM-UjHJNEvtVOGMhEHq2OcywxwSjKJfioxLg,90009
52
52
  resqpy/grid_surface/_grid_skin.py,sha256=D0cjHkcuT5KCKb-8EZfXgh0GgJj3kzOBS2wVNXg4bfY,26056
53
53
  resqpy/grid_surface/_grid_surface.py,sha256=l2NJo7Kiucolbb_TlLPC7NGdksg_JahkihfsrJVq99w,14379
54
54
  resqpy/grid_surface/_trajectory_intersects.py,sha256=Och9cZYU9Y7ofovhPzsLyIblRUl2xj9_5nHH3fMZp-A,22498
@@ -98,7 +98,7 @@ resqpy/olio/transmission.py,sha256=auz_12TKtSPy6Fv3wmKn5lXPRAEnn2tYVyTQfsj37xU,6
98
98
  resqpy/olio/triangulation.py,sha256=0WkN93PzBZ_hfAQ-CYNFldfW88koehPEL62GAjY7ZeM,45928
99
99
  resqpy/olio/uuid.py,sha256=JRMi-RZNeGm8tGNloIwTATzNtdj29lBQDV9OILboPRI,7324
100
100
  resqpy/olio/vdb.py,sha256=lQYuK1kr1Wnucq2EoKgT6lrR7vloCemnCKZktzBcLUc,45231
101
- resqpy/olio/vector_utilities.py,sha256=zPJHAcdEvuHNm2L3ldEHztBxVSHVJaSSClCO4ooFRG8,53546
101
+ resqpy/olio/vector_utilities.py,sha256=B354cr9-nqqPcb3SAx1jD9Uk51sjkV95xToAiF3-WHA,61127
102
102
  resqpy/olio/volume.py,sha256=F1pMnDoJ4ricy4dfdLuLuK1xkVgJckL9V06tUeyK6Wc,6185
103
103
  resqpy/olio/wellspec_keywords.py,sha256=ad3B727golWYiko54OZOw7vG21IvpNxCMCyLv8jSkcI,26533
104
104
  resqpy/olio/write_data.py,sha256=bIX7ilMkXWCMz_zQh-Gqk56sNzng4W5l4BahW2EV7Kw,5142
@@ -163,10 +163,10 @@ resqpy/surface/_base_surface.py,sha256=LsWrDrbuuaEVRgf2Dlbc-6ZvGQpjtrKuxF7Jjebvl
163
163
  resqpy/surface/_combined_surface.py,sha256=8TnNbSywjej6tW_vRr5zoVgBbvnadCaqWk6WyHWHTYQ,3082
164
164
  resqpy/surface/_mesh.py,sha256=yEFldNWT2g8MCGcU4mTeWzDrLHHGLLGLIle1gAjJ_lg,42352
165
165
  resqpy/surface/_pointset.py,sha256=niTkBik9hAvqrY8340K1TRG7mg4FMQbbp12WZiiXPMs,27416
166
- resqpy/surface/_surface.py,sha256=J2BN3wLzrwbvM5jaFsZpHSa7iRHCS2BQvr8T9rE7BXE,71172
166
+ resqpy/surface/_surface.py,sha256=fdVLBC4vI8SwsGNFNZhhPFu0FStlXIgzwxGRBSh85LY,71703
167
167
  resqpy/surface/_tri_mesh.py,sha256=EmV4FhyjuusQFruW1SseufbnHF5YFoJ6Uvb07UJbH6s,26609
168
168
  resqpy/surface/_tri_mesh_stencil.py,sha256=eXt_HIKvsXGsjQ7nm_NbozR6ProQxPbeO52r79j80ig,16087
169
- resqpy/surface/_triangulated_patch.py,sha256=y8XWN_AglpEzRfNvgY0RWSLaNXrI3gZ_8gZHuzuPTjk,26451
169
+ resqpy/surface/_triangulated_patch.py,sha256=FKn_Irzp4aLFkkN_-tx1MLMKjEAiOLE8636sOA481TQ,26802
170
170
  resqpy/time_series/__init__.py,sha256=jiB3HJUWe47OOJTVmRJ4Gh5vm-XdMaMXmD52kAGr2zY,1074
171
171
  resqpy/time_series/_any_time_series.py,sha256=43q5hV-VKReZ6rRMEFHx977OVcOKwPvWOJbB9fj3SFQ,8755
172
172
  resqpy/time_series/_from_nexus_summary.py,sha256=LWTcJNx_rDFNGP2iWk74ABip_f__iYNBE0R8lVzHOYo,6617
@@ -194,7 +194,7 @@ resqpy/well/_wellbore_marker_frame.py,sha256=xvYH2_2Ie3a18LReFymbUrZboOx7Rhv5DOD
194
194
  resqpy/well/blocked_well_frame.py,sha256=eK7Ca6PcqI3pK-XurZIcXAV5Z4B9PFe6H8a7DqVkmBo,22560
195
195
  resqpy/well/well_object_funcs.py,sha256=tWufc8wahihzMEO-Ou1dncIttrf4bNo1qmLgh3I2pOM,24717
196
196
  resqpy/well/well_utils.py,sha256=zwpYjT85nXAwWBhYB1Pygu2SgouZ-44k6hEOnpoMfBI,5969
197
- resqpy-4.17.0.dist-info/LICENSE,sha256=2duHPIkKQyESMdQ4hKjL8CYEsYRHXaYxt0YQkzsUYE4,1059
198
- resqpy-4.17.0.dist-info/METADATA,sha256=QpYj5sjXGcHQ3pQmtPBT4r-bEl1DxBrsL1R36zez7D0,4028
199
- resqpy-4.17.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
200
- resqpy-4.17.0.dist-info/RECORD,,
197
+ resqpy-4.17.2.dist-info/LICENSE,sha256=2duHPIkKQyESMdQ4hKjL8CYEsYRHXaYxt0YQkzsUYE4,1059
198
+ resqpy-4.17.2.dist-info/METADATA,sha256=82xvzgf-VX_O4dY0-3dNaM8wiGxwnMcaP_dJg3cJ-EM,4028
199
+ resqpy-4.17.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
200
+ resqpy-4.17.2.dist-info/RECORD,,