Giter VIP home page Giter VIP logo

sankee's Introduction

sankee

Earth Engine Python Binder conda-forge link conda-forge link Testing workflow codecov Read the Docs Downloads

Visualize changes in classified time series data with interactive Sankey plots in Google Earth Engine

Sankee example showing grassland expansion in the Nile Delta

Description

Use Earth Engine to visualize changes in land cover, plant health, burn severity, or any other time series of classified imagery with interactive Sankey plots. Use a library of built-in datasets for convenience or define your own custom datasets for flexibility.

Installation

Pip

pip install sankee

Conda

conda install -c conda-forge sankee

Quickstart

Premade Datasets

Visualize annual changes in land cover using popular LULC datasets with a couple lines of code. Just choose a dataset, an area of interest, and a list of years to generate a Sankey diagram from a premade dataset. Below, we can look at 30 years of vegetation recovery in the area devastated by the Mt. St. Helens eruption.

import sankee
import ee

ee.Initialize()

sankee.datasets.LCMS_LC.sankify(
  years=[1990, 2000, 2010, 2020],
  region=ee.Geometry.Point([-122.192688, 46.25917]).buffer(2000),
  max_classes=3,
  title="Mt. St. Helens Recovery"
)

Proportions of land cover over 4 periods increase from barren to grass and tree cover in a Sankey diagram

Check out the example notebook for an interactive demo.

Custom Datasets

Any classified images can be used by defining the dataset parameters (which pixel values correspond to which labels and colors). For example, we can look at classified Dynamic World scenes just two weeks apart that show substantial snow loss on Mountain Jefferson during the 2021 Heat Dome in the Pacific Northwest.

import sankee
import ee

ee.Initialize()

# Load a set of classified images
img_list = [
    ee.Image("GOOGLE/DYNAMICWORLD/V1/20210616T185919_20210616T190431_T10TEQ"),
    ee.Image("GOOGLE/DYNAMICWORLD/V1/20210706T185919_20210706T190638_T10TEQ")
]

# Which band contains the classified data?
band = "label"

# What labels correspond to which pixel values?
labels = {
    0: "Water", 1: "Trees", 2: "Grass", 3: "Flooded", 4: "Crops",
    5: "Shrub / Scrub", 6: "Build", 7: "Bare", 8: "Snow / Ice",
}

# What colors should be applied to which pixel values?
palette = {
    0: "#419BDF", 1: "#397D49", 2: "#88B053", 3: "#7A87C6", 4: "#E49635",
    5: "#DFC35A", 6: "#C4281B", 7: "#A59B8F", 8: "#B39FE1"
}

plot = sankee.sankify(
    image_list=img_list, 
    band=band, 
    labels=labels,
    palette=palette,
    region=ee.Geometry.Point([-121.80183, 44.67655]).buffer(3000), 
    max_classes=3,
    title="Mt. Jefferson Snow Loss - June 2021"
)

Integration with geemap

sankee premade datasets are usable through the geemap interactive GUI. Check out the documentation and video tutorials by @giswqs.

Contributing

If you find bugs or have feature requests, please open an issue!


Top

sankee's People

Contributors

aazuspan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

sankee's Issues

Allow labeling links by percent or count

Instead of labeling links by their class name, it would be nice to have the option to label them by sampled abundance. To do that, I could add a label_type parameter to sankify that would default to class.

Sample output with percent:

image

Make docs

  • Make official API documentation and deploy.

Docs build failing

Getting a weird failure building docs on readthedocs. Timeline below:

  • Built fine on 2023-03-10
  • Merged the theme branch b21cd20 which didn't touch the docs
  • Fails to build on 2023-03-12 due to a parsing error with one of my example notebooks.
reading sources... [ 28%] examples/custom_landsat_ndvi
pandoc: Unknown extension: smart

...

json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

The notebook that fails to parse hasn't been touched in 8 months, and the docs configs haven't changed either. Maybe this is on readthedocs's end, but I don't see any relevant recent issues there. Docs build fine locally. I'll give it a few days to see if it resolves or something shows up in their issues.

Contingency tables

Really loving how easy to use Sankee is - great work sir!

I was previously hacking around producing a frequencyHistogram() of pixel counts per landuse class to describe the changes between two images. Then using the R package OpenLand to produce a sankee diagram from the resulting featurecollection. Needless to say this was many more lines of code than I now need with sankee!

If I had to request a feature though it would be to be able to output a contingency table (data.frame) of the actual aggregate values i.e. either sum of pixel counts and/or areas (km2) of the transitions from one land use class to another between images. Would that be an easy addition?

Customize plot size

I am trying to display the sankee plot directly within the map. As can be seen from the screenshot below, only a portion of the plot is visible due to the limited size of the hosting widget. It would be great if sankee can support customizing plot size so that it can fit into the hosting widget.

image

Replace dev tools with `ruff`

I can swap out isort, flake8, and pyupgrade for ruff, simplifying tooling and configuration while improving performance 🚀

Non-transparent plot background

The switch from go.Figure to go.FigureWidget to include interactive buttons caused an unintended side effect of changing plot background color from transparent to white. This is caused by an inconsistency between the two classes (see plotly/plotly.py#3811).

If there's not a workaround or fix, we may just have to live with an opaque background. I guess there are worse things.

Deprecation warning for Pandas `groupby` functions

Running modis_snow_and_ice in Binder gives the following warning when you run dataset.sankify:

/srv/conda/envs/notebook/lib/python3.8/site-packages/sankee/plotting.py:153: FutureWarning:

The default value of numeric_only in DataFrameGroupBy.mean is deprecated. In a future version, numeric_only will default to False. Either specify numeric_only or select only columns which should be valid for the function.

/srv/conda/envs/notebook/lib/python3.8/site-packages/sankee/plotting.py:159: FutureWarning:

The default value of numeric_only in DataFrameGroupBy.sum is deprecated. In a future version, numeric_only will default to False. Either specify numeric_only or select only columns which should be valid for the function.

This happens within SankeyPlot.get_sorted_classes. I'm guessing I intentionally dropped some non-numeric columns that weren't needed, but I'll need to clean that up.

`KeyError` during data collection caused by mixed data types

Currently, the second example in the readme (code below) throws a KeyError when the max_classes are filtered

# Load a set of classified images
img_list = [
    ee.Image("GOOGLE/DYNAMICWORLD/V1/20210616T185919_20210616T190431_T10TEQ"),
    ee.Image("GOOGLE/DYNAMICWORLD/V1/20210706T185919_20210706T190638_T10TEQ")
]

# Which band contains the classified data?
band = "label"

# What labels correspond to which pixel values?
labels = {
    0: "Water", 1: "Trees", 2: "Grass", 3: "Flooded", 4: "Crops",
    5: "Shrub / Scrub", 6: "Build", 7: "Bare", 8: "Snow / Ice",
}

# What colors should be applied to which pixel values?
palette = {
    0: "#419BDF", 1: "#397D49", 2: "#88B053", 3: "#7A87C6", 4: "#E49635",
    5: "#DFC35A", 6: "#C4281B", 7: "#A59B8F", 8: "#B39FE1"
}

plot = sankee.sankify(
    image_list=img_list, 
    band=band, 
    labels=labels,
    palette=palette,
    region=ee.Geometry.Point([-121.80183, 44.67655]).buffer(3000), 
    max_classes=3,
    title="Mt. Jefferson Snow Loss - June 2021"
)

The root cause seems to be that sampling.collect_sankee_data returns mixed datatypes due to NaN sampled values. Casting to int after removing NaNs should resolve this.

Add LCMS datasets

  • Add builtin datasets for the LCMS land cover and land use bands
  • Update docs to include LCMS

[BUG] Unhelpful error when no data is sampled

If no data is sampled (for example if the sampling region is outside of the image bounds), a very unhelpful exception is thrown. If all of the sample points can't be extracted, raise a more helpful error.

To recreate, use the CONUS LCMS image collection outside of the CONUS.

Store sampled points in `SankeyPlot`

Being able to access the points that were used to sample the Sankey data might be useful (or at least interesting), and wouldn't require much work. Just need to refactor to generate the random points outside of the sampling function and pass them in. That change would also make it trivial to allow user-defined points, which could be worth adding in the future.

Drop 3.7 support

3.7 is EOL, so let's drop it from project metadata and from CI testing.

All available datasets in the GEE Catalog? :)

Hi, @aazuspan!

I was using sankee and it is amazing!

I was thinking that maybe it could be possible to add all datasets in the GEE Catalog that are Land Cover Classifications, or at least discrete products. Here is the idea!

If we take the Copernicus CORINE Land Cover Product as an example and get the STAC info, we can see that in the summaries property there is a eo:bands property. This property describes all the bands of the collection. If the band is a discrete band, it will have a gee:classes property explaining the color, the description and the value!

import ee, eemont

ee.Initialize()

ee.ImageCollection("COPERNICUS/CORINE/V20/100m").getSTAC()["summaries"]["eo:bands"]
[{'description': 'Land cover',
  'gee:classes': [{'color': 'E6004D',
    'description': 'Artificial surfaces > Urban fabric > Continuous urban fabric',
    'value': 111},
   {'color': 'FF0000',
    'description': 'Artificial surfaces > Urban fabric > Discontinuous urban fabric',
    'value': 112},
   {'color': 'CC4DF2',
    'description': 'Artificial surfaces > Industrial, commercial, and transport units > Industrial or commercial units',
    'value': 121},
   {'color': 'CC0000',
    'description': 'Artificial surfaces > Industrial, commercial, and\ntransport units > Road and rail networks and associated land\n',
    'value': 122},
   {'color': 'E6CCCC',
    'description': 'Artificial surfaces > Industrial, commercial, and transport units > Port areas',
    'value': 123},
   {'color': 'E6CCE6',
    'description': 'Artificial surfaces > Industrial, commercial, and transport units > Airports',
    'value': 124},
   {'color': 'A600CC',
    'description': 'Artificial surfaces > Mine, dump, and construction sites > Mineral extraction sites',
    'value': 131},
   {'color': 'A64DCC',
    'description': 'Artificial surfaces > Mine, dump, and construction sites > Dump sites',
    'value': 132},
   {'color': 'FF4DFF',
    'description': 'Artificial surfaces > Mine, dump, and construction sites > Construction sites',
    'value': 133},
   {'color': 'FFA6FF',
    'description': 'Artificial surfaces > Artificial, non-agricultural vegetated areas > Green urban areas',
    'value': 141},
   {'color': 'FFE6FF',
    'description': 'Artificial surfaces > Artificial, non-agricultural vegetated areas > Sport and leisure facilities',
    'value': 142},
   {'color': 'FFFFA8',
    'description': 'Agricultural areas > Arable land > Non-irrigated arable land',
    'value': 211},
   {'color': 'FFFF00',
    'description': 'Agricultural areas > Arable land > Permanently irrigated land',
    'value': 212},
   {'color': 'E6E600',
    'description': 'Agricultural areas > Arable land > Rice fields',
    'value': 213},
   {'color': 'E68000',
    'description': 'Agricultural areas > Permanent crops > Vineyards',
    'value': 221},
   {'color': 'F2A64D',
    'description': 'Agricultural areas > Permanent crops > Fruit trees and berry plantations',
    'value': 222},
   {'color': 'E6A600',
    'description': 'Agricultural areas > Permanent crops > Olive groves',
    'value': 223},
   {'color': 'E6E64D',
    'description': 'Agricultural areas > Pastures > Pastures',
    'value': 231},
   {'color': 'FFE6A6',
    'description': 'Agricultural areas > Heterogeneous agricultural areas > Annual crops associated with permanent crops',
    'value': 241},
   {'color': 'FFE64D',
    'description': 'Agricultural areas > Heterogeneous agricultural areas > Complex cultivation patterns',
    'value': 242},
   {'color': 'E6CC4D',
    'description': 'Agricultural areas > Heterogeneous agricultural areas >\nLand principally occupied by agriculture, with significant areas of\nnatural vegetation\n',
    'value': 243},
   {'color': 'F2CCA6',
    'description': 'Agricultural areas > Heterogeneous agricultural areas > Agro-forestry areas',
    'value': 244},
   {'color': '80FF00',
    'description': 'Forest and semi natural areas > Forests > Broad-leaved forest',
    'value': 311},
   {'color': '00A600',
    'description': 'Forest and semi natural areas > Forests > Coniferous forest',
    'value': 312},
   {'color': '4DFF00',
    'description': 'Forest and semi natural areas > Forests > Mixed forest',
    'value': 313},
   {'color': 'CCF24D',
    'description': 'Forest and semi natural areas > Scrub and/or herbaceous vegetation associations > Natural grasslands',
    'value': 321},
   {'color': 'A6FF80',
    'description': 'Forest and semi natural areas > Scrub and/or herbaceous vegetation associations > Moors and heathland',
    'value': 322},
   {'color': 'A6E64D',
    'description': 'Forest and semi natural areas > Scrub and/or herbaceous\nvegetation associations > Sclerophyllous vegetation\n',
    'value': 323},
   {'color': 'A6F200',
    'description': 'Forest and semi natural areas > Scrub and/or herbaceous\nvegetation associations > Transitional woodland-shrub\n',
    'value': 324},
   {'color': 'E6E6E6',
    'description': 'Forest and semi natural areas > Open spaces with little or no vegetation > Beaches, dunes, sands',
    'value': 331},
   {'color': 'CCCCCC',
    'description': 'Forest and semi natural areas > Open spaces with little or no vegetation > Bare rocks',
    'value': 332},
   {'color': 'CCFFCC',
    'description': 'Forest and semi natural areas > Open spaces with little or no vegetation > Sparsely vegetated areas',
    'value': 333},
   {'color': '000000',
    'description': 'Forest and semi natural areas > Open spaces with little or no vegetation > Burnt areas',
    'value': 334},
   {'color': 'A6E6CC',
    'description': 'Forest and semi natural areas > Open spaces with little or no vegetation > Glaciers and perpetual snow',
    'value': 335},
   {'color': 'A6A6FF',
    'description': 'Wetlands > Inland wetlands > Inland marshes',
    'value': 411},
   {'color': '4D4DFF',
    'description': 'Wetlands > Inland wetlands > Peat bogs',
    'value': 412},
   {'color': 'CCCCFF',
    'description': 'Wetlands > Maritime wetlands > Salt marshes',
    'value': 421},
   {'color': 'E6E6FF',
    'description': 'Wetlands > Maritime wetlands > Salines',
    'value': 422},
   {'color': 'A6A6E6',
    'description': 'Wetlands > Maritime wetlands > Intertidal flats',
    'value': 423},
   {'color': '00CCF2',
    'description': 'Water bodies > Inland waters > Water courses',
    'value': 511},
   {'color': '80F2E6',
    'description': 'Water bodies > Inland waters > Water bodies',
    'value': 512},
   {'color': '00FFA6',
    'description': 'Water bodies > Marine waters > Coastal lagoons',
    'value': 521},
   {'color': 'A6FFE6',
    'description': 'Water bodies > Marine waters > Estuaries',
    'value': 522},
   {'color': 'E6F2FF',
    'description': 'Water bodies > Marine waters > Sea and ocean',
    'value': 523}],
  'name': 'landcover'}]

Check it now for MODIS:

ee.ImageCollection("MODIS/006/MCD12Q1").getSTAC()["summaries"]["eo:bands"]
[{'description': 'Land Cover Type 1: Annual International Geosphere-Biosphere Programme (IGBP) classification',
  'gee:classes': [{'color': '05450a',
    'description': 'Evergreen Needleleaf Forests: dominated by evergreen\nconifer trees (canopy >2m). Tree cover >60%.',
    'value': 1},
   {'color': '086a10',
    'description': 'Evergreen Broadleaf Forests: dominated by evergreen\nbroadleaf and palmate trees (canopy >2m). Tree cover >60%.\n',
    'value': 2},
   {'color': '54a708',
    'description': 'Deciduous Needleleaf Forests: dominated by deciduous\nneedleleaf (larch) trees (canopy >2m). Tree cover >60%.\n',
    'value': 3},
   {'color': '78d203',
    'description': 'Deciduous Broadleaf Forests: dominated by deciduous\nbroadleaf trees (canopy >2m). Tree cover >60%.',
    'value': 4},
   {'color': '009900',
    'description': 'Mixed Forests: dominated by neither deciduous nor\nevergreen (40-60% of each) tree type (canopy >2m). Tree cover >60%.\n',
    'value': 5},
   {'color': 'c6b044',
    'description': 'Closed Shrublands: dominated by woody perennials\n(1-2m height) >60% cover.',
    'value': 6},
   {'color': 'dcd159',
    'description': 'Open Shrublands: dominated by woody perennials\n(1-2m height) 10-60% cover.',
    'value': 7},
   {'color': 'dade48',
    'description': 'Woody Savannas: tree cover 30-60% (canopy >2m).',
    'value': 8},
   {'color': 'fbff13',
    'description': 'Savannas: tree cover 10-30% (canopy >2m).',
    'value': 9},
   {'color': 'b6ff05',
    'description': 'Grasslands: dominated by herbaceous annuals (<2m).',
    'value': 10},
   {'color': '27ff87',
    'description': 'Permanent Wetlands: permanently inundated lands with\n30-60% water cover and >10% vegetated cover.',
    'value': 11},
   {'color': 'c24f44',
    'description': 'Croplands: at least 60% of area is cultivated\ncropland.',
    'value': 12},
   {'color': 'a5a5a5',
    'description': 'Urban and Built-up Lands: at least 30% impervious\nsurface area including building materials, asphalt and vehicles.\n',
    'value': 13},
   {'color': 'ff6d4c',
    'description': 'Cropland/Natural Vegetation Mosaics: mosaics of\nsmall-scale cultivation 40-60% with natural tree, shrub, or herbaceous\nvegetation.\n',
    'value': 14},
   {'color': '69fff8',
    'description': 'Permanent Snow and Ice: at least 60% of area is covered\nby snow and ice for at least 10 months of the year.\n',
    'value': 15},
   {'color': 'f9ffa4',
    'description': 'Barren: at least 60% of area is non-vegetated barren\n(sand, rock, soil) areas with less than 10% vegetation.\n',
    'value': 16},
   {'color': '1c0dff',
    'description': 'Water Bodies: at least 60% of area is covered by\npermanent water bodies.',
    'value': 17}],
  'name': 'LC_Type1'},
 {'description': 'Land Cover Type 2: Annual University of Maryland (UMD) classification',
  'gee:classes': [{'color': '1c0dff',
    'description': 'Water Bodies: at least 60% of area is covered by\npermanent water bodies.',
    'value': 0},
   {'color': '05450a',
    'description': 'Evergreen Needleleaf Forests: dominated by evergreen\nconifer trees (canopy >2m). Tree cover >60%.',
    'value': 1},
   {'color': '086a10',
    'description': 'Evergreen Broadleaf Forests: dominated by evergreen\nbroadleaf and palmate trees (canopy >2m). Tree cover >60%.\n',
    'value': 2},
   {'color': '54a708',
    'description': 'Deciduous Needleleaf Forests: dominated by deciduous\nneedleleaf (larch) trees (canopy >2m). Tree cover >60%.\n',
    'value': 3},
   {'color': '78d203',
    'description': 'Deciduous Broadleaf Forests: dominated by deciduous\nbroadleaf trees (canopy >2m). Tree cover >60%.',
    'value': 4},
   {'color': '009900',
    'description': 'Mixed Forests: dominated by neither deciduous nor\nevergreen (40-60% of each) tree type (canopy >2m). Tree cover >60%.\n',
    'value': 5},
   {'color': 'c6b044',
    'description': 'Closed Shrublands: dominated by woody perennials\n(1-2m height) >60% cover.',
    'value': 6},
   {'color': 'dcd159',
    'description': 'Open Shrublands: dominated by woody perennials\n(1-2m height) 10-60% cover.',
    'value': 7},
   {'color': 'dade48',
    'description': 'Woody Savannas: tree cover 30-60% (canopy >2m).',
    'value': 8},
   {'color': 'fbff13',
    'description': 'Savannas: tree cover 10-30% (canopy >2m).',
    'value': 9},
   {'color': 'b6ff05',
    'description': 'Grasslands: dominated by herbaceous annuals (<2m).',
    'value': 10},
   {'color': '27ff87',
    'description': 'Permanent Wetlands: permanently inundated lands with\n30-60% water cover and >10% vegetated cover.',
    'value': 11},
   {'color': 'c24f44',
    'description': 'Croplands: at least 60% of area is cultivated\ncropland.',
    'value': 12},
   {'color': 'a5a5a5',
    'description': 'Urban and Built-up Lands: at least 30% impervious\nsurface area including building materials, asphalt and vehicles.\n',
    'value': 13},
   {'color': 'ff6d4c',
    'description': 'Cropland/Natural Vegetation Mosaics: mosaics of\nsmall-scale cultivation 40-60% with natural tree, shrub, or herbaceous\nvegetation.\n',
    'value': 14},
   {'color': 'f9ffa4',
    'description': 'Non-Vegetated Lands: at least 60% of area is\nnon-vegetated barren (sand, rock, soil) or permanent snow and ice with\nless than 10% vegetation.\n',
    'value': 15}],
  'name': 'LC_Type2'},
 {'description': 'Land Cover Type 3: Annual Leaf Area Index (LAI) classification',
  'gee:classes': [{'color': '1c0dff',
    'description': 'Water Bodies: at least 60% of area is covered by permanent water bodies.',
    'value': 0},
   {'color': 'b6ff05',
    'description': 'Grasslands: dominated by herbaceous annuals (<2m) including cereal croplands.',
    'value': 1},
   {'color': 'dcd159',
    'description': 'Shrublands: shrub (1-2m) cover >10%.',
    'value': 2},
   {'color': 'c24f44',
    'description': 'Broadleaf Croplands: bominated by herbaceous annuals\n(<2m) that are cultivated with broadleaf crops.',
    'value': 3},
   {'color': 'fbff13',
    'description': 'Savannas: between 10-60% tree cover (>2m).',
    'value': 4},
   {'color': '086a10',
    'description': 'Evergreen Broadleaf Forests: dominated by evergreen\nbroadleaf and palmate trees (canopy >2m). Tree cover >60%.\n',
    'value': 5},
   {'color': '78d203',
    'description': 'Deciduous Broadleaf Forests: dominated by deciduous\nbroadleaf trees (canopy >2m). Tree cover >60%.',
    'value': 6},
   {'color': '05450a',
    'description': 'Evergreen Needleleaf Forests: dominated by evergreen\nconifer trees (canopy >2m). Tree cover >60%.',
    'value': 7},
   {'color': '54a708',
    'description': 'Deciduous Needleleaf Forests: dominated by deciduous\nneedleleaf (larch) trees (canopy >2m). Tree cover >60%.\n',
    'value': 8},
   {'color': 'f9ffa4',
    'description': 'Non-Vegetated Lands: at least 60% of area is\nnon-vegetated barren (sand, rock, soil) or permanent snow and ice with\nless than 10% vegetation.\n',
    'value': 9},
   {'color': 'a5a5a5',
    'description': 'Urban and Built-up Lands: at least 30% impervious\nsurface area including building materials, asphalt and vehicles.\n',
    'value': 10}],
  'name': 'LC_Type3'},
 {'description': 'Land Cover Type 4: Annual BIOME-Biogeochemical Cycles (BGC) classification',
  'gee:classes': [{'color': '1c0dff',
    'description': 'Water Bodies: at least 60% of area is covered by\npermanent water bodies.',
    'value': 0},
   {'color': '05450a',
    'description': 'Evergreen Needleleaf Vegetation: dominated by evergreen\nconifer trees and shrubs (>1m). Woody vegetation cover >10%.\n',
    'value': 1},
   {'color': '086a10',
    'description': 'Evergreen Broadleaf Vegetation: dominated by evergreen\nbroadleaf and palmate trees and shrubs (>1m). Woody vegetation cover\n>10%.\n',
    'value': 2},
   {'color': '54a708',
    'description': 'Deciduous Needleleaf Vegetation: dominated by deciduous\nneedleleaf (larch) trees and shrubs (>1m). Woody vegetation cover\n>10%.\n',
    'value': 3},
   {'color': '78d203',
    'description': 'Deciduous Broadleaf Vegetation: dominated by deciduous\nbroadleaf trees and shrubs (>1m). Woody vegetation cover >10%.\n',
    'value': 4},
   {'color': '009900',
    'description': 'Annual Broadleaf Vegetation: dominated by herbaceous\nannuals (<2m). At least 60% cultivated broadleaf crops.\n',
    'value': 5},
   {'color': 'b6ff05',
    'description': 'Annual Grass Vegetation: dominated by herbaceous\nannuals (<2m) including cereal croplands.',
    'value': 6},
   {'color': 'f9ffa4',
    'description': 'Non-Vegetated Lands: at least 60% of area is\nnon-vegetated barren (sand, rock, soil) or permanent snow/ice with\nless than 10% vegetation.\n',
    'value': 7},
   {'color': 'a5a5a5',
    'description': 'Urban and Built-up Lands: at least 30% impervious\nsurface area including building materials, asphalt, and vehicles.\n',
    'value': 8}],
  'name': 'LC_Type4'},
 {'description': 'Land Cover Type 5: Annual Plant Functional Types classification',
  'gee:classes': [{'color': '1c0dff',
    'description': 'Water Bodies: at least 60% of area is covered by permanent water bodies.',
    'value': 0},
   {'color': '05450a',
    'description': 'Evergreen Needleleaf Trees: dominated by evergreen\nconifer trees (>2m). Tree cover >10%.',
    'value': 1},
   {'color': '086a10',
    'description': 'Evergreen Broadleaf Trees: dominated by evergreen\nbroadleaf and palmate trees (>2m). Tree cover >10%.',
    'value': 2},
   {'color': '54a708',
    'description': 'Deciduous Needleleaf Trees: dominated by deciduous\nneedleleaf (larch) trees (>2m). Tree cover >10%.',
    'value': 3},
   {'color': '78d203',
    'description': 'Deciduous Broadleaf Trees: dominated by deciduous\nbroadleaf trees (>2m). Tree cover >10%.',
    'value': 4},
   {'color': 'dcd159',
    'description': 'Shrub: Shrub (1-2m) cover >10%.',
    'value': 5},
   {'color': 'b6ff05',
    'description': 'Grass: dominated by herbaceous annuals (<2m) that are\nnot cultivated.',
    'value': 6},
   {'color': 'dade48',
    'description': 'Cereal Croplands: dominated by herbaceous annuals\n(<2m). At least 60% cultivated cereal crops.',
    'value': 7},
   {'color': 'c24f44',
    'description': 'Broadleaf Croplands: dominated by herbaceous annuals\n(<2m). At least 60% cultivated broadleaf crops.',
    'value': 8},
   {'color': 'a5a5a5',
    'description': 'Urban and Built-up Lands: at least 30% impervious\nsurface area including building materials, asphalt, and vehicles.\n',
    'value': 9},
   {'color': '69fff8',
    'description': 'Permanent Snow and Ice: at least 60% of area is covered\nby snow and ice for at least 10 months of the year.\n',
    'value': 10},
   {'color': 'f9ffa4',
    'description': 'Non-Vegetated Lands: at least 60% of area is\nnon-vegetated barren (sand, rock, soil) with\nless than 10% vegetation.\n',
    'value': 11}],
  'name': 'LC_Type5'},
 {'description': 'LCCS1 land cover layer confidence',
  'gee:units': '%',
  'name': 'LC_Prop1_Assessment'},
 {'description': 'LCCS2 land use layer confidence',
  'gee:units': '%',
  'name': 'LC_Prop2_Assessment'},
 {'description': 'LCCS3 surface hydrology layer confidence',
  'gee:units': '%',
  'name': 'LC_Prop3_Assessment'},
 {'description': 'FAO-Land Cover Classification System 1 (LCCS1) land cover layer',
  'gee:classes': [{'color': 'f9ffa4',
    'description': 'Barren: at least of area 60% is non-vegetated barren\n(sand, rock, soil) or permanent snow/ice with less than 10%\nvegetation.\n',
    'value': 1},
   {'color': '69fff8',
    'description': 'Permanent Snow and Ice: at least 60% of area is covered\nby snow and ice for at least 10 months of the year.\n',
    'value': 2},
   {'color': '1c0dff',
    'description': 'Water Bodies: at least 60% of area is covered by\npermanent water bodies.',
    'value': 3},
   {'color': '05450a',
    'description': 'Evergreen Needleleaf Forests: dominated by evergreen\nconifer trees (>2m). Tree cover >60%.',
    'value': 11},
   {'color': '086a10',
    'description': 'Evergreen Broadleaf Forests: dominated by evergreen\nbroadleaf and palmate trees (>2m). Tree cover >60%.\n',
    'value': 12},
   {'color': '54a708',
    'description': 'Deciduous Needleleaf Forests: dominated by deciduous\nneedleleaf (larch) trees (>2m). Tree cover >60%.',
    'value': 13},
   {'color': '78d203',
    'description': 'Deciduous Broadleaf Forests: dominated by deciduous\nbroadleaf trees (>2m). Tree cover >60%.',
    'value': 14},
   {'color': '005a00',
    'description': 'Mixed Broadleaf/Needleleaf Forests: co-dominated\n(40-60%) by broadleaf deciduous and evergreen needleleaf tree (>2m)\ntypes. Tree cover >60%.\n',
    'value': 15},
   {'color': '009900',
    'description': 'Mixed Broadleaf Evergreen/Deciduous Forests:\nco-dominated (40-60%) by broadleaf evergreen and deciduous tree (>2m)\ntypes. Tree cover >60%.\n',
    'value': 16},
   {'color': '006c00',
    'description': 'Open Forests: tree cover 30-60% (canopy >2m).',
    'value': 21},
   {'color': '00d000',
    'description': 'Sparse Forests: tree cover 10-30% (canopy >2m).',
    'value': 22},
   {'color': 'b6ff05',
    'description': 'Dense Herbaceous: dominated by herbaceous annuals\n(<2m) at least 60% cover.',
    'value': 31},
   {'color': '98d604',
    'description': 'Sparse Herbaceous: dominated by herbaceous annuals\n(<2m) 10-60% cover.',
    'value': 32},
   {'color': 'dcd159',
    'description': 'Dense Shrublands: dominated by woody perennials (1-2m)\n>60% cover.',
    'value': 41},
   {'color': 'f1fb58',
    'description': 'Shrubland/Grassland Mosaics: dominated by woody\nperennials (1-2m) 10-60% cover with dense herbaceous annual\nunderstory.\n',
    'value': 42},
   {'color': 'fbee65',
    'description': 'Sparse Shrublands: dominated by woody perennials (1-2m)\n10-60% cover with minimal herbaceous understory.\n',
    'value': 43}],
  'name': 'LC_Prop1'},
 {'description': 'FAO-LCCS2 land use layer',
  'gee:classes': [{'color': 'f9ffa4',
    'description': 'Barren: at least of area 60% is non-vegetated barren\n(sand, rock, soil) or permanent snow/ice with less than 10%\nvegetation.\n',
    'value': 1},
   {'color': '69fff8',
    'description': 'Permanent Snow and Ice: at least 60% of area is covered\nby snow and ice for at least 10 months of the year.\n',
    'value': 2},
   {'color': '1c0dff',
    'description': 'Water Bodies: at least 60% of area is covered by\npermanent water bodies.',
    'value': 3},
   {'color': 'a5a5a5',
    'description': 'Urban and Built-up Lands: at least 30% of area is made\nup ofimpervious surfaces including building materials, asphalt, and\nvehicles.\n',
    'value': 9},
   {'color': '003f00',
    'description': 'Dense Forests: tree cover >60% (canopy >2m).',
    'value': 10},
   {'color': '006c00',
    'description': 'Open Forests: tree cover 10-60% (canopy >2m).',
    'value': 20},
   {'color': 'e3ff77',
    'description': 'Forest/Cropland Mosaics: mosaics of small-scale\ncultivation 40-60% with >10% natural tree cover.',
    'value': 25},
   {'color': 'b6ff05',
    'description': 'Natural Herbaceous: dominated by herbaceous annuals\n(<2m). At least 10% cover.',
    'value': 30},
   {'color': '93ce04',
    'description': 'Natural Herbaceous/Croplands Mosaics: mosaics of\nsmall-scale cultivation 40-60% with natural shrub or herbaceous\nvegetation.\n',
    'value': 35},
   {'color': '77a703',
    'description': 'Herbaceous Croplands: dominated by herbaceous annuals\n(<2m). At least 60% cover. Cultivated fraction >60%.\n',
    'value': 36},
   {'color': 'dcd159',
    'description': 'Shrublands: shrub cover >60% (1-2m).',
    'value': 40}],
  'name': 'LC_Prop2'},
 {'description': 'FAO-LCCS3 surface hydrology layer',
  'gee:classes': [{'color': 'f9ffa4',
    'description': 'Barren: at least of area 60% is non-vegetated barren\n(sand, rock, soil) or permanent snow/ice with less than 10%\nvegetation.\n',
    'value': 1},
   {'color': '69fff8',
    'description': 'Permanent Snow and Ice: at least 60% of area is covered\nby snow and ice for at least 10 months of the year.\n',
    'value': 2},
   {'color': '1c0dff',
    'description': 'Water Bodies: at least 60% of area is covered by\npermanent water bodies.',
    'value': 3},
   {'color': '003f00',
    'description': 'Dense Forests: tree cover >60% (canopy >2m).',
    'value': 10},
   {'color': '006c00',
    'description': 'Open Forests: tree cover 10-60% (canopy >2m).',
    'value': 20},
   {'color': '72834a',
    'description': 'Woody Wetlands: shrub and tree cover >10% (>1m).\nPermanently or seasonally inundated.',
    'value': 27},
   {'color': 'b6ff05',
    'description': 'Grasslands: dominated by herbaceous annuals (<2m) >10% cover.',
    'value': 30},
   {'color': 'c6b044',
    'description': 'Shrublands: shrub cover >60% (1-2m).',
    'value': 40},
   {'color': '3aba73',
    'description': 'Herbaceous Wetlands: dominated by herbaceous annuals\n(<2m) >10% cover. Permanently or seasonally inundated.\n',
    'value': 50},
   {'color': '1e9db3',
    'description': 'Tundra: tree cover <10%. Snow-covered for at least 8\nmonths of the year.',
    'value': 51}],
  'name': 'LC_Prop3'},
 {'description': 'Product quality flags',
  'gee:classes': [{'description': 'Classified land: has a classification label and is land\naccording to the water mask.',
    'value': 0},
   {'description': 'Unclassified land: not classified because of missing\ndata but land according to the water mask, labeled as barren.\n',
    'value': 1},
   {'description': 'Classified water: has a classification label and is\nwater according to the water mask.',
    'value': 2},
   {'description': 'Unclassified water: not classified because of missing\ndata but water according to the water mask.',
    'value': 3},
   {'description': 'Classified sea ice: classified as snow/ice but water\nmask says it is water and less than 100m elevation, switched to\nwater.\n',
    'value': 4},
   {'description': 'Misclassified water: classified as water but water mask\nsays it is land, switched to secondary label.',
    'value': 5},
   {'description': 'Omitted snow/ice: land according to the water mask that\nwas classified as something other than snow but with a maximum annual\ntemperature below 1◦C, relabeled as snow/ice.\n',
    'value': 6},
   {'description': 'Misclassified snow/ice: land according to the water mask\nthat was classified as snow but with a minimum annual temperature\ngreater than 1◦C, relabeled as barren.\n',
    'value': 7},
   {'description': 'Backfilled label: missing label from stabilization,\nfilled with the pre-stabilized result.',
    'value': 8},
   {'description': 'Forest type changed: climate-based change to forest class.',
    'value': 9}],
  'name': 'QC'},
 {'description': 'Binary land (class 2) / water (class 1) mask derived from MOD44W',
  'gee:classes': [{'color': '1c0dff', 'description': 'Water', 'value': 1},
   {'color': 'f9ffa4', 'description': 'Land,', 'value': 2}],
  'name': 'LW'}]

So, the idea is to create a repository like this one that I use to keep all the scale and offset parameters used for the scaleAndOffset() method in ee_extra : eemont updated. But, in this case, it would be a repository where we would store the collection, the band and the values, colors and descriptions just as you need them for the Dataset class! Then, sankee can just grab the data from this repository to keep all datasets updated :)

Let me know what you think, and, if you want, I can work on creating that repository and linking it to sankee!

Cheers,

Dave

Reduce unnecessary calls to `generate_dataframe`

Currently generate_dataframe gets called quite a few times when building a plot. I doubt this is a noticeable performance hit since it's a pretty simple method, but we could clean that up by storing a df attribute when a SankeyPlot is initialized and only re-generating when the plot is updated (e.g. a class is toggled).

Example not working

It seems the example no longer works. Getting EEException: Element.propertyNames: Parameter 'element' is required.

import sankee
import ee

ee.Initialize()

sankee.datasets.LCMS_LC.sankify(
  years=[1990, 2000, 2010, 2020],
  region=ee.Geometry.Point([-122.192688, 46.25917]).buffer(2000),
  max_classes=3,
  title="Mt. St. Helens Recovery"
)

image

Label order not preserved

The order of time steps in the output plot should match the order provided in img_list. Instead it looks they're sorted alpha based on label_list. This only affects custom datasets because premade datasets use sequential year labels which (accidentally) get sorted correctly.

Making sankee available on conda-forge

Thank you for developing this nice package! Have you considered making it available on conda-forge channel? I would love to incorporate sankee into the geemap toolbar and develop an interactive GUI for this so that users can create sankee plots without coding. Pull request is also welcome.

Here is a tutorial for publishing a Python package on conda-forge. I would be happy to help if needed.

Themes

Customizing appearance of the sankey plots is non-trivial since there's hard-coded CSS and you have to interact with the plotly graph objects API, so it would be nice to have a few premade themes to choose between, as well as the ability to define custom themes.

Issue with sankee.Dataset()

I am running one of the examples on Google Colab and encountered this problem:

AttributeError Traceback (most recent call last)
in ()
----> 1 dataset = sankee.Dataset(collection_name="custom", band=band, labels=labels, palette=palette)

AttributeError: module 'sankee' has no attribute 'Dataset'

image

[BUG] Error when some nan values sampled

When running sankify in an area that has some valid samples and some NaN samples, an error is thrown:

Exception: The following values are present in the data and undefined in the labels: [nan]

Instead, the NaN samples should be dropped if the dropna arg is true.

To recreate, run sankee.sankify with the LCMS dataset, 1985 and 2020 data, and the following region:

region = ee.Geometry.Polygon = [[
  [-104.983543, 48.545251],
  [-104.983543, 49.367619],
  [-104.43412, 49.367619],
  [-104.43412, 48.545251],
  [-104.983543, 48.545251]
]]

Custom dataset mtbs_1984_2018 not found

I was testing the custom dataset example, and it seems the asset 'users/aazuspan/fires/mtbs_1984_2018' is not accessible. Would you mind sharing this dataset? Thanks.

image

Interactive widgets

Instead of returning a plot object, returning a FigureWidget would allow for interactive controls of the plot parameters, like buttons to turn each class on and off or a slider to set the max classes.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.