help colrspace
---------------------------------------------------------------------------------------

Title

    ColrSpace -- Mata class for color management


Description

    ColrSpace is a class-based color management system implemented in Mata. It
    supports a wide variety of color spaces and translations among them, provides
    color generators and a large collection of named palettes, and features
    functionality such as color interpolation, grayscale conversion, or color vision
    deficiency simulation.

    ColrSpace requires Stata 14.2 or newer.

    The examples below make use of the colorpalette command, which is provided as
    part of the palettes package. Type

        . ssc install palettes, replace

    to install the package.


Contents

    Color spaces
    Alphabetical index of functions
    Initialize a ColrSpace object
    Settings:
        RGB working space
        XYZ reference white
        CIECAM02 viewing conditions
        Default coefficients for J'M'h and J'a'b'
        Chromatic adaption method
    Define and transform colors:
        String input/output (Stata interface)
        Import/export colors in various spaces
        Set/retrieve opacity and intensity
        Interpolate, mix, recycle, select, order
        Intensify, saturate, luminate
        Grayscale conversion
        Color vision deficiency simulation
        Color palettes
        Color generators
        Color differences and contrast ratios
        Some utilities
    Source code and certification script
    References
    Author
    Also see


Color spaces

    The following diagram shows an overview of the different color spaces and coding
    schemes supported by ColrSpace:

                  HEX   +- HSV
                   |    |
         (RGBA) - RGB   |- HSL                  xyY1
                   |    |                        |
        (RGBA1) - RGB1 --- CMYK1 - CMYK         xyY
                   |                             |
                  lRGB - (chromatic adaption) - XYZ - XYZ1
                                                 |
                        +------------------------+
                       Lab     Luv    CAM02 [mask]
                        |       |       |
                       LCh     HCL     JMh [coefs]
                                        |
                                       Jab [coefs]

    The shown acronyms are the names by which the color spaces are referred to in
    ColrSpace. Internally, ColrSpace stores colors using their RGB1 values and
    additionally maintains an opacity value (alpha) in [0,1] and an intensity
    adjustment multiplier in [0,255] for each color.

    HEX is a hex RGB value (hex triplet; see Wikipedia 2019c). Examples are "#ffffff"
        for white or "#1a476f" for Stata's navy. ColrSpace will always return HEX
        colors using their lowercase 6-digit codes. As input, however, uppercase
        spelling and 3-digit abbreviations are allowed. For example, white can be
        specified as are "#ffffff", "#FFFFFF", "#fff", or "#FFF".

    RGB is an RGB triplet (red, green, blue) in 0-255 scaling (see Wikipedia 2018f).
        When returning RGB values, ColrSpace will round the values to integers and
        clip them at 0 and 255.

    RGB1 is an RGB triplet in 0-1 scaling. ColrSpace does not clip or round the
        values and may thus return values larger than 1 or smaller than 0. Using
        unclipped values ensures consistency of translations among different color
        spaces. To retrieve a matrix of clipped values, you can type C =
        S.clip(S.get("RGB1"), 0, 1).

        RGB1 is the format in which ColrSpace stores colors internally. By default,
        ColrSpace assumes that the colors are in the standard RGB working space
        ("sRGB"), but this can be changed; see Setting the RGB working space. Note
        that changing the RGB working space after colors have been added to a
        ColrSpace object will not change the stored values. To transform colors from
        one RGB working space to another RGB working space, you could export the
        colors to XYZ typing XYZ = S.get("XYZ"), change the RGB working space using
        function S.rgbspace(), and then reimport the colors typing S.set(XYZ, "XYZ").

    lRGB stands for linear RGB in 0-1 scaling, that is, RGB1 from which gamma
        correction has been removed.

    HSV is a color triplet in the HSV (hue, saturation, value) color space. Hue is in
        degrees of the color wheel (0-360), saturation and value are numbers in
        [0,1]. ColrSpace uses the procedure described in Wikipedia (2018d) to
        translate between HSV and RGB.

    HSL is a color triplet in the HSL (hue, saturation, lightness) color space. Hue
        is in degrees of the color wheel (0-360), saturation and lightness are
        numbers in [0,1]. ColrSpace uses the procedure described in Wikipedia (2018d)
        to translate between HSL and RGB.

    CMYK is a CMYK quadruplet (cyan, magenta, yellow, black) in 0-255 scaling. When
        returning CMYK values, ColrSpace will round the values to integers and clip
        them at 0 and 255. There is no unique standard method to translate between
        CMYK and RGB, as translation is device-specific. ColrSpace uses the same
        translation as is implemented in official Stata (for CMYK to RGB see program
        setcmyk in file color.class; for RGB to CMYK see program rgb2cmyk in file
        palette.ado).

    CMYK1 is a CMYK quadruplet (cyan, magenta, yellow, black) in 0-1 scaling.
        ColrSpace does not clip or round the values and may thus return values larger
        than 1 or smaller than 0. To retrieve a matrix of clipped values, you can
        type C = S.clip(S.get("CMYK1"), 0, 1). See CMYK for additional explanations.

    XYZ is a CIE 1931 XYZ tristimulus value in Y_white = 100 scaling. See Wikipedia
        (2018a) for background information. XYZ values are defined with respect to a
        reference white; see Setting the XYZ reference white. The default illuminant
        used by ColrSpace to define the reference white is "D65" (noon daylight for a
        CIE 1931 2° standard observer). To transform RGB to CIE XYZ, ColrSpace first
        removes gamma correction to obtain linear RGB (lRGB) and then transforms lRGB
        to XYZ using an appropriate transformation matrix (see, e.g., Pascale 2003
        for detailed explanations of both steps), possibly applying chromatic
        adaption to take account of a change in the reference white between the RGB
        working space and the XYZ color space.

    XYZ1 is a CIE XYZ tristimulus value in Y_white = 1 scaling. See XYZ for
        additional explanations.

    xyY is a CIE xyY triplet, where x (cyan to red for y around .2) and y (magenta to
        green for x around .2) are the chromaticity coordinates in [0,1], with x + y
        <= 1, and Y is the luminance in Y_white = 100 scaling (Y in CIE xyY is the
        same as Y in CIE XYZ). ColrSpace uses the procedure described in Wikipedia
        (2018a) to translate between XYZ and xyY.

    xyY1 is a CIE xyY triplet, with Y in Y_white = 1 scaling. See xyY for additional
        explanations.

    Lab is a color triplet in the CIE L*a*b* color space. L* in [0,100] is the
        lightness of the color, a* is the green (-) to red (+) component, b* is the
        blue (-) to yellow (+) component. The range of a* and b* is somewhere around
        +/- 100 for typical colors. ColrSpace uses the procedure described in
        Wikipedia (2018b) to translate between XYZ and CIE L*a*b*.

    LCh is a color triplet in the CIE LCh color space (cylindrical representation of
        CIE L*a*b*). L (lightness) in [0,100] is the same as L* in CIE L*a*b*, C
        (chroma) is the relative colorfulness (with typical values in a range of
        0-100, although higher values are possible), h (hue) is the angle on the
        color wheel in degrees (0-360). See Wikipedia (2018b).

    Luv is a color triplet in the CIE L*u*v* color space. L* in [0,100] is the
        lightness of the color, u* is the green (-) to red (+) component, v* is the
        blue (-) to yellow (+) component. The range of u* and v* is somewhere around
        +/- 100 for typical colors. ColrSpace uses the procedure described in
        Wikipedia (2018c) to translate between XYZ and CIE L*u*v*. L* in CIE L*u*v*
        is the same as L* in CIE L*a*b*.

    HCL is a color triplet in the HCL color space (cylindrical representation of CIE
        L*u*v*). H (hue) is the angle on the color wheel in degrees (0-360), C
        (chroma) is the relative colorfulness (with typical values in a range of
        0-100, although higher values are possible), L (lightness) in [0,100] is the
        same as L* in CIE L*u*v*. See Wikipedia (2018c).

    CAM02 is a color value in the CIECAM02 color space. See Luo and Li (2013) for
        details. In ColrSpace, CIECAM02 is specified as

            "CAM02 [mask]"

        where optional mask selects the CIECAM02 attributes. The supported attributes
        are Q (brightness), J (lightness), M (colourfulness), C (chroma), s
        (saturation), h (hue angle), and H (hue composition). For example, you could
        type

            C = S.get("CAM02 QJMCshH")

        to obtain a n x 7 matrix containing all available attributes for each color.
        When importing colors, e.g. using S.colors() or S.set(), mask must contain at
        least one of Q and J, at least one of M, C, and s, and at least one of h and
        H. If mask is omitted, ColrSpace assumes "CAM02 JCh".

    JMh is a color triplet in the CIECAM02-based perceptually uniform J'M'h color
        space. See Luo and Li (2013, chapter 2.6.1) and Luo et al. (2006) for
        details. In ColrSpace, J'M'h is specified as

            "JMh [coefs]"

        where optional coefs selects the transformation coefficients. coefs can be

                UCS
            or  LCD
            or  SCD
            or  K_L c_1 c_2

        (lowercase spelling and abbreviations allowed). "JMh UCS" is equivalent to
        "JMh 1 .007 .0228", "JMh LCD" is equivalent to "JMh .77 .007 .0053",
        "JMh SCD" is equivalent to "JMh 1.24 .007 .0363". If coefs is omitted, the
        default coefficients as set by S.ucscoefs() will be used.

    Jab is a color triplet in the CIECAM02-based perceptually uniform J'a'b' color
        space. See Luo and Li (2013, chapter 2.6.1) and Luo et al. (2006) for
        details. In ColrSpace, J'a'b' is specified as

            "Jab [coefs]"

        where optional coefs is as described in JMh.

    RGBA is an opacity-extended RGB value (red, green, blue, alpha), where red,
        green, and blue are in 0-255 scaling and alpha is a number in [0,1] (0 =
        fully transparent, 1 = fully opaque). RGBA is not directly supported by
        S.convert(), but is allowed as input or output format in functions such as
        S.colors(), S.set(), or S.get(). Alternatively, in S.colors(), you can use
        non-extended RGB and specify opacity using Stata's colorstyle syntax; for
        example "RGBA 26 71 111 0.7" is equivalent to "RGB 26 71 111%70" or "26 71
        111%70" (see the section on String input/output below). A further alternative
        is to manage opacity using S.opacify() or S.alpha() (see Set/retrieve opacity
        and intensity).

    RGBA1 is an opacity-extended RGB value (red, green, blue, alpha), where red,
        green, and blue are in 0-1 scaling and alpha is a number in [0,1] (0 = fully
        transparent, 1 = fully opaque). See RGBA for additional explanations.


Alphabetical index of functions

    ColrSpace()         initialize a ColrSpace object
    S.add()             add colors in particular space
    S.alpha()           set/retrieve opacity
    S.chadapt()         set chromatic adaption method
    S.clip()            helper function for clipping
    S.contrast()        compute contrast ratios
    S.delta()           compute color differences
    S.colipolate()      helper function for interpolating
    S.colors()          string input/output (scalar)
    S.Colors()          string input/output (vector)
    S.colrecycle()      helper function for recycling
    S.convert()         convert colors between spaces
    S.cvd()             color vision deficiency simulation
    S.cvd_M()           helper function to retrieve CVD matrix
    S.generate()        color generators
    S.get()             retrieve colors in particular space
    S.gray()            gray scale conversion
    S.info()            color description input/output (scalar)
    S.Info()            color description input/output (vector)
    S.intensify()       adjust color intensity
    S.intensity()       set/retrieve intensity adjustment
    S.ipolate()         interpolate colors
    S.isipolate()       whether interpolation has been applied
    S.luminate()        adjust luminance of colors
    S.matplotlib()      retrieve matplotlib colormap
    S.matplotlib_ip()   helper function to create colormaps
    S.mix()             mix colors
    S.N()               retrieve number of colors
    S.opacity()         set/retrieve opacity
    S.order()           order colors
    S.palette()         retrieve colors from named palette
    S.pclass()          set/retrieve palette class
    S.pname()           set/retrieve palette name
    S.recycle()         recycle colors
    S.reset()           reset colors in particular space
    S.reverse()         reverse order of colors
    S.rgbspace()        set RGB working space
    S.rgb_gamma()       set/retrieve gamma correction
    S.rgb_invM()        set/retrieve XYZ-to-lRGB matrix
    S.rgb_M()           set/retrieve lRGB-to-XYZ matrix
    S.rgb_white()       set/retrieve RGB reference white
    S.rgb_xy()          set/retrieve RGB primaries
    S.saturate()        adjust saturation (chroma) of colors
    S.select()          select colors
    S.set()             set colors in particular space
    S.tmatrix()         retrieve transformation matrices
    S.ucscoefs()        set default J'M'h/J'a'b' coefficients
    S.viewcond()        set/retrieve CIECAM02 viewing conditions
    S.xyzwhite()        set/retrieve XYZ reference white
    S.XYZ_to_XYZ()      apply chromatic adaption

    Several of the above functions also come in variants such as S.add_name(),
    S.name_added(), or S.add_name_added(), where name is the function name.


Initialize a ColrSpace object

    To initialize a new ColrSpace object, type

        class ColrSpace scalar S

    or

        S = ColrSpace()

    where S is the name of the object. After initialization, the object will be
    empty, that is, contain no colors. However, the object will be initialized with
    the following default settings:

        S.rgbspace("sRGB")
        S.xyzwhite("D65")
        S.viewcond(20, 64/(5*pi()), "average")
        S.ucscoefs("UCS")
        S.chadapt("Bfd")


Setting the RGB working space

    To set the RGB working space, type

        S.rgbspace("name")

    where name is one of the following:

        Adobe 1998       Adobe RGB (1998)
        Apple            Apple RGB
        Best             Best RGB
        Beta             Beta RGB
        Bruce            Bruce RGB
        CIE              CIE 1931 RGB
        ColorMatch       ColorMatch RGB
        Don 4            Don RGB 4
        ECI v2           ECI RGB v2
        Ekta PS5         Ekta Space PS5
        Generic          Generic RGB
        HDTV             HDTV (HD-CIF)
        NTSC             NTSC RGB (1953)
        PAL/SECAM        PAL/SECAM RGB
        ProPhoto         ProPhoto RGB
        SGI              SGI RGB
        SMPTE-240M       SMPTE-240M RGB
        SMPTE-C          SMPTE-C RGB
        sRGB             Standard RGB using primaries from Lindbloom (2017b)
        sRGB2            Standard RGB using equation F.8 (XYZ to RGB matrix) from IEC
                           (2003)
        sRGB3            Standard RGB using equation F.7 (RGB to XYZ matrix) from IEC
                           (2003)
        Wide Gamut       Adobe Wide Gamut RGB
        Wide Gamut BL    Wide Gamut variant from Lindbloom (2017b)

    The names can be abbreviated and typed in lowercase letters. If abbreviation is
    ambiguous, the first matching name in the alphabetically ordered list will be
    used. See the ColrSpace source code for the definitions of the spaces. The
    definitions have been taken from Pascale (2003) and Lindbloom (2017b). Also see
    Wikipedia (2018g). The default is S.rgbspace("sRGB"). This default can also be
    selected by typing S.rgbspace(""). Other color management systems may use
    slightly different definition of standard RGB. For example, the colorspacious
    Python library by Smith (2018) uses a definition equivalent to "sRGB2". The
    advantage of "sRGB" is that RGB white (255, 255, 255) translates to the reference
    white in XYZ, which is not exactly true for "sRGB2" or "sRGB3".

    An RGB working space consists of three elements: the parameters of the gamma
    compression used to transform lRGB (linear RGB) to RGB, the reference white, and
    the working space primaries used to transform XYZ to lRGB. Instead of choosing a
    named RGB working space, the elements can also be set directly. To set the gamma
    compression parameters, type

        S.rgb_gamma(args)

    where args is

            gamma
        or  gamma, offset, transition, slope
        or  (gamma, offset, transition, slope)
        or  "gamma"
        or  "gamma offset transition slope"

    If only gamma is provided, simple gamma encoding C' = C^(1/gamma) is applied. If
    offset, transition, and slope are also provided, the detailed gamma encoding C' =
    (1 + offset) * C^(1/gamma) - offset if C > transition and else C' = C * slope is
    used. A typical value for gamma is 2.2; see Novak (2016) for an excellent
    explanation of gamma compression. Likewise, the reference white can be set by

        S.rgb_white(args)

    where args is as described in Setting the XYZ reference white. If the reference
    white of the RGB working space differs from the XYZ reference white, ColrSpace
    applies chromatic adaption when translating between XYZ and lRGB. Furthermore, to
    set the working space primaries. type

        S.rgb_xy(xy)

    where xy is a 3 x 2 matrix containing the red, green, and blue xy primaries.
    ColrSpace uses the method described in Lindbloom (2017c) to compute the
    lRGB-to-XYZ transformation matrix from the white point and the primaries, and
    sets the XYZ-to-lRGB matrix to the inverse of the lRGB-to-XYZ matrix.
    Alternatively, you can type

        S.rgb_M(M)

    where M is a 3 x 3 matrix, to directly set the lRGB-to-XYZ matrix to M and the
    XYZ-to-lRGB matrix to luinv(M), or

        S.rgb_invM(invM)

    to set the XYZ-to-lRGB matrix to invM and the lRGB-to-XYZ matrix to luinv(invM).
    To retrieve the current settings, you can type

        gamma = S.rgb_gamma()
        white = S.rgb_white()
           xy = S.rgb_xy()
            M = S.rgb_M()
         invM = S.rgb_invM()


Setting the XYZ reference white

    To set the reference white for the CIE XYZ color space, type

        S.xyzwhite(args)

    where args is

            X, Y, Z
        or  (X, Y, Z)
        or  "X Y Z"
        or  x, y
        or  (x, y)
        or  "x y"
        or  "name"

    where X, Y, and Z are the XYZ coordinates of the white point (with Y = 100), x
    and y are the xyY coordinates of the white point (assuming Y = 100), and name is
    one of the following:

        CIE 1931 2°  CIE 1964 10°    Description
        observer     observer        
        A            A 10 degree     Incandescent/Tungsten 2856K
        B            B 10 degree     Direct sunlight at noon 4874K (obsolete)
        B BL                         B 2 degree variant from Lindbloom (2017a)
        C            C 10 degree     North sky daylight 6774K (obsolete)
        D50          D50 10 degree   Horizon light 5003K (used for color rendering)
        D55          D55 10 degree   Mid-morning/mid-afternoon daylight 5503K (used
                                       for photography)
        D65          D65 10 degree   Noon daylight 6504K (new version of north sky
                                       daylight)
        D75          D75 10 degree   North sky daylight 7504K
        9300K                        High eff. blue phosphor monitors 9300K
        E                            Uniform energy illuminant 5454K
        F1           F1 10 degree    Daylight fluorescent 6430K
        F2           F2 10 degree    Cool white fluorescent 4200K
        F3           F3 10 degree    White fluorescent 3450K
        F4           F4 10 degree    Warm white fluorescent 2940K
        F5           F5 10 degree    Daylight fluorescent 6350K
        F6           F6 10 degree    Lite white fluorescent 4150K
        F7           F7 10 degree    Broad-band daylight fluorescent, 6500K
        F8           F8 10 degree    D50 simulator, Sylvania F40 design 50, 5000K
        F9           F9 10 degree    Cool white deluxe fluorescent 4150K
        F10          F10 10 degree   Philips TL85, Ultralume 50, 5000K
        F11          F11 10 degree   Narrow-band white fluorescen, Philips TL84,
                                       Ultralume 40, 4000K
        F12          F12 10 degree   Philips TL83, Ultralume 30, 3000K

    The names can be abbreviated and typed in lowercase letters (for example, "D55 10
    degree" could be typed as "d55 10"). If abbreviation is ambiguous, the first
    matching name in the alphabetically ordered list will be used. See the ColrSpace
    source code for the definitions of the white points. The definitions have been
    taken from Pascale (2003), Lindbloom (2017a), and Wikipedia (2018h). The default
    is S.xyzwhite("D65"). This default can also be selected by typing S.xyzwhite(.)
    or S.xyzwhite(""). To retrieve a 1 x 3 rowvector containing the XYZ coordinates
    of the current white point, you can type

        white = S.xyzwhite()


Setting the CIECAM02 viewing conditions

    To set the CIECAM02 viewing conditions, type

        S.viewcond(args)

    where args is

            Y_b, L_A, F, c, N_c
        or  Y_b, L_A, (F, c, N_c)
        or  (Y_b, L_A, F, c, N_c)
        or  "Y_b L_A F c N_c"
        or  Y_b, L_A, "surround"
        or  "Y_b L_A surround"

    with surround equal to average (F = 1, c = .69, N_c = 1), dim (F = .9, c = .59,
    N_c = .9), or dark (F = .8, c = .525, N_c = .8) (abbreviations allowed). The
    default is Y_b = 20, L_A = 64/(5*pi()), and average surround. These defaults can
    also be selected by typing S.viewcond(.) or S.viewcond(""), or by setting Y_b to
    ., L_A to ., and surround to . or empty string. To retrieve a 1 x 5 rowvector of
    the current viewing condition parameters, type

        viewcond = S.viewcond()

    See Luo and Li (2013) for details on CIECAM02 viewing conditions.


Setting the default coefficients for J'M'h and J'a'b'

    To set the default uniform color space coefficients for J'M'h and J'a'b', type

        S.ucscoefs(args)

    where args is

            K_L, c_1, c_2
        or  (K_L, c_1, c_2)
        or  "K_L c_1 c_2"
        or  "name"

    with name equal to UCS (K_L = 1, c_1 = .007, c_2 = .0228), LCD (K_L = .77, c_1 =
    .007, c_2 = .0053), or SCD (K_L = 1.24, c_1 = .007, c_2 = .0363) (abbreviations
    and lowercase letters allowed). To to retrieve a 1 x 3 rowvector of the current
    default coefficients, type

        ucscoefs = S.ucscoefs()

    See Luo and Li (2013, chapter 2.6.1) and Luo et al. (2006) for details on these
    coefficients.


Setting the chromatic adaption method

    To set the chromatic adaption method type

        S.chadapt(method)

    where method is "Bfd" (Bradford), "identity" (XYZ Scaling), "vKries" (Von Kries),
    or "CAT02" (abbreviations and lowercase letters allowed). The default is
    S.chadapt("Bfd"), which can also be selected by typing S.chadapt(""). The
    Bradford, XYZ Scaling, and Von Kries methods use the procedure described in
    Lindbloom (2017a), the "CAT02" method uses the procedure described in Luo and Li
    (2013) (page 33). To retrieve a string scalar containing the current method, type

        method = S.chadapt()

    ColrSpace uses chromatic adaption internally whenever such a translation is
    necessary. However, you can also apply chromatic adaption manually by typing

        XYZnew = S.XYZ_to_XYZ(XYZ, from, to)

    where XYZ is an n x 3 matrix of XYZ values to be adapted, from is the origin
    whitepoint, and to is the destination whitepoint; any single-argument whitepoint
    specification as described in Setting the XYZ reference white is allowed.
    Function S.XYZ_to_XYZ() does not change or store any colors in S.

    To retrieve the predefined transformation matrices on which chromatic adaption is
    based, type

        M = S.tmatrix(name)

    where name is "Bfd", "identity", "vKries", "CAT02", or "HPE"
    (Hunt-Pointer-Estevez) (abbreviations and lowercase letters allowed). The default
    is S.tmatrix("Bfd"), which can also be selected by typing S.tmatrix(""). The
    "HPE" matrix is not used for chromatic adaption but has been included in
    S.tmatrix() for convenience. It is used when translating colors from XYZ to
    CIECAM02; see Luo and Li (2013).


String input/output (Stata interface)

        +-------------+
    ----+ Color input +--------------------------------------------------------------

    To import colors from a string scalar colors containing a list of color
    specifications, type

        S.[add_]colors(colors[, delimiter])

    where string scalar delimiter sets the character(s) delimiting the
    specifications; the default is to assume a space-separated list, i.e. delimiter =
    " ". To avoid breaking a specification that contains a delimiting character,
    enclose the specification in double quotes. S.colors() will replace preexisting
    colors in S by the new colors; alternatively, use S.add_colors() to append the
    new colors to the existing colors.

    To import colors from a string vector Colors (each element containing a single
    color specification), type

        S.[add_]Colors(Colors)

    The syntax for a single color specification is

        color[%#][*#]

    where %# sets the opacity (in percent; 0 = fully transparent, 100 = fully
    opaque), *# sets the intensity adjustment multiplier (values between 0 and 1 make
    the color lighter; values larger than one make the color darker), and color is
    one of the following:

        name               official Stata color name as listed in colorstyle
        webname            web color name as listed below
        #rrggbb            6-digit hex RGB value; white = #FFFFFF or #ffffff, navy =
                             #1A476F or #1a476f
        #rgb               3-digit abbreviated hex RGB value; white = #FFF or #fff
        # # #              RGB value in 0-255 scaling; navy = "26 71 111"
        # # # #            CMYK value in 0-255 or 0-1 scaling; navy = "85 40 0 144"
                             or ".333 .157 0 .565"
        RGB # # #          RGB value in 0-255 scaling; navy = "RGB 26 71 111"
        RGB1 # # #         RGB value in 0-1 scaling; navy = "RGB1 .102 .278 .435"
        lRGB # # #         linear RGB value in 0-1 scaling; navy = "lRGB .0103 .063
                             .159"
        CMYK # # # #       CMYK value in 0-255 scaling; navy = "CMYK 85 40 0 144"
        CMYK1 # # # #      CMYK value in 0-1 scaling; navy = "CMYK1 .333 .157 0 .565"
        HSV # # #          HSV value; navy = "HSV 208 .766 .435"
        HSL # # #          HSL value; navy = "HSL 208 .620 .269"
        XYZ # # #          CIE XYZ value in 0-100 scaling; navy = "XYZ 5.55 5.87
                             15.9"
        XYZ1 # # #         CIE XYZ value in 0-1 scaling; navy = "XYZ1 .0555 .0587
                             .159"
        xyY # # #          CIE xyY value with Y in 0-100 scaling; navy = "xyY .203
                             .215 5.87"
        xyY1 # # #         CIE xyY value with Y in 0-1 scaling; navy = "xyY1 .203
                             .215 .0587"
        Lab # # #          CIE L*a*b* value; navy = "Lab 29 -.4 -27.5"
        LCh # # #          LCh value (polar CIE L*a*b*); navy = "LCh 29 27.5 269.2"
        Luv # # #          CIE L*u*v* value; navy = "Luv 29 -15.4 -35.6"
        HCL # # #          HCL value (polar CIE L*u*v*); navy = "HCL 246.6 38.8 29"
        CAM02 [mask] ...   CIECAM02 value according to mask; navy = "CAM02 JCh 20.2
                             37 245" or "CAM02 QsH 55.7 69.5 303.5"
        JMh [coefs] # # #  CIECAM02 J'M'h value; navy = "JMh 30.1 21 245"
        Jab [coefs] # # #  CIECAM02 J'a'b' value; navy = "Jab 30.1 -8.9 -19" or "Jab
                             LCD 39 -10.6 -23"
        RGBA # # # #       RGB 0-255 value where the last number specifies the
                             opacity in [0,1]
        RGBA1 # # # #      RGB 0-1 value where the last number specifies the opacity
                             in [0,1]

        The colorspace labels (but not mask) can be typed in lowercase letters. The
        provided examples are for standard viewing conditions.

    webname is one of the following (see 
    http://www.w3schools.com/colors/colors_names.asp):

        AliceBlue, AntiqueWhite, Aqua, Aquamarine, Azure, Beige, Bisque, Black,
        BlanchedAlmond, Blue, BlueViolet, Brown, BurlyWood, CadetBlue, Chartreuse,
        Chocolate, Coral, CornflowerBlue, Cornsilk, Crimson, Cyan, DarkBlue,
        DarkCyan, DarkGoldenRod, DarkGray, DarkGrey, DarkGreen, DarkKhaki,
        DarkMagenta, DarkOliveGreen, DarkOrange, DarkOrchid, DarkRed, DarkSalmon,
        DarkSeaGreen, DarkSlateBlue, DarkSlateGray, DarkSlateGrey, DarkTurquoise,
        DarkViolet, DeepPink, DeepSkyBlue, DimGray, DimGrey, DodgerBlue, FireBrick,
        FloralWhite, ForestGreen, Fuchsia, Gainsboro, GhostWhite, Gold, GoldenRod,
        Gray, Grey, Green, GreenYellow, HoneyDew, HotPink, IndianRed, Indigo, Ivory,
        Khaki, Lavender, LavenderBlush, LawnGreen, LemonChiffon, LightBlue,
        LightCoral, LightCyan, LightGoldenRodYellow, LightGray, LightGrey,
        LightGreen, LightPink, LightSalmon, LightSeaGreen, LightSkyBlue,
        LightSlateGray, LightSlateGrey, LightSteelBlue, LightYellow, Lime, LimeGreen,
        Linen, Magenta, Maroon, MediumAquaMarine, MediumBlue, MediumOrchid,
        MediumPurple, MediumSeaGreen, MediumSlateBlue, MediumSpringGreen,
        MediumTurquoise, MediumVioletRed, MidnightBlue, MintCream, MistyRose,
        Moccasin, NavajoWhite, Navy, OldLace, Olive, OliveDrab, Orange, OrangeRed,
        Orchid, PaleGoldenRod, PaleGreen, PaleTurquoise, PaleVioletRed, PapayaWhip,
        PeachPuff, Peru, Pink, Plum, PowderBlue, Purple, RebeccaPurple, Red,
        RosyBrown, RoyalBlue, SaddleBrown, Salmon, SandyBrown, SeaGreen, SeaShell,
        Sienna, Silver, SkyBlue, SlateBlue, SlateGray, SlateGrey, Snow, SpringGreen,
        SteelBlue, Tan, Teal, Thistle, Tomato, Turquoise, Violet, Wheat, White,
        WhiteSmoke, Yellow, YellowGreen

        The names can be abbreviated and typed in lowercase letters. If abbreviation
        is ambiguous, the first matching name in the alphabetically ordered list will
        be used. In case of name conflict, official Stata colors will take precedence
        over web colors; use the uppercase names as shown above to prevent such
        conflict (for example, pink will refer to official Stata pink, Pink will
        refer to web color pink).

    Example:

        . mata: S = ColrSpace()
        . mata: S.colors("LightCyan MediumAqua BurlyWood")
        . colorpalette mata(S)
        . mata: S.add_colors("SeaShell Crimson")
        . colorpalette mata(S)
        . mata: S.colors("#337ab7, lab 50 -23 32, xyz 80 30 40, hcl 200 50 30", ",")
        . colorpalette mata(S)
        . mata: S.colors("navy*.5 orange%80 maroon*.7%60")
        . colorpalette mata(S)

        +--------------+
    ----+ Color output +-------------------------------------------------------------

    To export colors into a string scalar containing a space-separated list of color
    specifications compatible with Stata graphics, type

        colors = S.colors[_added]([rgbforce])

    where rgbforce!=0 enforces exporting all colors using their in RGB values. Colors
    that have been defined in terms of their Stata color names or CMYK values are
    exported as is by default, because these specifications are understood by Stata
    graphics. Specify rgbforce!=0 to export these colors as RGB values. S.colors()
    exports all colors; use S.colors_added() to export only the colors that have been
    added last.

    To export colors into a string column vector (each row containing a single color
    specification), type

        Colors = S.Colors[_added]([rgbforce])

    Example:

        . mata: S = ColrSpace()
        . mata: S.colors("navy*.5 orange%80 maroon*.7%60")
        . mata: S.colors()
        . mata: S.colors(1)
        . mata: S.add_colors("SeaShell Crimson")
        . mata: S.colors_added()

        +-------------------+
    ----+ Description input +--------------------------------------------------------

    To import information from a string scalar info containing a list of color
    descriptions (e.g. color names or other text describing a color), type

        S.info[_added](info[, delimiter])

    where string scalar delimiter sets the character(s) delimiting the descriptions;
    the default is to assume a space-separated list, i.e. delimiter = " ". To avoid
    breaking a description that contains the a delimiting character, enclose the
    description in double quotes. S.info() affects all colors defined in S; use
    S.colors_added() to affect only the colors that have been added last.

    To import descriptions from a string vector Info (each element containing a
    single color description), type

        S.Info[_added](Info)

    Note that redefining the colors, e.g. by applying S.colors(colors) or S.set(),
    will delete existing color descriptions.

    Example (colors from http://getbootstrap.com/docs/3.3/):

        . mata: S = ColrSpace()
        . mata: S.colors("#337ab7 #5cb85c #5bc0de #f0ad4e #d9534f")
        . mata: S.info("primary success info warning danger")
        . mata: S.pname("Bootstrap 3.3 colors")
        . colorpalette mata(S)

        +--------------------+
    ----+ Description output +-------------------------------------------------------

    To export color descriptions into a string scalar containing a space-separated
    list of the descriptions, type

        info = S.info[_added]([rgbforce])

    where rgbforce!=0 changes the type of descriptions that are exported. By default,
    S.info() exports whatever descriptions have been defined. That is, empty string
    will be exported for colors that have no description. However, if rgbforce!=0 is
    specified, descriptions are automatically generated for colors that have no
    description but have been defined in terms of their Stata color names or CMYK
    values. Specifying rgbforce!=0 primarily makes sense in connection with
    specifying rgbforce!=0 when calling S.colors(). S.info() exports descriptions
    from all colors; use S.info_added() to export descriptions only from the colors
    that have been added last.

    Alternatively, to export the color descriptions into a string column vector (each
    row containing a single description) type

        Info = S.Info[_added]([rgbforce])

    Example:

        . mata: S = ColrSpace()
        . mata: S.colors("navy*.5 orange%80 maroon*.7%60 SeaShell Crimson")
        . mata: S.colors()
        . mata: S.info()
        . mata: S.colors(1)
        . mata: S.info(1)


Import/export colors in various spaces

        +---------------+
    ----+ Import colors +------------------------------------------------------------

    As an alternative to S.colors(), colors can be imported into S using the
    following functions:

        S.set(C[, space])
        S.add(C[, space])
        S.reset[_added](C[, space, p])

    S.set() replaces preexisting colors by the new colors; use S.add() if you want to
    append the new colors to the existing colors. S.reset() can be used to reset the
    values of colors, without reinitializing opacity and intensity adjustment;
    S.reset_added() is like S.reset() but only operates on the colors that have been
    added last. The arguments are as follows.

    C provides the color values. In case of space = "HEX", C is a string vector of
        length n containing n hex RGB values; in case of space = "CMYK", "CMYK1",
        "RGBA", or "RGBA1", C is a n x 4 real matrix; in case of space =
        "CAM02 mask", C is a n x strlen(mask) real matrix; in all other cases, C is a
        n x 3 real matrix of n color values in the respective space. In case of
        S.reset() the number of colors in C must match the length of p.

    space is a string scalar specifying the color space of C. It can be "HEX", "RGB",
        "RGB1", "lRGB", "HSV", "HSL", "CMYK", "CMYK1", "XYZ", "XYZ1", "xyY", "xyY1",
        "Lab", "LCh", "Luv", "HCL", "CAM02 [mask]", "JMh [coefs]", "Jab [coefs]",
        "RGBA", or "RGBA1" (lowercase spelling allowed). The default is "RGB". This
        default can also be selected by typing "".

    p is a real vector of the positions of the colors to be modified.  Positive
        numbers refer to colors from the start; negative numbers refer to colors from
        the end. S.reset() aborts with error if p addresses positions that do not
        exists. If p is omitted, the default is to modify all colors. This default
        can also be selected by typing . (missing).

    Example:

        . mata: S = ColrSpace()
        . mata: S.set((100,150,200) \ (200,50,50), "RGB")
        . mata: S.add((100,50,50) \ (200,50,50) \ (300,50,50), "HCL")
        . colorpalette mata(S)
        . mata: S.reset((100,50,50) \ (100,-20,10), "Luv", (2,-1))
        . colorpalette mata(S)
        . mata: S.set((100,150,200,.8) \ (200,50,50,.7) \ (100,200,50,1), "RGBA")
        . colorpalette mata(S)

        +---------------+
    ----+ Export colors +------------------------------------------------------------

    To retrieve the colors from S and return them in a particular color space, type

        C = S.get[_added]([space])

    where space is a string scalar specifying the color space. It can be "HEX",
    "RGB", "RGB1", "lRGB", "HSV", "HSL", "CMYK", "CMYK1", "XYZ", "XYZ1", "xyY",
    "xyY1", "Lab", "LCh", "Luv", "HCL", "CAM02 [mask]", "JMh [coefs]", "Jab [coefs]",
    "RGBA", or "RGBA1" (lowercase spelling allowed). The default is "RGB". This
    default can also be selected by typing "". S.get() returns all colors;
    S.get_added() only returns the colors that have been added last.

    Example:

        . mata: S = ColrSpace()
        . mata: S.palette("s2",5)
        . mata: S.Colors()
        . mata: S.get()
        . mata: S.get("RGB1")
        . mata: S.get("lRGB")
        . mata: S.get("XYZ")
        . mata: S.get("Lab")
        . mata: S.get("Jab")
        . mata: S.get("Jab LCD")
        . mata: S.get("CAM02 QsH")
        . mata: S.opacity((100,90,80,70,60))
        . mata: S.get("RGBa")

        +--------------------------------+
    ----+ Convert colors without storing +-------------------------------------------

    Instead of storing colors in S using S.set() and then retrieving the colors in a
    particular space using function S.get(), colors can also be converted directly
    from from one space to another using the S.convert() function. S.convert() will
    not store any colors or otherwise manipulate the content of S. The syntax is:

        C = S.convert(C0, from, to)

    where C0 is a matrix of input colors values in color space from, and to is a
    destination color space. from and to can be "HEX", "RGB", "RGB1", "lRGB", "HSV",
    "HSL", "CMYK", "CMYK1", "XYZ", "XYZ1", "xyY", "xyY1", "Lab", "LCh", "Luv", "HCL",
    "CAM02 [mask]", "JMh [coefs]", or "Jab [coefs]" (lowercase spelling allowed). The
    default is "RGB". This default can also be selected by typing "". If from is
    "HEX", C0 is a string vector containing n hex colors. In all other cases, C0 is a
    n x c real matrix of n color values in the respective coding scheme. See the
    diagram in Color spaces for the paths along which the colors will be translated.

    Example:

        . mata: S = ColrSpace()
        . mata: RGB = (25, 70, 120) \ (150, 60, 60)
        . mata: S.convert(RGB, "RGB", "xyY")
        . mata: S.convert(RGB, "RGB", "JMh")
        . mata: Jab = S.convert(RGB, "RGB", "Jab")
        . mata: S.convert(Jab, "Jab", "HSV")
        . mata: HCL = S.convert(Jab, "Jab", "HCL")
        . mata: S.convert(HCL, "HCL", "RGB")


    S.convert() can also be used for grayscale conversion or color vision deficiency
    simulation (see below). The syntax is

        C = S.convert(C0, from, "gray"[, proportion, method])

        C = S.convert(C0, from, "cvd"[, severity, type])

    where proportion and method are as described in Grayscale conversion and severity
    and type are as described in Color vision deficiency simulation. The adjusted
    colors will be returned in the same color space or coding scheme as the input
    colors.


Set/retrieve opacity and intensity

        +-------------+
    ----+ Set opacity +--------------------------------------------------------------

    To set the opacity of the colors in S, type

        S.[add_]opacity[_added](opacity[, noreplace])

    S.opacity() sets opacify for all existing colors; use S.opacity_added() if you
    only want to set opacify for the colors that have been added last. Furthermore,
    use S.add_opacity() or S.add_opacity_added() to leave the existing colors
    unchanged and append a copy of the colors with the new opacity settings.
    Arguments are as follows.

    opacity is a real vector of opacity values in [0,100]. A value of 0 makes the
        color fully transparent, a value of 100 makes the color fully opaque. If the
        number of specified opacity values is smaller than the number of existing
        colors, the opacity values will be recycled; if the number of opacity values
        is larger than the number of colors, the colors will be recycled. To skip
        assigning opacity to a particular color, you may set the corresponding
        element in opacity to . (missing).

    noreplace!=0 specifies that existing opacity values should not be replaced. By
        default, S.opacity() resets opacity for all colors irrespective of whether
        they already have an opacity value or not.

        +--------------------+
    ----+ Retrieving opacity +-------------------------------------------------------

    To retrieve a real colvector containing the opacity values of the colors in S,
    type

        opacity = S.opacity[_added]()

    opacity will be equal to . (missing) for colors that do not have an opacity
    value. S.opacity() returns the opacity values of all colors; S.opacity_added()
    only returns the opacity values of the colors that have been added last.

        +-------------------+
    ----+ Setting intensity +--------------------------------------------------------

    To set the intensity adjustment multipliers of the colors in S, type

        S.[add_]intensity[_added](intensity[, noreplace])

    S.intensity() sets the intensity multipliers for all existing colors; use
    S.intensity_added() if you only want to set intensity for the colors that have
    been added last. Furthermore, use S.add_intensity() and S.add_intensity_added()
    to leave the existing colors unchanged and append a copy of the colors with the
    new intensity settings. Arguments are as follows.

    intensity is a real vector of intensity adjustment multipliers in [0,255]. A
        multiplier smaller than 1 makes the color lighter, a multiplier larger than
        one make the color darker. If the number of specified intensity multipliers
        is smaller than the number of existing colors, the intensity multipliers will
        be recycled; if the number of intensity multipliers is larger than the number
        of colors, the colors will be recycled. To skip assigning an intensity
        multiplier to a particular color, you may set the corresponding element in
        intensity to . (missing).

    noreplace!=0 specifies that existing intensity adjustment multipliers should not
        be replaced. By default, S.intensity() resets the intensity multipliers for
        all colors irrespective of whether they already have an intensity multipliers
        or not.

    Note that S.intensity() does not manipulate the stored coordinates of a color, it
    just adds an extra piece of information. This extra information, the intensity
    multiplier, is added to a color specification when exporting the colors using
    S.colors(). If you want to actually transform the stored color values instead of
    just recording an intensity multiplier, you can use function S.intensify().

        +----------------------+
    ----+ Retrieving intensity +-----------------------------------------------------

    To retrieve a real colvector containing the intensity adjustment multipliers of
    the colors in S, type

        intensity = S.intensity[_added]()

    intensity will be equal to . (missing) for colors that do not have an intensity
    multiplier. S.intensity() returns the intensity multipliers of all colors;
    S.intensity_added() only returns the intensity multipliers of the colors that
    have been added last.

        +----------+
    ----+ Examples +-----------------------------------------------------------------

        . mata: S = ColrSpace()
        . mata: S.palette("s2", 4)
        . mata: S.opacity((., 80, ., 60))
        . mata: S.intensity((.7, ., .8, .))
        . mata: S.Colors()

        . mata: S = ColrSpace()
        . mata: S.colors("cranberry")
        . mata: S.intensity(range(1,.1,.10))
        . colorpalette mata(S)


Interpolate, mix, recycle, select, order

        +---------------+
    ----+ Interpolation +------------------------------------------------------------

    To apply linear interpolation to the colors in S, type:

        S.[add_]ipolate[_added](n[, space, range, power, positions, padded])

    Opacity values and intensity adjustment multipliers, if existing, will also be
    interpolated.  S.ipolate() takes all existing colors as input and replaces them
    with the interpolated colors; use S.ipolate_added() if you only want to
    interpolate the colors added last. Furthermore, use S.add_ipolate() or
    S.add_ipolate_added() to leave the existing colors unchanged and append the
    interpolated colors. Arguments are as follows.

    n is a real scalar specifying the number of destination colors. S.ipolate() will
        interpolate the existing (origin) colors to n new colors (thus increasing or
        decreasing the number of colors, depending on whether n is larger or smaller
        than the number of origin colors).

    space selects the color space in which the colors are interpolated. space can be
        "RGB", "lRGB", "HSV", "HSL", "CMYK", "XYZ", "xyY", "Lab", "LCh", "Luv",
        "HCL", "CAM02 [mask]", "JMh [coefs]", or "Jab [coefs]" (lowercase spelling
        allowed). The default is "Jab. This default can also be selected by typing
        "". When interpolating from one hue to the next (relevant for "HSV", "HSL",
        "LCh", "HCL", "JMh, and "CAM02" when mask contains h), S.ipolate() will
        travel around the color wheel in the direction in which the two hues are
        closer to each other.

    range = (lb[, ub]) specifies range of the destination colors. The default is
        (0,1). This default can also be selected by typing . (missing). If lb is
        larger than ub, the destination colors will be arranged in reverse order.
        Extrapolation will be applied if the specified range exceeds [0,1].

    power is a real scalar affecting the distribution of the destination colors
        across range. The default is to distribute them evenly. This default can also
        be selected by typing . (missing) or setting power to 1. A power value larger
        than 1 squishes the positions towards lb. If interpolating between two
        colors, this means that the first color will dominate most of the
        interpolation range (slow to fast transition). A value between 0 and 1
        squishes the positions towards ub, thus making the second color the dominant
        color for most of the range (fast to slow transition). Another way to think
        of the effect of power is that it moves the center of the color gradient up
        (if power is larger than 1) or down (if power is between 0 and 1).

    positions is a real vector specifying the positions of the origin colors. The
        default is to place them on a regular grid from 0 and 1. This default can
        also be selected by typing . (missing). If positions has less elements than
        there are colors, default positions are used for the remaining colors. If the
        same position is specified for multiple colors, these colors will be averaged
        before applying interpolation.

    padded!=0 requests padded interpolation. By default, if padded is omitted or
        equal to 0, the first color and the last color are taken as the end points of
        the interpolation range; these colors thus remain unchanged (as long as
        default settings are used for range and position). If padded!=0, the
        positions of the colors are interpreted as interval midpoints, such that the
        interpolation range is padded by half an interval on each side. This causes
        the destination colors to be spread out slightly more (less) than the origin
        colors, if the number of destination colors is larger (smaller) than the
        number of origin colors.

    Examples:

        . mata: Jab = ColrSpace()
        . mata: Jab.colors("#337ab7 #f0ad4e")
        . mata: JMh = J(1, 1, Jab)             (make copy)
        . mata: Jab.ipolate(30)
        . mata: JMh.ipolate(30, "JMh")
        . colorpalette: mata(Jab) / mata(JMh)

        . mata: A = ColrSpace()
        . mata: A.colors("#fafa6e #2A4858")
        . mata: B = C = D = J(1, 1, A)         (make copies)
        . mata: A.ipolate(30, "HCL")
        . mata: B.ipolate(30, "HCL", (.1,.9))  (select range)
        . mata: C.ipolate(30, "HCL", ., 1.5)   (make 1st color dominant)
        . mata: D.ipolate(30, "HCL", ., .6)    (make 2nd color dominant)
        . colorpalette: mata(A) / mata(B) / mata(C) / mata(D)

        . mata: A = ColrSpace()
        . mata: A.colors("black red yellow")
        . mata: B = C = J(1, 1, A)
        . mata: A.ipolate(30)                       (red in middle)
        . mata: B.ipolate(30, "", ., ., (0, .3, 1)) (shift left)
        . mata: C.ipolate(30, "", ., ., (0, .7, 1)) (shift right)
        . colorpalette: mata(A) / mata(B) / mata(C)

    For convenience, ColrSpace also provides an interpolation function that does not
    involve translation between colorspaces and does not store any colors in S. This
    direct interpolation function is

        C = S.colipolate(C0, n[, range, power, positions, padded])

    where C0 is an n0 x c matrix of n0 origin colors that are interpolated to n
    destination colors.

        +--------+
    ----+ Mixing +-------------------------------------------------------------------

    To mix (i.e. average) the colors in S, type:

        S.[add_]mix[_added]([space, w])

    Opacity values and intensity adjustment multipliers, if defined, will also be
    mixed (i.e. averaged). S.mix() takes all existing colors as input and replaces
    them with the mixed color; use S.mix_added() if you only want to mix the colors
    added last. Furthermore, use S.add_mix() or S.add_mix_added() to leave the
    existing colors unchanged and append the mixed color. Arguments are as follows.

    space selects the color space in which the colors are mixed. space can be "RGB",
        "lRGB", "HSV", "HSL", "CMYK", "XYZ", "xyY", "Lab", "LCh", "Luv", "HCL",
        "CAM02 [mask]", "JMh [coefs]", or "Jab [coefs]" (lowercase spelling allowed).
        The default is "Jab". This default can also be selected by typing "". When
        mixing hues (relevant for "HSV", "HSL", "LCh", "HCL", "JMh, and "CAM02" when
        mask contains h), S.mix() will compute the mean of angles as described at
        Wikipedia (2018e) (using weighted sums of the cartesian coordinates if
        weights are specified); this is slightly different from the procedure
        employed by S.ipolate().

    w is a real vector containing weights. Color mixing works by transforming the
        colors to the selected color space, taking the means of the attributes across
        colors, and then transforming the resulting "average" color back to the
        original space. w specifies the weights given to the individual colors when
        computing the means. If w contains less elements than there are colors, the
        weights will be recycled. Omit w, or specify w as 1 or as . (missing) to use
        unweighted means.

    Example:

        . mata: S = ColrSpace()
        . mata: S.colors("black red yellow")
        . mata: S.get()
        . mata: S.mix("lRGB")
        . mata: S.get()
        . mata: S.colors("black red yellow")
        . mata: S.mix("lRGB", (.5, 1, 1))
        . mata: S.get()

        +-----------+
    ----+ Recycling +----------------------------------------------------------------

    To recycle the colors in S, type

        S.[add_]recycle[_added](n)

    where n is a real scalar specifying the number of desired colors.  S.recycle()
    will create n colors by recycling the colors until the desired number of colors
    is reached. If n is smaller than the number of existing colors, S.recycle() will
    select the first n colors. S.recycle() operates on all existing colors; use
    S.recycle_added() if you only want to recycle the colors added last. Furthermore,
    use S.add_recycle() or S.add_recycle_added() to leave the existing colors
    unchanged and append the recycled colors.

    Example:

        . mata: S = ColrSpace()
        . mata: S.colors("black red yellow")
        . mata: S.recycle(7)
        . mata: S.colors()
        . mata: S.recycle(2)
        . mata: S.colors()

    For convenience, ColrSpace also provides a recycling function that does not store
    any colors in S. This direct recycling function is

        C = S.colrecycle(C0, n)

    where C0 is an n0 x c matrix of n0 input colors values that are recycled to n
    output colors.

        +------------------------+
    ----+ Selecting and ordering +---------------------------------------------------

    To select (and order) colors in S, type

        S.[add_]select[_added](p)

    where p is a real vector of the positions of the colors to be selected
    (permutation vector). Positive numbers refer to colors from the start; negative
    numbers refer to colors from the end. Colors not covered in p will be dropped and
    the selected colors will be ordered as specified in p. S.select() operates on all
    existing colors; use S.select_added() if you only want to manipulate the colors
    added last. Furthermore, use S.add_select() or S.add_select_added() to leave the
    existing colors unchanged and append the selected colors.

    To order the colors in S, type

        S.[add_]order[_added](p)

    where p is a real vector specifying the desired order of the colors (permutation
    vector). Positive numbers refer to colors from the start; negative numbers refer
    to colors from the end. Colors not covered in p will be placed last, in their
    original order. S.order() operates on all existing colors; use S.order_added() if
    you only want to manipulate the colors added last. Furthermore, use S.add_order()
    or S.add_order_added() to leave the existing colors unchanged and append the
    reordered colors.

    To reverse the colors in S, type:

        S.[add_]reverse[_added]()

    S.reverse() operates on all existing colors; use S.reverse_added() if you only
    want to manipulate the colors added last. Furthermore, use S.add_reverse() or
    S.add_reverse_added() to leave the existing colors unchanged and append the
    reversed colors.

    S.reverse() is equivalent to S.order(S.N()::1) or S.select(S.N()::1).

    Examples:

        . mata: S = ColrSpace()
        . mata: S.colors("black red yellow blue green")
        . mata: S.select((4,3,4))
        . mata: S.colors()

        . mata: S = ColrSpace()
        . mata: S.colors("black red yellow blue green")
        . mata: S.order((4,3,4))
        . mata: S.colors()

        . mata: S = ColrSpace()
        . mata: S.colors("black red yellow blue green")
        . mata: S.reverse()
        . mata: S.colors()


Intensify, saturate, luminate

        +-----------+
    ----+ Intensify +----------------------------------------------------------------

    To adjust the intensity of the colors in S, type

        S.[add_]intensify[_added](m)

    where m is a real vector of intensity adjustment multipliers in [0,255]. A
    multiplier smaller than 1 makes the color lighter, a multiplier larger than one
    make the color darker. If the number of specified multipliers is smaller than the
    number of colors, the multipliers will be recycled; if the number of multipliers
    is larger than the number of colors, the colors will be recycled. To skip
    adjusting the intensity of a particular color, you may set the corresponding
    multiplier to . (missing). S.intensify() operates on all existing colors; use
    S.intensify_added() if you only want to manipulate the colors added last.
    Furthermore, use S.add_intensify() or S.add_intensify_added() to leave the
    existing colors unchanged and append the manipulated colors.

    ColrSpace uses the same algorithm as is used in official Stata to adjust the
    color intensity. Applying S.intensify() thus results in colors that look the same
    as colors that have been specified using intensity multiplier syntax (see help
    colorstyle). The algorithm works by increasing or decreasing the RGB values
    proportionally, with rounding to the nearest integer and adjustment to keep all
    values within [0,255].

    Example:

        . mata: S = ColrSpace()
        . mata: S.colors("navy maroon forest_green")
        . mata: S.select((1,1,2,2,3,3))     (duplicate colors)
        . mata: S.intensify((., .5))
        . colorpalette mata(S), rows(2)

        +----------+
    ----+ Saturate +-----------------------------------------------------------------

    To change the saturation (colorfulness) of the colors in S, type:

        S.[add_]saturate[_added](d[, method, level])

    S.saturate() operates on all existing colors; use S.saturate_added() if you only
    want to manipulate the colors added last. Furthermore, use S.add_saturate() or
    S.add_saturate_added() to leave the existing colors unchanged and append the
    manipulated colors. Arguments are as follows.

    d is a real vector of saturation adjustments addends. Positive values increase
        saturation, negative values decrease saturation. If the number of specified
        addends is smaller than the number of colors, the addends will be recycled;
        if the number of addends is larger than the number of colors, the colors will
        be recycled. Typically, reasonable addends are in a range of about +/- 50.

    method selects the color space in which the colors are manipulated. It can be
        "LCh", "HCL", "JCh" (CIECAM02 JCh), or "JMh" (lowercase spelling allowed).
        The default is "LCh". This default can also be selected by typing "".
        S.saturate() works by converting the colors to the selected color space,
        adding d to the C channel (or M' in case of J'M'h), and then converting the
        colors back (after resetting negative chroma values to zero).

    level!=0 specifies that d provides chroma levels, not addends. In this case, the
        C channel will be set to d. Reasonable values typically lie in a range of
        0-100, although higher values are possible. Negative values will be reset to
        0.

    Example:

        . mata: A = ColrSpace()
        . mata: A.palette("RdYlGn")
        . mata: B = J(1, 1, A)           (make copy of A)
        . mata: B.saturate(25)
        . colorpalette: mata(A) / mata(B)

    S.saturate() has been inspired by the saturate() and desaturate() functions in
    Gregor Aisch's chroma.js.

        +----------+
    ----+ Luminate +-----------------------------------------------------------------

    To change the luminance of the colors in S, type

        S.[add_]luminate[_added](d[, method, level])

    S.luminate() operates on all existing colors; use S.luminate_added() if you only
    want to manipulate the colors added last. Furthermore, use S.add_luminate() or
    S.add_luminate_added() to leave the existing colors unchanged and append the
    manipulated colors. Arguments are as follows.

    d is a real vector of luminance adjustments addends. Positive values increase
        luminance, negative values decrease luminance. If the number of specified
        addends is smaller than the number of colors, the addends will be recycled;
        if the number of addends is larger than the number of colors, the colors will
        be recycled. Typically, reasonable addends are in a range of about +/- 50.

    method selects the color space in which the colors are manipulated. It can be
        "Lab", "LCh", "Luv", "HCL", "JCh" (CIECAM02 JCh), "JMh" or "Jab" (lowercase
        spelling allowed). The default is "JMh". This default can also be selected by
        typing "". S.luminate() works by converting the colors to the selected color
        space, adding d to the L channel (or J in case of CIECAM02 JCh, J' in case of
        J'M'h or J'a'b'), and then converting the colors back (after resetting
        negative luminance values to zero). Results will be identical between "Lab"
        and "LCh", between "Luv" as "HCL", and between "JMh" and "Jab".

    level!=0 specifies that d provides luminance levels, not addends. In this case,
        the L channel will be set to d. Reasonable values typically lie in a range of
        0-100. Negative values will be reset to 0.

    Example:

        . mata: A = ColrSpace()
        . mata: A.palette("ptol", 10)
        . mata: B = J(1, 1, A)           (make copy of A)
        . mata: B.luminate(20)
        . colorpalette, lc(black): mata(A) / mata(B)

    S.luminate() has been inspired by the darken() and brighten() functions in Gregor
    Aisch's chroma.js.


Grayscale conversion

    To convert the colors in S to gray, type

        S.[add_]gray[_added]([proportion, method])

    S.gray() transforms all existing colors; use S.gray_added() if you only want to
    transform the colors added last. Furthermore, use S.add_gray() or
    S.add_gray_added() to leave the existing colors unchanged and append the
    transformed colors. Arguments are as follows.

    proportion in [0,1] specifies the proportion of gray. The default is 1 (complete
        conversion to gray). This default can also be selected by typing . (missing).

    method specifies the color space in which the colors are manipulated. It can be
        "LCh", "HCL", "JCh" (CIECAM02 JCh), or "JMh" (lowercase spelling allowed).
        The default is "LCh". This default can also be selected by typing "".
        Grayscale cconversion works by converting the colors the selected color
        space, reducing the C channel (or M' in case of J'M'h) towards zero, and then
        converting the colors back.

    Example:

        . mata: A = ColrSpace()
        . mata: A.palette("s1")
        . mata: B = C = J(1, 1, A)      (make copies)
        . mata: B.gray(.7)
        . mata: C.gray()
        . colorpalette, lc(black): mata(A) / mata(B) / mata(C)

    Grayscale conversion is also supported by S.convert(); see Convert colors without
    storing.


Color vision deficiency simulation

    To convert the colors in S such that they look how they would appear to people
    suffering from color vision deficiency (color blindness), type

        S.[add_]cvd[_added]([severity, type])

    S.cvd() transforms all existing colors; use S.cvd_added() if you only want to
    transform the colors added last. Furthermore, use S.add_cvd() or
    S.add_cvd_added() to leave the existing colors unchanged and append the
    transformed colors. Arguments are as follows.

    severity in [0,1] specifies the severity of the deficiency. The default is 1
        (maximum severity, i.e. deuteranopia, protanopia, or tritanopia,
        respectively). This default can also be selected by typing . (missing).

    type specifies the type of color vision deficiency. It can be "deuteranomaly",
        "protanomaly", or "tritanomaly" (abbreviations allowed). The default is
        "deuteranomaly". This default can also be selected by typing "". See
        Wikipedia (2019a) for basic information on the different types of color
        blindness.

    ColrSpace implements color vision deficiency simulation based on Machado et al.
    (2009), using the transformation matrices provided at www.inf.ufrgs.br/~oliveira
    (employing linear interpolation between matrices for intermediate severity
    values). The transformations matrix for a specific combination of severity and
    type can be retrieved as follows:

        M = S.cvd_M([severity, type])

    Example:

        . mata: A = ColrSpace()
        . mata: A.palette("s2", 5)
        . mata: d = D = p = P = T = J(1, 1, A)  (make copies)
        . mata: d.cvd(.5);      d.pname("deuteranomaly")
        . mata: D.cvd();        D.pname("deuteranopia")
        . mata: p.cvd(.5, "p"); p.pname("protanomaly")
        . mata: P.cvd(1, "p");  P.pname("protanopia")
        . mata: T.cvd(1, "t");  T.pname("tritanopia")
        . colorpalette, lc(black): m(A) / m(d) / m(D) / m(p) / m(P) / m(T)

    Color vision deficiency simulation is also supported by S.convert(); see Convert
    colors without storing.


Color palettes

        +-------------------+
    ----+ Standard palettes +--------------------------------------------------------

    To import colors from a named color palette, type:

        C = S.[add_]palette(["name", n, noexpand])

    S.palette() replaces existing colors by the new colors; use S.add_palette() if
    you want to append the new colors. Arguments are as follows.

    name selects the palette and can be one of the following (also see help 
        colorpalette, if installed, for more information on these palettes):

            s1                       15 qualitative colors as in Stata's s1color
                                       scheme
            s1r                      15 qualitative colors as in Stata's s1rcolor
                                       scheme
            s2                       15 qualitative colors as in Stata's s2color
                                       scheme
            economist                15 qualitative colors as in Stata's economist
                                       scheme
            mono                     15 gray scales (qualitative) as in Stata's
                                       monochrome schemes
            cblind                   9 colorblind-friendly colors (qualitative) by
                                       Okabe and Ito (2002)
            plottig                  15 qualitative colors as in plottig by Bischof
                                       (2017b)
            538                      13 qualitative colors as in 538 by Bischof
                                       (2017a)
            tfl                      7 qualitative colors as in mrc by Morris (2013)
            mrc                      8 qualitative colors as in tfl by Morris (2015)
            burd                     13 qualitative colors as in burd by Briatte
                                       (2013)
            lean                     15 gray scales (qualitative) as in lean by Juul
                                       (2003)
            d3 10                    10 qualitative colors from D3.js
            d3 20                    20 qualitative colors in pairs from D3.js
            d3 20b                   20 qualitative colors in groups of four from
                                       D3.js
            d3 20c                   20 qualitative colors in groups of four from
                                       D3.js
            Accent                   8 accented colors (qualitative) from ColorBrewer
            Dark2                    8 dark colors (qualitative) from ColorBrewer
            Paired                   12 paired colors (qualitative) from ColorBrewer
            Pastel1                  9 pastel colors (qualitative) from ColorBrewer
            Pastel2                  8 pastel colors (qualitative) from ColorBrewer
            Set1                     9 qualitative colors from ColorBrewer
            Set2                     8 qualitative colors from ColorBrewer
            Set3                     12 qualitative colors from ColorBrewer
            Blues                    3-9 sequential colors from ColorBrewer
            BuGn                     3-9 sequential colors from ColorBrewer
            BuPu                     3-9 sequential colors from ColorBrewer
            GnBu                     3-9 sequential colors from ColorBrewer
            Greens                   3-9 sequential colors from ColorBrewer
            Greys                    3-9 sequential colors from ColorBrewer
            OrRd                     3-9 sequential colors from ColorBrewer
            Oranges                  3-9 sequential colors from ColorBrewer
            PuBu                     3-9 sequential colors from ColorBrewer
            PuBuGn                   3-9 sequential colors from ColorBrewer
            PuRd                     3-9 sequential colors from ColorBrewer
            Purples                  3-9 sequential colors from ColorBrewer
            RdPu                     3-9 sequential colors from ColorBrewer
            Reds                     3-9 sequential colors from ColorBrewer
            YlGn                     3-9 sequential colors from ColorBrewer
            YlGnBu                   3-9 sequential colors from ColorBrewer
            YlOrBr                   3-9 sequential colors from ColorBrewer
            YlOrRd                   3-9 sequential colors from ColorBrewer
            BrBG                     3-11 diverging colors from ColorBrewer
            PRGn                     3-11 diverging colors from ColorBrewer
            PiYG                     3-11 diverging colors from ColorBrewer
            PuOr                     3-11 diverging colors from ColorBrewer
            RdBu                     3-11 diverging colors from ColorBrewer
            RdGy                     3-11 diverging colors from ColorBrewer
            RdYlBu                   3-11 diverging colors from ColorBrewer
            RdYlGn                   3-11 diverging colors from ColorBrewer
            Spectral                 3-11 diverging colors from ColorBrewer
            ptol qualitative         1-12 qualitative colors by Tol (2012)
            ptol diverging           3-11 diverging colors by Tol (2012)
            ptol rainbow             4-12 rainbow colors by Tol (2012) (sequential)
            tableau                  20 qualitative colors by Lin et al. (2013)
            lin carcolor             6 car colors by Lin et al. (2013)
            lin carcolor algorithm   6 algorithm-selected car colors by Lin et al.
                                       (2013)
            lin food                 7 food colors by Lin et al. (2013)
            lin food algorithm       7 algorithm-selected food colors by Lin et al.
                                       (2013)
            lin features             5 feature colors by Lin et al. (2013)
            lin features algorithm   5 algorithm-selected feature colors by Lin et
                                       al. (2013)
            lin activities           5 activity colors by Lin et al. (2013)
            lin activities algorithm 5 algorithm-selected activity colors by Lin et
                                       al. (2013)
            lin fruits               7 fruit colors by Lin et al. (2013)
            lin fruits algorithm     7 algorithm-selected fruit colors by Lin et al.
                                       (2013)
            lin vegetables           7 vegetable colors by Lin et al. (2013)
            lin vegetables algorithm 7 algorithm-selected vegetable colors by Lin et
                                       al. (2013)
            lin drinks               7 drinks colors by Lin et al. (2013)
            lin drinks algorithm     7 algorithm-selected drinks colors by Lin et al.
                                       (2013)
            lin brands               7 brands colors by Lin et al. (2013)
            lin brands algorithm     7 algorithm-selected brands colors by Lin et al.
                                       (2013)
            spmap blues              2-99 sequential colors by Pisati (2007)
            spmap greens             2-99 sequential colors by Pisati (2007)
            spmap greys              2-99 sequential colors by Pisati (2007)
            spmap reds               2-99 sequential colors by Pisati (2007)
            spmap rainbow            2-99 rainbow colors (sequential) by Pisati
                                       (2007)
            spmap heat               2-16 heat colors (sequential) by Pisati (2007)
            spmap terrain            2-16 terrain colors (sequential) by Pisati
                                       (2007)
            spmap topological        2-16 topological colors (sequential) by Pisati
                                       (2007)
            sfso brown               6 sequential colors by SFSO (2017)
            sfso orange              6 sequential colors by SFSO (2017)
            sfso red                 6 sequential colors by SFSO (2017)
            sfso pink                6 sequential colors by SFSO (2017)
            sfso purple              6 sequential colors by SFSO (2017)
            sfso violet              6 sequential colors by SFSO (2017)
            sfso blue                7 sequential colors by SFSO (2017)
            sfso ltblue              6 sequential colors by SFSO (2017)
            sfso turquoise           6 sequential colors by SFSO (2017)
            sfso green               6 sequential colors by SFSO (2017)
            sfso olive               6 sequential colors by SFSO (2017)
            sfso black               6 sequential colors by SFSO (2017)
            sfso parties             11 qualitative colors by SFSO (2017)
            sfso languages           5 qualitative colors by SFSO (2017)
            sfso votes               10 diverging colors by SFSO (2017)

        The palette names can be abbreviated and typed in lowercase letters (for
        example, "BuGn" could be typed as "bugn", "lin carcolor algorithm" could be
        typed as "lin car a"). If abbreviation is ambiguous, the first matching name
        in the above list will be used. Default is "s2"; this default can also be
        selected by typing "".

        ColorBrewer is a set of color schemes developed by Brewer et al. (2003); also
        see Brewer (2016). The colors are licensed under Apache License Version 2.0;
        see the copyright notes at ColorBrewer_updates.html.

    n is the number of colors to be retrieved from the palette. Many palettes, such
        as, e.g., the sequential and diverging ColorBrewer palettes, are adaptive to
        n in the sense that they return different colors depending on n. Other
        palettes, such as "s2", contain a fixed set of colors. In any case, if n is
        different from the (maximum or minimum) number of colors defined by a
        palette, the colors are either recycled (qualitative palettes) or
        interpolated (all other palettes) such that the number of retrieved colors is
        equal to n.

    noexpand!=0 omits recycling or interpolating colors if n, the number of requested
        colors, is larger (smaller) than the maximum (minimum) number of colors
        defined by a palette. That is, if noexpand!=0 is specified, the resulting
        number of colors in S may be different from the requested number of colors.
        Exception: noexpand!=0 does not suppress "recycling" of qualitative palettes
        if n is smaller than the (minimum) number of colors defined by the palette.
        In this case, the first n colors of the palette are retrieved irrespective of
        whether noexpand!=0 is specified or not.

    Example:

        . mata: S = ColrSpace()
        . mata: S.palette("lin fruits")
        . mata: S.add_palette("lin veg")
        . mata: S.pname("fruits and vegetables")
        . colorpalette mata(S)

        +----------------------+
    ----+ Matplotlib colormaps +-----------------------------------------------------

    A selection of colormaps from matplotlib, a Python 2D plotting library (Hunter
    2007), is provided by function S.matplotlib(). The syntax is:

        S.[add_]matplotlib(["name", n, range])

    S.matplotlib() replaces existing colors by the new colors; use S.add_matplotlib()
    if you want to append the new colors. Arguments are as follows.

    name selects the colormap and can be one of viridis, magma, inferno, plasma,
        cividis, twilight, twilight shifted, autumn, spring, summer, winter, bone,
        cool, copper, coolwarm, jet, or hot. The names can be abbreviated; if
        abbreviation is ambiguous, the first matching name in the above list will be
        used. For example, "twilight shifted" could be typed "t s". Default is
        "viridis"; this default can also be selected by typing "".

    n is the number of colors to be retrieved from the colormap. The default is 15.

    range = (lb[, ub]) specifies the range of the colormap to be used, with lb and ub
        within [0,1] (values smaller than 0 or larger than 1 will be interpreted as 0
        or 1, respectively). The default is (0,1). This default can also be selected
        by typing . (missing). If lb is larger then ub, the colors are retrieved in
        reverse order.

    Example:

        . mata: A = B = ColrSpace()
        . mata: A.matplotlib("viridis")
        . mata: B.matplotlib("magma", ., (.2,1))
        . colorpalette: mata(A) / mata(B)

    For convenience, ColrSpace also provides function

        RGB1 = S.matplotlib_ip(R, G, B, n[, range])

    that can be used to create linear segmented colormaps. Some of the colormaps
    above are implemented in terms of this function. R, G, and B are matrices
    specifying the anchor points of the segments (each row consist of three values:
    the anchor, the value of the color on the left of the anchor, and the value of
    the color on the right). See the corresponding tutorial page at matplotlib.org
    for details. S.matplotlib_ip() does not check the consistency of the specified
    matrices and may return invalid results if consistency is violated.


Color generators

    To generate colors in different spaces you can use the S.generate() function. The
    syntax is:

        S.[add_]generate("HUE"         [, n, H, C, L, reverse])
        S.[add_]generate("HCL [class]" [, n, H, C, L, P])
        S.[add_]generate("LCh [class]" [, n, L, C, h, P])
        S.[add_]generate("JMh [class]" [, n, J, M, h, P])
        S.[add_]generate("HSV [class]" [, n, H, S, V, P])
        S.[add_]generate("HSL [class]" [, n, H, S, L, P])

    S.generate() replaces existing colors by the new colors; use S.add_generate() if
    you want to append the new colors.

    The first argument selects the color generator. The argument can be typed in
    lowercase letters. The default is "HUE"; this default can also be selected by
    typing "". The different color generators are as follows:

        "HUE" generates HCL colors with evenly spaced hues. The algorithm has been
        modeled after function hue_pal() from R's scales package by Hadley Wickham
        (see http://github.com/hadley/scales). The default parameters are H = (15,
        375), C = 100, and L = 65.  If the difference between the two values of H is
        a multiple of 360, the second value will be reduced by 360/n (so that the
        space between the last and the first color is the same as between the other
        colors).

        "HCL [class]" generates colors in the HCL space (radial CIE L*u*v*). The
        algorithm has been modeled after R's colorspace package by Ihaka et al.
        (2016); also see Zeileis et al. (2009) and hclwizard.org. Optional class can
        be "qualitative" (the default), "sequential", or "diverging" (abbreviations
        allowed). Let h1 and h2 be two hues on the 360 degree color wheel, c1 and c2
        two chroma levels, l1 and l2 two luminance levels, p1 and p2 two power
        parameters, and i an index from 1 to n. The colors are then generated as
        follows:

            qualitative     (h1 + (h2-h1) * (i-1)/(n-1), c1, l1)
                            defaults: h1 = 15, h2 = h1+360*(n-1)/n, c1 = 100, l1 = 65

            sequential      (h2 - (h2-h1) * j, c2 - (c2-c1) * j^p1, l2 - (l2-l1) *
                              j^p2)
                              with j = (n-i)/(n-1)
                            defaults: h1 = 260, h2 = h1, c1 = 80, c2 = 10, l1 = 25,
                              l2 = 95, p1 = 1, p2 = p1

            diverging       (cond(j>0, h1, h2), c1 * abs(j)^p1, l2 - (l2-l1) *
                              abs(j)^p2)
                              with j = (n-2*i+1)/(n-1)
                            defaults: h1 = 260, h2 = 0, c1 = 80, l1 = 30, l2 = 95, p1
                              = 1, p2 = p1

        "LCh" [class]" generates colors in the LCh space (radial CIE L*a*b*). The
        algorithm has been modeled in analogy to "HCL". The default parameters are as
        follows.

            qualitative     l1 = 65, c1 = 70, h1 = 30, h2 = h1+360*(n-1)/n
            sequential      l1 = 25, l2 = 95, c1 = 72, c2 = 6, h1 = 290, h2 = h1, p1
                              = 1, p2 = p1
            diverging       l1 = 30, l2 = 95, c1 = 60, h1 = 290, h2 = 10, p1 = 1, p2
                              = p1

        "JMh [class]" generates colors in the J'M'h space. The algorithm has been
        modeled in analogy to "HCL", with J' replacing L and M' replacing C. The
        default parameters are as follows.

            qualitative     j1 = 67, m1 = 35, h1 = 25, h2 = h1+360*(n-1)/n
            sequential      j1 = 25, j2 = 96, m1 = 32, m2 = 7, h1 = 260, h2 = h1, p1
                              = 1, p2 = p1
            diverging       j1 = 30, j2 = 96, m1 = 30, h1 = 260, h2 = 8, p1 = 1, p2 =
                              p1

        "HSV [class]" generates colors in the HSV space. The algorithm has been
        modeled in analogy to "HCL", with S replacing C and V replacing L. The
        default parameters are as follows.

            qualitative     h1 = 0, h2 = h1+360*(n-1)/n, s1 = .6, v1 = .9
            sequential      h1 = 240, h2 = h1, s1 = .8, s2 = .05, v1 = .6, v2 = 1, p1
                              = 1.2, p2 = p1
            diverging       h1 = 220, h2 = 350, s1 = .8, v1 = .6, v2 = .95, p1 = 1.2,
                              p2 = p1

        "HSL [class]" generates colors in the HSL space. The algorithm has been
        modeled in analogy to "HCL", with S replacing C. The default parameters are
        as follows.

            qualitative     h1 = 0, h2 = h1+360*(n-1)/n, s1 = .7, l1 = .6
            sequential      h1 = 240, h2 = h1, s1 = .65, s2 = .65, l1 = .35, l2 =
                              .975, p1 = 1.2, p2 = p1
            diverging       h1 = 220, h2 = 350, s1 = .65, l1 = .35, l2 = .95, p1 =
                              1.2, p2 = p1

    n specifies the number of colors to be generated. The default is 15.

    H (or h) is a real vector specifying one or two hues in degrees of the color
        wheel. The default hues can be selected by typing . (missing).

    C (or M') is a real scalar specifying a single chroma (colorfulness, color
        intensity) level for "HUE" or a real vector specifying one or two chroma
        levels for "HCL", "LCh", or "JMh". The default levels can be selected by
        typing . (missing).

    L (or J') is a real scalar specifying a single luminance/lightness level for
        "HUE" or a real vector specifying one or two luminance/lightness levels for
        "HCL", "LCh", "JMh", or "HSL". The default levels can be selected by typing .
        (missing).

    S is a real vector specifying one or two saturation levels for "HSV" or "HSL".
        The default levels can be selected by typing . (missing).

    V is a real vector specifying one or two value levels for "HSV". The default
        levels can be selected by typing . (missing).

    P is a real vector specifying one or two power parameters. The default parameters
        can be selected by typing . (missing).

    reverse!=0 causes "HUE" to travel counter-clockwise around the color wheel. By
        default, "HUE" travels clockwise.

    Examples:

        . mata: S = ColrSpace()
        . mata: S.generate("HUE", 5)
        . colorpalette mata(S)

        . mata: S.generate("HCL diverging", 30)
        . colorpalette: mata(S)

        . mata: S.generate("HCL diverging", 30, (0, 150), 70, (50, 98))
        . colorpalette: mata(S)


Color differences and contrast ratios

        +-------------------+
    ----+ Color differences +--------------------------------------------------------

    To compute differences between colors in S, type

        D = S.delta[_added]([P, method, noclip])

    where P is a r x 2 matrix with each row selecting two colors to be compared. For
    example, P = (3,5) would compare the 3rd and the 5th color; P = (1,2) \ (3,5)
    would make two comparisons: 1st to 2nd and 3rd to 5th. The default, if P is
    omitted, is to make n-1 consecutive comparisons, where n is the number of
    existing colors: 1st to 2nd, 2nd to 3rd, ..., (n-1)th to nth; this is equivalent
    to P = ((1::S.N()-1),(2::S.N())). This default can also be selected by typing .
    (missing). S.delta() operates on all existing colors, that is, P selects among
    all colors; in S.delta_added() P only selects among the colors added last.
    Further options are as follows.

    method selects the method used to compute the color differences. It can be "E76"
        for the 1976 CIELAB Delta E definition (equal to the euclidean distance in
        "Lab"), any of "RGB", "RGB1", "lRGB", "XYZ", "XYZ1", "xyY1", "Lab", "LCh",
        "Luv", "HCL", "JCh", or "JMh [coefs]" to compute the differences as euclidean
        distances in the respective color space (lowercase spelling allowed; "JCh"
        selecting J, C, and h of CIECAM02), or "Jab [coefs]" to compute the
        differences as described by Luo and Li (2013, chapter 2.6.1). The default is
        "Jab". This default can also be selected by typing "". Formally, a color
        difference can be written as

            d = sqrt( (x1 - x2)^2 + (y1 - y2)^2 + (z1 - z2)^2 )

        where x#, y#, and z# are the coordinates of the two colors in a particular
        space. For "E76", y = L*, x = a*, z = b* from the CIE L*a*b* color space; for
        "Jab", y = J'/K_L, x = a', z = b' from the CIECAM J'a'b' space, where K_L is
        a transformation coefficient set by coefs. For background information on
        color difference also see Wikipedia (2019b).

    noclip!=0 prevents converting the colors to valid RGB values before computing the
        differences. By default, S.delta() translates the colors to linear RGB and
        clips the coordinates at 0 and 1, before converting the colors to the color
        space selected by method, so that the computed differences are consistent
        with how the colors are perceived on an RGB device. Specify noclip!=0 to skip
        this extra step.

    Opacity settings and intensity adjustment multipliers are ignored when computing
    the color differences.

    Example:

        . mata: S = ColrSpace()
        . mata: S.colors("#337ab7 #f0ad4e")
        . mata: S.ipolate(6, "", (0, .5))
        . mata: S.delta((J(5,1,1), (2::6)))     (compare 1st to other colors)

          (illustrate using a graph ...)
        . mata: D = S.delta((J(5,1,1), (2::6)))
        . mata: D = `"""' :+ "{&Delta}E' = " :+ strofreal(D,"%9.3g") :+ `"""'
        . mata: D = strofreal(1::5) :+ " 3 " :+  D
        . mata: st_local("D", invtokens(D'))
        . colorpalette mata(S), order(1 1 1 1 1) gropts(text(`D'))

        +-----------------+
    ----+ Contrast ratios +----------------------------------------------------------

    To compute contrast ratios between colors in S, type

        R = S.contrast[_added]([P])

    where P is a r x 2 matrix with each row selecting two colors to be compared. For
    example, P = (3,5) would compare the 3rd and the 5th color; P = (1,2) \ (3,5)
    would make two comparisons: 1st to 2nd and 3rd to 5th. The default, if P is
    omitted, is to make n-1 consecutive comparisons, where n is the number of
    existing colors: 1st to 2nd, 2nd to 3rd, ..., (n-1)th to nth; this is equivalent
    to P = ((1::S.N()-1),(2::S.N())). This default can also be selected by typing .
    (missing). S.contrast() operates on all existing colors, that is, P selects among
    all colors; in S.contrast_added() P only selects among the colors added last.

    The contrast ratios are computed according to the Web Content Accessibility
    Guidelines (WCAG) 2.0 at www.w3.org. Let Y0 be the Y attribute of the lighter
    color, and Y1 be the Y attribute of the darker color, in CIE XYZ space (in
    Y_white = 100 scaling). The contrast ratio is then defined as (Y0 + 5) / (Y1 +
    5).  Typically, a contrast ratio of at least 4.5 is recommended between
    foreground text and background fill.

    Opacity settings and intensity adjustment multipliers are ignored when computing
    the contrast ratios.

    Example: Say, you want to print text inside bars and want the text and the bar
    fill to have the same basic color. One idea is to use colors with reduced
    intensity for the fill and print the text in the original color. S.contrast() may
    be helpful for finding out by how much you need to reduce intensity so that there
    is enough contrast between text and bar fill.

        . mata: S = ColrSpace()
        . mata: S.colors("navy maroon")
        . mata: S.add_intensify(.6)
        . mata: S.contrast((1,3) \ (2,4)) (not enough contrast)
        . colorpalette mata(S)

        . mata: S.select((1,2))
        . mata: S.add_intensify((.4,.3))
        . mata: S.contrast((1,3) \ (2,4)) (contrast now ok)
        . colorpalette mata(S)


Some utilities

        +------------------+
    ----+ Number of colors +---------------------------------------------------------

    To retrieve the number of colors defined in S, type

        n = S.N[_added]()

    S.N() returns the total number of colors; S.N_added() returns the number of
    colors added last.

        +---------------+
    ----+ Palette class +------------------------------------------------------------

    To assign a palette class to the colors in S, type

        S.pclass(class)

    where class is a string scalar such as, e.g., "qualitative" or "diverging". To
    retrieve the palette class, type

        class = S.pclass()

    Functions S.palette(), S.matplotlib(), and S.generate() automatically assign a
    palette class.

        +--------------+
    ----+ Palette name +-------------------------------------------------------------

    To assign a palette name to the colors in S, type

        S.pname(name)

    where name is a string scalar. To retrieve the palette name, type

        name = S.pname()

    Functions S.palette() and S.matplotlib() automatically assign a palette name.

        +----------------------+
    ----+ Interpolation status +-----------------------------------------------------

    ColrSpace maintains a 0/1 flag of whether S.ipolate() has been applied. To
    retrieve the status of the flag, type

        flag = S.isipolate()

        +----------+
    ----+ Clipping +-----------------------------------------------------------------

    For convenience, ColrSpace provides a function that can be used for clipping. The
    syntax is

        C = S.clip(C0, a, b)

    where C0 is a real matrix of input values, a is a real scalar specifying the
    lower bound, and b is a real scalar specifying the upper bound. Values in C0
    smaller than a will be set to a; values larger than b will be set to b; values
    between a and b as well as missing values will be left as is.


Source code and certification script

    lcolrspace.mlib has been compiled in Stata 14.2. The source code can be found in
    file colrspace_source.sthlp.

    A certification script testing internal consistency and comparing results to some
    test values and results from the colorspacious Python library by Smith (2018)
    (see file gold_values.py at Github) as well as to results obtained from the color
    calculators at colorizer.org and www.brucelindbloom.com, can be found at 
    http://fmwww.bc.edu/repec/bocode/c/colrspace_cscript.do.


References

    Bischof, D. 2017a. G538SCHEMES: module to provide graphics schemes for
        http://fivethirtyeight.com. Available from 
        http://ideas.repec.org/c/boc/bocode/s458404.html.
    Bischof, D. 2017b. New graphic schemes for Stata: plotplain and plottig.  The
        Stata Journal 17(3): 748–759.
    Brewer, C.A., G.W. Hatchard, M.A. Harrower. 2003. ColorBrewer in Print: A Catalog
        of Color Schemes for Maps.  Cartography and Geographic Information Science
        30(1): 5–32.
    Brewer, C.A. 2016. Designing Better Maps. A Guide for GIS Users. 2nd ed.
        Redlands, CA: Esri Press.
    Briatte, F. 2013. SCHEME-BURD: Stata module to provide a ColorBrewer-inspired
        graphics scheme with qualitative and blue-to-red diverging colors. Available
        from http://ideas.repec.org/c/boc/bocode/s457623.html.
    Hunter, J.D. 2007. Matplotlib: A 2D graphics environment. Computing in Science &
        Engineering 9(3): 90-95.
    Ihaka, R., P. Murrell, K. Hornik, J.C. Fisher, R. Stauffer, A. Zeileis.  2016.
        colorspace: Color Space Manipulation. R package version 1.3-2.  Available
        from http://CRAN.R-project.org/package=colorspace.
    International Electrotechnical Commission (IEC). 2003. International Standard IEC
        61966-2-1:1999/AMD1:2003. Amendment 1 – Multimedia systems and equipment –
        Color measurement and management – Part 2-1: Color management – Default RGB
        color space - sRGB. Available from 
        http://www.sis.se/api/document/preview/562720/.
    Juul, S. 2003. Lean mainstream schemes for Stata 8 graphics. The Stata Journal
        3(3): 295-301.
    Lin, S., J. Fortuna, C. Kulkarni, M. Stone, J. Heer. 2013. Selecting
        Semantically-Resonant Colors for Data Visualization. Computer Graphics Forum
        32(3pt4): 401-410.
    Lindbloom, B.J. 2017a. Chromatic Adaptation. Revision 06 Apr 2017. Available from
        http://www.brucelindbloom.com/Eqn_ChromAdapt.html.
    Lindbloom, B.J. 2017b. RGB Working Space Information. Revision 06 Apr 2017.
        Available from http://www.brucelindbloom.com/WorkingSpaceInfo.html.
    Lindbloom, B.J. 2017c. RGB/XYZ Matrices. Revision 07 Apr 2017. Available from 
        http://www.brucelindbloom.com/Eqn_RGB_XYZ_Matrix.html.
    Luo, R.M., G. Cui, C. Li. 2006.  Uniform Colour Spaces Based on CIECAM02 Colour
        Appearance Model. COLOR research and application 31(4): 320–330.
    Luo, M.R., C. Li. 2013. CIECAM02 and Its Recent Developments. P. 19-58 in: C.
        Fernandez-Maloigne (ed.). Advanced Color Image Processing and Analysis. New
        York: Springer.
    Machado, G.M., M.M. Oliveira, L.A.F. Fernandes. 2009.  A Physiologically-based
        Model for Simulation of Color Vision Deficiency. IEEE Transactions on
        Visualization and Computer Graphics 15(6): 1291-1298.
    Morris, T. 2013. SCHEME-MRC: Stata module to provide graphics scheme for UK
        Medical Research Council. Available from 
        http://ideas.repec.org/c/boc/bocode/s457703.html.
    Morris, T. 2015. SCHEME-TFL: Stata module to provide graph scheme, based on
        Transport for London's corporate colour pallette. Available from 
        http://ideas.repec.org/c/boc/bocode/s458103.html.
    Novak, J. (2016). What every coder should know about gamma. 2016 Sep 21.
        Available from 
        http://blog.johnnovak.net/2016/09/21/what-every-coder-should-know-about-gamma
        > /.
    Okabe, M., K. Ito. 2002. Color Universal Design (CUD). How to make figures and
        presentations that are friendly to Colorblind people. Available from 
        http://jfly.iam.u-tokyo.ac.jp/color/.
    Pascale, D. 2003. A review of RGB color spaces ... from xyY to R'G'B'. Montreal:
        The BabelColor Company. Available from 
        http://www.babelcolor.com/index_htm_files/A%20review%20of%20RGB%20color%20spa
        > ces.pdf.
    Pisati, M. 2007. SPMAP: Stata module to visualize spatial data. Available from 
        http://ideas.repec.org/c/boc/bocode/s456812.html.
    SFSO (Swiss Federal Statistical Office). 2017. Layoutrichtlinien. Gestaltungs und
        Redaktionsrichtlinien für Publikationen, Tabellen und grafische Assets.
        Version 1.1.1. Neuchâtel: Bundesamt für Statistik.
    Smith, N.J. (2018). colorspacious 1.1.2: A powerful, accurate, and easy-to-use
        Python library for doing colorspace conversions. Available from 
        http://pypi.org/project/colorspacious (DOI 10.5281/zenodo.1214904).
    Tol, P. 2012. Colour Schemes. SRON Technical Note, Doc. no. SRON/EPS/TN/09-002.
        Available from http://personal.sron.nl/~pault/colourschemes.pdf.
    Wikipedia. 2018a. CIE 1931 color space. Revision 22 October 2018. Available from 
        http://en.wikipedia.org/wiki/CIE_1931_color_space.
    Wikipedia. 2018b. CIELAB color space. Revision 28 November 2018. Available from 
        http://en.wikipedia.org/wiki/CIELAB_color_space.
    Wikipedia. 2018c. CIELUV. Revision 27 August 2018. Available from 
        http://en.wikipedia.org/wiki/CIELUV.
    Wikipedia. 2018d. HSL and HSV. Revision 6 November 2018. Available from 
        http://en.wikipedia.org/wiki/HSL_and_HSV.
    Wikipedia. 2018e. Mean of circular quantities. Revision 23 November 2018.
        Available from http://en.wikipedia.org/wiki/Mean_of_circular_quantities.
    Wikipedia. 2018f. RGB color model. Revision 22 October 2018. Available from 
        http://en.wikipedia.org/wiki/RGB_color_model.
    Wikipedia. 2018g. RGB color space. Revision 8 June 2018. Available from 
        http://en.wikipedia.org/wiki/RGB_color_space.
    Wikipedia. 2018h. Standard illuminant. Revision 18 July 2018. Available from 
        http://en.wikipedia.org/wiki/Standard_illuminant.
    Wikipedia. 2019a. Color blindness. Revision 7 January 2019. Available from 
        http://en.wikipedia.org/wiki/Color_blindness.
    Wikipedia. 2019b. Color difference. Revision 9 January 2019. Available from 
        http://en.wikipedia.org/wiki/Color_difference.
    Wikipedia. 2019c. Web colors. Revision 6 January 2019. Available from 
        http://en.wikipedia.org/wiki/Web_colors.
    Zeileis, A., K. Hornik, P. Murrell. 2009.  Escaping RGBland: Selecting Colors for
        Statistical Graphics.  Computational Statistics & Data Analysis 53:
        3259-3270.


Author

    Ben Jann, University of Bern, ben.jann@soz.unibe.ch

    Thanks for citing this software as

        Jann, B. (2019). ColrSpace: Mata class for color management. Available from 
        http://ideas.repec.org/c/boc/bocode/s458594.html.


Also see

    Online:  help for colorpalette (if installed), colorstyle