2

I want to do two things.

First, I want to map the number of nights that have temperatures below 0 in one year. This code seems to do this.

Second, I want to calculate the number of days between the first and last nights with sub-zero temps. I managed to get the first one in the series but the output is a format I don't know: 994118400000.

How can I get the last night the series and measure the span of time between the first and last dates in the series?

var NightSA = ee.ImageCollection('MODIS/006/MOD11A1').select('LST_Night_1km');

var count2001 = NightSA.filterDate('2001-07-01','2002-06-30').map(function(NightSA)
{return NightSA.lt(0).set('system:time_start',
NightSA.get('system:time_start'))});

var first2001 = count2001.first().get('system:time_start');
print (first2001);


var nightSurfaceTempVis = {
  min: 0,
  max: 365,
  palette: [
    '040274', '040281', '0502a3', '0502b8', '0502ce', '0502e6',
    '0602ff', '235cb1', '307ef3', '269db1', '30c8e2', '32d3ef',
    '3be285', '3ff38f', '86e26f', '3ae237', 'b5e22e', 'd6e21f',
    'fff705', 'ffd611', 'ffb613', 'ff8b13', 'ff6e08', 'ff500d',
    'ff0000', 'de0101', 'c21301', 'a71001', '911003'
  ],
};

Map.addLayer(count2001.count(),nightSurfaceTempVis,'Nights < 0');

2 Answers 2

3

As you want to calculate the number of days between the first and last day where the temperature dropped below zero, you will have to change the scaled Kelvin values first to temperature in degrees. In this post I came across a definition for that:

// map over the image collection and use server side functions
var tempToDegrees = NightSA.map(function(image){
  var props = image.toDictionary(image.propertyNames());
    return ee.Image(image.multiply(0.02).subtract(273.15).setMulti(props));
});

We will then have to add a time band, which we get from the system:time_start property of each image. Keep in mind the date image band is in milliseconds.

// Add a time band to the image
var withTimeBand = tempToDegrees.map(function(image){
  var dateMillis = ee.Image(ee.Number(image.get('system:time_start'))).toInt64();
  return image.addBands(dateMillis.rename('dateMillis'));
});

We now assume that the length of a frost period in a year (which should be defined from summer to summer) is from the first night with temperature below 0 till the last day. In your case (where you defined the filterDate), we are thus specifically looking at the northern hemisphere.

// Mask all values above 0 degrees
var masked  = withTimeBand.map(function(image){
  return image.updateMask(image.select('LST_Night_1km').lt(0));
});

We will now reduce the full image collection based on the non-masked pixels which are still present. That should give as the date in millisecond of the start and end of the frost period. We can convert that milliseconds into days by dividing it by 1000 and 86400. We then end up with an image with days from the start till the end frost day.

// Get the min and max date accros the image which has a valid input (non-masked by lt(0))
var minDates = masked.select('dateMillis').min();
var maxDates = masked.select('dateMillis').max();
var diff = maxDates.subtract(minDates); // in millis
var diffDays = diff.divide(1000).divide(86400);

In the link to the full script I added some point information graphs and pixel information so you can check that the method works well. Note that due to the filter date from July till July, this works ONLY for the Northern Hemisphere.

Also note that the result might not actually return 365 days for a year full of frost days, as there are simply not valid pixels at every location inside the image collection input.

Link script

2

first2001 is in milliseconds since 1970-01-01T00:00:00Z

to turn that back into a date that you will be able to understand, just make this change.

var first2001 = ee.Date(count2001.first().get('system:time_start'));

// sort the collection in descending to find the last
var last2001 = ee.Date(count2001.sort('system:time_start',false).first().get('system:time_start'));


print("difference in days", last2001.difference(first2001,"day"))
4
  • This is helpful but the result is 361 days – what I'm expecting is a few months between spring and fall. Could this be because ee.Date is checking all images in the collection all over the world? (I don't seem to be able to map the difference variable). Maybe we need an iterative command? What I want is a map with pixel values for the differences in days – for that pixel only. I'm looking for spatial differences in this difference in days.
    – Erik Marsh
    Commented Mar 1, 2019 at 20:43
  • You are getting the extra day because the time distance between the first image and the last image geographically is 24 hours. (hence the extra day.). If you filter to a bounds (like a city, or a state) this should not be an issue. It is unclear to me what you are trying to achieve beyond that. Commented Mar 2, 2019 at 12:01
  • No problem with the 361. What I want is a map of the number of frost-free days, like this one: charcoal.cnre.vt.edu/climate/current/allNA/derivedGrids/ffp.png
    – Erik Marsh
    Commented Mar 2, 2019 at 14:23
  • This answer does not answer the actual question
    – Kuik
    Commented Mar 19, 2019 at 18:23

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.