# Detrending MODIS NDVI timeseries for Harmonic Regression in Google Earth Engine

Trying to detrend MODIS MOD13Q1 NDVI time series using a tutorial from Ozzy Campos (@ghidora77). This tutorial was for Landsat NDVI LANDSAT/LC08/C02/T1_L2 but I am trying to modify it for MODIS.

Successfully imported the data, parse it for quality control, masked, scaled and plotted the initial time series with a trend line. See the code in help3. Link to the asset: Oban.

Independent ('constant', 't') and dependent variables ('NDVI') have also been set. However, when trying to detrend the time series, I get the error below (see attached image). Because detrending doesn't work properly, I don't trust the resultant harmonic model.

Error generating chart: Projection error: Unable to compute intersection of geometries in projections and .

``````// List of the independent variable names.
var independents = ee.List(['constant', 't']);
// Name of the dependent variable.
var dependent = ee.String('NDVI');
// Compute a linear trend. This will have two bands: 'residuals' and
// a 2x1 band called 'coefficients' (columns are for dependent variables).
.reduce(ee.Reducer.linearRegression(independents.length(), 1));

/////////////////////////////////////////////////
// **************** HELP!!!!!!! ***************

// Flatten the coefficients into a 2-band image.
var coefficients = trend.select('coefficients')
.arrayProject([0])
.arrayFlatten([independents]);
``````

Compute a detrended series.

``````var detrended = newndvi.map(function(image) {
return image.select(dependent).subtract(
image.select(independents).multiply(coefficients).reduce('sum'))
.rename(dependent)
.copyProperties(image, ['system:time_start']);
});

var detrendedChart = ui.Chart.image.series(detrended, Oban, null, 250)
.setOptions({
title: 'Detrended MODIS Time Series at Oban',
lineWidth: 1,
pointSize: 3,
});
print(detrendedChart);
``````

Use these independent variables in the harmonic regression.

``````var harmonicIndependents = ee.List(['constant', 't', 'cos', 'sin']);
// Add harmonic terms as new image bands.
var harmonicLandsat = newndvi.map(function(image) {
var timeRadians = image.select('t').multiply(2 * Math.PI);
return image
});

var harmonicTrend = harmonicLandsat
// The output of this reducer is a 4x1 array image.
.reduce(ee.Reducer.linearRegression({
numX: harmonicIndependents.length(),
numY: 1
}));

``````

Turn the array image into a multi-band image of coefficients.

``````var harmonicTrendCoefficients = harmonicTrend.select('coefficients')
.arrayProject([0])
.arrayFlatten([harmonicIndependents]);
// Compute fitted values.
var fittedHarmonic = harmonicLandsat.map(function(image) {
image.select(harmonicIndependents)
.multiply(harmonicTrendCoefficients)
.reduce('sum')
.rename('fitted'));
});
// Plot the fitted model and the original data at the Oban.
print(ui.Chart.image.series(fittedHarmonic.select(['fitted', 'NDVI']), Oban,
ee.Reducer.mean(), 250)
.setSeriesNames(['NDVI', 'fitted'])
.setOptions({
title: 'Harmonic Model: Original and Fitted Values',
lineWidth: 1,
pointSize: 3
})
);
``````

Compute phase and amplitude.

``````var phase = harmonicTrendCoefficients.select('sin')
.atan2(harmonicTrendCoefficients.select('cos'))
// Scale to [0, 1] from radians.
.unitScale(-Math.PI, Math.PI);
var amplitude = harmonicTrendCoefficients.select('sin')
.hypot(harmonicTrendCoefficients.select('cos'))
// Add a scale factor for visualization.
.multiply(5);
// Compute the mean NDVI.
var meanNdvi = newndvi.select('NDVI').mean();
// Use the HSV to RGB transformation to display phase and amplitude.
var rgb = ee.Image.cat([phase, amplitude, meanNdvi]).hsvToRgb();
Map.addLayer(rgb, {}, 'Phase (hue), Amplitude (sat), NDVI (val)');
``````

``````var detrended = newndvi.map(function(image) {