Source code for resqpy.well._wellbore_marker
"""WellboreMarker class."""
# Nexus is a registered trademark of the Halliburton Company
# RMS and ROXAR are registered trademarks of Roxar Software Solutions AS, an Emerson company
import logging
log = logging.getLogger(__name__)
import resqpy.olio.xml_et as rqet
import resqpy.olio.uuid as bu
from resqpy.olio.xml_namespaces import curly_namespace as ns
class WellboreMarker():
"""Class to handle RESQML WellboreMarker objects.
note:
wellbore markers are not high level RESQML objects
"""
resqml_type = 'WellboreMarker'
boundary_feature_dict = {
'GeologicBoundaryKind': ['fault', 'geobody', 'horizon'],
'FluidMarker': ['gas down to', 'gas up to', 'oil down to', 'oil up to', 'water down to', 'water up to'],
'FluidContact': ['free water contact', 'gas oil contact', 'gas water contact', 'seal', 'water oil contact']
}
[docs] def __init__(self,
parent_model,
parent_frame,
marker_index,
marker_node = None,
marker_type = None,
interpretation_uuid = None,
title = None,
originator = None,
extra_metadata = None):
"""Creates a new wellbore marker object and loads it from xml or populates it from arguments.
arguments:
parent_model (model.Model object): the model which the new wellbore marker belongs to
parent_frame (wellbore_marker_frame.WellboreMarkerFramer object): the wellbore marker frame to which
the wellbore marker belongs
marker_index (int): index of the wellbore marker in the parent WellboreMarkerFrame object
marker_node (xml node, optional): if given, loads from xml. Else, creates new
marker_type (str, optional): the type of geologic, fluid or contact feature
e.g. "fault", "geobody", "horizon ", "gas/oil/water down to", "gas/oil/water up to",
"free water contact", "gas oil contact", "gas water contact", "water oil contact", "seal";
ignored if marker_node is present
interpretation_uuid (uuid.UUID or string, optional): uuid of the boundary feature interpretation
organizational object that the marker refers to; ignored if marker_node is present
title (str, optional): the citation title to use for a new wellbore marker; ignored if marker_node is present
originator (str, optional): the name of the person creating the wellbore marker, defaults to login id;
ignored if uuid is not None; ignored if marker_node is present
extra_metadata (dict, optional): string key, value pairs to add as extra metadata for the wellbore marker;
ignored if uuid is not None; ignored if marker_node is present
returns:
the newly created wellbore marker object
note:
it is highly recommended that a related boundary feature interpretation uuid is provided
"""
# verify that marker type is valid
if marker_type is not None:
assert marker_type in ([
"fault", "geobody", "horizon", "gas down to", "oil down to", "water down to", "gas up to", "oil up to",
"water up to", "free water contact", "gas oil contact", "gas water contact", "water oil contact", "seal"
]), "invalid marker type specified"
self.model = parent_model
self.wellbore_frame = parent_frame
self.uuid = None
self.marker_index = marker_index
self.marker_type = None
self.interpretation_uuid = None
self.title = None
self.originator = None
self.extra_metadata = None
if marker_node is None:
self.marker_type = marker_type
self.interpretation_uuid = interpretation_uuid
self.title = title
self.originator = originator
self.extra_metadata = extra_metadata
else:
self._load_from_xml(marker_node = marker_node)
if self.uuid is None:
self.uuid = bu.new_uuid()
assert self.uuid is not None
[docs] def create_xml(self, parent_node, title = 'wellbore marker'):
"""Creates the xml tree for this wellbore marker.
arguments:
parent_node (xml node): the root node of the WellboreMarkerFrame object to which the newly created node
will be appended
title (string, default "wellbore marker"): the citation title of the newly created node; only used if
self.title is None
returns:
the newly created xml node
"""
assert self.uuid is not None
wbm_node = self.model.new_obj_node('WellboreMarker', is_top_lvl_obj = False)
wbm_node.set('uuid', str(self.uuid))
# Citation block
if self.title:
title = self.title
citation = self.model.create_citation(root = wbm_node, title = title, originator = self.originator)
# Add sub-elements to root node
for k, v in WellboreMarker.boundary_feature_dict.items():
if self.marker_type in v:
boundary_kind = k
break
wbm_gb_node = rqet.SubElement(wbm_node, ns['resqml2'] + boundary_kind)
# wbm_gb_node.set(ns['xsi'] + 'type', ns['xsd'] + 'string')
wbm_gb_node.set(ns['xsi'] + 'type', ns['resqml2'] + 'GeologicBoundaryKind')
wbm_gb_node.text = str(self.marker_type)
if self.interpretation_uuid is not None:
interp_content_type = 'obj_' + self.marker_type.capitalize() + 'Interpretation'
interp_root = self.model.root_for_uuid(uuid = self.interpretation_uuid)
self.model.create_ref_node(flavour = 'Interpretation',
title = rqet.find_tag(rqet.find_tag(interp_root, 'Citation'), 'Title').text,
uuid = self.interpretation_uuid,
content_type = interp_content_type,
root = wbm_node)
# Extra metadata
if hasattr(self, 'extra_metadata') and self.extra_metadata:
rqet.create_metadata_xml(node = wbm_node, extra_metadata = self.extra_metadata)
if parent_node is not None:
parent_node.append(wbm_node)
return wbm_node
def _load_from_xml(self, marker_node):
"""Load attributes from xml; 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
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)
# patch to deduce a boundary kind from the interpretation object
if self.marker_type is None and self.interpretation_uuid is not None:
interp_type = self.model.type_of_uuid(self.interpretation_uuid, strip_obj = True)
if interp_type == 'HorizonInterpretation':
self.marker_type = 'horizon'
elif interp_type == 'FaultInterpretation':
self.marker_type = 'fault'
elif interp_type == 'GeobodyBoundaryInterpretation':
self.marker_type = 'geobody'
assert self.marker_type is not None, f'geologic boundary tyoe not determined for marker {self.title}'
return True