parevalo / gee-ccdc-tools

Tools and Earth Engine apps to interact with the outputs from the CCDC algorithm

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

LC Mapping: Image (Error) Image.select: Pattern 'numObs' did not match any bands.

ericacinerea opened this issue · comments

Hi CCDC Team,
First, thank you very much for this resource; it´s very useful.
I am using the utilities 'users/parevalo_bu/gee-ccdc-tools:ccdcUtilities/api' to first detect changes and then get a classification of LandCover.

I have been able to run all the steps except the last one when I perform a Landcover classification for a specific date.

  • I get the ccdc multi-dimensional array and convert it to a ccdImage correctly
  • The training data is also created correctly
  • The RandomFroest Classification also works, and I can export classification results for specific segments.
// Classification parameters
var classification = {
  bandNames: ['BLUE','GREEN','RED','NIR','SWIR1','SWIR2'],
  inputFeatures: ["INTP", "SLP","PHASE","RMSE"],
  coefs: ["INTP", "SLP","COS", "SIN","RMSE","COS2","SIN2","COS3","SIN3"],
  ancillaryFeatures: ["ELEVATION","ASPECT","DEM_SLOPE","RAINFALL","TEMPERATURE"],
  resultFormat: 'SegCollection',
  classProperty: 'id',
  yearProperty: 'year',
  classifier: ee.Classifier.smileRandomForest,
  classifierParams: {
    numberOfTrees: 150,
    variablesPerSplit: null,
    minLeafPopulation: 1,
    bagFraction: 0.5,
    maxNodes: null
  },
  segs: ["S1", "S2", "S3", "S4", "S5", "S6"],
};


// Get classifier with params
var classifier = classification.classifier(classification.classifierParams);

var results_class = utils.Classification.classifySegments(
    ccdImage, classification.segs.length, classification.bandNames,
    ancillary, classification.ancillaryFeatures,
    trainingData, classifier, studyRegion, classification.classProperty,
    classification.inputFeatures)
    .clip(studyRegion);

It is now when printing and exporting the classification for a specific date, using the previous results "results_class" when I get the error: Image (Error) Image.select: Pattern 'numObs' did not match any bands.

var dateOfClassification = '2019-03-27';
var matchingDate = utils.Classification.getLcAtDate(results_class,
    dateOfClassification);
    
print(matchingDate, 'matchingDate');

Do you know where my mistake could be?

Here you are a link to the code:
https://code.earthengine.google.com/?accept_repo=users/ericacinerea/public

Thank you very much in advance.

Hi
I just got the same error. I think there is a problem when filtering the ccdcCollection with a metadataFilter, inside the utils.Classification.getLcAtDate function. The returned object is empty so I assume that the filter is not working as expected, in the following lines (thus, that is causing the 'numObs' error):

// Get CCDC coefficients
var ccdcCollectionFiltered = ccdcCollection
    .filterMetadata('system:index', 'starts_with',metadataFilter)`

I created another function based on the previous one, that seems to solve the problem. Right now I wrote it in a fast and messy way, but can be a quick workaround:

function getLcAtDate2(date){
  var segs = classificationStack;
  var numberOfSegments = 6;
  var bandNames = bands;//bandNames || ["BLUE","GREEN","RED","NIR","SWIR1","SWIR2","TEMP"]
  var inputFeatures = ["INTP", "SLP","PHASE","AMPLITUDE","COS","SIN","COS2","SIN2"];//inputFeatures || ; 
  numberOfSegments = ee.Image(segs).bandNames().length();//numberOfSegments || ;
  var behavior = 'after'//behavior || 'after'
    
  // Commented these lines for now  
  //if (dateFormat === 0){
  //  dateFormat = 0
  //} else if (dateFormat > 0) {
  //  dateFormat = dateFormat
  //} else {
  //  dateFormat = 1
  //}
  // dateFormat = (dateFormat && dateFormat === 0) || 1

  // Date passed as string 2020-01-01
  var dateFormat = 1;
  // CCDC Collection and 'system:index' metadata ftilter
  //var ccdcCollection = ccdcResults;
  var ccdcCollection = ee.Image('path/to/image/fromTemporalSegmentation.Ccdc');//ee.ImageCollection("projects/CCDC/" + ccdVersion)
  //print('ccdcCollection', ccdcCollection);
  // Get CCDC coefficients
  //var ccdcCollectionFiltered = ccdcCollection;//.filterMetadata('system:index', 'starts_with',metadataFilter)
  //print('ccdcCollectionFiltered', ccdcCollectionFiltered);
  // CCDC mosaic image
  var ccdc = ccdcCollection;//.mosaic()
  //print('ccdc', ccdc);
  // Turn array image into image
  var specImage = utils.CCDC.buildCcdImage(ccdc, numberOfSegments, bandNames)//specImage || 
  //print('specImage', specImage);
  var tStarts = specImage.select('.*tStart')
  var tEnds = specImage.select('.*tEnd')
  var dateFormatted = utils.Dates.convertDate({
    inputFormat: 3,
    inputDate: date,
    outputFormat: dateFormat
  })
  //print('tEnds',tEnds);
  if (behavior == 'before') {
    var dateMask = tStarts.lt(dateFormatted)
    var matchingDate =  segs.updateMask(dateMask).reduce(ee.Reducer.lastNonNull())
  } else if (behavior == 'after') {
    var dateMask = tEnds.gt(dateFormatted)
    var matchingDate =  segs.updateMask(dateMask).reduce(ee.Reducer.firstNonNull()) 
  } else {
    var dateMask = tStarts.lt(dateFormatted).and(tEnds.gt(dateFormatted))
    var matchingDate =  segs.updateMask(dateMask).reduce(ee.Reducer.firstNonNull()) 
  }
  
  return matchingDate;
}; 

var class2000 = getLcAtDate2('2000-01-01');

Hello, and thanks for your interest in this repo. I've been unable to work on this repo in a long time, but I just updated the getLcAtDate source code on GEE, and it should work now. This change won't be reflected in the Github copy of the code, or in the documentation because I need to bring a bunch of things up to date for that to happen. In the meantime, this is how you can use the function right now.

var matchingDate = utils.Classification.getLcAtDate(
    classificationStack, // Classified segments 
    dateOfClassification, // Date for which to retrieve the classification
    params.Classification.segs.length, // # of segments
    params.Classification.changeResults // the CCDC results
)

Thank you very much for your tutorial, but I used this function to extract two classifications that are years apart and the result is the same, what could be the reason?