Colormaps¶
playNano ships with three native colourmaps designed specifically for AFM
data. All three are registered globally on import as matplotlib colormaps,
making them available by name across the entire toolkit and in your own scripts
alongside built-in options such as afmhot and viridis.
import playnano # registers all three colourmaps on import
import matplotlib.pyplot as plt
plt.imshow(height_data, cmap="afm_brown")
plt.imshow(height_data, cmap="playnano_gold")
plt.imshow(height_data, cmap="classic_afm")
Overview¶
Name |
Character |
L* range |
Linearity (R²) |
Best for |
|---|---|---|---|---|
|
Near-black → brown → warm cream |
0.6 → 96.4 |
0.996 |
General use, HS-AFM video |
|
Black → deep red → amber → white |
0.0 → 100.0 |
0.978 |
High-contrast, feature-rich samples |
|
Black → dark red → brown → cream |
0.0 → 99.8 |
0.763 |
Continuity with legacy workflows |
The three native playNano colourmaps rendered across the full data range.¶
—
afm_brown¶
afm_brown is the default colourmap for all playNano visual exports and the GUI.
It was developed for this project to address the perceptual limitations of traditional
AFM colourmaps — in particular the dark plateau near zero that compresses
contrast in low-lying substrate regions, and the non-linear lightness
discontinuities that cause flickering in HS-AFM videos when the z-scale shifts
between frames.
The ramp runs from near-black through a warm brown mid-tone to a pale cream, retaining the familiar orange-brown character of conventional AFM colour schemes. Lightness (CIE L*) increases monotonically across the full range with near-perfect linearity (R² = 0.996), meaning equal steps in height produce equal steps in perceived brightness throughout the scale.
L* range |
0.6 → 96.4 |
Linearity (R²) |
0.996 |
Monotone |
Yes (zero non-monotone steps) |
Mean ΔE* per step |
0.647 |
ΔE* CoV |
0.20 |
Perceptual character |
Perceptually linear |
When to use
afm_brown is the recommended default for most AFM data. Its perceptually
linear lightness ensures fine substrate detail is resolved at the dark end of
the scale, and its visual stability makes it well-suited to HS-AFM video
exports where z-scale consistency between frames is important. It is also similar
enough to traditional AFM colour schemes to be visually familiar and easily accepted
by users used to older AFM colour scales.
—
playnano_gold¶
playnano_gold is a high-contrast colourmap spanning the full luminance
range (L* 0-100), from pure black through deep red and gold to white. The
wider hue sweep and full dynamic range make it effective for samples with
complex topography and a broad distribution of feature heights, where maximum
separation between levels is desirable.
Lightness increases monotonically throughout, though the larger hue excursion
means perceived colour differences per step are less uniform than in
afm_brown (ΔE* CoV = 0.57). For static images and figures where contrast
takes priority over strict perceptual linearity, this is the stronger choice.
L* range |
0.0 → 100.0 |
Linearity (R²) |
0.978 |
Monotone |
Yes (zero non-monotone steps) |
Mean ΔE* per step |
0.789 |
ΔE* CoV |
0.57 |
Perceptual character |
Monotone-lightness, high-contrast |
When to use
playnano_gold suits complex, feature-rich samples where the full height
range needs to be visually separated.
—
classic_afm¶
classic_afm replicates the non-linear brown colourmap commonly encountered
in AFM software. It is included for continuity, allowing direct visual
comparison with figures and data produced in other packages, and is not
recommended for new work.
The lightness profile is non-linear (R² = 0.763), with a pronounced dark
plateau in the lower quarter of the range (L* reaches only 5.5 at the 25th
percentile) that suppresses contrast in low-height regions. This is the
behaviour that afm_brown was specifically designed to overcome.
L* range |
0.0 → 99.8 |
Linearity (R²) |
0.763 |
Monotone |
Yes (zero non-monotone steps) |
Mean ΔE* per step |
0.738 |
ΔE* CoV |
0.50 |
Perceptual character |
Non-linear (legacy) |
When to use
Use classic_afm only when reproducing the look of figures generated with
other AFM software, or when comparing directly with existing published data
that used a similar colourmap.
—
Usage¶
Programmatic¶
All three colourmaps are available as matplotlib
LinearSegmentedColormap objects via
playnano.utils.colormaps.
import playnano # register_custom_colormaps() is called on import
# All three are now available by name for matplotlib functions like imshow():
plt.imshow(height_data, cmap="afm_brown")
plt.imshow(height_data, cmap="playnano_gold")
plt.imshow(height_data, cmap="classic_afm")
# Reversed versions are also registered automatically
plt.imshow(height_data, cmap="afm_brown_r")
# Additionally, they can be used within the playNano export functions
from playnano.io.gif_export import export_gif
export_gif(
stack,
make_gif=True,
output_folder="exports",
output_name="sample",
scale_bar_nm=100,
cmap_name="playnano_gold", # or "afm_brown", "classic_afm"
zmin="auto",
zmax="auto",
draw_ts=True,
draw_scale_bar=False,
)
CLI and GUI¶
The default colourmap for all animated exports (GIF Export,
Video Export, Image Sequence Export) is afm_brown. An
alternative colourmap can be set via the --cmap flag:
playnano process sample_data --make-gif --cmap playnano_gold
In the GUI, the colourmap and z-scale can be adjusted interactively from the display controls before export.
—
Background: perceptual linearity in AFM visualisation¶
Conventional AFM colourmaps such as Matplotlib’s afmhot and the traditional
colormap reprduced in classic_afm, were not designed with perceptual uniformity
in mind. Two common consequences are:
The black plateau — a long stretch of near-zero lightness at the low end of the scale that compresses contrast and obscures fine substrate detail.
Flicker in HS-AFM video — non-linear lightness kinks interact with small frame-to-frame changes in the data range, causing apparent brightness jumps between frames even when the underlying height values are stable.
Perceptual linearity (monotonically increasing L* at a near-constant rate)
addresses both issues. It does not require full perceptual uniformity in the
strict sense used to describe colourmaps such as viridis — where every
step produces an identical ΔE* — but it eliminates the artefacts above while
remaining visually familiar to AFM users.
The table below compares the playNano native colourmaps with afmhot on the
key perceptual metrics:
Colormap |
L* range |
Linearity (R²) |
Mean ΔE*/step |
ΔE* CoV |
|---|---|---|---|---|
|
0.6 → 96.4 |
0.996 |
0.647 |
0.20 |
|
0.0 → 100.0 |
0.978 |
0.789 |
0.57 |
|
0.0 → 99.8 |
0.763 |
0.738 |
0.50 |
|
0.0 → 100.0 |
0.872 |
1.004 |
0.16 |