Update calculations to ensure accurate raster totals in HTML report

This commit is contained in:
Emily Davis 2024-11-27 16:52:31 -07:00
parent a2a5862d4c
commit edfac6727f
2 changed files with 52 additions and 8 deletions

View File

@ -673,11 +673,17 @@ def _generate_report(raster_file_set, model_args, file_registry):
for raster_uri, description, units in report:
if raster_uri in raster_file_set:
summary_stat = _accumulate_totals(raster_uri)
total = _accumulate_totals(raster_uri)
raster_info = pygeoprocessing.get_raster_info(raster_uri)
pixel_area = abs(numpy.prod(raster_info['pixel_size']))
# Since each pixel value is in Mg/ha, ``total`` is in (Mg/ha * px) = Mg•px/ha.
# Adjusted sum = ([total] Mg•px/ha) * ([pixel_area] m^2 / 1 px) * (1 ha / 10000 m^2) = Mg.
summary_stat = total * pixel_area / 10000
report_doc.write(
'<tr><td>%s</td><td class="number">%.2f</td><td>%s</td>'
'<td>%s</td></tr>' % (
description, summary_stat, units, raster_uri))
'<tr><td>%s</td><td class="number" data-summary-stat="%s">'
'%.2f</td><td>%s</td><td>%s</td></tr>' % (
description, description, summary_stat, units,
raster_uri))
report_doc.write('</body></html>')

View File

@ -4,6 +4,7 @@ import unittest
import tempfile
import shutil
import os
import re
from osgeo import gdal
from osgeo import osr
@ -91,6 +92,28 @@ def make_pools_csv(pools_csv_path):
open_table.write('2,1,5,0,3,"lulc code 3"\n')
def assert_aggregate_result_equal(html_report_path, stat_name, val_to_compare):
"""Assert that the given stat in the HTML report has a specific value.
Args:
html_report_path (str): path to the HTML report generated by the model.
stat_name (str): name of the stat to find. Must match the name listed
in the HTML.
val_to_compare (float): the value to check against.
Returns:
None.
"""
with open(html_report_path) as file:
report = file.read()
pattern = (r'data-summary-stat="'
+ stat_name
+ r'">(\-?\d+\.\d{2})</td>')
match = re.search(pattern, report)
stat_str = match.groups()[0]
assert float(stat_str) == val_to_compare
class CarbonTests(unittest.TestCase):
"""Tests for the Carbon Model."""
@ -132,14 +155,14 @@ class CarbonTests(unittest.TestCase):
carbon.execute(args)
# Ensure totals are correct.
# Current: 15 + 10 + 60 + 1 = 86 Mg
# Ensure every pixel has the correct total C value.
# Current: 15 + 10 + 60 + 1 = 86 Mg/ha
assert_raster_equal_value(
os.path.join(args['workspace_dir'], 'tot_c_cur.tif'), 86)
# Future: 5 + 3 + 20 + 0 = 28 Mg
# Future: 5 + 3 + 20 + 0 = 28 Mg/ha
assert_raster_equal_value(
os.path.join(args['workspace_dir'], 'tot_c_fut.tif'), 28)
# REDD: 2 + 1 + 5 + 0 = 8 Mg
# REDD: 2 + 1 + 5 + 0 = 8 Mg/ha
assert_raster_equal_value(
os.path.join(args['workspace_dir'], 'tot_c_redd.tif'), 8)
@ -158,6 +181,21 @@ class CarbonTests(unittest.TestCase):
assert_raster_equal_value(
os.path.join(args['workspace_dir'], 'npv_redd.tif'), -4602.106)
# Ensure aggregate results are correct.
report_path = os.path.join(args['workspace_dir'], 'report.html')
# Raster size is 100 m^2; therefore, raster total is as follows:
# (x Mg / 1 ha) * (1 ha / 10000 m^2) * (100 m^2) = (x / 100) Mg
for (stat, expected_value) in [
('Total cur', 0.86),
('Total fut', 0.28),
('Total redd', 0.08),
('Change in C for fut', -0.58),
('Change in C for redd', -0.78),
('Net present value from cur to fut', -34.22),
('Net present value from cur to redd', -46.02),
]:
assert_aggregate_result_equal(report_path, stat, expected_value)
def test_carbon_zero_rates(self):
"""Carbon: test with 0 discount and rate change."""
from natcap.invest import carbon