Drillhole creation and quick visualisation#
In this notebook we use the GeoLime library to create our Drillhole objects and produce some interactive visualisations of the data.
We also use the library pyproj to handle Coordinates Reference Systems (CRS) and help us display data on a map with a background.
The library pyvista is used to visualise data in 3D.
Again, the pandas library is utilised to read the assay file obtained in the cleaning previous notebooks.
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#
This section uses the GeoLime library to draw an interactive map of the iron concentration.
First we need to import the collar and survey file to have all the spatial information 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 CRS Definition#
The CRS can be set using the geo.Project().set_crs method, allowing the user to define CRS parameters on a project scale, eliminating the need to set CRS for all individual objects.
geo.Project().set_crs(CRS("EPSG:20350"))
Drillholes Creation#
Drillholes are a specific type of GeoLime object which encapsulate all the information which defines a drillhole, including the collar, assay, and survey files.
We can create a drillhole using the geo.create_drillholes() method, giving a name, and pointing at our collar, assay and survey files.
dh = geo.create_drillholes(
name="rck_assay",
collar=collar,
assays=assay,
survey=survey
)
2025-09-25 11:44:37,750 [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
Unit can also be specified in the Project for each property.
Property units are managed using the Pint python package (Pint). Default unit are already available (Pint Units) 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
Graphic representations#
Most GeoLime objects are 3D objects (Drillholes, BlockModels) and their values must be “aggregated” in order to easily visualise them on 2D map. Drillholes are aggregated along the hole and BlockModels are aggregated within a “column” of Blocks, this being the blocks with the same X and Y coordinates.
For the following 2d plot, we use a mean average aggregation method to aggregate the average Iron concentration and display it on our interactive 2d map.
dh.plot_2d(property="Fe", agg_method="mean", interactive_map=True)
Points with no value can be hidden using extra keywords from the folium library: Folium
Here the fillColor keyword is used to assign no colour fill to all drillhole locations. Only holes with Fe percentages are now visible.
dh.plot_2d(property="Fe_pct", agg_method="mean", interactive_map=True, style_kwds={"fillColor": "none"})
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.
First, a drillhole is converted to a pyvista object
df_pv = dh.to_pyvista('Fe_pct')
Using the pyvista library scene creation we can then visualise data in 3D. A vertical exageration is applied for easier visualisation of the drillholes (set_scale(zscale=20))
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 a cross section by using the region parameter and providing spatial thresholds (X or Y coordinate limits) in order to define a specific section for visualisation.
Here, the Y coordinate is used to define a slice through the data.
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
f.write_image("../data/dh_section.png")
Using the plotly figure properties we can change the color of the plot by setting a property from the drillholes. Here we colour the points using the Iron content (Fe_Pct)
First, we specify the property to be used as our drillhole colour, and a region bounded by Y coordinates
We then choose a line width of 0 for easy visualisation
We then define the Fe percentage as our colorbar reference property
And finally we select a perceptually uniform colourscale ‘cividis’
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["data"][0]["marker"]["colorscale"] = "cividis"
f
Correlations between elements#
GeoLime includes the capability to create correlation heatmaps between elements. Here, various mineral properties from the drillhole are correlated in an interactive heatmap display.
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"
]
)
Several minerals show strong correlation. Relationships can be further established using scatterplots and Histogram displays.
Here we use a scatterplot with an associated histogram to visualise any potential relationship between the Aluminium Oxide (Al2O3) and Iron (Fe_pct) concentrations.
geo.scatter(geo_object=dh, property_x="Al2O3", property_y="Fe_pct", marginal_plot=geo.ScatterMethod.HISTOGRAM)
We see a strong negative correlation between the AL2O3 and Iron concentration.
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)
Here we can see a bimodal distribution of Fe_pct, with a cluster around 5-10m, and a second around 50m depth.
Multiple histograms can also be shown on the same figure. Here using 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
)
A strong negative correlation is seen between the SiO2 and Fe concentration.
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.
Files are saved with a .geo extension
dh.to_file("../data/dh_hyper")
Conclusions#
The analysis shown in this notebook indicates the main element of interest in this area is Iron, mainly as an oxide (likely Hematite/Goethite).
Secondly, the geological sections and various scatterplots show us that the iron is concentrated in two distinct deposits, at approximately 10m and 50m depth.
Strongly negative correlations are seen between Fe concentration and SiO2, typical of a paleochannel iron deposit in this region.
In the next notebook we will look at domaining workflows, where we will use our drillholes to divide the deposit into various domains based on geology, geochemistry, mineralogy, grade etc.