CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-cmasher

Scientific colormaps for making accessible, informative and 'cmashing' plots

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

registration.mddocs/

Colormap Registration and Import

Register custom colormaps and import colormap data from various formats. These functions enable extending CMasher with custom colormaps and creating portable colormap modules.

Capabilities

Custom Colormap Registration

Register new colormaps in both CMasher and matplotlib for use throughout the visualization ecosystem.

def register_cmap(name: str, data: list) -> None:
    """
    Creates and registers a custom colormap in CMasher and matplotlib.

    Parameters:
    - name: Name for the colormap (will be prefixed with 'cmr.' in matplotlib)
    - data: RGB color data as 2D array-like (N, 3) or 1D array of hex strings
           Float values (normalized), int values (8-bit), or hex strings

    Returns:
    None

    Notes:
    Creates both normal and reversed versions. Colormap accessible as
    cmasher.cm.{name} and matplotlib 'cmr.{name}'.
    """

Usage Examples

import cmasher as cmr
import numpy as np
import matplotlib.pyplot as plt

# Register colormap from normalized RGB values
rgb_data = [
    [0.0, 0.0, 0.5],   # Dark blue
    [0.0, 0.5, 1.0],   # Light blue
    [1.0, 1.0, 0.5],   # Light yellow
    [1.0, 0.5, 0.0]    # Orange
]
cmr.register_cmap('custom_gradient', rgb_data)

# Register colormap from 8-bit RGB values
rgb_8bit = [
    [0, 0, 128],       # Dark blue
    [0, 128, 255],     # Light blue
    [255, 255, 128],   # Light yellow
    [255, 128, 0]      # Orange
]
cmr.register_cmap('custom_8bit', rgb_8bit)

# Register colormap from hex strings
hex_colors = ['#000080', '#0080FF', '#FFFF80', '#FF8000']
cmr.register_cmap('custom_hex', hex_colors)

# Use registered colormap
data = np.random.rand(10, 10)
plt.imshow(data, cmap='cmr.custom_gradient')
plt.colorbar()
plt.title('Custom Registered Colormap')
plt.show()

# Access from CMasher module
import cmasher.cm as cmrcm
custom_cmap = cmrcm.custom_gradient

Colormap Import from Files

Import colormaps from various file formats including NumPy arrays, text files, and viscm source files.

def import_cmaps(
    cmap_path: str,
    *,
    _skip_registration: bool = False
) -> None:
    """
    Import custom colormaps from files or directories.

    Parameters:
    - cmap_path: Path to colormap file or directory containing colormap files
    - _skip_registration: Skip automatic registration (for testing)

    Returns:
    None

    Notes:
    Supports .npy (NumPy binary), .txt (text), .jscm (viscm) formats.
    Files must have 'cm_' prefix. Cyclic colormaps get shifted versions.
    
    Raises:
    FileNotFoundError: If path doesn't exist
    OSError: If file doesn't have 'cm_' prefix
    ValueError: If viscm package missing for .jscm files
    """

Usage Examples

import cmasher as cmr
import numpy as np
import os

# Create example colormap data file
colormap_data = np.array([
    [0.0, 0.0, 0.0],    # Black
    [0.5, 0.0, 0.5],    # Purple
    [1.0, 0.5, 0.0],    # Orange
    [1.0, 1.0, 1.0]     # White
])

# Save as NumPy binary file
np.save('cm_example.npy', colormap_data)

# Import single colormap file
cmr.import_cmaps('cm_example.npy')

# Now colormap is available
import matplotlib.pyplot as plt
data = np.random.rand(8, 8)
plt.imshow(data, cmap='cmr.example')
plt.show()

# Import from directory
os.makedirs('my_colormaps', exist_ok=True)
np.save('my_colormaps/cm_gradient1.npy', colormap_data)
np.save('my_colormaps/cm_gradient2.npy', colormap_data[::-1])  # Reversed

cmr.import_cmaps('my_colormaps/')

# Import from text file
with open('cm_text_example.txt', 'w') as f:
    for rgb in colormap_data:
        f.write(f"{rgb[0]:.6f} {rgb[1]:.6f} {rgb[2]:.6f}\n")

cmr.import_cmaps('cm_text_example.txt')

# Clean up example files
os.remove('cm_example.npy')
os.remove('cm_text_example.txt')

Standalone Colormap Module Creation

Create portable Python modules containing individual colormaps for sharing without CMasher dependency.

def create_cmap_mod(
    cmap: str,
    *,
    save_dir: str = ".",
    _copy_name: str | None = None
) -> str:
    """
    Creates a standalone Python module for a CMasher colormap.

    Parameters:
    - cmap: Name of CMasher colormap (with or without 'cmr.' prefix)
    - save_dir: Directory to save the module file
    - _copy_name: Alternative name for the module (internal use)

    Returns:
    str: Path to the created Python module file

    Notes:
    Creates a .py file that registers the colormap in matplotlib when
    imported. Includes reversed version and shifted version for cyclic
    colormaps.
    
    Raises:
    ValueError: If colormap name is not valid CMasher colormap
    """

Usage Examples

import cmasher as cmr
import os

# Create standalone module for rainforest colormap
module_path = cmr.create_cmap_mod('rainforest')
print(f"Created module: {module_path}")

# Create module in specific directory
os.makedirs('colormap_modules', exist_ok=True)
ocean_path = cmr.create_cmap_mod('ocean', save_dir='colormap_modules')

# Create modules for multiple colormaps
colormaps_to_export = ['iceburn', 'wildfire', 'seasons']
for cmap_name in colormaps_to_export:
    path = cmr.create_cmap_mod(cmap_name, save_dir='colormap_modules')
    print(f"Exported {cmap_name} to {path}")

# Use standalone module (in a new Python session)
# import rainforest  # This would register the colormap
# plt.imshow(data, cmap='cmr.rainforest')

Advanced Import Patterns

Batch Import from Directory

import cmasher as cmr
import numpy as np
import os

def create_colormap_collection(output_dir='my_colormaps'):
    """Create a collection of custom colormaps."""
    os.makedirs(output_dir, exist_ok=True)
    
    # Create various colormap types
    colormaps = {
        'cm_fire': np.array([[0, 0, 0], [1, 0, 0], [1, 1, 0], [1, 1, 1]]),
        'cm_ice': np.array([[0, 0, 0.5], [0, 0.5, 1], [0.8, 0.9, 1], [1, 1, 1]]),
        'cm_earth': np.array([[0.2, 0.1, 0], [0.5, 0.3, 0.1], [0.3, 0.6, 0.2], [0.8, 0.8, 0.6]])
    }
    
    for name, data in colormaps.items():
        np.save(f"{output_dir}/{name}.npy", data)
    
    # Import entire collection
    cmr.import_cmaps(output_dir)
    print(f"Imported {len(colormaps)} custom colormaps")

create_colormap_collection()

Colormap Format Conversion

import cmasher as cmr
import numpy as np

def convert_colormap_formats(source_file, output_formats=['npy', 'txt', 'hex']):
    """Convert colormap between different file formats."""
    # Load colormap data
    if source_file.endswith('.npy'):
        data = np.load(source_file)
    else:
        data = np.loadtxt(source_file)
    
    base_name = source_file.replace('.npy', '').replace('.txt', '')
    
    # Save in different formats
    if 'npy' in output_formats:
        np.save(f'{base_name}.npy', data)
    
    if 'txt' in output_formats:
        np.savetxt(f'{base_name}_norm.txt', data, fmt='%.6f')
    
    if 'hex' in output_formats:
        hex_colors = []
        for rgb in data:
            r, g, b = (rgb * 255).astype(int)
            hex_colors.append(f'#{r:02X}{g:02X}{b:02X}')
        
        with open(f'{base_name}_hex.txt', 'w') as f:
            for hex_color in hex_colors:
                f.write(hex_color + '\n')

# Example usage
data = np.random.rand(10, 3)  # Random colormap
np.save('cm_random.npy', data)
convert_colormap_formats('cm_random.npy')

Colormap Validation and Testing

import cmasher as cmr
import numpy as np
import matplotlib.pyplot as plt

def validate_custom_colormap(data, name='test_cmap'):
    """Validate custom colormap data before registration."""
    try:
        # Convert to numpy array
        data_array = np.array(data)
        
        # Check dimensions
        if data_array.ndim != 2 or data_array.shape[1] != 3:
            print(f"Error: Data must be (N, 3) shape, got {data_array.shape}")
            return False
        
        # Check value ranges for normalized RGB
        if np.any(data_array < 0) or np.any(data_array > 1):
            print("Warning: Values outside [0, 1] range, assuming 8-bit RGB")
            if np.any(data_array > 255):
                print("Error: Values too large for 8-bit RGB")
                return False
        
        # Test registration
        cmr.register_cmap(name, data)
        
        # Test visualization
        test_data = np.random.rand(5, 5)
        plt.figure(figsize=(8, 3))
        plt.subplot(1, 2, 1)
        plt.imshow(test_data, cmap=f'cmr.{name}')
        plt.title(f'Custom colormap: {name}')
        plt.colorbar()
        
        plt.subplot(1, 2, 2)
        plt.imshow(test_data, cmap=f'cmr.{name}_r')
        plt.title(f'Reversed: {name}_r')
        plt.colorbar()
        
        plt.tight_layout()
        plt.show()
        
        print(f"✓ Colormap '{name}' validated successfully")
        return True
        
    except Exception as e:
        print(f"✗ Validation failed: {e}")
        return False

# Test with example data
test_data = [[0, 0, 0.5], [0.5, 0, 1], [1, 0.5, 0.5], [1, 1, 1]]
validate_custom_colormap(test_data, 'validation_test')

Environment Variable Support

import os
import cmasher as cmr

# CMasher supports CMR_CMAP_PKGS environment variable
# for specifying additional colormap packages to import

# Set environment variable to include additional packages
os.environ['CMR_CMAP_PKGS'] = 'colorcet:cmocean'

# This would be used by CLI tools to import additional colormaps
# The packages are separated by ':' on Unix or ';' on Windows

Install with Tessl CLI

npx tessl i tessl/pypi-cmasher

docs

cli-tools.md

color-analysis.md

colormap-collections.md

index.md

integration.md

manipulation.md

registration.md

visualization.md

tile.json