Scientific colormaps for making accessible, informative and 'cmashing' plots
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Combine and modify colormaps to create custom color schemes. These functions enable advanced colormap customization for specific visualization needs.
Blend multiple colormaps together at specified transition points to create composite color schemes.
def combine_cmaps(
*cmaps: Colormap | str,
nodes: list[float] | None = None,
n_rgb_levels: int = 256,
combined_cmap_name: str = "combined_cmap"
) -> LinearSegmentedColormap:
"""
Create a composite colormap by combining multiple colormaps.
Parameters:
- *cmaps: Colormap objects or names to combine
- nodes: Transition points between colormaps in range [0, 1]
(None for equal divisions)
- n_rgb_levels: Number of RGB levels for each colormap segment
- combined_cmap_name: Name for the resulting colormap
Returns:
LinearSegmentedColormap: The composite colormap
Raises:
ValueError: If fewer than 2 colormaps provided, invalid nodes, etc.
TypeError: If invalid colormap types provided
"""import cmasher as cmr
import matplotlib.pyplot as plt
import numpy as np
# Combine two colormaps with equal division
combined = cmr.combine_cmaps('cmr.ocean', 'cmr.ember')
# Combine three colormaps with custom transition points
custom_combined = cmr.combine_cmaps(
'cmr.arctic', 'cmr.neutral', 'cmr.ember',
nodes=[0.3, 0.7], # Transitions at 30% and 70%
combined_cmap_name='arctic_neutral_ember'
)
# Use combined colormap in plot
data = np.random.rand(20, 20)
plt.imshow(data, cmap=combined)
plt.colorbar()
plt.title('Combined Colormap Example')
plt.show()
# Combine with different proportions
fire_ice = cmr.combine_cmaps(
'cmr.freeze', 'cmr.ember',
nodes=[0.2], # 20% freeze, 80% ember
n_rgb_levels=512 # Higher resolution
)Extract portions of existing colormaps to create focused color ranges.
def get_sub_cmap(
cmap: str | Colormap,
start: float,
stop: float,
*,
N: int | None = None
) -> ListedColormap:
"""
Creates a colormap using a subset of colors from an existing colormap.
Parameters:
- cmap: Source colormap name or object
- start: Start of range to extract (0.0 to 1.0)
- stop: End of range to extract (0.0 to 1.0)
- N: Number of discrete colors (None for continuous)
Returns:
ListedColormap: Subset colormap with '_sub' or '_qual' suffix
Notes:
Use at least 128 colors for smooth gradients. Setting N creates
a qualitative colormap with discrete colors.
"""import cmasher as cmr
import matplotlib.pyplot as plt
import numpy as np
# Extract first 80% of rainforest colormap
partial_cmap = cmr.get_sub_cmap('cmr.rainforest', 0, 0.8)
# Extract middle portion of a diverging colormap
center_cmap = cmr.get_sub_cmap('cmr.iceburn', 0.2, 0.8)
# Create qualitative colormap from sequential colormap
qual_colors = cmr.get_sub_cmap('cmr.tropical', 0.1, 0.9, N=8)
# Use in visualization
data = np.random.rand(15, 15)
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
axes[0].imshow(data, cmap='cmr.rainforest')
axes[0].set_title('Original Rainforest')
axes[1].imshow(data, cmap=partial_cmap)
axes[1].set_title('Partial Rainforest (0-80%)')
axes[2].imshow(data, cmap=qual_colors)
axes[2].set_title('Qualitative Subset')
plt.tight_layout()
plt.show()import cmasher as cmr
# Create diverging colormap from two sequential colormaps
def create_diverging_from_sequential(cmap1, cmap2, center_point=0.5):
"""Create diverging colormap from two sequential colormaps."""
# Reverse first colormap and combine
reversed_cmap1 = f"{cmap1}_r" if not cmap1.endswith('_r') else cmap1[:-2]
return cmr.combine_cmaps(
reversed_cmap1, cmap2,
nodes=[center_point],
combined_cmap_name=f"div_{cmap1}_{cmap2}"
)
# Create custom diverging colormap
custom_div = create_diverging_from_sequential('cmr.arctic', 'cmr.ember')import cmasher as cmr
# Create complex multi-segment colormap
spectrum = cmr.combine_cmaps(
'cmr.arctic', # Blue range
'cmr.emerald', # Green range
'cmr.amber', # Yellow range
'cmr.ember', # Red range
nodes=[0.25, 0.5, 0.75],
combined_cmap_name='custom_spectrum',
n_rgb_levels=1024
)import cmasher as cmr
def proportional_combine(cmaps_and_weights):
"""Combine colormaps with specific proportions."""
total_weight = sum(cmaps_and_weights.values())
# Calculate cumulative nodes
nodes = []
cumulative = 0
cmap_list = list(cmaps_and_weights.keys())
for i, (cmap, weight) in enumerate(cmaps_and_weights.items()):
if i < len(cmap_list) - 1: # Don't add node for last colormap
cumulative += weight / total_weight
nodes.append(cumulative)
return cmr.combine_cmaps(*cmap_list, nodes=nodes)
# Example: 40% ocean, 30% neutral, 30% ember
weighted_cmap = proportional_combine({
'cmr.ocean': 0.4,
'cmr.neutral': 0.3,
'cmr.ember': 0.3
})import cmasher as cmr
def create_themed_variants(base_cmap, theme_cmaps, theme_name):
"""Create multiple variants of a base colormap with different themes."""
variants = {}
for i, theme_cmap in enumerate(theme_cmaps):
# Create combination with different proportions
variant = cmr.combine_cmaps(
base_cmap, theme_cmap,
nodes=[0.7], # 70% base, 30% theme
combined_cmap_name=f"{theme_name}_variant_{i}"
)
variants[f"{theme_name}_{i}"] = variant
return variants
# Create ocean-themed variants
ocean_variants = create_themed_variants(
'cmr.neutral',
['cmr.ocean', 'cmr.tropical', 'cmr.arctic'],
'ocean_theme'
)import cmasher as cmr
def adjust_colormap_range(cmap_name, data_range=(0.1, 0.9)):
"""Adjust colormap to focus on specific data range."""
return cmr.get_sub_cmap(
cmap_name,
data_range[0],
data_range[1]
)
# Focus on middle range for low-contrast data
focused_cmap = adjust_colormap_range('cmr.rainforest', (0.3, 0.7))import cmasher as cmr
import matplotlib.pyplot as plt
import numpy as np
def harmonize_colormaps(*cmap_names, n_colors=256):
"""Create harmonized versions of multiple colormaps."""
harmonized = {}
for cmap_name in cmap_names:
# Extract subset that harmonizes well
base_cmap = cmr.get_sub_cmap(cmap_name, 0.1, 0.9)
harmonized[cmap_name.replace('cmr.', '')] = base_cmap
return harmonized
# Create harmonized set for multi-panel plots
harmonized_set = harmonize_colormaps(
'cmr.rainforest', 'cmr.ocean', 'cmr.ember'
)
# Use in multi-panel visualization
fig, axes = plt.subplots(1, 3, figsize=(15, 5))
data_sets = [np.random.rand(10, 10) for _ in range(3)]
for ax, (name, cmap), data in zip(axes, harmonized_set.items(), data_sets):
im = ax.imshow(data, cmap=cmap)
ax.set_title(f'Harmonized {name.title()}')
plt.colorbar(im, ax=ax)
plt.tight_layout()
plt.show()import cmasher as cmr
def safe_combine_cmaps(*cmaps, **kwargs):
"""Safely combine colormaps with error handling."""
try:
return cmr.combine_cmaps(*cmaps, **kwargs)
except ValueError as e:
print(f"Combination error: {e}")
return None
except TypeError as e:
print(f"Type error: {e}")
return None
# Example usage with error handling
result = safe_combine_cmaps('cmr.ocean') # Will fail - need 2+ colormaps
if result is None:
print("Using default colormap instead")
result = 'cmr.ocean'Install with Tessl CLI
npx tessl i tessl/pypi-cmasher