Skip to content

Commit b213f9e

Browse files
fixing the raster resampling bug
1 parent 0c987e9 commit b213f9e

7 files changed

Lines changed: 255 additions & 268 deletions

File tree

34.7 KB
Binary file not shown.

dist/fimeval-0.1.52.tar.gz

35.3 KB
Binary file not shown.

poetry.lock

Lines changed: 177 additions & 190 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "fimeval"
3-
version = "0.1.51"
3+
version = "0.1.52"
44
description = "A Framework for Automatic Evaluation of Flood Inundation Mapping Predictions Evaluation"
55
authors = [
66
"Surface Dynamics Modeling Lab",

src/fimeval/ContingencyMap/evaluationFIM.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@ def evaluateFIM(
9595
raise FileNotFoundError(
9696
"No shapefile (.shp, .gpkg, .geojson, .kml) found in the folder and none provided. Either provide a shapefile directory or put shapefile inside folder directory."
9797
)
98-
9998
# Run AOI with the found or provided shapefile
10099
bounding_geom = AOI(benchmark_path, shapefile, save_dir)
101100

@@ -361,6 +360,7 @@ def resize_image(
361360

362361
#Safely deleting the folder
363362
def safe_delete_folder(folder_path):
363+
fix_permissions(folder_path)
364364
try:
365365
shutil.rmtree(folder_path)
366366
except PermissionError:

src/fimeval/utilis.py

Lines changed: 63 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import os
12
import shutil
23
import pyproj
34
import rasterio
@@ -70,20 +71,27 @@ def reprojectFIMs(src_path, dst_path, target_crs):
7071

7172
#Resample into the coarser resoution amoung all FIMS within the case
7273
def resample_to_resolution(src_path, x_resolution, y_resolution):
74+
src_path = Path(src_path)
75+
print(src_path)
76+
temp_path = src_path.with_name(src_path.stem + "_resampled.tif")
77+
print(temp_path)
78+
7379
with rasterio.open(src_path) as src:
74-
transform = rasterio.transform.from_origin(src.bounds.left, src.bounds.top, x_resolution, y_resolution)
80+
transform = rasterio.transform.from_origin(
81+
src.bounds.left, src.bounds.top,
82+
x_resolution, y_resolution
83+
)
7584
width = int((src.bounds.right - src.bounds.left) / x_resolution)
7685
height = int((src.bounds.top - src.bounds.bottom) / y_resolution)
77-
7886
kwargs = src.meta.copy()
7987
kwargs.update({
8088
'transform': transform,
8189
'width': width,
8290
'height': height
8391
})
8492

85-
dst_path = src_path
86-
with rasterio.open(dst_path, 'w', **kwargs) as dst:
93+
# Write to temporary file
94+
with rasterio.open(temp_path, 'w', **kwargs) as dst:
8795
for i in range(1, src.count + 1):
8896
reproject(
8997
source=rasterio.band(src, i),
@@ -94,7 +102,9 @@ def resample_to_resolution(src_path, x_resolution, y_resolution):
94102
dst_crs=src.crs,
95103
resampling=Resampling.nearest
96104
)
97-
# compress_tif_lzw(dst_path)
105+
106+
os.remove(src_path) # delete original
107+
os.rename(temp_path, src_path)
98108

99109
#Check if the FIMs are in the same CRS or not else do further operation
100110
def MakeFIMsUniform(fim_dir, target_crs=None, target_resolution=None):
@@ -103,79 +113,69 @@ def MakeFIMsUniform(fim_dir, target_crs=None, target_resolution=None):
103113
if not tif_files:
104114
print(f"No TIFF files found in {fim_dir}")
105115
return
116+
117+
# Create processing folder to save standardized files
106118
processing_folder = fim_dir / 'processing'
107119
processing_folder.mkdir(exist_ok=True)
108120

109-
crs_list = []
110-
projected_status = []
111-
bounds_list = []
112-
fims_data = []
113-
121+
# Collect info about each TIFF
122+
crs_list, resolutions, bounds_list, projected_flags = [], [], [], []
114123
for tif_path in tif_files:
115124
try:
116125
with rasterio.open(tif_path) as src:
117126
crs_list.append(src.crs)
118-
projected_status.append(is_projected_crs(src.crs))
127+
resolutions.append(src.res)
119128
bounds_list.append(src.bounds)
120-
fims_data.append((src.bounds, src.crs))
121-
except rasterio.RasterioIOError as e:
129+
projected_flags.append(is_projected_crs(src.crs))
130+
except Exception as e:
122131
print(f"Error opening {tif_path}: {e}")
123132
return
124133

125-
all_projected = all(projected_status)
126-
first_crs = crs_list[0] if crs_list else None
127-
all_same_crs = all(crs == first_crs for crs in crs_list)
134+
#CRS Check & Reproject if needed
135+
all_projected = all(projected_flags)
136+
all_same_crs = len(set(crs_list)) == 1
128137

129138
if not all_projected or (all_projected and not all_same_crs):
130-
if target_crs:
131-
print(f"Reprojecting all FIMs to {target_crs}.")
132-
for src_path in tif_files:
133-
dst_path = processing_folder / src_path.name
134-
reprojectFIMs(str(src_path), str(dst_path), target_crs)
135-
compress_tif_lzw(dst_path)
136-
else:
137-
all_within_conus = all(is_within_conus(bounds_list[i], crs_list[i]) for i in range(len(bounds_list)))
138-
139-
if all_within_conus:
140-
default_target_crs = "EPSG:5070"
141-
print(f"FIMs are within CONUS, reprojecting all to {default_target_crs} and saving to {processing_folder}")
142-
for src_path in tif_files:
143-
dst_path = processing_folder / src_path.name
144-
reprojectFIMs(str(src_path), str(dst_path), default_target_crs)
139+
# Decide CRS to use
140+
final_crs = target_crs
141+
if not final_crs:
142+
if all(is_within_conus(b, c) for b, c in zip(bounds_list, crs_list)):
143+
final_crs = "EPSG:5070"
144+
print(f"Defaulting to CONUS CRS: {final_crs}")
145145
else:
146-
print("All flood maps are not in the projected CRS or are not in the same projected CRS.\n")
147-
print("Please provide a target CRS in EPSG format.")
148-
else:
146+
print("Mixed or non-CONUS CRS detected. Please provide a valid target CRS.")
147+
return
148+
149+
print(f"Reprojecting all rasters to {final_crs}")
149150
for src_path in tif_files:
150151
dst_path = processing_folder / src_path.name
151-
shutil.copy(src_path, dst_path)
152-
153-
# Resolution check and resampling
154-
processed_tifs = list(processing_folder.glob('*.tif'))
155-
if processed_tifs:
156-
resolutions = []
157-
for tif_path in processed_tifs:
158-
try:
159-
with rasterio.open(tif_path) as src:
160-
resolutions.append(src.res)
161-
except rasterio.RasterioIOError as e:
162-
print(f"Error opening {tif_path} in processing folder: {e}")
163-
return
164-
165-
first_resolution = resolutions[0] if resolutions else None
166-
all_same_resolution = all(res == first_resolution for res in resolutions)
152+
reprojectFIMs(str(src_path), str(dst_path), final_crs)
153+
compress_tif_lzw(dst_path)
154+
155+
else:
156+
print("All rasters are in the same projected CRS. Copying to processing folder.")
157+
for src_path in tif_files:
158+
shutil.copy(src_path, processing_folder / src_path.name)
167159

168-
if not all_same_resolution:
169-
if target_resolution is not None:
170-
for src_path in processed_tifs:
171-
resample_to_resolution(str(src_path), target_resolution, target_resolution)
172-
else:
173-
coarser_x = max(res[0] for res in resolutions)
174-
coarser_y = max(res[1] for res in resolutions)
175-
print(f"Using coarser resolution: X={coarser_x}, Y={coarser_y}. Resampling all FIMS to this resolution.")
176-
for src_path in processed_tifs:
177-
resample_to_resolution(str(src_path), coarser_x, coarser_y)
178-
else:
179-
print("All FIMs in the processing folder have the same resolution.")
160+
# Resolution Check & Resample if needed
161+
processed_tifs = list(processing_folder.glob('*.tif'))
162+
final_resolutions = []
163+
for tif_path in processed_tifs:
164+
with rasterio.open(tif_path) as src:
165+
final_resolutions.append(src.res)
166+
167+
unique_res = set(final_resolutions)
168+
if target_resolution:
169+
print(f"Resampling all rasters to target resolution: {target_resolution}m.")
170+
for src_path in processed_tifs:
171+
resample_to_resolution(str(src_path), target_resolution, target_resolution)
172+
173+
# Otherwise, only resample if resolutions are inconsistent
174+
elif len(unique_res) > 1:
175+
coarsest_x = max(res[0] for res in final_resolutions)
176+
coarsest_y = max(res[1] for res in final_resolutions)
177+
print(f"Using coarsest resolution: X={coarsest_x}, Y={coarsest_y}")
178+
for src_path in processed_tifs:
179+
resample_to_resolution(str(src_path), coarsest_x, coarsest_y)
180180
else:
181-
print("No TIFF files found in the processing folder after CRS standardization.")
181+
print("All rasters already have the same resolution. No resampling needed.")

tests/test_evaluationfim.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
# "../docs/sampledata"
66
)
77
PWD_dir = "./path/to/PWB"
8-
output_dir = "../docs/Output"
8+
output_dir = "./path/to/output" # This is the output directory where the results will be saved
99
target_crs = "EPSG:5070" # Target CRS for reprojecting the FIMs, need to be in EPSG code of Projected CRS
1010
target_resolution = 10 #This will be in meters, if it passes the FIMS will be resampled to this resolution else, it will find the coarser resolution among all FIMS for this case and use that to resample!
1111

@@ -29,23 +29,23 @@
2929
# fe.EvaluateFIM(Main_dir, method_name, output_dir)
3030

3131
# OR, If the Evaluation Study Area is outside the US or, user has their own PWB dataset
32-
# fe.EvaluateFIM(Main_dir, method_name, output_dir, PWB_dir=PWD_dir)
32+
fe.EvaluateFIM(Main_dir, method_name, output_dir)
3333

3434

3535
#If the FIMS are not in projected crs or are in different spatial resolution
36-
fe.EvaluateFIM(Main_dir, method_name, output_dir, target_crs=target_crs, shapefile_dir = AOI, target_resolution=target_resolution)
36+
# fe.EvaluateFIM(Main_dir, method_name, output_dir, target_crs=target_crs, shapefile_dir = AOI, target_resolution=target_resolution)
3737

38-
# Once the FIM evaluation is done, print the contingency map
39-
fe.PrintContingencyMap(Main_dir, method_name, output_dir)
38+
# # Once the FIM evaluation is done, print the contingency map
39+
# fe.PrintContingencyMap(Main_dir, method_name, output_dir)
4040

4141

42-
# Plot rhe evaluation metrics after the FIM evaluation
43-
fe.PlotEvaluationMetrics(Main_dir, method_name, output_dir)
42+
# # Plot rhe evaluation metrics after the FIM evaluation
43+
# fe.PlotEvaluationMetrics(Main_dir, method_name, output_dir)
4444

45-
# # FIM Evaluation with Building Footprint (by default, it uses the Microsoft Building Footprint dataset)
46-
fe.EvaluationWithBuildingFootprint(
47-
Main_dir, method_name, output_dir, country=countryISO
48-
)
45+
# # # FIM Evaluation with Building Footprint (by default, it uses the Microsoft Building Footprint dataset)
46+
# fe.EvaluationWithBuildingFootprint(
47+
# Main_dir, method_name, output_dir, country=countryISO
48+
# )
4949

50-
# If user have their own building footprint dataset, they can use it as well
51-
fe.EvaluationWithBuildingFootprint(Main_dir, method_name, output_dir, building_footprint = building_footprint, shapefile_dir=AOI)
50+
# # If user have their own building footprint dataset, they can use it as well
51+
# fe.EvaluationWithBuildingFootprint(Main_dir, method_name, output_dir, building_footprint = building_footprint, shapefile_dir=AOI)

0 commit comments

Comments
 (0)