0
# Colormap Registration and Import
1
2
Register custom colormaps and import colormap data from various formats. These functions enable extending CMasher with custom colormaps and creating portable colormap modules.
3
4
## Capabilities
5
6
### Custom Colormap Registration
7
8
Register new colormaps in both CMasher and matplotlib for use throughout the visualization ecosystem.
9
10
```python { .api }
11
def register_cmap(name: str, data: list) -> None:
12
"""
13
Creates and registers a custom colormap in CMasher and matplotlib.
14
15
Parameters:
16
- name: Name for the colormap (will be prefixed with 'cmr.' in matplotlib)
17
- data: RGB color data as 2D array-like (N, 3) or 1D array of hex strings
18
Float values (normalized), int values (8-bit), or hex strings
19
20
Returns:
21
None
22
23
Notes:
24
Creates both normal and reversed versions. Colormap accessible as
25
cmasher.cm.{name} and matplotlib 'cmr.{name}'.
26
"""
27
```
28
29
#### Usage Examples
30
31
```python
32
import cmasher as cmr
33
import numpy as np
34
import matplotlib.pyplot as plt
35
36
# Register colormap from normalized RGB values
37
rgb_data = [
38
[0.0, 0.0, 0.5], # Dark blue
39
[0.0, 0.5, 1.0], # Light blue
40
[1.0, 1.0, 0.5], # Light yellow
41
[1.0, 0.5, 0.0] # Orange
42
]
43
cmr.register_cmap('custom_gradient', rgb_data)
44
45
# Register colormap from 8-bit RGB values
46
rgb_8bit = [
47
[0, 0, 128], # Dark blue
48
[0, 128, 255], # Light blue
49
[255, 255, 128], # Light yellow
50
[255, 128, 0] # Orange
51
]
52
cmr.register_cmap('custom_8bit', rgb_8bit)
53
54
# Register colormap from hex strings
55
hex_colors = ['#000080', '#0080FF', '#FFFF80', '#FF8000']
56
cmr.register_cmap('custom_hex', hex_colors)
57
58
# Use registered colormap
59
data = np.random.rand(10, 10)
60
plt.imshow(data, cmap='cmr.custom_gradient')
61
plt.colorbar()
62
plt.title('Custom Registered Colormap')
63
plt.show()
64
65
# Access from CMasher module
66
import cmasher.cm as cmrcm
67
custom_cmap = cmrcm.custom_gradient
68
```
69
70
### Colormap Import from Files
71
72
Import colormaps from various file formats including NumPy arrays, text files, and viscm source files.
73
74
```python { .api }
75
def import_cmaps(
76
cmap_path: str,
77
*,
78
_skip_registration: bool = False
79
) -> None:
80
"""
81
Import custom colormaps from files or directories.
82
83
Parameters:
84
- cmap_path: Path to colormap file or directory containing colormap files
85
- _skip_registration: Skip automatic registration (for testing)
86
87
Returns:
88
None
89
90
Notes:
91
Supports .npy (NumPy binary), .txt (text), .jscm (viscm) formats.
92
Files must have 'cm_' prefix. Cyclic colormaps get shifted versions.
93
94
Raises:
95
FileNotFoundError: If path doesn't exist
96
OSError: If file doesn't have 'cm_' prefix
97
ValueError: If viscm package missing for .jscm files
98
"""
99
```
100
101
#### Usage Examples
102
103
```python
104
import cmasher as cmr
105
import numpy as np
106
import os
107
108
# Create example colormap data file
109
colormap_data = np.array([
110
[0.0, 0.0, 0.0], # Black
111
[0.5, 0.0, 0.5], # Purple
112
[1.0, 0.5, 0.0], # Orange
113
[1.0, 1.0, 1.0] # White
114
])
115
116
# Save as NumPy binary file
117
np.save('cm_example.npy', colormap_data)
118
119
# Import single colormap file
120
cmr.import_cmaps('cm_example.npy')
121
122
# Now colormap is available
123
import matplotlib.pyplot as plt
124
data = np.random.rand(8, 8)
125
plt.imshow(data, cmap='cmr.example')
126
plt.show()
127
128
# Import from directory
129
os.makedirs('my_colormaps', exist_ok=True)
130
np.save('my_colormaps/cm_gradient1.npy', colormap_data)
131
np.save('my_colormaps/cm_gradient2.npy', colormap_data[::-1]) # Reversed
132
133
cmr.import_cmaps('my_colormaps/')
134
135
# Import from text file
136
with open('cm_text_example.txt', 'w') as f:
137
for rgb in colormap_data:
138
f.write(f"{rgb[0]:.6f} {rgb[1]:.6f} {rgb[2]:.6f}\n")
139
140
cmr.import_cmaps('cm_text_example.txt')
141
142
# Clean up example files
143
os.remove('cm_example.npy')
144
os.remove('cm_text_example.txt')
145
```
146
147
### Standalone Colormap Module Creation
148
149
Create portable Python modules containing individual colormaps for sharing without CMasher dependency.
150
151
```python { .api }
152
def create_cmap_mod(
153
cmap: str,
154
*,
155
save_dir: str = ".",
156
_copy_name: str | None = None
157
) -> str:
158
"""
159
Creates a standalone Python module for a CMasher colormap.
160
161
Parameters:
162
- cmap: Name of CMasher colormap (with or without 'cmr.' prefix)
163
- save_dir: Directory to save the module file
164
- _copy_name: Alternative name for the module (internal use)
165
166
Returns:
167
str: Path to the created Python module file
168
169
Notes:
170
Creates a .py file that registers the colormap in matplotlib when
171
imported. Includes reversed version and shifted version for cyclic
172
colormaps.
173
174
Raises:
175
ValueError: If colormap name is not valid CMasher colormap
176
"""
177
```
178
179
#### Usage Examples
180
181
```python
182
import cmasher as cmr
183
import os
184
185
# Create standalone module for rainforest colormap
186
module_path = cmr.create_cmap_mod('rainforest')
187
print(f"Created module: {module_path}")
188
189
# Create module in specific directory
190
os.makedirs('colormap_modules', exist_ok=True)
191
ocean_path = cmr.create_cmap_mod('ocean', save_dir='colormap_modules')
192
193
# Create modules for multiple colormaps
194
colormaps_to_export = ['iceburn', 'wildfire', 'seasons']
195
for cmap_name in colormaps_to_export:
196
path = cmr.create_cmap_mod(cmap_name, save_dir='colormap_modules')
197
print(f"Exported {cmap_name} to {path}")
198
199
# Use standalone module (in a new Python session)
200
# import rainforest # This would register the colormap
201
# plt.imshow(data, cmap='cmr.rainforest')
202
```
203
204
### Advanced Import Patterns
205
206
#### Batch Import from Directory
207
208
```python
209
import cmasher as cmr
210
import numpy as np
211
import os
212
213
def create_colormap_collection(output_dir='my_colormaps'):
214
"""Create a collection of custom colormaps."""
215
os.makedirs(output_dir, exist_ok=True)
216
217
# Create various colormap types
218
colormaps = {
219
'cm_fire': np.array([[0, 0, 0], [1, 0, 0], [1, 1, 0], [1, 1, 1]]),
220
'cm_ice': np.array([[0, 0, 0.5], [0, 0.5, 1], [0.8, 0.9, 1], [1, 1, 1]]),
221
'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]])
222
}
223
224
for name, data in colormaps.items():
225
np.save(f"{output_dir}/{name}.npy", data)
226
227
# Import entire collection
228
cmr.import_cmaps(output_dir)
229
print(f"Imported {len(colormaps)} custom colormaps")
230
231
create_colormap_collection()
232
```
233
234
#### Colormap Format Conversion
235
236
```python
237
import cmasher as cmr
238
import numpy as np
239
240
def convert_colormap_formats(source_file, output_formats=['npy', 'txt', 'hex']):
241
"""Convert colormap between different file formats."""
242
# Load colormap data
243
if source_file.endswith('.npy'):
244
data = np.load(source_file)
245
else:
246
data = np.loadtxt(source_file)
247
248
base_name = source_file.replace('.npy', '').replace('.txt', '')
249
250
# Save in different formats
251
if 'npy' in output_formats:
252
np.save(f'{base_name}.npy', data)
253
254
if 'txt' in output_formats:
255
np.savetxt(f'{base_name}_norm.txt', data, fmt='%.6f')
256
257
if 'hex' in output_formats:
258
hex_colors = []
259
for rgb in data:
260
r, g, b = (rgb * 255).astype(int)
261
hex_colors.append(f'#{r:02X}{g:02X}{b:02X}')
262
263
with open(f'{base_name}_hex.txt', 'w') as f:
264
for hex_color in hex_colors:
265
f.write(hex_color + '\n')
266
267
# Example usage
268
data = np.random.rand(10, 3) # Random colormap
269
np.save('cm_random.npy', data)
270
convert_colormap_formats('cm_random.npy')
271
```
272
273
### Colormap Validation and Testing
274
275
```python
276
import cmasher as cmr
277
import numpy as np
278
import matplotlib.pyplot as plt
279
280
def validate_custom_colormap(data, name='test_cmap'):
281
"""Validate custom colormap data before registration."""
282
try:
283
# Convert to numpy array
284
data_array = np.array(data)
285
286
# Check dimensions
287
if data_array.ndim != 2 or data_array.shape[1] != 3:
288
print(f"Error: Data must be (N, 3) shape, got {data_array.shape}")
289
return False
290
291
# Check value ranges for normalized RGB
292
if np.any(data_array < 0) or np.any(data_array > 1):
293
print("Warning: Values outside [0, 1] range, assuming 8-bit RGB")
294
if np.any(data_array > 255):
295
print("Error: Values too large for 8-bit RGB")
296
return False
297
298
# Test registration
299
cmr.register_cmap(name, data)
300
301
# Test visualization
302
test_data = np.random.rand(5, 5)
303
plt.figure(figsize=(8, 3))
304
plt.subplot(1, 2, 1)
305
plt.imshow(test_data, cmap=f'cmr.{name}')
306
plt.title(f'Custom colormap: {name}')
307
plt.colorbar()
308
309
plt.subplot(1, 2, 2)
310
plt.imshow(test_data, cmap=f'cmr.{name}_r')
311
plt.title(f'Reversed: {name}_r')
312
plt.colorbar()
313
314
plt.tight_layout()
315
plt.show()
316
317
print(f"✓ Colormap '{name}' validated successfully")
318
return True
319
320
except Exception as e:
321
print(f"✗ Validation failed: {e}")
322
return False
323
324
# Test with example data
325
test_data = [[0, 0, 0.5], [0.5, 0, 1], [1, 0.5, 0.5], [1, 1, 1]]
326
validate_custom_colormap(test_data, 'validation_test')
327
```
328
329
### Environment Variable Support
330
331
```python
332
import os
333
import cmasher as cmr
334
335
# CMasher supports CMR_CMAP_PKGS environment variable
336
# for specifying additional colormap packages to import
337
338
# Set environment variable to include additional packages
339
os.environ['CMR_CMAP_PKGS'] = 'colorcet:cmocean'
340
341
# This would be used by CLI tools to import additional colormaps
342
# The packages are separated by ':' on Unix or ';' on Windows
343
```