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.
- {resqpy-4.16.1 → resqpy-4.16.3}/PKG-INFO +1 -1
- {resqpy-4.16.1 → resqpy-4.16.3}/pyproject.toml +1 -1
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/__init__.py +1 -1
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/model/_catalogue.py +9 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/model/_forestry.py +6 -8
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/model/_model.py +60 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/model/_xml.py +38 -13
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/xml_et.py +12 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/_collection_add_part.py +4 -1
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/attribute_property_set.py +41 -3
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/property_collection.py +9 -3
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/well/_blocked_well.py +82 -52
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/well/_trajectory.py +5 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/LICENSE +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/README.md +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/crs.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/__init__.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_add_edges_per_column_property_array.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_add_faults.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_add_one_blocked_well_property.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_add_one_grid_property_array.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_add_single_cell_grid.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_add_wells_from_ascii_file.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_add_zone_by_layer_property.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_coarsened_grid.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_common.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_copy_grid.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_drape_to_surface.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_extract_box.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_extract_box_for_well.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_fault_throw_scaling.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_gather_ensemble.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_interpolated_grid.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_local_depth_adjustment.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_refined_grid.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_tilted_grid.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_unsplit_grid.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_zonal_grid.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/derived_model/_zone_layer_ranges_from_array.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/fault/__init__.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/fault/_gcs_functions.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/fault/_grid_connection_set.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/__init__.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_cell_properties.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_connection_sets.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_create_grid_xml.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_defined_geometry.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_extract_functions.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_face_functions.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_faults.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_grid.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_grid_types.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_intervals_info.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_moved_functions.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_pillars.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_pixel_maps.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_points_functions.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_regular_grid.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_transmissibility.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_write_hdf5_from_caches.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_write_nexus_corp.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid/_xyz.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid_surface/__init__.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid_surface/_blocked_well_populate.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid_surface/_find_faces.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid_surface/_grid_skin.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid_surface/_grid_surface.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid_surface/_trajectory_intersects.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/grid_surface/grid_surface_cuda.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/lines/__init__.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/lines/_common.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/lines/_polyline.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/lines/_polyline_set.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/model/__init__.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/model/_context.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/model/_grids.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/model/_hdf5.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/multi_processing/__init__.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/multi_processing/_multiprocessing.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/multi_processing/wrappers/__init__.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/multi_processing/wrappers/blocked_well_mp.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/multi_processing/wrappers/grid_surface_mp.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/multi_processing/wrappers/mesh_mp.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/__init__.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/ab_toolbox.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/base.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/box_utilities.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/class_dict.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/consolidation.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/data/build.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/data/properties.json +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/dataframe.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/exceptions.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/factors.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/fine_coarse.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/grid_functions.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/intersection.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/keyword_files.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/load_data.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/point_inclusion.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/random_seed.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/read_nexus_fault.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/relperm.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/simple_lines.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/time.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/trademark.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/transmission.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/triangulation.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/uuid.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/vdb.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/vector_utilities.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/volume.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/wellspec_keywords.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/write_data.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/write_hdf5.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/xml_namespaces.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/olio/zmap_reader.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/__init__.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/_utils.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/boundary_feature.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/boundary_feature_interpretation.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/earth_model_interpretation.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/fault_interpretation.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/fluid_boundary_feature.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/frontier_feature.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/generic_interpretation.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/genetic_boundary_feature.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/geobody_boundary_interpretation.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/geobody_feature.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/geobody_interpretation.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/geologic_unit_feature.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/horizon_interpretation.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/organization_feature.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/rock_fluid_unit_feature.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/structural_organization_interpretation.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/tectonic_boundary_feature.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/wellbore_feature.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/organize/wellbore_interpretation.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/__init__.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/_collection_create_xml.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/_collection_get_attributes.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/_collection_support.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/_property.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/grid_property_collection.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/property_common.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/property_kind.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/string_lookup.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/well_interval_property.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/well_interval_property_collection.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/well_log.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/property/well_log_collection.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/rq_import/__init__.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/rq_import/_add_ab_properties.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/rq_import/_add_surfaces.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/rq_import/_grid_from_cp.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/rq_import/_import_nexus.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/rq_import/_import_vdb_all_grids.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/rq_import/_import_vdb_ensemble.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/strata/__init__.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/strata/_binary_contact_interpretation.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/strata/_geologic_unit_interpretation.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/strata/_strata_common.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/strata/_stratigraphic_column.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/strata/_stratigraphic_column_rank.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/strata/_stratigraphic_unit_feature.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/strata/_stratigraphic_unit_interpretation.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/surface/__init__.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/surface/_base_surface.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/surface/_combined_surface.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/surface/_mesh.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/surface/_pointset.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/surface/_surface.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/surface/_tri_mesh.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/surface/_tri_mesh_stencil.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/surface/_triangulated_patch.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/time_series/__init__.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/time_series/_any_time_series.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/time_series/_from_nexus_summary.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/time_series/_functions.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/time_series/_geologic_time_series.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/time_series/_time_duration.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/time_series/_time_series.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/unstructured/__init__.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/unstructured/_hexa_grid.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/unstructured/_prism_grid.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/unstructured/_pyramid_grid.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/unstructured/_tetra_grid.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/unstructured/_unstructured_grid.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/weights_and_measures/__init__.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/weights_and_measures/nexus_units.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/weights_and_measures/weights_and_measures.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/well/__init__.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/well/_deviation_survey.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/well/_md_datum.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/well/_wellbore_frame.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/well/_wellbore_marker.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/well/_wellbore_marker_frame.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/well/blocked_well_frame.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/well/well_object_funcs.py +0 -0
- {resqpy-4.16.1 → resqpy-4.16.3}/resqpy/well/well_utils.py +0 -0
@@ -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
|
-
|
204
|
-
if
|
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
|
-
|
218
|
-
if
|
219
|
-
|
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
|
-
|
426
|
-
|
427
|
-
|
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
|
-
|
430
|
-
|
431
|
-
|
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
|
-
|
434
|
-
value_node.set(ns['xsi'] + 'type', ns['xsd'] + 'string')
|
435
|
-
value_node.text = source
|
434
|
+
if emd_node is None:
|
436
435
|
|
437
|
-
|
438
|
-
|
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
|
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 =
|
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,
|
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,
|
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,
|
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
|
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
|
|