Skip to content

v.surf.rst.cv

Performs a cross-validation procedure to optimize the parameterization of v.surf.rst.

v.surf.rst.cv [-t] point_cloud=name [mask=name] [tension=float [,float,...]] [smooth=float [,float,...]] [npmin=integer [,integer,...]] [segmax=integer [,integer,...]] [dmin=float [,float,...]] [dmax=float [,float,...]] [theta=float [,float,...]] [scalex=float [,float,...]] [method=string] [levels=integer] [npoints=integer] [seed=integer] [layer=string] [zcolumn=name] [where=sql_query] [zscale=float] [cv_prefix=string] [output_file=name] format=name [nprocs=integer] [--overwrite] [--verbose] [--quiet] [--qq] [--ui]

Example:

v.surf.rst.cv point_cloud=name format=plain

grass.tools.Tools.v_surf_rst_cv(point_cloud, mask=None, tension=10,20,40,80,160, smooth=0.001,0.01,0.1,1.0,10.0, npmin=None, segmax=None, dmin=None, dmax=None, theta=None, scalex=None, method="grid", levels=3, npoints=None, seed=None, layer="1", zcolumn=None, where=None, zscale=1.0, cv_prefix=None, output_file=None, format="plain", nprocs=0, flags=None, overwrite=None, verbose=None, quiet=None, superquiet=None)

Example:

tools = Tools()
tools.v_surf_rst_cv(point_cloud="name", format="json")

This grass.tools API is experimental in version 8.5 and expected to be stable in version 8.6.

grass.script.parse_command("v.surf.rst.cv", point_cloud, mask=None, tension=10,20,40,80,160, smooth=0.001,0.01,0.1,1.0,10.0, npmin=None, segmax=None, dmin=None, dmax=None, theta=None, scalex=None, method="grid", levels=3, npoints=None, seed=None, layer="1", zcolumn=None, where=None, zscale=1.0, cv_prefix=None, output_file=None, format="plain", nprocs=0, flags=None, overwrite=None, verbose=None, quiet=None, superquiet=None)

Example:

gs.parse_command("v.surf.rst.cv", point_cloud="name", format="json")

Parameters

point_cloud=name [required]
    Name of the input point vector map
    Or data source for direct OGR access
mask=name
    Name of the raster map used as mask
    Name of input raster map
tension=float [,float,...]
    Tension parameter values to cross-validate
    Default: 10,20,40,80,160
smooth=float [,float,...]
    Smoothing parameter values to cross-validate
    Default: 0.001,0.01,0.1,1.0,10.0
npmin=integer [,integer,...]
    Minimum number of points for approximation in a segment (>segmax)
    Multiple values are swept as an outer loop
segmax=integer [,integer,...]
    Maximum number of points in a segment
    Multiple values are swept as an outer loop
dmin=float [,float,...]
    Minimum distance between points (to remove almost identical points)
    Multiple values are swept as an outer loop
dmax=float [,float,...]
    Maximum distance between points on isoline (to insert additional points)
    Multiple values are swept as an outer loop
theta=float [,float,...]
    Anisotropy angle (in degrees counterclockwise from East)
    Multiple values are swept as an outer loop
scalex=float [,float,...]
    Anisotropy scaling factor
    Multiple values are swept as an outer loop
method=string
    Search method over tension and smoothing (grid: full Cartesian product; refine: recursive refinement around the best cell)
    Allowed values: grid, refine
    Default: grid
levels=integer
    Maximum number of refinement levels for method=refine
    Default: 3
npoints=integer
    Cross-validate on a spatially stratified subsample of approximately this many points
seed=integer
    Seed value for the random number generator
    Using the same seed ensures identical results, while a randomly generated seed produces different outcomes in each run.
layer=string
    Layer number or name
    Vector features can have category values in different layers. This number determines which layer to use. When used with direct OGR access this is the layer name.
    Default: 1
zcolumn=name
    Name of the attribute column with values to be used for approximation
    If not given and input is 2D vector map then category values are used. If input is 3D vector map then z-coordinates are used.
where=sql_query
    WHERE conditions of SQL statement without 'where' keyword
    Example: elevation < 500 and elevation >= 1
zscale=float
    Conversion factor for values used for approximation
    Default: 1.0
cv_prefix=string
    Prefix to use for cross-validation output maps
    Prefix for saved cross-validation error vector maps and interpolated deviation surfaces. If not set, cross-validation maps are temporary.
output_file=name
    Output file
    Output file for the results in the selected format
format=name [required]
    Output format
    Allowed values: plain, csv, json
    Default: plain
    plain: Human readable table
    csv: CSV (Comma Separated Values)
    json: JSON (JavaScript Object Notation)
nprocs=integer
    Number of threads for parallel computing
    0: use OpenMP default; >0: use nprocs; <0: use MAX-nprocs
    Default: 0
-t
    Use scale dependent tension (recommended when tuning, makes tension transferable across point densities)
--overwrite
    Allow output files to overwrite existing files
--help
    Print usage summary
--verbose
    Verbose module output
--quiet
    Quiet module output
--qq
    Very quiet module output
--ui
    Force launching GUI dialog

point_cloud : str, required
    Name of the input point vector map
    Or data source for direct OGR access
    Used as: input, vector, name
mask : str | np.ndarray, optional
    Name of the raster map used as mask
    Name of input raster map
    Used as: input, raster, name
tension : float | list[float] | str, optional
    Tension parameter values to cross-validate
    Default: 10,20,40,80,160
smooth : float | list[float] | str, optional
    Smoothing parameter values to cross-validate
    Default: 0.001,0.01,0.1,1.0,10.0
npmin : int | list[int] | str, optional
    Minimum number of points for approximation in a segment (>segmax)
    Multiple values are swept as an outer loop
segmax : int | list[int] | str, optional
    Maximum number of points in a segment
    Multiple values are swept as an outer loop
dmin : float | list[float] | str, optional
    Minimum distance between points (to remove almost identical points)
    Multiple values are swept as an outer loop
dmax : float | list[float] | str, optional
    Maximum distance between points on isoline (to insert additional points)
    Multiple values are swept as an outer loop
theta : float | list[float] | str, optional
    Anisotropy angle (in degrees counterclockwise from East)
    Multiple values are swept as an outer loop
scalex : float | list[float] | str, optional
    Anisotropy scaling factor
    Multiple values are swept as an outer loop
method : str, optional
    Search method over tension and smoothing (grid: full Cartesian product; refine: recursive refinement around the best cell)
    Allowed values: grid, refine
    Default: grid
levels : int, optional
    Maximum number of refinement levels for method=refine
    Default: 3
npoints : int, optional
    Cross-validate on a spatially stratified subsample of approximately this many points
seed : int, optional
    Seed value for the random number generator
    Using the same seed ensures identical results, while a randomly generated seed produces different outcomes in each run.
layer : str, optional
    Layer number or name
    Vector features can have category values in different layers. This number determines which layer to use. When used with direct OGR access this is the layer name.
    Used as: input, layer
    Default: 1
zcolumn : str, optional
    Name of the attribute column with values to be used for approximation
    If not given and input is 2D vector map then category values are used. If input is 3D vector map then z-coordinates are used.
    Used as: input, dbcolumn, name
where : str, optional
    WHERE conditions of SQL statement without 'where' keyword
    Example: elevation < 500 and elevation >= 1
    Used as: input, sql_query, sql_query
zscale : float, optional
    Conversion factor for values used for approximation
    Default: 1.0
cv_prefix : str, optional
    Prefix to use for cross-validation output maps
    Prefix for saved cross-validation error vector maps and interpolated deviation surfaces. If not set, cross-validation maps are temporary.
output_file : str, optional
    Output file
    Output file for the results in the selected format
    Used as: output, file, name
format : str, required
    Output format
    Used as: name
    Allowed values: plain, csv, json
    plain: Human readable table
    csv: CSV (Comma Separated Values)
    json: JSON (JavaScript Object Notation)
    Default: plain
nprocs : int, optional
    Number of threads for parallel computing
    0: use OpenMP default; >0: use nprocs; <0: use MAX-nprocs
    Default: 0
flags : str, optional
    Allowed values: t
    t
        Use scale dependent tension (recommended when tuning, makes tension transferable across point densities)
overwrite : bool, optional
    Allow output files to overwrite existing files
    Default: None
verbose : bool, optional
    Verbose module output
    Default: None
quiet : bool, optional
    Quiet module output
    Default: None
superquiet : bool, optional
    Very quiet module output
    Default: None

Returns:

result : grass.tools.support.ToolResult | None
If the tool produces text as standard output, a ToolResult object will be returned. Otherwise, None will be returned.

Raises:

grass.tools.ToolError: When the tool ended with an error.

point_cloud : str, required
    Name of the input point vector map
    Or data source for direct OGR access
    Used as: input, vector, name
mask : str, optional
    Name of the raster map used as mask
    Name of input raster map
    Used as: input, raster, name
tension : float | list[float] | str, optional
    Tension parameter values to cross-validate
    Default: 10,20,40,80,160
smooth : float | list[float] | str, optional
    Smoothing parameter values to cross-validate
    Default: 0.001,0.01,0.1,1.0,10.0
npmin : int | list[int] | str, optional
    Minimum number of points for approximation in a segment (>segmax)
    Multiple values are swept as an outer loop
segmax : int | list[int] | str, optional
    Maximum number of points in a segment
    Multiple values are swept as an outer loop
dmin : float | list[float] | str, optional
    Minimum distance between points (to remove almost identical points)
    Multiple values are swept as an outer loop
dmax : float | list[float] | str, optional
    Maximum distance between points on isoline (to insert additional points)
    Multiple values are swept as an outer loop
theta : float | list[float] | str, optional
    Anisotropy angle (in degrees counterclockwise from East)
    Multiple values are swept as an outer loop
scalex : float | list[float] | str, optional
    Anisotropy scaling factor
    Multiple values are swept as an outer loop
method : str, optional
    Search method over tension and smoothing (grid: full Cartesian product; refine: recursive refinement around the best cell)
    Allowed values: grid, refine
    Default: grid
levels : int, optional
    Maximum number of refinement levels for method=refine
    Default: 3
npoints : int, optional
    Cross-validate on a spatially stratified subsample of approximately this many points
seed : int, optional
    Seed value for the random number generator
    Using the same seed ensures identical results, while a randomly generated seed produces different outcomes in each run.
layer : str, optional
    Layer number or name
    Vector features can have category values in different layers. This number determines which layer to use. When used with direct OGR access this is the layer name.
    Used as: input, layer
    Default: 1
zcolumn : str, optional
    Name of the attribute column with values to be used for approximation
    If not given and input is 2D vector map then category values are used. If input is 3D vector map then z-coordinates are used.
    Used as: input, dbcolumn, name
where : str, optional
    WHERE conditions of SQL statement without 'where' keyword
    Example: elevation < 500 and elevation >= 1
    Used as: input, sql_query, sql_query
zscale : float, optional
    Conversion factor for values used for approximation
    Default: 1.0
cv_prefix : str, optional
    Prefix to use for cross-validation output maps
    Prefix for saved cross-validation error vector maps and interpolated deviation surfaces. If not set, cross-validation maps are temporary.
output_file : str, optional
    Output file
    Output file for the results in the selected format
    Used as: output, file, name
format : str, required
    Output format
    Used as: name
    Allowed values: plain, csv, json
    plain: Human readable table
    csv: CSV (Comma Separated Values)
    json: JSON (JavaScript Object Notation)
    Default: plain
nprocs : int, optional
    Number of threads for parallel computing
    0: use OpenMP default; >0: use nprocs; <0: use MAX-nprocs
    Default: 0
flags : str, optional
    Allowed values: t
    t
        Use scale dependent tension (recommended when tuning, makes tension transferable across point densities)
overwrite : bool, optional
    Allow output files to overwrite existing files
    Default: None
verbose : bool, optional
    Verbose module output
    Default: None
quiet : bool, optional
    Quiet module output
    Default: None
superquiet : bool, optional
    Very quiet module output
    Default: None

DESCRIPTION

v.surf.rst.cv finds well performing parameters for the regularized spline with tension (RST) interpolation implemented in v.surf.rst by running its leave-one-out cross-validation procedure over combinations of parameter values. For every combination, each input point is withheld in turn, the surface is approximated from the remaining points, and the predictive error (predicted minus observed value) is recorded. The tool summarizes the errors of every combination, reports the best one, and optionally saves the cross-validation error maps. The mask, zcolumn, where, zscale, and layer options are passed through unchanged to every v.surf.rst run.

The tension and smooth options accept lists of values and form the core search space. The remaining RST parameters (npmin, segmax, dmin, dmax, theta, scalex) also accept lists and are swept as an outer loop: every combination of their values is combined with the full tension and smoothing search. See the NOTES for why these parameters need more care when interpreting results.

Two search methods are available:

  • method=grid (default) evaluates the full Cartesian product of the tension and smoothing lists.
  • method=refine first evaluates the tension x smoothing grid and then recursively refines the search around the best combination: geometric midpoints between the best cell and its neighbors are evaluated, up to levels times or until the error differences within the refinement window become negligible. Use it to locate a finer optimum without enumerating a dense grid. When the best combination lies on the border of the searched range, a warning recommends widening the range.

Parameter combinations are cross-validated in parallel; nprocs controls the number of concurrent runs (each v.surf.rst process runs single threaded). A failing combination is reported as a row with an error instead of stopping the search.

Error metrics

For each combination the tool reports the number of cross-validated points (n), mean error (me, a measure of bias), mean absolute error (mae), root mean square error (rmse), median error, normalized median absolute deviation (nmad), the 68.3rd and 95th percentiles of the absolute error (p68, p95), the extreme errors, and the normalization factor (dnorm, see below). The best combination is selected by RMSE. The best combinations under MAE and NMAD are also reported; when the metrics disagree, the tool warns, because the selection is then driven by a small number of large errors and the residual distribution should be inspected before accepting the result.

The reported cross-validation error of the winning combination is an optimistic estimate of the accuracy of the final surface, because it was selected as the minimum over many candidates. Use an independent set of withheld points to estimate the accuracy of the resulting surface.

Tension, dnorm, and the -t flag

v.surf.rst internally normalizes coordinates by a factor

dnorm = sqrt(area * npmin / n)

where area is the bounding box of the points and n their count. The effective range of the spline is therefore proportional to dnorm/tension: the same tension value acts differently for different point counts, extents, and npmin settings. Consequences:

  • A tension optimized for one data set does not transfer to another data set, or even to a subsample of the same data set, unless the -t flag (scale dependent tension) is used. With -t, tension is rescaled by dnorm/1000 and acts on the real coordinates.
  • Sweeping npmin together with tension without -t compares different effective tensions across rows; the tool warns in this case.

The computed dnorm is reported for every combination, and with -t the rescaled tension is reported as tension_rescaled. The reported dnorm is derived from the bounding box of the input points and is approximate when the computational region clips part of the input.

Cross-validation on large data sets

Leave-one-out cross-validation is reasonable for up to several thousand points. For larger data sets, set npoints to cross-validate on a spatially stratified random subsample: one point is drawn per cell of a coarse grid sized to yield approximately npoints points, which preserves the spatial coverage of clustered point clouds better than simple random sampling. Use seed for a reproducible selection. Combine subsampling with the -t flag, otherwise the optimal tension found on the subsample does not apply at full point density (the tool warns about this).

Saved cross-validation maps

When cv_prefix is set, the cross-validation error vector map of every combination is kept as <cv_prefix>_<index> (the cvdev column of the report gives the map name for each row), the errors are interpolated into a raster map of the same name, and a diverging color scheme centered on the median error is applied to both. The error value is stored in the flt1 attribute column as predicted minus observed.

NOTES

Parameters swept in the outer loop change more than the model fit:

  • dmin removes nearly coincident points before interpolation and dmax inserts additional points along lines. Both change which points receive a cross-validation error, so error metrics of rows with different dmin or dmax values are computed over different point sets and are not directly comparable; compare the n column and interpret those rows with care (the tool warns when n differs).
  • npmin and segmax control segmentation. For data sets larger than 2 x npmin points, v.surf.rst requires npmin > segmax. To skip segmentation entirely for smaller data sets, set segmax = 2 x npmin.
  • theta and scalex (anisotropy) are supported, but the current v.surf.rst evaluates cross-validation errors without applying the anisotropy transformation used in the interpolation, so cross-validation results with anisotropy are unreliable until this is fixed in GRASS; the tool warns when they are used.

The cross-validation procedure works well only for well-sampled phenomena and when minimizing the predictive error is the goal. The parameters found by minimizing the predictive error may not be the best for poorly sampled phenomena (the result could be strongly smoothed with lost details and fluctuations) or when significant noise is present that needs to be smoothed out.

The computational region affects the result: points outside the region receive no cross-validation error and the default dmin is derived from the region resolution. Compare runs only within the same region.

Results are always printed to standard output; output_file writes the same content to a file in addition. With nprocs greater than one, the tool runs each combination in a temporary mapset named tmp_cv_* inside the current project to avoid database contention; these mapsets are removed when the tool ends, but may remain after a hard interruption and can then be removed manually.

Possible future extensions include k-fold cross-validation (which would also make dmin/dmax rows comparable), buffered leave-one-out for data with near-duplicate points, and spatially blocked cross-validation for gap-filling applications.

EXAMPLES

g.region raster=elevation res=30 n=220790 s=218390 w=632680 e=635910 -a
r.random input=elevation npoints=500 seed=0 vector=points -z
v.surf.rst.cv point_cloud=points tension=10,100 smooth=0.5,5.0 \
    segmax=600 nprocs=4 format=json output_file=test_cv.json

The JSON output contains one entry per combination and the best combinations per metric:

{
    "input": "points",
    "method": "grid",
    "scale_dependent_tension": false,
    "subsample": null,
    "region": {...},
    "warnings": [],
    "results": [
        {
            "tension": 100.0,
            "smooth": 0.5,
            "segmax": 600,
            "cvdev": null,
            "n": 500,
            "me": 0.005205,
            "mae": 2.006109,
            "rmse": 2.715355,
            "median": -0.224484,
            "nmad": 2.269,
            "p68": 2.305549,
            "p95": 5.610012,
            "min": -9.519708,
            "max": 9.506766,
            "error": null,
            "dnorm": 2149.976744
        },
        ...
    ],
    "best": {"rmse": {...}, "mae": {...}, "nmad": {...}}
}

A report of the best parameter combination is printed to stderr:

Best parameter combination (by RMSE)
--------------------------------------------------
Tension: 100
Smoothing: 0.5
segmax: 600
RMSE: 2.71536
MAE: 2.00611
NMAD: 2.269
--------------------------------------------------

Instead of a dense grid, refine around the best coarse cell:

v.surf.rst.cv point_cloud=points tension=10,40,160 smooth=0.01,0.1,1.0 \
    segmax=600 method=refine levels=3 nprocs=4

Sweeping structural parameters

Evaluate the effect of segmentation settings on the optimum, using scale dependent tension so tension values stay comparable across npmin:

v.surf.rst.cv -t point_cloud=points tension=10,40,160 smooth=0.01,0.1,1.0 \
    npmin=150,300 segmax=120 nprocs=4

Large data sets

Cross-validate on a spatially stratified subsample of 2000 points:

v.surf.rst.cv -t point_cloud=lidar_points npoints=2000 seed=42 nprocs=8

Saving the error maps

When cv_prefix is set, the error point maps are kept and interpolated into deviation surfaces:

v.surf.rst.cv point_cloud=points tension=10,100 smooth=0.5,5.0 \
    segmax=600 cv_prefix=cvdev nprocs=4

cdev-surface Tension: 100 Smooth: 0.5 cdev-surface Tension: 100 Smooth: 5 cdev-surface Tension: 10 Smooth: 0.5 cdev-surface Tension: 10 Smooth: 5

REFERENCES

  • Mitasova, H., Mitas, L. and Harmon, R.S., 2005, Simultaneous spline approximation and topographic analysis for lidar elevation data in open source GIS, IEEE GRSL 2 (4), 375- 379.
  • Hofierka, J., 2005, Interpolation of Radioactivity Data Using Regularized Spline with Tension. Applied GIS, Vol. 1, No. 2, pp. 16-01 to 16-13. DOI: 10.2104/ag050016
  • Hofierka J., Parajka J., Mitasova H., Mitas L., 2002, Multivariate Interpolation of Precipitation Using Regularized Spline with Tension. Transactions in GIS 6(2), pp. 135-150.
  • H. Mitasova, L. Mitas, B.M. Brown, D.P. Gerdes, I. Kosinovsky, 1995, Modeling spatially and temporally distributed phenomena: New methods and tools for GRASS GIS. International Journal of GIS, 9 (4), special issue on Integrating GIS and Environmental modeling, 433-446.
  • Mitasova, H. and Mitas, L., 1993: Interpolation by Regularized Spline with Tension: I. Theory and Implementation, Mathematical Geology ,25, 641-655.
  • Mitasova, H. and Hofierka, J., 1993: Interpolation by Regularized Spline with Tension: II. Application to Terrain Modeling and Surface Geometry Analysis, Mathematical Geology 25, 657-667.
  • Mitas, L., and Mitasova H., 1988, General variational approach to the approximation problem, Computers and Mathematics with Applications, v.16, p. 983-992.
  • Neteler, M. and Mitasova, H., 2008, Open Source GIS: A GRASS GIS Approach, 3rd Edition, Springer, New York, 406 pages.
  • Talmi, A. and Gilat, G., 1977 : Method for Smooth Approximation of Data, Journal of Computational Physics, 23, p.93-123.
  • Wahba, G., 1990, : Spline Models for Observational Data, CNMS-NSF Regional Conference series in applied mathematics, 59, SIAM, Philadelphia, Pennsylvania.

SEE ALSO

r.resamp.rst, v.surf.bspline, v.surf.idw, v.surf.rst, v.vol.rst

AUTHORS

Corey T. White NCSU GeoForAll Lab

SOURCE CODE

Available at: v.surf.rst.cv source code (history)
Latest change: Saturday Aug 22 18:58:28 2026 in commit 388bb1f