Source code for geoh5py.data.visual_parameters

#  Copyright (c) 2024 Mira Geoscience Ltd.
#
#  This file is part of geoh5py.
#
#  geoh5py is free software: you can redistribute it and/or modify
#  it under the terms of the GNU Lesser General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  geoh5py is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU Lesser General Public License for more details.
#
#  You should have received a copy of the GNU Lesser General Public License
#  along with geoh5py.  If not, see <https://www.gnu.org/licenses/>.


from __future__ import annotations

import xml.etree.ElementTree as ET

import numpy as np

from .data_association_enum import DataAssociationEnum
from .text_data import TextData


PARAMETERS = ["Colour"]
ATTRIBUTES = ["tag", "text", "attrib"]


[docs] class VisualParameters(TextData): _xml: ET.Element | None = None _association = DataAssociationEnum.OBJECT @property def xml(self) -> ET.Element: """ :obj:`str` XML string. """ if self._xml is None: if isinstance(self.values, str): str_xml = self.values else: str_xml = """ <IParameterList Version="1.0"> </IParameterList> """ self._xml = ET.fromstring(str_xml) return self._xml @property def values(self) -> str | None: if self._xml is not None: self._values = ET.tostring(self._xml, encoding="unicode") elif (getattr(self, "_values", None) is None) and self.on_file: values = self.workspace.fetch_values(self) if isinstance(values, (np.ndarray, str, type(None))): self._values = values return self._values @values.setter def values(self, values: np.ndarray | str | None): if not isinstance(values, (np.ndarray, str, type(None))): raise ValueError( f"Input 'values' for {self} must be of type {np.ndarray} str or None." ) self._values = values self.workspace.update_attribute(self, "values") @property def colour(self) -> None | list: """ Colour of the object in [Red, Green, Blue] format. Each value is an integer between 0 and 255. The colour value is stored as a single integer converted from a byte string of the form 'RRGGBB' where 'BB' is the blue value, 'GG' is the green value, 'RR' is the red converted from hexadecimal format. """ element = self.get_tag("Colour") if element is None or not element.text: return None c_string = (int(element.text)).to_bytes(4, byteorder="little").hex() return [int(c_string[i : i + 2], 16) for i in range(0, 8, 2)][:3] @colour.setter def colour(self, rgb: list | tuple | np.ndarray): if ( not isinstance(rgb, (list, tuple, np.ndarray)) or len(rgb) != 3 or not all(isinstance(val, int) for val in rgb) ): raise TypeError("Input 'colour' values must be a list of 3 integers.") byte_string = "".join(f"{val:02x}" for val in rgb) byte_string.join(f"{255:02x}") # alpha value value = int.from_bytes(bytes.fromhex(byte_string), "little") self.set_tag("Colour", str(value))
[docs] def get_tag(self, tag: str) -> None | ET.Element: """ Recover the tag element. :param tag: The name of the tag. :return: The xml element. """ element = self.xml.find(tag) return element # type: ignore
[docs] def set_tag(self, tag: str, value: str): """ Set the value for the tag. :param tag: The name of the tag. :param value: the value to set. """ if not isinstance(value, str): raise TypeError( f"Input 'value' for VisualParameters.{tag} must be of type {str}." ) if self.xml.find(tag) is None: ET.SubElement(self.xml, tag) element = self.get_tag(tag) if element is not None: element.text = value self.workspace.update_attribute(self, "values")