gee-community / geemap

A Python package for interactive geospatial analysis and visualization with Google Earth Engine.
https://geemap.org
MIT License
3.47k stars 1.09k forks source link

Error exporting image as tif #1847

Closed nlebovits closed 11 months ago

nlebovits commented 11 months ago

Environment Information

OS | Windows | CPU(s) | 20 | Machine | AMD64

Architecture | 64bit | RAM | 63.8 GiB | Environment | Jupyter

Python 3.9.16 (main, Mar 8 2023, 10:39:24) [MSC v.1916 64 bit (AMD64)]

geemap | 0.23.1 | ee | 0.1.357 | ipyleaflet | 0.17.3 folium | 0.14.0 | jupyterlab | 3.6.3 | notebook | 6.5.4 ipyevents | 2.0.1 | geopandas | 0.12.2 |   |  

Intel(R) oneAPI Math Kernel Library Version 2023.1-Product Build 20230303 for Intel(R) 64 architecture applications

Description

I'm trying to export an image to my local machine via ee_export_image(). I followed the code here but am running into an error when downloading. The code runs but breaks after ~2.5s and says "An error occurred while downloading."

Error message here:

---------------------------------------------------------------------------
JSONDecodeError                           Traceback (most recent call last)
File [c:\Users\Nissim\AppData\Local\r-miniconda\envs\geemap\lib\site-packages\requests\models.py:971](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/site-packages/requests/models.py:971), in Response.json(self, **kwargs)
    [970](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/site-packages/requests/models.py:970) try:
--> [971](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/site-packages/requests/models.py:971)     return complexjson.loads(self.text, **kwargs)
    [972](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/site-packages/requests/models.py:972) except JSONDecodeError as e:
    [973](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/site-packages/requests/models.py:973)     # Catch JSON-related errors and raise as requests.JSONDecodeError
    [974](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/site-packages/requests/models.py:974)     # This aliases json.JSONDecodeError and simplejson.JSONDecodeError

File [c:\Users\Nissim\AppData\Local\r-miniconda\envs\geemap\lib\json\__init__.py:346](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/json/__init__.py:346), in loads(s, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, **kw)
    [343](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/json/__init__.py:343) if (cls is None and object_hook is None and
    [344](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/json/__init__.py:344)         parse_int is None and parse_float is None and
    [345](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/json/__init__.py:345)         parse_constant is None and object_pairs_hook is None and not kw):
--> [346](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/json/__init__.py:346)     return _default_decoder.decode(s)
    [347](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/json/__init__.py:347) if cls is None:

File [c:\Users\Nissim\AppData\Local\r-miniconda\envs\geemap\lib\json\decoder.py:337](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/json/decoder.py:337), in JSONDecoder.decode(self, s, _w)
    [333](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/json/decoder.py:333) """Return the Python representation of ``s`` (a ``str`` instance
    [334](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/json/decoder.py:334) containing a JSON document).
    [335](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/json/decoder.py:335) 
    [336](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/json/decoder.py:336) """
--> [337](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/json/decoder.py:337) obj, end = self.raw_decode(s, idx=_w(s, 0).end())
    [338](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/json/decoder.py:338) end = _w(s, end).end()

File [c:\Users\Nissim\AppData\Local\r-miniconda\envs\geemap\lib\json\decoder.py:355](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/json/decoder.py:355), in JSONDecoder.raw_decode(self, s, idx)
    [354](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/json/decoder.py:354) except StopIteration as err:
--> [355](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/json/decoder.py:355)     raise JSONDecodeError("Expecting value", s, err.value) from None
    [356](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/json/decoder.py:356) return obj, end

JSONDecodeError: Expecting value: line 1 column 1 (char 0)

During handling of the above exception, another exception occurred:

JSONDecodeError                           Traceback (most recent call last)
[c:\Users\Nissim\Documents\GitHub\HotspotStoplight\flood_mapping\flood_extents.ipynb](file:///C:/Users/Nissim/Documents/GitHub/HotspotStoplight/flood_mapping/flood_extents.ipynb) Cell 14 line 2
      [1](vscode-notebook-cell:/c%3A/Users/Nissim/Documents/GitHub/HotspotStoplight/flood_mapping/flood_extents.ipynb#X12sZmlsZQ%3D%3D?line=0) filename = 'data/outputs/san_jose_flood_100m_2023_10_05.tif'
----> [2](vscode-notebook-cell:/c%3A/Users/Nissim/Documents/GitHub/HotspotStoplight/flood_mapping/flood_extents.ipynb#X12sZmlsZQ%3D%3D?line=1) geemap.ee_export_image(flooded_100m, filename, scale=scale, crs=crs, region=aoi_geom, file_per_band=False)

File [c:\Users\Nissim\AppData\Local\r-miniconda\envs\geemap\lib\site-packages\geemap\common.py:2374](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/site-packages/geemap/common.py:2374), in ee_export_image(ee_object, filename, scale, crs, crs_transform, region, dimensions, file_per_band, format, unzip, unmask_value, timeout, proxies)
   [2372](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/site-packages/geemap/common.py:2372)     print("An error occurred while downloading.")
   [2373](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/site-packages/geemap/common.py:2373)     if r is not None:
-> [2374](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/site-packages/geemap/common.py:2374)         print(r.json()["error"]["message"])
   [2375](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/site-packages/geemap/common.py:2375)     return
   [2377](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/site-packages/geemap/common.py:2377) try:

File [c:\Users\Nissim\AppData\Local\r-miniconda\envs\geemap\lib\site-packages\requests\models.py:975](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/site-packages/requests/models.py:975), in Response.json(self, **kwargs)
    [971](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/site-packages/requests/models.py:971)     return complexjson.loads(self.text, **kwargs)
    [972](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/site-packages/requests/models.py:972) except JSONDecodeError as e:
    [973](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/site-packages/requests/models.py:973)     # Catch JSON-related errors and raise as requests.JSONDecodeError
    [974](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/site-packages/requests/models.py:974)     # This aliases json.JSONDecodeError and simplejson.JSONDecodeError
--> [975](file:///C:/Users/Nissim/AppData/Local/r-miniconda/envs/geemap/lib/site-packages/requests/models.py:975)     raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)

JSONDecodeError: Expecting value: line 1 column 1 (char 0)

What I Did

Here's my best attempt at a reprex:

import os
import json
import ee
import geemap
from geemap import geojson_to_ee, ee_to_geojson
from ipyleaflet import GeoJSON

file_path = os.path.abspath("data/resourceshedbb_CostaRica_SanJose.geojson")

with open(file_path) as f:
    json_data = json.load(f)

bbox_geojson = geojson_to_ee(json_data) # need as a feature collection, not bounding box
aoi = bbox_geojson
aoi_geom = aoi.geometry().bounds()

## set time frame
before_start= '2023-09-25'
before_end='2023-10-05'

after_start='2023-10-05'
after_end='2023-10-15'

# SET SAR PARAMETERS (can be left default)
polarization = "VH"  # or "VV"
pass_direction = "DESCENDING"  # or "ASCENDING"
difference_threshold = 1.25

# Load and filter Sentinel-1 GRD data by predefined parameters
collection = ee.ImageCollection('COPERNICUS/S1_GRD') \
    .filter(ee.Filter.eq('instrumentMode', 'IW')) \
    .filter(ee.Filter.listContains('transmitterReceiverPolarisation', polarization)) \
    .filter(ee.Filter.eq('orbitProperties_pass', pass_direction)) \
    .filter(ee.Filter.eq('resolution_meters', 10)) \
    .filterBounds(aoi) \
    .select(polarization)

# Select images by predefined dates
before_collection = collection.filterDate(before_start, before_end)
after_collection = collection.filterDate(after_start, after_end)

# Create a mosaic of selected tiles and clip to the study area
before = before_collection.mosaic().clip(aoi)
after = after_collection.mosaic().clip(aoi)

# Apply radar speckle reduction by smoothing
smoothing_radius = 50
before_filtered = before.focal_mean(smoothing_radius, 'circle', 'meters')
after_filtered = after.focal_mean(smoothing_radius, 'circle', 'meters')

# Calculate the difference between the before and after images
difference = after_filtered.divide(before_filtered)

# Apply the predefined difference-threshold and create the flood extent mask
threshold = difference_threshold
difference_binary = difference.gt(threshold)

# Refine the flood result using additional datasets
swater = ee.Image('JRC/GSW1_0/GlobalSurfaceWater').select('seasonality')
swater_mask = swater.gte(10).updateMask(swater.gte(10))
flooded_mask = difference_binary.where(swater_mask, 0)
flooded = flooded_mask.updateMask(flooded_mask)
connections = flooded.connectedPixelCount()
flooded = flooded.updateMask(connections.gte(8))

# Mask out areas with more than 5 percent slope using a Digital Elevation Model
DEM = ee.Image('WWF/HydroSHEDS/03VFDEM')
terrain = ee.Algorithms.Terrain(DEM)
slope = terrain.select('slope')
flooded = flooded.updateMask(slope.lt(5))

flooded = flooded.setDefaultProjection(crs=crs, scale=scale)

crs = flooded.projection().crs()
scale = 100 # 100m resolution

def reduce_resolution(image, reducer, scale):
    return image.reduceResolution(reducer=reducer, maxPixels=1024) \
                .reproject(crs=crs, scale=scale)

flooded_100m = reduce_resolution(flooded, ee.Reducer.mode(), scale)

filename = 'data/outputs/san_jose_flood_100m_2023_10_05.tif'
geemap.ee_export_image(flooded_100m, filename, scale=scale, crs=crs, region=aoi_geom, file_per_band=False)
nlebovits commented 11 months ago

I'm an idiot--the subdirectory just didn't exist.