Google Earth Engine – Generating MODIS LST Time Series for Daily Averaging Using Javascript

google-earth-enginejavascriptland-surface-temperatureremote sensingtime series

I am trying to compute and plot the linear regression model for MODIS terra LST values. I have successfully plotted the "LST_Day_1km" band by using the following code:

var terraD = ee.ImageCollection('MODIS/061/MOD11A1')
  .filterDate('2020-01-01', '2020-06-01').select('LST_Day_1km')
  .filterBounds(geometry);

var terraN = ee.ImageCollection('MODIS/061/MOD11A1')
  .filterDate('2020-01-01', '2020-06-01').select('LST_Night_1km')
  .filterBounds(geometry);
  
//Set scene for map
Map.centerObject(geometry, 11);

//Add Buffer
var region = geometry.buffer(10000);
Map.addLayer(region, {color: "yellow"}, "Region");

//declare global time variable
var timefield = 'system:time_start'

//convert to degree celcius
var celcius =  terraD.map(function(image){
    return image.multiply(0.02)
    .subtract(273.15)
    .copyProperties(image, ['system:time_start'])
})


//Add variables for time series
var ND =  celcius.map(function(image){
    // Compute time in fractional years since the epoch.
  var date = ee.Date(image.get(timefield));
  var years = date.difference(ee.Date('1970-01-01'), 'year');//
  return image
    // Add a time band(Independant variable)
    .addBands(ee.Image(years).rename('t').float())
    //add a constant band (Independant Variable)
    .addBands(ee.Image.constant(1).rename('constant'))
})

//Linear Trend//==================

//independant variable names
var independants = ee.List(['constant', 't'])

//dependant variable name 
var dependant = ee.String('LST_Day_1km')

//Compute the betas using linear regression reducer.
var trend = ND.select(independants.add(dependant))
    .reduce(ee.Reducer.linearRegression(independants.length(), 1)) 
   
var coefficients = trend.select('coefficients')
    .arrayProject([0])
    .arrayFlatten([independants]);//naming the output bands the same name as variables
    
var LinearFitted = ND.map(function(image){
  return image.addBands(
    image.select(independants)
      .multiply(coefficients)
      .reduce('sum')
      .rename('Linearfitted'))
})    

// Plot the fitted model and the original data at the ROI.
print(ui.Chart.image.series(
  LinearFitted.select(['Linearfitted','LST_Day_1km']), region, ee.Reducer.mean(), 30)
    .setSeriesNames(['fitted', 'LST'])
    .setOptions({
      title: 'Linear Model: original and fitted values',
      lineWidth: 1,
      pointSize: 3,
}));

Now instead of day-time LST, I want to include the LST_Night_1km band as well to create a time series of mean daily temperature. What would be the best way to proceed? Is there any way of perhaps creating an image collection with the mean of terraD and terraN and then using the "mean" band as the dependent variable?

Best Answer

For this specific image collection, it is straightforward to compute the daily mean, if what you want is the mean between LST_Day and LST_Night. This is because both of them are bands in the original images, and thus have the same system:time_start and system:time_end. To obtain the mean between all bands in one image, you can use .reduce(ee.Reducer.mean()):

var terra = ee.ImageCollection('MODIS/061/MOD11A1')
  .filterDate('2020-01-01', '2020-06-01')
  .filterBounds(geometry)
  .select(['LST_Day_1km','LST_Night_1km'])
  .map(function(img){
    return img.reduce(ee.Reducer.mean())
    .set({"system:time_start":img.get("system:time_start")})
  })

The above will be result in an image collection with one band named "mean". If you rename it to "LST_Day_1km" and change the name of the variable to terraD then you can test the rest of your code without changing anything else. You can try it out here: https://code.earthengine.google.com/d9ccba323c9459e627516e50d33c4b74

One caveat is that the mask for LST_Day_1km and LST_Night_1km might be different, so it is up to you what to do when one value is masked but not the other. Currently, if one of them is masked but not the other, the mean returns you the value of the valid pixel only.

Related Question