Visualizing Area Summaries#
It can be difficult to easily summarize GEE imageCollections and images over an area in an interactive environment
geeViz’s area charting methods allow for easy interactive charting with minimal additional code
This notebook shows several examples of different ways of using the area charting methods with GEE images and imageCollections
Copyright 2024 Ian Housman
Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
#Import modules
try:
import geeViz.geeView as geeView
except:
!python -m pip install geeViz
import geeViz.geeView as geeView
import geeViz.getImagesLib as gil
import pandas as pd
ee = geeView.ee
Map = geeView.Map
Map.clearMap()
print('done')
done
There are many different formats of data geeViz’s area charting module can handle
The most common is charting the percent or area in hectares or acres of thematic classes of an image collection
If an imageCollection has
class_values
,class_names
,class_palette
properties for its images, all charts will automatically be populated with those names and colorsFirst, we will look at these properties for a couple available images and image collections
lcms = ee.ImageCollection("USFS/GTAC/LCMS/v2023-9")
nlcd = ee.ImageCollection("USGS/NLCD_RELEASES/2021_REL/NLCD").select(['landcover'])
def get_props_dataFrames(props,bandNames = None):
props = {k:i for k,i in props.items() if k.find('_class_')>-1}
if bandNames == None:
bandNames = list(set([k.split('_class_')[0] for k in props.keys()]))
out = {}
for bn in bandNames:
print(bn)
df = pd.DataFrame({'Values':props[f'{bn}_class_values'],
'Names':props[f'{bn}_class_names'],
'Colors':props[f'{bn}_class_palette']})
display(df)
out[bn]=df
# return out
lcms_props = lcms.first().toDictionary().getInfo()
nlcd_props = nlcd.first().toDictionary().getInfo()
lcms_thematic_bandNames = lcms.select(['Change','Land_Cover','Land_Use']).first().bandNames().getInfo()
nlcd_landcover_bandNames = ['landcover']
get_props_dataFrames(lcms_props,lcms_thematic_bandNames)
get_props_dataFrames(nlcd_props,nlcd_landcover_bandNames)
# Shorten NLCD class names for later use
nlcd_class_names_key = f'{nlcd_landcover_bandNames[0]}_class_names'
nlcd_class_names_shortened = [nm.split(':')[0] for nm in nlcd_props[nlcd_class_names_key]]
nlcd_props_shortened_names = nlcd_props
nlcd_props_shortened_names[nlcd_class_names_key] = nlcd_class_names_shortened
print('Shortened NLCD class names:')
get_props_dataFrames(nlcd_props_shortened_names,nlcd_landcover_bandNames)
Change
Values | Names | Colors | |
---|---|---|---|
0 | 1 | Stable | 3d4551 |
1 | 2 | Slow Loss | f39268 |
2 | 3 | Fast Loss | d54309 |
3 | 4 | Gain | 00a398 |
4 | 5 | Non-Processing Area Mask | 1b1716 |
Land_Cover
Values | Names | Colors | |
---|---|---|---|
0 | 1 | Trees | 005e00 |
1 | 2 | Tall Shrubs & Trees Mix (SEAK Only) | 008000 |
2 | 3 | Shrubs & Trees Mix | 00cc00 |
3 | 4 | Grass/Forb/Herb & Trees Mix | b3ff1a |
4 | 5 | Barren & Trees Mix | 99ff99 |
5 | 6 | Tall Shrubs (SEAK Only) | b30088 |
6 | 7 | Shrubs | e68a00 |
7 | 8 | Grass/Forb/Herb & Shrubs Mix | ffad33 |
8 | 9 | Barren & Shrubs Mix | ffe0b3 |
9 | 10 | Grass/Forb/Herb | ffff00 |
10 | 11 | Barren & Grass/Forb/Herb Mix | aa7700 |
11 | 12 | Barren or Impervious | d3bf9b |
12 | 13 | Snow or Ice | ffffff |
13 | 14 | Water | 4780f3 |
14 | 15 | Non-Processing Area Mask | 1b1716 |
Land_Use
Values | Names | Colors | |
---|---|---|---|
0 | 1 | Agriculture | efff6b |
1 | 2 | Developed | ff2ff8 |
2 | 3 | Forest | 1b9d0c |
3 | 4 | Non-Forest Wetland | 97ffff |
4 | 5 | Other | a1a1a1 |
5 | 6 | Rangeland or Pasture | c2b34a |
6 | 7 | Non-Processing Area Mask | 1b1716 |
landcover
Values | Names | Colors | |
---|---|---|---|
0 | 11 | Open water: areas of open water, generally wit... | 466b9f |
1 | 12 | Perennial ice/snow: areas characterized by a p... | d1def8 |
2 | 21 | Developed, open space: areas with a mixture of... | dec5c5 |
3 | 22 | Developed, low intensity: areas with a mixture... | d99282 |
4 | 23 | Developed, medium intensity: areas with a mixt... | eb0000 |
5 | 24 | Developed high intensity: highly developed are... | ab0000 |
6 | 31 | Barren land (rock/sand/clay): areas of bedrock... | b3ac9f |
7 | 41 | Deciduous forest: areas dominated by trees gen... | 68ab5f |
8 | 42 | Evergreen forest: areas dominated by trees gen... | 1c5f2c |
9 | 43 | Mixed forest: areas dominated by trees general... | b5c58f |
10 | 52 | Shrub/scrub: areas dominated by shrubs less th... | ccb879 |
11 | 71 | Grassland/herbaceous: areas dominated by grama... | dfdfc2 |
12 | 81 | Pasture/hay: areas of grasses, legumes, or gra... | dcd939 |
13 | 82 | Cultivated crops: areas used for the productio... | ab6c28 |
14 | 90 | Woody wetlands: areas where forest or shrublan... | b8d9eb |
15 | 95 | Emergent herbaceous wetlands: areas where pere... | 6c9fb8 |
Shortened NLCD class names:
landcover
Values | Names | Colors | |
---|---|---|---|
0 | 11 | Open water | 466b9f |
1 | 12 | Perennial ice/snow | d1def8 |
2 | 21 | Developed, open space | dec5c5 |
3 | 22 | Developed, low intensity | d99282 |
4 | 23 | Developed, medium intensity | eb0000 |
5 | 24 | Developed high intensity | ab0000 |
6 | 31 | Barren land (rock/sand/clay) | b3ac9f |
7 | 41 | Deciduous forest | 68ab5f |
8 | 42 | Evergreen forest | 1c5f2c |
9 | 43 | Mixed forest | b5c58f |
10 | 52 | Shrub/scrub | ccb879 |
11 | 71 | Grassland/herbaceous | dfdfc2 |
12 | 81 | Pasture/hay | dcd939 |
13 | 82 | Cultivated crops | ab6c28 |
14 | 90 | Woody wetlands | b8d9eb |
15 | 95 | Emergent herbaceous wetlands | 6c9fb8 |
Basic Area Charting#
This example will show the most basic method for adding area chart layers
By setting
"canAreaChart":True
, the layer will be added to area charting. Available properties (shown above) will be used to set up names and colorsUsing the
Map.turnOnAutoAreaCharting()
method will turn on autmatic area charting. This will use the map extent as the summary area.Additional methods are
Map.turnOnSelectionAreaCharting()
andMap.turnOnUserDefinedAreaCharting()
for turning on different methods of providing areas to summarize. You can also change the method being used in the geeView UI underTools -> Area Tools
Map.clearMap()
Map.addLayer(lcms.select(['Land_Cover']),{'autoViz':True,'canAreaChart':True},'LCMS Land Cover')
Map.addLayer(nlcd.select(['landcover']),{'autoViz':True,'canAreaChart':True},'NLCD Land Cover')
Map.turnOnAutoAreaCharting()
Map.view()
Adding layer: LCMS Land Cover
Adding layer: NLCD Land Cover
Starting webmap
Using default refresh token for geeView
Line and Sankey Charts#
For thematic imageCollections, line and sankey charts are supported
You can specify one or both within the
areaChartParams
dictionary. By default, line is chosen. (e.g."areaChartParams":{"sankey":True}
)Note that sankey charts work well at showing transitions between classes. Since the number of transition classes is the number of classes2, if there are many classes, sankey charting will be quite slow and may error out.
For sankey charting, you can specify transition periods in the code using the
sankeyTransitionPeriods
key inareaChartParams
(e.g."sankeyTransitionPeriods":[[1985,1987],[2000,2002],[2020,2022]]
), or leave it blank and geeViz will try to figure out a good set given the years of the provided imageCollection. Note that if you add imageCollections with different time extents, geeViz will take the intersection for the default years. You can add and change the periods in the geeView UI as well underTools -> Area Tools -> Area Tools Parameters
Map.clearMap()
Map.addLayer(lcms.select(['Change']),{'autoViz':True,'canAreaChart':True,'areaChartParams':{'sankey':True}},'LCMS Change')
Map.addLayer(lcms.select(['Land_Cover']),{'autoViz':True,'canAreaChart':True,'areaChartParams':{'sankey':True}},'LCMS Land Cover')
Map.addLayer(lcms.select(['Land_Use']),{'autoViz':True,'canAreaChart':True,'areaChartParams':{'sankey':True}},'LCMS Land Use')
Map.turnOnAutoAreaCharting()
Map.view()
Adding layer: LCMS Change
Adding layer: LCMS Land Cover
Adding layer: LCMS Land Use
Starting webmap
Using default refresh token for geeView
Local web server at: http://localhost:8001/geeView/ already serving.
cwd a:\GEE\gee_py_modules_package\geeViz\examples
geeView URL: http://localhost:8001/geeView/?projectID=lcms-292214&accessToken=ya29.a0AeDClZBRE9mjI7Tbvn12JUdNHWBcQvnRwFG-hP61lUO5NJ1i3hUF5MWklT1YsQ2O8JTPO_c9dknJ4tLo2b1iWUDX3YpRH9D_GxcBzfpEkOKxbtzwZD_WgsZ2X5yrxgRqXDSdCClmIPTT7vOM7PivC2CznkBAOmJWgtu42xYKMiAaCgYKATwSARESFQHGX2MiL_SKbyR4o1MbYfhrP8JMSw0178&accessTokenCreationTime=1732072086594
Adding a layer to line and sankey charting is done as follows
Any time you specify
'line':True,'sankey':True
, both line and sankey charts will be createdThis can slow things down a lot if many layers are visible. Also, moving the map, pausing for a second or two, and then moving the map again, many times, can create a long queue and delay charting.
Map.clearMap()
Map.addLayer(lcms.select(['Change']),{'autoViz':True,'canAreaChart':True,'areaChartParams':{'line':True,'sankey':True}},'LCMS Change')
Map.addLayer(lcms.select(['Land_Cover']),{'autoViz':True,'canAreaChart':True,'areaChartParams':{'line':True,'sankey':True}},'LCMS Land Cover')
Map.addLayer(lcms.select(['Land_Use']),{'autoViz':True,'canAreaChart':True,'areaChartParams':{'line':True,'sankey':True}},'LCMS Land Use')
Map.turnOnAutoAreaCharting()
Map.view()
Adding layer: LCMS Change
Adding layer: LCMS Land Cover
Adding layer: LCMS Land Use
Starting webmap
Using default refresh token for geeView
Local web server at: http://localhost:8001/geeView/ already serving.
cwd a:\GEE\gee_py_modules_package\geeViz\examples
geeView URL: http://localhost:8001/geeView/?projectID=lcms-292214&accessToken=ya29.a0AeDClZCo6B7_61baBesuftX5imkCdbgjQ2cDhjfWwwxSln0lW_f7XfITgdSiXVr6J7_lAz_6b7EQ-Xe5TCpBXK4RUjicQGwh4rMOMReEYDZDmspR_UGbQyOcAv_d-F5vjiBfmKeFx-2ZO5E0GXkaW1-vaCjXC5uORbQQR6X_rmQaCgYKAVwSARESFQHGX2MitF33sKGsJctQg4HvPM9Rsg0178&accessTokenCreationTime=1732072108233
Ways of adding area charting layers#
There are two methods for adding area chart layers. The first is shown above, where when adding a layer using
Map.addLayer
, specify"canAreaChart":True
. With this method, if a layer is visible, it will be included in area charting.There are instances where you would like to summarize layers, but may not want them on the map or it is impossible to visualize all the thematic bands you’d like to chart. In this instance, you can use the
Map.addAreaChartLayer
method.If you use the
Map.addAreaChartLayer
method, you will need to use theMap.populateAreaChartLayerSelect()
method to instantiate a selection menu for choosing which area chart layers should be charted.In this example, we will summarize all thematic classes in LCMS in a single graph. This cannot be displayed on a map, but is an interesting way to look at the summarized data in charts
Note that the dictionary of parameters is more or less the same as what you would put in the
"areaChartParams"
if you were to use theMap.addLayer
method.Note that while multi thematic band image collections can be charted in a single line chart, sankey charts can only support one band per chart. If a multi thematic band image collection is given with
"sankey":True
(as is the case in this example), separate sankey charts will be created for each band.
Map.clearMap()
Map.addLayer(lcms.select(['Change_Raw_Probability.*']),{'reducer':ee.Reducer.stdDev(),'min':0,'max':10},'LCMS Change Prob')
Map.addAreaChartLayer(lcms,{'line':True},'LCMS All Thematic Classes Line',False)
Map.addAreaChartLayer(lcms,{'sankey':True},'LCMS All Thematic Classes Sankey',True)
Map.populateAreaChartLayerSelect()
Map.turnOnAutoAreaCharting()
Map.view()
Adding layer: LCMS Change Prob
Adding area chart layer: LCMS All Thematic Classes Line
Adding area chart layer: LCMS All Thematic Classes Sankey
Starting webmap
Using default refresh token for geeView
Local web server at: http://localhost:8001/geeView/ already serving.
cwd a:\GEE\gee_py_modules_package\geeViz\examples
geeView URL: http://localhost:8001/geeView/?projectID=lcms-292214&accessToken=ya29.a0AeDClZCjAoKLilGLZF5wIObir1p6XAIWJM6jMrodG8zcJg1jJ3GzF-yy8r7fbwHqpEcYQ5BC1P_unmAqFIY7hIVAU3CpkOzxnGMZkXx-ff3VoP2Tc2U4xdc3bq4Z9kKrw1dXI-iVO0V2p-DBHnOb5iUzgsp93zCB3IoXLA7IkTIaCgYKASMSARESFQHGX2MiCMKkLZs77Opz9_0uA6Jqig0178&accessTokenCreationTime=1732168152111
Charting Non-Thematic Data#
You can chart continuous data as well. By default, a
ee.Reducer.mean()
will be used. You can use any reducer that returns a single value per image-band (e.g.ee.Reducer.min()
,ee.Reducer.max()
,ee.Reducer.stdDev()
,ee.Reducer.mode()
, and notee.Reducer.percentile([0,50,100])
).You can specify this using
"areaChartParams":{"reducer":ee.Reducer.mean()}
Optionally, you can provide a color palette to be used. Each band will be assigned to a color in the order given
Notice in the example, the reducer for what is shown on the map is different from the zonal summary reducer. In this example, on the map the standard deviation of the probability is shown to highlight likely change, while the average over the area is shown in the chart since that is a more appropriate representation of probability over an area.
Map.clearMap()
Map.addLayer(lcms.select(['Change_Raw_Probability.*']),
{'reducer':ee.Reducer.stdDev(),'min':0,'max':10,'canAreaChart':True,'areaChartParams':{'palette':'f39268,d54309,00a398'}},'LCMS Change Prob')
Map.turnOnAutoAreaCharting()
Map.view()
Adding layer: LCMS Change Prob
Starting webmap
Using default refresh token for geeView
Local web server at: http://localhost:8001/geeView/ already serving.
cwd a:\GEE\gee_py_modules_package\geeViz\examples
geeView URL: http://localhost:8001/geeView/?projectID=lcms-292214&accessToken=ya29.a0AeDClZDC-kEJjZ7ANFvwoBVoe0PN6iyoJgDoKDC45AZod0eypEh2wmKRloLs4mY0cK4UTwGQGzF5lAPoAfQfF1B-0YjmglkLQmwOAqofFJtdBfjLRX5B61yrowTSG_D0u83cds1oShCZRR18Wapnif7vIHzAJZk8Zm2USy6000oaCgYKAdMSARESFQHGX2Mij0Uo4T2Bl89g0qog8XH6Sw0178&accessTokenCreationTime=1732168277196
Charting Images#
You can also chart images
It will behave in a similar fashion to imageCollections, but will show a bar chart
Placing names for bar charts can be challenging if the names are very long. geeViz will automatically change the bar chart to be a horizontal bar chart if long names are detected. This still does not ensure the bar charts are readable (as is the case in this example). Shortening class names is the easiest method to address this issue (shown by splitting the full NLCD landcover name with
:
and take the first part earlier in this notebook).If using
"autoViz":True
, be sure to copy the_class_
properties back in
Map.clearMap()
Map.addLayer(lcms.select(['Land_Cover']),{'autoViz':True,'canAreaChart':True},'LCMS Land Cover')
Map.addLayer(lcms.select(['Land_Cover']).mode().set(lcms.first().toDictionary()),{'autoViz':True,'canAreaChart':True},'LCMS Land Cover Mode')
Map.addLayer(nlcd.select(['landcover']),{'autoViz':True,'canAreaChart':True},'NLCD Land Cover')
Map.addLayer(nlcd.select(['landcover']).mode().set(nlcd.first().toDictionary()),{'autoViz':True,'canAreaChart':True},'NLCD Land Cover Mode')
# Use the shortened class names to clean up chart
Map.addLayer(nlcd.select(['landcover']).mode().set(nlcd_props_shortened_names),{'autoViz':True,'canAreaChart':True},'NLCD Land Cover Mode Shortened Names')
Map.turnOnAutoAreaCharting()
Map.view()
Adding layer: LCMS Land Cover
Adding layer: LCMS Land Cover Mode
Adding layer: NLCD Land Cover
Adding layer: NLCD Land Cover Mode
Adding layer: NLCD Land Cover Mode Shortened Names
Starting webmap
Using default refresh token for geeView
Local web server at: http://localhost:8001/geeView/ already serving.
cwd a:\GEE\gee_py_modules_package\geeViz\examples
geeView URL: http://localhost:8001/geeView/?projectID=lcms-292214&accessToken=ya29.a0AeDClZAYSRUVZEF7tD-uK6Zn-LCX2EMMf-R2VGKJu9WdAnWqeFNsxq2H9j8atAF7Cgu_1ISo0BaCA3RhHvOuKBVw6YK_DTXlSllbYjTie86dZHcp8w7QwXmPcwuaDieNGZVtAUDv3RV6dQ5ZIodg3F_bbcbIMN8HqXAryuqDPwgaCgYKAesSARESFQHGX2MiT8b83hyJMzIqna_6JYRXdQ0178&accessTokenCreationTime=1732169429393
Charting Images Without Color and Name Properties#
Sometimes you will have an image you add to the map with a min, max, and palette in the viz params that are thematic or ordinal thematic data. If those images have no class_names, etc properties set, geeViz will try to render the chart properly using the given min, max, and palette if you specify `”areaChartParams”:{“reducer”:ee.Reducer.frequencyHistogram()}
Map.clearMap()
def getMostRecentChange(c, code):
def wrapper(img):
yr = ee.Date(img.get("system:time_start")).get("year")
return (
ee.Image(yr)
.int16()
.rename(["year"])
.updateMask(img.eq(code))
.copyProperties(img, ["system:time_start"])
)
return c.map(wrapper)
mostRecentFastLossYear = getMostRecentChange(lcms.select(['Change']),3).max()
Map.addLayer(mostRecentFastLossYear, {'min':1985,'max':2023,'palette':["ffffe5", "fff7bc", "fee391", "fec44f", "fe9929", "ec7014", "cc4c02"],'canAreaChart':True,'areaChartParams':{'reducer':ee.Reducer.frequencyHistogram()}}, "Most Recent Fast Loss Year", True)
Map.turnOnAutoAreaCharting()
Map.view()
Adding layer: Most Recent Fast Loss Year
Starting webmap
Using default refresh token for geeView
Local web server at: http://localhost:8001/geeView/ already serving.
cwd a:\GEE\gee_py_modules_package\geeViz\examples
geeView URL: http://localhost:8001/geeView/?projectID=lcms-292214&accessToken=ya29.a0AeDClZB7X2qwuIOOEJXfmqKh4BlhENGTSj4_Xp7uL99qXMtkt7l1RdiAFuQ-jTN5Ou_2RTBOZA8k247QT8eAnc3ED6ZCf4C8NpZrsG070oER4EapnJsM2mAU33AayTBsxMbfWQEwW-zz9TBzm7LllyrVjOTEdpxzQloFUGOgQc8aCgYKAZISARESFQHGX2MiBqtgdGfy6Z72iUD04QOyfw0178&accessTokenCreationTime=1732169453056
Charting Time Lapses#
Time lapses also support area charting. All functionality is the same as the
Map.addLayer
methods.Band names can be specified in the
areaChartParams
. If they are not specified, butbands
is specified in the visualization parameters, those bands will be used instead. Otherwise, all bands will be shown.
Map.clearMap()
composites = ee.ImageCollection("projects/lcms-tcc-shared/assets/CONUS/Composites/Composite-Collection-yesL7")
years = list(range(1985,2024))
# Need to mosaic the tiled outputs for each year
composites = [composites.filter(ee.Filter.calendarRange(yr,yr,'year')).mosaic().set('system:time_start',ee.Date.fromYMD(yr,6,1).millis()) for yr in years]
composites = ee.ImageCollection(composites)
# Set up visualization parameters
viz = gil.vizParamsFalse10k
viz['canAreaChart']=True
viz['areaChartParams']={'bandNames':'blue,green,red,nir,swir1,swir2','palette':'00D,0D0,D00,D0D,0DD'}
Map.addTimeLapse(composites,gil.vizParamsFalse10k,'Composites')
Map.turnOnAutoAreaCharting()
Map.view()
Adding layer: Composites
Starting webmap
Using default refresh token for geeView
Local web server at: http://localhost:8001/geeView/ already serving.
cwd a:\GEE\gee_py_modules_package\geeViz\examples
geeView URL: http://localhost:8001/geeView/?projectID=lcms-292214&accessToken=ya29.a0AeDClZDgfsjQNYd5rrgKWcv3pcdtv1txAnIJB2FSclFLx0D3XVfXW_4f9nzPNOkWNGajJehlLbpshY5r0DKJkOAISTKp7KzzqPEEcD_7ickDf6gCwaZeLWYZzrnhv2ipteslzEO2FhDzVG_S-1Clyr-ZUdKk_ePFBjX-90WzNyMaCgYKATQSARESFQHGX2Mix24C9Alq9W4HMEp1x9x6UQ0178&accessTokenCreationTime=1732169481988
Charting Thematic Data without set properties#
You can chart thematic datasets that lack values, names, and palette properties by specifying the
ee.Reducer.frequencyHistogram()
as the reducerThis is not the best method however. Charts will lack descriptive class names and colors
# LCMAP example
Map.clearMap()
lcpri = ee.ImageCollection("projects/sat-io/open-datasets/LCMAP/LCPRI").select(['b1'],['LC'])
Map.addTimeLapse(lcpri,{'min':1,'max':9,'canAreaChart':True,"areaChartParams":{'reducer':ee.Reducer.frequencyHistogram()}},'LCMAP LC Primary')
Map.turnOnAutoAreaCharting()
Map.view()
Adding layer: LCMAP LC Primary
Starting webmap
Using default refresh token for geeView
Local web server at: http://localhost:8001/geeView/ already serving.
cwd a:\GEE\gee_py_modules_package\geeViz\examples
geeView URL: http://localhost:8001/geeView/?projectID=lcms-292214&accessToken=ya29.a0AeDClZDmawXDukWmO9oLKizTo6w7P9NlqXfKoaSIpzcAnlYGfgLMuBe34OfhIdC4T-bGS2FiEQpv42PPAgg3F1S8L5tTEZbWNnwCIheDSLkFekhdRunGkABnR_qx-2Z8J9NSmTr3pLc625m_vRcRl5c022VRG-mlVolIdq9qPqgaCgYKAV0SARESFQHGX2MiSeg0dJ97aOa4_Ib-smh2Ng0178&accessTokenCreationTime=1732169560625
Setting properties for charting#
The easiest way to chart thematic data where each class has a number, name, and color, but lack the preset properties, is to set them on-the-fly
These properties can then be used for charting and map rendering
# LCMAP example
Map.clearMap()
lcpri_palette = ['E60000','A87000','E3E3C2','1D6330','476BA1','BAD9EB','FFFFFF','B3B0A3','A201FF']
lc_names = ['Developed','Cropland','Grass/Shrub','Tree Cover','Water','Wetlands','Ice/Snow','Barren','Class Change']
lc_numbers = list(range(1,len(lcpri_palette)+1))
lcpri = ee.ImageCollection("projects/sat-io/open-datasets/LCMAP/LCPRI").select(['b1'],['LC'])
lcpri = lcpri.map(lambda img:img.set({'LC_class_values':lc_numbers,'LC_class_names':lc_names,'LC_class_palette':lcpri_palette}))
Map.addTimeLapse(lcpri,{'autoViz':True,'canAreaChart':True,'areaChartParams':{'line':True,'sankey':True}},'LCMAP LC Primary')
Map.turnOnAutoAreaCharting()
Map.view()
Adding layer: LCMAP LC Primary
Starting webmap
Using default refresh token for geeView
Local web server at: http://localhost:8001/geeView/ already serving.
cwd a:\GEE\gee_py_modules_package\geeViz\examples
geeView URL: http://localhost:8001/geeView/?projectID=lcms-292214&accessToken=ya29.a0AeDClZBE3rUf41t3ynct3TmFS9goflI3KxzwcFtJSPVFhjP-3bciOy90PgBO4ljJoWWQbcjYKjicRJGLxNds9V5CJvKnYv2uM2iU1aOgKxZ36FvToD5ZzOW7ddz9-pIWwDg8u-fIcr3PD3sLW7fe3E6GQFk01PWS4tmTmhTaAl8aCgYKAdASARESFQHGX2MitHZij8OK-HBPFllpNUWadg0178&accessTokenCreationTime=1732169652439
Comparing map output versions#
One common task is to understand the differences between 2 or more model runs. This can be challenging.
This example will show three versions of LCMS products and how they relate
This approach makes comparing the maps and their respective class counts relatively easy
This idea could be adapted to comparing different thematic or continuous outputs
Map.clearMap()
# Bring in 3 different LCMS versions
lcms_2020 = ee.ImageCollection("USFS/GTAC/LCMS/v2020-5").filter('study_area=="CONUS"')
lcms_2021 = ee.ImageCollection("USFS/GTAC/LCMS/v2021-7").filter('study_area=="CONUS"')
lcms_2022 = ee.ImageCollection("USFS/GTAC/LCMS/v2022-8").filter('study_area=="CONUS"')
lcms_2023 = ee.ImageCollection("USFS/GTAC/LCMS/v2023-9").filter('study_area=="CONUS"')
# Choose a year to compare (any year 1985-2020)
year = 2010
# Filter off the image and set that image to the version year
lcms_2020 = lcms_2020.filter(ee.Filter.calendarRange(year,year,'year')).first().set({'year':2020,'system:time_start':ee.Date.fromYMD(2020,6,1).millis()})
lcms_2021 = lcms_2021.filter(ee.Filter.calendarRange(year,year,'year')).first().set({'year':2021,'system:time_start':ee.Date.fromYMD(2021,6,1).millis()})
lcms_2022 = lcms_2022.filter(ee.Filter.calendarRange(year,year,'year')).first().set({'year':2022,'system:time_start':ee.Date.fromYMD(2022,6,1).millis()})
lcms_2023 = lcms_2023.filter(ee.Filter.calendarRange(year,year,'year')).first().set({'year':2023,'system:time_start':ee.Date.fromYMD(2023,6,1).millis()})
# Construct the image collection
c = ee.ImageCollection([lcms_2020,lcms_2021,lcms_2022,lcms_2023])
# Add the collection as a timelapse
# Will need to specify the transition years as the years used for each image, otherwise geeViz will default to only showing the first and last year
# Note that if you specify the sankey transition periods, any periods you enter in the geeViz UI will not be used for that layer
for bn in ['Change','Land_Cover','Land_Use']:
Map.addTimeLapse(c.select([bn]),{'autoViz':True,'canAreaChart':True,'areaChartParams':{'sankey':True,
'sankeyTransitionPeriods':[[2020,2020],[2021,2021],[2022,2022],[2023,2023]]
}}, f"LCMS {bn.replace('_',' ')} Comparison {year}")
Map.turnOnAutoAreaCharting()
Map.view()
c:\Users\ihousman\AppData\Local\Programs\Python\Python311\Lib\site-packages\ee\deprecation.py:207: DeprecationWarning:
Attention required for USFS/GTAC/LCMS/v2020-5! You are using a deprecated asset.
To ensure continued functionality, please update it.
Learn more: https://developers.google.com/earth-engine/datasets/catalog/USFS_GTAC_LCMS_v2020-5
warnings.warn(warning, category=DeprecationWarning)
c:\Users\ihousman\AppData\Local\Programs\Python\Python311\Lib\site-packages\ee\deprecation.py:207: DeprecationWarning:
Attention required for USFS/GTAC/LCMS/v2021-7! You are using a deprecated asset.
To ensure continued functionality, please update it.
Learn more: https://developers.google.com/earth-engine/datasets/catalog/USFS_GTAC_LCMS_v2021-7
warnings.warn(warning, category=DeprecationWarning)
c:\Users\ihousman\AppData\Local\Programs\Python\Python311\Lib\site-packages\ee\deprecation.py:207: DeprecationWarning:
Attention required for USFS/GTAC/LCMS/v2022-8! You are using a deprecated asset.
To ensure continued functionality, please update it.
Learn more: https://developers.google.com/earth-engine/datasets/catalog/USFS_GTAC_LCMS_v2022-8
warnings.warn(warning, category=DeprecationWarning)
Adding layer: LCMS Change Comparison 2010
Adding layer: LCMS Land Cover Comparison 2010
Adding layer: LCMS Land Use Comparison 2010
Starting webmap
Using default refresh token for geeView
Local web server at: http://localhost:8001/geeView/ already serving.
cwd a:\GEE\gee_py_modules_package\geeViz\examples
geeView URL: http://localhost:8001/geeView/?projectID=lcms-292214&accessToken=ya29.a0AeDClZD6JxbWi078FtM79_BeIKn2hGPtQvOfSbTkG0tNDgKyzDTdA43Ddjf-zHPe9n3L4jdSwTrA3YO5vD_gwS680uHwVbMJ48YU4zGg4TDd0Uvwew3z_qq8I9GRK9cvh1YmiBv642eY5BhQqpve_ns98U93p5l8ztQS0sAvbggaCgYKARsSARESFQHGX2MiWzcQ5PhrEcBC3wtjWUcqkg0178&accessTokenCreationTime=1732169696345
Other charting summary zone selection methods#
All examples have simply used the map extent as the zone to chart
There are other methods available
This example will show how to add a featureCollection to interactively select areas to summarize
All area selection will happen in the geeViz UI, under
Tools -> Area Tools -> Select an Area on Map
Map.clearMap()
for bn in ['Change','Land_Cover','Land_Use']:
Map.addLayer(lcms.select([bn]),{'autoViz':True,'canAreaChart':True}, f"LCMS {bn.replace('_',' ')} ")
# Bring in MTBS burn boundaries
mtbsBoundaries = ee.FeatureCollection("USFS/GTAC/MTBS/burned_area_boundaries/v1")
mtbsBoundaries = mtbsBoundaries.map(
lambda f: f.set("system:time_start", f.get("Ig_Date"))
)
# For area charting you can select areas to chart a number of ways. One method is using a map layer that is selectable by clicking on each feature.
Map.addSelectLayer(
mtbsBoundaries,
{
"strokeColor": "00F",
"selectLayerNameProperty": "Incid_Name",
},
"MTBS Fire Boundaries"
)
Map.turnOnSelectionAreaCharting()
Map.view()
Adding layer: LCMS Change
Adding layer: LCMS Land Cover
Adding layer: LCMS Land Use
Adding layer: MTBS Fire Boundaries
Starting webmap
Using default refresh token for geeView
Local web server at: http://localhost:8001/geeView/ already serving.
cwd a:\GEE\gee_py_modules_package\geeViz\examples
geeView URL: http://localhost:8001/geeView/?projectID=lcms-292214&accessToken=ya29.a0AeDClZBvafOCftFThE78i2zwWG34pYXzIRloRQ-qwsZ6O_Li22nUDmhYuvjQ252SF3npQhNR-Rjg4lInCL3TDlD3xvKgaHASqIX3MUSNFrXTlJZYkQ7tnPHY_NIFuoOAwgElS0AAvLVSnXifuaHQUgKKh77A04sLI_imBP_1yeUaCgYKAe8SARESFQHGX2Mi9nlpC9xjpq7pAmV7xBP8zg0178&accessTokenCreationTime=1732169830804