diff --git a/HISTORY.rst b/HISTORY.rst index dfa49b3025..348fd1442a 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -37,6 +37,14 @@ Unreleased Changes ------------------ +* Pollination + * Fixed an issue with nodata handling that was causing some outputs to be + filled either with the float32 value for positive infinity, or else with + a value very close to it. https://github.com/natcap/invest/issues/1635 + * While working on https://github.com/natcap/invest/issues/1635, we also + updated the stated dtype of most pollination model outputs to be float32 + instead of the float64 dtype that was being assumed previously. This + will result in smaller output filesizes with minimal loss of precision. * Workbench * Several small updates to the model input form UI to improve usability and visual consistency (https://github.com/natcap/invest/issues/912) diff --git a/src/natcap/invest/pollination.py b/src/natcap/invest/pollination.py index 60def5ec3e..e845f2180a 100644 --- a/src/natcap/invest/pollination.py +++ b/src/natcap/invest/pollination.py @@ -855,6 +855,7 @@ def execute(args): floral_resources_index_path_map[species], convolve_ps_path], target_path=pollinator_abundance_path, + target_dtype=numpy.float32, target_nodata=_INDEX_NODATA), dependent_task_list=[ foraged_flowers_index_task_map[(species, season)], @@ -935,7 +936,9 @@ def execute(args): rasters=[ half_saturation_raster_path, total_pollinator_abundance_index_path], - target_path=farm_pollinator_season_path), + target_path=farm_pollinator_season_path, + target_dtype=numpy.float32, + target_nodata=_INDEX_NODATA), dependent_task_list=[ half_saturation_task, total_pollinator_abundance_task[season]], target_path_list=[farm_pollinator_season_path])) @@ -976,7 +979,9 @@ def execute(args): kwargs=dict( op=pyt_op, rasters=[managed_pollinator_path, farm_pollinator_path], - target_path=total_pollinator_yield_path), + target_path=total_pollinator_yield_path, + target_dtype=numpy.float32, + target_nodata=_INDEX_NODATA), dependent_task_list=[farm_pollinator_task, managed_pollinator_task], target_path_list=[total_pollinator_yield_path]) @@ -984,12 +989,14 @@ def execute(args): wild_pollinator_yield_path = os.path.join( output_dir, _WILD_POLLINATOR_YIELD_FILE_PATTERN % file_suffix) wild_pollinator_task = task_graph.add_task( - task_name='calcualte_wild_pollinators', + task_name='calculate_wild_pollinators', func=pygeoprocessing.raster_map, kwargs=dict( op=pyw_op, rasters=[managed_pollinator_path, total_pollinator_yield_path], - target_path=wild_pollinator_yield_path), + target_path=wild_pollinator_yield_path, + target_dtype=numpy.float32, + target_nodata=_INDEX_NODATA), dependent_task_list=[pyt_task, managed_pollinator_task], target_path_list=[wild_pollinator_yield_path]) @@ -1392,7 +1399,8 @@ def _sum_arrays(*array_list): result = numpy.empty_like(array_list[0]) result[:] = 0 for array in array_list: - local_valid_mask = ~pygeoprocessing.array_equals_nodata(array, _INDEX_NODATA) + local_valid_mask = ~pygeoprocessing.array_equals_nodata( + array, _INDEX_NODATA) result[local_valid_mask] += array[local_valid_mask] valid_mask |= local_valid_mask result[~valid_mask] = _INDEX_NODATA @@ -1423,6 +1431,7 @@ def max_op(*substrate_index_arrays): pygeoprocessing.raster_map( op=max_op, rasters=substrate_path_list, + target_dtype=numpy.float32, target_path=target_habitat_nesting_index_path) @@ -1432,6 +1441,7 @@ def _multiply_by_scalar(raster_path, scalar, target_path): op=lambda array: array * scalar, rasters=[raster_path], target_path=target_path, + target_dtype=numpy.float32, target_nodata=_INDEX_NODATA, ) @@ -1455,6 +1465,7 @@ def _calculate_pollinator_supply_index( op=lambda f_r, h_n: species_abundance * f_r * h_n, rasters=[habitat_nesting_suitability_path, floral_resources_path], target_path=target_path, + target_dtype=numpy.float32, target_nodata=_INDEX_NODATA )