Commit message:
planemo upload for repository https://github.com/galaxyecology/tools-ecology/tree/master/tools/earth commit 4cbace8c3a71b7a1638cfd44a21f5d4b84d2fd15 |
added:
land_cover.py landcover_subindic.xml test-data/EU_CLC_1990.tiff test-data/EU_CLC_2018.tiff test-data/change_yf_yi0.shp test-data/landcover.json |
b |
diff -r 000000000000 -r 828c02027180 land_cover.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/land_cover.py Mon Oct 21 16:47:10 2024 +0000 |
[ |
b'@@ -0,0 +1,268 @@\n+# Land Cover TE Algorithm Without GEE\n+\n+# How to Execute:\n+# - Load the two images (.TIFF) of the rasters\n+# to be processed in the "/data/land_cover/input" folder\n+# - Setting the two filenames in the specific cell of this script (0)\n+# - Run all cells of the script\n+# - Check the script results in the "/data/land_cover/output" folder\n+# - Land Cover Degradation "/data/land_cover/output/lc_dg.tiff"\n+# - Land Cover Transition "/data/land_cover/output/lc_tr.tiff"\n+\n+# Librairies import\n+import argparse\n+import json\n+import os\n+import sys\n+\n+import matplotlib.pyplot as plt\n+\n+import numpy as np\n+\n+import rasterio\n+from rasterio.plot import show\n+\n+from te_schemas.land_cover import LCLegendNesting\n+from te_schemas.land_cover import LCTransitionDefinitionDeg\n+\n+# Methods to manage Rasters\n+\n+\n+def remap(raster, problem_numbers, alternative_numbers):\n+ n_min, n_max = raster.min(), raster.max()\n+ replacer = np.arange(n_min, n_max + 1)\n+ mask = (problem_numbers >= n_min) & (problem_numbers <= n_max)\n+ replacer[problem_numbers[mask] - n_min] = alternative_numbers[mask]\n+ raster_replaced = replacer[raster - n_min]\n+ return raster_replaced\n+\n+\n+def saveRaster(dataset, datasetPath, cols, rows, projection, namedataset=None):\n+ if namedataset:\n+ rasterSet = rasterio.open(datasetPath,\n+ \'w\',\n+ driver=\'GTiff\',\n+ height=rows,\n+ width=cols,\n+ count=1,\n+ dtype=np.int8,\n+ crs=projection,\n+ transform=transform, )\n+ rasterSet.write(dataset, 1)\n+ rasterSet.close()\n+ else:\n+ rasterSet = rasterio.open(datasetPath,\n+ \'w\',\n+ driver=\'GTiff\',\n+ height=rows,\n+ width=cols,\n+ count=1,\n+ dtype=np.int8,\n+ crs=projection,\n+ transform=transform, )\n+ rasterSet.write(dataset, 1)\n+ rasterSet.set_band_description(1, namedataset)\n+ rasterSet.close()\n+\n+\n+def plot(ndviImage, cmap):\n+ src = rasterio.open(ndviImage, \'r\')\n+ fig, ax = plt.subplots(1, figsize=(12, 12))\n+ show(src, cmap=cmap, ax=ax)\n+ ax.set_xlabel(\'Est\')\n+ ax.set_ylabel(\'Nord\')\n+ plt.show()\n+\n+\n+def plotContour(ndviImage, cmap):\n+ src = rasterio.open(ndviImage, \'r\')\n+ fig, ax = plt.subplots(1, figsize=(12, 12))\n+ show(src, cmap=cmap, contour=True, ax=ax)\n+ ax.set_xlabel(\'Est\')\n+ ax.set_ylabel(\'Nord\')\n+ plt.show()\n+\n+\n+# Setting inputs\n+command_line_args = sys.argv[1:]\n+\n+\n+parser = argparse.ArgumentParser(description="landcover inputs and outputs")\n+# Add arguments\n+parser.add_argument("--raster_1", help="raster 1")\n+parser.add_argument("--raster_2", help="raster 2")\n+parser.add_argument("--json", help="json")\n+\n+args = parser.parse_args(command_line_args)\n+\n+# Parse the command line arguments\n+\n+# Import data\n+\n+path_raster_yi = args.raster_1\n+path_raster_yf = args.raster_2\n+fjson = args.json\n+# Input Rasters\n+\n+# Outputs\n+out_dir = os.path.join(os.getcwd(), "data/land_cover/output/")\n+if not os.path.exists(out_dir):\n+ os.makedirs(out_dir)\n+\n+# Output Rasters\n+path_lc_tr = os.path.join(out_dir, \'lc_tr.tiff\')\n+path_lc_bl = os.path.join(out_dir, \'lc_bl.tiff\')\n+path_lc_dg = os.path.join(out_dir, \'lc_dg.tiff\')\n+path_lc_tg = os.path.join(out_dir, \'lc_tg.tiff\')\n+path_change_yf_yi = os.path.join(out_dir, \'change_yf_yi.tiff\')\n+path_lc_baseline_esa = os.path.join(out_dir, \'lc_baseline_esa.tiff\')\n+path_lc_target_esa = os.path.join(out_dir, \'lc_target_esa.tiff\')\n+path_out_img = os.path.join(out_dir, \'stack.tiff\')\n+\n+# Contours\n+contours_change_yf_yi = os.path.jo'..b'r_yi = rasterio.open(path_raster_yi)\n+lc_baseline_esa = raster_yi.read(1)\n+yi_dict_profile = dict(raster_yi.profile)\n+\n+for k in yi_dict_profile:\n+ print(k.upper(), yi_dict_profile[k])\n+\n+# Target ESA Raster\n+raster_yf = rasterio.open(path_raster_yf)\n+lc_target_esa = raster_yf.read(1)\n+yf_dict_profile = dict(raster_yf.profile)\n+\n+for k in yf_dict_profile:\n+ print(k.upper(), yf_dict_profile[k])\n+\n+cols = raster_yi.width\n+rows = raster_yf.height\n+transform = raster_yi.transform\n+projection = raster_yi.crs\n+\n+# Setting up output\n+saveRaster(lc_baseline_esa.astype(\'int8\'),\n+ path_lc_baseline_esa,\n+ cols,\n+ rows,\n+ projection,\n+ "Land_cover_yi")\n+\n+saveRaster(lc_target_esa.astype(\'int8\'),\n+ path_lc_target_esa,\n+ cols,\n+ rows,\n+ projection,\n+ "Land_cover_yf")\n+\n+# Algorithm execution\n+# Transition codes are based on the class code indices\n+# (i.e. their order when sorted by class code) -\n+# not the class codes themselves.\n+# So need to reclass the land cover used for the transition calculations\n+# from the raw class codes to the positional indices of those class codes.\n+# And before doing that, need to reclassified initial and\n+# final layers to the IPCC (or custom) classes.\n+\n+# Processing baseline raster\n+bl_remap_1 = remap(lc_baseline_esa,\n+ np.asarray(esa_to_custom_nesting.get_list()[0]),\n+ np.asarray(esa_to_custom_nesting.get_list()[1]))\n+lc_bl = remap(bl_remap_1, np.asarray(class_codes), np.asarray(class_positions))\n+\n+saveRaster(lc_bl.astype(\'int8\'),\n+ path_lc_bl,\n+ cols,\n+ rows,\n+ projection,\n+ "Land_cover_yi")\n+\n+# Processing Target Raster\n+tg_remap_1 = remap(lc_target_esa,\n+ np.asarray(esa_to_custom_nesting.get_list()[0]),\n+ np.asarray(esa_to_custom_nesting.get_list()[1]))\n+lc_tg = remap(tg_remap_1, np.asarray(class_codes), np.asarray(class_positions))\n+\n+saveRaster(lc_tg.astype(\'int8\'),\n+ path_lc_tg,\n+ cols,\n+ rows,\n+ projection,\n+ "Land_cover_yf")\n+\n+# Processing Transition Map\n+# Compute transition map (first digit for baseline land cover,\n+# and second digit for target year land cover)\n+lc_tr = (lc_bl * esa_to_custom_nesting.parent.get_multiplier()) + lc_tg\n+\n+# Compute land cover transition\n+# Remap persistence classes so they are sequential.\n+# This makes it easier to assign a clear color ramp in QGIS.\n+lc_tr_pre_remap = remap(lc_tr,\n+ np.asarray(trans_matrix.get_persistence_list()[0]),\n+ np.asarray(trans_matrix.get_persistence_list()[1]))\n+\n+saveRaster(lc_tr_pre_remap.astype(\'int8\'),\n+ path_lc_tr,\n+ cols,\n+ rows,\n+ projection,\n+ "Land_cover_transitions_yi-yf")\n+\n+# Compute land cover degradation\n+# definition of land cover transitions as degradation (-1),\n+# improvement (1), or no relevant change (0)\n+lc_dg = remap(lc_tr,\n+ np.asarray(trans_matrix.get_list()[0]),\n+ np.asarray(trans_matrix.get_list()[1]))\n+\n+saveRaster(lc_dg.astype(\'int8\'),\n+ path_lc_dg,\n+ cols,\n+ rows,\n+ projection,\n+ "Land_cover_degradation")\n+\n+# Compute Mutlibands stack\n+# Land Cover Degradation + Baseline ESA\n+# + Target ESA + Land Cover Transition\n+dg_raster = rasterio.open(path_lc_dg, "r")\n+dg = dg_raster.read(1, masked=True)\n+baseline_esa = rasterio.open(path_lc_baseline_esa, "r").read(1, masked=True)\n+target_esa = rasterio.open(path_lc_target_esa, "r").read(1, masked=True)\n+tr = rasterio.open(path_lc_tr, "r").read(1, masked=True)\n+\n+band_list = [dg, lc_baseline_esa, lc_target_esa, tr]\n+out_meta = dg_raster.meta.copy()\n+out_meta.update({"count": 4})\n+\n+with rasterio.open(path_out_img, \'w\', **out_meta) as dest:\n+ for band_nr, src in enumerate(band_list, start=1):\n+ dest.write(src, band_nr)\n' |
b |
diff -r 000000000000 -r 828c02027180 landcover_subindic.xml --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/landcover_subindic.xml Mon Oct 21 16:47:10 2024 +0000 |
[ |
b'@@ -0,0 +1,151 @@\n+<tool id="landcover_subindicator" name="Land cover degradation" version="@TOOL_VERSION@+galaxy@VERSION_SUFFIX@" profile="20.01" license="MIT">\n+ <description>subindicator to track land changes</description>\n+ <macros>\n+ <token name="@TOOL_VERSION@">0.1.0</token>\n+ <token name="@VERSION_SUFFIX@">0</token>\n+ </macros>\n+ <requirements>\n+ <requirement type="package" version="1.26.3">numpy</requirement>\n+ <requirement type="package" version="3.8.4">matplotlib</requirement>\n+ <requirement type="package" version="1.3.10">rasterio</requirement>\n+ <requirement type="package" version="2.1.14">trends_earth_algorithms</requirement>\n+ <requirement type="package" version="2.1.14">trends_earth_schemas</requirement>\n+ </requirements>\n+ <command detect_errors="exit_code"><![CDATA[\n+ #if \'$method.json_file\' == "no"\n+ python \'$__tool_directory__/land_cover.py\'\n+ --raster_1 \'$raster_1\'\n+ --raster_2 \'$raster_2\'\n+ --json \'$json\'\n+ #else \n+ python \'$__tool_directory__/land_cover.py\'\n+ --raster_1 \'$raster_1\'\n+ --raster_2 \'$raster_2\'\n+ --json \'$__tool_directory__/test-data/landcover.json\'\n+ #end if\n+\n+ ]]></command>\n+ <inputs>\n+ <param name="raster_1" type="data" format="tiff" label="A raster image of the land at a reference year" />\n+ <param name="raster_2" type="data" format="tiff" label="A raster image of the land at the year you want to study" />\n+ <conditional name="method">\n+ <param name="json_file" type="select" label="Do you want to use the default file json or your customized one ?" help="A file containing the land specifications, you can directly use the default one or you can customize it beforehand. The default one can be obtained at https://github.com/fair-ease/earth-critical-zone-galaxy/blob/main/landcover.json">\n+ <option value="yes">Yes, use the standard land specification time</option>\n+ <option value="no">No, I will provide my own.</option>\n+ </param>\n+ <when value="yes">\n+ </when>\n+ <when value="no">\n+ <param name="json" type="data" format="json" label="A file containing the land specifications" help="You can customize as needed the default file https://github.com/fair-ease/earth-critical-zone-galaxy/blob/main/landcover.json"/>\n+ </when>\n+ </conditional>\n+ </inputs>\n+ <outputs>\n+ <collection name="output_tiff" type="list" label="Land cover raster outputs">\n+ <discover_datasets pattern="__name_and_ext__" directory="data/land_cover/output/" />\n+ </collection>\n+ <!--<collection name="output_png" type="list" label="Land cover plots">\n+ <discover_datasets pattern="__name_and_ext__" directory="data/land_cover/" />\n+ </collection>-->\n+ <data name="contour" format="shp" from_work_dir="data/land_cover/output/change_yf_yi0.shp" label="${tool.name} on ${on_string}" />\n+ </outputs>\n+ <tests>\n+ <test expect_num_outputs="2">\n+ <param name="raster_1" value="EU_CLC_1990.tiff"/>\n+ <param name="raster_2" value="EU_CLC_2018.tiff"/> \n+ <param name="json_file" value="yes"/>\n+ <output name="contour" value="change_yf_yi0.shp"/>\n+ <output_collection name="output_tiff" type="list" count="7">\n+ <element name="lc_baseline_esa" ftype="tiff">\n+ <assert_contents>\n+ <has_text text="LAEA Europe"/>\n+ <has_size size="977"/>\n+ </assert_contents>\n+ </element>\n+ <element name="lc_bl" ftype="tiff">\n+ <assert_contents>\n+ <has_text text="LAEA Europe"/>\n+ <has_size s'..b' <has_size size="977"/>\n+ </assert_contents>\n+ </element> \n+ <element name="lc_tr" ftype="tiff">\n+ <assert_contents>\n+ <has_text text="LAEA Europe"/>\n+ <has_size size="977"/>\n+ </assert_contents>\n+ </element> \n+ <element name="stack" ftype="tiff">\n+ <assert_contents>\n+ <has_text text="LAEA Europe"/>\n+ <has_size size="977"/>\n+ </assert_contents>\n+ </element> \n+ </output_collection>\n+ </test>\n+ </tests>\n+ <help><![CDATA[\n+\n+**What it does**\n+This tool aims at facilitating the analysis of remotely-sensed datasets in support of monitoring land degradation. \n+This project contains common code used by the scripts in trends.earth.\n+\n+To assess changes in land cover users need land cover maps covering the study area for the baseline and target years. These maps need to be of acceptable accuracy and created in such a way which allows for valid comparisons. Trends.Earth uses ESA CCI land cover maps as the default dataset, but local maps can also be used. The indicator is computed as follows:\n+\n+ - Reclassify both land cover maps to the 7 land cover classes needed for reporting to the UNCCD (forest, grassland, cropland, wetland, artificial area, bare land and water).\n+ - Perform a land cover transition analysis to identify which pixels remained in the same land cover class, and which ones changed.\n+ - Based on your local knowledge of the conditions in the study area and the land degradation processed occurring there, use the table below to identify which transitions correspond to degradation (- sign), improvement (+ sign), or no change in terms of land condition (zero).\n+ - This tool will combine the information from the land cover maps and the table of degradation typologies by land cover transition to compute the land cover sub-indicator.\n+\n+**Input**\n+- One referenced raster of the land at an initial year\n+- A second raster of the same location at a final study year \n+\n+You can get these data on the `ESA (European Spatial Agency) website<https://www.esa-landcover-cci.org/?q=node/164>`. For more information follow the `Trends Earth doumentation<http://docs.trends.earth/en/latest/for_users/datasets/input_data.html>`\n+\n+- json file containing the 7 land cover classes. We specify by default a json feel free to customize it according to your need.\n+\n+\n+In the json config file you find defined a way to map ESA land cover classes into (the 7) IPCC land cover classes.\n+As a user you can add a new set of rules to map land cover classes from any system (ESA, CLC, \xe2\x80\xa6) to the IPCC ones. In the end, the user can do three different things:\n+\n+ - Use the default set of mapping rules findable on this `github repository<https://github.com/fair-ease/earth-critical-zone-galaxy/blob/main/landcover.json>`\n+ - Modify an existent set of mapping rules with custom associations\n+ - Add a new set of rules, useful for any custom map depicting land cover\n+\n+See also custom `land cover classes<http://docs.trends.earth/en/latest/for_users/training/settings.html#custom-land-cover-classes>`.\n+\n+**Output**\n+- A potential Land degradation raster\n+In the json config file there is also the definition of the transformation of the land use change into the three output classes (Degradation, Improvement, and Stable)\n+\n+For more information go on `the official trends earth documentation<http://docs.trends.earth/en/latest/for_users/features/unccdreporting.html>`\n+\n+ ]]></help>\n+ <citations>\n+ <citation type="bibtex">\n+ @Manual{\n+ title = {Trends.Earth. Conservation International},\n+ year = {2022},\n+ note = {http://trends.earth}\n+ }\n+ </citation>\n+ </citations>\n+</tool>\n' |
b |
diff -r 000000000000 -r 828c02027180 test-data/EU_CLC_1990.tiff |
b |
Binary file test-data/EU_CLC_1990.tiff has changed |
b |
diff -r 000000000000 -r 828c02027180 test-data/EU_CLC_2018.tiff |
b |
Binary file test-data/EU_CLC_2018.tiff has changed |
b |
diff -r 000000000000 -r 828c02027180 test-data/change_yf_yi0.shp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-data/change_yf_yi0.shp Mon Oct 21 16:47:10 2024 +0000 |
b |
@@ -0,0 +1,17 @@ +<html><head><title>Shapefile Galaxy Composite Dataset</title></head><p/> +<div>This composite dataset is composed of the following files:<p/><ul> +<li><a href="shapefile.shp" type="application/binary">shapefile.shp (Geometry File (shp))</a></li> +<li><a href="shapefile.shx" type="application/binary">shapefile.shx (Geometry index File (shx))</a></li> +<li><a href="shapefile.dbf" type="application/binary">shapefile.dbf (Columnar attributes for each shape (dbf))</a></li> +<li><a href="shapefile.prj" type="application/binary">shapefile.prj (Projection description (prj))</a> (optional)</li> +<li><a href="shapefile.sbn" type="application/binary">shapefile.sbn (Spatial index of the features (sbn))</a> (optional)</li> +<li><a href="shapefile.sbx" type="application/binary">shapefile.sbx (Spatial index of the features (sbx))</a> (optional)</li> +<li><a href="shapefile.fbn" type="application/binary">shapefile.fbn (Read only spatial index of the features (fbn))</a> (optional)</li> +<li><a href="shapefile.fbx" type="application/binary">shapefile.fbx (Read only spatial index of the features (fbx))</a> (optional)</li> +<li><a href="shapefile.ain" type="application/binary">shapefile.ain (Attribute index of the active fields in a table (ain))</a> (optional)</li> +<li><a href="shapefile.aih" type="application/binary">shapefile.aih (Attribute index of the active fields in a table (aih))</a> (optional)</li> +<li><a href="shapefile.atx" type="application/binary">shapefile.atx (Attribute index for the dbf file (atx))</a> (optional)</li> +<li><a href="shapefile.ixs" type="application/binary">shapefile.ixs (Geocoding index (ixs))</a> (optional)</li> +<li><a href="shapefile.mxs" type="application/binary">shapefile.mxs (Geocoding index in ODB format (mxs))</a> (optional)</li> +<li><a href="shapefile.shp.xml" type="application/binary">shapefile.shp.xml (Geospatial metadata in XML format (xml))</a> (optional)</li> +</ul></div></html> |
b |
diff -r 000000000000 -r 828c02027180 test-data/landcover.json --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test-data/landcover.json Mon Oct 21 16:47:10 2024 +0000 |
[ |
b'@@ -0,0 +1,1446 @@\n+{\n+ "crosses_180th": false,\n+ "crs": "GEOGCS[\\"WGS 84\\",DATUM[\\"WGS_1984\\",SPHEROID[\\"WGS 84\\",6378137,298.257223563,AUTHORITY[\\"EPSG\\",\\"7030\\"]],AUTHORITY[\\"EPSG\\",\\"6326\\"]],PRIMEM[\\"Greenwich\\",0,AUTHORITY[\\"EPSG\\",\\"8901\\"]],UNIT[\\"degree\\",0.0174532925199433,AUTHORITY[\\"EPSG\\",\\"9122\\"]],AUTHORITY[\\"EPSG\\",\\"4326\\"]]",\n+ "legend_nesting_custom_to_ipcc": {\n+ "child": {\n+ "key": [\n+ {\n+ "code": 1,\n+ "color": "#787F1B",\n+ "description": null,\n+ "name_long": "Tree-covered",\n+ "name_short": "Tree-covered"\n+ },\n+ {\n+ "code": 2,\n+ "color": "#FFAC42",\n+ "description": null,\n+ "name_long": "Grassland",\n+ "name_short": "Grassland"\n+ },\n+ {\n+ "code": 3,\n+ "color": "#FFFB6E",\n+ "description": null,\n+ "name_long": "Cropland",\n+ "name_short": "Cropland"\n+ },\n+ {\n+ "code": 4,\n+ "color": "#00DB84",\n+ "description": null,\n+ "name_long": "Wetland",\n+ "name_short": "Wetland"\n+ },\n+ {\n+ "code": 5,\n+ "color": "#E60017",\n+ "description": null,\n+ "name_long": "Artificial",\n+ "name_short": "Artificial"\n+ },\n+ {\n+ "code": 6,\n+ "color": "#FFF3D7",\n+ "description": null,\n+ "name_long": "Other land",\n+ "name_short": "Bare land"\n+ },\n+ {\n+ "code": 7,\n+ "color": "#0053C4",\n+ "description": null,\n+ "name_long": "Water body",\n+ "name_short": "Water body"\n+ }\n+ ],\n+ "name": "Custom Land Cover",\n+ "nodata": {\n+ "code": -32768,\n+ "color": "#000000",\n+ "description": null,\n+ "name_long": "No data",\n+ "name_short": "No data"\n+ }\n+ },\n+ "nesting": {\n+ "-32768": [\n+ -32768\n+ ],\n+ "1": [\n+ 1\n+ ],\n+ "2": [\n+ 2\n+ ],\n+ "3": [\n+ 3\n+ ],\n+ "4": [\n+ 4\n+ ],\n+ "5": [\n+ 5\n+ ],\n+ "6": [\n+ 6\n+ ],\n+ "7": [\n+ 7\n+ ]\n+ },\n+ "parent": {\n+ "key": [\n+ {\n+ "code": 1,\n+ "color": "#787F1B",\n+ "description": null,\n+ "name_long": "Tree-covered",\n+ "name_short": "Tree-covered"\n+ },\n+ {\n+ "code": 2,\n+ "color": "#FFAC42",\n+ "description": null,\n+ "name_long": "Grassland",\n+ "name_short": "Grassland"\n+ },\n+ {\n+ "code": 3,\n+ "color": "#FFFB6E",\n+ "description": null,\n+ "name_long": "Cropland",\n+ "name_short": "Cropland"\n+ },\n+ {\n+ "code": 4,\n+ "color": "#00DB84",\n+ "description": null,\n+ "name_long": "Wetland",\n+ "name_short": "Wetland"\n+ },\n+ '..b'll,\n+ "name_long": "Artificial",\n+ "name_short": "Artificial"\n+ },\n+ "initial": {\n+ "code": 7,\n+ "color": "#0053C4",\n+ "description": null,\n+ "name_long": "Water body",\n+ "name_short": "Water body"\n+ },\n+ "meaning": "stable"\n+ },\n+ {\n+ "final": {\n+ "code": 6,\n+ "color": "#FFF3D7",\n+ "description": null,\n+ "name_long": "Other land",\n+ "name_short": "Bare land"\n+ },\n+ "initial": {\n+ "code": 7,\n+ "color": "#0053C4",\n+ "description": null,\n+ "name_long": "Water body",\n+ "name_short": "Water body"\n+ },\n+ "meaning": "stable"\n+ },\n+ {\n+ "final": {\n+ "code": 7,\n+ "color": "#0053C4",\n+ "description": null,\n+ "name_long": "Water body",\n+ "name_short": "Water body"\n+ },\n+ "initial": {\n+ "code": 7,\n+ "color": "#0053C4",\n+ "description": null,\n+ "name_long": "Water body",\n+ "name_short": "Water body"\n+ },\n+ "meaning": "stable"\n+ }\n+ ]\n+ },\n+ "legend": {\n+ "key": [\n+ {\n+ "code": 1,\n+ "color": "#787F1B",\n+ "description": null,\n+ "name_long": "Tree-covered",\n+ "name_short": "Tree-covered"\n+ },\n+ {\n+ "code": 2,\n+ "color": "#FFAC42",\n+ "description": null,\n+ "name_long": "Grassland",\n+ "name_short": "Grassland"\n+ },\n+ {\n+ "code": 3,\n+ "color": "#FFFB6E",\n+ "description": null,\n+ "name_long": "Cropland",\n+ "name_short": "Cropland"\n+ },\n+ {\n+ "code": 4,\n+ "color": "#00DB84",\n+ "description": null,\n+ "name_long": "Wetland",\n+ "name_short": "Wetland"\n+ },\n+ {\n+ "code": 5,\n+ "color": "#E60017",\n+ "description": null,\n+ "name_long": "Artificial",\n+ "name_short": "Artificial"\n+ },\n+ {\n+ "code": 6,\n+ "color": "#FFF3D7",\n+ "description": null,\n+ "name_long": "Other land",\n+ "name_short": "Bare land"\n+ },\n+ {\n+ "code": 7,\n+ "color": "#0053C4",\n+ "description": null,\n+ "name_long": "Water body",\n+ "name_short": "Water body"\n+ }\n+ ],\n+ "name": "Custom Land Cover",\n+ "nodata": {\n+ "code": -32768,\n+ "color": "#000000",\n+ "description": null,\n+ "name_long": "No data",\n+ "name_short": "No data"\n+ }\n+ },\n+ "name": "Land cover transition definition matrix"\n+ }\n+}\n\\ No newline at end of file\n' |