fimeval 0.1.50__py3-none-any.whl → 0.1.52__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -85,6 +85,7 @@ def GetFloodedBuildingCountInfo(
85
85
  if "bm" in str(raster1_path).lower():
86
86
  count_centroids_in_raster(raster1_path, "Benchmark")
87
87
  count_centroids_in_raster(raster2_path, "Candidate")
88
+
88
89
  elif "candidate" in str(raster2_path).lower():
89
90
  count_centroids_in_raster(raster1_path, "Candidate")
90
91
  count_centroids_in_raster(raster2_path, "Benchmark")
@@ -105,6 +106,9 @@ def GetFloodedBuildingCountInfo(
105
106
  CSI = TP / (TP + FP + FN) if (TP + FP + FN) > 0 else 0
106
107
  FAR = FP / (TP + FP) if (TP + FP) > 0 else 0
107
108
  POD = TP / (TP + FN) if (TP + FN) > 0 else 0
109
+
110
+
111
+ BDR = (centroid_counts["Candidate"]- centroid_counts["Benchmark"])/centroid_counts["Benchmark"]
108
112
 
109
113
  counts_data = {
110
114
  "Category": [
@@ -116,6 +120,7 @@ def GetFloodedBuildingCountInfo(
116
120
  "CSI",
117
121
  "FAR",
118
122
  "POD",
123
+ "Building Deviation Ratio",
119
124
  ],
120
125
  "Building Count": [
121
126
  centroid_counts["Candidate"],
@@ -126,6 +131,7 @@ def GetFloodedBuildingCountInfo(
126
131
  f"{CSI:.3f}",
127
132
  f"{FAR:.3f}",
128
133
  f"{POD:.3f}",
134
+ f"{BDR:.3f}",
129
135
  ],
130
136
  }
131
137
 
@@ -75,9 +75,6 @@ def evaluateFIM(
75
75
  # Save the smallest extent boundary and cliped FIMS
76
76
  save_dir = os.path.join(output_dir, os.path.basename(folder), f"{method.__name__}")
77
77
  os.makedirs(save_dir, exist_ok=True)
78
-
79
- #Give the permission to the output directory
80
- fix_permissions(save_dir)
81
78
 
82
79
  # Get the smallest matched raster extent and make a boundary shapefile
83
80
  smallest_raster_path = get_smallest_raster_path(benchmark_path, *candidate_paths)
@@ -98,7 +95,6 @@ def evaluateFIM(
98
95
  raise FileNotFoundError(
99
96
  "No shapefile (.shp, .gpkg, .geojson, .kml) found in the folder and none provided. Either provide a shapefile directory or put shapefile inside folder directory."
100
97
  )
101
-
102
98
  # Run AOI with the found or provided shapefile
103
99
  bounding_geom = AOI(benchmark_path, shapefile, save_dir)
104
100
 
@@ -364,6 +360,7 @@ def evaluateFIM(
364
360
 
365
361
  #Safely deleting the folder
366
362
  def safe_delete_folder(folder_path):
363
+ fix_permissions(folder_path)
367
364
  try:
368
365
  shutil.rmtree(folder_path)
369
366
  except PermissionError:
@@ -6,13 +6,16 @@ if [ -z "$DIR" ]; then
6
6
  echo "No directory provided."
7
7
  exit 1
8
8
  fi
9
+ echo "Fixing permissions for: $DIR"
9
10
 
10
11
  UNAME=$(uname)
11
12
  if [[ "$UNAME" == "Darwin" || "$UNAME" == "Linux" ]]; then
12
13
  chmod -R u+rwX "$DIR"
14
+ echo "Permissions granted for user (u+rwX)"
13
15
 
14
16
  elif [[ "$UNAME" == *"MINGW"* || "$UNAME" == *"MSYS"* || "$UNAME" == *"CYGWIN"* ]]; then
15
17
  icacls "$DIR" /grant Everyone:F /T > /dev/null
18
+ echo "Permissions granted for working folder"
16
19
 
17
20
  else
18
21
  echo "Unsupported OS: $UNAME"
fimeval/utilis.py CHANGED
@@ -1,3 +1,4 @@
1
+ import os
1
2
  import shutil
2
3
  import pyproj
3
4
  import rasterio
@@ -70,11 +71,18 @@ def reprojectFIMs(src_path, dst_path, target_crs):
70
71
 
71
72
  #Resample into the coarser resoution amoung all FIMS within the case
72
73
  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
+
73
79
  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
+ )
75
84
  width = int((src.bounds.right - src.bounds.left) / x_resolution)
76
85
  height = int((src.bounds.top - src.bounds.bottom) / y_resolution)
77
-
78
86
  kwargs = src.meta.copy()
79
87
  kwargs.update({
80
88
  'transform': transform,
@@ -82,8 +90,8 @@ def resample_to_resolution(src_path, x_resolution, y_resolution):
82
90
  'height': height
83
91
  })
84
92
 
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:
87
95
  for i in range(1, src.count + 1):
88
96
  reproject(
89
97
  source=rasterio.band(src, i),
@@ -94,7 +102,9 @@ def resample_to_resolution(src_path, x_resolution, y_resolution):
94
102
  dst_crs=src.crs,
95
103
  resampling=Resampling.nearest
96
104
  )
97
- # compress_tif_lzw(dst_path)
105
+
106
+ os.remove(src_path) # delete original
107
+ os.rename(temp_path, src_path)
98
108
 
99
109
  #Check if the FIMs are in the same CRS or not else do further operation
100
110
  def MakeFIMsUniform(fim_dir, target_crs=None, target_resolution=None):
@@ -103,79 +113,69 @@ def MakeFIMsUniform(fim_dir, target_crs=None, target_resolution=None):
103
113
  if not tif_files:
104
114
  print(f"No TIFF files found in {fim_dir}")
105
115
  return
116
+
117
+ # Create processing folder to save standardized files
106
118
  processing_folder = fim_dir / 'processing'
107
119
  processing_folder.mkdir(exist_ok=True)
108
120
 
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 = [], [], [], []
114
123
  for tif_path in tif_files:
115
124
  try:
116
125
  with rasterio.open(tif_path) as src:
117
126
  crs_list.append(src.crs)
118
- projected_status.append(is_projected_crs(src.crs))
127
+ resolutions.append(src.res)
119
128
  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:
122
131
  print(f"Error opening {tif_path}: {e}")
123
132
  return
124
133
 
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
128
137
 
129
138
  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}")
145
145
  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}")
149
150
  for src_path in tif_files:
150
151
  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)
167
159
 
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)
180
180
  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.")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fimeval
3
- Version: 0.1.50
3
+ Version: 0.1.52
4
4
  Summary: A Framework for Automatic Evaluation of Flood Inundation Mapping Predictions Evaluation
5
5
  License: GPLv3
6
6
  Author: Surface Dynamics Modeling Lab
@@ -1,16 +1,16 @@
1
1
  fimeval/BuildingFootprint/__init__.py,sha256=oP9YWLdo6ANzSQFxYLv7Ku_26AY5NkLNhZLK28ICMLo,109
2
- fimeval/BuildingFootprint/evaluationwithBF.py,sha256=0jqHbzEhDSouXXBOGHuJ2R4yo1rBKrhiC5mXO8SwJek,14167
2
+ fimeval/BuildingFootprint/evaluationwithBF.py,sha256=mnmcfyNPL_XBg9fIDXJjBWsRDKlCZ8HPjIhzCiFJkb8,14352
3
3
  fimeval/ContingencyMap/PWBs3.py,sha256=YAg03jzdplYIstG-pZM1MECse7gYjWrJNKAopjgt3uk,1294
4
4
  fimeval/ContingencyMap/__init__.py,sha256=ckps2dyg6aci3TA-3P7oTMcCAcSTz9AA6sndHtZEwdE,259
5
- fimeval/ContingencyMap/evaluationFIM.py,sha256=UJZCioyczx3CEOwNrqGTMQGX_TfAKjTsvvEDK3WzEuA,16880
6
- fimeval/ContingencyMap/fix_permissions.sh,sha256=SNmYtVviwAs3_--xEE2pk6Mqyqj3XaImOiJMFK1AkDM,378
5
+ fimeval/ContingencyMap/evaluationFIM.py,sha256=F9hI1N0AhBFZhGIimfkIK4MsbHborAyjmPiZ95mFZZE,16828
6
+ fimeval/ContingencyMap/fix_permissions.sh,sha256=prIeJGXwAUO28nhgtCtvcpOxWK-J75rxN4FQ6QjGET4,508
7
7
  fimeval/ContingencyMap/methods.py,sha256=kbutfo9FUH-yjvnOXxwLpdErUuebMJ8NjCroNWIYCjo,3299
8
8
  fimeval/ContingencyMap/metrics.py,sha256=eEv1zAfmIjyg9OWM1b6-i25q_3jEBmeLZ7JeuvxS1QI,1070
9
9
  fimeval/ContingencyMap/plotevaluationmetrics.py,sha256=3bKfPKZnMR39dA3teDVpQBeTFKnF9v_2Vku0JNVGggs,3921
10
10
  fimeval/ContingencyMap/printcontingency.py,sha256=Ef0TlGNxvLlrliM2SCkhusgz9BsEGvVOBHAO62YC_QA,5421
11
11
  fimeval/__init__.py,sha256=kN114EvzG_BFjd65fKWXg29TqaWvR173EdCN3yj30oc,433
12
- fimeval/utilis.py,sha256=KNXcR0RvhT_lPqM_8cuAGXMpRtcLMfb_UDqUiMlDevs,7311
13
- fimeval-0.1.50.dist-info/LICENSE.txt,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
14
- fimeval-0.1.50.dist-info/METADATA,sha256=bf_oFaXWbJk8gufCpypNxyoldI4t36xQfVg8PuroN9g,14848
15
- fimeval-0.1.50.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
16
- fimeval-0.1.50.dist-info/RECORD,,
12
+ fimeval/utilis.py,sha256=Cueji5DWGAaXTGCcQmkVaHGpIJeIIMNOuq_1KUKM2oA,6920
13
+ fimeval-0.1.52.dist-info/LICENSE.txt,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
14
+ fimeval-0.1.52.dist-info/METADATA,sha256=JojzN5T77mRJveolF1lYAJlnKpqDhieHwbwE-hbWF4I,14848
15
+ fimeval-0.1.52.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
16
+ fimeval-0.1.52.dist-info/RECORD,,