resqpy 4.18.11__py3-none-any.whl → 5.1.0__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.
- resqpy/__init__.py +1 -1
 - resqpy/grid/__init__.py +2 -3
 - resqpy/grid/_grid.py +1 -7
 - resqpy/grid_surface/_find_faces.py +98 -29
 - resqpy/lines/_polyline.py +24 -33
 - resqpy/model/_model.py +9 -9
 - resqpy/multi_processing/wrappers/grid_surface_mp.py +91 -44
 - resqpy/olio/triangulation.py +19 -17
 - resqpy/olio/volume.py +0 -20
 - resqpy/property/__init__.py +3 -2
 - resqpy/property/_collection_get_attributes.py +2 -0
 - resqpy/rq_import/_grid_from_cp.py +2 -2
 - resqpy/surface/_surface.py +377 -53
 - resqpy/surface/_tri_mesh.py +3 -1
 - resqpy/time_series/_any_time_series.py +5 -4
 - resqpy/well/_blocked_well.py +1916 -1910
 - resqpy/well/_md_datum.py +11 -21
 - resqpy/well/_wellbore_frame.py +10 -2
 - resqpy/well/well_utils.py +33 -0
 - {resqpy-4.18.11.dist-info → resqpy-5.1.0.dist-info}/METADATA +8 -8
 - {resqpy-4.18.11.dist-info → resqpy-5.1.0.dist-info}/RECORD +23 -24
 - {resqpy-4.18.11.dist-info → resqpy-5.1.0.dist-info}/WHEEL +1 -1
 - resqpy/grid/_moved_functions.py +0 -15
 - {resqpy-4.18.11.dist-info → resqpy-5.1.0.dist-info}/LICENSE +0 -0
 
| 
         @@ -4,8 +4,10 @@ import logging 
     | 
|
| 
       4 
4 
     | 
    
         | 
| 
       5 
5 
     | 
    
         
             
            log = logging.getLogger(__name__)
         
     | 
| 
       6 
6 
     | 
    
         | 
| 
      
 7 
     | 
    
         
            +
            import os
         
     | 
| 
       7 
8 
     | 
    
         
             
            import numpy as np
         
     | 
| 
       8 
9 
     | 
    
         
             
            import uuid
         
     | 
| 
      
 10 
     | 
    
         
            +
            import ast
         
     | 
| 
       9 
11 
     | 
    
         
             
            from typing import Tuple, Union, List, Optional, Callable
         
     | 
| 
       10 
12 
     | 
    
         
             
            from pathlib import Path
         
     | 
| 
       11 
13 
     | 
    
         
             
            from uuid import UUID
         
     | 
| 
         @@ -18,33 +20,38 @@ import resqpy.surface as rqs 
     | 
|
| 
       18 
20 
     | 
    
         
             
            import resqpy.olio.uuid as bu
         
     | 
| 
       19 
21 
     | 
    
         | 
| 
       20 
22 
     | 
    
         | 
| 
       21 
     | 
    
         
            -
            def find_faces_to_represent_surface_regular_wrapper( 
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
             
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
             
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
             
     | 
| 
       37 
     | 
    
         
            -
             
     | 
| 
       38 
     | 
    
         
            -
             
     | 
| 
       39 
     | 
    
         
            -
             
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
             
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
             
     | 
| 
       45 
     | 
    
         
            -
             
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
             
     | 
| 
      
 23 
     | 
    
         
            +
            def find_faces_to_represent_surface_regular_wrapper(
         
     | 
| 
      
 24 
     | 
    
         
            +
                    index: int,
         
     | 
| 
      
 25 
     | 
    
         
            +
                    parent_tmp_dir: str,
         
     | 
| 
      
 26 
     | 
    
         
            +
                    use_index_as_realisation: bool,
         
     | 
| 
      
 27 
     | 
    
         
            +
                    grid_epc: str,
         
     | 
| 
      
 28 
     | 
    
         
            +
                    grid_uuid: Union[UUID, str],
         
     | 
| 
      
 29 
     | 
    
         
            +
                    surface_epc: str,
         
     | 
| 
      
 30 
     | 
    
         
            +
                    surface_uuid: Union[UUID, str],
         
     | 
| 
      
 31 
     | 
    
         
            +
                    name: str,
         
     | 
| 
      
 32 
     | 
    
         
            +
                    title: Optional[str] = None,
         
     | 
| 
      
 33 
     | 
    
         
            +
                    agitate: bool = False,
         
     | 
| 
      
 34 
     | 
    
         
            +
                    random_agitation: bool = False,
         
     | 
| 
      
 35 
     | 
    
         
            +
                    feature_type: str = 'fault',
         
     | 
| 
      
 36 
     | 
    
         
            +
                    trimmed: bool = False,
         
     | 
| 
      
 37 
     | 
    
         
            +
                    is_curtain = False,
         
     | 
| 
      
 38 
     | 
    
         
            +
                    extend_fault_representation: bool = False,
         
     | 
| 
      
 39 
     | 
    
         
            +
                    flange_inner_ring: bool = False,
         
     | 
| 
      
 40 
     | 
    
         
            +
                    saucer_parameter: Optional[float] = None,
         
     | 
| 
      
 41 
     | 
    
         
            +
                    retriangulate: bool = False,
         
     | 
| 
      
 42 
     | 
    
         
            +
                    related_uuid: Optional[Union[UUID, str]] = None,
         
     | 
| 
      
 43 
     | 
    
         
            +
                    progress_fn: Optional[Callable] = None,
         
     | 
| 
      
 44 
     | 
    
         
            +
                    extra_metadata = None,
         
     | 
| 
      
 45 
     | 
    
         
            +
                    return_properties: Optional[List[str]] = None,
         
     | 
| 
      
 46 
     | 
    
         
            +
                    raw_bisector: bool = False,
         
     | 
| 
      
 47 
     | 
    
         
            +
                    use_pack: bool = False,
         
     | 
| 
      
 48 
     | 
    
         
            +
                    flange_radius: Optional[float] = None,
         
     | 
| 
      
 49 
     | 
    
         
            +
                    reorient: bool = True,
         
     | 
| 
      
 50 
     | 
    
         
            +
                    n_threads: int = 20,
         
     | 
| 
      
 51 
     | 
    
         
            +
                    patchwork: bool = False,
         
     | 
| 
      
 52 
     | 
    
         
            +
                    grid_patching_property_uuid: Optional[Union[UUID, str]] = None,
         
     | 
| 
      
 53 
     | 
    
         
            +
                    surface_patching_property_uuid: Optional[Union[UUID, str]] = None) ->  \
         
     | 
| 
      
 54 
     | 
    
         
            +
                        Tuple[int, bool, str, List[Union[UUID, str]]]:
         
     | 
| 
       48 
55 
     | 
    
         
             
                """Multiprocessing wrapper function of find_faces_to_represent_surface_regular_optimised.
         
     | 
| 
       49 
56 
     | 
    
         | 
| 
       50 
57 
     | 
    
         
             
                arguments:
         
     | 
| 
         @@ -98,8 +105,17 @@ def find_faces_to_represent_surface_regular_wrapper(index: int, 
     | 
|
| 
       98 
105 
     | 
    
         
             
                    flange_radius (float, optional): the radial distance to use for outer flange extension points; if None,
         
     | 
| 
       99 
106 
     | 
    
         
             
                       a large value will be calculated from the grid size; units are xy units of grid crs
         
     | 
| 
       100 
107 
     | 
    
         
             
                    reorient (bool, default True):  if True, the points are reoriented to minimise the
         
     | 
| 
       101 
     | 
    
         
            -
             
     | 
| 
      
 108 
     | 
    
         
            +
                       z range prior to retriangulation (ie. z axis is approximate normal to plane of points), to enhace the triangulation
         
     | 
| 
       102 
109 
     | 
    
         
             
                    n_threads (int, default 20): the number of parallel threads to use in numba points in triangles function
         
     | 
| 
      
 110 
     | 
    
         
            +
                    patchwork (bool, default False): if True and grid bisector is included in return properties, a compostite
         
     | 
| 
      
 111 
     | 
    
         
            +
                       bisector is generated, based on individual ones for each patch of the surface; the following two
         
     | 
| 
      
 112 
     | 
    
         
            +
                       arguments must be set if patchwork is True
         
     | 
| 
      
 113 
     | 
    
         
            +
                    grid_patching_property_uuid (uuid, optional): required if patchwork is True, the uuid of a discrete or
         
     | 
| 
      
 114 
     | 
    
         
            +
                       categorical cells property on the grid which will be used to determine which patch of the surface is
         
     | 
| 
      
 115 
     | 
    
         
            +
                       relevant to a cell
         
     | 
| 
      
 116 
     | 
    
         
            +
                    surface_patching_property_uuid (uuid, optional): required if patchwork is True, the uuid of a discrete or
         
     | 
| 
      
 117 
     | 
    
         
            +
                       categorical property on the patches of the surface, identifying the value of the grid patching property
         
     | 
| 
      
 118 
     | 
    
         
            +
                       that each patch relates to
         
     | 
| 
       103 
119 
     | 
    
         | 
| 
       104 
120 
     | 
    
         
             
                returns:
         
     | 
| 
       105 
121 
     | 
    
         
             
                    Tuple containing:
         
     | 
| 
         @@ -109,18 +125,15 @@ def find_faces_to_represent_surface_regular_wrapper(index: int, 
     | 
|
| 
       109 
125 
     | 
    
         
             
                        - uuid_list (List[str]): list of UUIDs of relevant objects
         
     | 
| 
       110 
126 
     | 
    
         | 
| 
       111 
127 
     | 
    
         
             
                notes:
         
     | 
| 
       112 
     | 
    
         
            -
                     
     | 
| 
       113 
     | 
    
         
            -
             
     | 
| 
       114 
     | 
    
         
            -
             
     | 
| 
       115 
     | 
    
         
            -
                    the saucer_parameter is  
     | 
| 
       116 
     | 
    
         
            -
             
     | 
| 
       117 
     | 
    
         
            -
             
     | 
| 
       118 
     | 
    
         
            -
             
     | 
| 
       119 
     | 
    
         
            -
             
     | 
| 
       120 
     | 
    
         
            -
                     
     | 
| 
       121 
     | 
    
         
            -
                    +ve angles result in the shift being in the direction of the -ve z hemisphere; -ve angles result in
         
     | 
| 
       122 
     | 
    
         
            -
                    the shift being in the +ve z hemisphere; in either case the direction of the shift is perpendicular
         
     | 
| 
       123 
     | 
    
         
            -
                    to the average plane of the original points
         
     | 
| 
      
 128 
     | 
    
         
            +
                    - use this function as argument to the multiprocessing function; it will create a new model that is saved
         
     | 
| 
      
 129 
     | 
    
         
            +
                      in a temporary epc file and returns the required values, which are used in the multiprocessing function to
         
     | 
| 
      
 130 
     | 
    
         
            +
                      recombine all the objects into a single epc file
         
     | 
| 
      
 131 
     | 
    
         
            +
                    - the saucer_parameter is between -90.0 and 90.0 and is interpreted as an angle to apply out of
         
     | 
| 
      
 132 
     | 
    
         
            +
                      the plane of the original points, to give a simple saucer shape;
         
     | 
| 
      
 133 
     | 
    
         
            +
                      +ve angles result in the shift being in the direction of the -ve z hemisphere; -ve angles result in
         
     | 
| 
      
 134 
     | 
    
         
            +
                      the shift being in the +ve z hemisphere; in either case the direction of the shift is perpendicular
         
     | 
| 
      
 135 
     | 
    
         
            +
                      to the average plane of the original points
         
     | 
| 
      
 136 
     | 
    
         
            +
                    - patchwork is not compatible with re-triangulation
         
     | 
| 
       124 
137 
     | 
    
         
             
                """
         
     | 
| 
       125 
138 
     | 
    
         
             
                tmp_dir = Path(parent_tmp_dir) / f"{uuid.uuid4()}"
         
     | 
| 
       126 
139 
     | 
    
         
             
                tmp_dir.mkdir(parents = True, exist_ok = True)
         
     | 
| 
         @@ -149,11 +162,18 @@ def find_faces_to_represent_surface_regular_wrapper(index: int, 
     | 
|
| 
       149 
162 
     | 
    
         
             
                    flange_radius = 5.0 * np.sum(np.array(grid.extent_kji, dtype = float) * np.array(grid.aligned_dxyz()))
         
     | 
| 
       150 
163 
     | 
    
         
             
                s_model = rq.Model(surface_epc, quiet = True)
         
     | 
| 
       151 
164 
     | 
    
         
             
                model.copy_uuid_from_other_model(s_model, uuid = str(surface_uuid))
         
     | 
| 
      
 165 
     | 
    
         
            +
                if surface_patching_property_uuid is not None:
         
     | 
| 
      
 166 
     | 
    
         
            +
                    model.copy_uuid_from_other_model(s_model, uuid = surface_patching_property_uuid)
         
     | 
| 
      
 167 
     | 
    
         
            +
                    uuid_list.append(surface_patching_property_uuid)
         
     | 
| 
       152 
168 
     | 
    
         
             
                repr_type = model.type_of_part(model.part(uuid = surface_uuid), strip_obj = True)
         
     | 
| 
       153 
169 
     | 
    
         
             
                assert repr_type in ['TriangulatedSetRepresentation', 'PointSetRepresentation']
         
     | 
| 
      
 170 
     | 
    
         
            +
                assert repr_type == 'TriangulatedSetRepresentation' or not patchwork,  \
         
     | 
| 
      
 171 
     | 
    
         
            +
                    'patchwork only implemented for triangulated set surfaces'
         
     | 
| 
      
 172 
     | 
    
         
            +
             
     | 
| 
       154 
173 
     | 
    
         
             
                extended = False
         
     | 
| 
       155 
174 
     | 
    
         
             
                retriangulated = False
         
     | 
| 
       156 
175 
     | 
    
         
             
                flange_bool = None
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
       157 
177 
     | 
    
         
             
                if repr_type == 'PointSetRepresentation':
         
     | 
| 
       158 
178 
     | 
    
         
             
                    # trim pointset to grid xyz box
         
     | 
| 
       159 
179 
     | 
    
         
             
                    pset = rqs.PointSet(model, uuid = surface_uuid)
         
     | 
| 
         @@ -197,15 +217,22 @@ def find_faces_to_represent_surface_regular_wrapper(index: int, 
     | 
|
| 
       197 
217 
     | 
    
         
             
                surf_title = surface.title
         
     | 
| 
       198 
218 
     | 
    
         
             
                assert surf_title
         
     | 
| 
       199 
219 
     | 
    
         
             
                surface.change_crs(grid.crs)
         
     | 
| 
      
 220 
     | 
    
         
            +
                normal_vector = None
         
     | 
| 
      
 221 
     | 
    
         
            +
                if reorient:
         
     | 
| 
      
 222 
     | 
    
         
            +
                    normal_vector = surface.normal()
         
     | 
| 
      
 223 
     | 
    
         
            +
                if patchwork:  # disable trimming as whole patches could be trimmed out, changing the patch indexing from that expected
         
     | 
| 
      
 224 
     | 
    
         
            +
                    trimmed = True
         
     | 
| 
       200 
225 
     | 
    
         
             
                if not trimmed and surface.triangle_count() > 100:
         
     | 
| 
       201 
226 
     | 
    
         
             
                    if not surf_title.endswith('trimmed'):
         
     | 
| 
       202 
227 
     | 
    
         
             
                        surf_title += ' trimmed'
         
     | 
| 
       203 
228 
     | 
    
         
             
                    trimmed_surf = rqs.Surface(model, crs_uuid = grid.crs.uuid, title = surf_title)
         
     | 
| 
       204 
229 
     | 
    
         
             
                    # trimmed_surf.set_to_trimmed_surface(surf, xyz_box = xyz_box, xy_polygon = parent_seg.polygon)
         
     | 
| 
       205 
230 
     | 
    
         
             
                    trimmed_surf.set_to_trimmed_surface(surface, xyz_box = grid.xyz_box(local = True))
         
     | 
| 
      
 231 
     | 
    
         
            +
                    trimmed_surf.extra_metadata = surface.extra_metadata
         
     | 
| 
       206 
232 
     | 
    
         
             
                    surface = trimmed_surf
         
     | 
| 
       207 
233 
     | 
    
         
             
                    trimmed = True
         
     | 
| 
       208 
234 
     | 
    
         
             
                if (extend_fault_representation and not extended) or (retriangulate and not retriangulated):
         
     | 
| 
      
 235 
     | 
    
         
            +
                    assert not patchwork, 'extension or re-triangulation are not compatible with patchwork'
         
     | 
| 
       209 
236 
     | 
    
         
             
                    _, p = surface.triangles_and_points()
         
     | 
| 
       210 
237 
     | 
    
         
             
                    pset = rqs.PointSet(model, points_array = p, crs_uuid = grid.crs.uuid, title = surf_title)
         
     | 
| 
       211 
238 
     | 
    
         
             
                    if extend_fault_representation and not surf_title.endswith('extended'):
         
     | 
| 
         @@ -213,12 +240,13 @@ def find_faces_to_represent_surface_regular_wrapper(index: int, 
     | 
|
| 
       213 
240 
     | 
    
         
             
                    surface = rqs.Surface(model, crs_uuid = grid.crs.uuid, title = surf_title)
         
     | 
| 
       214 
241 
     | 
    
         
             
                    flange_bool = surface.set_from_point_set(pset,
         
     | 
| 
       215 
242 
     | 
    
         
             
                                                             convexity_parameter = 2.0,
         
     | 
| 
       216 
     | 
    
         
            -
                                                             reorient =  
     | 
| 
      
 243 
     | 
    
         
            +
                                                             reorient = reorient,
         
     | 
| 
       217 
244 
     | 
    
         
             
                                                             extend_with_flange = extend_fault_representation,
         
     | 
| 
       218 
245 
     | 
    
         
             
                                                             flange_inner_ring = flange_inner_ring,
         
     | 
| 
       219 
246 
     | 
    
         
             
                                                             saucer_parameter = saucer_parameter,
         
     | 
| 
       220 
247 
     | 
    
         
             
                                                             flange_radial_distance = flange_radius,
         
     | 
| 
       221 
     | 
    
         
            -
                                                             make_clockwise = False 
     | 
| 
      
 248 
     | 
    
         
            +
                                                             make_clockwise = False,
         
     | 
| 
      
 249 
     | 
    
         
            +
                                                             normal_vector = normal_vector)
         
     | 
| 
       222 
250 
     | 
    
         
             
                    del pset
         
     | 
| 
       223 
251 
     | 
    
         
             
                    extended = extend_fault_representation
         
     | 
| 
       224 
252 
     | 
    
         
             
                    retriangulated = True
         
     | 
| 
         @@ -242,7 +270,23 @@ def find_faces_to_represent_surface_regular_wrapper(index: int, 
     | 
|
| 
       242 
270 
     | 
    
         
             
                                                       discrete = True,
         
     | 
| 
       243 
271 
     | 
    
         
             
                                                       dtype = np.uint8)
         
     | 
| 
       244 
272 
     | 
    
         
             
                    uuid_list.append(flange_p.uuid)
         
     | 
| 
       245 
     | 
    
         
            -
             
     | 
| 
      
 273 
     | 
    
         
            +
             
     | 
| 
      
 274 
     | 
    
         
            +
                if not patchwork:
         
     | 
| 
      
 275 
     | 
    
         
            +
                    uuid_list.append(surface_uuid)
         
     | 
| 
      
 276 
     | 
    
         
            +
             
     | 
| 
      
 277 
     | 
    
         
            +
                patch_indices = None
         
     | 
| 
      
 278 
     | 
    
         
            +
                if patchwork:  # generate a patch indices array over grid cells based on supplied patching properties
         
     | 
| 
      
 279 
     | 
    
         
            +
                    assert grid_patching_property_uuid is not None and surface_patching_property_uuid is not None
         
     | 
| 
      
 280 
     | 
    
         
            +
                    g_patching_array = rqp.Property(g_model, uuid = grid_patching_property_uuid).array_ref()
         
     | 
| 
      
 281 
     | 
    
         
            +
                    assert g_patching_array.shape == tuple(grid.extent_kji)
         
     | 
| 
      
 282 
     | 
    
         
            +
                    s_patches_array = rqp.Property(model, uuid = surface_patching_property_uuid).array_ref()
         
     | 
| 
      
 283 
     | 
    
         
            +
                    patch_count = surface.number_of_patches()
         
     | 
| 
      
 284 
     | 
    
         
            +
                    assert s_patches_array.shape == (patch_count,)
         
     | 
| 
      
 285 
     | 
    
         
            +
                    p_dtype = (np.int8 if s_patches_array.shape[0] < 128 else np.int32)
         
     | 
| 
      
 286 
     | 
    
         
            +
                    patch_indices = np.full(g_patching_array.shape, -1, dtype = p_dtype)
         
     | 
| 
      
 287 
     | 
    
         
            +
                    for patch in range(patch_count):
         
     | 
| 
      
 288 
     | 
    
         
            +
                        gp = s_patches_array[patch]
         
     | 
| 
      
 289 
     | 
    
         
            +
                        patch_indices[(g_patching_array == gp).astype(bool)] = patch
         
     | 
| 
       246 
290 
     | 
    
         | 
| 
       247 
291 
     | 
    
         
             
                returns = rqgs.find_faces_to_represent_surface_regular_optimised(grid,
         
     | 
| 
       248 
292 
     | 
    
         
             
                                                                                 surface,
         
     | 
| 
         @@ -256,7 +300,8 @@ def find_faces_to_represent_surface_regular_wrapper(index: int, 
     | 
|
| 
       256 
300 
     | 
    
         
             
                                                                                 return_properties,
         
     | 
| 
       257 
301 
     | 
    
         
             
                                                                                 raw_bisector = raw_bisector,
         
     | 
| 
       258 
302 
     | 
    
         
             
                                                                                 n_batches = n_threads,
         
     | 
| 
       259 
     | 
    
         
            -
                                                                                 packed_bisectors = use_pack 
     | 
| 
      
 303 
     | 
    
         
            +
                                                                                 packed_bisectors = use_pack,
         
     | 
| 
      
 304 
     | 
    
         
            +
                                                                                 patch_indices = patch_indices)
         
     | 
| 
       260 
305 
     | 
    
         | 
| 
       261 
306 
     | 
    
         
             
                success = False
         
     | 
| 
       262 
307 
     | 
    
         | 
| 
         @@ -286,6 +331,7 @@ def find_faces_to_represent_surface_regular_wrapper(index: int, 
     | 
|
| 
       286 
331 
     | 
    
         | 
| 
       287 
332 
     | 
    
         
             
                if success and return_properties is not None and len(return_properties):
         
     | 
| 
       288 
333 
     | 
    
         
             
                    log.debug(f'{name} requested properties: {return_properties}')
         
     | 
| 
      
 334 
     | 
    
         
            +
                    assert isinstance(returns, tuple)
         
     | 
| 
       289 
335 
     | 
    
         
             
                    properties = returns[1]
         
     | 
| 
       290 
336 
     | 
    
         
             
                    realisation = index if use_index_as_realisation else None
         
     | 
| 
       291 
337 
     | 
    
         
             
                    property_collection = rqp.PropertyCollection(support = gcs)
         
     | 
| 
         @@ -346,6 +392,7 @@ def find_faces_to_represent_surface_regular_wrapper(index: int, 
     | 
|
| 
       346 
392 
     | 
    
         
             
                            if grid_pc is None:
         
     | 
| 
       347 
393 
     | 
    
         
             
                                grid_pc = rqp.PropertyCollection()
         
     | 
| 
       348 
394 
     | 
    
         
             
                                grid_pc.set_support(support = grid)
         
     | 
| 
      
 395 
     | 
    
         
            +
                            assert array.ndim == (2 if is_curtain else 3)
         
     | 
| 
       349 
396 
     | 
    
         
             
                            grid_pc.add_cached_array_to_imported_list(array,
         
     | 
| 
       350 
397 
     | 
    
         
             
                                                                      f"from find_faces function for {surface.title}",
         
     | 
| 
       351 
398 
     | 
    
         
             
                                                                      f'{surface.title} {p_name}',
         
     | 
    
        resqpy/olio/triangulation.py
    CHANGED
    
    | 
         @@ -25,7 +25,7 @@ import resqpy.olio.vector_utilities as vec 
     | 
|
| 
       25 
25 
     | 
    
         | 
| 
       26 
26 
     | 
    
         
             
            def _dt_scipy(points: np.ndarray) -> Tuple[np.ndarray, np.ndarray]:
         
     | 
| 
       27 
27 
     | 
    
         
             
                """Calculates the Delaunay triangulation for an array of points and the convex hull indices.
         
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
       29 
29 
     | 
    
         
             
                arguments:
         
     | 
| 
       30 
30 
     | 
    
         
             
                    points (np.ndarray): coordinates of the points to triangulate; array has shape
         
     | 
| 
       31 
31 
     | 
    
         
             
                        (npoints, ndim)
         
     | 
| 
         @@ -48,7 +48,7 @@ def _dt_scipy(points: np.ndarray) -> Tuple[np.ndarray, np.ndarray]: 
     | 
|
| 
       48 
48 
     | 
    
         | 
| 
       49 
49 
     | 
    
         | 
| 
       50 
50 
     | 
    
         
             
            def _dt_simple(po, plot_fn = None, progress_fn = None, container_size_factor = None):
         
     | 
| 
       51 
     | 
    
         
            -
                # returns  
     | 
| 
      
 51 
     | 
    
         
            +
                # returns Delaunay triangulation of po and list of hull point indices, using a simple algorithm
         
     | 
| 
       52 
52 
     | 
    
         | 
| 
       53 
53 
     | 
    
         
             
                def flip(ei):
         
     | 
| 
       54 
54 
     | 
    
         
             
                    nonlocal fm, e, t, te, p, nt, p_i, ne
         
     | 
| 
         @@ -234,7 +234,7 @@ def _dt_simple(po, plot_fn = None, progress_fn = None, container_size_factor = N 
     | 
|
| 
       234 
234 
     | 
    
         | 
| 
       235 
235 
     | 
    
         | 
| 
       236 
236 
     | 
    
         
             
            def dt(p, algorithm = "scipy", plot_fn = None, progress_fn = None, container_size_factor = 100.0, return_hull = False):
         
     | 
| 
       237 
     | 
    
         
            -
                """Returns the  
     | 
| 
      
 237 
     | 
    
         
            +
                """Returns the Delaunay Triangulation of 2D point set p.
         
     | 
| 
       238 
238 
     | 
    
         | 
| 
       239 
239 
     | 
    
         
             
                arguments:
         
     | 
| 
       240 
240 
     | 
    
         
             
                   p (numpy float array of shape (N, 2): the x,y coordinates of the points
         
     | 
| 
         @@ -253,7 +253,7 @@ def dt(p, algorithm = "scipy", plot_fn = None, progress_fn = None, container_siz 
     | 
|
| 
       253 
253 
     | 
    
         | 
| 
       254 
254 
     | 
    
         
             
                returns:
         
     | 
| 
       255 
255 
     | 
    
         
             
                   numpy int array of shape (M, 3) - being the indices into the first axis of p of the 3 points
         
     | 
| 
       256 
     | 
    
         
            -
                      per triangle in the  
     | 
| 
      
 256 
     | 
    
         
            +
                      per triangle in the Delaunay Triangulation - and if return_hull is True, another int array
         
     | 
| 
       257 
257 
     | 
    
         
             
                      of shape (B,) - being indices into p of the clockwise ordered points on the boundary of
         
     | 
| 
       258 
258 
     | 
    
         
             
                      the triangulation
         
     | 
| 
       259 
259 
     | 
    
         | 
| 
         @@ -261,7 +261,7 @@ def dt(p, algorithm = "scipy", plot_fn = None, progress_fn = None, container_siz 
     | 
|
| 
       261 
261 
     | 
    
         
             
                   the plot_fn, progress_fn and container_size_factor arguments are only used by the 'simple' algorithm;
         
     | 
| 
       262 
262 
     | 
    
         
             
                   if points p are 3D, the projection onto the xy plane is used for the triangulation
         
     | 
| 
       263 
263 
     | 
    
         
             
                """
         
     | 
| 
       264 
     | 
    
         
            -
                assert p.ndim == 2 and p.shape[1] >= 2, 'bad points shape for 2D  
     | 
| 
      
 264 
     | 
    
         
            +
                assert p.ndim == 2 and p.shape[1] >= 2, 'bad points shape for 2D Delaunay Triangulation'
         
     | 
| 
       265 
265 
     | 
    
         | 
| 
       266 
266 
     | 
    
         
             
                if not algorithm:
         
     | 
| 
       267 
267 
     | 
    
         
             
                    algorithm = 'scipy'
         
     | 
| 
         @@ -274,7 +274,7 @@ def dt(p, algorithm = "scipy", plot_fn = None, progress_fn = None, container_siz 
     | 
|
| 
       274 
274 
     | 
    
         
             
                                               progress_fn = progress_fn,
         
     | 
| 
       275 
275 
     | 
    
         
             
                                               container_size_factor = container_size_factor)
         
     | 
| 
       276 
276 
     | 
    
         
             
                else:
         
     | 
| 
       277 
     | 
    
         
            -
                    raise Exception(f'unrecognised  
     | 
| 
      
 277 
     | 
    
         
            +
                    raise Exception(f'unrecognised Delaunay Triangulation algorithm name: {algorithm}')
         
     | 
| 
       278 
278 
     | 
    
         | 
| 
       279 
279 
     | 
    
         
             
                assert tri.ndim == 2 and tri.shape[1] == 3
         
     | 
| 
       280 
280 
     | 
    
         | 
| 
         @@ -304,11 +304,11 @@ def ccc(p1, p2, p3): 
     | 
|
| 
       304 
304 
     | 
    
         | 
| 
       305 
305 
     | 
    
         | 
| 
       306 
306 
     | 
    
         
             
            def voronoi(p, t, b, aoi: rql.Polyline):
         
     | 
| 
       307 
     | 
    
         
            -
                """Returns dual Voronoi diagram for a  
     | 
| 
      
 307 
     | 
    
         
            +
                """Returns dual Voronoi diagram for a Delaunay triangulation.
         
     | 
| 
       308 
308 
     | 
    
         | 
| 
       309 
309 
     | 
    
         
             
                arguments:
         
     | 
| 
       310 
     | 
    
         
            -
                   p (numpy float array of shape (N, 2)): seed points used in the  
     | 
| 
       311 
     | 
    
         
            -
                   t (numpy int array of shape (M, 3)): the  
     | 
| 
      
 310 
     | 
    
         
            +
                   p (numpy float array of shape (N, 2)): seed points used in the Delaunay triangulation
         
     | 
| 
      
 311 
     | 
    
         
            +
                   t (numpy int array of shape (M, 3)): the Delaunay triangulation of p as returned by dt()
         
     | 
| 
       312 
312 
     | 
    
         
             
                   b (numpy int array of shape (B,)): clockwise sorted list of indices into p of the boundary
         
     | 
| 
       313 
313 
     | 
    
         
             
                      points of the triangulation t
         
     | 
| 
       314 
314 
     | 
    
         
             
                   aoi (lines.Polyline): area of interest; a closed clockwise polyline that must strictly contain
         
     | 
| 
         @@ -329,7 +329,7 @@ def voronoi(p, t, b, aoi: rql.Polyline): 
     | 
|
| 
       329 
329 
     | 
    
         | 
| 
       330 
330 
     | 
    
         
             
                # this code assumes that the Voronoi polygon for a seed point visits the circumcentres of
         
     | 
| 
       331 
331 
     | 
    
         
             
                # all the triangles that make use of the point – currently understood to be always the case
         
     | 
| 
       332 
     | 
    
         
            -
                # for a  
     | 
| 
      
 332 
     | 
    
         
            +
                # for a Delaunay triangulation
         
     | 
| 
       333 
333 
     | 
    
         | 
| 
       334 
334 
     | 
    
         
             
                def __aoi_intervening_nodes(aoi_count, c_count, seg_a, seg_c):
         
     | 
| 
       335 
335 
     | 
    
         
             
                    nodes = []
         
     | 
| 
         @@ -582,7 +582,7 @@ def voronoi(p, t, b, aoi: rql.Polyline): 
     | 
|
| 
       582 
582 
     | 
    
         | 
| 
       583 
583 
     | 
    
         
             
                # check for concavities in hull
         
     | 
| 
       584 
584 
     | 
    
         
             
                if not hull.is_convex():
         
     | 
| 
       585 
     | 
    
         
            -
                    log.warning(' 
     | 
| 
      
 585 
     | 
    
         
            +
                    log.warning('Delaunay triangulation is not convex; Voronoi diagram construction might fail')
         
     | 
| 
       586 
586 
     | 
    
         | 
| 
       587 
587 
     | 
    
         
             
                # compute circumcircle centres
         
     | 
| 
       588 
588 
     | 
    
         
             
                c = np.zeros((t.shape[0], 2))
         
     | 
| 
         @@ -750,7 +750,7 @@ def reorient(points, rough = True, max_dip = None, use_linalg = True, sample = 5 
     | 
|
| 
       750 
750 
     | 
    
         
             
                notes:
         
     | 
| 
       751 
751 
     | 
    
         
             
                   the original points array is not modified by this function;
         
     | 
| 
       752 
752 
     | 
    
         
             
                   implicit xy & z units for points are assumed to be the same;
         
     | 
| 
       753 
     | 
    
         
            -
                   the function may typically be called prior to the  
     | 
| 
      
 753 
     | 
    
         
            +
                   the function may typically be called prior to the Delaunay triangulation, which uses an xy projection to
         
     | 
| 
       754 
754 
     | 
    
         
             
                   determine the triangulation;
         
     | 
| 
       755 
755 
     | 
    
         
             
                   the numpy linear algebra option seems to be memory intensive, not recommended;
         
     | 
| 
       756 
756 
     | 
    
         
             
                   downsampling will occur (for normal vector determination) when the number of points exceeds double that
         
     | 
| 
         @@ -868,9 +868,11 @@ def surrounding_xy_ring(p, 
     | 
|
| 
       868 
868 
     | 
    
         
             
                      being an angle to determine a z offset for the ring(s); a +ve angle results in a -ve z shift
         
     | 
| 
       869 
869 
     | 
    
         | 
| 
       870 
870 
     | 
    
         
             
                returns:
         
     | 
| 
       871 
     | 
    
         
            -
                   numpy float array 
     | 
| 
       872 
     | 
    
         
            -
                    
     | 
| 
       873 
     | 
    
         
            -
             
     | 
| 
      
 871 
     | 
    
         
            +
                   (numpy float array, float) pair:
         
     | 
| 
      
 872 
     | 
    
         
            +
                   - numpy float array of shape (N, 3) being xyz points in surrounding ring(s); z is set constant to
         
     | 
| 
      
 873 
     | 
    
         
            +
                     mean value of z in p (optionally adjussted based on saucer_angle);
         
     | 
| 
      
 874 
     | 
    
         
            +
                     N is count if inner_ring is False, 3 * count if True
         
     | 
| 
      
 875 
     | 
    
         
            +
                   - radius used for ring of additional points
         
     | 
| 
       874 
876 
     | 
    
         
             
                """
         
     | 
| 
       875 
877 
     | 
    
         | 
| 
       876 
878 
     | 
    
         
             
                def make_ring(count, centre, radius, saucer_angle):
         
     | 
| 
         @@ -898,8 +900,8 @@ def surrounding_xy_ring(p, 
     | 
|
| 
       898 
900 
     | 
    
         
             
                    inner_radius = p_radius * 1.1
         
     | 
| 
       899 
901 
     | 
    
         
             
                    assert radius > inner_radius
         
     | 
| 
       900 
902 
     | 
    
         
             
                    in_ring = make_ring(2 * count, centre, inner_radius, saucer_angle)
         
     | 
| 
       901 
     | 
    
         
            -
                    return np.concatenate((in_ring, ring), axis = 0)
         
     | 
| 
       902 
     | 
    
         
            -
                return ring
         
     | 
| 
      
 903 
     | 
    
         
            +
                    return np.concatenate((in_ring, ring), axis = 0), radius
         
     | 
| 
      
 904 
     | 
    
         
            +
                return ring, radius
         
     | 
| 
       903 
905 
     | 
    
         | 
| 
       904 
906 
     | 
    
         | 
| 
       905 
907 
     | 
    
         
             
            def edges(t):
         
     | 
    
        resqpy/olio/volume.py
    CHANGED
    
    | 
         @@ -77,26 +77,6 @@ def tetra_cell_volume(cp, centre = None, off_hand = False): 
     | 
|
| 
       77 
77 
     | 
    
         
             
                return v / 6.0
         
     | 
| 
       78 
78 
     | 
    
         | 
| 
       79 
79 
     | 
    
         | 
| 
       80 
     | 
    
         
            -
            def tetra_volumes_slow(cp, centres = None, off_hand = False):
         
     | 
| 
       81 
     | 
    
         
            -
                """Returns volume array for all hexahedral cells assuming bilinear faces, using loop over cells."""
         
     | 
| 
       82 
     | 
    
         
            -
             
     | 
| 
       83 
     | 
    
         
            -
                # NB: deprecated, superceded by much faster function below
         
     | 
| 
       84 
     | 
    
         
            -
                # todo: handle NaNs
         
     | 
| 
       85 
     | 
    
         
            -
                # Pagoda style corner point data
         
     | 
| 
       86 
     | 
    
         
            -
                assert cp.ndim == 7
         
     | 
| 
       87 
     | 
    
         
            -
             
     | 
| 
       88 
     | 
    
         
            -
                flat = cp.reshape(-1, 2, 2, 2, 3)
         
     | 
| 
       89 
     | 
    
         
            -
                cells = flat.shape[0]
         
     | 
| 
       90 
     | 
    
         
            -
                if centres is None:
         
     | 
| 
       91 
     | 
    
         
            -
                    centres = np.mean(flat, axis = (1, 2, 3))
         
     | 
| 
       92 
     | 
    
         
            -
                else:
         
     | 
| 
       93 
     | 
    
         
            -
                    centres = centres.reshape((-1, 3))
         
     | 
| 
       94 
     | 
    
         
            -
                volumes = np.zeros(cells)
         
     | 
| 
       95 
     | 
    
         
            -
                for cell in range(cells):
         
     | 
| 
       96 
     | 
    
         
            -
                    volumes[cell] = tetra_cell_volume(flat[cell], centre = centres[cell], off_hand = off_hand)
         
     | 
| 
       97 
     | 
    
         
            -
                return volumes.reshape(cp.shape[0:3])
         
     | 
| 
       98 
     | 
    
         
            -
             
     | 
| 
       99 
     | 
    
         
            -
             
     | 
| 
       100 
80 
     | 
    
         
             
            def tetra_volumes(cp, centres = None, off_hand = False):
         
     | 
| 
       101 
81 
     | 
    
         
             
                """Returns volume array for all hexahedral cells assuming bilinear faces, using numpy operations.
         
     | 
| 
       102 
82 
     | 
    
         | 
    
        resqpy/property/__init__.py
    CHANGED
    
    | 
         @@ -8,7 +8,8 @@ __all__ = [ 
     | 
|
| 
       8 
8 
     | 
    
         
             
                'reformat_column_edges_from_resqml_format', 'same_property_kind', 'selective_version_of_collection',
         
     | 
| 
       9 
9 
     | 
    
         
             
                'supported_local_property_kind_list', 'supported_property_kind_list', 'supported_facet_type_list',
         
     | 
| 
       10 
10 
     | 
    
         
             
                'expected_facet_type_dict', 'create_transmisibility_multiplier_property_kind',
         
     | 
| 
       11 
     | 
    
         
            -
                'property_kind_and_facet_from_keyword', 'guess_uom', 'property_parts', 'property_part', 'make_aps_key'
         
     | 
| 
      
 11 
     | 
    
         
            +
                'property_kind_and_facet_from_keyword', 'guess_uom', 'property_parts', 'property_part', 'make_aps_key',
         
     | 
| 
      
 12 
     | 
    
         
            +
                'establish_zone_property_kind'
         
     | 
| 
       12 
13 
     | 
    
         
             
            ]
         
     | 
| 
       13 
14 
     | 
    
         | 
| 
       14 
15 
     | 
    
         
             
            from .property_common import property_collection_for_keyword,  \
         
     | 
| 
         @@ -27,7 +28,7 @@ from .property_common import property_collection_for_keyword,  \ 
     | 
|
| 
       27 
28 
     | 
    
         
             
                guess_uom,  \
         
     | 
| 
       28 
29 
     | 
    
         
             
                property_parts,  \
         
     | 
| 
       29 
30 
     | 
    
         
             
                property_part
         
     | 
| 
       30 
     | 
    
         
            -
            from .property_kind import PropertyKind, create_transmisibility_multiplier_property_kind
         
     | 
| 
      
 31 
     | 
    
         
            +
            from .property_kind import PropertyKind, create_transmisibility_multiplier_property_kind, establish_zone_property_kind
         
     | 
| 
       31 
32 
     | 
    
         
             
            from .string_lookup import StringLookup
         
     | 
| 
       32 
33 
     | 
    
         
             
            from .property_collection import PropertyCollection
         
     | 
| 
       33 
34 
     | 
    
         
             
            from .attribute_property_set import AttributePropertySet, ApsProperty, make_aps_key
         
     | 
| 
         @@ -509,6 +509,8 @@ def _supporting_shape_surface(support, indexable_element): 
     | 
|
| 
       509 
509 
     | 
    
         
             
                    shape_list = [support.triangle_count()]
         
     | 
| 
       510 
510 
     | 
    
         
             
                elif indexable_element == 'nodes':
         
     | 
| 
       511 
511 
     | 
    
         
             
                    shape_list = [support.node_count()]
         
     | 
| 
      
 512 
     | 
    
         
            +
                elif indexable_element == 'patches':
         
     | 
| 
      
 513 
     | 
    
         
            +
                    shape_list = [len(support.patch_list)]
         
     | 
| 
       512 
514 
     | 
    
         
             
                return shape_list
         
     | 
| 
       513 
515 
     | 
    
         | 
| 
       514 
516 
     | 
    
         | 
| 
         @@ -511,8 +511,8 @@ class _GridFromCp: 
     | 
|
| 
       511 
511 
     | 
    
         
             
                            assert len(where_defined) == 3 and len(where_defined[0]) > 0, 'no extant cell geometries'
         
     | 
| 
       512 
512 
     | 
    
         
             
                            sample_kji0 = (where_defined[0][0], where_defined[1][0], where_defined[2][0])
         
     | 
| 
       513 
513 
     | 
    
         
             
                        sample_cp = self.__cp_array[sample_kji0]
         
     | 
| 
       514 
     | 
    
         
            -
                        self.__cell_ijk_lefthanded = 
     | 
| 
       515 
     | 
    
         
            -
             
     | 
| 
      
 514 
     | 
    
         
            +
                        self.__cell_ijk_lefthanded =  \
         
     | 
| 
      
 515 
     | 
    
         
            +
                            (vec.clockwise(sample_cp[0, 0, 0], sample_cp[0, 1, 0], sample_cp[0, 0, 1]) >= 0.0)
         
     | 
| 
       516 
516 
     | 
    
         
             
                        if not self.grid.k_direction_is_down:
         
     | 
| 
       517 
517 
     | 
    
         
             
                            self.__cell_ijk_lefthanded = not self.__cell_ijk_lefthanded
         
     | 
| 
       518 
518 
     | 
    
         
             
                        if self.__crs.is_right_handed_xyz():
         
     |