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 extract_has_occurred_during(parent_node, tag = 'HasOccuredDuring'): # RESQML Occured (stet) """Extracts UUIDs of chrono bottom and top from xml for has occurred during sub-node, or (None, None).""" hod_node = rqet.find_tag(parent_node, tag) if hod_node is None: return (None, None) else: return (rqet.find_nested_tags_text(hod_node, ['ChronoBottom', 'UUID']), rqet.find_nested_tags_text(hod_node, ['ChronoTop', 'UUID']))
def _load_from_xml(self): """Loads the trajectory object from an xml node (and associated hdf5 data).""" node = self.root assert node is not None self.start_md = float( rqet.node_text(rqet.find_tag(node, 'StartMd')).strip()) self.finish_md = float( rqet.node_text(rqet.find_tag(node, 'FinishMd')).strip()) self.md_uom = rqet.length_units_from_node(rqet.find_tag(node, 'MdUom')) self.md_domain = rqet.node_text(rqet.find_tag(node, 'MdDomain')) geometry_node = rqet.find_tag(node, 'Geometry') self.crs_uuid = bu.uuid_from_string( rqet.find_nested_tags_text(geometry_node, ['LocalCrs', 'UUID'])) self.knot_count = int( rqet.node_text(rqet.find_tag(geometry_node, 'KnotCount')).strip()) self.line_kind_index = int( rqet.node_text(rqet.find_tag(geometry_node, 'LineKindIndex')).strip()) mds_node = rqet.find_tag(geometry_node, 'ControlPointParameters') if mds_node is not None: # not required for vertical or z linear cubic spline load_hdf5_array(self, mds_node, 'measured_depths') control_points_node = rqet.find_tag(geometry_node, 'ControlPoints') load_hdf5_array(self, control_points_node, 'control_points', tag='Coordinates') tangents_node = rqet.find_tag(geometry_node, 'TangentVectors') if tangents_node is not None: load_hdf5_array(self, tangents_node, 'tangent_vectors', tag='Coordinates') relatives_model = self.model # if hdf5_source_model is None else hdf5_source_model # md_datum - separate part, referred to in this tree md_datum_uuid = bu.uuid_from_string( rqet.find_nested_tags_text(node, ['MdDatum', 'UUID'])) assert md_datum_uuid is not None, 'failed to fetch uuid of md datum for trajectory' md_datum_part = relatives_model.part_for_uuid(md_datum_uuid) assert md_datum_part, 'md datum part not found in model' self.md_datum = MdDatum( self.model, uuid=relatives_model.uuid_for_part(md_datum_part)) ds_uuid = bu.uuid_from_string( rqet.find_nested_tags_text(node, ['DeviationSurvey', 'UUID'])) if ds_uuid is not None: # this will probably not work when relatives model is different from self.model ds_uuid = self.model.uuid(obj_type='DeviationSurveyRepresentation', uuid=ds_uuid) # check part is present if ds_uuid is not None: self.deviation_survey = DeviationSurvey(self.model, uuid=ds_uuid) interp_uuid = rqet.find_nested_tags_text( node, ['RepresentedInterpretation', 'UUID']) if interp_uuid is None: self.wellbore_interpretation = None else: self.wellbore_interpretation = rqo.WellboreInterpretation( self.model, uuid=interp_uuid)
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 bottom_ref_uuid = rqet.find_nested_tags_text( root_node, ['ChronostratigraphicBottom', 'UUID']) top_ref_uuid = rqet.find_nested_tags_text( root_node, ['ChronostratigraphicTop', 'UUID']) # todo: find out if these are meant to be references to other stratigraphic unit features or geologic unit features # and if so, instantiate those objects? # for now, simply note the uuids if bottom_ref_uuid is not None: self.bottom_unit_uuid = bu.uuid_from_string(bottom_ref_uuid) if top_ref_uuid is not None: self.top_unit_uuid = bu.uuid_from_string(top_ref_uuid)
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): assert self.root is not None # polyline xml node is specified poly_root = self.root self.title = rqet.citation_title_for_node(poly_root) self.extra_metadata = rqet.load_metadata_from_xml(self.root) self.isclosed = rqet.bool_from_text( rqet.node_text(rqet.find_tag(poly_root, 'IsClosed'))) assert self.isclosed is not None # Required field patch_node = rqet.find_tag(poly_root, 'NodePatch') assert patch_node is not None # Required field geometry_node = rqet.find_tag(patch_node, 'Geometry') assert geometry_node is not None # Required field self.crs_uuid = bu.uuid_from_string( rqet.find_nested_tags_text(geometry_node, ['LocalCrs', 'UUID'])) assert self.crs_uuid is not None # Required field points_node = rqet.find_tag(geometry_node, 'Points') assert points_node is not None # Required field load_hdf5_array(self, points_node, 'coordinates', tag='Coordinates') self.nodepatch = (rqet.find_tag_int(patch_node, 'PatchIndex'), rqet.find_tag_int(patch_node, 'Count')) assert not any( map(lambda x: x is None, self.nodepatch)) # Required fields - assert neither are None self.rep_int_root = self.model.referenced_node( rqet.find_tag(poly_root, 'RepresentedInterpretation'))
def _set_parent_window_in_grid(set_parent_window, source_grid, grid, fine_coarse): if set_parent_window: pw_grid_uuid = source_grid.uuid if isinstance(set_parent_window, str): if set_parent_window == 'grandparent': assert fine_coarse.within_fine_box is None or (np.all(fine_coarse.within_fine_box[0] == 0) and np.all(fine_coarse.within_fine_box[1]) == source_grid.extent_kji - 1), \ 'attempt to set grandparent window for grid when parent window is present' source_fine_coarse = source_grid.parent_window if source_fine_coarse is not None and ( source_fine_coarse.within_fine_box is not None or source_fine_coarse.within_coarse_box is not None): assert source_fine_coarse.fine_extent_kji == source_fine_coarse.coarse_extent_kji, 'parentage involves refinement or coarsening' if source_fine_coarse.within_fine_box is not None: fine_coarse.within_fine_box = source_fine_coarse.within_fine_box else: fine_coarse.within_fine_box = source_fine_coarse.within_coarse_box pw_grid_uuid = bu.uuid_from_string( rqet.find_nested_tags_text( source_grid.root, ['ParentWindow', 'ParentGrid', 'UUID'])) else: assert set_parent_window == 'parent', 'set_parent_window value not recognized: ' + set_parent_window grid.set_parent(pw_grid_uuid, False, fine_coarse)
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): """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 __load_from_xml_refz(self, support_geom_node): self.flavour = 'ref&z' # assert rqet.node_type(support_geom_node) == 'Point3dFromRepresentationLatticeArray' # only this supported for now self.ref_uuid = rqet.find_nested_tags_text( support_geom_node, ['SupportingRepresentation', 'UUID']) assert self.ref_uuid, 'missing supporting representation info in xml for z-value mesh' self.ref_mesh = Mesh(self.model, uuid=self.ref_uuid) assert self.nj == self.ref_mesh.nj and self.ni == self.ref_mesh.ni # only this supported for now niosr_node = rqet.find_tag(support_geom_node, 'NodeIndicesOnSupportingRepresentation') start_value = rqet.find_tag_int(niosr_node, 'StartValue') assert start_value == 0, 'only full use of supporting mesh catered for at present' offset_nodes = rqet.list_of_tag( niosr_node, 'Offset') # first occurrence for FastestAxis, ie. I; 2nd for J assert len( offset_nodes ) == 2, 'missing (or too many) offset nodes in xml for regular mesh (lattice)' for j_or_i in range(2): # 0 = J, 1 = I assert rqet.node_type( offset_nodes[j_or_i] ) == 'IntegerConstantArray', 'variable step not catered for' assert rqet.find_tag_int( offset_nodes[j_or_i], 'Value') == 1, 'step other than 1 not catered for' count = rqet.find_tag_int(offset_nodes[j_or_i], 'Count') assert count == (self.nj, self.ni)[j_or_i] - 1, \ 'unexpected value for count in xml spacing info for regular mesh (lattice)'
def _process_complex_types(schema, complex_types): for completon in rqet.list_of_tag(schema, 'complexType'): name = completon.attrib['name'] doc = rqet.find_nested_tags_text(completon, ['annotation', 'documentation']) content = rqet.find_tag(completon, 'complexContent') extension = rqet.find_tag(content, 'extension') if extension is None: e_base = None else: e_base = extension.attrib['base'] content = extension if content is None: content = completon sequence = rqet.find_tag(content, 'sequence') if sequence is None: sequence = content element_list = [] e_nodes = rqet.list_of_tag(sequence, 'element') if e_nodes is not None: for element in e_nodes: e_name = element.attrib['name'] flavour = element.attrib[ 'type'] # could strip prefix here? min_occurs = element.get('minOccurs') max_occurs = element.get('maxOccurs') element_list.append( (e_name, flavour, min_occurs, max_occurs)) complex_types[name] = (e_base, element_list, doc)
def grid_flavour(grid_root): """Returns a string indicating type of grid geometry, currently 'IjkGrid' or 'IjkBlockGrid'.""" if grid_root is None: return None em = rqet.load_metadata_from_xml(grid_root) flavour = em.get('grid_flavour') if flavour is None: node_type = rqet.node_type(grid_root, strip_obj = True) if node_type == 'IjkGridRepresentation': if rqet.find_tag(grid_root, 'Geometry') is not None: flavour = 'IjkGrid' else: flavour = 'IjkBlockGrid' # this might cause issues elif node_type == 'UnstructuredGridRepresentation': cell_shape = rqet.find_nested_tags_text(grid_root, ['Geometry', 'CellShape']) if cell_shape is None or cell_shape == 'polyhedral': flavour = 'UnstructuredGrid' elif cell_shape == 'tetrahedral': flavour = 'TetraGrid' elif cell_shape == 'hexahedral': flavour = 'HexaGrid' elif cell_shape == 'pyramidal': flavour = 'PyramidGrid' elif cell_shape == 'prism': flavour = 'PrismGrid' return flavour
def __create_xml_refandz(self, p_node, ext_uuid): assert ext_uuid is not None assert self.ref_uuid is not None p_node.set(ns['xsi'] + 'type', ns['resqml2'] + 'Point3dZValueArray') sg_node = rqet.SubElement(p_node, ns['resqml2'] + 'SupportingGeometry') sg_node.set(ns['xsi'] + 'type', ns['resqml2'] + 'Point3dFromRepresentationLatticeArray') sg_node.text = '\n' niosr_node = rqet.SubElement( sg_node, ns['resqml2'] + 'NodeIndicesOnSupportingRepresentation') niosr_node.set(ns['xsi'] + 'type', ns['resqml2'] + 'IntegerLatticeArray') niosr_node.text = '\n' sv_node = rqet.SubElement(niosr_node, ns['resqml2'] + 'StartValue') sv_node.set(ns['xsi'] + 'type', ns['xsd'] + 'integer') sv_node.text = '0' # no other possibility cater for at present for j_or_i in range(2): # 0 = J, 1 = I o_node = rqet.SubElement(niosr_node, ns['resqml2'] + 'Offset') o_node.set(ns['xsi'] + 'type', ns['resqml2'] + 'IntegerConstantArray' ) # no other possibility cater for at present o_node.text = '\n' ov_node = rqet.SubElement(o_node, ns['resqml2'] + 'Value') ov_node.set(ns['xsi'] + 'type', ns['xsd'] + 'integer') ov_node.text = '1' # no other possibility cater for at present oc_node = rqet.SubElement(o_node, ns['resqml2'] + 'Count') oc_node.set(ns['xsi'] + 'type', ns['xsd'] + 'positiveInteger') if j_or_i: oc_node.text = str(self.ni - 1) else: oc_node.text = str(self.nj - 1) ref_root = self.model.root_for_uuid(self.ref_uuid) self.model.create_ref_node('SupportingRepresentation', rqet.find_nested_tags_text( ref_root, ['Citation', 'Title']), self.ref_uuid, content_type='Grid2dRepresentation', root=sg_node) zv_node = rqet.SubElement(p_node, ns['resqml2'] + 'ZValues') zv_node.set(ns['xsi'] + 'type', ns['resqml2'] + 'DoubleHdf5Array') zv_node.text = '\n' v_node = rqet.SubElement(zv_node, ns['resqml2'] + 'Values') v_node.set(ns['xsi'] + 'type', ns['eml'] + 'Hdf5Dataset') v_node.text = '\n' self.model.create_hdf5_dataset_ref(ext_uuid, self.uuid, 'zvalues', root=v_node)
def _create_md_datum_reference(md_datum_root, root=None): """Creates a node refering to an existing measured depth datum and optionally adds as child of root.""" return _create_ref_node('MdDatum', rqet.find_nested_tags_text(md_datum_root, ['Citation', 'Title']), bu.uuid_from_string(md_datum_root.attrib['uuid']), content_type='obj_MdDatum', root=root)
def extract_grid_parent(grid): """Returns the uuid of the parent grid for the supplied grid""" if grid.extent_kji is None: grid.extract_extent_kji() if grid.parent_grid_uuid is not None: return grid.parent_grid_uuid grid.parent_window = None # FineCoarse cell index mapping info with respect to parent grid.is_refinement = None pw_node = rqet.find_tag(grid.root, 'ParentWindow') if pw_node is None: return None # load a FineCoarse object as parent_window attribute and set parent_grid_uuid attribute grid.parent_grid_uuid = bu.uuid_from_string(rqet.find_nested_tags_text(pw_node, ['ParentGrid', 'UUID'])) assert grid.parent_grid_uuid is not None parent_grid_root = grid.model.root(uuid = grid.parent_grid_uuid) if parent_grid_root is None: log.warning('parent grid not present in model, unable to treat as local grid') return None # etxract parent grid extent directly from xml to avoid risk of circular references parent_grid_extent_kji = np.array((rqet.find_tag_int( parent_grid_root, 'Nk'), rqet.find_tag_int(parent_grid_root, 'Nj'), rqet.find_tag_int(parent_grid_root, 'Ni')), dtype = int) parent_initials = [] intervals_count_list = [] parent_count_list_list = [] child_count_list_list = [] child_weight_list_list = [] refining_flag = None # gets set True if local grid is a refinement, False if a coarsening parent_box = np.zeros((2, 3), dtype = int) for axis in range(3): refining_flag = __process_axis(axis, child_count_list_list, child_weight_list_list, grid, intervals_count_list, parent_box, parent_count_list_list, parent_grid_extent_kji, parent_initials, pw_node, refining_flag) cell_overlap_node = rqet.find_tag(pw_node, 'CellOverlap') if cell_overlap_node is not None: log.warning('ignoring cell overlap information in grid relationship') omit_node = rqet.find_tag(pw_node, 'OmitParentCells') if omit_node is not None: log.warning('unable to handle parent cell omissions in local grid definition – ignoring') # todo: handle omissions if refining_flag is None: log.warning('local grid has no refinement nor coarsening – treating as a refined grid') refining_flag = True grid.is_refinement = refining_flag if refining_flag: # local grid is a refinement __extract_refined_parent(child_count_list_list, child_weight_list_list, grid, intervals_count_list, parent_box, parent_count_list_list) else: # local grid is a coarsening __extract_coarsening_parent(child_count_list_list, child_weight_list_list, grid, intervals_count_list, parent_box, parent_count_list_list) grid.parent_window.assert_valid() return grid.parent_grid_uuid
def _load_related_wellbore_interp(self): """Return related wellbore interp object from XML if present.""" interp_uuid = rqet.find_nested_tags_text(self.root, ['RepresentedInterpretation', 'UUID']) if interp_uuid is None: represented_interp = None else: represented_interp = rqo.WellboreInterpretation(self.model, uuid = interp_uuid) return represented_interp
def recursive_uuid_set(node): uuid_set = set() for child in node: uuid_set = uuid_set.union(recursive_uuid_set(child)) if rqet.node_type(node) == 'Hdf5Dataset': h5_uuid = bu.uuid_from_string( rqet.find_nested_tags_text(node, ['HdfProxy', 'UUID'])) uuid_set.add(h5_uuid) return uuid_set
def _process_simple_types(schema, simple_types): for simpleton in rqet.list_of_tag(schema, 'simpleType'): name = simpleton.attrib['name'] doc = rqet.find_nested_tags_text(simpleton, ['annotation', 'documentation']) restriction = rqet.find_tag(simpleton, 'restriction') restrict = None if restriction is None else rqet.stripped_of_prefix( restriction.attrib['base']) value_list = [] enum_list = rqet.list_of_tag(restriction, 'enumeration') if enum_list is not None: for enumeration in enum_list: value = enumeration.attrib['value'] v_doc = rqet.find_nested_tags_text( enumeration, ['annotation', 'documentation']) if v_doc is not None: v_doc = str(v_doc).replace('\n', ' ') value_list.append((value, v_doc)) simple_types[name] = (restrict, value_list, doc)
def _h5_uuid_and_path_for_node(model, node, tag='Values'): """Returns a (hdf5_uuid, hdf5_internal_path) pair for an xml array node.""" child = rqet.find_tag(node, tag) if child is None: return None assert rqet.node_type(child) == 'Hdf5Dataset' h5_path = rqet.find_tag(child, 'PathInHdfFile').text h5_uuid = bu.uuid_from_string( rqet.find_nested_tags_text(child, ['HdfProxy', 'UUID'])) return (h5_uuid, h5_path)
def __create_wellbore_interpretation_ref_node(self, ds_node): """Create a reference node for the WellboreInterpretation object and add to the DeviationSurvey root node. """ interp_root = None if self.wellbore_interpretation is not None: interp_root = self.wellbore_interpretation.root self.model.create_ref_node('RepresentedInterpretation', rqet.find_nested_tags_text(interp_root, ['Citation', 'Title']), bu.uuid_from_string(interp_root.attrib['uuid']), content_type = 'obj_WellboreInterpretation', root = ds_node) return interp_root
def _create_crs_reference(model, root=None, crs_uuid=None): """Creates a node refering to an existing crs node and optionally adds as child of root.""" assert crs_uuid is not None crs_root = model.root_for_uuid(crs_uuid) assert crs_root is not None return _create_ref_node('LocalCrs', rqet.find_nested_tags_text(crs_root, ['Citation', 'Title']), crs_uuid, content_type='obj_LocalDepth3dCrs', root=root)
def _load_from_xml(self): """Loads the wellbore frame object from an xml node (and associated hdf5 data).""" # NB: node is the root level xml node, not a node in the md list! node = self.root assert node is not None trajectory_uuid = bu.uuid_from_string( rqet.find_nested_tags_text(node, ['Trajectory', 'UUID'])) assert trajectory_uuid is not None, 'wellbore frame trajectory reference not found in xml' if self.trajectory is None: self.trajectory = resqpy.well.Trajectory(self.model, uuid=trajectory_uuid) else: assert bu.matching_uuids( self.trajectory.uuid, trajectory_uuid), 'wellbore frame trajectory uuid mismatch' self.node_count = rqet.find_tag_int(node, 'NodeCount') assert self.node_count is not None, 'node count not found in xml for wellbore frame' assert self.node_count > 1, 'fewer than 2 nodes for wellbore frame' mds_node = rqet.find_tag(node, 'NodeMd') assert mds_node is not None, 'wellbore frame measured depths hdf5 reference not found in xml' load_hdf5_array(self, mds_node, 'node_mds') assert self.node_mds is not None and self.node_mds.ndim == 1 and self.node_mds.size == self.node_count interp_uuid = rqet.find_nested_tags_text( node, ['RepresentedInterpretation', 'UUID']) if interp_uuid is None: self.wellbore_interpretation = None else: self.wellbore_interpretation = rqo.WellboreInterpretation( self.model, uuid=interp_uuid) # Create well log collection of all log data self.logs = rqp.WellLogCollection(frame=self)
def _load_from_xml(self): assert self.root is not None self.patch_count = rqet.count_tag(self.root, 'NodePatch') assert self.patch_count, 'no patches found in xml for point set' self.patch_array_list = [None for _ in range(self.patch_count)] patch_index = 0 for child in rqet.list_of_tag(self.root, 'NodePatch'): point_count = rqet.find_tag_int(child, 'Count') geom_node = rqet.find_tag(child, 'Geometry') assert geom_node is not None, 'geometry missing in xml for point set patch' crs_uuid = rqet.find_nested_tags_text(geom_node, ['LocalCrs', 'UUID']) assert crs_uuid, 'crs uuid missing in geometry xml for point set patch' self.check_crs_match(crs_uuid) ext_uuid = rqet.find_nested_tags_text(geom_node, ['Points', 'Coordinates', 'HdfProxy', 'UUID']) assert ext_uuid, 'missing hdf5 uuid in geometry xml for point set patch' hdf5_path = rqet.find_nested_tags_text(geom_node, ['Points', 'Coordinates', 'PathInHdfFile']) assert hdf5_path, 'missing internal hdf5 path in geometry xml for point set patch' self.patch_ref_list.append((ext_uuid, hdf5_path, point_count)) patch_index += 1 ref_node = rqet.find_tag(self.root, 'RepresentedInterpretation') if ref_node is not None: interp_root = self.model.referenced_node(ref_node) self.set_represented_interpretation_root(interp_root)
def extract_children(grid): """Looks for LGRs related to this grid and sets the local_grid_uuid_list attribute.""" assert grid.uuid is not None if grid.local_grid_uuid_list is not None: return grid.local_grid_uuid_list grid.local_grid_uuid_list = [] related_grid_roots = grid.model.roots(obj_type = 'IjkGridRepresentation', related_uuid = grid.uuid) if related_grid_roots is not None: for related_root in related_grid_roots: parent_uuid = rqet.find_nested_tags_text(related_root, ['ParentWindow', 'ParentGrid', 'UUID']) if parent_uuid is None: continue parent_uuid = bu.uuid_from_string(parent_uuid) if bu.matching_uuids(grid.uuid, parent_uuid): grid.local_grid_uuid_list.append(parent_uuid) return grid.local_grid_uuid_list
def __create_wellbore_interpretation_reference_node(self, wbt_node): """Create a reference node to a WellboreInterpretation object and append it to the WellboreTrajectory object's root node. """ interp_root = None if self.wellbore_interpretation is not None: interp_root = self.wellbore_interpretation.root self.model.create_ref_node( 'RepresentedInterpretation', rqet.find_nested_tags_text(interp_root, ['Citation', 'Title']), bu.uuid_from_string(interp_root.attrib['uuid']), content_type='obj_WellboreInterpretation', root=wbt_node) return interp_root
def extract_geometry_time_index(grid): """Returns integer time index, or None, for the grid geometry, as stored in xml for dynamic geometries. notes: if the value is not None, it represents the time index as stored in the xml, or the time index as updated when setting the node points from a points property """ if grid.time_index is not None and grid.time_series_uuid is not None: return grid.time_index grid.time_index = None grid.time_series_uuid = None ti_node = grid.resolve_geometry_child('TimeIndex') if ti_node is None: return None grid.time_index = rqet.find_tag_int(ti_node, 'Index') grid.time_series_uuid = bu.uuid_from_string(rqet.find_nested_tags_text(ti_node, ['TimeSeries', 'UUID'])) return grid.time_index
def _sort_parts_list_by_timestamp(model, parts_list): """Returns a copy of the parts list sorted by citation block creation date, with the newest first.""" if parts_list is None: return None if len(parts_list) == 0: return [] sort_list = [] for index, part in enumerate(parts_list): timestamp = rqet.find_nested_tags_text(_root_for_part(model, part), ['Citation', 'Creation']) sort_list.append((timestamp, index)) sort_list.sort() results = [] for timestamp, index in reversed(sort_list): results.append(parts_list[index]) return results
def __create_xml_basics(self, g2d_node): if self.represented_interpretation_root is not None: interp_root = self.represented_interpretation_root interp_uuid = bu.uuid_from_string(interp_root.attrib['uuid']) interp_part = self.model.part_for_uuid(interp_uuid) self.model.create_ref_node( 'RepresentedInterpretation', rqet.find_nested_tags_text(interp_root, ['Citation', 'Title']), interp_uuid, content_type=self.model.type_of_part(interp_part), root=g2d_node) role_node = rqet.SubElement(g2d_node, ns['resqml2'] + 'SurfaceRole') role_node.set(ns['xsi'] + 'type', ns['resqml2'] + 'SurfaceRole') role_node.text = self.surface_role patch_node = rqet.SubElement(g2d_node, ns['resqml2'] + 'Grid2dPatch') patch_node.set(ns['xsi'] + 'type', ns['resqml2'] + 'Grid2dPatch') patch_node.text = '\n' pi_node = rqet.SubElement(patch_node, ns['resqml2'] + 'PatchIndex') pi_node.set(ns['xsi'] + 'type', ns['xsd'] + 'nonNegativeInteger') pi_node.text = '0' fast_node = rqet.SubElement(patch_node, ns['resqml2'] + 'FastestAxisCount') fast_node.set(ns['xsi'] + 'type', ns['xsd'] + 'positiveInteger') fast_node.text = str(self.ni) slow_node = rqet.SubElement(patch_node, ns['resqml2'] + 'SlowestAxisCount') slow_node.set(ns['xsi'] + 'type', ns['xsd'] + 'positiveInteger') slow_node.text = str(self.nj) geom = rqet.SubElement(patch_node, ns['resqml2'] + 'Geometry') geom.set(ns['xsi'] + 'type', ns['resqml2'] + 'PointGeometry') geom.text = '\n' self.model.create_crs_reference(crs_uuid=self.crs_uuid, root=geom) p_node = rqet.SubElement(geom, ns['resqml2'] + 'Points') p_node.text = '\n' return p_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 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 extract_stratigraphy(grid): """Loads stratigraphic information from xml.""" grid.stratigraphic_column_rank_uuid = None grid.stratigraphic_units = None strata_node = rqet.find_tag(grid.root, 'IntervalStratigraphicUnits') if strata_node is None: return grid.stratigraphic_column_rank_uuid = \ bu.uuid_from_string(rqet.find_nested_tags_text(strata_node, ['StratigraphicOrganization', 'UUID'])) assert grid.stratigraphic_column_rank_uuid is not None unit_indices_node = rqet.find_tag(strata_node, 'UnitIndices') h5_key_pair = grid.model.h5_uuid_and_path_for_node(unit_indices_node) grid.model.h5_array_element(h5_key_pair, index = None, cache_array = True, object = grid, array_attribute = 'stratigraphic_units', dtype = 'int') assert len(grid.stratigraphic_units) == grid.nk_plus_k_gaps