示例#1
0
 def _create_feature_and_interpretation(model, feature_type, feature_name):
     # includes create_xml() for created organisational objects
     feature_type = feature_type.lower()
     assert feature_type in ['fault', 'horizon', 'geobody']
     if feature_type == 'fault':
         tbf = rqo.TectonicBoundaryFeature(model,
                                           kind='fault',
                                           feature_name=feature_name)
     else:
         tbf = rqo.GeneticBoundaryFeature(model,
                                          kind=feature_type,
                                          feature_name=feature_name)
     tbf.create_xml(reuse=True)
     if feature_type == 'fault':
         fi = rqo.FaultInterpretation(model,
                                      tectonic_boundary_feature=tbf,
                                      is_normal=True)
         # todo: set is_normal correctly
     elif feature_type == 'horizon':
         fi = rqo.HorizonInterpretation(model, genetic_boundary_feature=tbf)
         # todo: support boundary relation list and sequence stratigraphy surface
     else:  # geobody boundary
         fi = rqo.GeobodyBoundaryInterpretation(
             model, genetic_boundary_feature=tbf)
     fi.create_xml(reuse=True)
     return fi.uuid
示例#2
0
def test_is_equivalent_is_tectonic_boundary_one_none(tmp_model):

    # Arrange
    fault_interp = rqo.FaultInterpretation(
        tmp_model,
        title='tectonic_boundary_test',
    )
    fault_interp.tectonic_boundary_feature = 'something'

    # Act
    other = rqo.FaultInterpretation(
        tmp_model,
        title='tectonic_boundary_test',
    )
    other.tectonic_boundary_feature = None
    result = fault_interp.is_equivalent(other=other)

    # Assert
    assert result is False
示例#3
0
def test_FaultInterp(tmp_model):

    title = "not my fault"
    tect_boundary = rqo.TectonicBoundaryFeature(tmp_model, kind = 'fault')
    fault_interp = rqo.FaultInterpretation(
        tmp_model,
        tectonic_boundary_feature = tect_boundary,
        title = title,
        domain = "depth",
        is_normal = True,
        maximum_throw = 3,
    )

    tect_boundary.create_xml()
    fault_interp.create_xml()

    fault_interp_2 = rqo.FaultInterpretation(tmp_model, uuid = fault_interp.uuid)
    assert fault_interp_2.title == title
    assert fault_interp_2.maximum_throw == 3
示例#4
0
def test_is_equivalent_is_sameUUIDs(tmp_model):

    # Arrange
    object_uuid = uuid.new_uuid()
    fault_interp = rqo.FaultInterpretation(
        tmp_model,
        title='test_fault_interpretation',
    )
    fault_interp.uuid = object_uuid

    # Act
    other = rqo.FaultInterpretation(
        tmp_model,
        title='test_fault_interpretation_other',
    )
    other.uuid = object_uuid
    result = fault_interp.is_equivalent(other=other)

    # Assert
    assert result is True
示例#5
0
def test_is_equivalent_is_other(tmp_model):
    # Arrange
    fault_interp = rqo.FaultInterpretation(
        tmp_model,
        title='test_fault_interpretation',
    )
    # Act
    other = fault_interp
    result = fault_interp.is_equivalent(other=other)

    # Assert
    assert result is True
示例#6
0
def test_is_equivalent_throw_math_is_close(tmp_model):

    # Arrange
    fault_interp = rqo.FaultInterpretation(
        tmp_model,
        title='test_fault_interpretation',
    )
    fault_interp.maximum_throw = 1

    # Act

    other = rqo.FaultInterpretation(
        tmp_model,
        title='test_fault_interpretation',
    )
    other.maximum_throw = 1.002

    result = fault_interp.is_equivalent(other=other)

    # Assert
    assert result is False
示例#7
0
def test_is_equivalent_no_other(tmp_model):
    #Arrange
    fault_interp = rqo.FaultInterpretation(
        tmp_model,
        title='test_fault_interpretation',
        domain="depth",
        is_normal=True,
        maximum_throw=3,
    )
    #Act
    result = fault_interp.is_equivalent(other=None)

    #Assert
    assert result is False
示例#8
0
def test_is_equivalent_non_equivalent_tectonic_boundary(tmp_model):

    # Arrange
    tect_boundary = rqo.TectonicBoundaryFeature(tmp_model, kind='fault')

    fault_interp = rqo.FaultInterpretation(
        tmp_model,
        title='test_fault_interpretation',
    )
    fault_interp.tectonic_boundary_feature = tect_boundary

    # Act
    tect_boundary_other = rqo.TectonicBoundaryFeature(tmp_model,
                                                      kind='fracture')

    other = rqo.FaultInterpretation(
        tmp_model,
        title='test_fault_interpretation',
    )
    other.tectonic_boundary_feature = tect_boundary_other
    result = fault_interp.is_equivalent(other=other)

    # Assert
    assert result is False
示例#9
0
文件: _common.py 项目: bp/resqpy
    def create_interpretation_and_feature(self,
                                          kind='horizon',
                                          name=None,
                                          interp_title_suffix=None,
                                          is_normal=True):
        """Creates xml and objects for a represented interpretaion and interpreted feature, if not already present."""

        assert kind in ['horizon', 'fault', 'fracture', 'geobody boundary']
        assert name or self.title, 'title missing'
        if not name:
            name = self.title

        if self.rep_int_root is not None:
            log.debug(
                f'represented interpretation already exisrs for surface {self.title}'
            )
            return
        if kind in ['horizon', 'geobody boundary']:
            feature = rqo.GeneticBoundaryFeature(self.model,
                                                 kind=kind,
                                                 feature_name=name)
            feature.create_xml()
            if kind == 'horizon':
                interp = rqo.HorizonInterpretation(
                    self.model,
                    genetic_boundary_feature=feature,
                    domain='depth')
            else:
                interp = rqo.GeobodyBoundaryInterpretation(
                    self.model,
                    genetic_boundary_feature=feature,
                    domain='depth')
        elif kind in ['fault', 'fracture']:
            feature = rqo.TectonicBoundaryFeature(self.model,
                                                  kind=kind,
                                                  feature_name=name)
            feature.create_xml()
            interp = rqo.FaultInterpretation(
                self.model,
                is_normal=is_normal,
                tectonic_boundary_feature=feature,
                domain='depth')  # might need more arguments
        else:
            log.critical('code failure')
        interp_root = interp.create_xml(title_suffix=interp_title_suffix)
        self.rep_int_root = interp_root
示例#10
0
def test_property_collection(example_model_and_crs):
    # Create a WellboreMarkerFrame object
    # Load example model from a fixture
    model, crs = example_model_and_crs

    # Create a trajectory
    well_name = 'Banoffee'
    elevation = 100
    datum = resqpy.well.MdDatum(parent_model=model,
                                crs_uuid=crs.uuid,
                                location=(0, 0, -elevation),
                                md_reference='kelly bushing')
    mds = np.array([300.0, 310.0, 330.0])
    zs = mds - elevation
    source_dataframe = pd.DataFrame({
        'MD': mds,
        'X': [150.0, 165.0, 180.0],
        'Y': [240.0, 260.0, 290.0],
        'Z': zs,
    })
    trajectory = resqpy.well.Trajectory(parent_model=model,
                                        data_frame=source_dataframe,
                                        well_name=well_name,
                                        md_datum=datum,
                                        length_uom='m')
    trajectory.write_hdf5()
    trajectory.create_xml()
    trajectory_uuid = trajectory.uuid

    # Create features and interpretations
    horizon_feature_1 = rqo.GeneticBoundaryFeature(
        parent_model=model, kind='horizon', feature_name='horizon_feature_1')
    horizon_feature_1.create_xml()
    horizon_interp_1 = rqo.HorizonInterpretation(
        parent_model=model,
        title='horizon_interp_1',
        genetic_boundary_feature=horizon_feature_1,
        sequence_stratigraphy_surface='flooding',
        boundary_relation_list=['conformable'])
    horizon_interp_1.create_xml()

    woc_feature_1 = rqo.FluidBoundaryFeature(parent_model=model,
                                             kind='water oil contact',
                                             feature_name='woc_1')
    # fluid boundary feature does not have an associated interpretation
    woc_feature_1.create_xml()

    fault_feature_1 = rqo.TectonicBoundaryFeature(
        parent_model=model, kind='fault', feature_name='fault_feature_1')
    fault_feature_1.create_xml()
    fault_interp_1 = rqo.FaultInterpretation(
        parent_model=model,
        title='fault_interp_1',
        tectonic_boundary_feature=fault_feature_1,
        is_normal=True,
        maximum_throw=15)
    fault_interp_1.create_xml()

    df = pd.DataFrame({
        'MD': [400.0, 410.0, 430.0],
        'Boundary_Feature_Type': ['horizon', 'water oil contact', 'fault'],
        'Marker_Citation_Title':
        ['marker_horizon_1', 'marker_woc_1', 'marker_fault_1'],
        'Interp_Citation_Title': ['horizon_interp_1', None, 'fault_interp_1'],
    })

    # Create a wellbore marker frame from a dataframe
    wellbore_marker_frame = resqpy.well.WellboreMarkerFrame.from_dataframe(
        parent_model=model,
        dataframe=df,
        trajectory_uuid=trajectory_uuid,
        title='WBF1',
        originator='Human',
        extra_metadata={'target_reservoir': 'treacle'})
    wellbore_marker_frame.write_hdf5()
    wellbore_marker_frame.create_xml()

    # create a property collection for the wellbore marker frame and add a couple of properties
    pc = rqp.PropertyCollection(support=wellbore_marker_frame)
    assert pc is not None
    node_prop = np.array([123.45, -456.78, 987.65])
    pc.add_cached_array_to_imported_list(node_prop,
                                         source_info='unit test',
                                         keyword='node prop',
                                         uom='m',
                                         property_kind='length',
                                         indexable_element='nodes')
    interval_prop = np.array([3, 1], dtype=int)
    pc.add_cached_array_to_imported_list(interval_prop,
                                         source_info='unit test',
                                         keyword='interval prop',
                                         discrete=True,
                                         null_value=-1,
                                         property_kind='discrete',
                                         indexable_element='intervals')
    pc.write_hdf5_for_imported_list()
    pc.create_xml_for_imported_list_and_add_parts_to_model()
    del pc

    # reload the property collection
    pc = rqp.PropertyCollection(support=wellbore_marker_frame)
    node_prop_part = model.part(obj_type='ContinuousProperty',
                                title='node prop')
    interval_prop_part = model.part(obj_type='DiscreteProperty',
                                    title='interval prop')

    # check the property arrays
    assert pc is not None
    assert pc.number_of_parts() == 2
    assert node_prop_part is not None
    assert interval_prop_part is not None
    assert node_prop_part in pc.parts()
    assert interval_prop_part in pc.parts()
    assert_array_almost_equal(pc.cached_part_array_ref(node_prop_part),
                              [123.45, -456.78, 987.65])
    int_prop_array = pc.cached_part_array_ref(interval_prop_part)
    assert int_prop_array.size == 2
    assert np.all(int_prop_array == (3, 1))
示例#11
0
def test_find_marker_from_index(example_model_and_crs):
    # --------- Arrange ----------
    # Create a WellboreMarkerFrame object in memory
    # Load example model from a fixture
    model, crs = example_model_and_crs

    # Create a trajectory
    well_name = 'Banoffee'
    elevation = 100
    datum = resqpy.well.MdDatum(parent_model=model,
                                crs_uuid=crs.uuid,
                                location=(0, 0, -elevation),
                                md_reference='kelly bushing')
    mds = np.array([300.0, 310.0, 330.0])
    zs = mds - elevation
    source_dataframe = pd.DataFrame({
        'MD': mds,
        'X': [150.0, 165.0, 180.0],
        'Y': [240.0, 260.0, 290.0],
        'Z': zs,
    })
    trajectory = resqpy.well.Trajectory(parent_model=model,
                                        data_frame=source_dataframe,
                                        well_name=well_name,
                                        md_datum=datum,
                                        length_uom='m')
    trajectory.write_hdf5()
    trajectory.create_xml()
    trajectory_uuid = trajectory.uuid

    # Create features and interpretations
    horizon_feature_1 = rqo.GeneticBoundaryFeature(
        parent_model=model, kind='horizon', feature_name='horizon_feature_1')
    horizon_feature_1.create_xml()
    horizon_interp_1 = rqo.HorizonInterpretation(
        parent_model=model,
        title='horizon_interp_1',
        genetic_boundary_feature=horizon_feature_1,
        sequence_stratigraphy_surface='flooding',
        boundary_relation_list=['conformable'])
    horizon_interp_1.create_xml()

    woc_feature_1 = rqo.FluidBoundaryFeature(parent_model=model,
                                             kind='water oil contact',
                                             feature_name='woc_1')
    # fluid boundary feature does not have an associated interpretation
    woc_feature_1.create_xml()

    fault_feature_1 = rqo.TectonicBoundaryFeature(
        parent_model=model, kind='fault', feature_name='fault_feature_1')
    fault_feature_1.create_xml()
    fault_interp_1 = rqo.FaultInterpretation(
        parent_model=model,
        title='fault_interp_1',
        tectonic_boundary_feature=fault_feature_1,
        is_normal=True,
        maximum_throw=15)
    fault_interp_1.create_xml()

    df = pd.DataFrame({
        'MD': [400.0, 410.0, 430.0],
        'Boundary_Feature_Type': ['horizon', 'water oil contact', 'fault'],
        'Marker_Citation_Title':
        ['marker_horizon_1', 'marker_woc_1', 'marker_fault_1'],
        'Interp_Citation_Title': ['horizon_interp_1', None, 'fault_interp_1'],
    })

    # Create a wellbore marker frame from a dataframe
    wellbore_marker_frame = resqpy.well.WellboreMarkerFrame.from_dataframe(
        parent_model=model,
        dataframe=df,
        trajectory_uuid=trajectory_uuid,
        title='WBF1',
        originator='Human',
        extra_metadata={'target_reservoir': 'treacle'})

    # --------- Act ----------
    # Find marker indices based on interpretation uuids
    found_woc_marker = wellbore_marker_frame.find_marker_from_index(idx=1)
    index_error_result = wellbore_marker_frame.find_marker_from_index(idx=5)

    # --------- Assert ----------
    assert bu.matching_uuids(wellbore_marker_frame.marker_list[1].uuid,
                             found_woc_marker.uuid)
    assert index_error_result is None
示例#12
0
def test_from_dataframe_and_dataframe(example_model_and_crs):
    # Test that a WellboreMarkerFrame object can be correctly instantiated from a source dataframe and verify that the
    # dataframe generated by the dataframe() method matches the source dataframe

    # --------- Arrange ----------
    # Create a WellboreMarkerFrame object in memory
    # Load example model from a fixture
    model, crs = example_model_and_crs
    epc_path = model.epc_file

    # Create a trajectory
    well_name = 'Banoffee'
    elevation = 100
    datum = resqpy.well.MdDatum(parent_model=model,
                                crs_uuid=crs.uuid,
                                location=(0, 0, -elevation),
                                md_reference='kelly bushing')
    mds = np.array([300.0, 310.0, 330.0])
    zs = mds - elevation
    source_dataframe = pd.DataFrame({
        'MD': mds,
        'X': [150.0, 165.0, 180.0],
        'Y': [240.0, 260.0, 290.0],
        'Z': zs,
    })
    trajectory = resqpy.well.Trajectory(parent_model=model,
                                        data_frame=source_dataframe,
                                        well_name=well_name,
                                        md_datum=datum,
                                        length_uom='m')
    trajectory.write_hdf5()
    trajectory.create_xml()
    trajectory_uuid = trajectory.uuid

    # Create features and interpretations
    horizon_feature_1 = rqo.GeneticBoundaryFeature(
        parent_model=model, kind='horizon', feature_name='horizon_feature_1')
    horizon_feature_1.create_xml()
    horizon_interp_1 = rqo.HorizonInterpretation(
        parent_model=model,
        title='horizon_interp_1',
        genetic_boundary_feature=horizon_feature_1,
        sequence_stratigraphy_surface='flooding',
        boundary_relation_list=['conformable'])
    horizon_interp_1.create_xml()

    woc_feature_1 = rqo.FluidBoundaryFeature(parent_model=model,
                                             kind='water oil contact',
                                             feature_name='woc_1')
    # fluid boundary feature does not have an associated interpretation
    woc_feature_1.create_xml()

    fault_feature_1 = rqo.TectonicBoundaryFeature(
        parent_model=model, kind='fault', feature_name='fault_feature_1')
    fault_feature_1.create_xml()
    fault_interp_1 = rqo.FaultInterpretation(
        parent_model=model,
        title='fault_interp_1',
        tectonic_boundary_feature=fault_feature_1,
        is_normal=True,
        maximum_throw=15)
    fault_interp_1.create_xml()

    df = pd.DataFrame({
        'MD': [400.0, 410.0, 430.0],
        'Boundary_Feature_Type': ['horizon', 'water oil contact', 'fault'],
        'Marker_Citation_Title':
        ['marker_horizon_1', 'marker_woc_1', 'marker_fault_1'],
        'Interp_Citation_Title': ['horizon_interp_1', None, 'fault_interp_1'],
    })

    # Create a wellbore marker frame from a dataframe
    wellbore_marker_frame = resqpy.well.WellboreMarkerFrame.from_dataframe(
        parent_model=model,
        dataframe=df,
        trajectory_uuid=trajectory_uuid,
        title='WBF1',
        originator='Human',
        extra_metadata={'target_reservoir': 'treacle'})
    # --------- Act ----------
    # Save to disk
    wellbore_marker_frame.write_hdf5()
    wellbore_marker_frame.create_xml()
    wmf_uuid = wellbore_marker_frame.uuid  # called after create_xml method as it can alter the uuid
    # get the uuids of each of the markers
    marker_uuids = []
    for marker in wellbore_marker_frame.marker_list:
        marker_uuids.append(marker.uuid)
    model.store_epc()
    model.h5_release()

    # Clear memory
    del model, wellbore_marker_frame, datum, trajectory

    # Reload from disk
    model2 = Model(epc_file=epc_path)
    wellbore_marker_frame2 = resqpy.well.WellboreMarkerFrame(
        parent_model=model2, uuid=wmf_uuid)

    # Get the uuids of each of the markers
    marker_uuids2 = []
    for marker in wellbore_marker_frame2.marker_list:
        marker_uuids2.append(marker.uuid)

    # Create a dataframe from the attributes of the new wellbore marker frame object
    df2 = wellbore_marker_frame2.dataframe()
    df2_filtered_cols = df2[[
        'MD', 'Boundary_Feature_Type', 'Marker_Citation_Title',
        'Interp_Citation_Title'
    ]]

    # --------- Assert ----------
    # test that the attributes were reloaded correctly
    assert bu.matching_uuids(wellbore_marker_frame2.trajectory_uuid,
                             trajectory_uuid)
    assert wellbore_marker_frame2.node_count == len(
        wellbore_marker_frame2.node_mds) == len(
            wellbore_marker_frame2.marker_list) == 3
    assert wellbore_marker_frame2.title == 'WBF1'
    assert wellbore_marker_frame2.originator == 'Human'
    assert wellbore_marker_frame2.extra_metadata == {
        'target_reservoir': 'treacle'
    }
    np.testing.assert_almost_equal(wellbore_marker_frame2.node_mds,
                                   np.array([400.0, 410.0, 430.0]))
    for uuid1, uuid2 in zip(marker_uuids, marker_uuids2):
        assert bu.matching_uuids(uuid1, uuid2)
    # test that the generated dataframe contains the same data as the original df
    pd.testing.assert_frame_equal(df, df2_filtered_cols, check_dtype=False)