resqpy 4.16.1__tar.gz → 4.16.3__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 (200) hide show
  1. {resqpy-4.16.1 → resqpy-4.16.3}/PKG-INFO +1 -1
  2. {resqpy-4.16.1 → resqpy-4.16.3}/pyproject.toml +1 -1
  3. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/__init__.py +1 -1
  4. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/model/_catalogue.py +9 -0
  5. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/model/_forestry.py +6 -8
  6. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/model/_model.py +60 -0
  7. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/model/_xml.py +38 -13
  8. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/xml_et.py +12 -0
  9. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/_collection_add_part.py +4 -1
  10. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/attribute_property_set.py +41 -3
  11. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/property_collection.py +9 -3
  12. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/well/_blocked_well.py +82 -52
  13. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/well/_trajectory.py +5 -0
  14. {resqpy-4.16.1 → resqpy-4.16.3}/LICENSE +0 -0
  15. {resqpy-4.16.1 → resqpy-4.16.3}/README.md +0 -0
  16. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/crs.py +0 -0
  17. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/__init__.py +0 -0
  18. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_add_edges_per_column_property_array.py +0 -0
  19. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_add_faults.py +0 -0
  20. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_add_one_blocked_well_property.py +0 -0
  21. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_add_one_grid_property_array.py +0 -0
  22. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_add_single_cell_grid.py +0 -0
  23. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_add_wells_from_ascii_file.py +0 -0
  24. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_add_zone_by_layer_property.py +0 -0
  25. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_coarsened_grid.py +0 -0
  26. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_common.py +0 -0
  27. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_copy_grid.py +0 -0
  28. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_drape_to_surface.py +0 -0
  29. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_extract_box.py +0 -0
  30. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_extract_box_for_well.py +0 -0
  31. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_fault_throw_scaling.py +0 -0
  32. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_gather_ensemble.py +0 -0
  33. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_interpolated_grid.py +0 -0
  34. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_local_depth_adjustment.py +0 -0
  35. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_refined_grid.py +0 -0
  36. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_tilted_grid.py +0 -0
  37. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_unsplit_grid.py +0 -0
  38. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_zonal_grid.py +0 -0
  39. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_zone_layer_ranges_from_array.py +0 -0
  40. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/fault/__init__.py +0 -0
  41. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/fault/_gcs_functions.py +0 -0
  42. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/fault/_grid_connection_set.py +0 -0
  43. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/__init__.py +0 -0
  44. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_cell_properties.py +0 -0
  45. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_connection_sets.py +0 -0
  46. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_create_grid_xml.py +0 -0
  47. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_defined_geometry.py +0 -0
  48. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_extract_functions.py +0 -0
  49. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_face_functions.py +0 -0
  50. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_faults.py +0 -0
  51. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_grid.py +0 -0
  52. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_grid_types.py +0 -0
  53. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_intervals_info.py +0 -0
  54. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_moved_functions.py +0 -0
  55. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_pillars.py +0 -0
  56. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_pixel_maps.py +0 -0
  57. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_points_functions.py +0 -0
  58. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_regular_grid.py +0 -0
  59. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_transmissibility.py +0 -0
  60. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_write_hdf5_from_caches.py +0 -0
  61. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_write_nexus_corp.py +0 -0
  62. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_xyz.py +0 -0
  63. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid_surface/__init__.py +0 -0
  64. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid_surface/_blocked_well_populate.py +0 -0
  65. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid_surface/_find_faces.py +0 -0
  66. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid_surface/_grid_skin.py +0 -0
  67. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid_surface/_grid_surface.py +0 -0
  68. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid_surface/_trajectory_intersects.py +0 -0
  69. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid_surface/grid_surface_cuda.py +0 -0
  70. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/lines/__init__.py +0 -0
  71. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/lines/_common.py +0 -0
  72. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/lines/_polyline.py +0 -0
  73. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/lines/_polyline_set.py +0 -0
  74. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/model/__init__.py +0 -0
  75. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/model/_context.py +0 -0
  76. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/model/_grids.py +0 -0
  77. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/model/_hdf5.py +0 -0
  78. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/multi_processing/__init__.py +0 -0
  79. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/multi_processing/_multiprocessing.py +0 -0
  80. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/multi_processing/wrappers/__init__.py +0 -0
  81. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/multi_processing/wrappers/blocked_well_mp.py +0 -0
  82. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/multi_processing/wrappers/grid_surface_mp.py +0 -0
  83. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/multi_processing/wrappers/mesh_mp.py +0 -0
  84. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/__init__.py +0 -0
  85. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/ab_toolbox.py +0 -0
  86. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/base.py +0 -0
  87. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/box_utilities.py +0 -0
  88. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/class_dict.py +0 -0
  89. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/consolidation.py +0 -0
  90. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/data/build.py +0 -0
  91. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/data/properties.json +0 -0
  92. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/dataframe.py +0 -0
  93. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/exceptions.py +0 -0
  94. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/factors.py +0 -0
  95. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/fine_coarse.py +0 -0
  96. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/grid_functions.py +0 -0
  97. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/intersection.py +0 -0
  98. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/keyword_files.py +0 -0
  99. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/load_data.py +0 -0
  100. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/point_inclusion.py +0 -0
  101. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/random_seed.py +0 -0
  102. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/read_nexus_fault.py +0 -0
  103. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/relperm.py +0 -0
  104. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/simple_lines.py +0 -0
  105. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/time.py +0 -0
  106. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/trademark.py +0 -0
  107. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/transmission.py +0 -0
  108. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/triangulation.py +0 -0
  109. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/uuid.py +0 -0
  110. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/vdb.py +0 -0
  111. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/vector_utilities.py +0 -0
  112. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/volume.py +0 -0
  113. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/wellspec_keywords.py +0 -0
  114. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/write_data.py +0 -0
  115. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/write_hdf5.py +0 -0
  116. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/xml_namespaces.py +0 -0
  117. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/zmap_reader.py +0 -0
  118. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/__init__.py +0 -0
  119. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/_utils.py +0 -0
  120. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/boundary_feature.py +0 -0
  121. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/boundary_feature_interpretation.py +0 -0
  122. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/earth_model_interpretation.py +0 -0
  123. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/fault_interpretation.py +0 -0
  124. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/fluid_boundary_feature.py +0 -0
  125. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/frontier_feature.py +0 -0
  126. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/generic_interpretation.py +0 -0
  127. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/genetic_boundary_feature.py +0 -0
  128. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/geobody_boundary_interpretation.py +0 -0
  129. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/geobody_feature.py +0 -0
  130. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/geobody_interpretation.py +0 -0
  131. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/geologic_unit_feature.py +0 -0
  132. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/horizon_interpretation.py +0 -0
  133. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/organization_feature.py +0 -0
  134. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/rock_fluid_unit_feature.py +0 -0
  135. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/structural_organization_interpretation.py +0 -0
  136. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/tectonic_boundary_feature.py +0 -0
  137. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/wellbore_feature.py +0 -0
  138. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/wellbore_interpretation.py +0 -0
  139. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/__init__.py +0 -0
  140. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/_collection_create_xml.py +0 -0
  141. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/_collection_get_attributes.py +0 -0
  142. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/_collection_support.py +0 -0
  143. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/_property.py +0 -0
  144. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/grid_property_collection.py +0 -0
  145. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/property_common.py +0 -0
  146. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/property_kind.py +0 -0
  147. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/string_lookup.py +0 -0
  148. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/well_interval_property.py +0 -0
  149. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/well_interval_property_collection.py +0 -0
  150. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/well_log.py +0 -0
  151. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/well_log_collection.py +0 -0
  152. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/rq_import/__init__.py +0 -0
  153. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/rq_import/_add_ab_properties.py +0 -0
  154. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/rq_import/_add_surfaces.py +0 -0
  155. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/rq_import/_grid_from_cp.py +0 -0
  156. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/rq_import/_import_nexus.py +0 -0
  157. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/rq_import/_import_vdb_all_grids.py +0 -0
  158. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/rq_import/_import_vdb_ensemble.py +0 -0
  159. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/strata/__init__.py +0 -0
  160. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/strata/_binary_contact_interpretation.py +0 -0
  161. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/strata/_geologic_unit_interpretation.py +0 -0
  162. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/strata/_strata_common.py +0 -0
  163. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/strata/_stratigraphic_column.py +0 -0
  164. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/strata/_stratigraphic_column_rank.py +0 -0
  165. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/strata/_stratigraphic_unit_feature.py +0 -0
  166. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/strata/_stratigraphic_unit_interpretation.py +0 -0
  167. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/surface/__init__.py +0 -0
  168. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/surface/_base_surface.py +0 -0
  169. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/surface/_combined_surface.py +0 -0
  170. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/surface/_mesh.py +0 -0
  171. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/surface/_pointset.py +0 -0
  172. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/surface/_surface.py +0 -0
  173. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/surface/_tri_mesh.py +0 -0
  174. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/surface/_tri_mesh_stencil.py +0 -0
  175. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/surface/_triangulated_patch.py +0 -0
  176. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/time_series/__init__.py +0 -0
  177. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/time_series/_any_time_series.py +0 -0
  178. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/time_series/_from_nexus_summary.py +0 -0
  179. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/time_series/_functions.py +0 -0
  180. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/time_series/_geologic_time_series.py +0 -0
  181. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/time_series/_time_duration.py +0 -0
  182. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/time_series/_time_series.py +0 -0
  183. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/unstructured/__init__.py +0 -0
  184. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/unstructured/_hexa_grid.py +0 -0
  185. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/unstructured/_prism_grid.py +0 -0
  186. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/unstructured/_pyramid_grid.py +0 -0
  187. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/unstructured/_tetra_grid.py +0 -0
  188. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/unstructured/_unstructured_grid.py +0 -0
  189. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/weights_and_measures/__init__.py +0 -0
  190. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/weights_and_measures/nexus_units.py +0 -0
  191. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/weights_and_measures/weights_and_measures.py +0 -0
  192. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/well/__init__.py +0 -0
  193. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/well/_deviation_survey.py +0 -0
  194. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/well/_md_datum.py +0 -0
  195. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/well/_wellbore_frame.py +0 -0
  196. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/well/_wellbore_marker.py +0 -0
  197. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/well/_wellbore_marker_frame.py +0 -0
  198. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/well/blocked_well_frame.py +0 -0
  199. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/well/well_object_funcs.py +0 -0
  200. {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/well/well_utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: resqpy
3
- Version: 4.16.1
3
+ Version: 4.16.3
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.16.1" # Set at build time
12
+ version = "4.16.3" # 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.16.1" # Set at build time
31
+ __version__ = "4.16.3" # Set at build time
32
32
  log = logging.getLogger(__name__)
33
33
  log.info(f"Imported resqpy version {__version__}")
@@ -553,6 +553,15 @@ def _citation_title_for_part(model, part): # duplicate functionality to title_f
553
553
  return title
554
554
 
555
555
 
556
+ def _source_for_part(model, part):
557
+ """Returns the source string from the part's extra metadata, if present, else None."""
558
+
559
+ part_extra = rqet.load_metadata_from_xml(_root_for_part(model, part))
560
+ if not part_extra:
561
+ return None
562
+ return part_extra.get('source')
563
+
564
+
556
565
  def _root_for_time_series(model, uuid = None):
557
566
  """Return root for time series part."""
558
567
 
@@ -200,8 +200,8 @@ def _load_epc(model, epc_file, full_load = True, epc_subdir = None, copy_from =
200
200
  def _add_uuid_soft_relations(model, uuid_int, part):
201
201
  if "EpcExternalPart" in part:
202
202
  return
203
- value = model.rels_forest.get(rqet.rels_part_name_for_part(part))
204
- if value is not None:
203
+ rels_part = rqet.rels_part_name_for_part(part)
204
+ if rels_part in model.rels_forest:
205
205
  rels_root = m_c._root_for_part(model, rqet.rels_part_name_for_part(part), is_rels = True)
206
206
  if rels_root is not None:
207
207
  for relation_node in rels_root:
@@ -214,9 +214,10 @@ def _add_uuid_soft_relations(model, uuid_int, part):
214
214
  if relation_uuid_str is None:
215
215
  return # probably HDF5 external resource
216
216
  relation_uuid_int = _hex_to_int(relation_uuid_str)
217
- value = model.uuid_rels_dict.get(uuid_int)
218
- if value is not None and relation_uuid_int not in value[0] and relation_uuid_int not in value[1]:
219
- value[2].add(relation_uuid_int)
217
+ rels_sets = model.uuid_rels_dict.get(uuid_int)
218
+ if rels_sets is not None and relation_uuid_int not in rels_sets[
219
+ 0] and relation_uuid_int not in rels_sets[1]:
220
+ rels_sets[2].add(relation_uuid_int)
220
221
 
221
222
 
222
223
  def _add_uuid_relations(model, uuid_int, part):
@@ -719,9 +720,6 @@ def _copy_relationships_for_present_targets(model, other_model, consolidate, for
719
720
  continue
720
721
  else:
721
722
  continue
722
- if not force and resident_related_part in m_c._parts_list_filtered_by_related_uuid(
723
- model, m_c._list_of_parts(model), resident_uuid):
724
- continue
725
723
  related_node = m_c._root_for_part(model, resident_related_part)
726
724
  assert related_node is not None
727
725
 
@@ -1108,6 +1108,66 @@ class Model():
1108
1108
 
1109
1109
  return m_c._citation_title_for_part(self, part)
1110
1110
 
1111
+ def source_for_part(self, part):
1112
+ """Returns the source string from the part's extra metadata, if present, else None.
1113
+
1114
+ arguments:
1115
+ part (str): the part for which the source information is required
1116
+
1117
+ returns:
1118
+ str being the text of the source field in the xml extra metadata of the part, or None
1119
+ """
1120
+
1121
+ return m_c._source_for_part(self, part)
1122
+
1123
+ def set_source_for_part(self, part, source):
1124
+ """Sets the source string in the part's extra metadata.
1125
+
1126
+ arguments:
1127
+ part (str): the part for which the source information is to be set
1128
+ source (str): text for the extra metadata source item
1129
+
1130
+ notes:
1131
+ this function adds the source item to the in-memory xml extra metadata;
1132
+ any previous text for the source item (if present) will be replaced;
1133
+ it will be included in the epc if store_epc() is subsequently called
1134
+ """
1135
+
1136
+ m_x._create_source(source, root = m_c._root_for_part(self, part))
1137
+ self.set_modified()
1138
+
1139
+ def source_for_obj(self, obj):
1140
+ """Returns the source string from the object's extra metadata, if present, else None.
1141
+
1142
+ arguments:
1143
+ obj (BaseResqpy): any high level resqpy object (eg. Surface)
1144
+
1145
+ returns:
1146
+ str being the text of the source extra metadata item for the object, or None
1147
+ """
1148
+
1149
+ return m_c._source_for_part(self, obj.part)
1150
+
1151
+ def set_source_for_obj(self, obj, source):
1152
+ """Sets the source string in the object's extra metadata.
1153
+
1154
+ arguments:
1155
+ part (str): the part for which the source information is to be set
1156
+ source (str): text for the extra metadata source item
1157
+
1158
+ notes:
1159
+ this function adds the source item to the in-memory xml extra metadata as well as
1160
+ the object's extra_metadata dictionary
1161
+ any previous text for the source item (if present) will be replaced;
1162
+ it will be included in the epc if store_epc() is subsequently called
1163
+ """
1164
+
1165
+ m_x._create_source(source, root = obj.root)
1166
+ if not hasattr(obj, 'extra_metadata') or obj.extra_metadata is None:
1167
+ obj.extra_metadata = {}
1168
+ obj.extra_metadata['source'] = str(source)
1169
+ self.set_modified()
1170
+
1111
1171
  def root_for_time_series(self, uuid = None):
1112
1172
  """Return root for time series part.
1113
1173
 
@@ -420,22 +420,39 @@ def _create_supporting_representation(model,
420
420
 
421
421
 
422
422
  def _create_source(source, root = None):
423
- """Create an extra meta data node holding information on the source of the data, optionally add to root."""
423
+ """Create an extra meta data node holding information on the source of the data, optionally add to root.
424
424
 
425
- emd_node = rqet.Element(ns['resqml2'] + 'ExtraMetadata')
426
- emd_node.set(ns['xsi'] + 'type', ns['resqml2'] + 'NameValuePair')
427
- emd_node.text = rqet.null_xml_text
425
+ note:
426
+ if the root already contains a 'source' extra metadata item, its text field is updated and the
427
+ existing extra metadata xml node is returned
428
+ """
428
429
 
429
- name_node = rqet.SubElement(emd_node, ns['resqml2'] + 'Name')
430
- name_node.set(ns['xsi'] + 'type', ns['xsd'] + 'string')
431
- name_node.text = 'source'
430
+ emd_node = None
431
+ if root is not None:
432
+ emd_node = rqet.find_metadata_item_node_in_xml(root, 'source')
432
433
 
433
- value_node = rqet.SubElement(emd_node, ns['resqml2'] + 'Value')
434
- value_node.set(ns['xsi'] + 'type', ns['xsd'] + 'string')
435
- value_node.text = source
434
+ if emd_node is None:
436
435
 
437
- if root is not None:
438
- root.append(emd_node)
436
+ emd_node = rqet.Element(ns['resqml2'] + 'ExtraMetadata')
437
+ emd_node.set(ns['xsi'] + 'type', ns['resqml2'] + 'NameValuePair')
438
+ emd_node.text = rqet.null_xml_text
439
+
440
+ name_node = rqet.SubElement(emd_node, ns['resqml2'] + 'Name')
441
+ name_node.set(ns['xsi'] + 'type', ns['xsd'] + 'string')
442
+ name_node.text = 'source'
443
+
444
+ value_node = rqet.SubElement(emd_node, ns['resqml2'] + 'Value')
445
+ value_node.set(ns['xsi'] + 'type', ns['xsd'] + 'string')
446
+ value_node.text = str(source)
447
+
448
+ if root is not None:
449
+ root.append(emd_node)
450
+
451
+ else:
452
+
453
+ value_node = rqet.find_tag(emd_node, 'Value')
454
+ assert value_node is not None
455
+ value_node.text = str(source)
439
456
 
440
457
  return emd_node
441
458
 
@@ -457,7 +474,9 @@ def _create_patch(model,
457
474
  assert ext_uuid is not None
458
475
  else:
459
476
  assert const_count is not None and const_count > 0
460
- if hdf5_type.endswith('Hdf5Array'):
477
+ if isinstance(const_value, bool):
478
+ hdf5_type = 'BooleanConstantArray' # not actually stored in hdf5
479
+ elif hdf5_type.endswith('Hdf5Array'):
461
480
  hdf5_type = hdf5_type[:-9] + 'ConstantArray'
462
481
 
463
482
  lxt = str(xsd_type).lower()
@@ -488,6 +507,7 @@ def _create_patch(model,
488
507
  outer_values_node.text = rqet.null_xml_text
489
508
 
490
509
  if discrete and const_value is None:
510
+
491
511
  if null_value is None:
492
512
  if str(xsd_type).startswith('u'):
493
513
  null_value = 4294967295 # 2^32 - 1, used as default even for 64 bit data!
@@ -507,6 +527,11 @@ def _create_patch(model,
507
527
 
508
528
  else:
509
529
 
530
+ # TODO: handle bool const_value as special case
531
+ if isinstance(const_value, bool):
532
+ const_value = str(const_value).lower()
533
+ xsd_type = 'boolean'
534
+
510
535
  const_value_node = rqet.SubElement(outer_values_node, ns['resqml2'] + 'Value')
511
536
  const_value_node.set(ns['xsi'] + 'type', ns['xsd'] + xsd_type)
512
537
  const_value_node.text = str(const_value)
@@ -778,6 +778,18 @@ def load_metadata_from_xml(node):
778
778
  return extra_metadata
779
779
 
780
780
 
781
+ def find_metadata_item_node_in_xml(node, key):
782
+ """Returns the extra metadata node for a particular key, if present."""
783
+
784
+ if node is None:
785
+ return None
786
+ meta_nodes = list_of_tag(node, 'ExtraMetadata')
787
+ for meta in meta_nodes:
788
+ if find_tag_text(meta, 'Name') == key:
789
+ return meta
790
+ return None
791
+
792
+
781
793
  def create_metadata_xml(node, extra_metadata):
782
794
  """Writes the xml for the given metadata dictionary."""
783
795
 
@@ -202,6 +202,9 @@ def _process_imported_property(collection, attributes, property_kind_uuid, strin
202
202
  const_value, points, p_time_series_uuid, p_string_lookup_uuid) = attributes
203
203
 
204
204
  log.debug('processing imported property ' + str(p_keyword))
205
+ print(
206
+ f'**** keyword: {p_keyword}; const value: {const_value}; type: {type(const_value)}; is bool: {isinstance(const_value, bool)}'
207
+ )
205
208
  assert not points or not p_discrete
206
209
  if local_property_kind_uuid is None:
207
210
  local_property_kind_uuid = property_kind_uuid
@@ -214,7 +217,7 @@ def _process_imported_property(collection, attributes, property_kind_uuid, strin
214
217
  p_keyword, p_discrete, string_lookup_uuid, points)
215
218
 
216
219
  p_array = _process_imported_property_get_p_array(collection, p_cached_name)
217
- p_array_bool = None if p_array is None else p_array.dtype in [bool, np.int8]
220
+ p_array_bool = isinstance(const_value, bool) if p_array is None else p_array.dtype in [bool, np.int8]
218
221
 
219
222
  add_min_max = pcga._process_imported_property_get_add_min_max(points, property_kind, string_lookup_uuid,
220
223
  local_property_kind_uuid, p_array_bool)
@@ -159,6 +159,11 @@ class ApsProperty:
159
159
  """The extra metadata for this property (synonymous with extra)."""
160
160
  return self.extra
161
161
 
162
+ @property
163
+ def source(self):
164
+ """The source extra metadata value for this property (or None)."""
165
+ return self.aps.source_for_part(self.part)
166
+
162
167
  @property
163
168
  def support_uuid(self):
164
169
  """The uuid of the supporting representation for this property."""
@@ -183,7 +188,14 @@ class ApsProperty:
183
188
  class AttributePropertySet(rqp.PropertyCollection):
184
189
  """Class for set of RESQML properties for any supporting representation, using attribute syntax."""
185
190
 
186
- def __init__(self, model = None, support = None, property_set_uuid = None, realization = None, key_mode = 'pk'):
191
+ def __init__(self,
192
+ model = None,
193
+ support = None,
194
+ property_set_uuid = None,
195
+ realization = None,
196
+ key_mode = 'pk',
197
+ indexable = None,
198
+ multiple_handling = 'warn'):
187
199
  """Initialise an empty property set, optionally populate properties from a supporting representation.
188
200
 
189
201
  arguments:
@@ -198,6 +210,11 @@ class AttributePropertySet(rqp.PropertyCollection):
198
210
  if None, then the collection is either covering a whole ensemble (individual properties can each be flagged with a
199
211
  realisation number), or is for properties that do not have multiple realizations
200
212
  key_mode (str, default 'pk'): either 'pk' (for property kind) or 'title', identifying the basis of property attribute keys
213
+ indexable (str, optional): if present and key_mode is 'pk', properties with indexable element other than this will
214
+ have their indexable element included in their key
215
+ multiple_handling (str, default 'warn'): either 'ignore', 'warn' ,or 'exception'; if 'warn' or 'ignore', and properties
216
+ exist that generate the same key, then only the first is visible in the attribute property set (and a warning is given
217
+ for each of the others in the case of 'warn'); if 'exception', a KeyError is raised if there are any duplicate keys
201
218
 
202
219
  note:
203
220
  at present, if the collection is being initialised from a property set, the support argument must also be specified;
@@ -214,9 +231,12 @@ class AttributePropertySet(rqp.PropertyCollection):
214
231
  property_set_root = None
215
232
  else:
216
233
  property_set_root = model.root_for_uuid(property_set_uuid)
234
+ assert multiple_handling in ['ignore', 'warn', 'exception']
217
235
 
218
236
  super().__init__(support = support, property_set_root = property_set_root, realization = realization)
219
237
  self.key_mode = key_mode
238
+ self.indexable_mode = indexable
239
+ self.multiple_handling = multiple_handling
220
240
  self._make_attributes()
221
241
 
222
242
  def keys(self):
@@ -241,12 +261,21 @@ class AttributePropertySet(rqp.PropertyCollection):
241
261
  title = self.citation_title_for_part(part),
242
262
  facet = self.facet_for_part(part),
243
263
  time_index = self.time_index_for_part(part),
244
- realization = self.realization_for_part(part))
264
+ realization = self.realization_for_part(part),
265
+ indexable_mode = self.indexable_mode,
266
+ indexable = self.indexable_for_part(part))
245
267
 
246
268
  def _make_attributes(self):
247
269
  """Setup individual properties with attribute style read access to metadata."""
248
270
  for part in self.parts():
249
271
  key = self._key(part)
272
+ if getattr(self, key, None) is not None:
273
+ if self.multiple_handling == 'warn':
274
+ log.warning(f'duplicate key in AttributePropertySet; only first instance included: {key}')
275
+ continue
276
+ if self.multiple_handling == 'ignore':
277
+ continue
278
+ raise KeyError(f'duplicate key in attribute property set: {key}')
250
279
  aps_property = ApsProperty(self, part)
251
280
  setattr(self, key, aps_property)
252
281
 
@@ -255,11 +284,20 @@ class AttributePropertySet(rqp.PropertyCollection):
255
284
  return self.number_of_parts()
256
285
 
257
286
 
258
- def make_aps_key(key_mode, property_kind = None, title = None, facet = None, time_index = None, realization = None):
287
+ def make_aps_key(key_mode,
288
+ property_kind = None,
289
+ title = None,
290
+ facet = None,
291
+ time_index = None,
292
+ realization = None,
293
+ indexable_mode = None,
294
+ indexable = None):
259
295
  """Contructs the key (attribute name) for a property based on metadata items."""
260
296
  if key_mode == 'pk':
261
297
  assert property_kind is not None
262
298
  key = property_kind
299
+ if indexable_mode is not None and indexable is not None and indexable != indexable_mode:
300
+ key += f'_{indexable}'
263
301
  if facet is not None:
264
302
  key += f'_{facet}'
265
303
  else:
@@ -85,7 +85,7 @@ class PropertyCollection():
85
85
  self.realization = realization # model realization number within an ensemble
86
86
  self.null_value = None
87
87
  self.imported_list = []
88
- # above is list of (uuid, file_name, keyword, cached_name, discrete, uom, time_index, null_value,
88
+ # above is list of (uuid, source, keyword, cached_name, discrete, uom, time_index, null_value,
89
89
  # min_value, max_value, property_kind, facet_type, facet, realization,
90
90
  # indexable_element, count, local_property_kind_uuid, const_value, points,
91
91
  # time_series_uuid, string_lookup_uuid)
@@ -1300,6 +1300,12 @@ class PropertyCollection():
1300
1300
 
1301
1301
  return [self.citation_title_for_part(p) for p in self.parts()]
1302
1302
 
1303
+ def source_for_part(self, part):
1304
+ """Returns the source string from the part's extra metadata, if present, else None."""
1305
+
1306
+ assert self.model is not None
1307
+ return self.model.source_for_part(part)
1308
+
1303
1309
  def time_series_uuid_for_part(self, part):
1304
1310
  """If the property has an associated time series (is not static), returns the uuid for the time series.
1305
1311
 
@@ -2275,7 +2281,7 @@ class PropertyCollection():
2275
2281
  if cached_array is not None:
2276
2282
  min_value, max_value = pcga._min_max_of_cached_array(self, cached_name, cached_array, null_value, discrete)
2277
2283
  else:
2278
- if const_value == null_value or (not discrete and np.isnan(const_value)):
2284
+ if const_value == null_value or isinstance(const_value, bool) or (not discrete and np.isnan(const_value)):
2279
2285
  min_value = max_value = None
2280
2286
  else:
2281
2287
  min_value = max_value = const_value
@@ -2652,7 +2658,7 @@ class PropertyCollection():
2652
2658
  must cycle fastest in the array, ie. be the last index
2653
2659
  points (bool, default False): if True, this is a points property
2654
2660
  extra_metadata (dictionary, optional): if present, adds extra metadata in the xml
2655
- const_value (float or int, optional): if present, create xml for a constant array filled with this value
2661
+ const_value (float, int or bool, optional): if present, create xml for a constant array filled with this value
2656
2662
  expand_const_arrays (boolean, default False): if True, the hdf5 write must also have been called with the
2657
2663
  same argument and the xml will treat a constant array as a normal array
2658
2664