#!/usr/bin/env python # -*- coding: utf-8 -*- ## This script converts the .xml(ParaView compatible format) colormaps into Matplotlib or MATLAB format import sys import os import matplotlib as mpl import matplotlib.pyplot as plt import numpy as np from lxml import etree ## load source xml file def load_xml(xml): try: xmldoc = etree.parse(xml) except IOError as e: print( 'The input file is invalid. It must be a colormap xml file. Go to https://sciviscolor.org/home/colormaps/ for some good options') print('Go to https://sciviscolor.org/matlab-matplotlib-pv44/ for an example use of this script.') raise NameError('Invalid Input') data_vals = [] color_vals = [] for s in xmldoc.getroot().findall('.//Point'): data_vals.append(float(s.attrib['x'])) color_vals.append((float(s.attrib['r']), float(s.attrib['g']), float(s.attrib['b']))) return {'color_vals': color_vals, 'data_vals': data_vals} ## source of this function: http://schubert.atmos.colostate.edu/~cslocum/custom_cmap.html#code def make_cmap(xml): vals = load_xml(xml) colors = vals['color_vals'] position = vals['data_vals'] if len(position) != len(colors): sys.exit('position length must be the same as colors') elif ((position[0] != 0) or (position[-1] != 1)): sys.exit('position must start with 0 and end with 1') cdict = {'red': [], 'green': [], 'blue': []} if position[0] != 0: cdict['red'].append((0, colors[0][0], colors[0][0])) cdict['green'].append((0, colors[0][1], colors[0][1])) cdict['blue'].append((0, colors[0][2], colors[0][2])) for pos, color in zip(position, colors): cdict['red'].append((pos, color[0], color[0])) cdict['green'].append((pos, color[1], color[1])) cdict['blue'].append((pos, color[2], color[2])) if position[-1] != 1: cdict['red'].append((1, colors[-1][0], colors[-1][0])) cdict['green'].append((1, colors[-1][1], colors[-1][1])) cdict['blue'].append((1, colors[-1][2], colors[-1][2])) cmap = mpl.colors.LinearSegmentedColormap('my_colormap', cdict, 256) return cmap ## Print MATLAB compatible matrix def print_cmap_matrix(colormap): c = 0 print('') print('matlab-colormap = [') while (c <= 255): if c == 0: pass else: print('') print(str(colormap(c)[0:3]).replace('(', '').replace(')', '')) c = c + 1 print('];') ## This is a quick example plotting the 8 by 1 gradient of the colormap ## with Matplotlib def plot_cmap(colormap): gradient = np.linspace(0, 1, 256) gradient = np.vstack((gradient, gradient)) fig = plt.figure(figsize=(8, 1)) map = fig.add_subplot(111) map.set_frame_on(False) map.get_xaxis().set_visible(False) map.get_yaxis().set_visible(False) fig.tight_layout(pad=0) map.imshow(gradient, aspect='auto', cmap=plt.get_cmap(colormap)) plt.show() ## check for correct file type def is_xml(string): if os.path.isfile(string): return string else: raise argparse.ArgumentTypeError('The file %s does not exist!' % string) ## Example usage if __name__ == '__main__': import argparse parser = argparse.ArgumentParser( description='Convert ParaView compatible colormaps to Matplotlib or MATLAB compatible colormaps.') parser.add_argument('-f', '--file-path', dest='path', required=True, type=lambda s: is_xml(s), help='Input file path of .xml colormap with position starting at 0 and ending at 1.') parser.add_argument('-m', '--make-matrix', dest='matrix', action='store_true', required=False, help='Print a 3xn matrix of rgb values to copy and paste into MATLAB.') args = parser.parse_args() ## construct the colormap mycmap = make_cmap(args.path) print('converted successfully!') ## mycmap is matplotlib compatible object. to query color value out of it: print('example rgba value for data value 0 is: ' + str(mycmap(0.0))) ## MATLAB Users: This fuction will output a RGB matrix to use in MATLAB if args.matrix == True: print_cmap_matrix(mycmap) ## Plotting the colormap to test the conversion plot_cmap(mycmap) import matplotlib.pyplot as plt if __name__ == "__main__": pass