# check if in at least one of multiple habitat ranges
def in_hab(*ranges: tuple[int, int]) -> bool:
return any((r[0] <= map_code < r[1]) for r in ranges)
if h is not None:
if refine_method == "forest" or refine_method == "forest_add308":
h["resistance"] = 0 if in_hab(self.FORESTS) else h["resistance"]
elif refine_method == "forest_africa":
# will have the forest and shrublands set to 0 regardless of the habitat data
h["resistance"] = 0 if in_hab(self.FORESTS, self.SHRUBLANDS) else h["resistance"]
writer.writerow(h.values())
else:
if refine_method == "forest" or refine_method == "forest_add308":
writer.writerow([""] * 5 + [map_code] + [0 if in_hab(self.FORESTS) else 1])
elif refine_method == "forest_africa":
resistance = 1
if in_hab(self.FORESTS, self.SHRUBLANDS):
resistance = 0
elif in_hab(self.INTRODUCED_VEGETATION):
resistance = 0.1
elif in_hab(
self.SAVANNAS,
self.GRASSLANDS,
self.WETLANDS,
self.ROCKY,
self.CAVES,
self.OTHER,
self.UNKNOWN,
):
resistance = 0.9
elif in_hab(
self.DESERTS,
self.MARINE_NERITIC,
self.MARINE_OCEANIC,
self.MARINE_DEEP,
self.MARINE_INTERTIDAL,
self.MARINE_COSTAL,
self.ARTIFICIAL,
):
resistance = 1
I have the following issues with it.
First, there seem to be some errors. For example, there are branches that are taken if the terrain code is 308, but then 308 is not considered among self.FOREST.
Second, I think these refinements should happen elsewhere. This layers package should be tasked with deriving terrain and habitat rasters, and some standard simple resistance values. We can then do any post-processing we need in some other place.
As an example of the second point, it's not reasonable to add a forest_africa method -- the africa work should post-process the csv any way they want for resistance.
Rather, this package should be mainly concerned with getting the habitat raster right.
In regards to your second point it sounds like you want to make a new tool. This new tool could either generate resistance.csv's or it could generate a permeability layer. I could create this tool once we define what we would like it to do.
When this tool is made we can remove the resitance.csv creation from this tool. This should remove the need for refinement methods as this can happen in the new tool.
However, these resistance values are still potential needed for defining what the current habitat of the species.
There would need to be a standard way to define habitat. This would be needed as this tool could be used for more than just forest birds.
This could be done by saying where ever the habitat is major-importance which is 0 resistance. This would not follow the original paper though as in that paper it ignores IUCN habitat data and just says any forest is habitat.
Paper reproducibility could be fixed also by having a parameter that would allow overwriting the standard of using just major-importance with a list of map codes that should be the current habitat.
Regarding your first point, these definitions of ranges follow the IUCN documentation. It can be found here: https://www.iucnredlist.org/resources/habitat-classification-scheme . In this classification documentation it say that 3.8 which is 308 is a shrubland. It might be confusing if we drift from this documentation.
Let me know what your thoughts are and I will take appropriate action.
I removed the following code:
I have the following issues with it.
As an example of the second point, it's not reasonable to add a forest_africa method -- the africa work should post-process the csv any way they want for resistance.
Rather, this package should be mainly concerned with getting the habitat raster right.