geeViz.changeDetectionLib¶
Apply change detection methods using Google Earth Engine.
geeViz.changeDetectionLib is the core module for setting up change
detection algorithms in GEE. It facilitates preparation, application, and
output formatting/compression/decompression of results from:
LandTrendr — annual spectral segmentation. Recommended entry points:
runLANDTRENDR()(simple one-band run) andlandtrendrWrapper()(full disturbance pipeline).VERDET — annual noise-robust segmentation. See
VERDETVertStack()andVERDETFitMagSlopeDiffCollection().CCDC — continuous change detection. See
getCCDCSegCoeffs(),annualizeCCDC(), andsimpleCCDCPredictionAnnualized().Z-score / linear-fit change — see
zAndTrendChangeDetection()andthresholdZAndTrend().
Most helpers are lower-level building blocks used by the wrappers above;
each is a thin function that operates on ee.Image / ee.ImageCollection
inputs. When calling directly, consult the LandTrendr/VERDET/CCDC upstream
docs for parameter semantics — this module mostly plumbs their outputs
into GEE-friendly shapes for visualization + export.
Palettes exposed at module level (lossYearPalette, lossMagPalette,
gainYearPalette, gainMagPalette, changeDurationPalette) match
the color conventions used by addLossGainToMap().
Functions
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Wrapper function to join annualized CCDC images from two different CCDC collections, and iterate across images and apply featherCCDCImgs function The feather years are the overlapping years between the two CCDC collections that are used in weighting |
|
|
|
Function for getting change years and magnitudes for a specified band from CCDC outputs Only change from the breaks is extracted. |
|
|
|
|
|
Function to feather two CCDC collections together based on overlapping data time periods and weights The feather years are the overlapping years between the two CCDC collections that are used in weighting |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
One-call wrapper that runs LandTrendr end-to-end on a composite collection. |
|
|
|
Multiply every band of |
|
|
|
|
|
|
|
|
|
Takes one or two raw CCDC ee.Image array outputs, an ee.ImageCollection of time images, and returns a time-series ee.ImageCollection with harmonic coefficients and fitted values |
|
|
|
|
|
|
|
|
|
|
|
Run LandTrendr on a single band with sensible defaults. |
|
|
|
|
|
|
|
Provides a time series of year and decimal days ee.ImageCollection. |
|
Takes annual time series input data, properly sets it up for LandTrendr, runs LandTrendr, and provides both a compressed vertex-only format output as well as a basic change detection output. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- geeViz.changeDetectionLib.multBands(img, distDir, by=1)[source]¶
Multiply every band of
imgbydistDir * by, preserving properties.Used to flip the sign of a spectral index when the underlying algorithm expects “up == improvement” but the index is oriented the opposite way (e.g. NBR = negative on loss). Preserves
system:time_startand all other image properties.- Parameters:
img (ee.Image) – Input image.
distDir (int) – Direction multiplier — typically
+1or-1.by (float) – Additional scalar. Default
1(no extra scaling).
- Returns:
Multiplied image with source properties preserved.
- Return type:
ee.Image
- geeViz.changeDetectionLib.rawLTToVertices(rawLT, indexName=None, multBy=10000, vertexNoData=-32768)[source]¶
- geeViz.changeDetectionLib.landtrendrWrapper(processedComposites, startYear, endYear, indexName, distDir, run_params, distParams, mmu)[source]¶
One-call wrapper that runs LandTrendr end-to-end on a composite collection.
Reorients the target index (via
distDir), runsee.Algorithms.TemporalSegmentation.LandTrendr, extracts the greatest disturbance segment per pixel, filters bydistParams, applies MMU cleaning, and converts LT’s array output back to an ImageCollection of fitted values.- Parameters:
processedComposites (ee.ImageCollection) – Annual composites (one per year) with
indexNamepresent as a band.startYear (int) – First year in the analysis window.
endYear (int) – Last year in the analysis window (inclusive).
indexName (str) – Band name to segment on (e.g.
"NBR","NDVI").distDir (int) – Orientation of the index —
-1if losses are NEGATIVE in the raw index (NDVI, NBR),+1if losses are POSITIVE (e.g. brightness, TCA-inverse).run_params (dict) – LandTrendr algorithm params. See
default_lt_run_paramsfor defaults / valid keys.distParams (dict) – Disturbance-filter thresholds. Passed through to
extractDisturbance.mmu (int) – Minimum mapping unit (pixels). Segments smaller than this are filtered.
- Returns:
[lt, distImg, fittedCollection, vertStack]lt— raw LandTrendr array output (ee.Image).distImg— greatest-disturbance image (yod/mag/dur/preval bands).fittedCollection— per-year fitted values as an ImageCollection.vertStack— vertex-stack image (year_1, year_2, …, fit_1, fit_2, …).
- Return type:
list
- geeViz.changeDetectionLib.getRawAndFittedLT(rawTs, lt, startYear, endYear, indexName='Band', distDir=-1)[source]¶
- geeViz.changeDetectionLib.runLANDTRENDR(ts, bandName, run_params=None)[source]¶
Run LandTrendr on a single band with sensible defaults.
Thin, opinionated wrapper around
ee.Algorithms.TemporalSegmentation.LandTrendr— auto-picks the sign flip for the given band (viachangeDirDict, falls back to-1), runs LandTrendr, then packages the raw output into export-ready vertex-only form viaLTExportPrep.- Parameters:
ts (ee.ImageCollection) – Annual time series (one image per year) with
bandNamepresent.bandName (str) – Band to segment (e.g.
"NBR","NDVI","tcWetness").run_params (dict, optional) – Override for LandTrendr params. If
None, usesdefault_lt_run_params.
- Returns:
- Vertex-stack image with metadata properties
bandand run_paramsset for downstream traceability.
- Vertex-stack image with metadata properties
- Return type:
ee.Image
- geeViz.changeDetectionLib.addLossGainToMap(lossGainStack, startYear, endYear, lossMagMin=-8000, lossMagMax=-2000, gainMagMin=1000, gainMagMax=8000, indexName=None, howManyToPull=None)[source]¶
- geeViz.changeDetectionLib.simpleLANDTRENDR(ts, startYear, endYear, indexName='NBR', run_params=None, lossMagThresh=-0.15, lossSlopeThresh=-0.1, gainMagThresh=0.1, gainSlopeThresh=0.1, slowLossDurationThresh=3, chooseWhichLoss='largest', chooseWhichGain='largest', addToMap=True, howManyToPull=2, multBy=10000)[source]¶
Takes annual time series input data, properly sets it up for LandTrendr, runs LandTrendr, and provides both a compressed vertex-only format output as well as a basic change detection output.
- geeViz.changeDetectionLib.LANDTRENDRVertStack(composites, indexName, run_params, startYear, endYear)[source]¶
- geeViz.changeDetectionLib.simpleLTFit(ltStack, startYear, endYear, indexName='bn', arrayMode=True, maxSegs=6, multBy=1)[source]¶
- geeViz.changeDetectionLib.batchSimpleLTFit(ltStacks, startYear, endYear, indexNames=None, bandPropertyName='band', arrayMode=True, maxSegs=6, multBy=1, mosaicReducer=<ee.reducer.Reducer object>)[source]¶
- geeViz.changeDetectionLib.convertToLossGain(ltStack, format='rawLandTrendr', lossMagThresh=-0.15, lossSlopeThresh=-0.1, gainMagThresh=0.1, gainSlopeThresh=0.1, slowLossDurationThresh=3, chooseWhichLoss='largest', chooseWhichGain='largest', howManyToPull=2)[source]¶
- geeViz.changeDetectionLib.new_interp_date(dateYr, dateCollection, max_window=10, dummyImage=None, extrapolate=True)[source]¶
- geeViz.changeDetectionLib.new_interp_date_collection(dateCollection, max_window=20, dummyImage=None, extrapolate=True)[source]¶
- geeViz.changeDetectionLib.prepTimeSeriesForVerdet(ts, indexName, run_params, correctionFactor)[source]¶
- geeViz.changeDetectionLib.VERDETVertStack(ts, indexName, run_params={'alpha': 0.1, 'tolerance': 0.0001}, maxSegments=10, correctionFactor=1, doLinearInterp='false')[source]¶
- geeViz.changeDetectionLib.VERDETFitMagSlopeDiffCollection(composites, indexName, run_params={'alpha': 0.1, 'tolerance': 0.0001}, maxSegments=10, correctionFactor=1, doLinearInterp='false', masks=None)[source]¶
- geeViz.changeDetectionLib.verdetAnnualSlope(tsIndex, indexName, startYear, endYear, alpha, tolerance=0.0001)[source]¶
- geeViz.changeDetectionLib.zAndTrendChangeDetection(allScenes, indexNames, nDays, startYear, endYear, startJulian, endJulian, baselineLength=5, baselineGap=1, epochLength=5, zReducer=<ee.reducer.Reducer object>, useAnnualMedianForTrend=True, exportImages=False, exportPathRoot='users/iwhousman/test/ChangeCollection', studyArea=None, scale=30, crs=None, transform=None, minBaselineObservationsNeeded=10)[source]¶
- geeViz.changeDetectionLib.thresholdZAndTrend(zAndTrendCollection, zThresh, slopeThresh, startYear, endYear, negativeOrPositiveChange=None)[source]¶
- geeViz.changeDetectionLib.simpleCCDCPrediction(img, timeBandName, whichHarmonics, whichBands)[source]¶
- geeViz.changeDetectionLib.annualizeCCDC(ccdcImg, startYear, endYear, startJulian, endJulian, tEndExtrapolationPeriod, yearStartMonth=9, yearStartDay=1, annualizeWithCompositeDates=False, compositeCollection=None, interpolateCompositeDates=True)[source]¶
- geeViz.changeDetectionLib.predictCCDC(ccdcImg: list[Image, Image] | Image, timeImgs: ImageCollection, fillGaps: bool = True, whichHarmonics: list[int] = [1, 2, 3], featherStartYr: int = 2015, featherEndYr: int = 2021) ImageCollection[source]¶
Takes one or two raw CCDC ee.Image array outputs, an ee.ImageCollection of time images, and returns a time-series ee.ImageCollection with harmonic coefficients and fitted values
- Parameters:
ccdcImg (list[ee.Image, ee.Image] | ee.Image) – A raw CCDC ee.Image array or list of two raw CCDC ee.Image arrays. If a list of 2 images is provided, feathering will automatically be performed. Note that any pixel that is null in either CCDC image will result in a null value in the predicted output.
timeImgs (ee.ImageCollection) – An ee.ImageCollection of time images usually from functions such as simpleGetTimeImageCollection.
fillGaps (bool, optional) – Whether to fill gaps between segments. If false, outputs can have blank values mid time-series. Defaults to True.
whichHarmonics (list[int], optional) – Which harmonics to include in fitted outputs forreturned time-series. Defaults to [1,2,3].
featherStartYear (int, optional) – If a list of 2 images is provided as ccdcImg, this is the first year of the window used for feathering the two time-series together. Defaults to 2015.
featherEndYear (int, optional) – If a list of 2 images is provided as ccdcImg, this is the last year (inclusive) of the window used for feathering the two time-series together. Defaults to 2021.
- Returns:
A collection of CCDC coefficients and fitted values.
- Return type:
ee.ImageCollection
>>> import geeViz.changeDetectionLib as cdl >>> Map = cdl.Map >>> ee = cdl.ee >>> ccdcBandNames = ["tStart", "tEnd", "tBreak", "changeProb", "swir1.*", "NDVI.*"] >>> timeImgs = cdl.simpleGetTimeImageCollection(startYear=1984, endYear=2024, startJulian=1, endJulian=365, step=0.1) >>> ccdcImg1 = ee.ImageCollection("projects/lcms-292214/assets/CONUS-LCMS/Base-Learners/CCDC-Collection-1984-2022").select(ccdcBandNames).mosaic() >>> ccdcImg2 = ee.ImageCollection("projects/lcms-292214/assets/CONUS-LCMS/Base-Learners/CCDC-Feathered-Collection").select(ccdcBandNames).mosaic() >>> fittedFeathered = cdl.predictCCDC(ccdcImg=[ccdcImg1, ccdcImg2], timeImgs=timeImgs, fillGaps=True, whichHarmonics=[1, 2, 3], featherStartYr=2015, featherEndYr=2021) >>> Map.addLayer(fittedFeathered.select([".*_CCDC_fitted"]), {"reducer": ee.Reducer.mean(), "min": 0.3, "max": 0.8}, "Combined CCDC", True) >>> Map.turnOnInspector() >>> Map.setCenter(-88, 36, 12) >>> Map.view()
- geeViz.changeDetectionLib.getTimeImageCollection(startYear, endYear, startJulian=1, endJulian=365, step=0.1, yearStartMonth=1, yearStartDay=1)[source]¶
- geeViz.changeDetectionLib.simpleGetTimeImageCollection(startYear: int, endYear: int, startJulian: int = 1, endJulian: int = 365, step: float = 0.1)[source]¶
Provides a time series of year and decimal days ee.ImageCollection. This is useful for CCDC predictions
- Parameters:
startYear (int) – The starting year for returned time-series.
endYear (int) – The ending year for the returned time-series.
startJulian (int) – The starting Julian day of year for returned time-series (1-365).
endJulian (int) – The ending Julian day of year for returned time-series (1-365).
step (float, optional) – Fraction of a year for each output in returned time-series (~0.01-1). Defaults to 0.1.
- Returns:
A collection of time images.
- Return type:
ee.ImageCollection
>>> import geeViz.changeDetectionLib as cdl >>> Map = cdl.Map >>> ee = cdl.ee >>> timeImgs = cdl.simpleGetTimeImageCollection(startYear = 1984, endYear = 2024, startJulian = 1, endJulian = 365, step = 0.1) >>> Map.addLayer(timeImgs, {}, "Time Images", True) >>> Map.turnOnInspector() >>> Map.view()
- geeViz.changeDetectionLib.getTimeImageCollectionFromComposites(compositeCollection, startYear=None, endYear=None, interpolate=True, useNewInterpMethod=False)[source]¶
- geeViz.changeDetectionLib.ccdcChangeDetection(ccdcImg: list[Image, Image] | Image, bandName: str, startYear: None | int = None, endYear: None | int = None) dict[source]¶
Function for getting change years and magnitudes for a specified band from CCDC outputs Only change from the breaks is extracted. As of now, if a segment has a high slope value, this method will not extract that. If combining two CCDC raw outputs provide them as a list of two images for the ccdcImg parameter.
- Parameters:
ccdcImg (list[ee.Image, ee.Image] | ee.Image) – A raw CCDC ee.Image array or list of two raw CCDC ee.Image arrays. If a list of 2 images is provided, they will automatically be combined.
bandName (str) – The band name to use for magnitude of change.
startYear (None | int) – The start of the time window. If left as None, all years in the input CCDC images will be included. Defaults to None.
endYear (None | int) – The end of the time window (inclusive). If left as None, all years in the input CCDC images will be included. Defaults to None.
- Returns:
A dictionary of various CCDC change metrics.
- Return type:
dict
>>> import geeViz.changeDetectionLib as cdl >>> Map = cdl.Map >>> ee = cdl.ee >>> changeDetectionBandName = "NDVI" >>> ccdcChangeBandNames = ["tBreak", "changeProb", f"{changeDetectionBandName}.*"] >>> sortingMethod = "mostRecent" >>> ccdcImg1 = ee.ImageCollection("projects/lcms-292214/assets/CONUS-LCMS/Base-Learners/CCDC-Collection-1984-2022").select(ccdcChangeBandNames).mosaic() >>> ccdcImg2 = ee.ImageCollection("projects/lcms-292214/assets/CONUS-LCMS/Base-Learners/CCDC-Feathered-Collection").select(ccdcChangeBandNames).mosaic() >>> changeObjCombined = cdl.ccdcChangeDetection([ccdcImg1, ccdcImg2], changeDetectionBandName) >>> Map.addLayer(changeObjCombined[sortingMethod]["loss"]["year"], {"min": 1984, "max": 2024, "palette": cdl.lossYearPalette}, "Loss Year") >>> Map.addLayer(changeObjCombined[sortingMethod]["loss"]["mag"], {"min": -0.5, "max": -0.1, "palette": cdl.lossMagPalette}, "Loss Mag", False) >>> Map.addLayer(changeObjCombined[sortingMethod]["gain"]["year"], {"min": 1984, "max": 2024, "palette": cdl.gainYearPalette}, "Gain Year") >>> Map.addLayer(changeObjCombined[sortingMethod]["gain"]["mag"], {"min": 0.05, "max": 0.2, "palette": cdl.gainMagPalette}, "Gain Mag", False) >>> Map.turnOnInspector() >>> Map.setCenter(-88, 36, 12) >>> Map.view()
- geeViz.changeDetectionLib.featherCCDCImgs(joinedCCDCImg: Image, ccdcBnds: list | List, coeffs1_bns: list | List, coeffs2_bns: list | List, featherStartYr: int, featherEndYr: int) Image[source]¶
Function to feather two CCDC collections together based on overlapping data time periods and weights The feather years are the overlapping years between the two CCDC collections that are used in weighting
- geeViz.changeDetectionLib.batchFeatherCCDCImgs(ccdcAnnualizedCol1: ImageCollection, ccdcAnnualizedCol2: ImageCollection, featherStartYr: int, featherEndYr: int) ImageCollection[source]¶
Wrapper function to join annualized CCDC images from two different CCDC collections, and iterate across images and apply featherCCDCImgs function The feather years are the overlapping years between the two CCDC collections that are used in weighting