Variography#

import geolime as geo
dh_tom = geo.read_file("../data/dh_tom_comp.geo")

Once the capping value determined, we can create a new property to capp the value above 25.

dh_tom.set_property(name='Zn_cap', data='Zn_pct')
dh_tom.update_property(name='Zn_cap', data='25', region="(Zn_cap > 25)")

Normal Score#

For simplicity in variography analysis, let’s compute the normal scores of the data.

gauss_score function returns a numpy array, so let’s create a new property on the Drillholes.

geo.gauss_score(dh_tom['Zn_cap'])
2026-09-28 01:03:15,940 [WARNING] GeoLime Project - |GEOLIME|.anamorphosis.py : There are NaN in data. They will be ignored.
array([-0.78162595,         nan,         nan, ..., -0.7347981 ,
       -0.97560843, -1.06290788], shape=(3761,))
dh_tom.set_property(name="Zn_gauss", data=geo.gauss_score(dh_tom['Zn_cap']))
2026-09-28 01:03:16,115 [WARNING] GeoLime Project - |GEOLIME|.anamorphosis.py : There are NaN in data. They will be ignored.

Experimental Analysis#

Lag Creation#

For Variography analysis, lag creation can be perfom

  • implicitly with a number of lags and a length of lag

  • explicitly with interval values provided.

lags, tol = geo.generate_lags_from_interval([[0, 10], [10, 20], [20, 40]])
lags, tol = geo.generate_lags(lag=40, plag=50, nlags=15)
lags
array([  0,  40,  80, 120, 160, 200, 240, 280, 320, 360, 400, 440, 480,
       520, 560])
tol
20.0

Variography Analysis is perform in 2 step:

  • finding the main direction

  • computing the semi variogram 1D in the major/semi-major/minor directions

The finding of the main direction is perform through the analysis of variomap is the different planes.

  • Analysis around the Z axis for the azimuth using vario_map / vario_contour;

  • Once found the main azimuth, analysis around the X axis for the dip using vario_contour_dip;

  • Once found the correspond azimuth and dip, analysis around the Z axis for the pitch using vario_contour_pitch

Finding main direction#

geo.vario_map(
    geo_object=dh_tom,
    attribute="Zn_gauss",
    region="Zn_gauss.notna()",
    lags=lags,
    tol=tol,
    n_az=15,
    atol=15,
    backend=geo.GeostatsBackend.RUST,
    rust_multithread=True
)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[10], line 9
      5     lags=lags,
      6     tol=tol,
      7     n_az=15,
      8     atol=15,
----> 9     backend=geo.GeostatsBackend.RUST,
     10     rust_multithread=True
     11 )

AttributeError: module 'geolime' has no attribute 'GeostatsBackend'
geo.vario_contour(
    geo_object=dh_tom,
    attribute="Zn_gauss",
    region="Zn_gauss.notna()",
    lags=lags,
    tol=tol,
    n_az=15,
    atol=10,
    user_azimuth=145,
    backend=geo.GeostatsBackend.RUST,
    rust_multithread=True
)
geo.vario_contour_dip(
    geo_object=dh_tom,
    attribute="Zn_gauss",
    region="Zn_gauss.notna()",
    lags=lags,
    tol=tol,
    azimuth=145,
    n_dip=18,
    atol=10,
    user_dip=30,
    c_step=None,
    save_file=None,
    backend=geo.GeostatsBackend.RUST,
    rust_multithread=True
)
lags, tol = geo.generate_lags(lag=5, plag=50, nlags=15)
geo.vario_contour_pitch(
    geo_object=dh_tom,
    attribute="Zn_gauss",
    region="Zn_gauss.notna()",
    lags=lags,
    tol=tol,
    azimuth=145,
    dip=30,
    n_pitch=15,
    atol=10,
    user_pitch=40,
    c_step=None,
    save_file=None,
    backend=geo.GeostatsBackend.RUST,
    rust_multithread=True
)

Computing Major/Semi-major/minor 1D variograms#

lags, tol = geo.generate_lags(lag=40, plag=50, nlags=15)
vario_exp_major = geo.variogram(
    object=dh_tom,
    attribute="Zn_gauss",
    region="Zn_gauss.notna()",
    geographic_azimuth=145,
    dip=30,
    pitch=40,
    lags=lags,
    tol=tol,
    atol=15
)
vario_exp_major
geo.plot_semivariogram(
    variograms=[vario_exp_major],
    display_npairs=True
)
vario_exp_semi_major = geo.variogram(
    object=dh_tom,
    attribute="Zn_gauss",
    region="Zn_gauss.notna()",
    geographic_azimuth=145,
    dip=30,
    pitch=-50,
    lags=lags,
    tol=tol,
    atol=15
)

geo.plot_semivariogram(
    variograms=[vario_exp_semi_major],
    display_npairs=True
)
lags, tol = geo.generate_lags(lag=2, plag=50, nlags=15)
vario_exp_minor = geo.variogram(
    object=dh_tom,
    attribute="Zn_gauss",
    region="Zn_gauss.notna()",
    geographic_azimuth=145,
    dip=-60,
    pitch=40,
    lags=lags,
    tol=tol,
    atol=30
)

geo.plot_semivariogram(
    variograms=[vario_exp_minor],
    display_npairs=True
)

Computing Downhole Variogram#

lags, tol = geo.generate_lags(lag=1., plag=50, nlags=20)
vario_exp_bh = geo.variogram_downhole(
    object= dh_tom,
    attribute="Zn_gauss",
    region="Zn_gauss.notna()",
    lags=lags,
    tol=tol,
)
geo.plot_semivariogram(
    variograms=[vario_exp_bh],
    display_npairs=True
)

Automatic Fitting#

Automatic Fitting uses an empty model to fit along experimental variograms. Fitting is usually performed in 2 steps : first fit the nugget and then fit the other structures.

Fitting the Nugget#

nugget_model = geo.Nugget() + geo.Spherical()

The fitting algorithm can be set up to preferrentially fit the small ranges using the INVERSE_DISTANCE or SQUARED_INVERSE_DISTANCE.

geo.model_fit(
    variograms=[vario_exp_bh],
    cov=nugget_model,
    weighting_method=geo.VarioFitWeightingMethod.SQUARED_INVERSE_DISTANCE
)
print(nugget_model)

Model and experimental variogram can be plotted on the same graphic by specifying the parameter model and model_angles. Note that for downhole varigram the model_angles values do not have any importance.

geo.plot_semivariogram(
    variograms=[vario_exp_bh],
    model=nugget_model,
    model_angles=[{"azi":0, "dip":90, "pitch":90}],
    display_npairs=True
)

Each structure component can be accessed using the cov_elem_list attribute.

nugget_model.cov_elem_list[0].sill

Fitting the structures#

model =  geo.Nugget() + geo.Spherical() + geo.Spherical()
short_range_spherical_ratio = 0.6
long_range_spherical_ratio = 0.4
geo.model_fit(
    variograms=[
        vario_exp_major,
        vario_exp_semi_major,
        vario_exp_minor
    ],
    cov=model,
    constraints=[
        {"sill_fixed":0.13},
        {
            "sill_max": short_range_spherical_ratio * (vario_exp_major.attrs["variable_var"] - 0.13),
            "angle_fixed_0": 145,
            "angle_fixed_1": 60,
            "angle_fixed_2": 40,
            "scale_max_0":100,
            "scale_max_1":100,
            "scale_max_2":20 
        },
        {
            "sill_max": long_range_spherical_ratio * (vario_exp_major.attrs["variable_var"] - 0.13),
            "angle_fixed_0": 145,
            "angle_fixed_1": 60,
            "angle_fixed_2": 40, 
        }
    ]
)
geo.plot_semivariogram(
    variograms=[vario_exp_major, vario_exp_semi_major, vario_exp_minor],
    model=model,
    model_angles=[
        {"azi":145, "dip":60, "pitch":40},
        {"azi":145, "dip":60, "pitch":-50},
        {"azi":145, "dip":-30, "pitch":40},
    ],
    display_npairs=True
)
print(model)
dh_tom.to_file("../data/dh_tom_comp_capped.geo")