Forest Loss and Gain Misread

On this page

Problem statement

The analysis subtracted the gain layer from the loss layer and reported net forest change. Or it counted "forest in 2015" as all pixels with more than 30% cover in 2000 and a loss year after 2015, and got more forest than the region's land. Or it reported a pixel lost in 2005 and regrown by 2012 as forest again in 2024. Each follows from reading the Global Forest Change layers as a complete forest history, which they are not.

Three facts prevent all of these: loss records only the first stand-replacing event per pixel; gain is a single undated flag for 2000–2012; and a lossyear of 0 means "no loss detected", not "no data".

Quick answer

Keep loss and gain separate, derive forest at a date from the 2000 baseline and loss only, and never subtract gain from loss:

import numpy as np, rasterio
from rasterio.windows import from_bounds

V, TILE = "GFC-2024-v1.12", "10S_070W"
W, S, E, N = -63.0, -10.8, -62.5, -10.3
def layer(name):
    with rasterio.open(f"/vsicurl/https://storage.googleapis.com/earthenginepartners-hansen/"
                       f"{V}/Hansen_{V}_{name}_{TILE}.tif") as src:
        return src.read(1, window=from_bounds(W, S, E, N, src.transform))
tc, ly, gain, dm = (layer(n) for n in ("treecover2000", "lossyear", "gain", "datamask"))
px_ha = 0.00025 * 111_320 * np.cos(np.radians(10.55)) * 0.00025 * 110_574 / 1e4   # ~27.4 × 27.6 m

forest2000 = (tc > 30) & (dm == 1)
loss = forest2000 & (ly > 0)
g = gain == 1
print(f"forest 2000: {forest2000.sum() * px_ha:,.0f} ha")
print(f"loss 2001–2024 on it: {loss.sum() * px_ha:,.0f} ha")
print(f"gain 2000–2012 (anywhere): {g.sum() * px_ha:,.0f} ha")
print(f"'net change' = gain − loss: {(g.sum() - loss.sum()) * px_ha:,.0f} ha   <- not a valid quantity")
print(f"gain pixels that also have a loss year: {(g & (ly > 0)).sum() * px_ha:,.0f} ha")
forest 2000: 139,689 ha
loss 2001–2024 on it: 61,306 ha
gain 2000–2012 (anywhere): 2,183 ha
'net change' = gain − loss: -59,122 ha   <- not a valid quantity
gain pixels that also have a loss year: 1,281 ha

The subtraction mixes a 2000–2012 flag with a 2001–2024 record, measured by different methods over different periods. The result has a unit and no meaning — and more than half of the gain area here, 1,281 of 2,183 ha, is on pixels that also carry a loss year, so the two layers are not even describing separate land.

Close-up map of forest in Rondônia: standing forest in teal, forest lost since 2000 in red, and small patches of gain in blue and purple, many of them inside areas marked lost, with a solid purple block in the south-west corner. Close-up map of forest in Rondônia: standing forest in teal, forest lost since 2000 in red, and small patches of gain in blue and purple, many of them inside areas marked lost, with a solid purple block in the south-west corner.
The 0.1° block of the window with the most gain. The red is loss since 2001; the gain is small and patchy, and most of it (purple) sits on pixels that also carry a loss year — regrowth before 2012 that was cleared again later, or the other way round. Across the window those pixels are 1,281 of the 2,183 ha of gain, which is why gain cannot be netted off against loss.

Forest at a date from the baseline, gain as older

1. Derive forest at a date from the baseline

Forest in year Y is forest in 2000 minus pixels lost in 2001…Y. Nothing in the data adds forest back after 2012.

2. Treat gain as a separate, older signal

Gain marks pixels where tree cover established between 2000 and 2012. It has no year and is not updated. Use it to describe regrowth in that period, not to offset later loss.

3. Remember loss is recorded once

A pixel cleared, regrown and cleared again shows only the first loss. Loss statistics undercount repeated clearing of regrowth.

4. Read 0 as "no loss detected"

Water and no-data are in datamask, not in lossyear. Mask with datamask before counting non-loss as forest.

5. For net change, use a product built for it

Land cover time series or dedicated forest-extent products model gains and losses consistently over time.

One pixel cleared in 2005, regrowing, and cleared again in 2020, with what the loss and gain layers record. one pixel, two numbers kept2000forest (tree cover)2005cleared: lossyear = 52008–12regrowth: gain = 12020again: unrecordedMore than half the gain area also carries a loss year spatialworkflow.io
One pixel's history, and the two numbers the dataset keeps of it.

Forest at a date, done wrong and right

Example 1 — forest at a date, done wrong and right

def forest_in(year):
    return forest2000 & ((ly == 0) | (ly > year - 2000))
wrong = forest2000 & (ly > 2015 - 2000)                  # forgets the pixels never lost
print(f"forest 2015, correct: {forest_in(2015).sum() * px_ha:,.0f} ha")
print(f"forest 2015, 'loss after 2015' only: {wrong.sum() * px_ha:,.0f} ha")
forest 2015, correct: 96,245 ha
forest 2015, 'loss after 2015' only: 17,862 ha

Pixels with lossyear 0 were never lost and are the bulk of remaining forest; a condition that only looks at later loss years leaves them out.

Example 2 — regrowth the data cannot see

early = forest2000 & (ly >= 1) & (ly <= 5)
print(f"forest cleared 2001–05: {early.sum() * px_ha:,.0f} ha")
print(f"flagged as gain 2000–12: {(early & g).sum() * px_ha:,.0f} ha "
      f"({(early & g).sum() / early.sum():.1%})")
print("regrowth after 2012, and second clearings of it, are not in the data at all")
forest cleared 2001–05: 28,323 ha
flagged as gain 2000–12: 513 ha (1.8%)
regrowth after 2012, and second clearings of it, are not in the data at all

Only a small share of early clearings carries the gain flag; whether the rest stayed pasture or regrew after 2012 cannot be read from these layers. A canopy height map or land cover time series can answer it.

Example 3 — the datamask

print(f"pixels: land {np.mean(dm == 1):.1%}, water {np.mean(dm == 2):.1%}, no data {np.mean(dm == 0):.1%}")
print(f"'not lost' including water: {(ly == 0).mean():.1%}; on land only: {((ly == 0) & (dm == 1)).mean():.1%}")
pixels: land 100.0%, water 0.0%, no data 0.0%
'not lost' including water: 78.6%; on land only: 78.6%

This window happens to contain no mapped water, so the two shares agree to the decimal — which is exactly how the land mask gets forgotten: code tested on a dry window gives the right answer. Water pixels have a loss year of 0 too, and on a window with rivers or reservoirs, counting "never lost" without the land mask adds them to the unchanged forest.

Common misreadings of the Global Forest Change loss and gain layers with the correct reading. four misreadings of two layersmisreadingcorrect readingnet = gain − lossdifferent periods → reportseparatelyforest = lossyear > Yforgets 0 → (ly == 0) | (ly > Y)regrowth after 2012 in gaingain stops in 2012never lost = forestmask water with datamaskForest in year Y is the 2000 baseline minus loss to Y, nothing added back spatialworkflow.io
Four misreadings of two layers.

Why gain stops in 2012

Why gain stops in 2012

Detecting new canopy needs years of growth to register in Landsat time series. The original analysis mapped gain for its 12-year window; later releases extended loss annually but did not extend gain in the same way. Regrowth has since been mapped in separate products with different methods.

Why only one loss per pixel

The loss layer stores a single year per pixel — the first detected stand-replacement event. Encoding repeated events would need a different data structure. The consequence is that land in rotation — shifting cultivation, plantations, repeatedly burned regrowth — is undercounted after its first event.

Why net change needs consistent methods

Net change is the difference between two forest extents measured the same way. Loss and gain here are measured differently, over different periods, and gain is incomplete. Their difference is not a forest extent change.

Forest in 2015 computed correctly and with a condition that only looks at later loss years. forest in 2015, hacorrect96,245 halossyear > 1517,862 ha — forgets 0060k120kPixels never lost are the bulk of the remaining forest spatialworkflow.io
One missing condition drops four-fifths of the forest.

Same-pixel loss and gain, and plantation cycles

  • Loss and gain on the same pixel is possible: gain before 2012, loss after.
  • Plantation cycles appear as loss once, then nothing, whatever happens later.
  • Version updates can change loss years for recent years; they do not add gain.
  • Tree cover 2010 exists in some releases as a separate layer with its own caveats.
  • Forest extent products from national monitoring systems usually include regrowth rules.

FAQ

Can I compute net forest change from Hansen gain and loss?

No. Gain is an undated 2000–2012 flag; loss is annual from 2001. Their difference is not meaningful.

How do I get forest cover in a given year?

Forest in 2000 above your threshold, minus pixels with a loss year up to that year.

Does lossyear 0 mean forest?

It means no loss was detected. Combine it with the 2000 baseline and the land mask.

Can a pixel be lost twice?

Only the first loss is recorded.

Does the data show regrowth after 2012?

No. Use canopy height or land cover time series.

What does the gain layer mean?

Tree cover gain detected between 2000 and 2012, without a year.