Beispiel #1
0
def restoration_carbon(rest_type, length_yr, crs, geojsons, EXECUTION_ID,
                       logger):
    logger.debug("Entering restoration_carbon function.")
    # biomass
    agb_30m = ee.Image(
        "users/geflanddegradation/toolbox_datasets/forest_agb_30m_woodhole")
    agb_1km = ee.Image(
        "users/geflanddegradation/toolbox_datasets/forest_agb_1km_geocarbon")

    # c sequestration coefficients by intervention from winrock paper
    agfor0020 = ee.Image(
        "users/geflanddegradation/toolbox_datasets/winrock_co2_seq_coeff_adm1"
    ).select("b1").divide(100)
    agfor2060 = ee.Image(
        "users/geflanddegradation/toolbox_datasets/winrock_co2_seq_coeff_adm1"
    ).select("b2").divide(100)
    mshrr0020 = ee.Image(
        "users/geflanddegradation/toolbox_datasets/winrock_co2_seq_coeff_adm1"
    ).select("b3").divide(100)
    mshrr2060 = ee.Image(
        "users/geflanddegradation/toolbox_datasets/winrock_co2_seq_coeff_adm1"
    ).select("b4").divide(100)
    mtrer0020 = ee.Image(
        "users/geflanddegradation/toolbox_datasets/winrock_co2_seq_coeff_adm1"
    ).select("b5").divide(100)
    mtrer2060 = ee.Image(
        "users/geflanddegradation/toolbox_datasets/winrock_co2_seq_coeff_adm1"
    ).select("b6").divide(100)
    natre0020 = ee.Image(
        "users/geflanddegradation/toolbox_datasets/winrock_co2_seq_coeff_adm1"
    ).select("b7").divide(100)
    natre2060 = ee.Image(
        "users/geflanddegradation/toolbox_datasets/winrock_co2_seq_coeff_adm1"
    ).select("b8").divide(100)
    pwobr0020 = ee.Image(
        "users/geflanddegradation/toolbox_datasets/winrock_co2_seq_coeff_adm1"
    ).select("b9").divide(100)
    pweuc0020 = ee.Image(
        "users/geflanddegradation/toolbox_datasets/winrock_co2_seq_coeff_adm1"
    ).select("b10").divide(100)
    pwoak0020 = ee.Image(
        "users/geflanddegradation/toolbox_datasets/winrock_co2_seq_coeff_adm1"
    ).select("b11").divide(100)
    pwoco0020 = ee.Image(
        "users/geflanddegradation/toolbox_datasets/winrock_co2_seq_coeff_adm1"
    ).select("b12").divide(100)
    pwpin0020 = ee.Image(
        "users/geflanddegradation/toolbox_datasets/winrock_co2_seq_coeff_adm1"
    ).select("b13").divide(100)
    pwtea0020 = ee.Image(
        "users/geflanddegradation/toolbox_datasets/winrock_co2_seq_coeff_adm1"
    ).select("b14").divide(100)

    # combine the global 1km and the pantropical 30m datasets into one layer for analysis
    agb = agb_30m.float().unmask(0).where(
        ee.Image.pixelLonLat().select('latitude').abs().gte(29.999), agb_1km)

    # calculate below ground biomass following Mokany et al. 2006 = (0.489)*(AGB)^(0.89)
    bgb = agb.expression('0.489 * BIO**(0.89)', {'BIO': agb})

    # calculate total biomass (t/ha) then convert to carbon equilavent (*0.5) to get Total Carbon (t ha-1) = (AGB+BGB)*0.5
    tbc = agb.expression('(bgb + abg ) * 0.5 ', {'bgb': bgb, 'abg': agb})

    # convert Total carbon to total CO2 eq (One ton of carbon equals 44/12 = 11/3 = 3.67 tons of carbon dioxide)
    current_co2 = tbc.expression('totalcarbon * 3.67 ', {'totalcarbon': tbc})

    if rest_type == "terrestrial":
        if length_yr <= 20:
            d_natre = natre0020.multiply(length_yr).subtract(current_co2)
            d_natre = d_natre.where(d_natre.lte(0), 0)
            d_agfor = agfor0020.multiply(length_yr).subtract(current_co2)
            d_agfor = d_agfor.where(d_agfor.lte(0), 0)
            d_pwtea = pwtea0020.multiply(length_yr).subtract(current_co2)
            d_pweuc = pweuc0020.multiply(length_yr).subtract(current_co2)
            d_pwoak = pwoak0020.multiply(length_yr).subtract(current_co2)
            d_pwobr = pwobr0020.multiply(length_yr).subtract(current_co2)
            d_pwpin = pwpin0020.multiply(length_yr).subtract(current_co2)
            d_pwoco = pwoco0020.multiply(length_yr).subtract(current_co2)
        if length_yr > 20:
            d_natre = natre0020.multiply(20).add(
                natre2060.multiply(length_yr - 20)).subtract(current_co2)
            d_natre = d_natre.where(d_natre.lte(0), 0)
            d_agfor = agfor0020.multiply(20).add(
                agfor2060.multiply(length_yr - 20)).subtract(current_co2)
            d_agfor = d_agfor.where(d_agfor.lte(0), 0)
            d_pwtea = pwtea0020.multiply(20).subtract(current_co2)
            d_pweuc = pweuc0020.multiply(20).subtract(current_co2)
            d_pwoak = pwoak0020.multiply(20).subtract(current_co2)
            d_pwobr = pwobr0020.multiply(20).subtract(current_co2)
            d_pwpin = pwpin0020.multiply(20).subtract(current_co2)
            d_pwoco = pwoco0020.multiply(20).subtract(current_co2)

        output = current_co2.addBands(d_natre).addBands(d_agfor) \
                    .addBands(d_pwtea).addBands(d_pweuc) \
                    .addBands(d_pwoak).addBands(d_pwobr) \
                    .addBands(d_pwpin).addBands(d_pwoco) \
                    .rename(['current','natreg','agrfor','pwteak','pweuca','pwoaks','pwobro','pwpine','pwocon'])

        logger.debug("Setting up output for terrestrial restoration.")
        out = TEImage(output, [
            BandInfo("Biomass (tonnes CO2e per ha)",
                     add_to_map=True,
                     metadata={'year': 'current'}),
            BandInfo("Restoration biomass difference (tonnes CO2e per ha)",
                     metadata={
                         'years': length_yr,
                         'type': 'natural regeneration'
                     }),
            BandInfo("Restoration biomass difference (tonnes CO2e per ha)",
                     metadata={
                         'years': length_yr,
                         'type': 'agroforestry'
                     }),
            BandInfo("Restoration biomass difference (tonnes CO2e per ha)",
                     metadata={
                         'years': length_yr,
                         'type': 'teak plantation'
                     }),
            BandInfo("Restoration biomass difference (tonnes CO2e per ha)",
                     metadata={
                         'years': length_yr,
                         'type': 'eucalyptus plantation'
                     }),
            BandInfo("Restoration biomass difference (tonnes CO2e per ha)",
                     metadata={
                         'years': length_yr,
                         'type': 'oak plantation'
                     }),
            BandInfo("Restoration biomass difference (tonnes CO2e per ha)",
                     metadata={
                         'years': length_yr,
                         'type': 'other broadleaf plantation'
                     }),
            BandInfo("Restoration biomass difference (tonnes CO2e per ha)",
                     metadata={
                         'years': length_yr,
                         'type': 'pine plantation'
                     }),
            BandInfo("Restoration biomass difference (tonnes CO2e per ha)",
                     metadata={
                         'years': length_yr,
                         'type': 'conifer plantation'
                     })
        ])
    elif rest_type == "coastal":
        if length_yr <= 20:
            d_mshrr = mshrr0020.multiply(length_yr).subtract(current_co2)
            d_mshrr = d_mshrr.where(d_mshrr.lte(0), 0)
            d_mtrer = mtrer0020.multiply(length_yr).subtract(current_co2)
            d_mtrer = d_mtrer.where(d_mtrer.lte(0), 0)
        if length_yr > 20:
            d_mshrr = mshrr0020.multiply(20).add(
                mshrr2060.multiply(length_yr - 20)).subtract(current_co2)
            d_mshrr = d_mshrr.where(d_mshrr.lte(0), 0)
            d_mtrer = mtrer0020.multiply(20).add(
                mtrer2060.multiply(length_yr - 20)).subtract(current_co2)
            d_mtrer = d_mtrer.where(d_mtrer.lte(0), 0)

        logger.debug("Setting up output for coastal restoration.")
        out = TEImage(
            current_co2.addBands(d_mshrr).addBands(d_mtrer).rename(
                ['current', 'mshrr', 'mtrer']),
            [
                BandInfo("Biomass (tonnes CO2e per ha)",
                         add_to_map=True,
                         metadata={'year': 'current'}),
                BandInfo("Restoration biomass difference (tonnes CO2e per ha)",
                         metadata={
                             'years': length_yr,
                             'type': 'mangrove shrub'
                         }),
                BandInfo("Restoration biomass difference (tonnes CO2e per ha)",
                         metadata={
                             'years': length_yr,
                             'type': 'mangrove tree'
                         })
            ])
    else:
        raise

    out.image = out.image.reproject(crs=agb_30m.projection())

    return out
Beispiel #2
0
def soc(geometry, year_start, year_end, fl, remap_matrix, dl_annual_lc,
        EXECUTION_ID, logger):
    """
    Calculate SOC indicator.
    """
    logger.debug("Entering soc function.")
    geom = ee.Geometry.Polygon(geometry)
    # Location
    area = ee.FeatureCollection(geom)
    # soc
    soc = ee.Image(
        "users/geflanddegradation/toolbox_datasets/soc_sgrid_30cm").clip(area)
    soc_t0 = soc.updateMask(soc.neq(-32768))

    # land cover - note it needs to be reprojected to match soc so that it can
    # be output to cloud storage in the same stack
    lc = ee.Image("users/geflanddegradation/toolbox_datasets/lcov_esacc_1992_2018") \
            .select(ee.List.sequence(year_start - 1992, year_end - 1992, 1)) \
            .clip(area) \
            .reproject(crs=soc.projection())

    lc = lc.where(lc.eq(9999), -32768)
    lc = lc.updateMask(lc.neq(-32768))

    if fl == 'per pixel':
        # Setup a raster of climate regimes to use for coding Fl automatically
        climate = ee.Image("users/geflanddegradation/toolbox_datasets/ipcc_climate_zones") \
            .clip(area) \
            .remap([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
                   [0, 2, 1, 2, 1, 2, 1, 2, 1, 5, 4, 4, 3])
        clim_fl = climate.remap([0, 1, 2, 3, 4, 5],
                                [0, 0.8, 0.69, 0.58, 0.48, 0.64])
    # create empty stacks to store annual land cover maps
    stack_lc = ee.Image().select()

    # create empty stacks to store annual soc maps
    stack_soc = ee.Image().select()

    # loop through all the years in the period of analysis to compute changes in SOC
    for k in range(year_end - year_start):
        # land cover map reclassified to UNCCD 7 classes (1: forest, 2:
        # grassland, 3: cropland, 4: wetland, 5: artifitial, 6: bare, 7: water)
        lc_t0 = lc.select(k).remap(remap_matrix[0], remap_matrix[1])

        lc_t1 = lc.select(k + 1).remap(remap_matrix[0], remap_matrix[1])

        if (k == 0):
            # compute transition map (first digit for baseline land cover, and
            # second digit for target year land cover)
            lc_tr = lc_t0.multiply(10).add(lc_t1)

            # compute raster to register years since transition
            tr_time = ee.Image(2).where(lc_t0.neq(lc_t1), 1)
        else:
            # Update time since last transition. Add 1 if land cover remains
            # constant, and reset to 1 if land cover changed.
            tr_time = tr_time.where(lc_t0.eq(lc_t1), tr_time.add(ee.Image(1))) \
                .where(lc_t0.neq(lc_t1), ee.Image(1))

            # compute transition map (first digit for baseline land cover, and
            # second digit for target year land cover), but only update where
            # changes actually ocurred.
            lc_tr_temp = lc_t0.multiply(10).add(lc_t1)
            lc_tr = lc_tr.where(lc_t0.neq(lc_t1), lc_tr_temp)

        # stock change factor for land use - note the 99 and -99 will be
        # recoded using the chosen Fl option
        lc_tr_fl_0 = lc_tr.remap([
            11, 12, 13, 14, 15, 16, 17, 21, 22, 23, 24, 25, 26, 27, 31, 32, 33,
            34, 35, 36, 37, 41, 42, 43, 44, 45, 46, 47, 51, 52, 53, 54, 55, 56,
            57, 61, 62, 63, 64, 65, 66, 67, 71, 72, 73, 74, 75, 76, 77
        ], [
            1, 1, 99, 1, 0.1, 0.1, 1, 1, 1, 99, 1, 0.1, 0.1, 1, -99, -99, 1,
            1 / 0.71, 0.1, 0.1, 1, 1, 1, 0.71, 1, 0.1, 0.1, 1, 2, 2, 2, 2, 1,
            1, 1, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
        ])

        if fl == 'per pixel':
            lc_tr_fl = lc_tr_fl_0.where(lc_tr_fl_0.eq(99), clim_fl)\
                                 .where(lc_tr_fl_0.eq(-99), ee.Image(1).divide(clim_fl))
        else:
            lc_tr_fl = lc_tr_fl_0.where(lc_tr_fl_0.eq(99), fl)\
                                 .where(lc_tr_fl_0.eq(-99), ee.Image(1).divide(fl))

        # stock change factor for management regime
        lc_tr_fm = lc_tr.remap([
            11, 12, 13, 14, 15, 16, 17, 21, 22, 23, 24, 25, 26, 27, 31, 32, 33,
            34, 35, 36, 37, 41, 42, 43, 44, 45, 46, 47, 51, 52, 53, 54, 55, 56,
            57, 61, 62, 63, 64, 65, 66, 67, 71, 72, 73, 74, 75, 76, 77
        ], [
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1
        ])

        # stock change factor for input of organic matter
        lc_tr_fo = lc_tr.remap([
            11, 12, 13, 14, 15, 16, 17, 21, 22, 23, 24, 25, 26, 27, 31, 32, 33,
            34, 35, 36, 37, 41, 42, 43, 44, 45, 46, 47, 51, 52, 53, 54, 55, 56,
            57, 61, 62, 63, 64, 65, 66, 67, 71, 72, 73, 74, 75, 76, 77
        ], [
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
            1, 1, 1, 1, 1
        ])

        if (k == 0):
            soc_chg = (soc_t0.subtract((soc_t0.multiply(lc_tr_fl).multiply(
                lc_tr_fm).multiply(lc_tr_fo)))).divide(20)

            # compute final SOC stock for the period
            soc_t1 = soc_t0.subtract(soc_chg)

            # add to land cover and soc to stacks from both dates for the first
            # period
            stack_lc = stack_lc.addBands(lc_t0).addBands(lc_t1)
            stack_soc = stack_soc.addBands(soc_t0).addBands(soc_t1)

        else:
            # compute annual change in soc (updates from previous period based
            # on transition and time <20 years)
            soc_chg = soc_chg.where(lc_t0.neq(lc_t1),
                                    (stack_soc.select(k).subtract(stack_soc.select(k) \
                                                                  .multiply(lc_tr_fl) \
                                                                  .multiply(lc_tr_fm) \
                                                                  .multiply(lc_tr_fo))).divide(20)) \
                             .where(tr_time.gt(20), 0)

            # compute final SOC for the period
            socn = stack_soc.select(k).subtract(soc_chg)

            # add land cover and soc to stacks only for the last year in the
            # period
            stack_lc = stack_lc.addBands(lc_t1)
            stack_soc = stack_soc.addBands(socn)

    # compute soc percent change for the analysis period
    soc_pch = ((stack_soc.select(year_end - year_start) \
                .subtract(stack_soc.select(0))) \
               .divide(stack_soc.select(0))) \
              .multiply(100)

    logger.debug("Setting up output.")
    out = TEImage(soc_pch, [
        BandInfo("Soil organic carbon (degradation)",
                 add_to_map=True,
                 metadata={
                     'year_start': year_start,
                     'year_end': year_end
                 })
    ])

    logger.debug("Adding annual SOC layers.")
    # Output all annual SOC layers
    d_soc = []
    for year in range(year_start, year_end + 1):
        if (year == year_start) or (year == year_end):
            add_to_map = True
        else:
            add_to_map = False
        d_soc.append(
            BandInfo("Soil organic carbon",
                     add_to_map=add_to_map,
                     metadata={'year': year}))
    out.addBands(stack_soc, d_soc)

    if dl_annual_lc:
        logger.debug("Adding all annual LC layers.")
        d_lc = []
        for year in range(year_start, year_end + 1):
            d_lc.append(
                BandInfo("Land cover (7 class)", metadata={'year': year}))
        out.addBands(stack_lc, d_lc)
    else:
        logger.debug("Adding initial and final LC layers.")
        out.addBands(
            stack_lc.select(0).addBands(
                stack_lc.select(len(stack_lc.getInfo()['bands']) - 1)),
            [
                BandInfo("Land cover (7 class)", metadata={'year': year_start
                                                           }),
                BandInfo("Land cover (7 class)", metadata={'year': year_end})
            ])

    out.image = out.image.unmask(-32768).int16()

    return out
Beispiel #3
0
def land_cover(year_baseline, year_target, trans_matrix, remap_matrix,
               EXECUTION_ID, logger):
    """
    Calculate land cover indicator.
    """
    logger.debug("Entering land_cover function.")

    ## land cover
    lc = ee.Image(
        "users/geflanddegradation/toolbox_datasets/lcov_esacc_1992_2018")
    lc = lc.where(lc.eq(9999), -32768)
    lc = lc.updateMask(lc.neq(-32768))

    # Remap LC according to input matrix
    lc_remapped = lc.select('y{}'.format(year_baseline)).remap(
        remap_matrix[0], remap_matrix[1])
    for year in range(year_baseline + 1, year_target + 1):
        lc_remapped = lc_remapped.addBands(
            lc.select('y{}'.format(year)).remap(remap_matrix[0],
                                                remap_matrix[1]))

    ## target land cover map reclassified to IPCC 6 classes
    lc_bl = lc_remapped.select(0)

    ## baseline land cover map reclassified to IPCC 6 classes
    lc_tg = lc_remapped.select(len(lc_remapped.getInfo()['bands']) - 1)

    ## compute transition map (first digit for baseline land cover, and second digit for target year land cover)
    lc_tr = lc_bl.multiply(10).add(lc_tg)

    ## definition of land cover transitions as degradation (-1), improvement (1), or no relevant change (0)
    lc_dg = lc_tr.remap([
        11, 12, 13, 14, 15, 16, 17, 21, 22, 23, 24, 25, 26, 27, 31, 32, 33, 34,
        35, 36, 37, 41, 42, 43, 44, 45, 46, 47, 51, 52, 53, 54, 55, 56, 57, 61,
        62, 63, 64, 65, 66, 67, 71, 72, 73, 74, 75, 76, 77
    ], trans_matrix)

    ## Remap persistence classes so they are sequential. This
    ## makes it easier to assign a clear color ramp in QGIS.
    lc_tr = lc_tr.remap([
        11, 12, 13, 14, 15, 16, 17, 21, 22, 23, 24, 25, 26, 27, 31, 32, 33, 34,
        35, 36, 37, 41, 42, 43, 44, 45, 46, 47, 51, 52, 53, 54, 55, 56, 57, 61,
        62, 63, 64, 65, 66, 67, 71, 72, 73, 74, 75, 76, 77
    ], [
        1, 12, 13, 14, 15, 16, 17, 21, 2, 23, 24, 25, 26, 27, 31, 32, 3, 34,
        35, 36, 37, 41, 42, 43, 4, 45, 46, 47, 51, 52, 53, 54, 5, 56, 57, 61,
        62, 63, 64, 65, 6, 67, 71, 72, 73, 74, 75, 76, 7
    ])

    logger.debug("Setting up output.")
    out = TEImage(
        lc_dg.addBands(lc.select('y{}'.format(year_baseline))).addBands(
            lc.select('y{}'.format(year_target))).addBands(lc_tr), [
                BandInfo("Land cover (degradation)",
                         add_to_map=True,
                         metadata={
                             'year_baseline': year_baseline,
                             'year_target': year_target
                         }),
                BandInfo("Land cover (ESA classes)",
                         metadata={'year': year_baseline}),
                BandInfo("Land cover (ESA classes)",
                         metadata={'year': year_target}),
                BandInfo("Land cover transitions",
                         add_to_map=True,
                         metadata={
                             'year_baseline': year_baseline,
                             'year_target': year_target
                         })
            ])

    # Return the full land cover timeseries so it is available for reporting
    logger.debug("Adding annual lc layers.")
    d_lc = []
    for year in range(year_baseline, year_target + 1):
        if (year == year_baseline) or (year == year_target):
            add_to_map = True
        else:
            add_to_map = False
        d_lc.append(
            BandInfo("Land cover (7 class)",
                     add_to_map=add_to_map,
                     metadata={'year': year}))
    out.addBands(lc_remapped, d_lc)

    out.image = out.image.unmask(-32768).int16()

    return out