I am trying to calculate the minimum cumulative water deficit for a region.

terraclim = (ee.ImageCollection('IDAHO_EPSCOR/TERRACLIMATE')
              .filterDate('1985-01-01', '2019-12-31'))
prec = terraclim.select('pr')

# water deficit here is precipitation - 100mm/month, mean ET value for Amazonia
water_deficit = prec.map(lambda image: image.subtract(100))
monthly_wd_list = water_deficit.toList(water_deficit.size())

resultImage = ee.Image(0)
cwd_list = []

# here we calculate the monthly cumulative water deficit values
for i in range(monthly_wd_list.size().getInfo()):
    # get this month's water deficit value
    currentImage = ee.Image(monthly_wd_list.get(i))
    # add value to last month's water deficit value
    resultImage = resultImage.add(currentImage)
    # if value is positive, it rained enough to compensate for previous drought (zero deficit)
    resultImage = resultImage.where(resultImage.gt(0), 0)
    # otherwise, result is negative, and deficit carries on to coming month
    cwd_list.append(resultImage.set('month', i))

# Determining the lowest cumulative water deficit value of the year
annual_mcwd_list = []
year_count = 1984
for i in range(0, (2020-1985)*12, 12):
    year_count += 1 
    yr = cwd_list[i:i+12]
    cwd_a = ee.ImageCollection.fromImages(yr)
    mcwd_a = cwd_a.reduce(ee.Reducer.min())
    annual_mcwd_list.append(mcwd_a.set('year', year_count))

The images in annual_mcwd_list are generated, but are all empty.

I have tried testing

i = 1
yr = [cwd_list[1], cwd_list[2]]
cwd_a = ee.ImageCollection.fromImages(yr)
mcwd_a = cwd_a.reduce(ee.Reducer.min())

and cwd_a.first() is a real image that maps perfectly, but the reduction mcwd_a appears empty when added to the map. Same outcome when I use .min() instead of .reduce()

  • 1
    You're using a client-side structure for server-side functions. Maybe that's the issue here, even using Python API you should keep in that way. Relevant to read: Client vs Server
    – aldo_tapia
    Dec 29, 2023 at 13:44
  • Thank you, I'm getting more informed about how this works. That seems to be the solution. Dec 29, 2023 at 21:49

1 Answer 1


Try this approach using server-side functions (with code reformatting):

terraclim = (ee.ImageCollection('IDAHO_EPSCOR/TERRACLIMATE')
              .filterDate('1985-01-01', '2019-12-31'))

def get_wd(img):
  result = img.select('pr').subtract(100)
  result = result.where(result.gt(0), 0).rename('wd')
  result = result.copyProperties(img, ['system:time_start'])
  return result

wd_col = terraclim.map(get_wd)

years = ee.List.sequence(1985, 2019)

def get_min_yearly(y):
  return wd_col.filter(ee.Filter.calendarRange(y, y, 'year')).select('wd').min().set('year', y)

min_yearly = ee.ImageCollection.fromImages(years.map(get_min_yearly).flatten())

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.