Drillhole creation and quick visualiation#

Here along GeoLime are used CRS from pyproj in order to deal with Coordinates Reference System and display data on a map with a background, pyvista in order to visualise data in 3D and pandas to read the assay file obtained in the cleaning notebook.

import geolime as geo
from pyproj import CRS
import pyvista as pv
import pandas as pd

pv.set_jupyter_backend('html')
geo.Project().set_crs(CRS("EPSG:20350"))

GeoLime Drillholes Creation#

The next command will use the Geo Lime library to draw an interactive map of the iron concentration. First we need to import the survey and collar file to have all the informations about the drillholes.

Note

Survey File Survey File was created as it is not provided by the CSIRO. In this case of vertical drillholes, a survey file is optionnal as GeoLime will consider it automatically. For the purpose of this a survey file is however created in order to behave like most cases.

survey = geo.datasets.load("rocklea_dome/survey.csv")
collar = geo.datasets.load("rocklea_dome/collar.csv")
assay = pd.read_csv("../data/assay_hyper.csv")

Project Definition#

The CRS can be set using the Project() object, allowing to define parameters once and not for every new imported data.

geo.Project().set_crs(CRS("EPSG:20350"))

Drillholes Creation#

Then we can create the drillholes and draw the map showing the average iron weight percentage of each hole.

dh = geo.create_drillholes(
    name="rck_assay", 
    collar=collar, 
    assays=assay, 
    survey=survey
)
2024-12-03 15:36:01,119 [INFO] GeoLime Project - |GEOLIME|.drillholes_api.py : Following mapping has been identified: {
    "HOLEID": "Hole_ID",
    "X_COLLAR": "X",
    "Y_COLLAR": "Y",
    "Z_COLLAR": "RL_AHD",
    "AZIMUTH": "Azi_mag",
    "DEPTH_SURVEY": "Distance",
    "DIP": "Dip",
    "FROM": "From",
    "TO": "To"
}

Like Pandas library, GeoLime uses the describe method to quickly access to the aggregated statistics of an object.

dh.describe()
__TOPO_LEVEL__ __TOPO_TYPE__ __TOPO_ELEMENT_V1__ __TOPO_ELEMENT_V2__ FROM TO X_COLLAR Y_COLLAR Z_COLLAR X_M ... SiO2 MnO Mn CaO K2O MgO Na2O TiO2 LOI_100 Depth
count 7108.0 7108.0 7108.000000 7108.000000 7108.000000 7108.000000 7108.000000 7.108000e+03 7108.000000 7108.000000 ... 7036.000000 7036.0 7036.000000 7036.000000 7036.000000 7036.000000 7036.000000 7036.000000 7036.000000 7108.000000
mean 2.0 1.0 3649.240293 3650.240293 20.568655 21.568655 547413.687521 7.475481e+06 458.500774 547413.687521 ... 20.022739 0.0 0.058710 1.061883 0.130430 0.885746 0.001279 0.448157 0.000007 42.645751
std 0.0 0.0 2111.443717 2111.443717 13.834178 13.834178 685.729896 1.587386e+03 7.467718 685.729896 ... 21.012233 0.0 0.133017 3.609818 0.491768 1.982652 0.107295 0.537459 0.000608 11.275263
min 2.0 1.0 0.000000 1.000000 0.000000 1.000000 545494.900000 7.472793e+06 441.000000 545494.900000 ... 0.000000 0.0 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 7.000000
25% 2.0 1.0 1816.750000 1817.750000 9.000000 10.000000 546904.700000 7.474003e+06 453.800000 546904.700000 ... 0.000000 0.0 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 36.000000
50% 2.0 1.0 3650.500000 3651.500000 19.000000 20.000000 547586.100000 7.475604e+06 458.200000 547586.100000 ... 12.735000 0.0 0.010000 0.110000 0.025000 0.310000 0.000000 0.267000 0.000000 46.000000
75% 2.0 1.0 5479.250000 5480.250000 31.000000 32.000000 547947.600000 7.476004e+06 463.600000 547947.600000 ... 33.555000 0.0 0.090000 0.300000 0.082000 0.720000 0.000000 0.692000 0.000000 51.000000
max 2.0 1.0 7298.000000 7299.000000 60.000000 61.000000 548498.100000 7.479595e+06 478.600000 548498.100000 ... 92.810000 0.0 6.160000 40.820000 21.250000 20.010000 9.000000 10.000000 0.051000 61.000000

8 rows × 51 columns

The basic properties of a drillholes object already have unit specify.

dh.property("X_M").unit
meter

Unit can also be specified in the Project for each property.

Property units are managed using the Pint python package (https://pint.readthedocs.io/en/stable/index.html). Default unit are already available (https://github.com/hgrecco/pint/blob/master/pint/default_en.txt) and other can be added to a GeoLime project.

This will allow to specify the percent property to each property of a GeoLime object.

geo.Project().unit_registry.define("percent = 1e-2 frac = pct")

Using the percent unit defined, we can now specify it to all other related property, especially the ones with _pct in their names.

for prop in dh.properties():
    if "_pct" in dh.property(prop).name:
        dh.property(prop).unit = geo.Project().unit_registry.pct
dh.property("Fe_pct").unit
percent

Graphic representations#

Most of GeoLime objects are 3D objects (Drillholes, BlockModel) and their visualisation on a map in 2D needs to “aggregate” values on the vertical dimensions. Drillholes are aggregated alond the hole and BlockModel are aggregated along a “column” of Block, being the block with the same X and Y.

dh.plot_2d(property="Fe", agg_method="mean", interactive_map=True)
Make this Notebook Trusted to load map: File -> Trust Notebook

Points with no value can be hidden using extra keywords from the folium library: https://python-visualization.github.io/folium/quickstart.html#Getting-Started

dh.plot_2d(property="Fe_pct", agg_method="mean", interactive_map=True, style_kwds={"fillColor": "none"})
Make this Notebook Trusted to load map: File -> Trust Notebook

Aggregation along axes can be plotted using the scatter function. Unlike a cross section where only a slice is viewed, here all data are visualised.

In drillholes objects there are 3 coordinates availables for each composite :

  • the coordinates of the begininng of the composites (X_B, Y_B and Z_B)

  • the coordinates of the midpoint of the composites (X_M, Y_M and Z_M)

  • the coordinates of the end of the composites (X_E, Y_E and Z_E)

Midpoints are the coordinates used in most of the algorithms.

geo.scatter(geo_object=dh, property_x="X_M", property_y="Z_M")
geo.scatter(geo_object=dh, property_x="Y_M", property_y="Z_M")

Exploratory Analysis#

Data can be visualised in 3D using the pyvista library. Any Object can be converted to a pyvista object using the to_pyvista method.

df_pv = dh.to_pyvista('Fe_pct')

Using the pyvista library scene creation we can then visualise data in 3D. Here as the data are mostly flat, a vertical exageration is used.

pl = pv.Plotter()
pl.add_mesh(df_pv.tube(radius=10))
pl.set_scale(zscale=20)

pl.show()

Geological section#

scatter function can also be used to view cross section by using the region parameter and provided spatial thresholds in order to define a specific slice.

geo.scatter(
    geo_object=dh, 
    property_x="X_M", 
    property_y="FROM", 
    region="(Y_M > 7475791.8 - 400) &  (Y_M < 7475791.8 + 400)"
)

Scatter function takes also into account all layout properties from plotly : https://plotly.com/python/reference/layout/.

As GeoLime plotting functions returns Plotly Figure, they can be stored in a variable.

f = geo.scatter(
    geo_object=dh, 
    property_x="X_M", 
    property_y="FROM", 
    region="(Y_M > 7475791.8 - 20) &  (Y_M < 7475791.8 + 20)", 
    yaxis_autorange="reversed"
)

Plotly figures can then be exported to

  • standard image format (PNG, PDF, JPEG) for static export

  • HTML format for interactive export and sharing only figure without code

  • JSON format to be used in other software or in a Web Application

  • python dictionnary to understand figure architecture and modify every elements

For example, we can change the color by setting a property from the drillholes, here we color the point using the Iron content

f["data"][0]["marker"]["color"] = dh.data("Fe_pct", "(Y_M > 7475791.8 - 20) & (Y_M < 7475791.8 + 20)")
f["data"][0]["marker"]["line"]["width"] = 0
f["data"][0]["marker"]["colorbar"] = dict(title = 'Fe_pct')
f
f["data"][0]["marker"]["colorscale"] = "cividis"
f

Correlations between elements#

geo.correlation_heatmap(
    geo_object=dh, 
    properties=[
        "Mn_pct", "P_pct", "Fe_pct", "CaO_pct", "MgO_pct", "S_pct", "Al2O3", "TiO2_pct", "SiO2_pct", "K2O_pct"
    ]
)
geo.scatter(geo_object=dh, property_x="Al2O3", property_y="Fe_pct", marginal_plot=geo.ScatterMethod.HISTOGRAM)

Histograms#

geo.histogram_plot(data=[{"object": dh, "property": "Fe_pct"}])

Bin number can also be specified.

geo.histogram_plot(data=[{"object": dh, "property": "Al2O3"}], nbins=30)

Multiple histograms can also be shown on the same figure. Here using also the region parameter it is possible to visualise the histogram of the iron values where silica values are lower and higher than 20 %.

geo.histogram_plot(
    data=[
        {"object": dh, "property": "Fe_pct", "region":"SiO2 < 20"},
        {"object": dh, "property": "Fe_pct", "region":"SiO2 >= 20"} 
    ], 
    nbins=30
)

Export File#

For faster import/export and ease of use, instead of exporting the drillholes into csv, GeoLime has its own format. To export an object, use the to_file method.

dh.to_file("../data/dh_hyper")

Conclusions#

As we can see with the visualization above, the main element in this area is Iron, mainly as an oxyde (Hematite/Goethite). Secondly, the geological sections and various scatter showed us that the iron is located in two separate deposits, the first one being located near 10 meters deep, and the other around 50m. This distribution of iron seems to show again in the histograms by its bimodal aspect.

Our tools have also revealed the presence of Al2O3 and TiO2, which are highly correlated (0.7 according to our heatmap, and located in the same areas, indicating a common backgroud and deposit history. However, their distribution is way lower than the iron one (Maximum 60% for the iron against 30% for the Aluminium and 3% Titanium), and they exist as punctual traces, not well defined deposits.