Merge branch 'main' of https://github.com/natcap/invest into bugfix/1917-gsutil-not-working-on-gha-macos-13
This commit is contained in:
commit
f1fbbe36cb
|
@ -14,7 +14,7 @@ conda:
|
|||
environment: .readthedocs_environment.yml
|
||||
|
||||
build:
|
||||
os: ubuntu-22.04
|
||||
os: ubuntu-24.04
|
||||
tools:
|
||||
python: "mambaforge-4.10"
|
||||
jobs:
|
||||
|
|
19
HISTORY.rst
19
HISTORY.rst
|
@ -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)
|
||||
-------------------
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Reference in New Issue