giga-spatial 0.6.0__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.
Files changed (47) hide show
  1. giga_spatial-0.6.0.dist-info/METADATA +141 -0
  2. giga_spatial-0.6.0.dist-info/RECORD +47 -0
  3. giga_spatial-0.6.0.dist-info/WHEEL +5 -0
  4. giga_spatial-0.6.0.dist-info/licenses/LICENSE +661 -0
  5. giga_spatial-0.6.0.dist-info/top_level.txt +1 -0
  6. gigaspatial/__init__.py +1 -0
  7. gigaspatial/config.py +226 -0
  8. gigaspatial/core/__init__.py +0 -0
  9. gigaspatial/core/io/__init__.py +5 -0
  10. gigaspatial/core/io/adls_data_store.py +325 -0
  11. gigaspatial/core/io/data_api.py +113 -0
  12. gigaspatial/core/io/data_store.py +147 -0
  13. gigaspatial/core/io/local_data_store.py +92 -0
  14. gigaspatial/core/io/readers.py +265 -0
  15. gigaspatial/core/io/writers.py +128 -0
  16. gigaspatial/core/schemas/__init__.py +0 -0
  17. gigaspatial/core/schemas/entity.py +244 -0
  18. gigaspatial/generators/__init__.py +2 -0
  19. gigaspatial/generators/poi.py +636 -0
  20. gigaspatial/generators/zonal/__init__.py +3 -0
  21. gigaspatial/generators/zonal/base.py +370 -0
  22. gigaspatial/generators/zonal/geometry.py +439 -0
  23. gigaspatial/generators/zonal/mercator.py +78 -0
  24. gigaspatial/grid/__init__.py +1 -0
  25. gigaspatial/grid/mercator_tiles.py +286 -0
  26. gigaspatial/handlers/__init__.py +40 -0
  27. gigaspatial/handlers/base.py +761 -0
  28. gigaspatial/handlers/boundaries.py +305 -0
  29. gigaspatial/handlers/ghsl.py +772 -0
  30. gigaspatial/handlers/giga.py +145 -0
  31. gigaspatial/handlers/google_open_buildings.py +472 -0
  32. gigaspatial/handlers/hdx.py +241 -0
  33. gigaspatial/handlers/mapbox_image.py +208 -0
  34. gigaspatial/handlers/maxar_image.py +291 -0
  35. gigaspatial/handlers/microsoft_global_buildings.py +548 -0
  36. gigaspatial/handlers/ookla_speedtest.py +199 -0
  37. gigaspatial/handlers/opencellid.py +290 -0
  38. gigaspatial/handlers/osm.py +356 -0
  39. gigaspatial/handlers/overture.py +126 -0
  40. gigaspatial/handlers/rwi.py +157 -0
  41. gigaspatial/handlers/unicef_georepo.py +806 -0
  42. gigaspatial/handlers/worldpop.py +266 -0
  43. gigaspatial/processing/__init__.py +4 -0
  44. gigaspatial/processing/geo.py +1054 -0
  45. gigaspatial/processing/sat_images.py +39 -0
  46. gigaspatial/processing/tif_processor.py +477 -0
  47. gigaspatial/processing/utils.py +49 -0
@@ -0,0 +1,439 @@
1
+ from typing import Dict, List, Optional, Union
2
+ from shapely.geometry import Polygon, MultiPolygon
3
+
4
+ import geopandas as gpd
5
+ import pandas as pd
6
+ import logging
7
+
8
+ from gigaspatial.core.io.data_store import DataStore
9
+ from gigaspatial.config import config as global_config
10
+ from gigaspatial.processing.geo import (
11
+ add_area_in_meters,
12
+ get_centroids,
13
+ )
14
+ from gigaspatial.handlers.ghsl import GHSLDataHandler
15
+ from gigaspatial.handlers.google_open_buildings import GoogleOpenBuildingsHandler
16
+ from gigaspatial.handlers.microsoft_global_buildings import MSBuildingsHandler
17
+ from gigaspatial.generators.zonal.base import (
18
+ ZonalViewGenerator,
19
+ ZonalViewGeneratorConfig,
20
+ T,
21
+ )
22
+
23
+
24
+ class GeometryBasedZonalViewGenerator(ZonalViewGenerator[T]):
25
+ """Mid-level class for zonal view generation based on geometries with identifiers.
26
+
27
+ This class serves as an intermediate between the abstract ZonalViewGenerator and specific
28
+ implementations like MercatorViewGenerator or H3ViewGenerator. It handles the common case
29
+ where zones are defined by a mapping between zone identifiers and geometries, either
30
+ provided as a dictionary or as a GeoDataFrame.
31
+
32
+ The class extends the base functionality with methods for mapping common geospatial
33
+ datasets including GHSL (Global Human Settlement Layer), Google Open Buildings,
34
+ and Microsoft Global Buildings data.
35
+
36
+ Attributes:
37
+ zone_dict (Dict[T, Polygon]): Mapping of zone identifiers to geometries.
38
+ zone_id_column (str): Name of the column containing zone identifiers.
39
+ zone_data_crs (str): Coordinate reference system of the zone data.
40
+ _zone_gdf (gpd.GeoDataFrame): Cached GeoDataFrame representation of zones.
41
+ data_store (DataStore): For accessing input data.
42
+ config (ZonalViewGeneratorConfig): Configuration for view generation.
43
+ logger: Logger instance for this class.
44
+ """
45
+
46
+ def __init__(
47
+ self,
48
+ zone_data: Union[Dict[T, Polygon], gpd.GeoDataFrame],
49
+ zone_id_column: str = "zone_id",
50
+ zone_data_crs: str = "EPSG:4326",
51
+ config: Optional[ZonalViewGeneratorConfig] = None,
52
+ data_store: Optional[DataStore] = None,
53
+ logger: logging.Logger = None,
54
+ ):
55
+ """Initialize with zone geometries and identifiers.
56
+
57
+ Args:
58
+ zone_data (Union[Dict[T, Polygon], gpd.GeoDataFrame]): Zone definitions.
59
+ Either a dictionary mapping zone identifiers to Polygon/MultiPolygon geometries,
60
+ or a GeoDataFrame with geometries and a zone identifier column.
61
+ zone_id_column (str): Name of the column containing zone identifiers.
62
+ Only used if zone_data is a GeoDataFrame. Defaults to "zone_id".
63
+ zone_data_crs (str): Coordinate reference system of the zone data.
64
+ Defaults to "EPSG:4326" (WGS84).
65
+ config (ZonalViewGeneratorConfig, optional): Generator configuration.
66
+ If None, uses default configuration.
67
+ data_store (DataStore, optional): Data store for accessing input data.
68
+ If None, uses LocalDataStore.
69
+
70
+ Raises:
71
+ TypeError: If zone_data is not a dictionary or GeoDataFrame, or if dictionary
72
+ values are not Polygon/MultiPolygon geometries.
73
+ ValueError: If zone_id_column is not found in GeoDataFrame, or if the provided
74
+ CRS doesn't match the GeoDataFrame's CRS.
75
+ """
76
+ super().__init__(config=config, data_store=data_store, logger=logger)
77
+
78
+ self.zone_id_column = zone_id_column
79
+ self.zone_data_crs = zone_data_crs
80
+
81
+ # Store zone data based on input type
82
+ if isinstance(zone_data, dict):
83
+ for zone_id, geom in zone_data.items():
84
+ if not isinstance(geom, (Polygon, MultiPolygon)):
85
+ raise TypeError(
86
+ f"Zone {zone_id}: Expected (Multi)Polygon, got {type(geom).__name__}"
87
+ )
88
+
89
+ # Store the original dictionary
90
+ self.zone_dict = zone_data
91
+
92
+ # Also create a GeoDataFrame for consistent access
93
+ self._zone_gdf = gpd.GeoDataFrame(
94
+ {
95
+ "zone_id": list(zone_data.keys()),
96
+ "geometry": list(zone_data.values()),
97
+ },
98
+ crs=zone_data_crs,
99
+ )
100
+ self.zone_id_column = "zone_id"
101
+ else:
102
+ if not isinstance(zone_data, gpd.GeoDataFrame):
103
+ raise TypeError(
104
+ "zone_data must be either a Dict[T, Polygon] or a GeoDataFrame"
105
+ )
106
+
107
+ if zone_id_column not in zone_data.columns:
108
+ raise ValueError(
109
+ f"Zone ID column '{zone_id_column}' not found in GeoDataFrame"
110
+ )
111
+
112
+ if zone_data_crs != zone_data.crs:
113
+ raise ValueError(
114
+ f"Provided data crs '{zone_data_crs}' does not match to the crs of the data '{zone_data.crs}'"
115
+ )
116
+
117
+ # Store the GeoDataFrame
118
+ self._zone_gdf = zone_data.rename(columns={zone_id_column: "zone_id"})
119
+
120
+ # Also create a dictionary for fast lookups
121
+ self.zone_dict = dict(zip(zone_data[zone_id_column], zone_data.geometry))
122
+
123
+ def get_zonal_geometries(self) -> List[Polygon]:
124
+ """Get the geometry of each zone.
125
+
126
+ Returns:
127
+ List[Polygon]: A list of zone geometries in the order they appear in the
128
+ underlying GeoDataFrame.
129
+ """
130
+ return self._zone_gdf.geometry.tolist()
131
+
132
+ def get_zone_identifiers(self) -> List[T]:
133
+ """Get the identifier for each zone.
134
+
135
+ Returns:
136
+ List[T]: A list of zone identifiers in the order they appear in the
137
+ underlying GeoDataFrame.
138
+ """
139
+ return self._zone_gdf[self.zone_id_column].tolist()
140
+
141
+ def to_geodataframe(self) -> gpd.GeoDataFrame:
142
+ """Convert zones to a GeoDataFrame with standardized column names.
143
+
144
+ Returns:
145
+ gpd.GeoDataFrame: A GeoDataFrame with 'zone_id' and 'geometry' columns.
146
+ The zone_id column is renamed from the original zone_id_column if different.
147
+ """
148
+ # If we already have a GeoDataFrame, just rename the ID column if needed
149
+ result = self._zone_gdf.copy()
150
+ if self.zone_id_column != "zone_id":
151
+ result = result.rename(columns={self.zone_id_column: "zone_id"})
152
+ return result
153
+
154
+ def map_built_s(
155
+ self,
156
+ year=2020,
157
+ resolution=100,
158
+ stat: str = "sum",
159
+ name_prefix: str = "built_surface_m2_",
160
+ **kwargs,
161
+ ) -> gpd.GeoDataFrame:
162
+ """Map GHSL Built-up Surface data to zones.
163
+
164
+ Convenience method for mapping Global Human Settlement Layer Built-up Surface
165
+ data using appropriate default parameters for built surface analysis.
166
+
167
+ Args:
168
+ ghsl_data_config (GHSLDataConfig): Configuration for GHSL Built-up Surface data.
169
+ Defaults to GHS_BUILT_S product for 2020 at 100m resolution.
170
+ stat (str): Statistic to calculate for built surface values within each zone.
171
+ Defaults to "sum" which gives total built surface area.
172
+ name_prefix (str): Prefix for the output column name. Defaults to "built_surface_m2_".
173
+
174
+ Returns:
175
+ gpd.GeoDataFrame: Updated GeoDataFrame with zones and built surface metrics.
176
+ Adds a column named "{name_prefix}{stat}" containing the aggregated values.
177
+ """
178
+ handler = GHSLDataHandler(
179
+ product="GHS_BUILT_S",
180
+ year=year,
181
+ resolution=resolution,
182
+ data_store=self.data_store,
183
+ **kwargs,
184
+ )
185
+
186
+ return self.map_ghsl(
187
+ handler=handler, stat=stat, name_prefix=name_prefix, **kwargs
188
+ )
189
+
190
+ def map_smod(
191
+ self,
192
+ year=2020,
193
+ resolution=100,
194
+ stat: str = "median",
195
+ name_prefix: str = "smod_class_",
196
+ **kwargs,
197
+ ) -> gpd.GeoDataFrame:
198
+ """Map GHSL Settlement Model data to zones.
199
+
200
+ Convenience method for mapping Global Human Settlement Layer Settlement Model
201
+ data using appropriate default parameters for settlement classification analysis.
202
+
203
+ Args:
204
+ ghsl_data_config (GHSLDataConfig): Configuration for GHSL Settlement Model data.
205
+ Defaults to GHS_SMOD product for 2020 at 1000m resolution in Mollweide projection.
206
+ stat (str): Statistic to calculate for settlement class values within each zone.
207
+ Defaults to "median" which gives the predominant settlement class.
208
+ name_prefix (str): Prefix for the output column name. Defaults to "smod_class_".
209
+
210
+ Returns:
211
+ gpd.GeoDataFrame: Updated GeoDataFrame with zones and settlement classification.
212
+ Adds a column named "{name_prefix}{stat}" containing the aggregated values.
213
+ """
214
+ handler = GHSLDataHandler(
215
+ product="GHS_SMOD",
216
+ year=year,
217
+ resolution=resolution,
218
+ data_store=self.data_store,
219
+ coord_system=54009,
220
+ **kwargs,
221
+ )
222
+
223
+ return self.map_ghsl(
224
+ handler=handler, stat=stat, name_prefix=name_prefix, **kwargs
225
+ )
226
+
227
+ def map_ghsl(
228
+ self,
229
+ handler: GHSLDataHandler,
230
+ stat: str,
231
+ name_prefix: Optional[str] = None,
232
+ **kwargs,
233
+ ) -> gpd.GeoDataFrame:
234
+ """Map Global Human Settlement Layer data to zones.
235
+
236
+ Loads and processes GHSL raster data for the intersecting tiles, then samples
237
+ the raster values within each zone using the specified statistic.
238
+
239
+ Args:
240
+ ghsl_data_config (GHSLDataConfig): Configuration specifying which GHSL
241
+ product, year, resolution, and coordinate system to use.
242
+ stat (str): Statistic to calculate for raster values within each zone.
243
+ Common options: "mean", "sum", "median", "min", "max".
244
+ name_prefix (str, optional): Prefix for the output column name.
245
+ If None, uses the GHSL product name in lowercase followed by underscore.
246
+
247
+ Returns:
248
+ gpd.GeoDataFrame: Updated GeoDataFrame with zones and GHSL metrics.
249
+ Adds a column named "{name_prefix}{stat}" containing the sampled values.
250
+
251
+ Note:
252
+ The method automatically determines which GHSL tiles intersect with the zones
253
+ and loads only the necessary data for efficient processing.
254
+ """
255
+ handler = handler or GHSLDataHandler(data_store=self.data_store, **kwargs)
256
+ self.logger.info(
257
+ f"Mapping {handler.config.product} data (year: {handler.config.year}, resolution: {handler.config.resolution}m)"
258
+ )
259
+ tif_processors = handler.load_data(
260
+ self.zone_gdf, ensure_available=self.config.ensure_available
261
+ )
262
+
263
+ self.logger.info(
264
+ f"Sampling {handler.config.product} data using '{stat}' statistic"
265
+ )
266
+ sampled_values = self.map_rasters(tif_processors=tif_processors, stat=stat)
267
+
268
+ name_prefix = (
269
+ name_prefix if name_prefix else handler.config.product.lower() + "_"
270
+ )
271
+ column_name = f"{name_prefix}{stat}"
272
+ self._zone_gdf[column_name] = sampled_values
273
+
274
+ self.logger.info(f"Added {column_name} column")
275
+
276
+ return self._zone_gdf.copy()
277
+
278
+ def map_google_buildings(
279
+ self,
280
+ handler: Optional[GoogleOpenBuildingsHandler] = None,
281
+ use_polygons: bool = False,
282
+ ) -> gpd.GeoDataFrame:
283
+ """Map Google Open Buildings data to zones.
284
+
285
+ Processes Google Open Buildings dataset to calculate building counts and total
286
+ building area within each zone. Can use either point centroids (faster) or
287
+ polygon geometries (more accurate) for spatial operations.
288
+
289
+ Args:
290
+ google_open_buildings_config (GoogleOpenBuildingsConfig): Configuration
291
+ for accessing Google Open Buildings data. Uses default configuration if not provided.
292
+ use_polygons (bool): Whether to use polygon geometries for buildings.
293
+ If True, uses actual building polygons for more accurate area calculations
294
+ but with slower performance. If False, uses building centroids with
295
+ area values from attributes for faster processing. Defaults to False.
296
+
297
+ Returns:
298
+ gpd.GeoDataFrame: Updated GeoDataFrame with zones and building metrics.
299
+ Adds columns:
300
+ - 'google_buildings_count': Number of buildings in each zone
301
+ - 'google_buildings_area_in_meters': Total building area in square meters
302
+
303
+ Note:
304
+ If no Google Buildings data is found for the zones, returns the original
305
+ GeoDataFrame unchanged with a warning logged.
306
+ """
307
+ self.logger.info(
308
+ f"Mapping Google Open Buildings data (use_polygons={use_polygons})"
309
+ )
310
+
311
+ self.logger.info("Loading Google Buildings point data")
312
+ handler = handler or GoogleOpenBuildingsHandler(data_store=self.data_store)
313
+ buildings_df = handler.load_points(
314
+ self.zone_gdf, ensure_available=self.config.ensure_available
315
+ )
316
+
317
+ if buildings_df.empty:
318
+ self.logger.warning("No Google buildings data found for the provided zones")
319
+ return self._zone_gdf.copy()
320
+
321
+ if not use_polygons:
322
+ self.logger.info("Aggregating building data using points with attributes")
323
+ result = self.map_points(
324
+ points=buildings_df,
325
+ value_columns=["full_plus_code", "area_in_meters"],
326
+ aggregation={"full_plus_code": "count", "area_in_meters": "sum"},
327
+ predicate="within",
328
+ )
329
+
330
+ count_result = result["full_plus_code"]
331
+ area_result = result["area_in_meters"]
332
+
333
+ else:
334
+ self.logger.info(
335
+ "Loading Google Buildings polygon data for more accurate mapping"
336
+ )
337
+ buildings_gdf = handler.load_polygons(
338
+ self.zone_gdf, self.config.ensure_available
339
+ )
340
+
341
+ self.logger.info(
342
+ "Calculating building areas with area-weighted aggregation"
343
+ )
344
+ area_result = self.map_polygons(buildings_gdf, area_weighted=True)
345
+
346
+ self.logger.info("Counting buildings using points data")
347
+ count_result = self.map_points(points=buildings_df, predicate="within")
348
+
349
+ self._zone_gdf["google_buildings_count"] = self.zone_gdf.index.map(count_result)
350
+ self._zone_gdf["google_buildings_area_in_meters"] = self.zone_gdf.index.map(
351
+ area_result
352
+ )
353
+
354
+ self.logger.info(f"Added Google building data")
355
+
356
+ return self._zone_gdf.copy()
357
+
358
+ def map_ms_buildings(
359
+ self,
360
+ handler: Optional[MSBuildingsHandler] = None,
361
+ use_polygons: bool = False,
362
+ ) -> gpd.GeoDataFrame:
363
+ """Map Microsoft Global Buildings data to zones.
364
+
365
+ Processes Microsoft Global Buildings dataset to calculate building counts and
366
+ total building area within each zone. Can use either centroid points (faster)
367
+ or polygon geometries (more accurate) for spatial operations.
368
+
369
+ Args:
370
+ ms_buildings_config (MSBuildingsConfig, optional): Configuration for
371
+ accessing Microsoft Global Buildings data. If None, uses default configuration.
372
+ use_polygons (bool): Whether to use polygon geometries for buildings.
373
+ If True, uses actual building polygons for more accurate area calculations
374
+ but with slower performance. If False, uses building centroids with
375
+ area values from attributes for faster processing. Defaults to False.
376
+
377
+ Returns:
378
+ gpd.GeoDataFrame: Updated GeoDataFrame with zones and building metrics.
379
+ Adds columns:
380
+ - 'ms_buildings_count': Number of buildings in each zone
381
+ - 'ms_buildings_area_in_meters': Total building area in square meters
382
+
383
+ Note:
384
+ If no Microsoft Buildings data is found for the zones, returns the original
385
+ GeoDataFrame unchanged with a warning logged. Building areas are calculated
386
+ in meters using appropriate UTM projections.
387
+ """
388
+ self.logger.info("Mapping Microsoft Global Buildings data")
389
+
390
+ self.logger.info("Loading Microsoft Buildings polygon data")
391
+ handler = MSBuildingsHandler(data_store=self.data_store)
392
+ buildings_gdf = handler.load_data(
393
+ self.zone_gdf, ensure_available=self.config.ensure_available
394
+ )
395
+
396
+ # Check if we found any buildings
397
+ if buildings_gdf.empty:
398
+ self.logger.warning(
399
+ "No Microsoft buildings data found for the provided zones"
400
+ )
401
+ return self._zone_gdf.copy()
402
+
403
+ buildings_gdf = add_area_in_meters(buildings_gdf)
404
+
405
+ building_centroids = get_centroids(buildings_gdf)
406
+
407
+ if not use_polygons:
408
+ self.logger.info("Aggregating building data using points with attributes")
409
+
410
+ result = self.map_points(
411
+ points=building_centroids,
412
+ value_columns=["type", "area_in_meters"],
413
+ aggregation={"type": "count", "area_in_meters": "sum"},
414
+ predicate="within",
415
+ )
416
+
417
+ count_result = result["type"]
418
+ area_result = result["area_in_meters"]
419
+ else:
420
+
421
+ self.logger.info(
422
+ "Calculating building areas with area-weighted aggregation"
423
+ )
424
+ area_result = self.map_polygons(buildings_gdf, area_weighted=True)
425
+
426
+ self.logger.info("Counting Microsoft buildings per zone")
427
+
428
+ count_result = self.map_points(
429
+ points=building_centroids, predicate="within"
430
+ )
431
+
432
+ self._zone_gdf["ms_buildings_count"] = self.zone_gdf.index.map(count_result)
433
+ self._zone_gdf["ms_buildings_area_in_meters"] = self.zone_gdf.index.map(
434
+ area_result
435
+ )
436
+
437
+ self.logger.info(f"Added Microsoft building data")
438
+
439
+ return self._zone_gdf.copy()
@@ -0,0 +1,78 @@
1
+ from typing import List, Optional, Union, Tuple, Iterable
2
+ from shapely.geometry import Point
3
+ from shapely.geometry.base import BaseGeometry
4
+
5
+ import geopandas as gpd
6
+ import logging
7
+
8
+ from gigaspatial.core.io.data_store import DataStore
9
+ from gigaspatial.grid.mercator_tiles import MercatorTiles, CountryMercatorTiles
10
+ from gigaspatial.generators.zonal.base import (
11
+ ZonalViewGeneratorConfig,
12
+ T,
13
+ )
14
+ from gigaspatial.generators.zonal.geometry import GeometryBasedZonalViewGenerator
15
+
16
+
17
+ class MercatorViewGenerator(GeometryBasedZonalViewGenerator[T]):
18
+ """Mid-level class for zonal view generation based on geometries with identifiers.
19
+
20
+ This class serves as an intermediate between the abstract ZonalViewGenerator and specific
21
+ implementations like MercatorViewGenerator or H3ViewGenerator. It handles the common case
22
+ where zones are defined by a mapping between zone identifiers and geometries, either
23
+ provided as a dictionary or as a GeoDataFrame.
24
+
25
+ The class extends the base functionality with methods for mapping common geospatial
26
+ datasets including GHSL (Global Human Settlement Layer), Google Open Buildings,
27
+ and Microsoft Global Buildings data.
28
+
29
+ Attributes:
30
+ zone_dict (Dict[T, Polygon]): Mapping of zone identifiers to geometries.
31
+ zone_id_column (str): Name of the column containing zone identifiers.
32
+ zone_data_crs (str): Coordinate reference system of the zone data.
33
+ _zone_gdf (gpd.GeoDataFrame): Cached GeoDataFrame representation of zones.
34
+ data_store (DataStore): For accessing input data.
35
+ generator_config (ZonalViewGeneratorConfig): Configuration for view generation.
36
+ logger: Logger instance for this class.
37
+ """
38
+
39
+ def __init__(
40
+ self,
41
+ source: Union[
42
+ str, # country
43
+ BaseGeometry, # shapely geom
44
+ gpd.GeoDataFrame,
45
+ List[Union[Point, Tuple[float, float]]], # points
46
+ List[str], # quadkeys
47
+ ],
48
+ zoom_level: int,
49
+ predicate="intersects",
50
+ config: Optional[ZonalViewGeneratorConfig] = None,
51
+ data_store: Optional[DataStore] = None,
52
+ logger: logging.Logger = None,
53
+ ):
54
+
55
+ super().__init__(
56
+ zone_data=self._init_zone_data(source, zoom_level, predicate),
57
+ zone_id_column="quadkey",
58
+ config=config,
59
+ data_store=data_store,
60
+ logger=logger,
61
+ )
62
+
63
+ def _init_zone_data(self, source, zoom_level, predicate):
64
+ if isinstance(source, str):
65
+ tiles = CountryMercatorTiles.create(country=source, zoom_level=zoom_level)
66
+ elif isinstance(source, (BaseGeometry, Iterable)):
67
+ if isinstance(source, Iterable) and all(
68
+ isinstance(qk, str) for qk in source
69
+ ):
70
+ tiles = MercatorTiles.from_quadkeys(source)
71
+ else:
72
+ tiles = MercatorTiles.from_spatial(
73
+ source=source, zoom_level=zoom_level, predicate=predicate
74
+ )
75
+ else:
76
+ raise ValueError("sadadasfasfkasmf")
77
+
78
+ return tiles.to_geodataframe()
@@ -0,0 +1 @@
1
+ from gigaspatial.grid.mercator_tiles import *