SnowMapPy 0.0.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Haytam Elyoussfi, Hatim Bechri, Mostafa Bousbaa
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,24 @@
1
+ # Include essential files
2
+ include LICENSE
3
+ include README.md
4
+ include requirements.txt
5
+ include pyproject.toml
6
+
7
+ # Include all Python source files
8
+ recursive-include SnowMapPy *.py
9
+
10
+ # Exclude compiled files and caches
11
+ global-exclude __pycache__
12
+ global-exclude *.py[cod]
13
+ global-exclude *.so
14
+ global-exclude *.nbc
15
+ global-exclude *.nbi
16
+
17
+ # Exclude Jupyter notebooks
18
+ global-exclude *.ipynb
19
+
20
+ # Exclude test data
21
+ global-exclude *.zarr
22
+ global-exclude *.nc
23
+ global-exclude *.tif
24
+ global-exclude *.shp
@@ -0,0 +1,441 @@
1
+ Metadata-Version: 2.4
2
+ Name: SnowMapPy
3
+ Version: 0.0.1
4
+ Summary: MODIS NDSI snow cover processing for Google Earth Engine
5
+ Author-email: Haytam Elyoussfi <haytam.elyoussfi@um6p.ma>, Hatim BECHRI <hatim.bechri@uqtr.ca>, Mostafa Bousbaa <Mostafa.bousbaa@um6p.ma>
6
+ Maintainer-email: Haytam Elyoussfi <haytam.elyoussfi@um6p.ma>
7
+ License-Expression: MIT
8
+ Project-URL: Homepage, https://github.com/haytamelyo/SnowMapPy
9
+ Project-URL: Bug Reports, https://github.com/haytamelyo/SnowMapPy/issues
10
+ Project-URL: Source, https://github.com/haytamelyo/SnowMapPy
11
+ Project-URL: Documentation, https://github.com/haytamelyo/SnowMapPy#readme
12
+ Keywords: modis,ndsi,snow-cover,remote-sensing,earth-engine,gis,hydrology,gap-filling,terra,aqua,cryosphere
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Scientific/Engineering :: GIS
21
+ Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
22
+ Classifier: Topic :: Scientific/Engineering :: Hydrology
23
+ Requires-Python: >=3.11
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: numpy<3.0.0,>=1.24.0
27
+ Requires-Dist: scipy<2.0.0,>=1.10.0
28
+ Requires-Dist: pandas<3.0.0,>=2.0.0
29
+ Requires-Dist: numba<1.0.0,>=0.58.0
30
+ Requires-Dist: xarray>=2024.1.0
31
+ Requires-Dist: dask[array]>=2024.1.0
32
+ Requires-Dist: rasterio<2.0.0,>=1.3.0
33
+ Requires-Dist: rioxarray>=0.15.0
34
+ Requires-Dist: geopandas<2.0.0,>=0.14.0
35
+ Requires-Dist: pyproj<4.0.0,>=3.6.0
36
+ Requires-Dist: shapely<3.0.0,>=2.0.0
37
+ Requires-Dist: earthengine-api>=0.1.380
38
+ Requires-Dist: geemap>=0.32.0
39
+ Requires-Dist: xee>=0.0.15
40
+ Requires-Dist: zarr<4.0.0,>=2.16.0
41
+ Requires-Dist: numcodecs<1.0.0,>=0.12.0
42
+ Requires-Dist: tqdm>=4.66.0
43
+ Requires-Dist: affine>=2.4.0
44
+ Requires-Dist: questionary>=2.0.0
45
+ Provides-Extra: dev
46
+ Requires-Dist: pytest>=6.0; extra == "dev"
47
+ Requires-Dist: flake8>=3.8; extra == "dev"
48
+ Requires-Dist: black>=21.0; extra == "dev"
49
+ Requires-Dist: matplotlib>=3.5.0; extra == "dev"
50
+ Dynamic: license-file
51
+
52
+ # SnowMapPy
53
+
54
+ [![PyPI version](https://badge.fury.io/py/SnowMapPy.svg)](https://pypi.org/project/SnowMapPy/)
55
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
56
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
57
+
58
+ A high-performance Python package for processing MODIS NDSI (Normalized Difference Snow Index) snow cover data from Google Earth Engine. SnowMapPy implements a scientifically validated 6-day moving window gap-filling algorithm for accurate Snow Cover Area (SCA) estimation.
59
+
60
+ ---
61
+
62
+ ## Table of Contents
63
+
64
+ - [Features](#features)
65
+ - [Installation](#installation)
66
+ - [Quick Start](#quick-start)
67
+ - [Command-Line Interface](#command-line-interface)
68
+ - [Algorithm](#algorithm)
69
+ - [Technical Specifications](#technical-specifications)
70
+ - [API Reference](#api-reference)
71
+ - [Configuration](#configuration)
72
+ - [Troubleshooting](#troubleshooting)
73
+ - [Citation](#citation)
74
+ - [License](#license)
75
+
76
+ ---
77
+
78
+ ## Features
79
+
80
+ | Feature | Description |
81
+ |---------|-------------|
82
+ | **Cloud Processing** | Direct integration with Google Earth Engine for MODIS data access |
83
+ | **Sensor Fusion** | Combines Terra (MOD10A1) and Aqua (MYD10A1) observations |
84
+ | **Gap-Filling** | 6-day moving window with quality-controlled interpolation |
85
+ | **Elevation Correction** | DEM-based snow detection for high-altitude gaps (>1000m) |
86
+ | **Memory Efficient** | Dask lazy loading with server-side GEE reprojection |
87
+ | **Optimized Storage** | Zarr format with ZSTD compression (level 3) |
88
+ | **Float16 Output** | 50% memory reduction while preserving NDSI precision |
89
+ | **Interactive CLI** | User-friendly command-line interface with guided prompts |
90
+ | **Progress Tracking** | Real-time progress bar during time series processing |
91
+
92
+ ---
93
+
94
+ ## Installation
95
+
96
+ ### Requirements
97
+
98
+ - **Python**: 3.11 or higher
99
+ - **Memory**: 8 GB RAM minimum (16 GB recommended for large regions)
100
+ - **Internet**: Required for Google Earth Engine data access
101
+
102
+ ### Install from PyPI
103
+
104
+ ```bash
105
+ pip install SnowMapPy
106
+ ```
107
+
108
+ ### Install from Source
109
+
110
+ ```bash
111
+ git clone https://github.com/haytamelyo/SnowMapPy.git
112
+ cd SnowMapPy
113
+ pip install -e .
114
+ ```
115
+
116
+ ### Google Earth Engine Setup
117
+
118
+ 1. **Create a GEE account** at [earthengine.google.com](https://earthengine.google.com/)
119
+
120
+ 2. **Create a Cloud Project** in [Google Cloud Console](https://console.cloud.google.com/)
121
+
122
+ 3. **Authenticate**:
123
+ ```bash
124
+ earthengine authenticate
125
+ ```
126
+
127
+ 4. **Verify**:
128
+ ```python
129
+ import ee
130
+ ee.Initialize(project='your-project-name')
131
+ print("Authentication successful")
132
+ ```
133
+
134
+ ---
135
+
136
+ ## Quick Start
137
+
138
+ ### Python API
139
+
140
+ ```python
141
+ from SnowMapPy import process_modis_ndsi_cloud
142
+
143
+ result, counters = process_modis_ndsi_cloud(
144
+ project_name="your-gee-project",
145
+ shapefile_path="study_area.shp",
146
+ start_date="2020-01-01",
147
+ end_date="2020-12-31",
148
+ output_path="./output",
149
+ crs="EPSG:32629", # Target CRS (server-side reprojection)
150
+ interpolation_method="nearest", # Options: nearest, linear, cubic
151
+ spatial_correction_method="elevation_mean", # Options: elevation_mean, neighbor_based, none
152
+ save_pixel_counters=True # Save gap-filling statistics
153
+ )
154
+
155
+ print(f"Processed {len(result.time)} days")
156
+ ```
157
+
158
+ ### Output Structure
159
+
160
+ ```
161
+ output/
162
+ ├── study_area_NDSI.zarr/ # Gap-filled NDSI time series
163
+ │ ├── NDSI_Snow_Cover/ # Values 0-100 (float16)
164
+ │ ├── lat/ # Coordinates
165
+ │ ├── lon/
166
+ │ └── time/
167
+ ├── study_area_NDSI_pixel_counters.csv # Gap-filling statistics
168
+ ├── MOD.zarr/ # Original Terra data (optional)
169
+ ├── MYD.zarr/ # Original Aqua data (optional)
170
+ └── DEM.zarr/ # Elevation data (optional)
171
+ ```
172
+
173
+ ---
174
+
175
+ ## Command-Line Interface
176
+
177
+ ### Interactive Mode
178
+
179
+ ```bash
180
+ snowmappy
181
+ ```
182
+
183
+ The wizard guides you through all configuration options.
184
+
185
+ ### Command-Line Arguments
186
+
187
+ ```bash
188
+ snowmappy \
189
+ -p your-gee-project \
190
+ -s study_area.shp \
191
+ --start 2020-01-01 \
192
+ --end 2020-12-31 \
193
+ -o ./output
194
+ ```
195
+
196
+ | Option | Description | Default |
197
+ |--------|-------------|---------|
198
+ | `-p, --project` | GEE project name | Required |
199
+ | `-s, --shapefile` | Study area shapefile | Required |
200
+ | `--start` | Start date (YYYY-MM-DD) | Required |
201
+ | `--end` | End date (YYYY-MM-DD) | Required |
202
+ | `-o, --output` | Output directory | Required |
203
+ | `-n, --name` | Output filename | `<shapefile>_NDSI` |
204
+ | `-i, --interpolation` | Interpolation method | `nearest` |
205
+ | `--spatial-correction` | Spatial correction method | `elevation_mean` |
206
+ | `--crs` | Coordinate reference system | `EPSG:4326` |
207
+ | `--save-counters` | Save pixel counters | `False` |
208
+
209
+ ---
210
+
211
+ ## Algorithm
212
+
213
+ ### 6-Day Moving Window
214
+
215
+ SnowMapPy processes each day using a 6-day temporal window:
216
+
217
+ ```
218
+ Day Index: -3 -2 -1 0 +1 +2
219
+ ├─────┼─────┼─────┼─────┼─────┤
220
+ │ 3 days before │ 2 days after │
221
+ Current Day
222
+ ```
223
+
224
+ The window configuration (3 days before + current + 2 days after) optimizes temporal coverage while preserving computational efficiency.
225
+
226
+ ### Processing Pipeline
227
+
228
+ ```
229
+ Terra MOD10A1 ──┐
230
+ ├──► Quality Control ──► Sensor Fusion ──► 6-Day Window
231
+ Aqua MYD10A1 ───┘ │
232
+
233
+ SRTM DEM ────────────────────────────► Spatial Correction
234
+
235
+
236
+ Temporal Interpolation
237
+
238
+
239
+ Zarr Output
240
+ ```
241
+
242
+ ### Quality Control
243
+
244
+ Invalid MODIS classes are masked before processing:
245
+
246
+ | Class | Description | Action |
247
+ |-------|-------------|--------|
248
+ | 50 | Cloud | Masked |
249
+ | 37 | Lake ice | Masked |
250
+ | 39 | Inland water | Masked |
251
+ | 255 | Ocean/Fill | Masked |
252
+
253
+ ### Spatial Correction Methods
254
+
255
+ | Method | Description |
256
+ |--------|-------------|
257
+ | `elevation_mean` | Fill gaps above mean snow elevation with NDSI=100 (recommended) |
258
+ | `neighbor_based` | Fill based on snow presence in surrounding pixels above 1000m |
259
+ | `none` | No spatial correction |
260
+
261
+ ### Interpolation Methods
262
+
263
+ | Method | Speed | Description |
264
+ |--------|-------|-------------|
265
+ | `nearest` | Fastest | Forward/backward fill (preserves extremes) |
266
+ | `linear` | Medium | Linear interpolation between valid observations |
267
+ | `cubic` | Slower | Cubic spline (smoothest transitions) |
268
+
269
+ ---
270
+
271
+ ## Technical Specifications
272
+
273
+ ### Storage Format
274
+
275
+ SnowMapPy uses **Zarr v3** with **ZSTD compression** (level 3) for optimal storage:
276
+
277
+ - Chunked storage for efficient partial reads
278
+ - ZSTD provides ~60% compression ratio with fast decompression
279
+ - Cloud-optimized format compatible with Dask parallel computing
280
+
281
+ ### Memory Optimization
282
+
283
+ | Technique | Benefit |
284
+ |-----------|---------|
285
+ | Server-side reprojection | Eliminates ~10GB local memory allocation |
286
+ | Dask lazy loading | Only 6-day window materialized in RAM |
287
+ | Float16 output | 50% memory reduction (sufficient for NDSI 0-100 range) |
288
+ | Streaming to Zarr | Original data saved without full materialization |
289
+
290
+ ### Data Types
291
+
292
+ Output uses `float16` by default:
293
+ - Preserves NaN values for missing data
294
+ - Sufficient precision for NDSI range (0-100)
295
+ - 50% smaller than float32, 75% smaller than float64
296
+
297
+ ---
298
+
299
+ ## API Reference
300
+
301
+ ### `process_modis_ndsi_cloud`
302
+
303
+ Main processing function for MODIS NDSI data.
304
+
305
+ ```python
306
+ def process_modis_ndsi_cloud(
307
+ project_name: str,
308
+ shapefile_path: str,
309
+ start_date: str,
310
+ end_date: str,
311
+ output_path: str,
312
+ file_name: Optional[str] = None,
313
+ crs: str = "EPSG:4326",
314
+ save_original_data: bool = False,
315
+ interpolation_method: str = "nearest",
316
+ spatial_correction_method: str = "elevation_mean",
317
+ save_pixel_counters: bool = False,
318
+ verbose: bool = True,
319
+ output_dtype: str = "float16"
320
+ ) -> Tuple[xr.Dataset, dict]
321
+ ```
322
+
323
+ **Parameters:**
324
+
325
+ | Parameter | Type | Description |
326
+ |-----------|------|-------------|
327
+ | `project_name` | str | GEE project name |
328
+ | `shapefile_path` | str | Path to study area shapefile |
329
+ | `start_date` | str | Start date (YYYY-MM-DD) |
330
+ | `end_date` | str | End date (YYYY-MM-DD) |
331
+ | `output_path` | str | Output directory |
332
+ | `file_name` | str | Output filename (default: `<shapefile>_NDSI`) |
333
+ | `crs` | str | Target CRS (default: EPSG:4326) |
334
+ | `save_original_data` | bool | Save Terra/Aqua/DEM data |
335
+ | `interpolation_method` | str | `nearest`, `linear`, or `cubic` |
336
+ | `spatial_correction_method` | str | `elevation_mean`, `neighbor_based`, or `none` |
337
+ | `save_pixel_counters` | bool | Save statistics to CSV |
338
+ | `output_dtype` | str | `float16`, `float32`, or `float64` |
339
+
340
+ **Returns:** Tuple of (xr.Dataset, dict) containing processed data and counters.
341
+
342
+ ---
343
+
344
+ ## Configuration
345
+
346
+ ### Date Range
347
+
348
+ MODIS data availability:
349
+ - **Terra**: February 24, 2000 - present
350
+ - **Aqua**: July 4, 2002 - present
351
+
352
+ Dates outside availability are automatically adjusted.
353
+
354
+ ### Performance Recommendations
355
+
356
+ For large study areas, process in yearly segments:
357
+
358
+ ```python
359
+ for year in range(2010, 2021):
360
+ process_modis_ndsi_cloud(
361
+ project_name="your-project",
362
+ shapefile_path="large_area.shp",
363
+ start_date=f"{year}-01-01",
364
+ end_date=f"{year}-12-31",
365
+ output_path=f"./output/{year}"
366
+ )
367
+ ```
368
+
369
+ ---
370
+
371
+ ## Troubleshooting
372
+
373
+ ### Authentication Error
374
+
375
+ ```bash
376
+ # Re-authenticate with GEE
377
+ earthengine authenticate
378
+ ```
379
+
380
+ ### Memory Issues
381
+
382
+ - Process smaller time ranges (monthly instead of yearly)
383
+ - Reduce study area extent
384
+ - The package automatically uses memory-efficient processing
385
+
386
+ ### Slow Downloads
387
+
388
+ Data download time scales with:
389
+ - Study area size
390
+ - Time range length
391
+ - GEE server load
392
+
393
+ ### CRS Issues
394
+
395
+ Ensure shapefile has valid CRS:
396
+
397
+ ```python
398
+ import geopandas as gpd
399
+ gdf = gpd.read_file("input.shp")
400
+ gdf = gdf.to_crs("EPSG:4326")
401
+ gdf.to_file("output.shp")
402
+ ```
403
+
404
+ ---
405
+
406
+ ## Citation
407
+
408
+ ```bibtex
409
+ @software{snowmappy2025,
410
+ author = {Elyoussfi, Haytam and Bechri, Hatim and Bousbaa, Mostafa},
411
+ title = {SnowMapPy: MODIS Snow Cover Processing for Google Earth Engine},
412
+ year = {2025},
413
+ version = {0.0.1},
414
+ publisher = {GitHub},
415
+ url = {https://github.com/haytamelyo/SnowMapPy}
416
+ }
417
+ ```
418
+
419
+ ### Related Publication
420
+
421
+ Bousbaa, M., et al. (2024). An accurate snow cover product for the Moroccan Atlas Mountains. *International Journal of Applied Earth Observation and Geoinformation*, 129, 103851. https://doi.org/10.1016/j.jag.2024.103851
422
+
423
+ ---
424
+
425
+ ## License
426
+
427
+ MIT License - see [LICENSE](LICENSE) for details.
428
+
429
+ ---
430
+
431
+ ## Authors
432
+
433
+ - **Haytam Elyoussfi** - Lead Developer - [haytam.elyoussfi@um6p.ma](mailto:haytam.elyoussfi@um6p.ma)
434
+ - **Hatim Bechri** - [hatim.bechri@uqtr.ca](mailto:hatim.bechri@uqtr.ca)
435
+ - **Mostafa Bousbaa** - [Mostafa.bousbaa@um6p.ma](mailto:Mostafa.bousbaa@um6p.ma)
436
+
437
+ ---
438
+
439
+ <p align="center">
440
+ <strong>SnowMapPy - Precision Snow Cover Mapping</strong>
441
+ </p>