예제 #1
0
    def _set_mesh_from_df(self):
        """Creates Mesh object; called before writing to hdf5 or creating xml."""
        # note: actual data is stored in related Property if realization number is present, directly in Mesh otherwise

        assert self.n_rows == len(self.df)
        assert self.n_cols == len(self.df.columns)

        if self.mesh is None:
            origin = (0.0, 0.0, 0.0)
            dxyz_dij = np.array([[1.0, 0.0, 0.0], [0.0, 1.0, 0.0]])
            crs_uuids = self.model.uuids(obj_type='LocalDepth3dCrs')
            if len(crs_uuids) == 0:
                crs = rqc.Crs(self.model)
                crs.create_xml()
                crs_uuid = crs.uuid
            else:  # use any available crs
                crs_uuid = crs_uuids[0]
            if self.realization is None:
                self.mesh = rqs.Mesh(self.model,
                                     mesh_flavour='reg&z',
                                     ni=self.n_cols,
                                     nj=self.n_rows,
                                     dxyz_dij=dxyz_dij,
                                     origin=origin,
                                     z_values=np.array(self.df),
                                     crs_uuid=crs_uuid)
            else:
                self.mesh = rqs.Mesh(self.model,
                                     mesh_flavour='regular',
                                     ni=self.n_cols,
                                     nj=self.n_rows,
                                     dxyz_dij=dxyz_dij,
                                     origin=origin,
                                     crs_uuid=crs_uuid)
            self.mesh.write_hdf5()
            mesh_root = self.mesh.create_xml(title=self.title)
            rqet.create_metadata_xml(mesh_root, {'dataframe': 'true'})
            if self.realization is not None:
                self.pc = rqp.PropertyCollection()
                self.pc.set_support(support=self.mesh)
                dataframe_pk_uuid = self.model.uuid(obj_type='PropertyKind',
                                                    title='dataframe')
                if dataframe_pk_uuid is None:
                    dataframe_pk = rqp.PropertyKind(self.model,
                                                    title='dataframe',
                                                    example_uom='Euc')
                    dataframe_pk.create_xml()
                    dataframe_pk_uuid = dataframe_pk.uuid
                self.pc.add_cached_array_to_imported_list(
                    np.array(self.df),
                    'dataframe',
                    self.title,
                    uom='Euc',
                    property_kind='dataframe',
                    local_property_kind_uuid=dataframe_pk_uuid,
                    realization=self.realization,
                    indexable_element='nodes')
                self.pc.write_hdf5_for_imported_list()
                self.pc.create_xml_for_imported_list_and_add_parts_to_model()
예제 #2
0
파일: _add_surfaces.py 프로젝트: bp/resqpy
def _add_single_surface(model, surf_file, surface_file_format, surface_role, quad_triangles, crs_uuid, rq_class,
                        hdf5_file, h5_mode, make_horizon_interpretations_and_features, ext_uuid):
    _, short_name = os.path.split(surf_file)
    dot = short_name.rfind('.')
    if dot > 0:
        short_name = short_name[:dot]

    log.info('surface ' + short_name + ' processing file: ' + surf_file + ' using format: ' + surface_file_format)
    if rq_class == 'surface':
        if surface_file_format == 'GOCAD-Tsurf':
            surface = rqs.Surface(model,
                                  tsurf_file = surf_file,
                                  surface_role = surface_role,
                                  quad_triangles = quad_triangles)
        else:
            surface = rqs.Surface(model,
                                  mesh_file = surf_file,
                                  mesh_format = surface_file_format,
                                  surface_role = surface_role,
                                  quad_triangles = quad_triangles)
    elif rq_class == 'mesh':
        if surface_file_format == 'GOCAD-Tsurf':
            log.info(f"Cannot convert a GOCAD-Tsurf to mesh, only to TriangulatedSurface - skipping file {surf_file}")
            return model
        else:
            surface = rqs.Mesh(model,
                               mesh_file = surf_file,
                               mesh_format = surface_file_format,
                               mesh_flavour = 'reg&z',
                               surface_role = surface_role,
                               crs_uuid = crs_uuid)
    else:
        log.critical('this is impossible')
    # NB. surface may be either a Surface object or a Mesh object

    log.debug('appending to hdf5 file for surface file: ' + surf_file)
    surface.write_hdf5(hdf5_file, mode = h5_mode)

    if make_horizon_interpretations_and_features:
        feature = rqo.GeneticBoundaryFeature(model, kind = 'horizon', feature_name = short_name)
        feature.create_xml()
        interp = rqo.HorizonInterpretation(model, genetic_boundary_feature = feature, domain = 'depth')
        interp_root = interp.create_xml()
        surface.set_represented_interpretation_root(interp_root)

    surface.create_xml(ext_uuid,
                       add_as_part = True,
                       add_relationships = True,
                       title = short_name + ' sourced from ' + surf_file,
                       originator = None)

    return model
예제 #3
0
def _set_support_uuid_notnone_supportnone(collection, support_uuid, model):
    import resqpy.fault as rqf
    import resqpy.grid as grr
    import resqpy.surface as rqs
    import resqpy.unstructured as rug
    import resqpy.well as rqw

    support_part = model.part_for_uuid(support_uuid)
    assert support_part is not None, 'supporting representation part missing in model'
    collection.support_root = model.root_for_part(support_part)
    support_type = model.type_of_part(support_part)
    assert support_type is not None
    if support_type == 'obj_IjkGridRepresentation':
        collection.support = grr.any_grid(model,
                                          uuid=collection.support_uuid,
                                          find_properties=False)
    elif support_type == 'obj_WellboreFrameRepresentation':
        collection.support = rqw.WellboreFrame(model,
                                               uuid=collection.support_uuid)
    elif support_type == 'obj_BlockedWellboreRepresentation':
        collection.support = rqw.BlockedWell(model,
                                             uuid=collection.support_uuid)
    elif support_type == 'obj_Grid2dRepresentation':
        collection.support = rqs.Mesh(model, uuid=collection.support_uuid)
    elif support_type == 'obj_GridConnectionSetRepresentation':
        collection.support = rqf.GridConnectionSet(
            model, uuid=collection.support_uuid)
    elif support_type == 'obj_TriangulatedSetRepresentation':
        collection.support = rqs.Surface(model, uuid=collection.support_uuid)
    elif support_type == 'obj_UnstructuredGridRepresentation':
        collection.support = rug.UnstructuredGrid(model,
                                                  uuid=collection.support_uuid,
                                                  geometry_required=False,
                                                  find_properties=False)
    elif support_type == 'obj_WellboreMarkerFrameRepresentation':
        collection.support = rqw.WellboreMarkerFrame(
            model, uuid=collection.support_uuid)
    else:
        raise TypeError(
            'unsupported property supporting representation class: ' +
            str(support_type))
예제 #4
0
def test_vertical_prism_grid_from_seed_points_and_surfaces(tmp_path):

    seed(23487656)  # to ensure test reproducibility

    epc = os.path.join(tmp_path, 'voronoi_prism_grid.epc')
    model = rq.new_model(epc)
    crs = rqc.Crs(model)
    crs.create_xml()

    # define a boundary polyline:
    b_count = 7
    boundary_points = np.empty((b_count, 3))
    radius = 1000.0
    for i in range(b_count):
        theta = -vec.radians_from_degrees(i * 360.0 / b_count)
        boundary_points[i] = (2.0 * radius * maths.cos(theta),
                              radius * maths.sin(theta), 0.0)
    boundary = rql.Polyline(model,
                            set_coord=boundary_points,
                            set_bool=True,
                            set_crs=crs.uuid,
                            title='rough ellipse')
    boundary.write_hdf5()
    boundary.create_xml()

    # derive a larger area of interest
    aoi = rql.Polyline.from_scaled_polyline(boundary,
                                            1.1,
                                            title='area of interest')
    aoi.write_hdf5()
    aoi.create_xml()
    min_xy = np.min(aoi.coordinates[:, :2], axis=0) - 50.0
    max_xy = np.max(aoi.coordinates[:, :2], axis=0) + 50.0

    print(f'***** min max xy aoi+ : {min_xy} {max_xy}')  # debug

    # create some seed points within boundary
    seed_count = 5
    seeds = rqs.PointSet(model,
                         crs_uuid=crs.uuid,
                         polyline=boundary,
                         random_point_count=seed_count,
                         title='seeds')
    seeds.write_hdf5()
    seeds.create_xml()
    seeds_xy = seeds.single_patch_array_ref(0)

    for seed_xy in seeds_xy:
        assert aoi.point_is_inside_xy(
            seed_xy), f'seed point {seed_xy} outwith aoi'

    print(
        f'***** min max xy seeds : {np.min(seeds_xy, axis = 0)} {np.max(seeds_xy, axis = 0)}'
    )  # debug

    # create some horizon surfaces
    ni, nj = 21, 11
    lattice = rqs.Mesh(model,
                       crs_uuid=crs.uuid,
                       mesh_flavour='regular',
                       ni=ni,
                       nj=nj,
                       origin=(min_xy[0], min_xy[1], 0.0),
                       dxyz_dij=np.array([[
                           (max_xy[0] - min_xy[0]) / (ni - 1), 0.0, 0.0
                       ], [0.0, (max_xy[1] - min_xy[1]) / (nj - 1), 0.0]]))
    lattice.write_hdf5()
    lattice.create_xml()
    horizons = []
    for i in range(4):
        horizon_depths = 1000.0 + 100.0 * i + 20.0 * (np.random.random(
            (nj, ni)) - 0.5)
        horizon_mesh = rqs.Mesh(model,
                                crs_uuid=crs.uuid,
                                mesh_flavour='ref&z',
                                ni=ni,
                                nj=nj,
                                z_values=horizon_depths,
                                z_supporting_mesh_uuid=lattice.uuid,
                                title='h' + str(i))
        horizon_mesh.write_hdf5()
        horizon_mesh.create_xml()
        horizon_surface = rqs.Surface(model,
                                      crs_uuid=crs.uuid,
                                      mesh=horizon_mesh,
                                      quad_triangles=True,
                                      title=horizon_mesh.title)
        horizon_surface.write_hdf5()
        horizon_surface.create_xml()
        horizons.append(horizon_surface)

    # create a re-triangulated Voronoi vertical prism grid
    grid = rug.VerticalPrismGrid.from_seed_points_and_surfaces(
        model, seeds_xy, horizons, aoi, title="giant's causeway")
    assert grid is not None
    grid.write_hdf5()
    grid.create_xml()

    # check cell thicknesses are in expected range
    thick = grid.thickness()
    assert np.all(thick >= 80.0)
    assert np.all(thick <= 120.0)

    model.store_epc()
예제 #5
0
    def __init__(
            self,
            model,
            support_root=None,  # deprecated
            uuid=None,
            df=None,
            uom_list=None,
            realization=None,
            title='dataframe',
            column_lookup_uuid=None,
            uom_lookup_uuid=None,
            extra_metadata=None):
        """Create a new Dataframe object from either a previously stored property or a pandas dataframe.

        arguments:
           model (model.Model): the model to which the new Dataframe will be attached
           support_root (lxml.Element, DEPRECATED): use uuid instead
           uuid (uuid.UUID, optional): the uuid of an existing Grid2dRepresentation
              object acting as support for a dataframe property (or holding the dataframe as z values)
           df (pandas.DataFrame, optional): a dataframe from which the new Dataframe is to be created;
              if both uuid (or support_root) and df are supplied, realization must not be None and a new
              realization property will be created
           uom_list (list of str, optional): a list holding the units of measure for each
              column; if present, length of list must match number of columns in df; ignored if
              uuid or support_root is not None
           realization (int, optional): if present, the realization number of the RESQML property
              holding the dataframe
           title (str, default 'dataframe'): used as the citation title for the Mesh (and property);
              ignored if uuid or support_root is not None
           column_lookup_uuid (uuid, optional): if present, the uuid of a string lookup table holding
              the column names; if present, the contents and order of the table must match the columns
              in the dataframe; if absent, a new lookup table will be created; ignored if support_root
              is not None
           uom_lookup_uuid (uuid, optional): if present, the uuid of a string lookup table holding
              the units of measure for each column; if None and uom_list is present, a new table
              will be created; if both uom_list and uom_lookup_uuid are present, their contents
              must match; ignored if support_root is not None
           extra_metadata (dict, optional): if present, a dictionary of extra metadata items, str: str;
              ignored if uuid (or support_root) is not None

        returns:
           a newly created Dataframe object

        notes:
           when initialising from an existing RESQML object, the supporting mesh and its property should
           have been originally created using this class; when working with ensembles, each object of this
           class will only handle the data for one realization, though they may share a common support_root
        """

        assert uuid is not None or support_root is not None or df is not None
        assert (uuid is None and
                support_root is None) or df is None or realization is not None

        if uuid is None:
            if support_root is not None:
                warnings.warn(
                    "support_root parameter is deprecated, use uuid instead",
                    DeprecationWarning)
                uuid = rqet.uuid_for_part_root(support_root)
        else:
            support_root = model.root_for_uuid(uuid)

        self.model = model
        self.df = None
        self.n_rows = self.n_cols = 0
        self.uom_list = None
        self.realization = realization
        self.title = title
        self.mesh = None  # only generated when needed for write_hdf5(), create_xml()
        self.pc = None  # property collection; only generated when needed for write_hdf5(), create_xml()
        self.column_lookup_uuid = column_lookup_uuid
        self.column_lookup = None  # string lookup table mapping column index (0 based) to column name
        self.uom_lookup_uuid = uom_lookup_uuid
        self.uom_lookup = None  # string lookup table mapping column index (0 based) to uom
        self.extra_metadata = extra_metadata

        if uuid is not None:
            assert rqet.node_type(support_root) == 'obj_Grid2dRepresentation'
            self.mesh = rqs.Mesh(self.model, uuid=uuid)
            self.extra_metadata = self.mesh.extra_metadata
            assert 'dataframe' in self.extra_metadata and self.extra_metadata[
                'dataframe'] == 'true'
            self.title = self.mesh.title
            self.n_rows, self.n_cols = self.mesh.nj, self.mesh.ni
            cl_uuid = self.model.uuid(obj_type='StringTableLookup',
                                      related_uuid=uuid,
                                      title='dataframe columns')
            assert cl_uuid is not None, 'column name lookup table not found for dataframe'
            self.column_lookup = rqp.StringLookup(self.model, uuid=cl_uuid)
            self.column_lookup_uuid = self.column_lookup.uuid
            assert self.column_lookup.length() == self.n_cols
            ul_uuid = self.model.uuid(obj_type='StringTableLookup',
                                      related_uuid=uuid,
                                      title='dataframe units')
            if ul_uuid is not None:
                self.uom_lookup = rqp.StringLookup(self.model, uuid=ul_uuid)
                self.uom_lookup_uuid = self.uom_lookup.uuid
                self.uom_list = self.uom_lookup.get_list()
            da = self.mesh.full_array_ref(
            )[...,
              2]  # dataframe data as 2D numpy array, defaulting to z values in mesh
            existing_pc = rqp.PropertyCollection(support=self.mesh)
            existing_count = 0 if existing_pc is None else existing_pc.number_of_parts(
            )
            if df is None:  # existing dara, either in mesh or property
                if existing_count > 0:  # use property data instead of z values
                    if existing_count == 1:
                        if self.realization is not None:
                            assert existing_pc.realization_for_part(
                                existing_pc.singleton()) == self.realization
                    else:
                        assert self.realization is not None, 'no realization specified when accessing ensemble dataframe'
                    da = existing_pc.single_array_ref(
                        realization=self.realization)
                    assert da is not None and da.ndim == 2 and da.shape == (
                        self.n_rows, self.n_cols)
                else:
                    assert realization is None
                self.df = pd.DataFrame(da,
                                       columns=self.column_lookup.get_list())
            else:  # both support_root and df supplied: add a new realisation
                if existing_count > 0:
                    assert existing_pc.singleton(
                        realization=self.realization
                    ) is None, 'dataframe realization already exists'
                self.df = df.copy()
                assert len(self.df) == self.n_rows
                assert len(self.df.columns) == self.n_rows
        else:
            assert df is not None, 'no dataframe (or support root) provided when instantiating DataFrame object'
            self.df = df.copy()
            # todo: check data type of columns – restrict to numerical data
            self.n_rows = len(self.df)
            self.n_cols = len(self.df.columns)
            if column_lookup_uuid is not None:
                self.column_lookup = rqp.StringLookup(self.model,
                                                      uuid=column_lookup_uuid)
                assert self.column_lookup is not None
                assert self.column_lookup.length() == self.n_cols
                assert all(self.df.columns == self.column_lookup.get_list()
                           )  # exact match of column names required!
            if uom_lookup_uuid is not None:
                self.uom_lookup = rqp.StringLookup(self.model,
                                                   uuid=uom_lookup_uuid)
                assert self.uom_lookup is not None
            if uom_list is not None:
                assert len(uom_list) == self.n_cols
                self.uom_list = uom_list.copy()
                if self.uom_lookup is not None:
                    assert self.uom_list == self.uom_lookup.get_list()
            elif self.uom_lookup is not None:
                self.uom_list = self.uom_lookup.get_list()