> For the complete documentation index, see [llms.txt](https://docs.mapbox.com/mapbox-tiling-service/llms.txt)

# Rasterarray Recipe

**Current version:** `1`

A **rasterarray recipe** is a JSON document containing configuration options that tell [Raster MTS](https://docs.mapbox.com/mapbox-tiling-service/raster/) how to turn raster source data into Mapbox Raster Tiles (MRT).

Recipes must be constructed according to the rules in this recipe reference.

## Recipe top-level fields

A recipe is a JSON object that must contain the following top-level fields:

| Required fields | Description | Data type |
| --- | --- | --- |
| [**version**](#option-version) | The version of the Mapbox Tiling Service recipe reference that the recipe uses. | `Integer` |
| [**type**](#option-type) | Key to show this as a Raster MTS recipe | `"rasterarray"` |
| [**sources**](#option-sources) | List of input source files | `List<SourceObject>` |
| [**layers**](#option-layers) | The names of the layers and their configuration options. | `Object<String, LayerObject>` |

| Optional fields | Description | Data type |
| --- | --- | --- |
| [**minzoom**](#option-minzoom) | The lowest zoom level for the tileset. For more information about this option, see the [Zoom Levels](#zoom-levels) section. | `Integer` |
| [**maxzoom**](#option-maxzoom) | The highest zoom level for the tileset. For more information about this option, see the [Zoom Levels](#zoom-levels) section. | `Integer` |

```json
{
  "version": 1,
  "type":"rasterarray",
  "sources":[{"uri":"mapbox://tileset-source/{ACCOUNT}/{SOURCE_NAME}"}],
  "minzoom":0,
  "maxzoom":6,
  "layers": { layername: LayerObject, ... }
}
```

## Recipe version

The recipe `version` indicates the version of the Raster MTS recipe reference that the recipe uses. The current version is `1`. Using any `version` other than the current version or a previous version will result in an error.

## Sources

The recipe `sources` object is a list of sources used to generate a tileset. This list must contain at least a single source.

### Source configuration

| Required fields | Description | Data type |
| --- | --- | --- |
| [**uri**](#source-object-uri) | The URI of the source uploaded into Mapbox. Sources are always prefixed with the `mapbox://` protocol. | `String` |

### Optional source configuration

| Optional fields | Description | Data type |
| --- | --- | --- |
| [**crs**](#source-object-crs) | The EPSG coordinate system code of the source file. This is an optional field and only necessary if the source file is missing a CRS. This will override the source file's CRS if passed in and the source file already contains a CRS. | `String` |

## Zoom Levels

The `minzoom` and `maxzoom` fields are optional and define the [zoom levels](https://docs.mapbox.com/help/glossary/zoom-level/) at which the tileset is available. The `minzoom` field is the lowest zoom level at which the tileset is available, and the `maxzoom` field is the highest zoom level at which the tileset is available. `maxzoom` must be greater than or equal to `minzoom`.

### Optional behavior

If `minzoom` and `maxzoom` are not provided, appropriate zoom levels will be calculated based on the `tilesize` and pixel resolution of the source data.

## Layers

The recipe `layers` object contains key-value pairs associating the names of tile layers with their configuration. For each key-value pair, the key is the name of the layer, and the value is a [`LayerObject`](#optional-layer-configuration) containing the configuration and options for the layer.

Each layer must have a name (for example `"temperature"`, `"precipitation"`, or `"cloud"` in the example below). This is the unique identifier for the layer of data in your final tileset. In any tileset, each layer name must be unique. The layer name must be a string with only underscores (`_`) and alphanumeric characters.

The corresponding `LayerObject` for each layer name describes how that MRTs should be created.

### Layer example

```json
...
  "layers": {
    "Pressure": {
      "tilesize": 512,
      "offset": -100,
      "buffer": 1,
      "scale": 0.1,
      "units": "Pa",
      "source_rules": {"name": ["to-number", ["get", "GRIB_VALID_TIME"]]},
    }
  },
...
```

### Optional layer configuration

| Optional fields | Description | Data type |
| --- | --- | --- |
| [**tilesize**](#layer-object-tilesize) | Tile size (excluding buffer). Must be a power of two | `Integer` |
| [**buffer**](#layer-object-buffer) | Number of pixels surrounding each edge of a tile | `Integer` |
| [**units**](#layer-object-units) | Units of layer variable | `String` |
| [**input_no_data_value**](#layer-object-input-no-data-value) | A source data value which denotes masked data | `Number` |
| [**resampling**](#layer-object-resampling) | Resampling applied to source data during reprojecting to spherical mercator tiles | `"nearest" | "bilinear" | "cubic" | "cubic_spline" | "lanczos" | "average" | "gauss" | "mode" | "min" | "max" | "med" | "q1" | "q3" | "sum" | "rms"` |
| [**source_rules**](#layer-object-source-rules) | Rules for mapping sources to bands | `Object<String, SourceRuleObject>` |
| [**offset**](#layer-object-offset) | Offset of the encoding, which defines the minimum permissible value. For more information about this option, see the [Offset and Scale](#offset-and-scale) section. | `Integer` |
| [**scale**](#layer-object-scale) | Scale of the encoding (for example a reasonable scale for temperature can be 0.1). For more information about this option, see the [Offset and Scale](#offset-and-scale) section. | `Float` |

#### Tile Size

The `tilesize` must be a power of two using values such as 128, 256, or 512 and defines the resolution (excluding the `buffer`) of data in each raster tile. The tile size is an essential control which helps manage data transfer and performance. Using a smaller `tilesize` will result in lower resolution imagery that loads faster. If not provided, 512 is used as the default value for `tilesize`.

For example, a `tilesize` of 512 may produce sharp, retina-resolution output but may be unnecessary to represent a smoothly varying temperature field with an added cost of larger data transfer per tile. In contrast, a `tilesize` of 128 would reduce the resolution by a factor of four and require one sixteenth the total data transfer.

#### Buffer

The `buffer` defines the number of pixels around the border of each tile which are duplicated across tiles. In general, this value should be `1` to decrease tile boundary artifacts when using a raster layer with linear resampling.

#### Units

Units is an optional string used strictly for annotating the data, for example so that units are presented to designers when styling the data in Mapbox Studio. Any string value is permitted, for example `"C"`, `"Celsius"`, or `"kg/m²/s"`.

#### Input NoData value

An input NoData value specifies a custom source data value which denotes masked pixels. Source data will often contain metadata which specifies how its mask is encoded. Instead of reencoding your source data when this metadata is not available or is not correct, you may use `input_no_data_value` to specify a custom NoData value. For example, `"input_no_data_value": 9999` would result in a tileset which masks all pixels with source data value 9999.

This option only affects interpretation of source data. The internal representation of masked pixels within MRT tiles is unrelated to `input_no_data_value`.

#### Resampling

The coordinate Coordinate Reference System (CRS) of your source data will often differ from Spherical Mercator projection with which MTS stores data for transmission and display. By default during the tiling phase, Raster MTS will resample your data using `bilinear` interpolation. Use the `resampling` layer configuration option to specify a different resampling strategy.

Note that this configuration option differs from the [`raster-resampling`](https://docs.mapbox.com/style-spec/reference/layers/#paint-raster-raster-resampling) Mapbox Style Spec property, which affects how tiled data is resampled during rendering to the screen.

#### Offset and Scale

While any numerical format is acceptable as source input, data in each layer is encoded as a 32-bit unsigned integer. A single value (2³² - 1) is reserved to denote NoData. Depending on the range and precision of your data, you must select a suitable floating point `offset` and `scale`. Given some encoded `pixel` value, the `value` is computed as:

```
value = offset + scale * pixel
```

The `offset` and `scale` have a significant effect on the resulting tileset. The `offset` defines the minimum value which may be encoded. Source values lower than this bound will trigger an error. The `scale` defines the fixed increment between each representable value.

To determine an appropriate `offset` and `scale` for your data, it is appropriate to examine the source input, for example using `gdalinfo -stats` to examine the range of data contained in each band. For example, to encode air temperature in Celsius, -100 might be a reasonably safe `offset` you never expect to exceed, although -274 is an offset which is impossible to exceed. The `offset` defines a permissible range of values but does not significantly impact the size of the resulting tileset.

The `scale` defines the precision of the resulting tileset, and as such has a significant effect on the size of the tileset. To reduce data transfer, choose a value as large as tolerable while balancing posterization due to quantization. For example, `0.1` may be an acceptable increment for temperatures in Celsius, while `1` or `10` degrees Celsius may be too large.

##### Optional behavior

> **Note**
> 
> `offset` and `scale` must be included or excluded together.

If `offset` AND `scale` are not provided, values will be selected automatically based on the range of the source data.

## Source Rules

Source rules are additional configuration that can be added to recipe for processing. They are build upon [expressions](https://docs.mapbox.com/help/glossary/expression/). Below are the supported expression rules for Raster MTS.

| Optional fields | Description | Data type |
| --- | --- | --- |
| [**filter**](#layer-object-filter) | Expression for selecting a single scalar element or vector elements of a raster | `expression` \| `[expression, expression]` |
| [**sort_key**](#layer-object-sort-key) | Expression for sorting the selected elements | `expression` |
| [**name**](#layer-object-name) | Expression for naming the selected elements | `expression` |
| [**order**](#layer-object-order) | Sorting order for the selected elements | `String` |

### Source rule example

```json
{
  "source_rules": {
    "filter": ["==", ["get", "GRIB_COMMENT"], "Total precipitation [kg/(m^2)]"],
    "sort_key": ["to-number", ["get", "GRIB_VALID_TIME"]],
    "name": ["to-number", ["get", "GRIB_VALID_TIME"]],
    "order": "asc"
  }
}
```

The `source_rules` field allows you to select elements of a raster. For example, in this recipe, the precipitation data exists in a band labeled with `Total precipitation [kg/(m^2)]`. You can find this information with `gdalinfo`.

The following construct indicates that Raster MTS should only process bands that have a GRIB_COMMENT that includes Total precipitation [kg/(m^2)].

```json
"filter": ["==", ["get","GRIB_COMMENT"], "Total precipitation [kg/(m^2)]"],
```

We then name the constructed slice of data with:

```json
"name": ["to-number", ["get","GRIB_VALID_TIME"]],
```

And then organize those distinct slices of data with:

```json
"order": "asc".
```

### Filter example (scalar)

```json
{
  "filter": ["==", ["get", "GRIB_COMMENT"], "Total precipitation [kg/(m^2)]"]
}
```

The `source_rules.filter` field allows you to select a single element of a raster by specifying a single filter rule. For example, in this recipe, the precipitation data exists in a band labeled with Total precipitation [kg/(m^2)]. You can find this information with gdalinfo.

### Filter example (vector)

```json
{
  "filter": [
    [
      "all",
      ["==", ["get", "GRIB_COMMENT"], "u-component of wind [m/s]"],
      ["==", ["get", "GRIB_SHORT_NAME"], "10-HTGL"]
    ],
    [
      "all",
      ["==", ["get", "GRIB_COMMENT"], "v-component of wind [m/s]"],
      ["==", ["get", "GRIB_SHORT_NAME"], "10-HTGL"]
    ]
  ]
}
```

The `source_rules.filter` field allows you to select vector components of a raster by specifying multiple filter rules. In this example, the `U` and `V` components of 10 meter winds are selected. You can find this information with gdalinfo.