> For the complete documentation index, see [llms.txt](https://mapir.gitbook.io/chloros/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mapir.gitbook.io/chloros/image-viewer-gui/index-lut-sandbox.md).

# Index/LUT Sandbox

The Index/LUT Sandbox is the interactive workspace in the Chloros Image Viewer sidebar. You pick a formula, bind your camera's channels to it, colour it with a gradient and tune the value range — and the image updates live while you do. Since 1.2.0 you can also **save what you built**, for one image or for the whole project, without reprocessing.

## What the Sandbox is for

| Index/LUT Sandbox (interactive)        | Project Processing (batch)       |
| -------------------------------------- | -------------------------------- |
| One image at a time, instant feedback  | The whole dataset in one run     |
| Experimental and iterative             | Pre-configured settings          |
| Renders live; saves only when you ask  | Always writes product files      |
| Perfect for finding the right settings | Best once the settings are final |

{% hint style="success" %}
**The usual workflow**: tune in the Sandbox until the visualisation says what you want, then either export straight from the Sandbox, or copy the same index and LUT settings into [Project Settings](/chloros/project-settings/project-settings.md) so the next processing run bakes them into every image.
{% endhint %}

***

## Opening the Sandbox

1. Click an image in the grid — it opens full screen in the **Image Viewer** <img src="https://1328410239-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOlCbgXiWzMtaOKj49kpf%2Fuploads%2Fgit-blob-61f7b64995600417b62eb916ea2c22ddf4c7738f%2Ficon_image-viewer.JPG?alt=media" alt="" data-size="line"> tab
2. Click the **Image Viewer** <img src="https://1328410239-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOlCbgXiWzMtaOKj49kpf%2Fuploads%2Fgit-blob-61f7b64995600417b62eb916ea2c22ddf4c7738f%2Ficon_image-viewer.JPG?alt=media" alt="" data-size="line"> icon to slide out the left sidebar if it is not already open
3. Choose a multi-band layer from the layer dropdown at the top-right — **RAW (Reflectance)** is the usual choice, because index values computed on calibrated reflectance are comparable between images

The sidebar shows, top to bottom:

* the image name and its camera model
* the **Export/Save Image(s)** button — appears once Index or LUT is ticked
* the **Index** and **LUT** checkboxes
* the index configuration panel
* the **Cursor Values** panel with the readout, histogram and GSD control

{% hint style="warning" %}
**Not available for mono cameras.** On a single-band LATTICE M3M image both checkboxes are disabled, with the tooltip *"Not available for mono (M3M) sensors"* — a multi-band index is undefined on one band. To compute indices from M3M cameras, combine two or more into an aligned multi-band stack and use the LATTICE index engine.
{% endhint %}

***

## Applying an index

1. Tick the **Index** box at the top of the sidebar
2. Choose your camera's filter from the left dropdown (`RGN`, `OCN`, `NGB`, `RGB`, `RE`, `NIR`)
3. Choose an index formula from the right dropdown — 27 built-in formulas, plus any custom formulas you have saved
4. The formula renders as math below, with an empty circle at each band slot. **Drag a coloured channel circle onto a slot** to bind it
5. Once every slot the formula uses is bound, the image updates and shows index values
6. Move the cursor over the image to read values; the **Cursor Values** panel adds an index row with the value under the cursor

Double-click a bound slot to clear it. An incomplete formula is a normal mid-drag state, not an error — the image simply does not update until the formula is complete.

The channel circles are colour-coded: red = Red, green = Green, blue = Blue, orange = Orange, cyan = Cyan, purple = NIR, magenta = RE. The same colours are used for the channel dots and histogram curves in the Cursor Values panel.

### NDVI example

```
Formula: (NIR - Red) / (NIR + Red)

For a Survey3W RGN camera:
  NIR = 850 nm band
  Red = 661 nm band

Result range:          -1.0 to +1.0
Typical vegetation:     0.4 to 0.9
Stressed vegetation:    0.2 to 0.4
Bare soil:              0.0 to 0.2
Water:                 -0.1 to 0.1
```

For the complete formula reference — all three preset lists and which names work where — see [Multispectral Index Formulas](/chloros/project-settings/multispectral-index-formulas.md).

### With Index ticked but no LUT

The image is drawn in **greyscale**, stretched between the two threshold values. This is deliberate: the index image is scalar data, and greyscale is the honest rendering of it. Add a LUT when you want colour.

***

## Working with LUTs (Look-Up Tables)

A **Look-Up Table** maps index values to colours: input NDVI 0.65, output a particular green. It does not change the data — it changes how you read it.

### Adding a LUT

1. Click the <img src="https://1328410239-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOlCbgXiWzMtaOKj49kpf%2Fuploads%2FrbOZ3I0GBk4BpziAVBSC%2Fimage.png?alt=media&amp;token=7443bece-a290-41da-88b4-15be9f7795fb" alt="" data-size="line"> **"+ Add LUT"** button below the formula
2. Pick a colour gradient
3. Set the clipping minimum and maximum
4. Choose a Clipping Mode
5. Tick the **LUT** box in the sidebar to render it

The LUT checkbox stays disabled until a LUT has actually been configured on the index.

### Choosing a colour gradient

Hover the **gradient bar** to open the preset list — Chloros ships **seven** gradient presets:

| # | Gradient                            | Shape                                                               |
| - | ----------------------------------- | ------------------------------------------------------------------- |
| 1 | Red → Yellow → Green (**default**)  | Diverging — matches the usual vegetation intuition, green = healthy |
| 2 | Purple → Yellow → Green             | Diverging, with a distinct low end                                  |
| 3 | Brown → White → Blue                | Diverging around a light midpoint                                   |
| 4 | Black → Purple → Pink → Pale yellow | Sequential, dark to light                                           |
| 5 | Red → Yellow → Blue                 | Diverging around a light midpoint                                   |
| 6 | Purple → Blue → Green → Yellow      | Sequential, dark to light                                           |
| 7 | Orange → White → Purple             | Diverging around a light midpoint                                   |

A **diverging** gradient puts a neutral colour at the middle of your window, which reads well when the midpoint means something (a threshold, a baseline date). A **sequential** gradient runs monotonically dark-to-light, which reads well for a quantity that only has "more" and "less".

Each preset has seven colour stops. Click a preset and the image updates immediately (when the LUT box is ticked).

### Editing the colour stops

Below the gradient bar is a row of colour swatches, one per stop:

* **Change a colour**: click a swatch to open the colour picker (colour wheel, RGB/HSV sliders, or a hex code such as `#FF0000`)
* **Add a stop**: click the **+** button at the end of the row — a white stop is appended
* **Remove a stop**: **double-click** the swatch
* **Keep an edited gradient**: click the save icon next to the gradient bar to add your edited gradient to the preset list so you can pick it again

The gradient you have configured on an index is stored with that index in the project's settings, so it survives closing and reopening the project.

**Fewer stops** produce distinct zones that read as a classification; **more stops** produce smooth, near-photographic transitions. Three to five stops suit presentation slides and classification maps; six to ten suit general analysis; fifteen or more suit detailed inspection and publication figures.

### Setting the value range

The threshold control is a **dual-handle slider** running from −1 to +1, with an editable text box at each end for exact values, and an **AUTO** button.

* Drag either handle, or type a number into its box and press Enter
* **AUTO** sets the range to the **2nd and 98th percentiles** of the image's valid index values — a good starting point that ignores outliers. Chloros rounds the result adaptively, to 4 decimal places for a very narrow range, 3 for a narrow one, 2 otherwise
* Any manual adjustment takes precedence over AUTO until you press AUTO again

Example NDVI windows:

| Goal                                    | Min  | Max |
| --------------------------------------- | ---- | --- |
| Show everything                         | −1.0 | 1.0 |
| Vegetation only, exclude soil and water | 0.2  | 0.9 |
| Healthy vegetation only                 | 0.5  | 0.9 |
| Emphasise stress                        | 0.2  | 0.5 |

Narrowing the window raises contrast inside your area of interest and pushes everything else out of range — where the **Clipping Mode** decides what happens to it.

***

## Clipping modes

When a pixel's index value falls outside the min/max window, the Clipping Mode decides how it is drawn.

| Dropdown label                  | Stored value      | Out-of-range pixels are drawn as                                                                                                |
| ------------------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------- |
| **Minimum & Maximum** (default) | `clip`            | The nearest end colour of the gradient — values below the minimum take the first colour, values above the maximum take the last |
| **Transparent Background**      | `transparent`     | Fully transparent (real alpha)                                                                                                  |
| **Index Background**            | `indexColor`      | Greyscale, stretched across the image's **full** index range, so out-of-range structure is still visible in grey                |
| **Original Background**         | `backgroundColor` | The underlying image itself, so the colour overlay sits on top of the real scene                                                |

| Mode                       | Best for                               | Look                                      |
| -------------------------- | -------------------------------------- | ----------------------------------------- |
| **Minimum & Maximum**      | Full data display, scientific analysis | Every pixel coloured                      |
| **Transparent Background** | GIS overlays, isolating a value band   | Colour inside the window, nothing outside |
| **Index Background**       | Emphasis while keeping data context    | Colour inside, grey outside               |
| **Original Background**    | Reports and presentations              | Colour inside, photograph outside         |

{% hint style="info" %}
**No-data pixels are always transparent, in every mode.** A pixel whose index is not finite (a 0/0 division) or is exactly −1.0 or +1.0 (saturation sentinels, from one band reading zero while the other does not) is treated as no-data rather than as an extreme value. This keeps blown highlights and dead shadows out of your colour scale instead of painting them as the most extreme reading in the frame. The same rule defines which pixels feed the AUTO thresholds and the index histogram, so all three agree.
{% endhint %}

Transparency is preserved when the export is written as PNG. It cannot be represented in JPG.

***

## Reading values while you tune

The **Cursor Values** panel below the configuration panel is the measuring instrument for the Sandbox:

* Move the cursor over the image and read the per-channel source values, plus the index value in its own row
* Turn on the **INDEX** button above the histogram to see the distribution of index values in the frame, with your two clip thresholds drawn as orange dashed lines and the cursor's value as a white line — this is the fastest way to choose a window that actually contains your data
* Turn on **CURSOR** to see marker lines at the values under the pointer
* Zoom past 60× (less if a GSD block size is set) to highlight individual displayed pixels with a floating value

A practical routine:

1. Note the values over healthy vegetation, stressed vegetation, bare soil and water
2. Look at where those clusters sit on the index histogram
3. Set min/max to bracket the cluster you care about
4. Pick a clipping mode — *Original Background* keeps the scene visible around it

***

## Exporting from the Sandbox

Everything above is a live preview until you save it. The **Export/Save Image(s)** button at the top of the sidebar opens a pane that slides over the sidebar (rather than covering the image, so you can still see what you are deciding about).

<figure><img src="https://1328410239-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FOlCbgXiWzMtaOKj49kpf%2Fuploads%2FG1gEgccvj7UE5pe4Hzqp%2Fimage.png?alt=media&amp;token=ffa41c13-c1cc-49bf-9f7f-f356e4f249bb" alt=""><figcaption></figcaption></figure>

### Options

| Option                          | Effect                                                                                                                                            |
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Apply to current image**      | Saves exactly the image shown, with these settings                                                                                                |
| **Apply to all project images** | Re-runs the identical configuration on every image in the project. Images without the bands this index needs are skipped, not treated as failures |
| **Index/LUT gradient bar**      | Also writes a separate legend image per export, with the value range labelled                                                                     |
| **Index histogram**             | Also writes a separate histogram image per export, showing the data min/max and the clip thresholds                                               |

If the image tab's **GSD block size** is above 1, the pane says so before you commit: the export saves what you are looking at, block averaging included. Set the GSD control back to 1 first if you want full resolution.

### Where the files go

Each click of **Export** allocates a **new, never-reused folder**:

```
<project folder>/Sandbox_Exports/<IndexName>_<Index|LUT>_<NNN>/
```

Examples: `Sandbox_Exports/NDVI_LUT_001/`, then `Sandbox_Exports/NDVI_LUT_002/` for the next run. The numbering is derived by scanning what is already on disk, so it survives restarts and folders you delete by hand. Nothing is ever overwritten — the whole point of the Sandbox is comparing one attempt against the last.

Inside the folder, per image:

| File                                                   | Contents                                                   |
| ------------------------------------------------------ | ---------------------------------------------------------- |
| `<source name>_<IndexName>_<Index\|LUT>.png`           | The rendered image, pixel-for-pixel what the viewer showed |
| `<source name>_<IndexName>_<Index\|LUT>_legend.png`    | The gradient bar sidecar, if requested                     |
| `<source name>_<IndexName>_<Index\|LUT>_histogram.png` | The index histogram sidecar, if requested                  |

The two sidecars are always written at **full resolution**, even when the main image is block-averaged: a block size is a display resolution, and both sidecars read the true per-pixel index values. They also print more than the on-screen versions do — both stamp the stretch window *and* the true data min/max, so a saved legend is still readable months later without the project open.

### Progress and results

A whole-project export takes minutes, so the run reports back over a live progress channel rather than blocking:

* A progress bar shows `current / total` and the file being written
* When it finishes, the pane reports how many images were exported, how many were skipped, and the output folder path
* Skipped images are listed with the reason (up to five shown, then a "+N more" line). The usual reason is a layer that does not have the channels this index needs
* If **no** image in the project could use the index, the run reports failure rather than leaving you an empty folder

Only one sandbox export runs at a time. Starting a second while one is in flight is refused with a clear message rather than letting two runs fight over the same project file.

### The grid picks the run up

Every completed run appears as its own button in the [image grid](/chloros/image-viewer-gui/image-grid.md) toolbar, labelled `<IndexName> <Index|LUT> <NNN>`. That is how you compare runs: export twice with different gradients or thresholds, then flip between the two buttons on the grid.

***

## Custom index formulas (Chloros+)

{% hint style="info" %}
**Where to create them**: in the Sandbox sidebar, or in **Project Settings** before processing. Both write to the same project-level list.
{% endhint %}

1. Open the custom formula calculator from the index formula dropdown (requires signing in with a qualifying Chloros+ subscription)
2. Write the formula using the **band-slot symbols** `x`, `y`, `z`, `a`, `b`, `c` — not band names
3. Operators available: `+`, `-`, `*`, `/`, `^`, and `()` for grouping
4. Functions available: `sqrt()`, `log()`, `ln()`, `abs()`, `sign()`, `log1p()`, `log2()`
5. Name and save it — it appears at the bottom of the formula dropdown and you bind its slots by dragging channel circles, exactly like a built-in preset

```
Modified NDVI with an offset:   (y-x)/(y+x+0.5)
Simple ratio:                   y/x
Three-band difference:          (y-x)/(y+x-z)
Squared ratio:                  (y/x)^2
```

{% hint style="warning" %}
**Custom formulas are GUI-only.** The CLI/SDK `--indices` option expands the 22 built-in preset names and silently skips anything else, including your custom formulas. To batch a custom formula, configure it in Project Settings and run processing, or use the Sandbox's "Apply to all project images" export.
{% endhint %}

***

## Troubleshooting

### "This layer doesn't have the channels this index needs"

The formula reads a channel position the current layer does not have — for example a three-slot index on a one- or two-channel file. Switch to a multi-band layer (reflectance or debayered), or pick an index that fits your camera's filter.

### "Could not reach the image processing backend"

The backend is not answering. Check the Log tab; if the backend is restarting, the Sandbox recovers on its own once it is back.

### The image did not change when I dragged a circle

The formula is not complete yet. An incomplete formula is treated as a normal mid-drag state — nothing renders and nothing is reported as an error. Fill every slot the formula uses.

### The whole image is one colour

Your clip window is probably far outside the data. Press **AUTO** to snap it to the 2nd/98th percentiles, or turn on the **INDEX** histogram to see where the data actually lies.

### Exported colours do not match what I saw

They should — the export path is a deliberate mirror of the live preview, including the clipping-mode alpha, and the block averaging is applied *after* colourisation exactly as the viewer does it. If they differ, check that the GSD block size has not changed between viewing and exporting.

***

## Next Steps

* [**Image Layers**](/chloros/image-viewer-gui/image-layers.md) — which layer to run an index on, and what its values mean
* [**Opening an Image Full Screen**](/chloros/image-viewer-gui/opening-an-image-full-screen.md) — the cursor readout, histogram and GSD control in detail
* [**Multispectral Index Formulas**](/chloros/project-settings/multispectral-index-formulas.md) — every preset, on every surface
* [**Project Settings**](/chloros/project-settings/project-settings.md) — baking the settings you found into a processing run
