# geo pack 35 nodes, in `noodlelab[geo]` and above. ## Geo/Plot (node-geo.map_plot)= ### Map Plot `geo.map_plot` A map from any mix of layers, drawn bottom to top: hillshade, raster, polygons, lines, points. Layers are projected to the CRS of the first of raster, polygons, lines and points. Classified rasters get a legend, other rasters and numeric point colours a colour bar; the default class colours suit land cover (water, bare, grassland, forest), ``class_colors`` sets others. **Inputs** | Name | Type | Description | |---|---|---| | `raster` | `Raster \| None` | Optional. | | `hillshade` | `Raster \| None` | Grey relief drawn under the raster Optional. | | `polygons` | `GeoDataFrame \| None` | Optional. | | `lines` | `GeoDataFrame \| None` | Optional. | | `points` | `GeoDataFrame \| None` | Optional. | | `polygon_color` | `str` | Fill by column Default `''`. | | `polygon_labels` | `str` | Label column Default `''`. | | `point_color` | `str` | Colour by column Default `''`. | | `point_labels` | `str` | Label column Default `''`. | | `point_size` | `float` | Default `18.0`. | | `size_by` | `str` | Scale by column Default `''`. | | `raster_colormap` | `Literal['viridis', 'terrain', 'gist_earth', 'RdYlGn', 'YlGnBu', 'YlOrRd', 'magma', 'Blues', 'coolwarm', 'Greys']` | Default `'viridis'`. | | `class_colors` | `str` | Classified rasters: one colour per class, e.g. #2e7d32, #f2c14e, #d7301f Default `''`. | | `point_colormap` | `Literal['viridis', 'plasma', 'YlOrRd', 'RdYlBu_r', 'coolwarm', 'magma']` | Default `'YlOrRd'`. | | `raster_label` | `str` | Default `''`. | | `point_label` | `str` | Default `''`. | | `title` | `str` | Default `''`. | | `scale_bar` | `bool` | Default `True`. | | `north_arrow` | `bool` | Default `True`. | | `width` | `float` | Inches Default `6.5`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `Figure` | | ## Geo/Raster (node-geo.classify)= ### Classify `geo.classify` Group values into classes (e.g. NDVI into land cover), and the area of each class. A value equal to a break goes into the upper class. **Inputs** | Name | Type | Description | |---|---|---| | `raster` | `Raster` | | | `breaks` | `str` | Class boundaries, ascending: 0.1, 0.3, 0.6 Default `'0.1, 0.3, 0.6'`. | | `labels` | `str` | One more label than breaks Default `'water, bare, grassland, forest'`. | | `area_unit` | `Literal['km²', 'ha', 'm²']` | Default `'km²'`. | **Outputs** | Name | Type | Description | |---|---|---| | `classes` | `Raster` | | | `areas` | `DataFrame` | | (node-geo.hillshade)= ### Hillshade `geo.hillshade` Shaded relief, 0 (dark) to 1 (lit), as seen with the sun at the given direction and height: the classic map backdrop for terrain. **Inputs** | Name | Type | Description | |---|---|---| | `dem` | `Raster` | | | `azimuth` | `float` | Sun direction, degrees from north Default `315.0`. | | `altitude` | `float` | Sun height, degrees Default `45.0`. | | `z_factor` | `float` | Default `1.0`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `Raster` | | (node-geo.idw_interpolation)= ### IDW Interpolation `geo.idw_interpolation` Interpolate point measurements onto a grid by inverse distance weighting: each cell is the average of its nearest points, weighted by 1/distanceᵖ. Uses the template's grid if one is linked (to line up with other rasters), otherwise the points' extent. Points in longitude and latitude are projected to UTM first. **Inputs** | Name | Type | Description | |---|---|---| | `points` | `GeoDataFrame` | | | `value` | `str` | Default `''`. | | `template` | `Raster \| None` | Optional. | | `cell` | `float` | Cell size in metres, without a template Default `100.0`. | | `power` | `float` | Default `2.0`. | | `neighbours` | `int` | Default `12`. | | `padding` | `float` | Metres added around the points Default `0.0`. | | `name` | `str` | Default `''`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `Raster` | | (node-geo.mask_raster)= ### Mask Raster `geo.mask_raster` Keep the cells inside the polygons (or outside, inverted); the rest become missing. **Inputs** | Name | Type | Description | |---|---|---| | `raster` | `Raster` | | | `polygons` | `GeoDataFrame` | | | `invert` | `bool` | Default `False`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `Raster` | | (node-geo.normalized_difference)= ### Normalized Difference `geo.normalized_difference` (A − B) / (A + B), between −1 and 1: with A = near infrared and B = red, the vegetation index NDVI; with green and NIR, the water index NDWI. **Inputs** | Name | Type | Description | |---|---|---| | `a` | `Raster` | | | `b` | `Raster` | | | `name` | `str` | Default `'NDVI'`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `Raster` | | (node-geo.point_density)= ### Point Density `geo.point_density` Kernel density: how many points (or how much weight) per km², smoothed with a Gaussian of the given bandwidth. Hot spots of events such as earthquakes or observations. **Inputs** | Name | Type | Description | |---|---|---| | `points` | `GeoDataFrame` | | | `template` | `Raster \| None` | Optional. | | `cell` | `float` | Cell size in metres, without a template Default `1000.0`. | | `bandwidth` | `float` | Smoothing radius in metres Default `5000.0`. | | `padding` | `float` | Metres added around the points Default `10000.0`. | | `weight` | `str` | Weight column Default `''`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `Raster` | | (node-geo.raster_math)= ### Raster Math `geo.raster_math` Cell-by-cell arithmetic between two rasters on the same grid, or a raster and a number. Comparisons give 1 (true) and 0 (false). **Inputs** | Name | Type | Description | |---|---|---| | `a` | `Raster` | | | `b` | `Raster \| None` | Optional. | | `value` | `float` | Used when B is not linked Default `1.0`. | | `operation` | `Literal['add', 'subtract', 'multiply', 'divide', 'power', 'minimum', 'maximum', 'greater than', 'less than', 'equal']` | Default `'multiply'`. | | `name` | `str` | Default `''`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `Raster` | | (node-geo.raster_statistics)= ### Raster Statistics `geo.raster_statistics` Summary statistics of the valid cells, and the area they cover (km², for rasters in metres). **Inputs** | Name | Type | Description | |---|---|---| | `raster` | `Raster` | | **Outputs** | Name | Type | Description | |---|---|---| | `mean` | `float` | | | `std` | `float` | | | `minimum` | `float` | | | `maximum` | `float` | | | `valid_cells` | `int` | | | `area_km2` | `float` | | | `summary` | `dict[str, Any]` | | (node-geo.raster_values)= ### Raster Values `geo.raster_values` The raster's valid (non-missing) values as a flat array, for histograms and statistics. Inserted when a raster is linked into an array input. **Inputs** | Name | Type | Description | |---|---|---| | `raster` | `Raster` | | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `NDArray[float64]` | | (node-geo.read_ascii_grid)= ### Read ASCII Grid `geo.read_ascii_grid` Read an ESRI ASCII grid (.asc), the plain-text raster format most GIS programs export. The CRS comes from a .prj file with the same name, or is given here. No-data cells become NaN. **Inputs** | Name | Type | Description | |---|---|---| | `path` | `FileRef` | | | `crs` | `str` | EPSG code; empty: from the .prj file next to it Default `''`. | | `name` | `str` | Default `''`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `Raster` | | (node-geo.read_raster)= ### Read Raster `geo.read_raster` Read one band of a GeoTIFF, or of any raster GDAL reads (.vrt, .img, .jp2, NetCDF...), as a grid of floats. No-data cells become NaN, and the CRS comes from the file. **Inputs** | Name | Type | Description | |---|---|---| | `path` | `FileRef` | | | `band` | `int` | Which band, from 1 Default `1`. | | `name` | `str` | Default `''`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `Raster` | | (node-geo.reclassify)= ### Reclassify `geo.reclassify` Give each class of a classified raster a number, such as a runoff coefficient or a roughness per land-cover class. **Inputs** | Name | Type | Description | |---|---|---| | `classes` | `Raster` | | | `values` | `str` | One number per class, in class order: 1.0, 0.6, 0.35, 0.2 Default `''`. | | `name` | `str` | Default `''`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `Raster` | | (node-geo.sample_raster)= ### Sample Raster `geo.sample_raster` Add the raster value under each point as a column (the cell the point falls in; NaN outside the grid). **Inputs** | Name | Type | Description | |---|---|---| | `points` | `GeoDataFrame` | | | `raster` | `Raster` | | | `name` | `str` | Default `''`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `GeoDataFrame` | | (node-geo.slope_aspect)= ### Slope & Aspect `geo.slope_aspect` Terrain slope in degrees (0 = flat) and aspect, the compass direction the slope faces (0 = north, 90 = east), from an elevation model in a projected CRS. **Inputs** | Name | Type | Description | |---|---|---| | `dem` | `Raster` | | | `z_factor` | `float` | Elevation units per horizontal unit Default `1.0`. | **Outputs** | Name | Type | Description | |---|---|---| | `slope` | `Raster` | | | `aspect` | `Raster` | | (node-geo.zonal_statistics)= ### Zonal Statistics `geo.zonal_statistics` Summarise a raster inside each polygon: mean, min, max, standard deviation, and the area covered (km²); optionally the share above a threshold (e.g. of an interpolated concentration over a limit), or, for a classified raster, the share of each class. A cell belongs to a zone when its centre is inside. **Inputs** | Name | Type | Description | |---|---|---| | `zones` | `GeoDataFrame` | | | `raster` | `Raster` | | | `prefix` | `str` | Column name prefix; empty: the raster's name Default `''`. | | `threshold` | `float` | Default `0.0`. | | `share_above` | `bool` | Add the % of each zone's area above the threshold Default `False`. | | `categories` | `bool` | Classified raster: the % of each zone in each class Default `False`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `GeoDataFrame` | | ## Geo/Seismology (node-geo.gutenberg_richter)= ### Gutenberg-Richter `geo.gutenberg_richter` The magnitude–frequency distribution log₁₀ N(≥M) = a − b·M of a catalogue. **Inputs** | Name | Type | Description | |---|---|---| | `catalog` | `DataFrame` | | | `magnitude` | `str` | Default `'magnitude'`. | | `bin_width` | `float` | Default `0.1`. | | `completeness` | `Literal['maximum curvature', 'fixed']` | Default `'maximum curvature'`. | | `mc` | `float` | The fixed magnitude of completeness Default `2.0`. | | `correction` | `float` | Added to the maximum-curvature estimate (often 0.2) Default `0.2`. | **Outputs** | Name | Type | Description | |---|---|---| | `b_value` | `float` | | | `b_error` | `float` | | | `a_value` | `float` | | | `completeness` | `float` | | | `events` | `int` | | | `table` | `DataFrame` | | | `plot` | `Figure` | | | `summary` | `dict[str, Any]` | | ## Geo/Track (node-geo.track_statistics)= ### Track Statistics `geo.track_statistics` Analyse a GPS log (one row per fix, in time order): the geodesic distance on the WGS84 ellipsoid, speed, grade, total ascent and descent (from lightly smoothed elevation, so GPS noise does not add up), and moving time. **Inputs** | Name | Type | Description | |---|---|---| | `table` | `DataFrame` | | | `time` | `str` | Default `'time'`. | | `lat` | `str` | Default `'lat'`. | | `lon` | `str` | Default `'lon'`. | | `elevation` | `str` | Metres; none: no climbing figures Default `'elevation'`. | | `stopped_below` | `float` | km/h: slower counts as stopped Default `1.0`. | | `smoothing` | `int` | Points in the elevation smoothing window Default `5`. | **Outputs** | Name | Type | Description | |---|---|---| | `points` | `DataFrame` | | | `line` | `GeoDataFrame` | | | `distance` | `Quantity[km]` | | | `ascent` | `Quantity[m]` | | | `descent` | `Quantity[m]` | | | `moving_time` | `Quantity[h]` | | | `total_time` | `Quantity[h]` | | | `moving_speed` | `Quantity[km/h]` | | | `summary` | `dict[str, Any]` | | ## Geo/Vector (node-geo.add_coordinates)= ### Add Coordinates `geo.add_coordinates` Add each feature's x and y (of its centroid, for lines and polygons) as columns, for tables in reports or plots. **Inputs** | Name | Type | Description | |---|---|---| | `data` | `GeoDataFrame` | | | `crs` | `str` | The coordinates' CRS; empty: the data's Default `'EPSG:4326'`. | | `x_name` | `str` | Default `'lon'`. | | `y_name` | `str` | Default `'lat'`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `GeoDataFrame` | | (node-geo.as_features)= ### As Features `geo.as_features` Features again after table nodes: the table nodes (Add Column, Filter Rows, Join Tables, ...) work on GeoDataFrames too, but say they return a plain table. This passes a GeoDataFrame through, or rebuilds one from a ``geometry`` column. Offered when such a table is linked into a features input. **Inputs** | Name | Type | Description | |---|---|---| | `table` | `DataFrame` | | | `crs` | `str` | Only for tables that lost their CRS Default `''`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `GeoDataFrame` | | (node-geo.buffer)= ### Buffer `geo.buffer` The area within a distance of each feature, e.g. a protection zone around a river. Computed in metres whatever the CRS; the result is in the input's CRS. **Inputs** | Name | Type | Description | |---|---|---| | `data` | `GeoDataFrame` | | | `distance` | `Quantity[m]` | Default `'100.0 m'`. | | `merge` | `bool` | Merge overlapping buffers into one area Default `False`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `GeoDataFrame` | | (node-geo.centroids)= ### Centroids `geo.centroids` The centre point of each feature (computed in metres, returned in the input's CRS). **Inputs** | Name | Type | Description | |---|---|---| | `data` | `GeoDataFrame` | | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `GeoDataFrame` | | (node-geo.clip)= ### Clip `geo.clip` Cut features to the area of the mask polygons (points outside are dropped). **Inputs** | Name | Type | Description | |---|---|---| | `data` | `GeoDataFrame` | | | `mask` | `GeoDataFrame` | | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `GeoDataFrame` | | (node-geo.count_in_polygons)= ### Count In Polygons `geo.count_in_polygons` How many points fall in each polygon (earthquakes per region, samples per district), optionally with an aggregate of a point attribute and the density per km². **Inputs** | Name | Type | Description | |---|---|---| | `polygons` | `GeoDataFrame` | | | `points` | `GeoDataFrame` | | | `name` | `str` | Default `'count'`. | | `value` | `str` | Also aggregate this column Default `''`. | | `aggregate` | `Literal['mean', 'sum', 'max', 'min', 'median']` | Default `'mean'`. | | `density` | `bool` | Also add the count per km² Default `True`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `GeoDataFrame` | | (node-geo.dissolve)= ### Dissolve `geo.dissolve` Merge features into one per group, aggregating their numeric columns. **Inputs** | Name | Type | Description | |---|---|---| | `data` | `GeoDataFrame` | | | `by` | `str` | Merge features with the same value Default `''`. | | `aggregate` | `Literal['first', 'sum', 'mean', 'min', 'max', 'count']` | Default `'sum'`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `GeoDataFrame` | | (node-geo.distance_to_nearest)= ### Distance To Nearest `geo.distance_to_nearest` Add the distance in metres from each feature to the nearest target feature (e.g. wells to the river), computed in a metric CRS. **Inputs** | Name | Type | Description | |---|---|---| | `data` | `GeoDataFrame` | | | `targets` | `GeoDataFrame` | | | `name` | `str` | Default `'distance_m'`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `GeoDataFrame` | | (node-geo.filter_features)= ### Filter Features `geo.filter_features` Keep the features matching a condition on their attributes. **Inputs** | Name | Type | Description | |---|---|---| | `data` | `GeoDataFrame` | | | `condition` | `str` | A pandas query on the columns: magnitude >= 3 and type == "well" Default `''`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `GeoDataFrame` | | (node-geo.measure)= ### Measure `geo.measure` Add each feature's area and perimeter (polygons) or length (lines) as columns. Longitude/latitude data is measured on the ellipsoid (geodesic), projected data in its own units (metres). **Inputs** | Name | Type | Description | |---|---|---| | `data` | `GeoDataFrame` | | | `area_unit` | `Literal['km²', 'ha', 'm²']` | Default `'km²'`. | | `length_unit` | `Literal['km', 'm']` | Default `'km'`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `GeoDataFrame` | | (node-geo.points_from_table)= ### Points From Table `geo.points_from_table` Make point features from two coordinate columns, e.g. station or sample locations in a CSV. Rows without coordinates are dropped. **Inputs** | Name | Type | Description | |---|---|---| | `table` | `DataFrame` | | | `x` | `str` | Default `'lon'`. | | `y` | `str` | Default `'lat'`. | | `crs` | `str` | The CRS of the coordinates Default `'EPSG:4326'`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `GeoDataFrame` | | (node-geo.read_vector)= ### Read Vector File `geo.read_vector` Read GeoJSON, GeoPackage, Shapefile or FlatGeobuf features, from the workspace or remote storage (downloaded once and cached). **Inputs** | Name | Type | Description | |---|---|---| | `path` | `FileRef` | | | `layer` | `str` | For GeoPackages with several layers Default `''`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `GeoDataFrame` | | (node-geo.reproject)= ### Reproject `geo.reproject` Transform the coordinates to another CRS: UTM for metres, EPSG:4326 for longitude and latitude, or a national grid. **Inputs** | Name | Type | Description | |---|---|---| | `data` | `GeoDataFrame` | | | `crs` | `str` | An EPSG code, or "UTM" for the UTM zone of the data Default `'UTM'`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `GeoDataFrame` | | (node-geo.spatial_join)= ### Spatial Join `geo.spatial_join` Attach the attributes of ``right`` to each feature of ``left`` by their spatial relation: the district each well lies within, or the nearest river (with the distance in metres in ``distance_m``). **Inputs** | Name | Type | Description | |---|---|---| | `left` | `GeoDataFrame` | | | `right` | `GeoDataFrame` | | | `relation` | `Literal['within', 'intersects', 'contains', 'nearest']` | Default `'within'`. | | `keep` | `Literal['all left features', 'matches only']` | Default `'all left features'`. | | `max_distance` | `Quantity[m]` | Nearest only; 0 m: no limit Default `'0.0 m'`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `GeoDataFrame` | | ## Output (node-geo.save_ascii_grid)= ### Save ASCII Grid `geo.save_ascii_grid` Write a raster as an ESRI ASCII grid into this run's output folder, with a .prj file for its CRS. **Inputs** | Name | Type | Description | |---|---|---| | `raster` | `Raster` | | | `filename` | `str` | Default `'grid.asc'`. | | `decimals` | `int` | Default `3`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `Path` | | (node-geo.save_geotiff)= ### Save GeoTIFF `geo.save_geotiff` Write a raster as a compressed GeoTIFF (float32, NaN as no-data) into this run's output folder. **Inputs** | Name | Type | Description | |---|---|---| | `raster` | `Raster` | | | `filename` | `str` | Default `'raster.tif'`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `Path` | | (node-geo.save_vector)= ### Save Vector File `geo.save_vector` Write features into this run's output folder. The extension picks the format: .geojson, .gpkg (GeoPackage) or .fgb (FlatGeobuf). **Inputs** | Name | Type | Description | |---|---|---| | `data` | `GeoDataFrame` | | | `filename` | `str` | Default `'features.geojson'`. | **Outputs** | Name | Type | Description | |---|---|---| | `result` | `Path` | |