Beispiel #1
0
def import_cmaps(cmap_path):
    """
    Reads in custom colormaps from a provided file or directory `cmap_path`;
    transforms them into :obj:`~matplotlib.colors.ListedColormap` objects; and
    makes them available in the :mod:`cmasher.cm` module, in addition to
    registering them in the :mod:`matplotlib.cm` module.
    Both the imported colormap and its reversed version will be registered.

    Parameters
    ----------
    cmap_path : str
        Relative or absolute path to a custom colormap file; or directory that
        contains custom colormap files. A colormap file can be a *NumPy* binary
        file ('.npy'); a *viscm* source file ('.jscm'); or any text file.
        If the file is not a JSCM-file, it must contain the normalized RGB
        values that define the colormap.

    Notes
    -----
    All colormap files must have names starting with the 'cm\\_' prefix. The
    resulting colormaps will have the name of their file without the prefix and
    extension.

    In *MPL*, the colormaps will have the added 'cmr.' prefix to avoid name
    clashes.

    Example
    -------
    Importing a colormap named 'test' can be done by saving its normalized RGB
    values in a file called 'cm_test.txt' and executing

        >>> import_cmaps('/path/to/dir/cm_test.txt')

    The 'test' colormap is now available in *CMasher* and *MPL* using

        >>> cmr.cm.test                 # CMasher
        >>> plt.get_cmap('cmr.test')    # MPL

    """

    # Obtain path to file or directory with colormaps
    cmap_path = path.abspath(cmap_path)

    # Check if provided file or directory exists
    if not path.exists(cmap_path):
        raise OSError(
            "Input argument 'cmap_path' is a non-existing path (%r)!" %
            (cmap_path))

    # Check if cmap_path is a file or directory and act accordingly
    if path.isfile(cmap_path):
        # If file, split cmap_path up into dir and file components
        cmap_dir, cmap_file = path.split(cmap_path)

        # Check if its name starts with 'cm_' and raise error if not
        if not cmap_file.startswith('cm_'):
            raise OSError("Input argument 'cmap_path' does not lead to a file "
                          "with the 'cm_' prefix (%r)!" % (cmap_path))

        # Set cm_files to be the sole read-in file
        cm_files = [cmap_file]
    else:
        # If directory, obtain the names of all files in cmap_path
        cmap_dir = cmap_path
        filenames = next(os.walk(cmap_dir))[2]

        # Extract the files with defined colormaps
        cm_files = [name for name in filenames if name.startswith('cm_')]
        cm_files.sort()

    # Read in all the defined colormaps, transform and register them
    for cm_file in cm_files:
        # Split basename and extension
        base_str, ext_str = path.splitext(cm_file)
        cm_name = base_str[3:]

        # Obtain absolute path to colormap data file
        cm_file_path = path.join(cmap_dir, cm_file)

        # Process colormap files
        try:
            # If file is a NumPy binary file
            if (ext_str == '.npy'):
                colorlist = np.load(cm_file_path).tolist()

            # If file is viscm source file
            elif (ext_str == '.jscm'):
                # Check if viscm is available
                try:
                    import viscm
                # If that fails, raise error
                except ImportError:
                    raise ImportError("The 'viscm' package is required to read"
                                      " '.jscm' files!")
                # If that succeeds, load RGB values from source file
                else:
                    # Load colormap
                    cmap = viscm.gui.Colormap(None, None, None)
                    cmap.load(cm_file_path)

                    # Create editor and obtain RGB values
                    v = viscm.viscm_editor(uniform_space=cmap.uniform_space,
                                           cmtype=cmap.cmtype,
                                           method=cmap.method,
                                           **cmap.params)
                    rgb, _ = v.cmap_model.get_sRGB(num=256)
                    colorlist = rgb.tolist()

            # If file is anything else
            else:
                colorlist = np.genfromtxt(cm_file_path).tolist()

            # Transform colorlist into a Colormap
            cmap_mpl = LC(colorlist, 'cmr.' + cm_name, N=len(colorlist))
            cmap_cmr = LC(colorlist, cm_name, N=len(colorlist))
            cmap_mpl_r = cmap_mpl.reversed()
            cmap_cmr_r = cmap_cmr.reversed()

            # Test that the colormaps can be called
            cmap_mpl(1)
            cmap_mpl_r(1)

            # Determine the cm_type of the colormap
            cm_type = _get_cm_type(cmap_mpl)

            # Add cmap to matplotlib's cmap list
            mplcm.register_cmap(cmap=cmap_mpl)
            setattr(cmrcm, cmap_cmr.name, cmap_cmr)
            cmrcm.__all__.append(cmap_cmr.name)
            cmrcm.cmap_d[cmap_cmr.name] = cmap_cmr
            cmrcm.cmap_cd[cm_type][cmap_cmr.name] = cmap_cmr

            # Add reversed cmap to matplotlib's cmap list
            mplcm.register_cmap(cmap=cmap_mpl_r)
            setattr(cmrcm, cmap_cmr_r.name, cmap_cmr_r)
            cmrcm.__all__.append(cmap_cmr_r.name)
            cmrcm.cmap_d[cmap_cmr_r.name] = cmap_cmr_r
            cmrcm.cmap_cd[cm_type][cmap_cmr_r.name] = cmap_cmr_r

        # If any error is raised, reraise it
        except Exception as error:
            raise ValueError("Provided colormap %r is invalid! (%s)" %
                             (cm_name, error))
Beispiel #2
0
        jscm_path = path.abspath(sys.argv[1])
        name = path.splitext(path.basename(jscm_path))[0]

        # Make a directory for the colormap files
        os.mkdir(name)

        # Move the .jscm-file to it
        shutil.move(jscm_path, name)

        # Load colormap from .jscm-file
        cmap = viscm.gui.Colormap(None, None, None)
        cmap.load("{0}/{0}.jscm".format(name))

        # Obtain RGB values of colormap
        v = viscm.viscm_editor(uniform_space=cmap.uniform_space,
                               cmtype=cmap.cmtype,
                               method=cmap.method,
                               **cmap.params)
        rgb, _ = v.cmap_model.get_sRGB(num=256)
        cmtype = cmap.cmtype

    elif (len(sys.argv) == 3):
        # Else, a diverging colormap is provided
        jscm_paths = [path.abspath(arg) for arg in sys.argv[1:]]
        name = path.basename(path.commonprefix(jscm_paths))[:-1]

        # Make a directory for the colormap files
        os.mkdir(name)

        # Move the .jscm-files to it
        for jscm_path in jscm_paths:
            shutil.move(jscm_path, name)
Beispiel #3
0
def import_cmaps(cmap_path):
    """
    Reads in custom colormaps from a provided file or directory `cmap_path`;
    transforms them into :obj:`~matplotlib.colors.ListedColormap` objects; and
    makes them available in the :mod:`cmasher.cm` module, in addition to
    registering them in the :mod:`matplotlib.cm` module.
    Both the imported colormap and its reversed version will be registered.

    If a provided colormap is a 'cyclic' colormap, its shifted version will
    also be registered.

    Parameters
    ----------
    cmap_path : str
        Relative or absolute path to a custom colormap file; or directory that
        contains custom colormap files. A colormap file can be a *NumPy* binary
        file ('.npy'); a *viscm* source file ('.jscm'); or any text file.
        If the file is not a JSCM-file, it must contain the normalized; 8-bit;
        or hexadecimal string RGB values that define the colormap.

    Notes
    -----
    All colormap files must have names starting with the 'cm\\_' prefix. The
    resulting colormaps will have the name of their file without the prefix and
    extension.

    In *MPL*, the colormaps will have the added 'cmr.' prefix to avoid name
    clashes.

    Example
    -------
    Importing a colormap named 'test' can be done by saving its normalized RGB
    values in a file called 'cm_test.txt' and executing

        >>> import_cmaps('/path/to/dir/cm_test.txt')

    The 'test' colormap is now available in *CMasher* and *MPL* using

        >>> cmr.cm.test                 # CMasher
        >>> plt.get_cmap('cmr.test')    # MPL

    """

    # Obtain path to file or directory with colormaps
    cmap_path = path.abspath(cmap_path)

    # Check if provided file or directory exists
    if not path.exists(cmap_path):
        raise OSError(
            "Input argument 'cmap_path' is a non-existing path (%r)!" %
            (cmap_path))

    # Check if cmap_path is a file or directory and act accordingly
    if path.isfile(cmap_path):
        # If file, split cmap_path up into dir and file components
        cmap_dir, cmap_file = path.split(cmap_path)

        # Check if its name starts with 'cm_' and raise error if not
        if not cmap_file.startswith('cm_'):
            raise OSError("Input argument 'cmap_path' does not lead to a file "
                          "with the 'cm_' prefix (%r)!" % (cmap_path))

        # Set cm_files to be the sole read-in file
        cm_files = [cmap_file]
    else:
        # If directory, obtain the names of all colormap files in cmap_path
        cmap_dir = cmap_path
        cm_files = list(map(path.basename, glob("%s/cm_*" % (cmap_dir))))
        cm_files.sort()

    # Read in all the defined colormaps, transform and register them
    for cm_file in cm_files:
        # Split basename and extension
        base_str, ext_str = path.splitext(cm_file)
        cm_name = base_str[3:]

        # Obtain absolute path to colormap data file
        cm_file_path = path.join(cmap_dir, cm_file)

        # Process colormap files
        try:
            # If file is a NumPy binary file
            if (ext_str == '.npy'):
                rgb = np.load(cm_file_path)

            # If file is viscm source file
            elif (ext_str == '.jscm'):
                # Check if viscm is available
                try:
                    import viscm
                # If that fails, raise error
                except ImportError:  # pragma: no cover
                    raise ImportError("The 'viscm' package is required to read"
                                      " '.jscm' files!")
                # If that succeeds, load RGB values from source file
                else:
                    # Load colormap
                    cmap = viscm.gui.Colormap(None, None, None)
                    cmap.load(cm_file_path)

                    # Create editor and obtain RGB values
                    v = viscm.viscm_editor(uniform_space=cmap.uniform_space,
                                           cmtype=cmap.cmtype,
                                           method=cmap.method,
                                           **cmap.params)
                    rgb, _ = v.cmap_model.get_sRGB()

            # If file is anything else
            else:
                rgb = np.genfromtxt(cm_file_path,
                                    dtype=None,
                                    comments='//',
                                    encoding=None)

            # Register colormap
            register_cmap(cm_name, rgb)

            # Check if provided cmap is a cyclic colormap
            # If so, obtain its shifted (reversed) versions as well
            if (get_cmap_type('cmr.' + cm_name) == 'cyclic'):
                # Determine the central value index of the colormap
                idx = len(rgb) // 2

                # Shift the entire colormap by this index
                rgb_s = np.concatenate([rgb[idx:], rgb[:idx]], axis=0)

                # Register this colormap as well
                register_cmap(cm_name + '_shifted', rgb_s)

        # If any error is raised, reraise it
        except Exception as error:
            raise ValueError("Provided colormap %r is invalid! (%s)" %
                             (cm_name, error))
Beispiel #4
0
    # Get colormap name
    name = path.splitext(path.basename(jscm_path))[0]

    # Make a directory for the colormap files
    os.mkdir(name)

    # Move the .jscm-file to it
    shutil.move(jscm_path, name)

    # Load colormap from .jscm-file
    cmap = viscm.gui.Colormap(None, None, None)
    cmap.load("{0}/{0}.jscm".format(name))

    # Obtain RGB values of colormap
    v = viscm.viscm_editor(uniform_space=cmap.uniform_space,
                           cmtype=cmap.cmtype,
                           method=cmap.method,
                           **cmap.params)
    rgb, _ = v.cmap_model.get_sRGB()
    cmtype = cmap.cmtype

    # Convert RGB values to string
    array_str = np.array2string(rgb,
                                max_line_width=79,
                                prefix='cm_data = ',
                                separator=', ',
                                threshold=rgb.size,
                                precision=8)

    # Remove all whitespaces before commas
    for i in range(8, 0, -1):
        array_str = array_str.replace(' ' * i + ', ', '0' * i + ', ')