Google Earth Engine – How to Grow Number of Images in an Image Collection in Google Earth Engine

google-earth-engine

I want to calculate hourly temperatures from daily temperatures based on formulas I have from Goudrian and Laar. My daily temperatures come from the Image Collection for Daymet.

// Raster of boundary of lower U.S. 48
var us = ee.Image("users/japolo/us_bounds");

var usbound = us.geometry();

// Set up Daymet collection from 2009 to 2020
var daymetb = ee.ImageCollection("NASA/ORNL/DAYMET_V4")
.filterDate('2009-01-01', '2020-12-31')
.map(function(im){return im.clip(usbound)});

// Set a threshold of temps for use in a later calculation
var threshold = function(im) {
  return im.where(im.lt(-5.0), -5)
};

// Get mean temp. over collection
var daymean = daymet.map(function (image) {
  var dayx = image.select('tmax')
  var dayn = image.select('tmin')
  // Apply threshold
  var dayxt = threshold(dayx)
  var daynt = threshold(dayn)
  // Calculate mean temp.
  return daynt.add(dayxt).divide(2)
})

This Image Collection has daily means for 12 years: 4380 Images. I don't know what the function is to do what I want. I'm still learning to use GEE and have no background in JavaScript, but I know that GEE has the .reduce function when one wants to go from, say daily to weekly values, but I want to go in the reverse direction. I think that I may need to map() something over the Image Collection, but I have no idea what kind of function will increase the number of Image, especially in a way that uses time to go from 1 day to 24 hours.

For example, if I have a 7 images in an Image Collection, say 2020-01-08 to 2020-01-14, to start, I want to finish with 168 images, where every 24 images are the seven 24 hours periods for 8 Jan. through 14 Jan.

This is the code I have for the hourly temperatures. I added this after the comment from xunilk. It doesn't create Images, it assigns values to Images, so it won't help me with expanding the Image Collection.

var daylen_cal = function(image) {
    // Constants
    var pi = 3.141593
    var rad = pi/180
    // Latitude of pixel
    var imla = ee.Image.pixelLonLat().select('latitude');
    // Date --- THIS COULD CHANGE FOR ImageCollection vs. Image
    //var imgda = ee.Date(image);
    var magda = ee.ImageCollection(image).toList(3);
    var imgda = ee.Image(ee.List(magda).get(0));
    var imgd2 = imgda.date();
    print(imgd2)
    // Day of year
    var doy = imgd2.getRelative('day', 'year').add(1);
    // Sine of latitude
    var latsn = imla.multiply(rad).sin();
    // Cosine of latitude
    var latcs = imla.multiply(rad).cos();
    // Max of sine of declination
    var xsindecl = ee.Number(rad).multiply(23.45).sin();
    // Sine of declination
    var sndl1 = doy.add(10).divide(365).multiply(pi).multiply(2).cos()
    var sindecl = xsindecl.multiply(-1).multiply(sndl1)
    // Cosine of declination
    var cosf = function(image) {
        return ee.Image().expression(
          '(1 - im * im)**0.5', {
          'im' : sindecl
      })
    };
    var cosdecl = cosf();
    // Parts for the day length equation
    var p_a = latsn.multiply(sindecl);
    var p_b = latcs.multiply(cosdecl);
    var p_c = p_a.divide(p_b);
    // Daylength equation
    var dayeq = function(image) {
      return ee.Image().expression(
        '12 * (1 + (2 / pi) * atan(im / (im*im+1)**0.5))', {
        'pi' : pi,
        'im' : p_c
      })
    };
    var daylen = dayeq();
    return ee.Image(daylen)
}

EDIT #2: I wonder if I can add the additional layers as bands? I don't know what the different is between an Image and a band in GEE. I see there is the .addBands function, so I tried this, but it doesn't work, mostly because I don't know how to iterate the addBands part. I know GEE doesn't like for loops, but I have not idea how to approach this otherwise.

var usbounds = ee.Image("users/japolo/us_bounds"),
    dec0112 = ee.Image("users/japolo/time_raster_2012_01_01");
    
var us = usbounds.geometry();

var dec0112 = dec0112.clip(us);

//1 hr = 3600000 ms; 8760 steps in one year

var startdate = ee.Date('2009-01-01T00:00:00').millis();

var timelist = ee.List.sequence(1230768000000, null, 3600000, 8760)

var n = timelist.size().getInfo();

for (var i = 0; i < n; i++) {
  print(timelist.get(i));
  var col2 = dec0112.addBands(dec0112);
}

Best Answer

I tried using the code in this answer. It seems close, but I didn't know how to use it with the list of dates I made.

As a matter of luck, I was searching for something else related to this work and came across this answer. I modified the code a little and this is the code that creates an Image Collection with a specified number of Images.

var usbounds = ee.Image("users/japolo/us_bounds"),
    dec0112 = ee.Image("users/japolo/time_raster_2012_01_01");
    
var us = usbounds.geometry();

// My starting image
var dec0112 = dec0112.clip(us);

//1 hr = 3600000 ms; 8760 steps in one year; ~720 / month

var startdate = ee.Date('2009-01-01T00:00:00').millis();

var timelist = ee.List.sequence(1230768000000, null, 3600000, 8760)

var Date_Start = ee.Date('2009-01-01T00:00:00');
// Wanted a year's worth. The ImageCollection in last step won't create more
// than 5000 Images, so I cut back.
var Date_End = ee.Date('2009-06-30T23:00:00');
// Was originally 8760
var num_in_interval = 4343;

// Create list of dates for time series
var n_units = Date_End.difference(Date_Start,'hour').round();
var dates = ee.List.sequence(0, n_units, null, num_in_interval);
var make_datelist = function(n) {
  return Date_Start.advance(n,'hour');
};
var dates = dates.map(make_datelist);

var addmoreims = function(image) {
  return ee.Image(dec0112);
};

var CreateCol = function(d1) {
  var start = ee.Date(d1);
  var end = ee.Date(d1).advance(num_in_interval, 'hour');
  var name = start.format('YYYY-MM-dd H:00:ss');
  var intCol = ee.ImageCollection(dec0112)
    .map(addmoreims)
    .toList(2);
  // Change the ImageCollection to an Image
  // otherwise, the list created will be a list 
  // of ImageCollections and that can't be 
  // turned into an ImageCollection
  return ee.Image(ee.List(intCol).get(0)).set({name: name});
};

// A list of images that has the length I need
var list_of_images = dates.map(CreateCol);

// Create an ImageCollection from the list I made in previous step
var ims_l = ee.ImageCollection(list_of_images);

I reused my starting image each time, but I don't think that will be a problem, since this is supposed to be a skeleton for other code that I hope will assign the new values I intend to use.

Related Question