Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support categorical colour palettes #4

Open
robyngit opened this issue Oct 10, 2022 · 1 comment
Open

Support categorical colour palettes #4

robyngit opened this issue Oct 10, 2022 · 1 comment
Labels
enhancement New feature or request

Comments

@robyngit
Copy link
Member

In the future, we will need to process raster data that is categorical/qualitative in nature, e.g. the infrastructure layer. We need to be able to configure these types of colormaps and render web tiles that use them.

One option might be to start using the colormap functionality from the rio-tiler package. This package has other functionality that we will likely want to use when we build our workflow to accept raster data as input, instead of just vector data. (e.g. partial reads of GeoTIFFs, tiling overlapping GeoTIFFs, etc.)

@robyngit robyngit added the enhancement New feature or request label Oct 10, 2022
@julietcohen
Copy link
Collaborator

I have processed 2 datasets with categorical color palettes so far:

For the permafrost and ground ice layer, the attribute to visualize has four different letters that each represent one type (% range) of extent of the permafrost coverage for the geometry (c = continuous, d = discontinuous, s = sporadic, i = isolated patches). To process the data in the visualization workflow, I created dummy number codes, one for each of the four letters, so 1-4. The full cleaning script is at /var/data/10.18739/A2MG7FX35/clean_data.py, but the relevant snippet of code is below.

assign numerical code
input = "/home/jcohen/permafrost_ground_layer/data/permaice.shp"
perm = gpd.read_file(input)

# drop rows that have missing value for extent attribute
perm.dropna(subset = ['EXTENT'], inplace = True)

# add column that codes the categorical extent strings into numbers 
# in order to do stats with the workflow and assign palette to this
# first, define the conditions and choices for new extent_code attribute
conditions = [
    (perm['EXTENT'] == "C"),
    (perm['EXTENT'] == "D"),
    (perm['EXTENT'] == "S"),
    (perm['EXTENT'] == "I")
]

choices = [4, 3, 2, 1]

# Use numpy.select() to assign extent_code based on the conditions and choices
perm['extent_code'] = np.select(conditions, choices)

I made the palette 4 separate hex codes for 4 shades of blue.

For the infrastructure layer, the categories already were in numbers, so I did not have to add a dummy code attribute to visualize. Since there were 7 types of infrastructure, I made the palette 7 separate hex codes.

infrastructure config
{ 
  "dir_input": "/home/jcohen/infrastructure/data_cleaned_split", 
  "ext_input": ".gpkg",
  "dir_staged": "staged/",
  "dir_geotiff": "geotiff/", 
  "dir_web_tiles": "web_tiles/", 
  "filename_staging_summary": "staging_summary.csv",
  "filename_rasterization_events": "raster_events.csv",
  "filename_rasters_summary": "raster_summary.csv",
  "filename_config": "config",
  "simplify_tolerance": 0.1,
  "tms_id": "WGS1984Quad",
  "z_range": [
    0,
    12
  ],
  "geometricError": 57,
  "z_coord": 0,
  "statistics": [
    {
      "name": "infrastructure_code",
      "weight_by": "area", 
      "property": "DN",
      "aggregation_method": "max", 
      "resampling_method": "nearest",
      "val_range": [
        11,
        50
      ], 
      "palette": [
        "#f48525", 
        "#f4e625", 
        "#47f425", 
        "#25f4e2", 
        "#2525f4", 
        "#f425c3", 
        "#f42525" 
      ],
      "nodata_val": 0,
      "nodata_color": "#ffffff00"
    }
  ],
  "deduplicate_at": null,
  "deduplicate_keep_rules": null,
  "deduplicate_method": null,
  "clip_to_footprint": false
}

For both datasets, I made the val_range in the config have a min val of the smallest number possible of the categorical numerical codes, and the max val the largest of the numerical codes. The aggregation_method in the config is set to "max" and the resampling_method was set to "mode" for permafrost and ground ice, and "nearest" (nearest neighbor) for infrastructure. This way, no intermediate value is assigned to any pixel. We only want to see one of the several specified colors in the config.

In order to communicate the string label of each color to the user on the PDG, we simply give the label for each category in the legend in the XML. See below the snippet of the XML for the infrastructure for example.

assign labels in XML
"colorPalette": {
        "paletteType": "categorical",
        "property": "DN",
        "colors": [
          {
            "color": "#f48525",
            "label": "Linear transport infrastructure (asphalt)",
            "value": 11
          },
          {
            "color": "#f4e625",
            "label": "Linear transport infrastructure (gravel)",
            "value": 12
          },
          {
            "color": "#47f425",
            "label": "Linear transport infrastructure (undefined)",
            "value": 13
          },
          {
            "color": "#25f4e2",
            "label": "Buildings (and other constructions such as bridges)",
            "value": 20
          },
          {
            "color": "#2525f4",
            "label": "Other impacted area (includes gravel pads, mining sites)",
            "value": 30
          },
          {
            "color": "#f425c3",
            "label": "Airstrip",
            "value": 40
          },
          {
            "color": "#f42525",
            "label": "Reservoir or other water body impacted by human activities",
            "value": 50
          }
        ]
      }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: No status
Status: No status
Development

No branches or pull requests

2 participants