Skip to content

ridgeplot.colors

This module collects functions for manipulating color legends for matplotlib plots and a collections of color palettes.

ColorEncoder

color-encoding a categoric vector

Example
>>> from ridgeplot.colors import ColorEncoder, ColorPalette
>>> categorical_vector = ['group a','group b','group c','group a']
>>> colors = ColorPalette["okabeito"]
>>> ce = ColorEncoder()
>>> ce.fit(categorical_vector, colors)
>>> ce.encoder
OrderedDict([('group a', '#E69F00'),
     ('group b', '#56B4E9'),
     ('group c', '#009E73')])
>>> ce.transform(["group b", "group c", "group a"])
['#56B4E9', '#009E73', '#E69F00']
or
>>> ce = ColorEncoder()
>>> ce.fit_transform(categorical_vector, colors)
['#E69F00', '#56B4E9', '#009E73', '#E69F00']
access color encoder
>>> ce.encoder
OrderedDict([('group a', '#E69F00'),
     ('group b', '#56B4E9'),
     ('group c', '#009E73')])
Source code in ridgeplot/colors.py
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
class ColorEncoder:
    """
    color-encoding a categoric vector

    Example:
        ```
        >>> from ridgeplot.colors import ColorEncoder, ColorPalette
        >>> categorical_vector = ['group a','group b','group c','group a']
        >>> colors = ColorPalette["okabeito"]
        >>> ce = ColorEncoder()
        >>> ce.fit(categorical_vector, colors)
        >>> ce.encoder
        OrderedDict([('group a', '#E69F00'),
             ('group b', '#56B4E9'),
             ('group c', '#009E73')])
        >>> ce.transform(["group b", "group c", "group a"])
        ['#56B4E9', '#009E73', '#E69F00']
        ```

    or:
        ```
        >>> ce = ColorEncoder()
        >>> ce.fit_transform(categorical_vector, colors)
        ['#E69F00', '#56B4E9', '#009E73', '#E69F00']
        ```

    access color encoder:
        ```
        >>> ce.encoder
        OrderedDict([('group a', '#E69F00'),
             ('group b', '#56B4E9'),
             ('group c', '#009E73')])
        ```
    """

    def __init__(self):
        self.x: List[str] = list()
        self.distinct_categories: List[str] = []
        self.encoder: OrderedDict[str, str] = OrderedDict()

    def fit(self, categories: List[str], colors: List[str] = ColorPalette["invitae"]) -> None:
        """
        mapping colors to the unique categories in the input list
        basically fill the encoder dictionary

        Example:
            ```
            >>> categorical_vector = ['group a','group b','group c','group a']
            >>> colors = ColorPalette["okabeito"]
            >>> ce = ColorEncoder()
            >>> ce.fit(categroical_vector, colors)
            ```

        Args:
            categories: list of input values (i.e. labels of the samples), can be duplicated
            colors: list of colors, intentionally not checked for duplication
        Returns:
            NoneType
        """
        self.distinct_categories = check_color_vector_size(categories, colors)
        self.encoder = OrderedDict({category: col for category, col in zip(self.distinct_categories, colors)})

    def transform(self, categories: List[str]) -> List[str]:
        """
        mapping color to the a list of category in the input list

        Example:
            ```
            >>> categorical_vector = ['group a','group b','group c','group a']
            >>> colors = ColorPalette["okabeito"]
            >>> ce = color_encoder()
            >>> ce.fit(categroical_vector, colors)
            >>> new_categorical_vector = ["group b", "group c"]
            >>> ce.transform(new_categorical_vector)
            ['#56B4E9', '#009E73']
            ```

        Args:
            categories: list of input values (i.e. labels of the samples), can be duplicated
        Returns:
            list of colors for the input list according to the fitted color encoder
        """
        if not self.encoder:
            raise ValueError("Call color_encoder.fit() first!!")

        union_set = set(self.distinct_categories).union(set(categories))
        if len(union_set) != len(self.distinct_categories):
            unseen = union_set - set(self.distinct_categories)
            unseen_str = ", ".join(sorted(list(unseen)))
            raise ValueError(f"Input [categories] contain unseen data!!: {unseen_str}")

        return [self.encoder[category] for category in categories]

    def fit_transform(self, categories: List[str], colors: List[str] = ColorPalette["invitae"]) -> List[str]:
        """
        first map the color to the categories, and then return the
        corresponding color for each category in the input list

        Example:
            ```
            >>> categorical_vector = ["group1", "group2", "group1"]
            >>> colors = ["salmon","gold"]
            >>> ce = ColorEncoder()
            >>> ce.fit_transform(categorical_vector, colors)
            ['salmon', 'gold', 'salmon']
            ```

        Args:
            categories: list of input values (i.e. labels of the samples), can be duplicated
            colors: list of colors to be assigned to the categories
        Returns:
            list of colors corresponding to the input
        """
        self.fit(categories, colors=colors)
        return self.transform(categories)

    def show_legend(
        self,
        ax: matplotlib.axes._axes.Axes,
        sort: bool = False,
        **kwargs: Dict[str, Any],
    ) -> legend.Legend:
        """
        Adding matplotlib legend describing the color encoder to a matplotlib ax object

        Args:
            ax: matplotlib ax object
            sort: sort the legend by the category
            **kwargs: keyword arguments for matplotlib.pyplot.legend

        Returns:
            the matplotlib legend object
        """

        if sort:
            self.encoder = OrderedDict(sorted(self.encoder.items(), key=lambda item: item[0]))
        pat = [mpatches.Patch(color=col, label=lab) for lab, col in self.encoder.items()]
        lgd = ax.legend(handles=pat, **kwargs)
        return lgd

fit(categories, colors=ColorPalette['invitae'])

mapping colors to the unique categories in the input list basically fill the encoder dictionary

Example
>>> categorical_vector = ['group a','group b','group c','group a']
>>> colors = ColorPalette["okabeito"]
>>> ce = ColorEncoder()
>>> ce.fit(categroical_vector, colors)

Parameters:

Name Type Description Default
categories List[str]

list of input values (i.e. labels of the samples), can be duplicated

required
colors List[str]

list of colors, intentionally not checked for duplication

ColorPalette['invitae']

Returns: NoneType

Source code in ridgeplot/colors.py
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
def fit(self, categories: List[str], colors: List[str] = ColorPalette["invitae"]) -> None:
    """
    mapping colors to the unique categories in the input list
    basically fill the encoder dictionary

    Example:
        ```
        >>> categorical_vector = ['group a','group b','group c','group a']
        >>> colors = ColorPalette["okabeito"]
        >>> ce = ColorEncoder()
        >>> ce.fit(categroical_vector, colors)
        ```

    Args:
        categories: list of input values (i.e. labels of the samples), can be duplicated
        colors: list of colors, intentionally not checked for duplication
    Returns:
        NoneType
    """
    self.distinct_categories = check_color_vector_size(categories, colors)
    self.encoder = OrderedDict({category: col for category, col in zip(self.distinct_categories, colors)})

fit_transform(categories, colors=ColorPalette['invitae'])

first map the color to the categories, and then return the corresponding color for each category in the input list

Example
>>> categorical_vector = ["group1", "group2", "group1"]
>>> colors = ["salmon","gold"]
>>> ce = ColorEncoder()
>>> ce.fit_transform(categorical_vector, colors)
['salmon', 'gold', 'salmon']

Parameters:

Name Type Description Default
categories List[str]

list of input values (i.e. labels of the samples), can be duplicated

required
colors List[str]

list of colors to be assigned to the categories

ColorPalette['invitae']

Returns: list of colors corresponding to the input

Source code in ridgeplot/colors.py
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
def fit_transform(self, categories: List[str], colors: List[str] = ColorPalette["invitae"]) -> List[str]:
    """
    first map the color to the categories, and then return the
    corresponding color for each category in the input list

    Example:
        ```
        >>> categorical_vector = ["group1", "group2", "group1"]
        >>> colors = ["salmon","gold"]
        >>> ce = ColorEncoder()
        >>> ce.fit_transform(categorical_vector, colors)
        ['salmon', 'gold', 'salmon']
        ```

    Args:
        categories: list of input values (i.e. labels of the samples), can be duplicated
        colors: list of colors to be assigned to the categories
    Returns:
        list of colors corresponding to the input
    """
    self.fit(categories, colors=colors)
    return self.transform(categories)

show_legend(ax, sort=False, **kwargs)

Adding matplotlib legend describing the color encoder to a matplotlib ax object

Parameters:

Name Type Description Default
ax Axes

matplotlib ax object

required
sort bool

sort the legend by the category

False
**kwargs Dict[str, Any]

keyword arguments for matplotlib.pyplot.legend

{}

Returns:

Type Description
Legend

the matplotlib legend object

Source code in ridgeplot/colors.py
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
def show_legend(
    self,
    ax: matplotlib.axes._axes.Axes,
    sort: bool = False,
    **kwargs: Dict[str, Any],
) -> legend.Legend:
    """
    Adding matplotlib legend describing the color encoder to a matplotlib ax object

    Args:
        ax: matplotlib ax object
        sort: sort the legend by the category
        **kwargs: keyword arguments for matplotlib.pyplot.legend

    Returns:
        the matplotlib legend object
    """

    if sort:
        self.encoder = OrderedDict(sorted(self.encoder.items(), key=lambda item: item[0]))
    pat = [mpatches.Patch(color=col, label=lab) for lab, col in self.encoder.items()]
    lgd = ax.legend(handles=pat, **kwargs)
    return lgd

transform(categories)

mapping color to the a list of category in the input list

Example
>>> categorical_vector = ['group a','group b','group c','group a']
>>> colors = ColorPalette["okabeito"]
>>> ce = color_encoder()
>>> ce.fit(categroical_vector, colors)
>>> new_categorical_vector = ["group b", "group c"]
>>> ce.transform(new_categorical_vector)
['#56B4E9', '#009E73']

Parameters:

Name Type Description Default
categories List[str]

list of input values (i.e. labels of the samples), can be duplicated

required

Returns: list of colors for the input list according to the fitted color encoder

Source code in ridgeplot/colors.py
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
def transform(self, categories: List[str]) -> List[str]:
    """
    mapping color to the a list of category in the input list

    Example:
        ```
        >>> categorical_vector = ['group a','group b','group c','group a']
        >>> colors = ColorPalette["okabeito"]
        >>> ce = color_encoder()
        >>> ce.fit(categroical_vector, colors)
        >>> new_categorical_vector = ["group b", "group c"]
        >>> ce.transform(new_categorical_vector)
        ['#56B4E9', '#009E73']
        ```

    Args:
        categories: list of input values (i.e. labels of the samples), can be duplicated
    Returns:
        list of colors for the input list according to the fitted color encoder
    """
    if not self.encoder:
        raise ValueError("Call color_encoder.fit() first!!")

    union_set = set(self.distinct_categories).union(set(categories))
    if len(union_set) != len(self.distinct_categories):
        unseen = union_set - set(self.distinct_categories)
        unseen_str = ", ".join(sorted(list(unseen)))
        raise ValueError(f"Input [categories] contain unseen data!!: {unseen_str}")

    return [self.encoder[category] for category in categories]

check_color_vector_size(categorical_vector, color_vector)

asserting the number of different categories in the input list is less than the given color list

Parameters:

Name Type Description Default
categorical_vector List[str]

list of input values (i.e. labels of the samples), can be duplicated

required
color_vector List[str]

list of colors, intentionally not checked for duplication

required

Returns:

Type Description
List[str]

list of unique categories in the input list

Source code in ridgeplot/colors.py
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
def check_color_vector_size(categorical_vector: List[str], color_vector: List[str]) -> List[str]:
    """
    asserting the number of different categories in the input list is less than the given color list

    Args:
        categorical_vector: list of input values (i.e. labels of the samples), can be duplicated
        color_vector: list of colors, intentionally not checked for duplication

    Returns:
        list of unique categories in the input list
    """
    categories = ordered_set(categorical_vector)

    if len(categories) > len(color_vector):
        raise ValueError(f"Not enough colors!! {len(color_vector)} colors for {len(categories)} categories")
    return categories

get_cmap_color_values(cmap_name)

Get color values for the min and max color in a color map

Parameters:

Name Type Description Default
cmap_name str

color map name (e.g. viridis)

required

Returns:

Type Description
Tuple[str, str]

hex code for the min and max color

Source code in ridgeplot/colors.py
279
280
281
282
283
284
285
286
287
288
289
290
def get_cmap_color_values(cmap_name: str) -> Tuple[str, str]:
    """
    Get color values for the min and max color in a color map

    Args:
        cmap_name: color map name (e.g. viridis)

    Returns:
        hex code for the min and max color
    """
    cmap = get_cmap(cmap_name)
    return to_hex(cmap(0.0)), to_hex(cmap(1.0))

ordered_set(xs)

this is a simple function to make a set according to the order of the input list

because python set is unordered, see: https://stackoverflow.com/questions/9792664/converting-a-list-to-a-set-changes-element-order

Parameters:

Name Type Description Default
xs List[str]

list of input values

required

Returns:

Type Description
List[str]

a list of unique input values in the order of how they arranged in the input list

Source code in ridgeplot/colors.py
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
def ordered_set(xs: List[str]) -> List[str]:
    """
    this is a simple function to make a set according to the order of the input list

    because python set is unordered, see:
        https://stackoverflow.com/questions/9792664/converting-a-list-to-a-set-changes-element-order

    Args:
        xs: list of input values

    Returns:
        a list of unique input values in the order of how they arranged in the input list
    """  # noqa: E501
    xs = list(xs)
    return sorted(set(xs), key=xs.index)