Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: check-json

- repo: https://github.com/abravalheri/validate-pyproject
rev: v0.23
hooks:
Expand Down
27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,33 @@ curl -G "$API_URL/tiles/WebMercatorQuad/4/3/6.png" \
`tilejson.json` forwards `where` into its tile template, so filtered
TileJSON URLs work in map clients unchanged.

## Custom colormaps

Besides rio-tiler's built-in colormaps, this service registers every
`src/titiler/multidim/cmap_data/<name>.json` file as colormap `<name>`. Each
file records its `source`, a `reference` URL, any `notes` on its limits, and
either color `stops` at data values or `breakpoints` onto another file's stops;
`colormaps.py` interpolates it into a 256-row table. titiler applies that table **after**
`rescale` stretches the data to 0-255, so each colormap is only meaningful with
the `rescale` listed below.

| `colormap_name` | What it is | Use with |
|---|---|---|
| [`worldview_rainbow_4`](src/titiler/multidim/cmap_data/worldview_rainbow_4.json) | NASA Worldview's "Rainbow 4" palette | the value range you would set in Worldview, e.g. `rescale=0,2e16` for TEMPO NO2 tropospheric column in molecules/cm² |
| [`naqfc_o3`](src/titiler/multidim/cmap_data/naqfc_o3.json) | NOAA Air Quality Forecast Guidance Viewer ozone ramp | `rescale=0,200` for data in ppb, `rescale=0,0.2` for ppm |
| [`naqfc_pm25`](src/titiler/multidim/cmap_data/naqfc_pm25.json) | the ozone ramp, stretched so each EPA PM2.5 AQI category gets its ozone category's colors | `rescale=0,225.4` for data in µg/m³ |

Every custom colormap places category boundaries to the nearest 1/255 of the
`rescale` range (0.8 ppb for ozone, 0.9 µg/m³ for PM2.5), and gives values
above the `rescale` maximum the top color and values below the minimum the
bottom color.

```bash
curl -G "$API_URL/tiles/WebMercatorQuad/4/3/6.png" \
--data-urlencode "url=..." --data-urlencode "variable=vertical_column" \
--data-urlencode "rescale=0,2e16" --data-urlencode "colormap_name=worldview_rainbow_4"
```

## Authorizing icechunk virtual chunk access

Icechunk datasets can reference "virtual chunks" stored outside the repository (for example NetCDF files in another bucket). Access to those locations is denied unless each container URL prefix is explicitly authorized via the `TITILER_MULTIDIM_AUTHORIZED_CHUNK_ACCESS` setting, a JSON object mapping prefixes to access options:
Expand Down
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ ignore = [

[tool.ruff.lint.per-file-ignores]
"tests/test_app.py" = ["D1"]
"tests/test_cmaps.py" = ["D1"]
"tests/test_chunk_access.py" = ["D1"]
"tests/test_settings.py" = ["D1"]
"tests/test_earthdata.py" = ["D1"]
Expand All @@ -142,6 +143,9 @@ strict_optional = true
namespace_packages = true
explicit_package_bases = true

[tool.uv]
exclude-newer = "1 week"

[build-system]
requires = ["pdm-backend"]
build-backend = "pdm.backend"
Expand Down
28 changes: 28 additions & 0 deletions src/titiler/multidim/cmap_data/naqfc_o3.json

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moving the tables to JSON files is a nice improvement!

The only trap we need to avoid is the potential for accidental duplicate keys, which can go silently unnoticed. For example, if we were to accidentally write the "110" key as "100", it would be a duplicate of the preceding, correct entry for "100", but json.loads doesn't complain about duplicate keys. It simply allows the last key to "win".

However, if we add the following to .pre-commit-config.yaml, it will fail pre-commit if any JSON file contains duplicate keys anywhere (I suggest listing it as the first repo in the repos list. Although order doesn't matter, it's simply conventional for pre-commit's own hooks.):

  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v6.0.0
    hooks:
    - id: check-json

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"source": "NOAA Air Quality Forecast Guidance Viewer ozone ramp (ppb), one color per 10 ppb, sampled by hand from the provider's screenshot in the referenced pull request",
"reference": "https://github.com/NASA-IMPACT/veda-backend/pull/665",
"notes": "Sampled from a screenshot, not from a provider color table. The provider's stated intent (Air-Quality-Portal/aq-arch#192) is category boundaries at the EPA breakpoints (54, 70, 85, 105, 200 ppb) with a gradient inside each category; these stops do not change color exactly at those breakpoints. Replace them when the provider supplies the table.",
"stops": {
"0": "#AFFEB0",
"10": "#7EFE7E",
"20": "#4BFF4C",
"30": "#08F001",
"40": "#03C300",
"50": "#008700",
"60": "#E1E103",
"70": "#FEBC2E",
"80": "#E17411",
"90": "#FE7879",
"100": "#BE0001",
"110": "#F0B4E7",
"120": "#DC8CD3",
"130": "#C864BF",
"140": "#B43DAB",
"150": "#A02497",
"160": "#8B1D83",
"170": "#781470",
"180": "#640D5B",
"190": "#500347",
"200": "#3C003C"
}
}
14 changes: 14 additions & 0 deletions src/titiler/multidim/cmap_data/naqfc_pm25.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"source": "EPA AQI category breakpoints, 24-hour PM2.5 (ug/m3) mapped to 8-hour ozone (ppb), so each PM2.5 category spans the same naqfc_o3 colors as its ozone category",
"reference": "https://aqs.epa.gov/aqsweb/documents/codetables/aqi_breakpoints.html",
"notes": "Borrows the naqfc_o3 stops, so it shares their limits: see that file's notes.",
"ramp": "naqfc_o3",
"breakpoints": {
"0.0": 0.0,
"9.0": 54.0,
"35.4": 70.0,
"55.4": 85.0,
"125.4": 105.0,
"225.4": 200.0
}
}
262 changes: 262 additions & 0 deletions src/titiler/multidim/cmap_data/worldview_rainbow_4.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
{
"source": "NASA Worldview custom palette \"Rainbow 4\" (255 colors), verbatim at the referenced commit, with the top color repeated to fill row 255",
"reference": "https://github.com/nasa-gibs/worldview/blob/7d16ee53eb38a90fe66c9860015b51094c96ed25/config/default/common/config/palettes-custom.json/rainbow_4.json",
"stops": {
"0": "#3b76c6",
"1": "#3a78c6",
"2": "#3979c6",
"3": "#377cc6",
"4": "#367ec6",
"5": "#3680c6",
"6": "#3584c6",
"7": "#3587c5",
"8": "#368ac5",
"9": "#368dc4",
"10": "#3890c3",
"11": "#3a94c2",
"12": "#3c97c1",
"13": "#3f9bbf",
"14": "#429fbe",
"15": "#45a2bc",
"16": "#49a6bb",
"17": "#4ca9b9",
"18": "#51acb7",
"19": "#54afb6",
"20": "#58b2b5",
"21": "#5db5b3",
"22": "#60b8b2",
"23": "#65bbb0",
"24": "#69bdaf",
"25": "#6dc0af",
"26": "#73c2ae",
"27": "#77c4ad",
"28": "#7cc7ad",
"29": "#80c9ac",
"30": "#85caac",
"31": "#8accac",
"32": "#8eceac",
"33": "#94d0ac",
"34": "#98d2ac",
"35": "#9dd3ab",
"36": "#a2d5ab",
"37": "#a6d6aa",
"38": "#acd8a9",
"39": "#b0daa9",
"40": "#b4dba8",
"41": "#b9dda7",
"42": "#bddea6",
"43": "#c2e0a4",
"44": "#c5e1a3",
"45": "#c9e2a2",
"46": "#cde4a1",
"47": "#d1e6a1",
"48": "#d5e7a0",
"49": "#d8e9a0",
"50": "#dbeaa0",
"51": "#dfeca0",
"52": "#e2eda0",
"53": "#e5efa1",
"54": "#e7f0a3",
"55": "#eaf1a4",
"56": "#ecf3a6",
"57": "#eef4a8",
"58": "#f1f5ab",
"59": "#f2f6ad",
"60": "#f4f7af",
"61": "#f6f8b2",
"62": "#f7f9b4",
"63": "#f8f9b7",
"64": "#f9fab9",
"65": "#fafaba",
"66": "#fbfabc",
"67": "#fcfabd",
"68": "#fdf9be",
"69": "#fdf9be",
"70": "#fef8bd",
"71": "#fef7bc",
"72": "#fef6bb",
"73": "#fff5b9",
"74": "#fff3b7",
"75": "#fff2b5",
"76": "#fff0b1",
"77": "#ffefaf",
"78": "#ffedab",
"79": "#feeba7",
"80": "#fee9a4",
"81": "#fee79f",
"82": "#fee59c",
"83": "#fee397",
"84": "#fee093",
"85": "#fede90",
"86": "#fedc8c",
"87": "#fed988",
"88": "#fed784",
"89": "#fed481",
"90": "#fed27f",
"91": "#fecf7b",
"92": "#fecd79",
"93": "#feca76",
"94": "#fec773",
"95": "#fec571",
"96": "#fec16e",
"97": "#febf6c",
"98": "#febb69",
"99": "#feb867",
"100": "#feb564",
"101": "#feb262",
"102": "#feaf60",
"103": "#feab5d",
"104": "#fea75b",
"105": "#fea459",
"106": "#fea056",
"107": "#fe9d55",
"108": "#fe9953",
"109": "#fe9552",
"110": "#fe9251",
"111": "#fd8e50",
"112": "#fd8b50",
"113": "#fd8750",
"114": "#fc8450",
"115": "#fc8151",
"116": "#fb7e52",
"117": "#fa7b53",
"118": "#f97754",
"119": "#f87556",
"120": "#f67257",
"121": "#f56f59",
"122": "#f36d5a",
"123": "#f26a5c",
"124": "#f0685d",
"125": "#ef655e",
"126": "#ed6360",
"127": "#ec6061",
"128": "#ea5e62",
"129": "#e85b63",
"130": "#e75964",
"131": "#e55665",
"132": "#e35466",
"133": "#e15266",
"134": "#df4f67",
"135": "#de4d68",
"136": "#db4b69",
"137": "#d94a6a",
"138": "#d8486b",
"139": "#d5466c",
"140": "#d3456c",
"141": "#d1436e",
"142": "#cf426e",
"143": "#cd416f",
"144": "#ca4070",
"145": "#c83f71",
"146": "#c53d72",
"147": "#c33c73",
"148": "#c13b74",
"149": "#be3a75",
"150": "#bc3976",
"151": "#b93877",
"152": "#b63778",
"153": "#b43679",
"154": "#b13579",
"155": "#af347a",
"156": "#ac337b",
"157": "#a9327b",
"158": "#a7317c",
"159": "#a3307c",
"160": "#a12f7d",
"161": "#9e2e7d",
"162": "#9b2d7d",
"163": "#992c7e",
"164": "#952b7e",
"165": "#932a7e",
"166": "#90297f",
"167": "#8d287f",
"168": "#8a277f",
"169": "#872680",
"170": "#852580",
"171": "#822480",
"172": "#802480",
"173": "#7d2380",
"174": "#7a2280",
"175": "#782180",
"176": "#762080",
"177": "#731f7f",
"178": "#711e7f",
"179": "#6f1d7f",
"180": "#6d1c7f",
"181": "#6a1b7e",
"182": "#681b7e",
"183": "#661a7e",
"184": "#63197d",
"185": "#61187d",
"186": "#5f177d",
"187": "#5d167c",
"188": "#5b157c",
"189": "#58157b",
"190": "#56147a",
"191": "#541379",
"192": "#521378",
"193": "#501277",
"194": "#4d1276",
"195": "#4b1274",
"196": "#491173",
"197": "#471171",
"198": "#44116f",
"199": "#42116d",
"200": "#40116b",
"201": "#3d1169",
"202": "#3b1167",
"203": "#391165",
"204": "#371062",
"205": "#351060",
"206": "#32105e",
"207": "#30105c",
"208": "#2e105a",
"209": "#2c1057",
"210": "#2a1055",
"211": "#281053",
"212": "#261051",
"213": "#25104f",
"214": "#23104d",
"215": "#22104b",
"216": "#200f49",
"217": "#1f0f48",
"218": "#1e0f46",
"219": "#1d0f44",
"220": "#1c0e43",
"221": "#1b0e41",
"222": "#1a0e3f",
"223": "#1a0d3e",
"224": "#190d3c",
"225": "#180d3a",
"226": "#180d39",
"227": "#170c37",
"228": "#170c36",
"229": "#160c34",
"230": "#150b32",
"231": "#150b31",
"232": "#140b2f",
"233": "#130a2e",
"234": "#130a2c",
"235": "#120a2a",
"236": "#110928",
"237": "#110927",
"238": "#100925",
"239": "#100924",
"240": "#0f0822",
"241": "#0e081f",
"242": "#0d071d",
"243": "#0d071c",
"244": "#0c071a",
"245": "#0b0618",
"246": "#0b0617",
"247": "#0a0616",
"248": "#0a0614",
"249": "#090513",
"250": "#080511",
"251": "#080510",
"252": "#08040f",
"253": "#07040e",
"254": "#07040d",
"255": "#07040d"
}
}
Loading
Loading