GlacioHack / xdem

Analysis of digital elevation models (DEMs)
https://xdem.readthedocs.io/
MIT License
139 stars 39 forks source link

[POC]: delete richdem from source #558

Open adebardo opened 2 months ago

adebardo commented 2 months ago

Context

The purpose of this ticket is to remove the dependency richdem in the source files to ensure its license does not alter the license of xdem.

Indeed, the GNU GPL v3.0 free license is strongly copyleft. In other words, it applies to:

The xDEM project falls into the third category, as it uses the Richdem API and imports the symbols exposed by this package (i.e., this library).

Code

@overload  
def maximum_curvature(  
    dem: RasterType,  
    resolution: float | tuple[float, float] | None = None,  
- use_richdem: bool = False,  
) -> RasterType:  
    ...

Test

The use of richdem in the tests does not impact the xdem license. Therefore, it is possible to keep the ground truth generated by xdem.

Two Solutions are Possible:

1 - Keep richdem

However, it is necessary to remove the tests that verify the outputs of richdem in certain APIs. Thus, we will no longer be able to generate the terrain ground truth as follows:

# Functions for RichDEM wrapper methods  
functions_richdem = {  
-    "slope_Horn": lambda dem: xdem.terrain.slope(dem, degrees=True, use_richdem=True),  
-    "aspect_Horn": lambda dem: xdem.terrain.aspect(dem, degrees=True, use_richdem=True),  
-    "hillshade_Horn": lambda dem: xdem.terrain.hillshade(dem, use_richdem=True),  
-    "curvature": lambda dem: xdem.terrain.curvature(dem, use_richdem=True),  
-    "profile_curvature": lambda dem: xdem.terrain.profile_curvature(dem, use_richdem=True),  
-    "planform_curvature": lambda dem: xdem.terrain.planform_curvature(dem, use_richdem=True),  
}

We will need to directly obtain their implementation.

Example for aspect:

def _get_terrainattr_richdem(rst: RasterType, attribute: str = "slope_radians") -> NDArrayf:  
    """  
 Derive terrain attribute for DEM opened with rasterio. One of "slope_degrees", "slope_percentage", "aspect", "profile_curvature", "planform_curvature", "curvature" and others (see RichDEM documentation). :param rst: DEM as raster :param attribute: RichDEM terrain attribute :return: """  
 rda = _raster_to_rda(rst)  
 terrattr = rd.TerrainAttribute(rda, attrib=attribute)  
 terrattr[terrattr == terrattr.no_data] = np.nan  

    return np.array(terrattr)
# The aspect of RichDEM is returned in degrees, we convert to radians to match the others  
terrain_attributes["aspect"] = np.deg2rad(_get_terrainattr_richdem(dem, attribute="aspect"))  
# For flat slopes, RichDEM returns a 90° aspect by default, while GDAL return a 180° aspect  
# We stay consistent with GDAL  
slope_tmp = _get_terrainattr_richdem(dem, attribute="slope_radians")  
terrain_attributes["aspect"][slope_tmp == 0] = np.pi

2 - Generate Terrain Truths

Documentation

README(.md|.rst|.txt)

Contribution Guide

Estimation

3 days

erikmannerfelt commented 1 month ago

A small comment to this. I do support removing it altogether (#127), but keeping it with a licensing clause that it's indeed an optional dependency sounds viable in the short-term too! The optional part is clear in setup.cfg.