Merge branch 'main' of https://github.com/natcap/invest into bugfix/1917-gsutil-not-working-on-gha-macos-13

This commit is contained in:
James Douglass 2025-05-27 11:56:53 -07:00
commit f1fbbe36cb
6 changed files with 55 additions and 30 deletions

View File

@ -14,7 +14,7 @@ conda:
environment: .readthedocs_environment.yml
build:
os: ubuntu-22.04
os: ubuntu-24.04
tools:
python: "mambaforge-4.10"
jobs:

View File

@ -70,6 +70,25 @@ Workbench
existing user-added metadata preserved)
(`#1774 <https://github.com/natcap/invest/issues/1774>`_).
Coastal Blue Carbon
===================
* Updated the Coastal Blue Carbon documentation to clarify what happens when a
class transitions from a state of accumulation or decay to a No Carbon Change
("NCC") state. (`#671 <https://github.com/natcap/invest/issues/671>`_).
HRA
===
* The intermediate simplified vectors will now inherit their geometry type from
the input vectors, rather than using ``ogr.wkbUnknown``
(`#1881 <https://github.com/natcap/invest/issues/1881>`_).
NDR
===
* Fixed a bug in the effective retention calculation where nodata pour point
pixels were mistakenly used as real data. The effect of this change is most
pronounced along stream edges and should not affect the overall pattern of
results. (`#1845 <https://github.com/natcap/invest/issues/1845>`_)
3.15.1 (2025-05-06)
-------------------

View File

@ -93,8 +93,8 @@ here for several reasons:
"""
import logging
import os
import time
import shutil
import time
import numpy
import pandas
@ -103,13 +103,12 @@ import scipy.sparse
import taskgraph
from osgeo import gdal
from .. import utils
from .. import gettext
from .. import spec_utils
from ..unit_registry import u
from .. import utils
from .. import validation
from ..model_metadata import MODEL_METADATA
from .. import gettext
from ..unit_registry import u
LOGGER = logging.getLogger(__name__)
@ -328,7 +327,14 @@ MODEL_SPEC = {
"description": gettext("low carbon disturbance rate")
},
"NCC": {
"description": gettext("no change in carbon")
"description": gettext(
"no change in carbon. Defining 'NCC' for a "
"transition will halt any in-progress carbon "
"accumulation or emissions at the year of "
"transition, until the class transitions "
"again to a state of accumulation or "
"disturbance."
)
}
},
"about": gettext(

View File

@ -1629,14 +1629,12 @@ def _simplify(source_vector_path, tolerance, target_vector_path,
target_layer_name = os.path.splitext(
os.path.basename(target_vector_path))[0]
# Using wkbUnknown is important here because a user can provide a single
# vector with multiple geometry types. GPKG can handle whatever geom types
# we want it to use, but it will only be a conformant GPKG if and only if
# we set the layer type to ogr.wkbUnknown. Otherwise, the GPKG standard
# would expect that all geometries in a layer match the geom type of the
# layer and GDAL will raise a warning if that's not the case.
# Use the same geometry type from the source layer. This may be wkbUnknown
# if the layer contains multiple geometry types.
target_layer = target_vector.CreateLayer(
target_layer_name, source_layer.GetSpatialRef(), ogr.wkbUnknown)
target_layer_name,
srs=source_layer.GetSpatialRef(),
geom_type=source_layer.GetGeomType())
for field in source_layer.schema:
if field.GetName().lower() in preserve_columns:

View File

@ -177,6 +177,13 @@ void run_effective_retention(
neighbor.y < 0 or neighbor.y >= n_rows) {
continue;
}
neighbor_effective_retention = (
effective_retention_raster.get(
neighbor.x, neighbor.y));
if (is_close(neighbor_effective_retention, effective_retention_nodata)) {
continue;
}
if (neighbor.direction % 2 == 1) {
step_size = cell_size * 1.41421356237;
} else {
@ -189,10 +196,6 @@ void run_effective_retention(
current_step_factor = 0;
}
neighbor_effective_retention = (
effective_retention_raster.get(
neighbor.x, neighbor.y));
// Case 1: downslope neighbor is a stream pixel
if (neighbor_effective_retention == STREAM_EFFECTIVE_RETENTION) {
intermediate_retention = (
@ -222,7 +225,6 @@ void run_effective_retention(
}
}
// search upslope to see if we need to push a cell on the stack
// for i in range(8):
up_neighbors = UpslopeNeighbors<T>(Pixel<T>(flow_dir_raster, global_col, global_row));
for (auto neighbor: up_neighbors) {
neighbor_outflow_dir = INFLOW_OFFSETS[neighbor.direction];

View File

@ -152,10 +152,10 @@ class NDRTests(unittest.TestCase):
('p_surface_load', 41.826904),
('p_surface_export', 5.566120),
('n_surface_load', 2977.551270),
('n_surface_export', 274.020844),
('n_surface_export', 274.062129),
('n_subsurface_load', 28.558048),
('n_subsurface_export', 15.578484),
('n_total_export', 289.599314)]:
('n_total_export', 289.640609)]:
if not numpy.isclose(feature.GetField(field), value, atol=1e-2):
error_results[field] = (
'field', feature.GetField(field), value)
@ -226,12 +226,12 @@ class NDRTests(unittest.TestCase):
# results
expected_watershed_totals = {
'p_surface_load': 41.826904,
'p_surface_export': 5.870544,
'p_surface_export': 5.866880,
'n_surface_load': 2977.551270,
'n_surface_export': 274.020844,
'n_surface_export': 274.062129,
'n_subsurface_load': 28.558048,
'n_subsurface_export': 15.578484,
'n_total_export': 289.599314
'n_total_export': 289.640609
}
for field in expected_watershed_totals:
@ -306,12 +306,12 @@ class NDRTests(unittest.TestCase):
# results
for field, expected_value in [
('p_surface_load', 41.826904),
('p_surface_export', 4.915544),
('p_surface_export', 5.100640),
('n_surface_load', 2977.551914),
('n_surface_export', 320.082319),
('n_surface_export', 350.592891),
('n_subsurface_load', 28.558048),
('n_subsurface_export', 12.609187),
('n_total_export', 330.293407)]:
('n_total_export', 360.803969)]:
val = result_feature.GetField(field)
if not numpy.isclose(val, expected_value):
mismatch_list.append(
@ -361,12 +361,12 @@ class NDRTests(unittest.TestCase):
# results
for field, expected_value in [
('p_surface_load', 41.826904),
('p_surface_export', 5.870544),
('p_surface_export', 5.866880),
('n_surface_load', 2977.551270),
('n_surface_export', 274.020844),
('n_surface_export', 274.062129),
('n_subsurface_load', 28.558048),
('n_subsurface_export', 15.578484),
('n_total_export', 289.599314)]:
('n_total_export', 289.640609)]:
val = result_feature.GetField(field)
if not numpy.isclose(val, expected_value):
mismatch_list.append(