giga-spatial 0.6.9__tar.gz → 0.7.1__tar.gz

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 (94) hide show
  1. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/.env_sample +1 -0
  2. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/CHANGELOG.md +179 -0
  3. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/PKG-INFO +30 -4
  4. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/README.md +8 -0
  5. giga_spatial-0.7.1/docs/examples/processing/tif.md +146 -0
  6. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/giga_spatial.egg-info/PKG-INFO +30 -4
  7. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/giga_spatial.egg-info/SOURCES.txt +2 -0
  8. giga_spatial-0.6.9/requirements.txt → giga_spatial-0.7.1/giga_spatial.egg-info/requires.txt +4 -2
  9. giga_spatial-0.7.1/gigaspatial/__init__.py +1 -0
  10. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/config.py +1 -0
  11. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/core/io/adls_data_store.py +104 -11
  12. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/core/io/local_data_store.py +8 -0
  13. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/generators/poi.py +226 -82
  14. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/generators/zonal/base.py +41 -28
  15. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/generators/zonal/geometry.py +91 -41
  16. giga_spatial-0.7.1/gigaspatial/grid/h3.py +417 -0
  17. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/grid/mercator_tiles.py +1 -1
  18. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/handlers/base.py +22 -8
  19. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/handlers/ghsl.py +22 -8
  20. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/handlers/giga.py +9 -4
  21. giga_spatial-0.7.1/gigaspatial/handlers/healthsites.py +350 -0
  22. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/handlers/osm.py +325 -105
  23. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/handlers/worldpop.py +228 -9
  24. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/processing/geo.py +11 -6
  25. giga_spatial-0.7.1/gigaspatial/processing/tif_processor.py +1737 -0
  26. giga_spatial-0.6.9/giga_spatial.egg-info/requires.txt → giga_spatial-0.7.1/requirements.txt +3 -1
  27. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/setup.py +19 -1
  28. giga_spatial-0.6.9/docs/examples/processing/tif.md +0 -33
  29. giga_spatial-0.6.9/gigaspatial/__init__.py +0 -1
  30. giga_spatial-0.6.9/gigaspatial/processing/tif_processor.py +0 -1050
  31. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/CODE_OF_CONDUCT.md +0 -0
  32. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/CONTRIBUTING.md +0 -0
  33. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/LICENSE +0 -0
  34. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/MANIFEST.in +0 -0
  35. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/PULL_REQUEST_TEMPLATE.md +0 -0
  36. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/.DS_Store +0 -0
  37. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/api/core.md +0 -0
  38. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/api/generators.md +0 -0
  39. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/api/grid.md +0 -0
  40. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/api/handlers.md +0 -0
  41. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/api/index.md +0 -0
  42. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/api/processing.md +0 -0
  43. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/assets/GIGA_horizontal_notext_white.webp +0 -0
  44. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/assets/datasets.png +0 -0
  45. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/assets/logo.png +0 -0
  46. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/changelog.md +0 -0
  47. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/contributing.md +0 -0
  48. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/examples/advanced.md +0 -0
  49. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/examples/basic.md +0 -0
  50. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/examples/downloading/ghsl.md +0 -0
  51. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/examples/downloading/osm.md +0 -0
  52. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/examples/index.md +0 -0
  53. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/examples/use-cases.md +0 -0
  54. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/getting-started/installation.md +0 -0
  55. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/getting-started/quickstart.md +0 -0
  56. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/index.md +0 -0
  57. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/license.md +0 -0
  58. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/stylesheets/extra.css +0 -0
  59. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/user-guide/configuration.md +0 -0
  60. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/docs/user-guide/index.md +0 -0
  61. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/giga_spatial.egg-info/dependency_links.txt +0 -0
  62. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/giga_spatial.egg-info/top_level.txt +0 -0
  63. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/core/__init__.py +0 -0
  64. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/core/io/__init__.py +0 -0
  65. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/core/io/data_api.py +0 -0
  66. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/core/io/data_store.py +0 -0
  67. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/core/io/database.py +0 -0
  68. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/core/io/readers.py +0 -0
  69. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/core/io/writers.py +0 -0
  70. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/core/schemas/__init__.py +0 -0
  71. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/core/schemas/entity.py +0 -0
  72. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/generators/__init__.py +0 -0
  73. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/generators/zonal/__init__.py +0 -0
  74. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/generators/zonal/admin.py +0 -0
  75. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/generators/zonal/mercator.py +0 -0
  76. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/grid/__init__.py +0 -0
  77. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/handlers/__init__.py +0 -0
  78. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/handlers/boundaries.py +0 -0
  79. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/handlers/google_open_buildings.py +0 -0
  80. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/handlers/hdx.py +0 -0
  81. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/handlers/mapbox_image.py +0 -0
  82. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/handlers/maxar_image.py +0 -0
  83. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/handlers/microsoft_global_buildings.py +0 -0
  84. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/handlers/ookla_speedtest.py +0 -0
  85. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/handlers/opencellid.py +0 -0
  86. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/handlers/overture.py +0 -0
  87. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/handlers/rwi.py +0 -0
  88. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/handlers/unicef_georepo.py +0 -0
  89. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/processing/__init__.py +0 -0
  90. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/processing/algorithms.py +0 -0
  91. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/processing/sat_images.py +0 -0
  92. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/gigaspatial/processing/utils.py +0 -0
  93. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/pyproject.toml +0 -0
  94. {giga_spatial-0.6.9 → giga_spatial-0.7.1}/setup.cfg +0 -0
@@ -15,6 +15,7 @@ export GEOREPO_USER_EMAIL=""
15
15
  export GIGA_SCHOOL_LOCATION_API_KEY=""
16
16
  export GIGA_SCHOOL_PROFILE_API_KEY=""
17
17
  export GIGA_SCHOOL_MEASUREMENTS_API_KEY=""
18
+ export HEALTHSITES_API_KEY=""
18
19
  export ROOT_DATA_DIR=""
19
20
  export BRONZE_DIR=""
20
21
  export SILVER_DIR=""
@@ -2,6 +2,185 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [v0.7.1] - 2025-10-15
6
+
7
+ ### Added
8
+
9
+ - **Healthsites.io API Integration (`HealthSitesFetcher`):**
10
+ - New class `HealthSitesFetcher` to fetch and process health facility data from the Healthsites.io API.
11
+ - Supports filtering by country, bounding box extent, and date ranges (`from_date`, `to_date`).
12
+ - Provides methods for:
13
+ - `fetch_facilities()`: Retrieves health facility locations, returning a `pd.DataFrame` or `gpd.GeoDataFrame` based on output format.
14
+ - `fetch_statistics()`: Fetches aggregated statistics for health facilities based on provided filters.
15
+ - `fetch_facility_by_id()`: Retrieves details for a specific facility using its OSM type and ID.
16
+ - Includes robust handling for API pagination, different output formats (JSON, GeoJSON), and nested data structures.
17
+ - Integrates with `OSMLocationFetcher` and `pycountry` to standardize country names to OSM English names for consistent querying.
18
+ - Configurable parameters for API URL, API key, page size, flat properties, tag format, output format, and request sleep time.
19
+
20
+ - **OSMLocationFetcher Enhancements:**
21
+ - **Historical Data Fetching (`fetch_locations_changed_between`):**
22
+ - New method `fetch_locations_changed_between()` to retrieve OSM objects that were created or modified within a specified date range. This enables historical analysis and change tracking.
23
+ - Defaults `include_metadata` to `True` for this method, as it's typically used for change tracking.
24
+ - **Comprehensive OSM Country Information (`get_osm_countries`):**
25
+ - New static method `get_osm_countries()` to fetch country-level administrative boundaries directly from the OSM database.
26
+ - Supports fetching all countries or a specific country by ISO 3166-1 alpha-3 code.
27
+ - Option to include various name variants (e.g., `name:en`, `official_name`) and ISO codes.
28
+ - **Metadata Inclusion in Fetched Locations:**
29
+ - Added `include_metadata` parameter to `fetch_locations()` to optionally retrieve change tracking metadata (timestamp, version, changeset, user, uid) for each fetched OSM element.
30
+ - This metadata is now extracted and included in the DataFrame for nodes, relations, and ways.
31
+ - **Flexible Date Filtering in Overpass Queries:**
32
+ - Introduced `date_filter_type` (`newer`, `changed`) and `start_date`/`end_date` parameters to `_build_queries()` for more granular control over time-based filtering in Overpass QL.
33
+ - **Date Normalization Utility:**
34
+ - Added `_normalize_date()` helper method to convert various date inputs (string, datetime object) into a standardized ISO 8601 format for Overpass API queries.
35
+
36
+ - **TifProcessor**
37
+ - **Comprehensive Memory Management:**
38
+ - Introduced `_check_available_memory()`, `_estimate_memory_usage()`, and `_memory_guard()` methods for proactive memory assessment across various operations.
39
+ - Added warnings (`ResourceWarning`) for potentially high memory usage in batched operations, with suggestions for optimizing `n_workers`.
40
+ - **Chunked DataFrame Conversion:**
41
+ - Implemented `to_dataframe_chunked()` for memory-efficient processing of large rasters by converting them to DataFrames in manageable chunks.
42
+ - Automatic calculation of optimal `chunk_size` based on target memory usage via `_calculate_optimal_chunk_size()`.
43
+ - New helper methods: `_get_chunk_windows()`, `_get_chunk_coordinates()`.
44
+ - **Raster Clipping Functionality:**
45
+ - `clip_to_geometry()`: New method to clip rasters to arbitrary geometries (Shapely, GeoDataFrame, GeoSeries, GeoJSON-like dicts).
46
+ - `clip_to_bounds()`: New method to clip rasters to rectangular bounding boxes, supporting optional CRS transformation for the bounds.
47
+ - New helper methods for clipping: `_prepare_geometry_for_clipping()`, `_validate_geometry_crs()`, `_create_clipped_processor()`.
48
+
49
+ - **WorldPopDownloader Zip Handling:**
50
+ - Modified `download_data_unit` in `WPPopulationDownloader` to correctly handle `.zip` files (e.g., school age datasets) by downloading them to a temporary location and extracting the contained `.tif` files.
51
+ - Updated `download_data_units` to correctly flatten the list of paths returned by `download_data_unit` when zip extraction results in multiple files.
52
+ - Adjusted `WPPopulationConfig.get_data_unit_paths` to correctly identify and return paths for extracted `.tif` files from zip resources. It is now intelligently resolves paths. For school-age datasets, it returns paths to extracted `.tif` files if available; otherwise, it returns the original `.zip` path(s) to trigger download and extraction.
53
+ - Added filter support to `WPPopulationConfig.get_data_unit_paths` hence to the `WPPopulationHandler` for:
54
+ - School-age datasets: supports `sex` (e.g., "F", "M", "F_M") and `education_level` (e.g., "PRIMARY", "SECONDARY") filters on extracted `.tif` filenames.
55
+ - Non-school-age age_structures: supports `sex`, `ages`, `min_age`, and `max_age` filters on `.tif` filenames.
56
+ - **WorldPop: Filtered aggregation in `GeometryBasedZonalViewGenerator.map_wp_pop`**:
57
+ - `map_wp_pop` now enforces a single country input when `handler.config.project` is "age_structures".
58
+ - When `predicate` is "centroid_within" and the project is "age_structures", individual `TifProcessor` objects (representing age/sex combinations) are loaded, sampled with `map_rasters(stat="sum")`, and their results are summed per zone, preventing unintended merging.
59
+
60
+ - **PoiViewGenerator: Filtered aggregation in `PoiViewGenerator.map_wp_pop`**:
61
+ - `map_wp_pop` now enforces a single country input when `handler.config.project` is "age_structures".
62
+ - When `predicate` is "centroid_within" and the project is "age_structures", individual `TifProcessor` objects (representing age/sex combinations) are loaded, sampled with `map_zonal_stats(stat="sum")`, and their results are summed per POI, preventing unintended merging.
63
+
64
+ - **TifProcessor Multi-Raster Merging in Handlers and Generators:**
65
+ - Extended `_load_raster_data` in `BaseHandlerReader` to support an optional `merge_rasters` argument. When `True` and multiple raster paths are provided, `TifProcessor` now merges them into a single `TifProcessor` object during loading.
66
+ - Integrated `merge_rasters` argument into `GHSLDataReader` and `WPPopulationReader`'s `load_from_paths` and `load` methods, enabling control over raster merging at the reader level.
67
+ - Propagated `merge_rasters` to `GHSLDataHandler`'s `load_into_dataframe`, and `load_into_geodataframe` methods for consistent behavior across the handler interface.
68
+
69
+ ### Changed
70
+
71
+ - **TifProcessor**
72
+ - **Unified DataFrame Conversion:**
73
+ - Refactored `to_dataframe()` to act as a universal entry point, dynamically routing to internal, more efficient methods for single and multi-band processing.
74
+ - Deprecated the individual `_to_band_dataframe()`, `_to_rgb_dataframe()`, `_to_rgba_dataframe()`, and `_to_multi_band_dataframe()` methods in favor of the new unified `_to_dataframe()`.
75
+ - `to_dataframe()` now includes a `check_memory` parameter.
76
+ - **Optimized `open_dataset` Context Manager:**
77
+ - The `open_dataset` context manager now directly opens local files when `LocalDataStore` is used, avoiding unnecessary `rasterio.MemoryFile` creation for improved performance and reduced memory overhead.
78
+ - **Enhanced `to_geodataframe` and `to_graph`:**
79
+ - Added `check_memory` parameter to `to_geodataframe()` and `to_graph()` for memory pre-checks.
80
+ - **Refined `sample_by_polygons_batched`:**
81
+ - Included `check_memory` parameter for memory checks before batch processing.
82
+ - Implemented platform-specific warnings for potential multiprocessing issues on Windows/macOS.
83
+ - **Improved Multiprocessing Initialization:**
84
+ - The `_initializer_worker()` method now prioritizes merged, reprojected, or original local file paths for opening, ensuring workers access the most relevant data.
85
+ - **Modular Masking and Coordinate Extraction:**
86
+ - Introduced new private helper methods: `_extract_coordinates_with_mask()`, `_build_data_mask()`, `_build_multi_band_mask()`, and `_bands_to_dict()` to centralize and improve data masking and coordinate extraction logic.
87
+ - **Streamlined Band-Mode Validation:**
88
+ - Moved the logic for validating `mode` and band count compatibility into a dedicated `_validate_mode_band_compatibility()` method for better code organization.
89
+
90
+ - **GigaSchoolLocationFetcher**
91
+ - `fetch_locations()` method:
92
+ - Added `process_geospatial` parameter (defaults to `False`) to optionally process geospatial data and return a `gpd.GeoDataFrame`.
93
+ - `_process_geospatial_data()` method:
94
+ - Modified to return a `gpd.GeoDataFrame` by converting the `pd.DataFrame` with a `geometry` column and `EPSG:4326` CRS.
95
+
96
+ - **OSMLocationFetcher Refactoring:**
97
+ - **Unified Query Execution and Processing:** Refactored the core logic for executing Overpass queries and processing their results into a new private method `_execute_and_process_queries()`. This centralizes common steps and reduces code duplication between `fetch_locations()` and the new `fetch_locations_changed_between()`.
98
+ - **Enhanced `_build_queries`:** Modified `_build_queries` to accept `date_filter_type`, `start_date`, `end_date`, and `include_metadata` to construct more dynamic and feature-rich Overpass QL queries.
99
+ - **Updated `fetch_locations` Signature:**
100
+ - Replaced `since_year` parameter with `since_date` (which can be a `str` or `datetime` object) for more precise time-based filtering.
101
+ - Added `include_metadata` parameter.
102
+ - **Improved Logging of Category Distribution:**
103
+ - Modified the logging for category distribution to correctly handle cases where categories are combined into a list (when `handle_duplicates='combine'`).
104
+ - **`since_year` Parameter:** Removed `since_year` from `fetch_locations()` as its functionality is now superseded by the more flexible `since_date` parameter and the `_build_queries` enhancements.
105
+
106
+ - **`PoiViewGenerator` Mapping Methods (`map_zonal_stats`, `map_nearest_points`, `map_google_buildings`, `map_ms_buildings`, `map_built_s`, `map_smod`):**
107
+ - Changed `map_zonal_stats` and `map_nearest_points` to return `pd.DataFrame` results (including `'poi_id'` and new mapped columns) instead of directly updating the internal view.
108
+ - Updated `map_google_buildings`, `map_ms_buildings`, `map_built_s`, and `map_smod` to capture the `pd.DataFrame` returned by their respective underlying mapping calls (`map_nearest_points` or `map_zonal_stats`) and then explicitly call `self._update_view()` with these results.
109
+ - This enhances modularity and allows for more flexible result handling and accumulation.
110
+
111
+ - **`ZonalViewGenerator.map_rasters` Enhancements:**
112
+ - Modified `map_rasters` to accept `raster_data` as either a single `TifProcessor` or a `List[TifProcessor]`.
113
+ - Implemented internal merging of `List[TifProcessor]` into a single `TifProcessor` before performing zonal statistics.
114
+ - Replaced `sample_multiple_tifs_by_polygons` with the `TifProcessor.sample_by_polygons` method.
115
+
116
+ ### Fixed
117
+
118
+ - **TifProcessor**:
119
+ - **`to_graph()` Sparse Matrix Creation:**
120
+ - Corrected the sparse matrix creation logic in `to_graph()` to ensure proper symmetric graph representation when `graph_type="sparse"`.
121
+ - **Coordinate System Handling in `_initializer_worker`:**
122
+ - Ensured that `_initializer_worker` correctly handles different data storage scenarios to provide the correct dataset handle to worker processes, preventing `RuntimeError` due to uninitialized raster datasets.
123
+
124
+ ### Removed
125
+
126
+ - **OSMLocationFetcher**
127
+ - **Redundant Category Distribution Logging:** Removed the explicit category distribution logging for `handle_duplicates == "separate"` since the `value_counts()` method on the 'category' column already provides this.
128
+
129
+
130
+ ## [v0.7.0] - 2025-09-17
131
+
132
+ ### Added
133
+
134
+ - **TifProcessor Revamp**
135
+ - **Explicit Reprojection Method:** Introduced `reproject_to()` method, allowing on-demand reprojection of rasters to a new CRS with customizable `resampling_method` and `resolution`.
136
+ - **Reprojection Resolution Control:** Added `reprojection_resolution` parameter to `TifProcessor` for precise control over output pixel size during reprojection.
137
+ - **Advanced Raster Information:** Added `get_raster_info()` method to retrieve a comprehensive dictionary of raster metadata.
138
+ - **Graph Conversion Capabilities:** Implemented `to_graph()` method to convert raster data into a graph (NetworkX or sparse matrix) based on pixel adjacency (4- or 8-connectivity).
139
+ - **Internal Refactoring: `_reproject_to_temp_file`:** Introduced `_reproject_to_temp_file` as a helper for reprojection into temporary files.
140
+
141
+ - **H3 Grid Generation**
142
+ - **H3 Grid Generation Module (`gigaspatial/grid/h3.py`):**
143
+ - Introduced `H3Hexagons` class for managing H3 cell IDs.
144
+ - Supports creation from lists of hexagons, geographic bounds, spatial geometries, or points.
145
+ - Provides methods to convert H3 hexagons to pandas DataFrames and GeoPandas GeoDataFrames.
146
+ - Includes functionalities for filtering, getting k-ring neighbors, compacting hexagons, and getting children/parents at different resolutions.
147
+ - Allows saving H3Hexagons to JSON, Parquet, or GeoJSON files.
148
+ - **Country-Specific H3 Hexagons (`CountryH3Hexagons`):**
149
+ - Extends `H3Hexagons` for generating H3 grids constrained by country boundaries.
150
+ - Integrates with `AdminBoundaries` to fetch country geometries for precise H3 cell generation.
151
+
152
+ - **Documentation**
153
+ - Improved `tif.md` example to showcase multi-raster initialization, explicit reprojection, and graph conversion.
154
+
155
+ ### Changed
156
+
157
+ - **TifProcessor**
158
+ - **Improved Temporary File Management:** Refactored temporary file handling for merging and reprojection using `tempfile.mkdtemp()` and `shutil.rmtree` for more robust and reliable cleanup. Integrated with context manager (`__enter__`, `__exit__`) and added a dedicated `cleanup()` method.
159
+ - **Reprojection during Initialization:** Implemented automatic reprojection of single rasters to a specified `target_crs` during `TifProcessor` initialization.
160
+ - **Enhanced `open_dataset` Context Manager:** The `open_dataset` context manager now intelligently opens the most up-to-date (merged or reprojected) version of the dataset.
161
+ - **More Flexible Multi-Dataset Validation:** Modified `_validate_multiple_datasets` to issue a warning instead of raising an error for CRS mismatches when `target_crs` is not set.
162
+ - **Optimized `_get_reprojection_profile`:** Dynamically calculates transform and dimensions based on `reprojection_resolution` and added LZW compression to reprojected TIFF files to reduce file size.
163
+
164
+ - **ADLSDataStore Enhancements**
165
+ - **New `copy_file` method:** Implemented a new method for copying individual files within ADLS, with an option to overwrite existing files.
166
+ - **New `rename` method:** Added a new method to rename (move) files in ADLS, which internally uses `copy_file` and then deletes the source, with options for overwrite, waiting for copy completion, and polling.
167
+ - **Revamped `rmdir` method:** Modified `rmdir` to perform batch deletions of blobs, addressing the Azure Blob batch delete limit (256 sub-requests) and improving efficiency for large directories.
168
+
169
+ - **LocalDataStore Enhancements**
170
+ - **New `copy_file` method:** Implemented a new method for copying individual files.
171
+
172
+ ### Removed
173
+
174
+ - Removed deprecated `tabular` property and `get_zoned_geodataframe` method from `TifProcessor`. Users should now use `to_dataframe()` and `to_geodataframe()` respectively.
175
+
176
+ ### Dependencies
177
+
178
+ - Added `networkx` and `h3` as new dependencies.
179
+
180
+ ### Fixed
181
+
182
+ - Several small fixes and improvements to aggregation methods.
183
+
5
184
  ## [v0.6.9] - 2025-07-26
6
185
 
7
186
  ### Fixed
@@ -1,13 +1,29 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: giga-spatial
3
- Version: 0.6.9
3
+ Version: 0.7.1
4
4
  Summary: A package for spatial data download & processing
5
- Home-page: https://github.com/unicef/giga-spatial
6
5
  Author: Utku Can Ozturk
7
6
  Author-email: utkucanozturk@gmail.com
8
7
  License: AGPL-3.0-or-later
8
+ Project-URL: Homepage, https://github.com/unicef/giga-spatial
9
+ Project-URL: Documentation, https://unicef.github.io/giga-spatial/
10
+ Project-URL: Source, https://github.com/unicef/giga-spatial
11
+ Project-URL: Issue Tracker, https://github.com/unicef/giga-spatial/issues
12
+ Project-URL: Discussions, https://github.com/unicef/giga-spatial/discussions
13
+ Project-URL: Changelog, https://unicef.github.io/giga-spatial/changelog
9
14
  Keywords: gigaspatial,spatial,geospatial,gis,remote sensing,data processing,download,openstreetmap,osm,ghsl,grid,point of interest,POI,raster,vector,school connectivity,unicef,giga,mapping,analysis,python
15
+ Classifier: Development Status :: 5 - Production/Stable
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: Intended Audience :: Education
18
+ Classifier: Intended Audience :: Healthcare Industry
19
+ Classifier: Intended Audience :: Science/Research
20
+ Classifier: Intended Audience :: Telecommunications Industry
21
+ Classifier: Programming Language :: Python
10
22
  Classifier: Programming Language :: Python :: 3
23
+ Classifier: Programming Language :: Python :: 3.10
24
+ Classifier: Programming Language :: Python :: 3.11
25
+ Classifier: Programming Language :: Python :: 3.12
26
+ Classifier: Topic :: Scientific/Engineering :: GIS
11
27
  Classifier: License :: OSI Approved :: GNU Affero General Public License v3
12
28
  Classifier: Operating System :: OS Independent
13
29
  Requires-Python: >=3.10
@@ -24,8 +40,9 @@ Requires-Dist: pycountry==24.6.1
24
40
  Requires-Dist: pydantic>=2.10.6
25
41
  Requires-Dist: rasterio==1.3.10
26
42
  Requires-Dist: Requests==2.32.3
27
- Requires-Dist: scipy==1.15.1
43
+ Requires-Dist: scipy>=1.15.1
28
44
  Requires-Dist: Shapely>=2.0.7
45
+ Requires-Dist: networkx>=3.2.1
29
46
  Requires-Dist: tqdm==4.65.0
30
47
  Requires-Dist: OWSLib==0.32.1
31
48
  Requires-Dist: pydantic-settings>=2.7.1
@@ -33,15 +50,16 @@ Requires-Dist: hdx-python-api>=6.3.8
33
50
  Requires-Dist: bs4==0.0.2
34
51
  Requires-Dist: sqlalchemy-trino==0.5.0
35
52
  Requires-Dist: dask>=2024.12.1
53
+ Requires-Dist: h3>=4.2.0
36
54
  Dynamic: author
37
55
  Dynamic: author-email
38
56
  Dynamic: classifier
39
57
  Dynamic: description
40
58
  Dynamic: description-content-type
41
- Dynamic: home-page
42
59
  Dynamic: keywords
43
60
  Dynamic: license
44
61
  Dynamic: license-file
62
+ Dynamic: project-url
45
63
  Dynamic: requires-dist
46
64
  Dynamic: requires-python
47
65
  Dynamic: summary
@@ -53,6 +71,14 @@ Dynamic: summary
53
71
 
54
72
  # GigaSpatial
55
73
 
74
+ [![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-brightgreen.svg)](https://opensource.org/license/agpl-v3)
75
+ [![PyPI version](https://badge.fury.io/py/giga-spatial.svg)](https://badge.fury.io/py/giga-spatial)
76
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/giga-spatial.svg?color=dark-green)](https://pypi.org/project/giga-spatial/)
77
+ [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
78
+ [![PyPI Downloads](https://static.pepy.tech/badge/giga-spatial)](https://pepy.tech/projects/giga-spatial)
79
+ [![GitHub commit activity](https://img.shields.io/github/commit-activity/y/unicef/giga-spatial.svg?color=dark-green)](https://github.com/unicef/giga-spatial/graphs/contributors)
80
+
81
+
56
82
  ## About Giga
57
83
 
58
84
  [Giga](https://giga.global/) is a UNICEF-ITU initiative to connect every school to the Internet and every young person to information, opportunity and choice.
@@ -5,6 +5,14 @@
5
5
 
6
6
  # GigaSpatial
7
7
 
8
+ [![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-brightgreen.svg)](https://opensource.org/license/agpl-v3)
9
+ [![PyPI version](https://badge.fury.io/py/giga-spatial.svg)](https://badge.fury.io/py/giga-spatial)
10
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/giga-spatial.svg?color=dark-green)](https://pypi.org/project/giga-spatial/)
11
+ [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
12
+ [![PyPI Downloads](https://static.pepy.tech/badge/giga-spatial)](https://pepy.tech/projects/giga-spatial)
13
+ [![GitHub commit activity](https://img.shields.io/github/commit-activity/y/unicef/giga-spatial.svg?color=dark-green)](https://github.com/unicef/giga-spatial/graphs/contributors)
14
+
15
+
8
16
  ## About Giga
9
17
 
10
18
  [Giga](https://giga.global/) is a UNICEF-ITU initiative to connect every school to the Internet and every young person to information, opportunity and choice.
@@ -0,0 +1,146 @@
1
+ # Processing Raster Files
2
+
3
+ This example demonstrates how to process raster files using the `TifProcessor` class.
4
+
5
+ ## Prerequisites
6
+
7
+ Ensure you have installed the `gigaspatial` package and set up the necessary configuration. Follow the [Installation Guide](../getting-started/installation.md) if you haven’t already.
8
+
9
+ ## Example Code
10
+
11
+ ```python
12
+ from gigaspatial.processing import TifProcessor
13
+ from gigaspatial.core.io import LocalDataStore
14
+ from rasterio.warp import Resampling # For reprojection methods
15
+
16
+ # NOTE: For these examples, replace "/path/to/your/file.tif" with actual paths to your GeoTIFF files.
17
+ # You might need to create dummy files or use existing ones for local testing.
18
+
19
+ # 1. Initialize with a single TIFF file
20
+ print("--- Single TIFF File Processing ---")
21
+ single_processor = TifProcessor(
22
+ "/path/to/single_band.tif",
23
+ mode="single" # Can be "rgb", "rgba", "multi"
24
+ )
25
+ df_single = single_processor.to_dataframe()
26
+ print("Single-band DataFrame head:")
27
+ print(df_single.head())
28
+ print("Raster Info for single_processor:")
29
+ print(single_processor.get_raster_info())
30
+
31
+
32
+ # 2. Initialize with multiple TIFF files for merging and reprojection
33
+ print("\n--- Multi-raster Merging and Reprojection ---")
34
+ # Replace with actual paths to your tif files. Ensure they are compatible for merging.
35
+ # Example: two adjacent tiles from a dataset.
36
+ tif_paths = [
37
+ "/path/to/raster1.tif",
38
+ "/path/to/raster2.tif"
39
+ ]
40
+ merged_reprojected_processor = TifProcessor(
41
+ dataset_path=tif_paths,
42
+ mode="single", # Or "multi", "rgb", "rgba" depending on your data
43
+ merge_method="mean", # Options: "first", "last", "min", "max", "mean"
44
+ target_crs="EPSG:4326", # Reproject all rasters to WGS84 during initialization
45
+ )
46
+ df_merged = merged_reprojected_processor.to_dataframe()
47
+ print("Merged and Reprojected DataFrame head:")
48
+ print(df_merged.head())
49
+ print("Raster Info for merged_reprojected_processor:")
50
+ print(merged_reprojected_processor.get_raster_info())
51
+
52
+ # 3. Explicit Reprojection after initialization
53
+ print("\n--- Explicit Reprojection ---")
54
+ # Reproject the current raster (e.g., the merged one) to a different CRS or resolution
55
+ # In a real scenario, you'd save this to a persistent location.
56
+ reprojected_output_path = "./temp_reprojected_raster.tif"
57
+ reprojected_path = merged_reprojected_processor.reproject_to(
58
+ target_crs="EPSG:3857", # Web Mercator
59
+ output_path=reprojected_output_path,
60
+ resampling_method=Resampling.bilinear # Different resampling method
61
+ )
62
+ print(f"Raster reprojected to: {reprojected_path}")
63
+
64
+ # 4. Convert raster to a graph (NetworkX example)
65
+ print("\n--- Raster to Graph Conversion ---")
66
+ # Assuming '/path/to/single_band.tif' is a suitable single-band raster
67
+ graph_processor = TifProcessor(
68
+ "/path/to/single_band.tif",
69
+ mode="single" # Graph conversion typically for single-band data
70
+ )
71
+ graph = graph_processor.to_graph(
72
+ connectivity=8, # 4-connectivity (von Neumann) or 8-connectivity (Moore)
73
+ include_coordinates=True, # Include 'x' and 'y' coordinates as node attributes
74
+ graph_type="networkx" # Or "sparse" for scipy.sparse.csr_matrix
75
+ )
76
+ print(f"Generated a NetworkX graph with {graph.number_of_nodes()} nodes and {graph.number_of_edges()} edges.")
77
+ # Example: Access node attributes (first 5 nodes)
78
+ # for node_id, data in list(graph.nodes(data=True))[:5]:
79
+ # print(f"Node {node_id}: Value={data['value']:.2f}, X={data.get('x'):.2f}, Y={data.get('y'):.2f}")
80
+ ```
81
+
82
+ ## Explanation
83
+
84
+ The `TifProcessor` class provides robust functionalities for handling GeoTIFF files, from single-band to multi-band (RGB, RGBA) datasets, with advanced processing capabilities including:
85
+
86
+ - **Initialization**:
87
+ - Can be initialized with a single GeoTIFF file path.
88
+ - Supports a list of GeoTIFF file paths for **automatic merging** during initialization, configured via `merge_method` (`first`, `last`, `min`, `max`, `mean`).
89
+ - The `mode` parameter (`single`, `rgb`, `rgba`, `multi`) dictates how bands are interpreted and validated.
90
+ - `target_crs` and `reprojection_resolution` can be set during initialization to reproject rasters immediately to a consistent CRS and pixel size.
91
+ - **Data Extraction**:
92
+ - `to_dataframe()`: Converts raster data into a pandas DataFrame, with columns for longitude, latitude, and pixel values (or band-specific values for multi-band modes).
93
+ - `to_geodataframe()`: Extends `to_dataframe()` by adding a `geometry` column, converting each pixel into a GeoDataFrame representing its bounding box, with the correct CRS.
94
+ - **Reprojection (`reproject_to`)**:
95
+ - Allows explicit reprojection of the current raster to a new Coordinate Reference System (CRS) and/or resolution, saving the output to a specified path or a temporary file.
96
+ - Supports different `resampling_method` options (e.g., `Resampling.nearest`, `Resampling.bilinear`).
97
+ - **Raster Information (`get_raster_info`)**:
98
+ - Provides a dictionary containing comprehensive metadata about the raster, such as band count, dimensions, CRS, bounds, transform, data types, nodata values, processing mode, and merge status.
99
+ - **Graph Conversion (`to_graph`)**:
100
+ - Converts raster data into a graph (NetworkX graph or SciPy sparse matrix) based on pixel adjacency.
101
+ - Supports `connectivity` of 4 (von Neumann neighborhood) or 8 (Moore neighborhood).
102
+ - Can include geographic coordinates and pixel values as node attributes.
103
+ - **Sampling**:
104
+ - `sample_by_coordinates()`: Extracts pixel values at specific geographic coordinates.
105
+ - `sample_by_polygons()`: Computes aggregate statistics (e.g., mean, sum, min, max, count) of pixel values within given polygon boundaries, supporting single or multiple statistics.
106
+ - `sample_by_polygons_batched()`: Provides a parallelized version of polygon sampling for performance-intensive tasks.
107
+
108
+ ---
109
+
110
+ # Multi-raster reprojection
111
+
112
+ The differences in the reprojected metadata are expected and are a direct result of the order of operations: **reproject then merge** versus **merge then reproject**. The two processes follow different steps, leading to variations in the final raster's dimensions, bounds, and resolution.
113
+
114
+ ---
115
+
116
+ ### **Reproject then Merge**
117
+
118
+ When you specify `target_crs` at initialization, the code first **reprojects each individual raster** to the target CRS (`EPSG:4326`) and then **merges the reprojected outputs**.
119
+
120
+ - **Step 1: Reprojection**: Each input raster is reprojected from `ESRI:54009` to `EPSG:4326`. During this step, `rasterio`'s `calculate_default_transform` function computes a new transform and pixel dimensions (`width`, `height`) for each raster. The reprojected rasters are now in the same CRS with a consistent resolution (e.g., `0.00918...` degrees).
121
+ - **Step 2: Merging**: The reprojected rasters, which are now in the same CRS and have similar resolutions, are merged. The `rasterio.merge` function can combine these aligned rasters seamlessly. The final output's dimensions are calculated by finding the union of all reprojected rasters' bounds and applying the shared resolution, resulting in a single, larger raster.
122
+
123
+ This process ensures a uniform resolution and grid alignment across all parts of the final merged raster.
124
+
125
+ ---
126
+
127
+ ### **Merge then Reproject**
128
+
129
+ When `target_crs` is not specified at initialization, the code first **merges the two rasters** in their original `ESRI:54009` CRS and then **reprojects the single, merged output** to `EPSG:4326`.
130
+
131
+ - **Step 1: Merging**: The two rasters are merged in `ESRI:54009`. Since they are in the same CRS and have the same resolution (`1000.0` meters), `rasterio.merge` can simply combine them side-by-side. The original raster was `1000x1000`, so merging a second one next to it likely creates a `2000x1000` raster, as seen in the metadata. The resolution remains `1000.0` meters.
132
+ - **Step 2: Reprojection**: The single `2000x1000` raster is then reprojected to `EPSG:4326`. A new transform and pixel dimensions are calculated for this single, larger raster. Since `calculate_default_transform` is working on a different-shaped input, it will calculate a different output resolution and grid shape. The resulting resolution (`0.00973...`) and dimensions (`2076x832`) will be different because the reprojection is performed on a single, larger input rather than two smaller ones.
133
+
134
+ ---
135
+
136
+ ### **Why the Metadata is Different**
137
+
138
+ - **Resolution**: The `reproject-then-merge` approach maintains a consistent resolution that is calculated for a single tile and then applied to all. The `merge-then-reproject` approach calculates a single resolution for the entire, larger combined area. The process of resampling to a new grid (a core part of reprojection) is inherently sensitive to the input's size and shape.
139
+ - **Dimensions (`width`, `height`)**: The final pixel dimensions are a function of the total bounds and the final resolution. Since the resolution is different in the two methods, the width and height must also be different to cover the same geographic area.
140
+ - **Bounds**: The final bounds are nearly identical in latitude and longitude, which makes sense because both methods represent the same geographic area. Any slight differences are due to rounding and the nuances of resampling.
141
+
142
+ **Conclusion**: The differences are normal and reflect the non-commutative nature of these two geospatial operations. The **reproject then merge** approach is generally preferable as it ensures greater consistency and can be more accurate when dealing with rasters that have slightly different resolutions or alignments, as it creates a single, clean grid before combining the data.
143
+
144
+ ---
145
+
146
+ [Back to Examples](../index.md)
@@ -1,13 +1,29 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: giga-spatial
3
- Version: 0.6.9
3
+ Version: 0.7.1
4
4
  Summary: A package for spatial data download & processing
5
- Home-page: https://github.com/unicef/giga-spatial
6
5
  Author: Utku Can Ozturk
7
6
  Author-email: utkucanozturk@gmail.com
8
7
  License: AGPL-3.0-or-later
8
+ Project-URL: Homepage, https://github.com/unicef/giga-spatial
9
+ Project-URL: Documentation, https://unicef.github.io/giga-spatial/
10
+ Project-URL: Source, https://github.com/unicef/giga-spatial
11
+ Project-URL: Issue Tracker, https://github.com/unicef/giga-spatial/issues
12
+ Project-URL: Discussions, https://github.com/unicef/giga-spatial/discussions
13
+ Project-URL: Changelog, https://unicef.github.io/giga-spatial/changelog
9
14
  Keywords: gigaspatial,spatial,geospatial,gis,remote sensing,data processing,download,openstreetmap,osm,ghsl,grid,point of interest,POI,raster,vector,school connectivity,unicef,giga,mapping,analysis,python
15
+ Classifier: Development Status :: 5 - Production/Stable
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: Intended Audience :: Education
18
+ Classifier: Intended Audience :: Healthcare Industry
19
+ Classifier: Intended Audience :: Science/Research
20
+ Classifier: Intended Audience :: Telecommunications Industry
21
+ Classifier: Programming Language :: Python
10
22
  Classifier: Programming Language :: Python :: 3
23
+ Classifier: Programming Language :: Python :: 3.10
24
+ Classifier: Programming Language :: Python :: 3.11
25
+ Classifier: Programming Language :: Python :: 3.12
26
+ Classifier: Topic :: Scientific/Engineering :: GIS
11
27
  Classifier: License :: OSI Approved :: GNU Affero General Public License v3
12
28
  Classifier: Operating System :: OS Independent
13
29
  Requires-Python: >=3.10
@@ -24,8 +40,9 @@ Requires-Dist: pycountry==24.6.1
24
40
  Requires-Dist: pydantic>=2.10.6
25
41
  Requires-Dist: rasterio==1.3.10
26
42
  Requires-Dist: Requests==2.32.3
27
- Requires-Dist: scipy==1.15.1
43
+ Requires-Dist: scipy>=1.15.1
28
44
  Requires-Dist: Shapely>=2.0.7
45
+ Requires-Dist: networkx>=3.2.1
29
46
  Requires-Dist: tqdm==4.65.0
30
47
  Requires-Dist: OWSLib==0.32.1
31
48
  Requires-Dist: pydantic-settings>=2.7.1
@@ -33,15 +50,16 @@ Requires-Dist: hdx-python-api>=6.3.8
33
50
  Requires-Dist: bs4==0.0.2
34
51
  Requires-Dist: sqlalchemy-trino==0.5.0
35
52
  Requires-Dist: dask>=2024.12.1
53
+ Requires-Dist: h3>=4.2.0
36
54
  Dynamic: author
37
55
  Dynamic: author-email
38
56
  Dynamic: classifier
39
57
  Dynamic: description
40
58
  Dynamic: description-content-type
41
- Dynamic: home-page
42
59
  Dynamic: keywords
43
60
  Dynamic: license
44
61
  Dynamic: license-file
62
+ Dynamic: project-url
45
63
  Dynamic: requires-dist
46
64
  Dynamic: requires-python
47
65
  Dynamic: summary
@@ -53,6 +71,14 @@ Dynamic: summary
53
71
 
54
72
  # GigaSpatial
55
73
 
74
+ [![License: AGPL v3](https://img.shields.io/badge/License-AGPL%20v3-brightgreen.svg)](https://opensource.org/license/agpl-v3)
75
+ [![PyPI version](https://badge.fury.io/py/giga-spatial.svg)](https://badge.fury.io/py/giga-spatial)
76
+ [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/giga-spatial.svg?color=dark-green)](https://pypi.org/project/giga-spatial/)
77
+ [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
78
+ [![PyPI Downloads](https://static.pepy.tech/badge/giga-spatial)](https://pepy.tech/projects/giga-spatial)
79
+ [![GitHub commit activity](https://img.shields.io/github/commit-activity/y/unicef/giga-spatial.svg?color=dark-green)](https://github.com/unicef/giga-spatial/graphs/contributors)
80
+
81
+
56
82
  ## About Giga
57
83
 
58
84
  [Giga](https://giga.global/) is a UNICEF-ITU initiative to connect every school to the Internet and every young person to information, opportunity and choice.
@@ -61,6 +61,7 @@ gigaspatial/generators/zonal/base.py
61
61
  gigaspatial/generators/zonal/geometry.py
62
62
  gigaspatial/generators/zonal/mercator.py
63
63
  gigaspatial/grid/__init__.py
64
+ gigaspatial/grid/h3.py
64
65
  gigaspatial/grid/mercator_tiles.py
65
66
  gigaspatial/handlers/__init__.py
66
67
  gigaspatial/handlers/base.py
@@ -69,6 +70,7 @@ gigaspatial/handlers/ghsl.py
69
70
  gigaspatial/handlers/giga.py
70
71
  gigaspatial/handlers/google_open_buildings.py
71
72
  gigaspatial/handlers/hdx.py
73
+ gigaspatial/handlers/healthsites.py
72
74
  gigaspatial/handlers/mapbox_image.py
73
75
  gigaspatial/handlers/maxar_image.py
74
76
  gigaspatial/handlers/microsoft_global_buildings.py
@@ -9,12 +9,14 @@ pycountry==24.6.1
9
9
  pydantic>=2.10.6
10
10
  rasterio==1.3.10
11
11
  Requests==2.32.3
12
- scipy==1.15.1
12
+ scipy>=1.15.1
13
13
  Shapely>=2.0.7
14
+ networkx>=3.2.1
14
15
  tqdm==4.65.0
15
16
  OWSLib==0.32.1
16
17
  pydantic-settings>=2.7.1
17
18
  hdx-python-api>=6.3.8
18
19
  bs4==0.0.2
19
20
  sqlalchemy-trino==0.5.0
20
- dask>=2024.12.1
21
+ dask>=2024.12.1
22
+ h3>=4.2.0
@@ -0,0 +1 @@
1
+ __version__ = "0.7.1"
@@ -38,6 +38,7 @@ class Config(BaseSettings):
38
38
  GIGA_SCHOOL_MEASUREMENTS_API_KEY: str = Field(
39
39
  default="", alias="GIGA_SCHOOL_MEASUREMENTS_API_KEY"
40
40
  )
41
+ HEALTHSITES_API_KEY: str = Field(default="", alias="HEALTHSITES_API_KEY")
41
42
 
42
43
  ROOT_DATA_DIR: Path = Field(
43
44
  default=Path("."),