Example #1
0
def ue_trend(year_start, year_end, ndvi_1yr, climate_1yr, logger):
    # Convert the climate layer to meters (for precip) so that RUE layer can be
    # scaled correctly
    # TODO: Need to handle scaling for ET for WUE
    climate_1yr = climate_1yr.divide(1000)
    logger.debug("Entering ue_trend function.")

    def f_img_coll(ndvi_stack):
        img_coll = ee.List([])
        for k in range(year_start, year_end + 1):
            ndvi_img = ndvi_stack.select('y{}'.format(k)).divide(climate_1yr.select('y{}'.format(k)))\
                .addBands(ee.Image(k).float())\
                .rename(['ue', 'year']).set({'year': k})
            img_coll = img_coll.add(ndvi_img)
        return ee.ImageCollection(img_coll)

    ## Apply function to compute ue and store as a collection
    ue_1yr_coll = f_img_coll(ndvi_1yr)

    ## Compute linear trend function to predict ndvi based on year (ndvi trend)
    lf_trend = ue_1yr_coll.select(['year', 'ue']).reduce(ee.Reducer.linearFit())

    ## Compute Kendall statistics
    mk_trend = stats.mann_kendall(ue_1yr_coll.select('ue'))

    return (lf_trend, mk_trend)
Example #2
0
def ndvi_trend(year_start, year_end, ndvi_1yr, logger):
    """Calculate temporal NDVI analysis.
    Calculates the trend of temporal NDVI using NDVI data from the
    MODIS Collection 6 MOD13Q1 dataset. Areas where changes are not significant
    are masked out using a Mann-Kendall test.
    Args:
        year_start: The starting year (to define the period the trend is
            calculated over).
        year_end: The ending year (to define the period the trend is
            calculated over).
    Returns:
        Output of google earth engine task.
    """
    logger.debug("Entering ndvi_trend function.")

    def f_img_coll(ndvi_stack):
        img_coll = ee.List([])
        for k in range(year_start, year_end + 1):
            ndvi_img = ndvi_stack.select('y' + str(k)).addBands(ee.Image(k).float()).rename(['ndvi', 'year'])
            img_coll = img_coll.add(ndvi_img)
        return ee.ImageCollection(img_coll)

    ## Apply function to compute NDVI annual integrals from 15d observed NDVI data
    ndvi_1yr_coll = f_img_coll(ndvi_1yr)

    ## Compute linear trend function to predict ndvi based on year (ndvi trend)
    lf_trend = ndvi_1yr_coll.select(['year', 'ndvi']).reduce(ee.Reducer.linearFit())

    ## Compute Kendall statistics
    mk_trend = stats.mann_kendall(ndvi_1yr_coll.select('ndvi'))

    return (lf_trend, mk_trend)
def restrend_pointwise(year_start, year_end, geojson, EXECUTION_ID, logger):
    """Calculate temporal NDVI analysis.
    Calculates the trend of temporal NDVI using NDVI data from the
    MODIS Collection 6 MOD13Q1 dataset. Areas where changes are not significant
    are masked out using a Mann-Kendall test.
    Args:
        year_start: The starting year (to define the period the trend is
            calculated over).
        year_end: The ending year (to define the period the trend is
            calculated over).
        geojson: A polygon defining the area of interest.
    Returns:
        Output of google earth engine task.
    """

    # Function to integrate NDVI dataset from 15d to 1yr
    def int_15d_1yr_clim(img_stack):
        img_coll = ee.List([])
        for k in range(1, 34):
            ndvi_lyr = img_stack.select(
                ee.List.sequence((k - 1) * 24, (k * 24) - 1)).reduce(
                    ee.Reducer.mean()).rename(['ndvi']).set({'year': 1981 + k})
            img_coll = img_coll.add(ndvi_lyr)
        return ee.ImageCollection(img_coll)

    # Function to compute differences between observed and predicted NDVI and comilation in an image collection
    def stack(year_start, year_end):
        img_coll = ee.List([])
        for k in range(year_start, year_end):
            ndvi = ndvi_1yr_o.filter(ee.Filter.eq('year',
                                                  k)).select('ndvi').median()
            clim = clim_1yr_o.filter(ee.Filter.eq('year',
                                                  k)).select('ndvi').median()
            img = ndvi.addBands(clim.addBands(ee.Image(k).float())).rename(
                ['ndvi', 'clim', 'year']).set({'year': k})
            img_coll = img_coll.add(img)
        return ee.ImageCollection(img_coll)

    # Function to predict NDVI from climate
    first = ee.List([])

    def ndvi_clim_p(image, list):
        ndvi = lf_clim_ndvi.select('offset').add(
            (lf_clim_ndvi.select('scale').multiply(image))).set(
                {'year': image.get('year')})
        return ee.List(list).add(ndvi)

    # Create image collection of residuals
    def ndvi_res(year_start, year_end):
        img_coll = ee.List([])
        for k in range(year_start, year_end):
            ndvi_o = coll_1yr_o.filter(ee.Filter.eq(
                'year', k)).select('ndvi').median()
            ndvi_p = ndvi_1yr_p.filter(ee.Filter.eq('year', k)).median()
            ndvi_r = ee.Image(k).float().addBands(ndvi_o.subtract(ndvi_p))
            img_coll = img_coll.add(ndvi_r.rename(['year', 'ndvi_res']))
        return ee.ImageCollection(img_coll)

    ndvi_1yr_o = preproc.modis_ndvi_annual_integral(year_start, year_end)

    # TODO: define clim_15d_o which is the merra-2 soil moisture data. For now,
    # forcing use of Senegal data for testing.
    clim_15d_o = ee.Image(
        'users/geflanddegradation/soil/sen_soilm_merra2_15d_1982_2015')

    # Apply function to compute climate annual integrals from 15d observed data
    clim_1yr_o = int_15d_1yr_clim(clim_15d_o.divide(10000))

    # Apply function to create image collection with stack of NDVI int, climate int and year
    coll_1yr_o = stack(year_start, year_end)

    # Reduce the collection with the linear fit reducer (independent var are followed by dependent var)
    lf_clim_ndvi = coll_1yr_o.select(['clim',
                                      'ndvi']).reduce(ee.Reducer.linearFit())

    # Apply function to  predict NDVI based on climate
    ndvi_1yr_p = ee.ImageCollection(
        ee.List(coll_1yr_o.select('clim').iterate(ndvi_clim_p, first)))

    # Apply function to compute NDVI annual residuals
    ndvi_1yr_r = ndvi_res(year_start, year_end)

    # Fit a linear regression to the NDVI residuals
    lf_prest = ndvi_1yr_r.select(['year',
                                  'ndvi_res']).reduce(ee.Reducer.linearFit())

    # Compute Kendall statistics
    mk_prest = stats.mann_kendall(ndvi_1yr_r.select('ndvi_res'))

    # Define Kendall parameter values for a significance of 0.05
    period = year_end - year_start + 1
    coefficients = ee.Array([
        4, 6, 9, 11, 14, 16, 19, 21, 24, 26, 31, 33, 36, 40, 43, 47, 50, 54,
        59, 63, 66, 70, 75, 79, 84, 88, 93, 97, 102, 106, 111, 115, 120, 126,
        131, 137, 142
    ])
    kendall = coefficients.get([period - 4])

    # Create export function
    export = {
        'image':
        lf_prest.select('scale').where(
            mk_prest.abs().lte(kendall), -99999).where(
                lf_prest.select('scale').abs().lte(0.000001),
                -99999).unmask(-99999),
        'description':
        EXECUTION_ID,
        'fileNamePrefix':
        EXECUTION_ID,
        'bucket':
        BUCKET,
        'maxPixels':
        10000000000,
        'scale':
        250,
        'region':
        util.get_coords(geojson)
    }

    # Export final mosaic to assets
    task = ee.batch.Export.image.toCloudStorage(**export)

    task.start()
    task_state = task.status().get('state')
    while task_state == 'READY' or task_state == 'RUNNING':
        task_progress = task.status().get('progress', 0.0)
        # update GEF-EXECUTION progress
        logger.send_progress(task_progress)
        # update variable to check the condition
        task_state = task.status().get('state')
        sleep(5)

    return "https://{}.storage.googleapis.com/{}.tif".format(
        BUCKET, EXECUTION_ID)
Example #4
0
def p_restrend(year_start, year_end, ndvi_1yr, climate_1yr, logger):
    logger.debug("Entering p_restrend function.")

    def f_img_coll(ndvi_stack):
        img_coll = ee.List([])
        for k in range(year_start, year_end + 1):
            ndvi_img = ndvi_stack.select('y{}'.format(k))\
                .addBands(climate_1yr.select('y{}'.format(k)))\
                .rename(['ndvi', 'clim']).set({'year': k})
            img_coll = img_coll.add(ndvi_img)
        return ee.ImageCollection(img_coll)

    ## Function to predict NDVI from climate
    first = ee.List([])

    def f_ndvi_clim_p(image, list):
        ndvi = lf_clim_ndvi.select('offset').add((lf_clim_ndvi.select('scale').multiply(image))).set({'year': image.get('year')})
        return ee.List(list).add(ndvi)

    ## Function to compute residuals (ndvi obs - ndvi pred)
    def f_ndvi_clim_r_img(year):
        ndvi_o = ndvi_1yr_coll.filter(ee.Filter.eq('year', year)).select('ndvi').median()
        ndvi_p = ndvi_1yr_p.filter(ee.Filter.eq('year', year)).median()
        ndvi_r = ee.Image(year).float().addBands(ndvi_o.subtract(ndvi_p))
        return ndvi_r.rename(['year', 'ndvi_res'])

    # Function to compute differences between observed and predicted NDVI and compilation in an image collection
    def stack(year_start, year_end):
        img_coll = ee.List([])
        for k in range(year_start, year_end + 1):
            ndvi = ndvi_1yr_o.filter(ee.Filter.eq('year', k)).select('ndvi').median()
            clim = clim_1yr_o.filter(ee.Filter.eq('year', k)).select('ndvi').median()
            img = ndvi.addBands(clim.addBands(ee.Image(k).float())).rename(['ndvi', 'clim', 'year']).set({'year': k})
            img_coll = img_coll.add(img)
        return ee.ImageCollection(img_coll)

    ## Function create image collection of residuals
    def f_ndvi_clim_r_coll(year_start, year_end):
        res_list = ee.List([])
        #for(i = year_start i <= year_end i += 1):
        for i in range(year_start, year_end + 1):
            res_image = f_ndvi_clim_r_img(i)
            res_list = res_list.add(res_image)
        return ee.ImageCollection(res_list)

    ## Apply function to create image collection of ndvi and climate
    ndvi_1yr_coll = f_img_coll(ndvi_1yr)

    ## Compute linear trend function to predict ndvi based on climate (independent are followed by dependent var
    lf_clim_ndvi = ndvi_1yr_coll.select(['clim', 'ndvi']).reduce(ee.Reducer.linearFit())

    ## Apply function to  predict NDVI based on climate
    ndvi_1yr_p = ee.ImageCollection(ee.List(ndvi_1yr_coll.select('clim').iterate(f_ndvi_clim_p, first)))

    ## Apply function to compute NDVI annual residuals
    ndvi_1yr_r = f_ndvi_clim_r_coll(year_start, year_end)

    ## Fit a linear regression to the NDVI residuals
    lf_trend = ndvi_1yr_r.select(['year', 'ndvi_res']).reduce(ee.Reducer.linearFit())

    ## Compute Kendall statistics
    mk_trend = stats.mann_kendall(ndvi_1yr_r.select('ndvi_res'))

    return (lf_trend, mk_trend)
def restrend_system(year_start, year_end, geojson, EXECUTION_ID, logger):
    """Calculate temporal NDVI analysis.
    Calculates the trend of temporal NDVI using NDVI data from the
    MODIS Collection 6 MOD13Q1 dataset. Areas where changes are not significant
    are masked out using a Mann-Kendall test.
    Args:
        year_start: The starting year (to define the period the trend is
            calculated over).
        year_end: The ending year (to define the period the trend is
            calculated over).
        geojson: A polygon defining the area of interest.
    Returns:
        Output of google earth engine task.
    """

    # Function to integrate NDVI dataset from 15d to 1yr
    def int_15d_1yr_p(img_stack):
        img_coll = ee.List([])
        for k in range(1, 34):
            ndvi_lyr = img_stack.select(
                ee.List.sequence((k - 1) * 24, (k * 24) - 1)).reduce(
                    ee.Reducer.mean()).rename(['ndvi']).set({'year': 1981 + k})
            img_coll = img_coll.add(ndvi_lyr)
        return ee.ImageCollection(img_coll)

    # Create image collection of residuals
    def ndvi_res(year_start, year_end):
        img_coll = ee.List([])
        for k in range(year_start, year_end):
            ndvi_o = coll_1yr_o.filter(ee.Filter.eq(
                'year', k)).select('ndvi').median()
            ndvi_p = ndvi_1yr_p.filter(ee.Filter.eq('year', k)).median()
            ndvi_r = ee.Image(k).float().addBands(ndvi_o.subtract(ndvi_p))
            img_coll = img_coll.add(ndvi_r.rename(['year', 'ndvi_res']))
        return ee.ImageCollection(img_coll)

    # Conversion of soil moisture to NDVI using equations developed by NASA presented in the report 1
    # TODO: define clim_15d_o which is the merra-2 soil moisture data. For now,
    # forcing use of Senegal data for testing.
    clim_15d_o = ee.Image(
        'users/geflanddegradation/soil/sen_soilm_merra2_15d_1982_2015')

    ndvi_p1 = clim_15d_o.divide(10000).multiply(0.11).add(0.19)
    ndvi_p2 = clim_15d_o.divide(10000).multiply(6.63).add(-2.22)
    ndvi_p3 = clim_15d_o.divide(10000).pow(3).multiply(1.38).add(
        clim_15d_o.divide(10000).pow(2).multiply(-3.83)).add(
            clim_15d_o.divide(10000).multiply(3.83)).add(-0.63)

    # Conditional statement to combine the 3 NDVI estimates into one image
    ndvi_15d_p = ndvi_p2.where(clim_15d_o.lte(0.37 * 10000),
                               ndvi_p1).where(clim_15d_o.gte(0.39 * 10000),
                                              ndvi_p3)

    # Apply function to compute predicted NDVI annual integrals from 15d predicted NDVI data
    ndvi_1yr_p = int_15d_1yr_p(ndvi_15d_p)

    coll_1yr_o = preproc.modis_ndvi_annual_integral(year_start, year_end)

    # Compute differences between observed and predicted NDVI annual integrals
    ndvi_1yr_r = ndvi_res(year_start, year_end)

    # Fit a linear regression to the NDVI differences
    lf_srest = ndvi_1yr_r.select(['year',
                                  'ndvi_res']).reduce(ee.Reducer.linearFit())

    # Compute Kendall statistics
    mk_srest = stats.mann_kendall(ndvi_1yr_r.select('ndvi_res'))

    # Define Kendall parameter values for a significance of 0.05
    period = year_end - year_start + 1
    coefficients = ee.Array([
        4, 6, 9, 11, 14, 16, 19, 21, 24, 26, 31, 33, 36, 40, 43, 47, 50, 54,
        59, 63, 66, 70, 75, 79, 84, 88, 93, 97, 102, 106, 111, 115, 120, 126,
        131, 137, 142
    ])
    kendall = coefficients.get([period - 4])

    # Create export function
    export = {
        'image':
        lf_srest.select('scale').where(
            mk_srest.abs().lte(kendall), -99999).where(
                lf_srest.select('scale').abs().lte(0.000001),
                -99999).unmask(-99999),
        'description':
        EXECUTION_ID,
        'fileNamePrefix':
        EXECUTION_ID,
        'bucket':
        BUCKET,
        'maxPixels':
        10000000000,
        'scale':
        250,
        'region':
        util.get_coords(geojson)
    }

    # Export final mosaic to assets
    task = ee.batch.Export.image.toCloudStorage(**export)

    task.start()
    task_state = task.status().get('state')
    while task_state == 'READY' or task_state == 'RUNNING':
        task_progress = task.status().get('progress', 0.0)
        # update GEF-EXECUTION progress
        logger.send_progress(task_progress)
        # update variable to check the condition
        task_state = task.status().get('state')
        sleep(5)

    return "https://{}.storage.googleapis.com/{}.tif".format(
        BUCKET, EXECUTION_ID)
Example #6
0
def integral_trend(year_start, year_end, geojson, EXECUTION_ID, logger):
    """Calculate annual trend of integrated NDVI.

    Calculates the trend of annual integrated NDVI using NDVI data from the
    MODIS Collection 6 MOD13Q1 dataset. Areas where changes are not significant
    are masked out using a Mann-Kendall test.

    Args:
        year_start: The starting year (to define the period the trend is
            calculated over).
        year_end: The ending year (to define the period the trend is
            calculated over).
        geojson: A polygon defining the area of interest.
        EXECUTION_ID: String identifying this process, used in naming the 
            results.

    Returns:
        Location of output on google cloud storage.
    """

    # Compute NDVI annual integrals from 15d observed NDVI data
    ndvi_1yr_o = preproc.modis_ndvi_annual_integral(year_start, year_end)

    # Compute linear trend function to predict ndvi based on year (ndvi trend)
    lf_trend = ndvi_1yr_o.select(['year',
                                  'ndvi']).reduce(ee.Reducer.linearFit())

    # Define Kendall parameter values for a significance of 0.05
    period = year_end - year_start + 1
    coefficients = ee.Array([
        4, 6, 9, 11, 14, 16, 19, 21, 24, 26, 31, 33, 36, 40, 43, 47, 50, 54,
        59, 63, 66, 70, 75, 79, 84, 88, 93, 97, 102, 106, 111, 115, 120, 126,
        131, 137, 142
    ])
    kendall = coefficients.get([period - 4])

    # Compute Kendall statistics
    mk_trend = stats.mann_kendall(ndvi_1yr_o.select('ndvi'))

    export = {
        'image':
        lf_trend.select('scale').where(
            mk_trend.abs().lte(kendall), -99999).where(
                lf_trend.select('scale').abs().lte(0.000001),
                -99999).unmask(-99999),
        'description':
        EXECUTION_ID,
        'fileNamePrefix':
        EXECUTION_ID,
        'bucket':
        BUCKET,
        'maxPixels':
        10000000000,
        'scale':
        250,
        'region':
        util.get_coords(geojson)
    }

    # Export final mosaic to assets
    task = ee.batch.Export.image.toCloudStorage(**export)

    # Task -> READY
    task.start()
    task_state = task.status().get('state')
    while task_state == 'READY' or task_state == 'RUNNING':
        task_progress = task.status().get('progress', 0.0)
        # update GEF-EXECUTION progress
        logger.send_progress(task_progress)
        # update variable to check the condition
        task_state = task.status().get('state')
        sleep(5)

    return "https://{}.storage.googleapis.com/{}.tif".format(
        BUCKET, EXECUTION_ID)