|
13 | 13 | PopulationModelData, |
14 | 14 | ) |
15 | 15 |
|
| 16 | +MAX_BOUNDS = { |
| 17 | + "ESRI:54034": (-20037508.34, 20037508.34, -6363885.33, 6363885.33), |
| 18 | +} |
| 19 | + |
16 | 20 |
|
17 | 21 | def build_location_masks( |
18 | 22 | hierarchy: str, |
@@ -136,11 +140,32 @@ def get_bbox(raster: rt.RasterArray, crs: str | None = None) -> shapely.Polygon: |
136 | 140 | shapely.Polybon |
137 | 141 | The bounding box of the raster in the CRS specified by the crs parameter. |
138 | 142 | """ |
| 143 | + if raster.crs not in MAX_BOUNDS: |
| 144 | + msg = f"Unsupported CRS: {raster.crs}" |
| 145 | + raise ValueError(msg) |
| 146 | + |
| 147 | + xmin_clip, xmax_clip, ymin_clip, ymax_clip = MAX_BOUNDS[raster.crs] |
139 | 148 | xmin, xmax, ymin, ymax = raster.bounds |
| 149 | + |
| 150 | + xmin = np.clip(xmin, xmin_clip, xmax_clip) |
| 151 | + xmax = np.clip(xmax, xmin_clip, xmax_clip) |
| 152 | + ymin = np.clip(ymin, ymin_clip, ymax_clip) |
| 153 | + ymax = np.clip(ymax, ymin_clip, ymax_clip) |
| 154 | + |
140 | 155 | bbox = gpd.GeoSeries([shapely.box(xmin, ymin, xmax, ymax)], crs=raster.crs) |
141 | | - if crs is not None: |
142 | | - bbox = bbox.to_crs(crs) |
143 | | - return cast(shapely.Polygon, bbox.iloc[0]) |
| 156 | + out_bbox = bbox.to_crs(crs) if crs is not None else bbox.copy() |
| 157 | + |
| 158 | + # Check that our transformation didn't do something weird |
| 159 | + # (e.g. artificially clip the bounds or have the bounds extend over the |
| 160 | + # antimeridian) |
| 161 | + check_bbox = out_bbox.to_crs(raster.crs) |
| 162 | + area_change = (np.abs(bbox.area - check_bbox.area) / bbox.area).iloc[0] |
| 163 | + tolerance = 1e-6 |
| 164 | + if area_change > tolerance: |
| 165 | + msg = f"Area change: {area_change}" |
| 166 | + raise ValueError(msg) |
| 167 | + |
| 168 | + return cast(shapely.Polygon, out_bbox.iloc[0]) |
144 | 169 |
|
145 | 170 |
|
146 | 171 | def aggregate_climate_to_hierarchy( |
@@ -173,21 +198,17 @@ def aggregate_climate_to_hierarchy( |
173 | 198 | subset["parent_id"] = parent_map |
174 | 199 |
|
175 | 200 | parent_values = ( |
176 | | - subset.groupby(["year_id", "scenario", "parent_id"])[ |
177 | | - ["weighted_climate", "population"] |
178 | | - ] |
| 201 | + subset.groupby(["year_id", "parent_id"])[["weighted_climate", "population"]] |
179 | 202 | .sum() |
180 | 203 | .reset_index() |
181 | 204 | .rename(columns={"parent_id": "location_id"}) |
182 | 205 | .set_index("location_id") |
183 | 206 | ) |
184 | | - parent_values["value"] = ( |
185 | | - parent_values.weighted_climate / parent_values.population |
186 | | - ) |
187 | 207 | results = pd.concat([results, parent_values]) |
188 | 208 | results = ( |
189 | 209 | results.reset_index() |
190 | 210 | .sort_values(["location_id", "year_id"]) |
191 | 211 | .reset_index(drop=True) |
192 | 212 | ) |
| 213 | + parent_values["value"] = parent_values.weighted_climate / parent_values.population |
193 | 214 | return results |
0 commit comments