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
True
orFalse
. 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
dh = geo.datasets.load(data_name="rocklea_dome/dh_hyper.geo")
Properties and regions creation¶
Create a property from data¶
First create an array of density values, here being 2.4 t/m3. The Drillholes object has 7134 composites, so let's create an array of the same size to associate the property to each composite.
density = np.ones(7134) * 2.4
And now create a property "density"
using the set_property
method and the created array. Note that list can also be used instead of Numpy arrays.
dh.set_property(name="density", data=density)
If properties are constant across an object they can also be created using the set_property_expr
method.
dh.set_property_expr("density", "2.4")
Properties can also be string values, needing to add nesting quotes.
dh.set_property_expr("lithology", "'channel'")
Property can be set using the subscript shortcut []
, allowing to set easily set properties from list/array of from constant values.
dh["density"] = density
dh["litho_code"] = 1
dh["lithology"] = "'channel'"
Create a region from a list of booleans¶
Use the set_region
method to create a region from a list of booleans.
First let's create a boolean array of the composite higher than a cutoff of 50% Fe.
fe_above_50 = dh["Fe_pct"] > 50
fe_above_50
array([False, False, False, ..., False, False, False])
dh.set_region(name="fe_above_50", data=fe_above_50)
Create a region from an existing property¶
Use the set_region_condition
method to create a region from an existing property.
dh.set_region_condition(name="Fe_pct_below_50_strict", condition="Fe_pct < 50")
Using numpy when condition thickens¶
dh.set_region_condition(name="Fe_pct_lt_5", condition="Fe_pct < 5")
dh.set_region_condition(name="SiO2_pct_gt_25", condition="SiO2_pct > 25")
fe_high_silica_array = np.where(
dh["SiO2_pct_gt_25"] & dh["Fe_pct_lt_5"],
5,
dh["Fe_pct"]
)
dh.set_property(name="fe_high_silica", data=fe_high_silica_array)
Dynamic region¶
To ensure the region values dynamically reflect changes in the property from which they were created, set the dynamic
argument to True
.
dh.set_region_condition(name="Fe_pct_below_50", condition="Fe_pct < 50", dynamic=True)
Create property from other properties¶
To create a property for an object, use its set_property_expr
method with the following arguments:
expr
: A string representing either an existing property or a mathematical expression involving two or more properties.region
: A condition used as a filter or mask applied to the current data.default
: An optional default value applied outside the specified region, if a region is defined.
Create property from a mathematical operation¶
Create the property "composite_thickness"
by substracting the existing properties "TO"
and "FROM"
each other:
dh.set_property_expr(name="composite_thickness", expr="TO - FROM")
Or with the shorter version:
dh["composite_thickness"] = "TO - FROM"
Create an empty property to be filled later¶
Create an empty property named "High_Fe"
with the value "nan"
.
dh.set_property_expr(name="High_Fe", expr="nan")
Now, assign the "Fe_pct"
property using the region "Fe_pct > 30"
. For each value outside the region, the value is set to "nan"
.
dh.set_property_expr(name="High_Fe", expr="Fe_pct", region="Fe_pct > 30")
Create a property with a region and a default value¶
Create a property "High_Fe"
from "Fe_pct"
with the region "Fe_pct > 30"
and default value as "nan."
. This means that for each value outside the region, the value is set to nan.
dh.set_property_expr(name="High_Fe", expr="Fe_pct", region="Fe_pct > 30", default="nan")
Update an existing property/region¶
Use the set_property_value
method to update an existing property:
dh.set_property_value(name="Fe_pct", data=np.random.rand(7134))
It also possible to update in a given region only. For this to work the provided array/list must have the same number of elements as the region.
dh.set_property_value(name="Fe_pct", data=np.random.rand(3890), region="Fe_pct_below_50_strict")
Use the set_region_value
method to update an existing region:
dh.set_region_value(name="Fe_pct_below_50", data=dh["Fe_pct"] <= 50)
Properties and regions renaming¶
To rename properties, regions, or attributes for an object, use the rename_property
, rename_region
, or rename_attribute
methods. These methods accept a dictionary as an argument, allowing you to rename multiple properties or regions simultaneously.
First, create a property of random values using numpy random functionnality. Random values will follow a standard gaussian distribution of 0 mean and variance of 1.
data_property = np.random.rand(7134)
dh.set_property(name="my_property", data=data_property)
Now create a region selecting only values below 0.8
data_region = data_property < 0.8
dh.set_region(name="my_region", data=data_region)
Using the renaming methods we can rename the created attributes to have more meaningful names.
dh.rename_property(names={"my_property": "random_values"})
dh.rename_region(names={"my_region": "random_values_lt_0_8"})
In this exemple, we rename several properties and region at the same by passing a dictionnary to the rename_attribute
method:
First, create two properties of random values.
dh.set_property(name="my_property_1", data=np.random.rand(7134))
dh.set_property(name="my_property_2", data=np.random.rand(7134))
Create two regions using the region_condition method.
dh.set_region_condition(name="my_region_1", condition="my_property_1 < 0.5")
dh.set_region_condition(name="my_region_2", condition="my_property_2 > 0.8")
Rename both region and properties using the rename_attribute
method.
dh.rename_attribute(
names={
"my_property_1": "random_values_1",
"my_property_2": "random_values_2",
"my_region_1": "random_values_1_lt_0_5",
"my_region_2": "random_values_2_gt_0_8",
}
)
Properties and regions removing¶
To remove properties, regions, or attributes from an object, use the remove_property
, remove_region
, or remove_attribute
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.
First, create two properties of random values.
data_property = np.random.rand(7134)
dh.set_property(name="my_property", data=np.random.rand(7134))
Now create a region selecting only values below 0.8
data_region = data_property < 0.8
dh.set_region(name="my_region", data=data_region)
Using the removing methods we can remove the created property and region.
dh.remove_property(name="my_property")
dh.remove_region(name="my_region")
In this exemple, we remove several properties and regions at the same time by passing a dictonnary to the remove_attribute
method:
First, create two properties of random values.
dh.set_property(name="my_property_1", data=np.random.rand(7134))
dh.set_property(name="my_property_2", data=np.random.rand(7134))
Create two regions using the region_condition method.
dh.set_region_condition(name="my_region_1", condition="my_property_1 < 0.5")
dh.set_region_condition(name="my_region_2", condition="my_property_2 > 0.8")
Remove both region and properties using the remove_attribute
method.
dh.remove_attribute(name=["my_property_1", "my_property_2", "my_region_1", "my_region_2"])
Acces to attribute data and objects¶
List 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_high_silica | Fe_pct_below_50 | composite_thickness | High_Fe | random_values | random_values_lt_0_8 | random_values_1 | random_values_2 | random_values_1_lt_0_5 | random_values_2_gt_0_8 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2 | 1 | 0 | 1 | 0.0 | 1.0 | RKC278 | 548001.3 | 7474002.1 | 453.5 | ... | NaN | True | 1.0 | NaN | 0.099471 | True | 0.520252 | 0.019162 | False | False |
1 | 2 | 1 | 1 | 2 | 1.0 | 2.0 | RKC278 | 548001.3 | 7474002.1 | 453.5 | ... | NaN | True | 1.0 | NaN | 0.733282 | True | 0.237584 | 0.870749 | True | True |
2 | 2 | 1 | 2 | 3 | 2.0 | 3.0 | RKC278 | 548001.3 | 7474002.1 | 453.5 | ... | NaN | True | 1.0 | NaN | 0.015121 | True | 0.092222 | 0.965749 | True | True |
3 | 2 | 1 | 3 | 4 | 3.0 | 4.0 | RKC278 | 548001.3 | 7474002.1 | 453.5 | ... | NaN | True | 1.0 | NaN | 0.036565 | True | 0.613430 | 0.598907 | False | False |
4 | 2 | 1 | 4 | 5 | 4.0 | 5.0 | RKC278 | 548001.3 | 7474002.1 | 453.5 | ... | NaN | True | 1.0 | NaN | 0.297960 | True | 0.813314 | 0.405749 | False | False |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
7129 | 2 | 1 | 7319 | 7320 | 43.0 | 44.0 | RKC485 | 547913.3 | 7473917.2 | 452.4 | ... | 16.0 | True | 1.0 | NaN | 0.175220 | True | 0.761276 | 0.747462 | False | False |
7130 | 2 | 1 | 7320 | 7321 | 44.0 | 45.0 | RKC485 | 547913.3 | 7473917.2 | 452.4 | ... | 12.0 | True | 1.0 | NaN | 0.295890 | True | 0.813187 | 0.113204 | False | False |
7131 | 2 | 1 | 7322 | 7323 | 0.0 | 1.0 | RKD015 | 547905.0 | 7476800.0 | 470.0 | ... | NaN | True | 1.0 | NaN | 0.622923 | True | 0.603627 | 0.345215 | False | False |
7132 | 2 | 1 | 7323 | 7324 | 0.0 | 1.0 | RKD015 | 547905.0 | 7476800.0 | 470.0 | ... | NaN | True | 1.0 | NaN | 0.718195 | True | 0.111673 | 0.076237 | True | False |
7133 | 2 | 1 | 7324 | 7325 | 0.0 | 1.0 | RKD015 | 547905.0 | 7476800.0 | 470.0 | ... | NaN | True | 1.0 | NaN | 0.372248 | True | 0.947436 | 0.775815 | False | False |
7134 rows × 56 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', 'lithology', 'litho_code', 'fe_high_silica', 'composite_thickness', 'High_Fe', 'random_values', 'random_values_1', 'random_values_2']
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', 'lithology', 'litho_code', 'fe_high_silica', 'composite_thickness', 'High_Fe', 'random_values', 'random_values_1', 'random_values_2']
List all existing regions:
dh.regions()
['fe_above_50', 'Fe_pct_below_50_strict', 'Fe_pct_lt_5', 'SiO2_pct_gt_25', 'Fe_pct_below_50', 'random_values_lt_0_8', 'random_values_1_lt_0_5', 'random_values_2_gt_0_8']
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([0.40166037, 0.43530166, 0.49034046, ..., 0.99395002, 0.71928743, 0.22561103])
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([0.40166037, 0.49034046, 0.26513984, ..., 0.7829412 , 0.25628263, 0.42859783])
Get the mask of a region¶
To access the mask of a region, represented as a boolean array
dh.region_mask(region="Fe_pct_below_50")
array([ True, True, True, ..., True, True, True])
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([0.86335055, 0.3355012 , 0.34358704, ..., 0.37688351, 0.88033172, 0.28818935])
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.
fct_pct_region_b50 = dh.region("Fe_pct_below_50")
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.
fct_pct_region_b50.expr
'Fe_percent < 50'
Same as properties, regions can be read_only
.
fct_pct_region_b50.read_only
False
Get the mask of the region:
fct_pct_region_b50.data()
array([ True, True, True, ..., True, True, True])
Rename the region:
fct_pct_region_b50.name = "new_name_fct_pct_region_b50"
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_f1b811'