Skip to content

Commit cbc724a

Browse files
authored
Merge pull request #23 from quantifyearth/mwd-expand-tests
Add some tests for major parts of AOH calc and habitat processing scripts
2 parents 262af5a + f5be055 commit cbc724a

File tree

7 files changed

+706
-11
lines changed

7 files changed

+706
-11
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ To calculate the AoH we need the following information:
6363
- Habitats: A directory containing a series of GeoTIFFs, one per habitat class, indicating which pixels contain that habitat. Float values indicate partial occupancy.
6464
- Elevation-max/Elevation-min: Two GeoTIFFs, in which the highest and lowest elevation for that pixel is recorded. Must be in same units as those in the GeoJSON.
6565
- Crosswalk: A crosswalk table in CSV format that converts between the IUCN habitat classes and names of the habitat raster layers.
66-
- Area: An optiona raster containing the area of each pixel, which will be multipled with the AoH raster before saving to produce a result in area rahter than pixel occupancy.
66+
- Area: An optiona raster containing the area of each pixel, which will be multipled with the AoH raster before saving to produce a result in area rather than pixel occupancy.
6767
- Force habitat: An optional flag that means rather than following the IUCN RLTWG guidelines, whereby if there is zero area in the habitat layer after filtering for species habitat preferneces we should revert to range, this flag will keep the result as zero. This is to allow for evaluation of scenarios that might lead to extinction via land use chnages.
6868
- Output directory - Two files will be output to this directory: an AoH raster with the format `{id_no}_{seasonal}.tif` and a manifest containing information about the raster `{id_no}_{seasonal}.json`.
6969

aohcalc.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import logging
66
import sys
77
from pathlib import Path
8-
from typing import Dict, List, Optional, Set
8+
from typing import Dict, List, Optional, Set, Union
99

1010
# import pyshark # pylint: disable=W0611
1111
import numpy as np
@@ -89,15 +89,15 @@ def aohcalc(
8989
manifest["error"] = "Species data missing one or more needed attributes"
9090
with open(manifest_filename, 'w', encoding="utf-8") as f:
9191
json.dump(manifest, f)
92-
sys.exit()
92+
return
9393

9494
habitat_list = crosswalk_habitats(crosswalk_table, raw_habitats)
9595
if force_habitat and len(habitat_list) == 0:
9696
logger.error("No habitats found in crosswalk! %s_%s had %s", species_id, seasonality, raw_habitats)
9797
manifest["error"] = "No habitats found in crosswalk"
9898
with open(manifest_filename, 'w', encoding="utf-8") as f:
9999
json.dump(manifest, f)
100-
sys.exit()
100+
return
101101

102102
ideal_habitat_map_files = [habitat_path / f"lcc_{x}.tif" for x in habitat_list]
103103
habitat_map_files = [x for x in ideal_habitat_map_files if x.exists()]
@@ -107,7 +107,7 @@ def aohcalc(
107107
manifest["error"] = "No matching habitat layers found"
108108
with open(manifest_filename, 'w', encoding="utf-8") as f:
109109
json.dump(manifest, f)
110-
sys.exit()
110+
return
111111

112112
habitat_maps = [RasterLayer.layer_from_file(x) for x in habitat_map_files]
113113

@@ -118,7 +118,7 @@ def aohcalc(
118118
min_elevation_map
119119
)
120120

121-
area_map = ConstantLayer(1.0)
121+
area_map : Union[ConstantLayer, RasterLayer, UniformAreaLayer] = ConstantLayer(1.0)
122122
if area_path:
123123
try:
124124
area_map = UniformAreaLayer.layer_from_file(area_path)

habitat_process.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
BLOCKSIZE = 512
2121

22-
def enumerate_subset(
22+
def _enumerate_subset(
2323
habitat_path: Path,
2424
offset: int,
2525
) -> Set[int]:
@@ -41,7 +41,7 @@ def enumerate_terrain_types(
4141
blocks = range(0, ysize, BLOCKSIZE)
4242
logger.info("Enumerating habitat classes in raster...")
4343
with Pool(processes=int(cpu_count() / 2)) as pool:
44-
sets = pool.map(partial(enumerate_subset, habitat_path), blocks)
44+
sets = pool.map(partial(_enumerate_subset, habitat_path), blocks)
4545
superset = set()
4646
for s in sets:
4747
superset.update(s)
@@ -51,7 +51,7 @@ def enumerate_terrain_types(
5151
pass
5252
return superset
5353

54-
def make_single_type_map(
54+
def _make_single_type_map(
5555
habitat_path: Path,
5656
pixel_scale: Optional[float],
5757
target_projection: Optional[str],
@@ -135,12 +135,12 @@ def habitat_process(
135135
if max_copies > 1:
136136
with Pool(processes=process_count) as pool:
137137
pool.map(
138-
partial(make_single_type_map, habitat_path, pixel_scale, target_projection, output_directory_path),
138+
partial(_make_single_type_map, habitat_path, pixel_scale, target_projection, output_directory_path),
139139
habitats
140140
)
141141
else:
142142
for habitat in habitats:
143-
make_single_type_map(habitat_path, pixel_scale, target_projection, output_directory_path, habitat)
143+
_make_single_type_map(habitat_path, pixel_scale, target_projection, output_directory_path, habitat)
144144

145145
def main() -> None:
146146
parser = argparse.ArgumentParser(description="Downsample habitat map to raster per terrain type.")

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ mypy
1818
pytest
1919
types-psutil
2020
pandas-stubs
21+
geojson

0 commit comments

Comments
 (0)