resqpy 4.14.2__tar.gz → 4.14.4__tar.gz

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.
Files changed (199) hide show
  1. {resqpy-4.14.2 → resqpy-4.14.4}/PKG-INFO +1 -1
  2. {resqpy-4.14.2 → resqpy-4.14.4}/pyproject.toml +1 -1
  3. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/__init__.py +1 -1
  4. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/surface/_surface.py +142 -54
  5. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/time_series/_any_time_series.py +3 -1
  6. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/time_series/_geologic_time_series.py +1 -1
  7. {resqpy-4.14.2 → resqpy-4.14.4}/LICENSE +0 -0
  8. {resqpy-4.14.2 → resqpy-4.14.4}/README.md +0 -0
  9. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/crs.py +0 -0
  10. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/derived_model/__init__.py +0 -0
  11. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/derived_model/_add_edges_per_column_property_array.py +0 -0
  12. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/derived_model/_add_faults.py +0 -0
  13. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/derived_model/_add_one_blocked_well_property.py +0 -0
  14. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/derived_model/_add_one_grid_property_array.py +0 -0
  15. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/derived_model/_add_single_cell_grid.py +0 -0
  16. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/derived_model/_add_wells_from_ascii_file.py +0 -0
  17. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/derived_model/_add_zone_by_layer_property.py +0 -0
  18. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/derived_model/_coarsened_grid.py +0 -0
  19. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/derived_model/_common.py +0 -0
  20. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/derived_model/_copy_grid.py +0 -0
  21. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/derived_model/_drape_to_surface.py +0 -0
  22. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/derived_model/_extract_box.py +0 -0
  23. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/derived_model/_extract_box_for_well.py +0 -0
  24. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/derived_model/_fault_throw_scaling.py +0 -0
  25. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/derived_model/_gather_ensemble.py +0 -0
  26. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/derived_model/_interpolated_grid.py +0 -0
  27. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/derived_model/_local_depth_adjustment.py +0 -0
  28. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/derived_model/_refined_grid.py +0 -0
  29. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/derived_model/_tilted_grid.py +0 -0
  30. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/derived_model/_unsplit_grid.py +0 -0
  31. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/derived_model/_zonal_grid.py +0 -0
  32. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/derived_model/_zone_layer_ranges_from_array.py +0 -0
  33. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/fault/__init__.py +0 -0
  34. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/fault/_gcs_functions.py +0 -0
  35. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/fault/_grid_connection_set.py +0 -0
  36. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid/__init__.py +0 -0
  37. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid/_cell_properties.py +0 -0
  38. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid/_connection_sets.py +0 -0
  39. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid/_create_grid_xml.py +0 -0
  40. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid/_defined_geometry.py +0 -0
  41. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid/_extract_functions.py +0 -0
  42. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid/_face_functions.py +0 -0
  43. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid/_faults.py +0 -0
  44. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid/_grid.py +0 -0
  45. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid/_grid_types.py +0 -0
  46. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid/_intervals_info.py +0 -0
  47. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid/_moved_functions.py +0 -0
  48. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid/_pillars.py +0 -0
  49. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid/_pixel_maps.py +0 -0
  50. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid/_points_functions.py +0 -0
  51. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid/_regular_grid.py +0 -0
  52. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid/_transmissibility.py +0 -0
  53. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid/_write_hdf5_from_caches.py +0 -0
  54. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid/_write_nexus_corp.py +0 -0
  55. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid/_xyz.py +0 -0
  56. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid_surface/__init__.py +0 -0
  57. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid_surface/_blocked_well_populate.py +0 -0
  58. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid_surface/_find_faces.py +0 -0
  59. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid_surface/_grid_skin.py +0 -0
  60. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid_surface/_grid_surface.py +0 -0
  61. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid_surface/_trajectory_intersects.py +0 -0
  62. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/grid_surface/grid_surface_cuda.py +0 -0
  63. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/lines/__init__.py +0 -0
  64. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/lines/_common.py +0 -0
  65. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/lines/_polyline.py +0 -0
  66. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/lines/_polyline_set.py +0 -0
  67. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/model/__init__.py +0 -0
  68. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/model/_catalogue.py +0 -0
  69. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/model/_context.py +0 -0
  70. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/model/_forestry.py +0 -0
  71. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/model/_grids.py +0 -0
  72. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/model/_hdf5.py +0 -0
  73. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/model/_model.py +0 -0
  74. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/model/_xml.py +0 -0
  75. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/multi_processing/__init__.py +0 -0
  76. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/multi_processing/_multiprocessing.py +0 -0
  77. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/multi_processing/wrappers/__init__.py +0 -0
  78. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/multi_processing/wrappers/blocked_well_mp.py +0 -0
  79. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/multi_processing/wrappers/grid_surface_mp.py +0 -0
  80. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/multi_processing/wrappers/mesh_mp.py +0 -0
  81. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/__init__.py +0 -0
  82. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/ab_toolbox.py +0 -0
  83. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/base.py +0 -0
  84. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/box_utilities.py +0 -0
  85. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/class_dict.py +0 -0
  86. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/consolidation.py +0 -0
  87. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/data/build.py +0 -0
  88. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/data/properties.json +0 -0
  89. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/dataframe.py +0 -0
  90. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/exceptions.py +0 -0
  91. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/factors.py +0 -0
  92. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/fine_coarse.py +0 -0
  93. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/grid_functions.py +0 -0
  94. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/intersection.py +0 -0
  95. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/keyword_files.py +0 -0
  96. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/load_data.py +0 -0
  97. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/point_inclusion.py +0 -0
  98. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/random_seed.py +0 -0
  99. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/read_nexus_fault.py +0 -0
  100. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/relperm.py +0 -0
  101. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/simple_lines.py +0 -0
  102. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/time.py +0 -0
  103. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/trademark.py +0 -0
  104. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/transmission.py +0 -0
  105. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/triangulation.py +0 -0
  106. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/uuid.py +0 -0
  107. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/vdb.py +0 -0
  108. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/vector_utilities.py +0 -0
  109. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/volume.py +0 -0
  110. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/wellspec_keywords.py +0 -0
  111. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/write_data.py +0 -0
  112. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/write_hdf5.py +0 -0
  113. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/xml_et.py +0 -0
  114. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/xml_namespaces.py +0 -0
  115. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/olio/zmap_reader.py +0 -0
  116. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/organize/__init__.py +0 -0
  117. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/organize/_utils.py +0 -0
  118. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/organize/boundary_feature.py +0 -0
  119. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/organize/boundary_feature_interpretation.py +0 -0
  120. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/organize/earth_model_interpretation.py +0 -0
  121. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/organize/fault_interpretation.py +0 -0
  122. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/organize/fluid_boundary_feature.py +0 -0
  123. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/organize/frontier_feature.py +0 -0
  124. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/organize/generic_interpretation.py +0 -0
  125. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/organize/genetic_boundary_feature.py +0 -0
  126. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/organize/geobody_boundary_interpretation.py +0 -0
  127. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/organize/geobody_feature.py +0 -0
  128. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/organize/geobody_interpretation.py +0 -0
  129. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/organize/geologic_unit_feature.py +0 -0
  130. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/organize/horizon_interpretation.py +0 -0
  131. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/organize/organization_feature.py +0 -0
  132. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/organize/rock_fluid_unit_feature.py +0 -0
  133. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/organize/structural_organization_interpretation.py +0 -0
  134. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/organize/tectonic_boundary_feature.py +0 -0
  135. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/organize/wellbore_feature.py +0 -0
  136. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/organize/wellbore_interpretation.py +0 -0
  137. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/property/__init__.py +0 -0
  138. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/property/_collection_add_part.py +0 -0
  139. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/property/_collection_create_xml.py +0 -0
  140. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/property/_collection_get_attributes.py +0 -0
  141. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/property/_collection_support.py +0 -0
  142. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/property/_property.py +0 -0
  143. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/property/grid_property_collection.py +0 -0
  144. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/property/property_collection.py +0 -0
  145. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/property/property_common.py +0 -0
  146. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/property/property_kind.py +0 -0
  147. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/property/string_lookup.py +0 -0
  148. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/property/well_interval_property.py +0 -0
  149. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/property/well_interval_property_collection.py +0 -0
  150. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/property/well_log.py +0 -0
  151. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/property/well_log_collection.py +0 -0
  152. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/rq_import/__init__.py +0 -0
  153. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/rq_import/_add_ab_properties.py +0 -0
  154. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/rq_import/_add_surfaces.py +0 -0
  155. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/rq_import/_grid_from_cp.py +0 -0
  156. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/rq_import/_import_nexus.py +0 -0
  157. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/rq_import/_import_vdb_all_grids.py +0 -0
  158. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/rq_import/_import_vdb_ensemble.py +0 -0
  159. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/strata/__init__.py +0 -0
  160. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/strata/_binary_contact_interpretation.py +0 -0
  161. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/strata/_geologic_unit_interpretation.py +0 -0
  162. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/strata/_strata_common.py +0 -0
  163. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/strata/_stratigraphic_column.py +0 -0
  164. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/strata/_stratigraphic_column_rank.py +0 -0
  165. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/strata/_stratigraphic_unit_feature.py +0 -0
  166. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/strata/_stratigraphic_unit_interpretation.py +0 -0
  167. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/surface/__init__.py +0 -0
  168. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/surface/_base_surface.py +0 -0
  169. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/surface/_combined_surface.py +0 -0
  170. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/surface/_mesh.py +0 -0
  171. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/surface/_pointset.py +0 -0
  172. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/surface/_tri_mesh.py +0 -0
  173. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/surface/_tri_mesh_stencil.py +0 -0
  174. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/surface/_triangulated_patch.py +0 -0
  175. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/time_series/__init__.py +0 -0
  176. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/time_series/_from_nexus_summary.py +0 -0
  177. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/time_series/_functions.py +0 -0
  178. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/time_series/_time_duration.py +0 -0
  179. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/time_series/_time_series.py +0 -0
  180. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/unstructured/__init__.py +0 -0
  181. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/unstructured/_hexa_grid.py +0 -0
  182. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/unstructured/_prism_grid.py +0 -0
  183. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/unstructured/_pyramid_grid.py +0 -0
  184. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/unstructured/_tetra_grid.py +0 -0
  185. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/unstructured/_unstructured_grid.py +0 -0
  186. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/weights_and_measures/__init__.py +0 -0
  187. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/weights_and_measures/nexus_units.py +0 -0
  188. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/weights_and_measures/weights_and_measures.py +0 -0
  189. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/well/__init__.py +0 -0
  190. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/well/_blocked_well.py +0 -0
  191. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/well/_deviation_survey.py +0 -0
  192. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/well/_md_datum.py +0 -0
  193. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/well/_trajectory.py +0 -0
  194. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/well/_wellbore_frame.py +0 -0
  195. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/well/_wellbore_marker.py +0 -0
  196. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/well/_wellbore_marker_frame.py +0 -0
  197. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/well/blocked_well_frame.py +0 -0
  198. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/well/well_object_funcs.py +0 -0
  199. {resqpy-4.14.2 → resqpy-4.14.4}/resqpy/well/well_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: resqpy
3
- Version: 4.14.2
3
+ Version: 4.14.4
4
4
  Summary: Python API for working with RESQML models
5
5
  Home-page: https://github.com/bp/resqpy
6
6
  License: MIT
@@ -9,7 +9,7 @@ build-backend = "poetry.masonry.api"
9
9
 
10
10
  [tool.poetry]
11
11
  name = "resqpy"
12
- version = "4.14.2" # Set at build time
12
+ version = "4.14.4" # Set at build time
13
13
  description = "Python API for working with RESQML models"
14
14
  authors = ["BP"]
15
15
  license = "MIT"
@@ -28,6 +28,6 @@
28
28
 
29
29
  import logging
30
30
 
31
- __version__ = "4.14.2" # Set at build time
31
+ __version__ = "4.14.4" # Set at build time
32
32
  log = logging.getLogger(__name__)
33
33
  log.info(f"Imported resqpy version {__version__}")
@@ -272,48 +272,86 @@ class Surface(rqsb.BaseSurface):
272
272
 
273
273
  self.model = parent_model
274
274
 
275
- def triangles_and_points(self):
276
- """Returns arrays representing combination of all the patches in the surface.
275
+ def number_of_patches(self):
276
+ """Returns the number of patches present in the surface."""
277
+
278
+ self.extract_patches(self.root)
279
+ return len(self.patch_list)
280
+
281
+ def triangles_and_points(self, patch = None):
282
+ """Returns arrays representing one patch or a combination of all the patches in the surface.
283
+
284
+ arguments:
285
+ patch (int, optional): patch index; if None, combined arrays for all patches are returned
277
286
 
278
287
  returns:
279
288
  tuple (triangles, points):
280
289
  triangles (int array of shape[:, 3]): integer indices into points array,
281
- being the nodes of the corners of the triangles;
290
+ being the nodes of the corners of the triangles;
282
291
  points (float array of shape[:, 3]): flat array of xyz points, indexed by triangles
283
292
 
284
293
  :meta common:
285
294
  """
286
295
 
287
- if self.triangles is not None:
288
- return (self.triangles, self.points)
289
296
  self.extract_patches(self.root)
290
- points_offset = 0
291
- for triangulated_patch in self.patch_list:
292
- (t, p) = triangulated_patch.triangles_and_points()
293
- if points_offset == 0:
294
- self.triangles = t.copy()
295
- self.points = p.copy()
296
- else:
297
- self.triangles = np.concatenate((self.triangles, t.copy() + points_offset))
298
- self.points = np.concatenate((self.points, p.copy()))
299
- points_offset += p.shape[0]
300
- return (self.triangles, self.points)
297
+ if patch is None:
298
+ if self.triangles is None:
299
+ points_offset = 0
300
+ for triangulated_patch in self.patch_list:
301
+ (t, p) = triangulated_patch.triangles_and_points()
302
+ if points_offset == 0:
303
+ self.triangles = t.copy()
304
+ self.points = p.copy()
305
+ else:
306
+ self.triangles = np.concatenate((self.triangles, t.copy() + points_offset))
307
+ self.points = np.concatenate((self.points, p.copy()))
308
+ points_offset += p.shape[0]
309
+ return (self.triangles, self.points)
310
+ assert 0 <= patch < len(self.patch_list), \
311
+ ValueError(f'patch index {patch} out of range for surface with {len(self.patch_list)} patches')
312
+ return self.patch_list[patch].triangles_and_points()
313
+
314
+ def triangle_count(self, patch = None):
315
+ """Return the numner of triangles in this surface, or in one patch.
301
316
 
302
- def triangle_count(self):
303
- """Return the numner of triangles in this surface."""
317
+ arguments:
318
+ patch (int, optional): patch index; if None, a combined triangle count for all patches is returned
319
+
320
+ returns:
321
+ int being the number of trianges in the patch (if specified) or in all the patches
322
+ """
304
323
 
305
324
  self.extract_patches(self.root)
306
- if not self.patch_list:
307
- return 0
308
- return np.sum([tp.triangle_count for tp in self.patch_list])
325
+ if patch is None:
326
+ if not self.patch_list:
327
+ return 0
328
+ return np.sum([tp.triangle_count for tp in self.patch_list])
329
+ assert 0 <= patch < len(self.patch_list), \
330
+ ValueError(f'patch index {patch} out of range for surface with {len(self.patch_list)} patches in triangle_count')
331
+ return self.patch_list[patch].triangle_count
332
+
333
+ def node_count(self, patch = None):
334
+ """Return the number of nodes (points) used in this surface, or in one patch.
335
+
336
+ arguments:
337
+ patch (int, optional): patch index; if None, a combined node count for all patches is returned
309
338
 
310
- def node_count(self):
311
- """Return the number of nodes (points) used in this surface."""
339
+ returns:
340
+ int being the number of nodes in the patch (if specified) or in all the patches
341
+
342
+ note:
343
+ a multi patch surface might have more than one node colocated; this method will treat such coincident nodes
344
+ as separate nodes
345
+ """
312
346
 
313
347
  self.extract_patches(self.root)
314
- if not self.patch_list:
315
- return 0
316
- return np.sum([tp.node_count for tp in self.patch_list])
348
+ if patch is None:
349
+ if not self.patch_list:
350
+ return 0
351
+ return np.sum([tp.node_count for tp in self.patch_list])
352
+ assert 0 <= patch < len(self.patch_list), \
353
+ ValueError(f'patch index {patch} out of range for surface with {len(self.patch_list)} patches in node_count')
354
+ return self.patch_list[patch].node_count
317
355
 
318
356
  def change_crs(self, required_crs):
319
357
  """Changes the crs of the surface, also sets a new uuid if crs changed.
@@ -381,7 +419,7 @@ class Surface(rqsb.BaseSurface):
381
419
  self.uuid = bu.new_uuid()
382
420
 
383
421
  def set_to_split_surface(self, large_surface, line, delta_xyz):
384
- """Populate this (empty) surface with a version of a larger surface split by an xy line.
422
+ """Populate this (empty) surface with a version of a larger surface split by a straight xy line.
385
423
 
386
424
  arguments:
387
425
  large_surface (Surface): the larger surface, a copy of which is to be split
@@ -404,8 +442,8 @@ class Surface(rqsb.BaseSurface):
404
442
  tp[:, 1] = len(p) + 1
405
443
  tp[:, 2] = np.arange(len(p), dtype = int)
406
444
  cw = vec.clockwise_triangles(pp, tp)
407
- pai = np.where(cw >= 0.0, True, False) # bool mask over p
408
- pbi = np.where(cw <= 0.0, True, False) # bool mask over p
445
+ pai = (cw >= 0.0) # bool mask over p
446
+ pbi = (cw <= 0.0) # bool mask over p
409
447
  tap = pai[t]
410
448
  tbp = pbi[t]
411
449
  ta = np.any(tap, axis = 1) # bool array over t
@@ -435,17 +473,24 @@ class Surface(rqsb.BaseSurface):
435
473
 
436
474
  self.set_from_triangles_and_points(t_combo, p_combo)
437
475
 
438
- def distinct_edges(self):
439
- """Returns a numpy int array of shape (N, 2) being the ordered node pairs of distinct edges of triangles."""
476
+ def distinct_edges(self, patch = None):
477
+ """Returns a numpy int array of shape (N, 2) being the ordered node pairs of distinct edges of triangles.
440
478
 
441
- triangles, _ = self.triangles_and_points()
479
+ arguments:
480
+ patch (int, optional): patch index; if None, a combination of edges for all patches is returned
481
+ """
482
+
483
+ triangles, _ = self.triangles_and_points(patch = patch)
442
484
  assert triangles is not None
443
485
  unique_edges, _ = triangulate.edges(triangles)
444
486
  return unique_edges
445
487
 
446
- def distinct_edges_and_counts(self):
488
+ def distinct_edges_and_counts(self, patch = None):
447
489
  """Returns unique edges as pairs of point indices, and a count of uses of each edge.
448
490
 
491
+ arguments:
492
+ patch (int, optional): patch index; if None, combined results for all patches are returned
493
+
449
494
  returns:
450
495
  numpy int array of shape (N, 2), numpy int array of shape (N,)
451
496
  where 2D array is list-like sorted points index pairs for unique edges
@@ -453,14 +498,39 @@ class Surface(rqsb.BaseSurface):
453
498
 
454
499
  notes:
455
500
  first entry in each pair is always the lower of the two point indices;
456
- for well formed surfaces, the count should everywhere be zero or one;
501
+ for well formed surfaces, the count should everywhere be one or two;
457
502
  the function does not attempt to detect coincident points
458
503
  """
459
504
 
460
- triangles, _ = self.triangles_and_points()
505
+ triangles, _ = self.triangles_and_points(patch = patch)
461
506
  assert triangles is not None
462
507
  return triangulate.edges(triangles)
463
508
 
509
+ def edge_lengths(self, required_uom = None, patch = None):
510
+ """Returns float array of shape (N, 3) being triangle edge lengths.
511
+
512
+ arguments:
513
+ required_uom (str, optional): the required length uom for the resulting edge lengths; default is crs xy units
514
+ patch (int, optional): patch index; if None, edge lengths for all patches are returned
515
+
516
+ returns:
517
+ numpy float array of shape (N, 3) where N is the number of triangles
518
+ """
519
+
520
+ t, p = self.triangles_and_points(patch = patch)
521
+ crs = rqc.Crs(self.model, uuid = self.crs_uuid)
522
+ if required_uom is None:
523
+ required_uom = crs.xy_units
524
+ if crs.xy_units != required_uom or crs.z_units != required_uom:
525
+ p = p.copy()
526
+ wam.convert_lengths(p[:, :2], crs.xy_units, required_uom)
527
+ wam.convert_lengths(p[:, 2], crs.z_units, required_uom)
528
+ t_end = np.empty_like(t)
529
+ t_end[:, :2] = t[:, 1:]
530
+ t_end[:, 2] = t[:, 0]
531
+ edge_v = p[t_end, :] - p[t, :]
532
+ return vec.naive_lengths(edge_v)
533
+
464
534
  def set_from_triangles_and_points(self, triangles, points):
465
535
  """Populate this (empty) Surface object from an array of triangle corner indices and an array of points."""
466
536
 
@@ -468,6 +538,22 @@ class Surface(rqsb.BaseSurface):
468
538
  tri_patch.set_from_triangles_and_points(triangles, points)
469
539
  self.patch_list = [tri_patch]
470
540
  self.uuid = bu.new_uuid()
541
+ self.triangles = triangles.copy()
542
+ self.points = points.copy()
543
+
544
+ def set_multi_patch_from_triangles_and_points(self, triangles_and_points_list):
545
+ """Populate this (empty) Surface object from a list of paits: array of triangle corner indices, array of points."""
546
+
547
+ self.patch_list = []
548
+ self.trianges = None
549
+ self.points = None
550
+ for patch, entry in enumerate(triangles_and_points_list):
551
+ assert len(entry) == 2, 'expecting pair of arrays (triangles, points) for each patch'
552
+ triangles, points = entry
553
+ tri_patch = rqstp.TriangulatedPatch(self.model, patch_index = patch, crs_uuid = self.crs_uuid)
554
+ tri_patch.set_from_triangles_and_points(triangles, points)
555
+ self.patch_list.append(tri_patch)
556
+ self.uuid = bu.new_uuid()
471
557
 
472
558
  def set_from_point_set(self,
473
559
  point_set,
@@ -901,10 +987,10 @@ class Surface(rqsb.BaseSurface):
901
987
  for patch in self.patch_list:
902
988
  patch.vertical_rescale_points(ref_depth, scaling_factor)
903
989
 
904
- def line_intersection(self, line_p, line_v, line_segment = False):
990
+ def line_intersection(self, line_p, line_v, line_segment = False, patch = None):
905
991
  """Returns x,y,z of an intersection point of straight line with the surface, or None if no intersection found."""
906
992
 
907
- t, p = self.triangles_and_points()
993
+ t, p = self.triangles_and_points(patch = patch)
908
994
  tp = p[t]
909
995
  intersects = meet.line_triangles_intersects(line_p, line_v, tp, line_segment = line_segment)
910
996
  indices = meet.intersects_indices(intersects)
@@ -912,21 +998,22 @@ class Surface(rqsb.BaseSurface):
912
998
  return None
913
999
  return intersects[indices[0]]
914
1000
 
915
- def sample_z_at_xy_points(self, points, multiple_handling = 'any'):
1001
+ def sample_z_at_xy_points(self, points, multiple_handling = 'any', patch = None):
916
1002
  """Returns interpolated z values for an array of xy values.
917
1003
 
918
1004
  arguments:
919
1005
  points (numpy float array of shape (..., 2 or 3)): xy points to sample surface at (z values ignored)
920
1006
  multiple_handling (str, default 'any'): one of 'any', 'minimum', 'maximum', 'exception'
1007
+ patch (int, optional): patch index; if None, results are for the full surface
921
1008
 
922
1009
  returns:
923
1010
  numpy float array of shape points.shape[:-1] being z values interpolated from the surface z values
924
1011
 
925
1012
  notes:
926
1013
  points must be in the same crs as the surface;
927
- NaN will be set for any points that do not intersect with the surface in the xy projection;
928
- multiple_handling argument controls behaviour when one sample point intersects surface more than
929
- once: 'any' a random one of the intersection z values is returned; 'minimum' or 'maximum': the
1014
+ NaN will be set for any points that do not intersect with the patch or surface in the xy projection;
1015
+ multiple_handling argument controls behaviour when one sample point intersects more than once:
1016
+ 'any' a random one of the intersection z values is returned; 'minimum' or 'maximum': the
930
1017
  numerical min or max of the z values is returned; 'exception': a ValueError is raised
931
1018
  """
932
1019
 
@@ -938,7 +1025,7 @@ class Surface(rqsb.BaseSurface):
938
1025
  else:
939
1026
  sample_xy = np.zeros((points.size // 2, 3), dtype = float)
940
1027
  sample_xy[:, :2] = points.reshape((-1, 2))
941
- t, p = self.triangles_and_points()
1028
+ t, p = self.triangles_and_points(patch = patch)
942
1029
  p_list = vec.points_in_triangles_njit(sample_xy, p[t], 1)
943
1030
  vertical = np.array((0.0, 0.0, 1.0), dtype = float)
944
1031
  z = np.full(sample_xy.shape[0], np.NaN, dtype = float)
@@ -957,17 +1044,18 @@ class Surface(rqsb.BaseSurface):
957
1044
  raise ValueError(f'multiple {self.title} surface intersections at xy: {sample_xy[p_index]}')
958
1045
  return z.reshape(points.shape[:-1])
959
1046
 
960
- def normal_vectors(self, add_as_property: bool = False) -> np.ndarray:
961
- """Returns the normal vectors for each triangle in the surface.
962
-
1047
+ def normal_vectors(self, add_as_property: bool = False, patch = None) -> np.ndarray:
1048
+ """Returns the normal vectors for each triangle in the patch or surface.
1049
+
963
1050
  arguments:
964
- add_as_property (bool): if True, face_surface_normal_vectors_array is added as a property to the model.
1051
+ add_as_property (bool): if True, face_surface_normal_vectors_array is added as a property to the model
1052
+ patch (int, optional): patch index; if None, normal vectors for triangles in all patches are returned
965
1053
 
966
1054
  returns:
967
- normal_vectors_array (np.ndarray): the normal vectors corresponding to each triangle in the surface.
1055
+ normal_vectors_array (np.ndarray): the normal vectors corresponding to each triangle in the surface
968
1056
  """
969
1057
  crs = rqc.Crs(self.model, uuid = self.crs_uuid)
970
- triangles, points = self.triangles_and_points()
1058
+ triangles, points = self.triangles_and_points(patch = patch)
971
1059
  if crs.xy_units != crs.z_units:
972
1060
  points = points.copy()
973
1061
  wam.convert_lengths(points[:, 2], crs.z_units, crs.xy_units)
@@ -1027,13 +1115,13 @@ class Surface(rqsb.BaseSurface):
1027
1115
  return ep
1028
1116
 
1029
1117
  def resampled_surface(self, title = None):
1030
- """Creates a new triangulated set which is a resampled version of the current triangulated set. Each existing triangle in the tset is divided equally into 4 new triangles.
1031
-
1118
+ """Creates a new surface which is a refined version of this surface; each triangle is divided equally into 4 new triangles.
1119
+
1032
1120
  arguments:
1033
- title (str): a new title for the output triangulated set, if None the title will have the same title as the input triangulated set
1034
-
1121
+ title (str): title for the output triangulated set, if None the title will be inherited from the input surface
1122
+
1035
1123
  returns:
1036
- resqpy.surface.Surface object, with extra_metadata ('resampled from surface': <uuid>), where uuid is the origin surface uuid
1124
+ resqpy.surface.Surface object, with extra_metadata ('resampled from surface': uuid), where uuid is for the original surface uuid
1037
1125
  """
1038
1126
  rt, rp = self.triangles_and_points()
1039
1127
  edge1 = np.mean(rp[rt[:]][:, ::2, :], axis = 1)
@@ -1051,7 +1139,7 @@ class Surface(rqsb.BaseSurface):
1051
1139
  # TODO: implement alternate solution using edge functions in olio triangulation to optimise
1052
1140
  points_unique, inverse = np.unique(allpoints, axis = 0, return_inverse = True)
1053
1141
  tris = np.array(tris)
1054
- tris_unique = np.empty(shape = tris.shape)
1142
+ tris_unique = np.empty(shape = tris.shape, dtype = int)
1055
1143
  tris_unique[:, 0] = inverse[tris[:, 0]]
1056
1144
  tris_unique[:, 1] = inverse[tris[:, 1]]
1057
1145
  tris_unique[:, 2] = inverse[tris[:, 2]]
@@ -34,8 +34,10 @@ class AnyTimeSeries(BaseResqpy):
34
34
  dt_text = rqet.find_tag_text(child, 'DateTime')
35
35
  assert dt_text, 'missing DateTime field in xml for time series'
36
36
  year_offset = rqet.find_tag_int(child, 'YearOffset')
37
- if year_offset:
37
+ if year_offset is not None:
38
38
  assert self.timeframe == 'geologic'
39
+ if year_offset > 0:
40
+ log.warning(f'positive year offset in xml indicates future geological time: {year_offset}')
39
41
  self.timestamps.append(year_offset) # todo: trim and check timestamp
40
42
  else:
41
43
  assert self.timeframe == 'human'
@@ -29,7 +29,7 @@ class GeologicTimeSeries(ats.AnyTimeSeries):
29
29
 
30
30
  note:
31
31
  if instantiating from an existing RESQML time series, its Time entries must all have YearOffset data
32
- which should be large negative integers
32
+ which should be large negative integers (or zero if reaching the current era)
33
33
 
34
34
  :meta common:
35
35
  """
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes