# Producing image depicting number of days to value > 0 at each pixel in an ImageCollection with daily values of NDVI for North America

New to GEE but excited to learn more about it. I have produced NDVI values from the 'LANDSAT/LC08/C02/T1_L2' ImageCollection including every available day in 2022. I fitted a harmonic regression to these values to estimate the missing (daily) values at every pixel within North America. I am now interested in producing an image where the value for any given pixel is simply the number of days it took at that site for NDVI to become greater than 0 as the year progressed. I have not been able to figure out how to find out the different dates for each pixel and combine them into a single image. I am attaching my latest attempt to do this (but it clearly does not accomplish what I want to do).

``````///////////////////// CODE /////////////////////////////
var startdate = '2022-01-01'
var enddate = '2022-12-31'

// define region of interest
var polygon = ee.Geometry.Polygon({
coords: [[[-50, 10], [-180, 10],
[-180, 85], [-50, 85],
[-50, 100]]],
geodesic: false
});

// (NDVI, time and a constant) to Landsat 8 imagery.
// Bit 0 - Fill
// Bit 1 - Dilated Cloud
// Bit 2 - Cirrus
// Bit 3 - Cloud
// Bit 4 - Cloud Shadow
2)).eq(0);

// Apply the scaling factors to the appropriate bands.
0.2);
var thermalBands=image.select('ST_B.*').multiply(0.00341802)

// Replace the original bands with the scaled ones and apply the masks.

// Now we start to add variables of interest.
// Compute time in fractional years since the epoch.
var date=ee.Date(image.get('system:time_start'));
var JulianDate=date.difference(ee.Date(startdate), 'year');
// Return the image with the added bands.
return imgScaled
.rename('NDVI'))
.float()
}

// Import the USGS Landsat 8 Level 2, Collection 2, Tier 1 image collection),
var landsat8sr=ee.ImageCollection('LANDSAT/LC08/C02/T1_L2')
.filterBounds(polygon)
.filterDate(startdate, enddate)

////////////////////////////////////////////////////////////////////
// fit harmonic regression to the observed NDVI data

// Name of the dependent variable.
var dependent=ee.String('NDVI');

// 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=landsat8sr.map(function(image){
return image
});

// Fit the model.
var harmonicTrend=harmonicLandsat
// The output of this reducer is a 4x1 array image.
.reduce(ee.Reducer.linearRegression(harmonicIndependents.length(),
1));

// Turn the array image into a multi-band image of coefficients.
var harmonicTrendCoefficients=harmonicTrend.select('coefficients')
.arrayProject([0])
.arrayFlatten([harmonicIndependents]);

// Compute fitted values.

// Apply the coefficients obtained from linear regression to each pixel's time series
var fittedHarmonic = harmonicLandsat.map(function(image) {
// Multiply the harmonic coefficients with the independent variables (time, cosine, sine)
var fittedValues = image.select(harmonicIndependents)
.multiply(harmonicTrendCoefficients)
.reduce('sum')
.rename('fitted');

// Add the fitted values as a new band to the image
});

////////////////////////////////////////////////////////////////////////////
// Here I am trying to figure out the first day in which NDVI > 0 for each pixel

// Define a function to find the first unmasked NDVI value for each pixel
var findFirstValidNDVI = function(image) {
var fittedBand = image.select('fitted');

// Create a binary mask where 'fitted' is greater than or equal to 0

// Use reduceRegion to find the first valid NDVI value for each pixel
reducer: ee.Reducer.min(),
geometry: polygon,
scale: 30, // adjust scale as needed
bestEffort: true
});

// Return an image with the index of the first valid NDVI value
return ee.Image.constant(firstValidIndex.get('fitted')).rename('first_valid_ndvi');
};

// Apply the reducer to your Image Collection
var firstNDVI = fittedHarmonic.map(findFirstValidNDVI);

// Calculate the number of days since the beginning of the year for each image
var dayOfYear = firstNDVI.map(function(image) {
return doy;
});

// Combine the images in the collection into one image using mosaic or reduce with max reducer
var dayOfYearImage = dayOfYear.max(); // Or use .mosaic()

// Subtract the day of the year of the first unmasked NDVI value from each image
var daysSinceFirstValidNDVI = dayOfYearImage.subtract(1); // Subtract 1 to account for 0-based indexing

// Create a single image from the collection representing the number of days since the first unmasked NDVI value
var daysSinceFirstImage = daysSinceFirstValidNDVI.max(); // Use 'max()' to merge all images into one

// Display the result
Map.addLayer(daysSinceFirstImage, {min: 0, max: 50, palette: ['purple', 'blue', 'green', 'yellow', 'red']}, 'Days since first valid NDVI');

// Center the map on the polygon of interest
Map.centerObject(polygon, 3);

``````

You can simply mask all the pixel values in your images that have NDVI values <= 0 and then apply a minimum reducer to the collection and extract the minimum date image. Here's a solution that makes minimal changes to your code.

``````////////////////////////////////////////////////////////////////////////////
// Here I am trying to figure out the first day in which NDVI > 0 for each pixel
// Changes start in this section
// Define a function to add new band that adds Julian Date as another band
// and mask all NDVI values <=0 on all bands.
var fittedBand = image.select('fitted');

// Create a binary mask where 'fitted' is greater than to 0
// Create julianDate band
var julianDate = ee.Image.constant(ee.Date(image.get('system:time_start'))
.difference(ee.Date(startdate), 'day'))
.rename('julianDate')
.float();

// Return an image with the julianDate band and masked with the new NDVI mask