def _load_from_xml(self): root_node = self.root assert root_node is not None flavour = rqet.node_type(root_node) assert flavour in ['obj_LocalDepth3dCrs', 'obj_LocalTime3dCrs' ], f'bad crs node type: {flavour}' if flavour == 'obj_LocalTime3dCrs': self.time_units = rqet.find_tag_text(root_node, 'TimeUom') assert self.time_units else: self.time_units = None self.xy_units = rqet.find_tag_text(root_node, 'ProjectedUom') self.axis_order = rqet.find_tag_text(root_node, 'ProjectedAxisOrder') self.z_units = rqet.find_tag_text(root_node, 'VerticalUom') self.z_inc_down = rqet.find_tag_bool(root_node, 'ZIncreasingDownward') self.x_offset = rqet.find_tag_float(root_node, 'XOffset') self.y_offset = rqet.find_tag_float(root_node, 'YOffset') self.z_offset = rqet.find_tag_float(root_node, 'ZOffset') self.rotation = rqet.find_tag_float(root_node, 'ArealRotation') rotation_node = rqet.find_tag(root_node, 'ArealRotation') self.rotation_units = rotation_node.attrib.get('uom') parent_xy_crs = rqet.find_tag(root_node, 'ProjectedCrs') if parent_xy_crs is not None and rqet.node_type( parent_xy_crs) == 'ProjectedCrsEpsgCode': self.epsg_code = rqet.find_tag_text( parent_xy_crs, 'EpsgCode') # should be an integer? else: self.epsg_code = None
def __init__(self, model, uuid=None, title=None, originator=None, extra_metadata=None): """Load an existing resqml object, or create new. Args: model (resqpy.model.Model): Parent model uuid (str, optional): Load from existing uuid (if given), else create new. title (str, optional): Citation title originator (str, optional): Creator of object. By default, uses user id. """ self.model = model self.title = title #: Citation title self.originator = originator #: Creator of object. By default, user id. self.extra_metadata = {} if extra_metadata: self.extra_metadata = extra_metadata self._standardise_extra_metadata( ) # has side effect of making a copy if uuid is None: self.uuid = bu.new_uuid() #: Unique identifier else: self.uuid = uuid root_node = self.root citation_node = rqet.find_tag(root_node, 'Citation') if citation_node is not None: self.title = rqet.find_tag_text(citation_node, 'Title') self.originator = rqet.find_tag_text(citation_node, 'Originator') self.extra_metadata = rqet.load_metadata_from_xml(root_node) self._load_from_xml()
def _add_part_to_dict_get_property_kind(xml_node, citation_title): perm_synonyms = ['permeability rock', 'rock permeability'] (p_kind_from_keyword, facet_type, facet) = property_kind_and_facet_from_keyword(citation_title) prop_kind_node = rqet.find_tag(xml_node, 'PropertyKind') assert (prop_kind_node is not None) kind_node = rqet.find_tag(prop_kind_node, 'Kind') property_kind_uuid = None # only used for bespoke (local) property kinds if kind_node is not None: property_kind = kind_node.text # could check for consistency with that derived from citation title lpk_node = None else: lpk_node = rqet.find_tag(prop_kind_node, 'LocalPropertyKind') if lpk_node is not None: property_kind = rqet.find_tag_text(lpk_node, 'Title') property_kind_uuid = rqet.find_tag_text(lpk_node, 'UUID') assert property_kind is not None and len(property_kind) > 0 if (p_kind_from_keyword and p_kind_from_keyword != property_kind and (p_kind_from_keyword not in ['cell length', 'length', 'thickness'] or property_kind not in ['cell length', 'length', 'thickness'])): if property_kind not in perm_synonyms or p_kind_from_keyword not in perm_synonyms: log.warning( f'property kind {property_kind} not the expected {p_kind_from_keyword} for keyword {citation_title}' ) return property_kind, property_kind_uuid, lpk_node
def _load_from_xml(self): """Loads class specific attributes from xml for an existing RESQML object; called from BaseResqpy.""" root_node = self.root assert root_node is not None assert rqet.find_tag_text(root_node, 'OrderingCriteria') == 'age', \ 'stratigraphic column rank interpretation ordering criterion must be age' self.domain = rqet.find_tag_text(root_node, 'Domain') self.feature_uuid = bu.uuid_from_string( rqet.find_nested_tags_text(root_node, ['InterpretedFeature', 'UUID'])) self.has_occurred_during = rqo.extract_has_occurred_during(root_node) self.index = rqet.find_tag_int(root_node, 'Index') self.units = [] for su_node in rqet.list_of_tag(root_node, 'StratigraphicUnits'): index = rqet.find_tag_int(su_node, 'Index') unit_uuid = bu.uuid_from_string( rqet.find_nested_tags_text(su_node, ['Unit', 'UUID'])) assert index is not None and unit_uuid is not None assert self.model.type_of_uuid( unit_uuid, strip_obj=True) == 'StratigraphicUnitInterpretation' self.units.append( (index, StratigraphicUnitInterpretation(self.model, uuid=unit_uuid))) self._sort_units() self.contacts = [] for contact_node in rqet.list_of_tag(root_node, 'ContactInterpretation'): self.contacts.append( BinaryContactInterpretation(self.model, existing_xml_node=contact_node)) self._sort_contacts()
def _load_from_xml(self): root_node = self.root self.is_abstract = rqet.find_tag_bool(root_node, 'IsAbstract') self.naming_system = rqet.find_tag_text(root_node, 'NamingSystem') self.example_uom = rqet.find_tag_text(root_node, 'RepresentativeUom') ppk_node = rqet.find_tag(root_node, 'ParentPropertyKind') assert ppk_node is not None ppk_kind_node = rqet.find_tag(ppk_node, 'Kind') assert ppk_kind_node is not None, 'only standard property kinds supported as parent kind' self.parent_kind = ppk_kind_node.text
def _load_from_xml(self, bci_node): """Populates this binary contact interpretation based on existing xml. arguments: bci_node (lxml.etree._Element): the root xml node for the binary contact interpretation sub-tree """ assert bci_node is not None self.contact_relationship = rqet.find_tag_text(bci_node, 'ContactRelationship') assert self.contact_relationship in valid_contact_relationships, \ f'missing or invalid contact relationship {self.contact_relationship} in xml for binary contact interpretation' self.index = rqet.find_tag_int(bci_node, 'Index') assert self.index is not None, 'missing index in xml for binary contact interpretation' self.part_of_uuid = bu.uuid_from_string(rqet.find_nested_tags_text(bci_node, ['PartOf', 'UUID'])) sr_node = rqet.find_tag(bci_node, 'Subject') assert sr_node is not None, 'missing subject in xml for binary contact interpretation' self.subject_uuid = bu.uuid_from_string(rqet.find_tag_text(sr_node, 'UUID')) assert self.subject_uuid is not None self.subject_contact_side = rqet.find_tag_text(sr_node, 'Qualifier') self.subject_contact_mode = rqet.find_tag_text(sr_node, 'SecondaryQualifier') dor_node = rqet.find_tag(bci_node, 'DirectObject') assert dor_node is not None, 'missing direct object in xml for binary contact interpretation' self.direct_object_uuid = bu.uuid_from_string(rqet.find_tag_text(dor_node, 'UUID')) assert self.direct_object_uuid is not None self.direct_object_contact_side = rqet.find_tag_text(dor_node, 'Qualifier') self.direct_object_contact_mode = rqet.find_tag_text(dor_node, 'SecondaryQualifier') self.verb = rqet.find_tag_text(bci_node, 'Verb') assert self.verb in valid_contact_verbs, \ f'missing or invalid contact verb {self.verb} in xml for binary contact interpretation'
def _load_from_xml(self): root_node = self.root self.domain = rqet.find_tag_text(root_node, 'Domain') interp_feature_ref_node = rqet.find_tag(root_node, 'InterpretedFeature') assert interp_feature_ref_node is not None self.feature_root = self.model.referenced_node(interp_feature_ref_node) if self.feature_root is not None: self.tectonic_boundary_feature = TectonicBoundaryFeature(self.model, uuid = self.feature_root.attrib['uuid'], feature_name = self.model.title_for_root( self.feature_root)) self.main_has_occurred_during = extract_has_occurred_during(root_node) self.is_listric = rqet.find_tag_bool(root_node, 'IsListric') self.is_normal = (self.is_listric is None) self.maximum_throw = rqet.find_tag_float(root_node, 'MaximumThrow') # todo: check that type="eml:LengthMeasure" is simple float self.mean_azimuth = rqet.find_tag_float(root_node, 'MeanAzimuth') self.mean_dip = rqet.find_tag_float(root_node, 'MeanDip') throw_interpretation_nodes = rqet.list_of_tag(root_node, 'ThrowInterpretation') if throw_interpretation_nodes is not None and len(throw_interpretation_nodes): self.throw_interpretation_list = [] for ti_node in throw_interpretation_nodes: hod_pair = extract_has_occurred_during(ti_node) throw_kind_list = rqet.list_of_tag(ti_node, 'Throw') for tk_node in throw_kind_list: self.throw_interpretation_list.append((tk_node.text, hod_pair))
def _load_from_xml(self): """Loads class specific attributes from xml for an existing RESQML object; called from BaseResqpy.""" super()._load_from_xml() root_node = self.root assert root_node is not None feature_uuid = bu.uuid_from_string( rqet.find_nested_tags_text(root_node, ['InterpretedFeature', 'UUID'])) if feature_uuid is not None: self.geologic_unit_feature = StratigraphicUnitFeature( self.model, uuid=feature_uuid, title=self.model.title(uuid=feature_uuid)) # load deposition mode and min & max thicknesses (& uom), if present self.deposition_mode = rqet.find_tag_text(root_node, 'DepositionMode') for min_max in ['Min', 'Max']: thick_node = rqet.find_tag(root_node, min_max + 'Thickness') if thick_node is not None: thick = float(thick_node.text) if min_max == 'Min': self.min_thickness = thick else: self.max_thickness = thick thick_uom = thick_node.attrib[ 'uom'] # todo: check this is correct uom representation if self.thickness_uom is None: self.thickness_uom = thick_uom else: assert thick_uom == self.thickness_uom, 'inconsistent length units of measure for stratigraphic thicknesses'
def _referenced_node(model, ref_node, consolidate=False): """For a given xml reference node, returns the node for the object referred to, if present.""" # log.debug(f'ref node called for: {ref_node}') if ref_node is None: return None # content_type = rqet.find_tag_text(ref_node, 'ContentType') # log.debug(f'ref node title: {rqet.citation_title_for_node(rqet.find_tag(ref_node, "Title"))}') uuid = bu.uuid_from_string(rqet.find_tag_text(ref_node, 'UUID')) # log.debug(f'ref node uuid: {uuid}') if uuid is None: return None # return model.root_for_part(model.parts_list_of_type(type_of_interest = content_type, uuid = uuid)) if consolidate and model.consolidation is not None and uuid in model.consolidation.map: resident_uuid = model.consolidation.map[uuid] if resident_uuid is None: return None node = model.root_for_part(model.part_for_uuid(resident_uuid)) if node is not None: # patch resident uuid and title into ref node! uuid_node = rqet.find_tag(ref_node, 'UUID') uuid_node.text = str(resident_uuid) title_node = rqet.find_tag(ref_node, 'Title') if title_node is not None: title = rqet.citation_title_for_node(node) if title: title_node.text = str(title) else: node = model.root_for_part(model.part_for_uuid(uuid)) # log.debug(f'ref_node return node: {node}') return node
def test_forestry(example_model_with_prop_ts_rels): model = example_model_with_prop_ts_rels full_parts_list = model.parts() dp_parts_list = model.parts(obj_type='DiscreteProperty') assert len(dp_parts_list) > 1 # remove an individual part model.remove_part(dp_parts_list[0]) # corrupt some forest dictionary entries and test tidy up for part in dp_parts_list[1:]: model.parts_forest[part] = (None, None, None) model.tidy_up_forests() assert len(model.parts()) + len(dp_parts_list) == len(full_parts_list) assert all(p not in model.parts() for p in dp_parts_list) # test patch_root_for_part() crs_uuid = model.uuid(obj_type='LocalDepth3dCrs') crs_part = model.part_for_uuid(crs_uuid) assert crs_uuid is not None and crs_part is not None crs = rqc.Crs(model, uuid=crs_uuid) assert crs is not None crs.title = 'relativity' crs.originator = 'einstein' new_crs_node = crs.create_xml(add_as_part=False, reuse=False) rqet.find_tag(new_crs_node, 'VerticalUom').text = 'ft[US]' model.patch_root_for_part(crs_part, new_crs_node) assert rqet.find_tag_text(model.root(uuid=crs_uuid), 'VerticalUom') == 'ft[US]' assert model.citation_title_for_part(crs_part) == 'relativity' assert model.title(uuid=crs_uuid) == 'relativity' assert rqet.find_nested_tags_text(model.root(uuid=crs_uuid), ['Citation', 'Originator']) == 'einstein' # rough test of low level fell_part() model.fell_part(crs_part) assert len(model.parts()) + len(dp_parts_list) + 1 == len(full_parts_list)
def _load_from_xml(self): root_node = self.root interp_feature_ref_node = rqet.find_tag(root_node, 'InterpretedFeature') assert interp_feature_ref_node is not None self.feature_root = self.model.referenced_node(interp_feature_ref_node) if self.feature_root is not None: self.geobody_feature = GeobodyFeature( self.model, uuid=self.feature_root.attrib['uuid'], feature_name=self.model.title_for_root(self.feature_root)) self.has_occurred_during = extract_has_occurred_during(root_node) self.composition = rqet.find_tag_text(root_node, 'GeologicUnitComposition') self.implacement = rqet.find_tag_text( root_node, 'GeologicUnitMaterialImplacement') self.geobody_shape = rqet.find_tag_text(root_node, 'Geobody3dShape')
def _load_from_xml(self): """Loads class specific attributes from xml for an existing RESQML object; called from BaseResqpy.""" rank_node_list = rqet.list_of_tag(self.root, 'Ranks') assert rank_node_list is not None, 'no stratigraphic column ranks in xml for stratigraphic column' for rank_node in rank_node_list: rank = StratigraphicColumnRank(self.model, uuid=rqet.find_tag_text( rank_node, 'UUID')) self.add_rank(rank)
def _load_from_xml(self): """Loads class specific attributes from xml for an existing RESQML object; called from BaseResqpy.""" root_node = self.root assert root_node is not None self.domain = rqet.find_tag_text(root_node, 'Domain') # following allows derived StratigraphicUnitInterpretation to instantiate its own interpreted feature if self.resqml_type == 'GeologicUnitInterpretation': feature_uuid = bu.uuid_from_string( rqet.find_nested_tags_text(root_node, ['InterpretedFeature', 'UUID'])) if feature_uuid is not None: self.geologic_unit_feature = rqo.GeologicUnitFeature( self.model, uuid=feature_uuid, feature_name=self.model.title(uuid=feature_uuid)) self.has_occurred_during = rqo.extract_has_occurred_during(root_node) self.composition = rqet.find_tag_text(root_node, 'GeologicUnitComposition') self.material_implacement = rqet.find_tag_text( root_node, 'GeologicUnitMaterialImplacement')
def _load_from_xml(self): root = self.root self.domain = rqet.find_tag_text(root, 'Domain') interp_feature_ref_node = rqet.find_tag(root, 'InterpretedFeature') assert interp_feature_ref_node is not None self.feature_root = self.model.referenced_node(interp_feature_ref_node) if self.feature_root is not None: self.organization_feature = OrganizationFeature(self.model, uuid = self.feature_root.attrib['uuid'], feature_name = self.model.title_for_root(self.feature_root)) self.has_occurred_during = extract_has_occurred_during(root)
def _load_from_xml(self): root_node = self.root self.domain = rqet.find_tag_text(root_node, 'Domain') interp_feature_ref_node = rqet.find_tag(root_node, 'InterpretedFeature') assert interp_feature_ref_node is not None self.feature_root = self.model.referenced_node(interp_feature_ref_node) if self.feature_root is not None: self.genetic_boundary_feature = GeneticBoundaryFeature( self.model, kind='horizon', uuid=self.feature_root.attrib['uuid'], feature_name=self.model.title_for_root(self.feature_root)) self.has_occurred_during = extract_has_occurred_during(root_node) br_node_list = rqet.list_of_tag(root_node, 'BoundaryRelation') if br_node_list is not None and len(br_node_list) > 0: self.boundary_relation_list = [] for br_node in br_node_list: self.boundary_relation_list.append(br_node.text) self.sequence_stratigraphy_surface = rqet.find_tag_text( root_node, 'SequenceStratigraphySurface')
def extract_crs_root_and_uuid(self): """Caches uuid for coordinate reference system, as stored in geometry xml sub-tree.""" if self.crs_uuid is None: crs_root = rqet.find_nested_tags(self.node, ['Geometry', 'LocalCrs']) assert crs_root is not None, 'failed to find crs reference in triangulated patch xml' self.crs_uuid = bu.uuid_from_string( rqet.find_tag_text(crs_root, 'UUID')) else: crs_root = self.model.root_for_uuid(self.crs_uuid) return crs_root, self.crs_uuid
def _load_from_xml(self): root_node = self.root for v_node in rqet.list_of_tag(root_node, 'Value'): key = rqet.find_tag_int(v_node, 'Key') value = rqet.find_tag_text(v_node, 'Value') assert key not in self.str_dict, 'key value ' + str( key) + ' occurs more than once in string lookup table xml' self.str_dict[key] = value if self.min_index is None or key < self.min_index: self.min_index = key if self.max_index is None or key > self.max_index: self.max_index = key
def _load_from_xml(self, marker_node): """Load attributes from xml. This is invoked as part of the init method when an existing uuid is given. Returns: [bool]: True if successful """ assert marker_node is not None # Load XML data uuid_str = marker_node.attrib.get('uuid') if uuid_str: self.uuid = bu.uuid_from_string(uuid_str) citation_tag = rqet.find_nested_tags(root=marker_node, tag_list=['Citation']) assert citation_tag is not None self.title = rqet.find_tag_text(root=citation_tag, tag_name='Title') self.originator = rqet.find_tag_text(root=citation_tag, tag_name='Originator') self.marker_type = None for boundary_feature_type in [ 'GeologicBoundaryKind', 'FluidMarker', 'FluidContact' ]: found_tag_text = rqet.find_tag_text(root=marker_node, tag_name=boundary_feature_type) if found_tag_text is not None: self.marker_type = found_tag_text break assert self.marker_type is not None self.interpretation_uuid = bu.uuid_from_string( rqet.find_nested_tags_text(root=marker_node, tag_list=['Interpretation', 'UUID'])) self.extra_metadata = rqet.load_metadata_from_xml(node=marker_node) return True
def _load_from_xml(self): root_node = self.root self.is_drilled = rqet.find_tag_bool(root_node, 'IsDrilled') self.domain = rqet.find_tag_text(root_node, 'Domain') interp_feature_ref_node = rqet.find_tag(root_node, 'InterpretedFeature') if interp_feature_ref_node is not None: self.feature_root = self.model.referenced_node( interp_feature_ref_node) if self.feature_root is not None: self.wellbore_feature = WellboreFeature( self.model, uuid=self.feature_root.attrib['uuid'], feature_name=self.model.title_for_root(self.feature_root))
def _load_from_xml(self): root_node = self.root self.domain = rqet.find_tag_text(root_node, 'Domain') interp_feature_ref_node = rqet.find_tag(root_node, 'InterpretedFeature') assert interp_feature_ref_node is not None feature_root = self.model.referenced_node(interp_feature_ref_node) if feature_root is not None: self.feature_uuid = feature_root.attrib['uuid'] self.boundary_feature = BoundaryFeature( self.model, uuid=self.feature_uuid, feature_name=self.model.title_for_root(feature_root)) self.has_occurred_during = extract_has_occurred_during(root_node)
def extract_crs_uuid(grid): """Returns uuid for coordinate reference system, as stored in geometry xml tree. returns: uuid.UUID object """ if grid.crs_uuid is not None: return grid.crs_uuid crs_root = grid.resolve_geometry_child('LocalCrs') uuid_str = rqet.find_tag_text(crs_root, 'UUID') if uuid_str: grid.crs_uuid = bu.uuid_from_string(uuid_str) return grid.crs_uuid
def _load_from_xml(self): time_series_root = self.root assert time_series_root is not None # for human timeframe series, timestamps is an ordered list of timestamp strings in resqml/iso format # for geological timeframe series, timestamps is an ordered list of ints being the year offsets from present self.timestamps = [] for child in rqet.list_of_tag(time_series_root, 'Time'): dt_text = rqet.find_tag_text(child, 'DateTime') assert dt_text, 'missing DateTime field in xml for time series' year_offset = rqet.find_tag_int(child, 'YearOffset') if year_offset: assert self.timeframe == 'geologic' self.timestamps.append(year_offset) # todo: trim and check timestamp else: assert self.timeframe == 'human' self.timestamps.append(dt_text) # todo: trim and check timestamp self.timestamps.sort()
def _load_from_xml(self): self.phase = rqet.find_tag_text(self.root, 'Phase') feature_ref_node = rqet.find_tag(self.root, 'FluidBoundaryTop') assert feature_ref_node is not None feature_root = self.model.referenced_node(feature_ref_node) feature_uuid = rqet.uuid_for_part_root(feature_root) assert feature_uuid is not None, 'rock fluid top boundary feature missing from model' self.top_boundary_feature = BoundaryFeature(self.model, uuid=feature_uuid) feature_ref_node = rqet.find_tag(self.root, 'FluidBoundaryBottom') assert feature_ref_node is not None feature_root = self.model.referenced_node(feature_ref_node) feature_uuid = rqet.uuid_for_part_root(feature_root) assert feature_uuid is not None, 'rock fluid bottom boundary feature missing from model' self.base_boundary_feature = BoundaryFeature(self.model, uuid=feature_uuid)
def _add_part_to_dict_get_type_details(collection, part, continuous, xml_node): sl_ref_node = None type = collection.model.type_of_part(part) # log.debug('adding part ' + part + ' of type ' + type) assert type in [ 'obj_ContinuousProperty', 'obj_DiscreteProperty', 'obj_CategoricalProperty', 'obj_PointsProperty' ] if continuous is None: continuous = (type in ['obj_ContinuousProperty', 'obj_PointsProperty']) else: assert continuous == (type in [ 'obj_ContinuousProperty', 'obj_PointsProperty' ]) points = (type == 'obj_PointsProperty') string_lookup_uuid = None if type == 'obj_CategoricalProperty': sl_ref_node = rqet.find_tag(xml_node, 'Lookup') string_lookup_uuid = bu.uuid_from_string( rqet.find_tag_text(sl_ref_node, 'UUID')) return type, continuous, points, string_lookup_uuid, sl_ref_node
def __load_from_xml_basics(self): root_node = self.root assert root_node is not None self.surface_role = rqet.find_tag_text(root_node, 'SurfaceRole') ref_node = rqet.find_tag(root_node, 'RepresentedInterpretation') if ref_node is not None: self.represented_interpretation_root = self.model.referenced_node( ref_node) patch_node = rqet.find_tag(root_node, 'Grid2dPatch') assert rqet.find_tag_int(patch_node, 'PatchIndex') == 0 self.ni = rqet.find_tag_int(patch_node, 'FastestAxisCount') self.nj = rqet.find_tag_int(patch_node, 'SlowestAxisCount') assert self.ni is not None and self.nj is not None, 'mesh extent info missing in xml' geom_node = rqet.find_tag(patch_node, 'Geometry') assert geom_node is not None, 'geometry missing in mesh xml' self.crs_uuid = rqet.find_nested_tags_text(geom_node, ['LocalCrs', 'UUID']) assert self.crs_uuid is not None, 'crs reference missing in mesh geometry xml' point_node = rqet.find_tag(geom_node, 'Points') assert point_node is not None, 'missing Points node in mesh geometry xml' flavour = rqet.node_type(point_node) return point_node, flavour
def _load_from_xml(self): """Load attributes from xml and associated hdf5 data. This is invoked as part of the init method when an existing uuid is given. Returns: [bool]: True if successful """ # Get node from self.uuid node = self.root assert node is not None # Load XML data self.md_uom = rqet.length_units_from_node(rqet.find_tag(node, 'MdUom', must_exist = True)) self.angle_uom = rqet.find_tag_text(node, 'AngleUom', must_exist = True) self.station_count = rqet.find_tag_int(node, 'StationCount', must_exist = True) self.first_station = extract_xyz(rqet.find_tag(node, 'FirstStationLocation', must_exist = True)) self.is_final = rqet.find_tag_bool(node, 'IsFinal') # Load HDF5 data mds_node = rqet.find_tag(node, 'Mds', must_exist = True) load_hdf5_array(self, mds_node, 'measured_depths') azimuths_node = rqet.find_tag(node, 'Azimuths', must_exist = True) load_hdf5_array(self, azimuths_node, 'azimuths') inclinations_node = rqet.find_tag(node, 'Inclinations', must_exist = True) load_hdf5_array(self, inclinations_node, 'inclinations') # Set related objects self.md_datum = self._load_related_datum() self.represented_interp = self._load_related_wellbore_interp() # Validate assert self.measured_depths is not None assert len(self.measured_depths) > 0 return True
def test_load_from_xml(example_model_and_crs): # --------- Arrange ---------- model, crs = example_model_and_crs epc_path = model.epc_file elevation = 100 # Create a measured depth datum datum = resqpy.well.MdDatum(parent_model=model, crs_uuid=crs.uuid, location=(0, 0, -elevation), md_reference='kelly bushing') datum.create_xml() mds = np.array([300, 310, 330, 340]) zs = mds - elevation well_name = 'JubJub' source_dataframe = pd.DataFrame({ 'MD': mds, 'X': [1, 2, 3, 4], 'Y': [1, 2, 3, 4], 'Z': zs, 'WELL': ['JubJub', 'JubJub', 'JubJub', 'JubJub'] }) # Create a trajectory from dataframe 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 a wellbore marker frame wellbore_marker_frame = resqpy.well.WellboreMarkerFrame( parent_model=model, trajectory_uuid=trajectory_uuid, title='WMF1', originator='Person1', extra_metadata={'target_reservoir': 'r1'}) wellbore_marker_frame.create_xml() # Create several boundary 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() horizon_interp_uuid = horizon_interp_1.uuid fluid_contact_feature1 = rqo.FluidBoundaryFeature(parent_model=model, kind="gas oil contact", feature_name='goc_1') fluid_contact_feature1.create_xml() # --------- Act ---------- # Create a wellbore marker object wellbore_marker_1 = resqpy.well.WellboreMarker( parent_model=model, parent_frame=wellbore_marker_frame, marker_index=0, marker_type='horizon', interpretation_uuid=horizon_interp_uuid, title='Horizon1_marker', extra_metadata={'FormationName': 'Banoffee'}) wellbore_marker_1_uuid = wellbore_marker_1.uuid wellbore_marker_2 = resqpy.well.WellboreMarker( parent_model=model, parent_frame=wellbore_marker_frame, marker_index=1, marker_type='gas oil contact', title='GOC_marker') # Create xml for new wellbore markers wbm_node_1 = wellbore_marker_1.create_xml( parent_node=wellbore_marker_frame.root) wbm_node_2 = wellbore_marker_2.create_xml( parent_node=wellbore_marker_frame.root) # Load a new wellbore marker using a marker node wellbore_marker_3 = resqpy.well.WellboreMarker( parent_model=model, parent_frame=wellbore_marker_frame, marker_index=0, marker_node=wbm_node_1) # --------- Assert ---------- assert rqet.find_tag_text(root=wbm_node_1, tag_name='GeologicBoundaryKind') == 'horizon' assert rqet.find_tag_text(root=wbm_node_2, tag_name='FluidContact') == 'gas oil contact' assert wellbore_marker_3 is not None assert wellbore_marker_3.title == 'Horizon1_marker' assert wellbore_marker_3.marker_type == 'horizon' assert bu.matching_uuids(wellbore_marker_3.interpretation_uuid, horizon_interp_uuid) assert wellbore_marker_3.extra_metadata == {'FormationName': 'Banoffee'} assert bu.matching_uuids(wellbore_marker_3.uuid, wellbore_marker_1_uuid)
def _load_from_xml(self): self.kind = rqet.find_tag_text(self.root, 'FluidContact')
def _load_from_xml(self): self.organization_kind = rqet.find_tag_text(self.root, 'OrganizationKind')
def _load_from_xml(self): self.kind = rqet.find_tag_text(self.root, 'GeneticBoundaryKind') age_node = rqet.find_tag(self.root, 'AbsoluteAge') if age_node: self.absolute_age = (rqet.find_tag_text(age_node, 'DateTime'), rqet.find_tag_int(age_node, 'YearOffset') ) # year offset may be None