------------------
* Adding explicit support for Python 3.9 and testing on Python 3.9.
* Fixed an issue in ``create_raster_from_vector_extents`` that would cause a
confusing exception to be raised if there was no geometry in the vector.
Now raises a ``ValueError`` with a helpful error message.
* Changed parameters in ``convolve_2d`` to allow API to set
``ignore_nodata_and_edges=True`` while ``mask_nodata=False`` and updated
docstring to indicate this is useful in cases such as filling nodata holes
in missing datasets. Additionally added a logger ``debug`` message to note
this "unusual" setting of these parameters in case of accidental usage
which could be noted during development.
* Fixed issue in zonal statistics that could cause the aggregate vector to be
locked due to a dereferencing race condition. This was present in some
cases with a flaky unit test but could have been seen in practice if the
vector was deleted immediately after the call to ``zonal_statistics``.
* Fixed issue in ``routing.fill_pits`` that used a numerical "is close" test
when determining if two pixels were at equal height. In the case of
hydrological pitfilling, pixels must be exactly equal height to be
considered a plateau otherwise a drain into or out of the pixel is
resolved. Testing is close allowed a hydrological pit to remain since it
was "close" to the same height as a draining pixel.
* Added a D8 Strahler order stream extraction function at
``pygeoprocessing.extract_strahler_streams_d8``. Creates segmented
geometric lines which correspond to streams on the landscape.
* Added a D8 subwatershed calculation function at
``pygeoprocessing.calculate_subwatershed_boundary``. Creates subwatersheds
that are segmented at the junctions of the streams created by
``pygeoprocessing.extract_strahler_streams_d8``.
* Removing all instances of ``__swig_destroy__`` to prevent multiprocessing
memory corruption.
* Exposing a ``use_shared_memory`` flag on ``raster_calculator`` to allow
a user to use shared memory objects when calculating statistics. This
feature is only available for Python >= 3.8. If available, this
feature creates a significant runtime improvement but can be unstable
in multiprocessing configurations. For this reason it is set to
``False`` as the default value.
* Added a ``max_timeout`` parameter to ``convolve_2d`` and
``raster_calculator`` to allow the user to specify the maximum amount of
time to wait for worker threads to terminate. In normal operation these
threads should terminate in a short amount of time but are generously
timed with the ``pygeoprocessing._MAX_TIMEOUT`` parameter. This parameter
allows a user to tune in cases that may involve significant latency such
as in a heavy multiprocess environment.
* Added a ``pygeoprocessing.routing.detect_outlets`` function that creates a
vector with points placed on the center of the pixels in a D8 or MFD flow
direction raster that are outlet pixels. The vector has additional metadata
about the (i, j) locations of the pixel in raster coordinate space.
* Replacing ``merge_rasters`` with ``stitch_rasters`` that can take an
arbitrary list of raster path bands and stitch them into an existing raster
of same or different projection. Additional functionality to preserve
area variant values when stitching from a linear meters projection to
WGS84. Useful when the units of the base raster are in "units per pixel"
rather than "units per area".
* Added a ``max_pixel_fill_count`` parameter to ``routing.fill_pits`` to
guard against pitfilling large natural depression. Defaults to 500.
* Fixed an issue in ``align_and_resize_raster_stack`` that would ignore
the bounds of a feature in a mask vector if the
``"mask_vector_where_filter"`` clause was invoked and instead only
considered the entire bounds of the vector.
* Fixed an issue with ``convolve_2d`` that allowed output rasters to be
created without a defined nodata value.
* Fixed a LOGGER message bug that occurred in ``zonal_statistics``.
* Fixed an issue in ``distance_to_channel_mfd`` that would generate a raster
with distances to the edge of the raster even if there was no channel. Now
generates nodata so it is consistent with ``distance_to_channel_d8``.
* The ``convolve_2d`` function now raises a ValueError if either the signal
or kernel raster has a row based blocksize since this could result in
very long runtimes due to gdal cache thrashing.
* Fixed an issue that would cause a ``convolve_2d`` worker to crash if the
integrating kernel was not a float and also ``normalize_kernel=True``
thus causing the entire function call to deadlock.
* Added a check on ``transform_bounding_box`` to ensure the target bounding
box's coordinates were finite. This guards against cases where a transform
into another coordinate system creates a degenerate bounding box.
Previously the function would silently return non-finite coordinates.
* Fixing issue when calculating histogram for floating point rasters the
logging progress percent would be incorrectly calculated.