Properties and regions¶
GeoLime Objects have two types of attribute :
Property
Property consists in information on the object about a certain caracteristic. It can be continuous, such as a grade variable, or discrete, such a lithology variable.
Region
Region consists in boolean information on the object, allowing filtering and masking. Values of a region are either
TrueorFalse. For example a region named"orebody"can be created on a Drillholes objet where each value equals True if the composite lies in the Solid of the orebody and False if the composite lies outside the Solid of the orebody.Region does not necesseraly be spatial, region can also be based on property value, for example a region consisting of the grade higher than a specific threshold.
Assume the following examples will use these imports and the dh object.
import geolime as geo
import numpy as np
from pint import Unit
dh = geo.datasets.load(data_name="rocklea_dome/dh_hyper.geo")
Creating properties¶
Fundamentals¶
A property can be created from a sequence (list, numpy ndarray...), a numerical value (int, float), a string or another existing properties.
To create a new property, use the method set_property as the followed examples:
- From Sequences
Initialize a numpy ndarray:
density_array = np.ones(7134) * 2.4
density_array
array([2.4, 2.4, 2.4, ..., 2.4, 2.4, 2.4])
Create a new property "density" from the numpy array:
dh.set_property(name="density_1", data=density_array)
dh.data("density_1")
array([2.4, 2.4, 2.4, ..., 2.4, 2.4, 2.4])
- From numerical values & strings
In previous example, a property was created from a sequence filled with the same value. An easier approach exists by using int or float data:
dh.set_property(name="density_2", data=2.4)
dh.data("density_2")
array([2.4, 2.4, 2.4, ..., 2.4, 2.4, 2.4])
The numerical value can also be embedded in a string:
dh.set_property(name="density_3", data="2.4")
dh.data("density_3")
array([2.4, 2.4, 2.4, ..., 2.4, 2.4, 2.4])
If the data value needs to be register as a string, use backquotes as follow:
dh.set_property(name="density_4", data="'2.4'") # or '"2.4"'
dh.data("density_4")
array(['2.4', '2.4', '2.4', ..., '2.4', '2.4', '2.4'], dtype=object)
dh.set_property(name="lithology_1", data="'channel'") # or '"channel"'
dh.data("lithology_1")
array(['channel', 'channel', 'channel', ..., 'channel', 'channel',
'channel'], dtype=object)
In the same way, it is possible to initialize an empty property:
dh.set_property(name="High_Fe_1", data="nan")
dh.data("High_Fe_1")
array([nan, nan, nan, ..., nan, nan, nan])
- From existing properties
It is possible to create a new property by combining different other existing properties. In this case, the data value is an expression.
For example, substracting the values of two properties:
dh.data("TO")
array([1., 2., 3., ..., 1., 1., 1.])
dh.set_property(name="composite_thickness_1", data="TO - FROM")
dh.data("composite_thickness_1")
array([1., 1., 1., ..., 1., 1., 1.])
- Shortcuts alternative
A simpler way to create a new property, is to use the shortcuts: Property can be set and accessed using the subscript shortcut [], allowing to set easily properties from any kind of the compatible entry types.
Numerical value:
dh["density_5"] = 2.4
dh["density_5"]
array([2.4, 2.4, 2.4, ..., 2.4, 2.4, 2.4])
String:
dh["lithology_2"] = "'channel'"
dh["lithology_2"]
array(['channel', 'channel', 'channel', ..., 'channel', 'channel',
'channel'], dtype=object)
Expression:
dh["composite_thickness_2"] = "TO - FROM"
dh["composite_thickness_2"]
array([1., 1., 1., ..., 1., 1., 1.])
Using region to create/update properties¶
Region or condition act as filters and are used to update properties at certain location:
- Create a property and update it by adding a region and associated data.
- Create a property with an expression, a region and a default value for each point would be outside.
1. Update an existing property by adding a region
Create a new property using a formula relating two existing properties:
dh.set_property(name="calcined_iron", data="Fe_pct / (100 - LOI)")
dh.describe("calcined_iron")
count 4979.000000 mean 0.357367 std 0.201023 min 0.000000 25% 0.157640 50% 0.393473 75% 0.546897 max 0.662847 Name: calcined_iron, dtype: float64
Ore might contains residual moisture and correction needs to be applied to low grade in order to avoid overestimation. Calcined iron value is therefore updated only in low iron value
dh.update_property(name="calcined_iron", data="calcined_iron * 0.9", region="Fe_pct < 5")
np.nanmean(dh["calcined_iron"])
0.3571805259571685
Of course, it works with single value or expression:
dh.set_property(name="calcined_iron_2", data=0.36)
dh.update_property(name="calcined_iron_2", data="0.9 * calcined_iron_2", region="Fe_pct < 5")
2. With default value
Another way, it is possible to create directly a new property with a region and an associated default value.
This alternative works only with expression using existing properties.
If values from expression are not contained in the given region, the default value is used.
dh.set_property(name="High_Fe", data="Fe_pct", region="Fe_pct > 30", default="nan")
np.nanmin(dh.data("High_Fe"))
31.0
Other and advanced options¶
1. Property kind
Add an optional description of the property's kind:
geo.PropertyKind._member_names_
['USER_DEFINED', 'GEOMETRY', 'INDEX', 'LENGTH', 'HEIGHT', 'GRADE', 'ANGLE', 'LABEL']
Used to categorize the kind of a property associated to the GeoLime objects:
dh.set_property(
name="composite_thickness",
data="TO - FROM",
kind=geo.PropertyKind.LENGTH
)
dh.property("composite_thickness")
ObjectProperty └─data() └─dynamic ⇨ False └─expr ⇨ TO - FROM └─kind ⇨ LENGTH └─name ⇨ composite_thickness └─read_only ⇨ False └─unit ⇨ None
2. Unit
A Pint Unit object that defines the unit of the property:
dh.set_property(
name="High_Fe_2",
data="Fe_pct",
region="Fe_pct > 30",
default=np.nan,
unit=Unit("%")
)
dh.property("High_Fe_2")
ObjectProperty └─data() └─dynamic ⇨ False └─expr ⇨ Fe_pct └─kind ⇨ None └─name ⇨ High_Fe_2 └─read_only ⇨ False └─unit ⇨ percent
3. Read only
Once a property is tagged as read_only=True, it cannot be modified, but it can be removed:
dh.set_property(
name="High_Fe_read_only",
data="Fe_pct",
region="Fe_pct > 30",
default=np.nan,
read_only=True
)
dh.update_property(
name="High_Fe_read_only",
data="Fe_pct",
region="Fe_pct > 50",
)
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[21], line 9 1 dh.set_property( 2 name="High_Fe_read_only", 3 data="Fe_pct", (...) 6 read_only=True 7 ) ----> 9 dh.update_property( 10 name="High_Fe_read_only", 11 data="Fe_pct", 12 region="Fe_pct > 50", 13 ) File ~/Documents/jupylime/geolime/objects/object_mixin.py:859, in ObjectMixin.update_property(self, name, data, region, support) 856 raise ValueError(f"{name} does not exist.") 858 if isinstance(data, (str, int, float)): --> 859 db.set_property_expr(name, data, region=region) 860 else: 861 db.set_property_data(name, data, True, region=region) File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:40, in pydantic.decorator.validate_arguments.validate.wrapper_function() File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:134, in pydantic.decorator.ValidatedFunction.call() File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:206, in pydantic.decorator.ValidatedFunction.execute() File ~/Documents/jupylime/geolime/schema/object_db.py:685, in ObjectDB.set_property_expr(self, name, expr, dynamic, kind, unit, read_only, region, default) 677 raise ValueError(strip_extra_ws(f""" 678 Property {name} cannot be created in region {region}. 679 The region parameter must be used in combination with the default parameter. 680 """)) 682 # check if the attribute exists 683 # - if not, create it 684 # - if yes, ensure it is a property not read-only and overwrite it, otherwise raise error --> 685 self._check_attribute(name, ObjectProperty) 687 if region is None: 688 self._data.eval( 689 f"{name} = {expr}", 690 inplace=True, 691 resolvers=[{"NaN": np.float64(np.nan)}, {"nan": np.float64(np.nan)}] 692 ) File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:40, in pydantic.decorator.validate_arguments.validate.wrapper_function() File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:134, in pydantic.decorator.ValidatedFunction.call() File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:206, in pydantic.decorator.ValidatedFunction.execute() File ~/Documents/jupylime/geolime/schema/object_db.py:578, in ObjectDB._check_attribute(self, name, instance) 573 raise ValueError(strip_extra_ws(f""" 574 [{str(self)}] {name} exists on object {self.object.name} 575 but is not a {cls_name} 576 """)) 577 elif self.__attributes[name].read_only: --> 578 raise ValueError(strip_extra_ws(f""" 579 [{str(self)}] {cls_name.capitalize()} {name} exists on object {self.object.name} 580 but is read-only 581 """)) ValueError: [ObjectTopology] Property High_Fe_read_only exists on object rck_hs but is read-only
4. Dynamic
Set to True to have property values recomputed each time the data is requested. Dynamic properties need to be create with an expression.
Create a property moisture_content from a single of value. Then, create is the corrected iron value Fe_pct_corected accounting for the moisture content:
dh.set_property(
name="moisture_content",
data=3,
unit=Unit("%")
)
dh.set_property(
name="Fe_pct_corrected",
data="Fe_pct * moisture_content",
unit=Unit("%"),
dynamic=True
)
np.nanmean(dh["Fe_pct_corrected"])
94.91696750902527
When moisture_content is updated, the values inside Fe_pct_corrected change too:
dh.update_property(
name="moisture_content",
data=12,
)
np.nanmean(dh["Fe_pct_corrected"])
379.6678700361011
5. Support
Used to defined the type of support of property. In other words, it allows you to specify whether a property is defined at the node level or the element level. For example a GridObject can have properties at the cell level or at the node level.
geo.AttributeSupportType._member_names_
['NODE', 'ELEMENT']
Creating regions¶
Fundamentals¶
A region can be created from a sequence of booleans (list, numpy ndarray...), or another existing properties (expression).
To create a new region, use the method set_region as the followed examples:
- From Sequences
Initialize a numpy ndarray of booleans:
values = dh['Fe_pct'] < 30
values
array([False, False, False, ..., False, False, False])
Create a new property "low_grade_Fe" from the numpy array:
dh.set_region(name="low_grade_Fe", data=values)
dh.region("low_grade_Fe")
ObjectRegion └─data() └─dynamic ⇨ False └─expr ⇨ None └─name ⇨ low_grade_Fe └─read_only ⇨ False
- From existing properties
It is possible to create a new region by combining different other existing properties. In this case, the data value is an expression.
dh.set_region(name="Fe_lt_30", data="Fe_pct < 30")
dh.region("Fe_lt_30")
ObjectRegion └─data() └─dynamic ⇨ False └─expr ⇨ Fe_pct < 30 └─name ⇨ Fe_lt_30 └─read_only ⇨ False
- Using numpy when condition thickens
dh.set_region(name="Fe_lt_5", data="Fe_pct < 5")
dh.set_region(name="SiO2_gt_25", data="SiO2_pct > 25")
fe_high_silica_array = np.where(
dh["SiO2_gt_25"] & dh["Fe_lt_5"],
5,
dh["Fe_pct"]
)
dh.set_property(name="iron_high_silica", data=fe_high_silica_array)
Other and advanced options¶
1. Read only
Once a property is tagged as read_only=True, it cannot be modified but it can be removed:
values = dh['Fe_pct'] < 30
dh.set_region(
name="density_region_2",
data=values,
read_only=True
)
dh.update_region(
name="density_region_2",
data=values
)
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[29], line 9 1 values = dh['Fe_pct'] < 30 3 dh.set_region( 4 name="density_region_2", 5 data=values, 6 read_only=True 7 ) ----> 9 dh.update_region( 10 name="density_region_2", 11 data=values 12 ) File ~/Documents/jupylime/geolime/objects/object_mixin.py:899, in ObjectMixin.update_region(self, name, data, region, support) 897 db.set_region_condition(name, data, region=region) 898 else: --> 899 db.set_region_data(name, data, True, region=region) File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:40, in pydantic.decorator.validate_arguments.validate.wrapper_function() File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:134, in pydantic.decorator.ValidatedFunction.call() File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:206, in pydantic.decorator.ValidatedFunction.execute() File ~/Documents/jupylime/geolime/schema/object_db.py:744, in ObjectDB.set_region_data(self, name, data, update_only, read_only, region) 739 if update_only and name not in self.__attributes: 740 raise ValueError(strip_extra_ws(f""" 741 [{str(self)}] Attribute {name} does not exist on object {self.object.name} 742 """)) --> 744 self._check_attribute(name, ObjectRegion) 746 # force conversion as boolean if not already boolean 747 self.__set_data(name, data.astype(bool), region) File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:40, in pydantic.decorator.validate_arguments.validate.wrapper_function() File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:134, in pydantic.decorator.ValidatedFunction.call() File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:206, in pydantic.decorator.ValidatedFunction.execute() File ~/Documents/jupylime/geolime/schema/object_db.py:578, in ObjectDB._check_attribute(self, name, instance) 573 raise ValueError(strip_extra_ws(f""" 574 [{str(self)}] {name} exists on object {self.object.name} 575 but is not a {cls_name} 576 """)) 577 elif self.__attributes[name].read_only: --> 578 raise ValueError(strip_extra_ws(f""" 579 [{str(self)}] {cls_name.capitalize()} {name} exists on object {self.object.name} 580 but is read-only 581 """)) ValueError: [ObjectTopology] Region density_region_2 exists on object rck_hs but is read-only
2. Dynamic
Set to True to have region values recomputed each time the data is requested. Dynamic region need to be create with an expression.
dh.set_region(name="wet", data="moisture_content < 10", dynamic=True)
dh.region("wet").data()
array([False, False, False, ..., False, False, False])
dh.update_property(name="moisture_content", data="7")
dh.region("wet").data()
array([ True, True, True, ..., True, True, True])
3. Region
The region parameter allows you to restrict the application of the condition to a region that already exists in the object.
Select all intervals where Fe_pct > 50.
dh.set_region(name="OreZone", data="Fe_pct > 50")
Select the intervals already in OreZone where Si02_pct > 10.
dh.set_region(
name="HighSilicaInOre",
data="SiO2_pct > 10",
region="OreZone"
)
Properties and regions updating¶
Once a property or a region is created, it can only be updated or removed. This mechanism prevents any data overriding.
Trying to recreate an existing property will raise an error:
dh.set_property(
name="comp_thickness",
data="TO - FROM",
kind=geo.PropertyKind.LENGTH,
unit=Unit("m")
)
dh.set_property(name="comp_thickness", data="(TO - FROM) / 2")
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[34], line 8 1 dh.set_property( 2 name="comp_thickness", 3 data="TO - FROM", 4 kind=geo.PropertyKind.LENGTH, 5 unit=Unit("m") 6 ) ----> 8 dh.set_property(name="comp_thickness", data="(TO - FROM) / 2") File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:40, in pydantic.decorator.validate_arguments.validate.wrapper_function() File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:134, in pydantic.decorator.ValidatedFunction.call() File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:206, in pydantic.decorator.ValidatedFunction.execute() File ~/Documents/jupylime/geolime/objects/object_mixin.py:724, in ObjectMixin.set_property(self, name, data, kind, unit, read_only, support, region, default, dynamic) 721 db = self._get_db(support) 723 if name in self.properties(support): --> 724 raise ValueError(f"{name} already exists. It only can be updated or removed.") 726 if not isinstance(data, str) and dynamic: 727 warning(strip_extra_ws(""" 728 'dynamic' parameter is only intended to be used for properties 729 that store string expression. 730 """)) ValueError: comp_thickness already exists. It only can be updated or removed.
To change the values inside the property, use the method update_property:
dh.update_property(name="comp_thickness", data="(TO - FROM) / 2")
dh.property("comp_thickness").data()
array([0.5, 0.5, 0.5, ..., 0.5, 0.5, 0.5])
Of course, it works exactly the same for regions:
dh.set_region(name="Fe_below_30", data="Fe_pct < 30")
dh.set_region(name="Fe_below_30", data="Fe_pct < 50")
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[36], line 2 1 dh.set_region(name="Fe_below_30", data="Fe_pct < 30") ----> 2 dh.set_region(name="Fe_below_30", data="Fe_pct < 50") File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:40, in pydantic.decorator.validate_arguments.validate.wrapper_function() File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:134, in pydantic.decorator.ValidatedFunction.call() File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:206, in pydantic.decorator.ValidatedFunction.execute() File ~/Documents/jupylime/geolime/objects/object_mixin.py:807, in ObjectMixin.set_region(self, name, data, read_only, support, region, dynamic) 805 db = self._get_db(support) 806 if name in self.regions(support): --> 807 raise ValueError(f"{name} already exists. It only can be updated or removed.") 809 if not isinstance(data, str) and dynamic: 810 warning(strip_extra_ws(""" 811 'dynamic' parameter is only intended to be used for regions that store expression. 812 """)) ValueError: Fe_below_30 already exists. It only can be updated or removed.
dh.update_region(name="Fe_below_30", data="Fe_pct < 50")
dh.region("Fe_below_30").data()
array([False, False, False, ..., False, False, False])
To check if a property or a region already exists, use the following commands:
dh.property("comp_thickness")
ObjectProperty └─data() └─dynamic ⇨ False └─expr ⇨ (TO - FROM) / 2 └─kind ⇨ None └─name ⇨ comp_thickness └─read_only ⇨ False └─unit ⇨ None
dh.region("no_reg", return_none=False)
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[39], line 1 ----> 1 dh.region("no_reg", return_none=False) File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:40, in pydantic.decorator.validate_arguments.validate.wrapper_function() File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:134, in pydantic.decorator.ValidatedFunction.call() File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:206, in pydantic.decorator.ValidatedFunction.execute() File ~/Documents/jupylime/geolime/objects/object_mixin.py:543, in ObjectMixin.region(self, name, support, return_none) 500 """ 501 Return the object region for the given name for the given support type. 502 The support databased are disjoints, so it is possible to have regions carried by (...) 540 541 """ 542 db = self._get_db(support) --> 543 return db.get_region(name, return_none) File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:40, in pydantic.decorator.validate_arguments.validate.wrapper_function() File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:134, in pydantic.decorator.ValidatedFunction.call() File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:206, in pydantic.decorator.ValidatedFunction.execute() File ~/Documents/jupylime/geolime/schema/object_db.py:954, in ObjectDB.get_region(self, name, return_none) 933 @check_type 934 def get_region( 935 self, 936 name: str, 937 return_none: bool = False 938 ) -> ObjectRegion: 939 """ 940 Return the object region associated to the given name. 941 (...) 952 953 """ --> 954 attribute = self.get_attribute(name, return_none) 955 if (attribute is None and not return_none) or \ 956 (attribute is not None and not isinstance(attribute, ObjectRegion)): 957 raise ValueError(strip_extra_ws(f""" 958 [{str(self)}] {name} is not a region on object {self.object.name} 959 """)) File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:40, in pydantic.decorator.validate_arguments.validate.wrapper_function() File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:134, in pydantic.decorator.ValidatedFunction.call() File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:206, in pydantic.decorator.ValidatedFunction.execute() File ~/Documents/jupylime/geolime/schema/object_db.py:897, in ObjectDB.get_attribute(self, name, return_none) 895 return None 896 else: --> 897 raise ValueError(strip_extra_ws(f""" 898 [{str(self)}] No property or region {name} exists on object {self.object.name} 899 """)) 901 return self.__attributes[name] ValueError: [ObjectTopology] No property or region no_reg exists on object rck_hs
To avoid error when checking if a region exist, we can use the return_none parameter, which will return None instead.
dh.region("no_reg", return_none=True)
Properties and regions renaming¶
To rename properties, regions, or attributes for an object, use the rename_property and rename_region methods. These methods accept a dictionary as an argument, allowing you to rename multiple properties or regions simultaneously.
Using the renaming methods we can rename the created attributes to have more meaningful names.
dh.rename_property(names={"moisture_content": "moisture"})
dh.rename_region(names={"Fe_below_30": "Fe_lt_30"})
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In[41], line 2 1 dh.rename_property(names={"moisture_content": "moisture"}) ----> 2 dh.rename_region(names={"Fe_below_30": "Fe_lt_30"}) File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:40, in pydantic.decorator.validate_arguments.validate.wrapper_function() File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:134, in pydantic.decorator.ValidatedFunction.call() File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:206, in pydantic.decorator.ValidatedFunction.execute() File ~/Documents/jupylime/geolime/objects/object_mixin.py:1013, in ObjectMixin.rename_region(self, names, support) 1011 db = self._get_db(support) 1012 for current_name, new_name in names.items(): -> 1013 db.rename_region(current_name, new_name) File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:40, in pydantic.decorator.validate_arguments.validate.wrapper_function() File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:134, in pydantic.decorator.ValidatedFunction.call() File ~/.virtualenvs/geolime_310/lib/python3.10/site-packages/pydantic/decorator.py:206, in pydantic.decorator.ValidatedFunction.execute() File ~/Documents/jupylime/geolime/schema/object_db.py:1108, in ObjectDB.rename_region(self, current_name, new_name) 1094 """ 1095 Args: 1096 current_name: the current name of the region. (...) 1105 1106 """ 1107 if new_name in self.__attributes: -> 1108 raise ValueError(f"Region {new_name} already exists") 1110 self._check_attribute(current_name, ObjectRegion) 1111 self._check_attribute(new_name, ObjectRegion) ValueError: Region Fe_lt_30 already exists
Properties and regions removing¶
To remove properties, regions, or attributes from an object, use the remove_property and remove_region methods. For greater efficiency when removing multiple properties or regions, pass a list of names to the method instead of calling it repeatedly in a loop.
dh.remove_property(names="density_2")
dh.remove_region(names="Fe_lt_30")
Acces to attribute data and objects¶
Existing properties and regions¶
Show properties and regions as pandas DataFrame representation:
dh.to_dataframe()
| __TOPO_LEVEL__ | __TOPO_TYPE__ | __TOPO_ELEMENT_V1__ | __TOPO_ELEMENT_V2__ | FROM | TO | HOLEID | X_COLLAR | Y_COLLAR | Z_COLLAR | ... | Fe_lt_5 | SiO2_gt_25 | iron_high_silica | density_region_2 | wet | OreZone | HighSilicaInOre | comp_thickness | Fe_below_30 | moisture | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2 | 1 | 0 | 1 | 0.0 | 1.0 | RKC278 | 548001.3 | 7474002.1 | 453.5 | ... | False | False | NaN | False | True | False | False | 0.5 | False | 7 |
| 1 | 2 | 1 | 1 | 2 | 1.0 | 2.0 | RKC278 | 548001.3 | 7474002.1 | 453.5 | ... | False | False | NaN | False | True | False | False | 0.5 | False | 7 |
| 2 | 2 | 1 | 2 | 3 | 2.0 | 3.0 | RKC278 | 548001.3 | 7474002.1 | 453.5 | ... | False | False | NaN | False | True | False | False | 0.5 | False | 7 |
| 3 | 2 | 1 | 3 | 4 | 3.0 | 4.0 | RKC278 | 548001.3 | 7474002.1 | 453.5 | ... | False | False | NaN | False | True | False | False | 0.5 | False | 7 |
| 4 | 2 | 1 | 4 | 5 | 4.0 | 5.0 | RKC278 | 548001.3 | 7474002.1 | 453.5 | ... | False | False | NaN | False | True | False | False | 0.5 | False | 7 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 7129 | 2 | 1 | 7319 | 7320 | 43.0 | 44.0 | RKC485 | 547913.3 | 7473917.2 | 452.4 | ... | False | True | 16.0 | True | True | False | False | 0.5 | True | 7 |
| 7130 | 2 | 1 | 7320 | 7321 | 44.0 | 45.0 | RKC485 | 547913.3 | 7473917.2 | 452.4 | ... | False | True | 12.0 | True | True | False | False | 0.5 | True | 7 |
| 7131 | 2 | 1 | 7322 | 7323 | 0.0 | 1.0 | RKD015 | 547905.0 | 7476800.0 | 470.0 | ... | False | False | NaN | False | True | False | False | 0.5 | False | 7 |
| 7132 | 2 | 1 | 7323 | 7324 | 0.0 | 1.0 | RKD015 | 547905.0 | 7476800.0 | 470.0 | ... | False | False | NaN | False | True | False | False | 0.5 | False | 7 |
| 7133 | 2 | 1 | 7324 | 7325 | 0.0 | 1.0 | RKD015 | 547905.0 | 7476800.0 | 470.0 | ... | False | False | NaN | False | True | False | False | 0.5 | False | 7 |
7134 rows × 66 columns
List every existing properties, including built-in and internal properties:
dh.properties()
['__TOPO_LEVEL__', '__TOPO_TYPE__', '__TOPO_ELEMENT_V1__', '__TOPO_ELEMENT_V2__', 'FROM', 'TO', 'HOLEID', 'X_COLLAR', 'Y_COLLAR', 'Z_COLLAR', 'X_M', 'Y_M', 'Z_M', 'X_B', 'Y_B', 'Z_B', 'X_E', 'Y_E', 'Z_E', 'Fe_pct', 'Al2O3', 'SiO2_pct', 'K2O_pct', 'CaO_pct', 'MgO_pct', 'TiO2_pct', 'P_pct', 'S_pct', 'Mn_pct', 'LOI', 'Fe_ox_ai', 'hem_over_goe', 'kaolin_abundance', 'kaolin_composition', 'wmAlsmai', 'wmAlsmci', 'carbai3pfit', 'carbci3pfit', 'Depth', 'density_1', 'density_3', 'density_4', 'lithology_1', 'High_Fe_1', 'composite_thickness_1', 'density_5', 'lithology_2', 'composite_thickness_2', 'calcined_iron', 'calcined_iron_2', 'High_Fe', 'composite_thickness', 'High_Fe_2', 'High_Fe_read_only', 'Fe_pct_corrected', 'iron_high_silica', 'comp_thickness', 'moisture']
List only properties created by the user:
dh.user_properties()
['X_COLLAR', 'Y_COLLAR', 'Z_COLLAR', 'X_M', 'Y_M', 'Z_M', 'X_B', 'Y_B', 'Z_B', 'X_E', 'Y_E', 'Z_E', 'Fe_pct', 'Al2O3', 'SiO2_pct', 'K2O_pct', 'CaO_pct', 'MgO_pct', 'TiO2_pct', 'P_pct', 'S_pct', 'Mn_pct', 'LOI', 'Fe_ox_ai', 'hem_over_goe', 'kaolin_abundance', 'kaolin_composition', 'wmAlsmai', 'wmAlsmci', 'carbai3pfit', 'carbci3pfit', 'Depth', 'density_1', 'density_3', 'density_4', 'lithology_1', 'High_Fe_1', 'composite_thickness_1', 'density_5', 'lithology_2', 'composite_thickness_2', 'calcined_iron', 'calcined_iron_2', 'High_Fe', 'composite_thickness', 'High_Fe_2', 'High_Fe_read_only', 'Fe_pct_corrected', 'iron_high_silica', 'comp_thickness', 'moisture']
List all existing regions:
dh.regions()
['low_grade_Fe', 'Fe_lt_5', 'SiO2_gt_25', 'density_region_2', 'wet', 'OreZone', 'HighSilicaInOre', 'Fe_below_30']
Get the data of a property¶
To simply access the data of a property, use the object that contains it as follows:
dh["kaolin_composition"]
array([0.999, 1.006, nan, ..., nan, nan, nan])
Data are returned in a numpy array, so all features from numpy are available, such as statistics computation, for example the mean elevation of the composites centers.
dh["Z_M"].mean()
437.4488505747126
Or the max elevation of the composites centers.
dh["Z_M"].max()
478.1
Extract data from condition¶
Data can also be extracted on specific region, here accessing the Fe values of composites lying below 437 meters.
dh.data(names="Fe_pct", region="Z_M < 437")
array([48., 40., 56., ..., 39., 16., 12.])
Multiple conditions can be used for the region selection, here adding a constraint on the silica in order to access quickly grades in zone with low silica.
dh.data(names="Fe_pct", region="(Z_M < 437) and (SiO2_pct < 20)")
array([48., 56., 55., ..., 47., 44., 43.])
Get the mask of a region¶
To access the mask of a region, represented as a boolean array
dh.region_mask(region="Fe_below_30")
array([False, False, False, ..., False, False, False])
Acces to the property object¶
Use the property method to get and access to the property object. Look at the API documentation to know all the attributes of ObjectAttribute and ObjectProperty.
For example let's extract the "Fe_pct" property
fe_prop = dh.property("Fe_pct")
Properties have multiple attributes
fe_prop
ObjectProperty └─data() └─dynamic ⇨ False └─expr ⇨ None └─kind ⇨ None └─name ⇨ Fe_pct └─read_only ⇨ False └─unit ⇨ None
For example unit can be set and accessed
fe_prop.unit
Properties can be marked as read_only, preventing them from being modified after creation. While built-in properties are read_only by default, user-created properties can also be set as read_only during their creation.
fe_prop.read_only
False
Data can also be accessed from a property object
fe_prop.data()
array([nan, nan, nan, ..., nan, nan, nan])
Rename the property:
fe_prop.name = "Fe_percent"
Acces to the region object¶
Use the region method to get and access to the region object. Look at the API documentation to know all the attributes of ObjectObjectRegion.
fe_pct_lt_30 = dh.region("Fe_below_30")
Checking the "expr" attributes allows to check if a region is an expression from other properties or if it was created providing directly an list of boolean values. Here the region was created using an expression.
fe_pct_lt_30.expr
'Fe_percent < 50'
Same as properties, regions can be read_only.
fe_pct_lt_30.read_only
False
Get the mask of the region:
fe_pct_lt_30.data()
array([False, False, False, ..., False, False, False])
Rename the region:
fe_pct_lt_30.name = "Fe_lt_30"
Generate descriptive statistics from one or more property data¶
Use the describe method from the object which owns the properties you want to observe. Pass a list of one or more property names as an argument.
dh.describe(["SiO2_pct", "Fe_ox_ai"])
| SiO2_pct | Fe_ox_ai | |
|---|---|---|
| count | 4986.000000 | 6920.000000 |
| mean | 28.268343 | 0.175605 |
| std | 19.818963 | 0.083948 |
| min | 2.380000 | 0.001300 |
| 25% | 11.132500 | 0.107000 |
| 50% | 22.565000 | 0.185500 |
| 75% | 42.497500 | 0.246000 |
| max | 92.810000 | 0.355000 |
Other features¶
Generate a random and unused name with the given prefix.
prefix = "my_property_"
dh.generate_attribute_name(prefix)
'my_property_b2482c'