Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add color converter #158

Merged
merged 1 commit into from
May 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 49 additions & 3 deletions bioframe/vis.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,62 @@
from typing import Union
import itertools
import numpy as np
import pandas as pd

import matplotlib
from matplotlib.colors import to_rgb
import matplotlib as mpl
import matplotlib.pyplot as plt

from .core import arrops

DEFAULT_FACECOLOR = "skyblue"
DEFAULT_EDGECOLOR = "dimgray"

__all__ = ["plot_intervals"]
__all__ = ["plot_intervals", "to_ucsc_colorstring"]


def to_ucsc_colorstring(color: Union[str, tuple]) -> str:
"""
Convert any matplotlib color identifier into a UCSC itemRgb color string.

Parameters
----------
color : str or tuple
Any valid matplotlib color representation (e.g. 'red', 'tomato',
'#ff0000', '#ff00', "#ff000055", (1, 0, 0), (1, 0, 0, 0.5))

Returns
-------
str
A UCSC itemRgb colorstring of the form "r,g,b" where r, g, and b are
integers between 0 and 255, inclusive.

Notes
-----
The alpha (opacity) channel is ignored if represented in the input.

Null values are converted to "0", which is shorthand for "0,0,0" (black).
Note that BED9+ files with uninformative itemRgb values should use "0" as
the itemRgb value on every data line.

Examples
--------
>>> to_ucsc_colorstring("red")
'255,0,0'
>>> to_ucsc_colorstring("tomato")
'255,99,71'
>>> df["itemRgb"] = df["color"].apply(to_ucsc_colorstring)
>>> df
chrom start end color itemRgb
chr1 0 10 red 255,0,0
chr1 10 20 blue 0,0,255
chr2 0 10 green 0,128,0
chr2 10 20 None 0
"""
if pd.isnull(color):
nvictus marked this conversation as resolved.
Show resolved Hide resolved
return "0"
else:
return ",".join(str(int(x*255)) for x in to_rgb(color))


def _plot_interval(
Expand All @@ -21,7 +67,7 @@ def _plot_interval(

ax = plt.gca() if ax is None else ax
ax.add_patch(
matplotlib.patches.Rectangle(
mpl.patches.Rectangle(
(start, level - height / 2),
end - start,
height,
Expand Down
38 changes: 38 additions & 0 deletions tests/test_vis.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import bioframe
import numpy as np
import pandas as pd

import pytest


def test_to_ucsc_colorstring():
bioframe.to_ucsc_colorstring("red") == "255,0,0"
bioframe.to_ucsc_colorstring("blue") == "0,0,255"
bioframe.to_ucsc_colorstring("green") == "0,128,0"
bioframe.to_ucsc_colorstring("black") == "0,0,0"
bioframe.to_ucsc_colorstring("white") == "255,255,255"
bioframe.to_ucsc_colorstring("r") == "255,0,0"
bioframe.to_ucsc_colorstring("tomato") == "255,99,71"
bioframe.to_ucsc_colorstring("xkcd:sky blue") == "135,206,235"
bioframe.to_ucsc_colorstring("#abc") == "170,187,204"
bioframe.to_ucsc_colorstring("#ff0000") == "255,0,0"
bioframe.to_ucsc_colorstring("#ff000055") == "255,0,0"
bioframe.to_ucsc_colorstring((1, 0, 0)) == "255,0,0"
bioframe.to_ucsc_colorstring((1, 0, 0, 0.5)) == "255,0,0"
bioframe.to_ucsc_colorstring((0, 0, 1)) == "0,0,255"
bioframe.to_ucsc_colorstring(None) == "0"
bioframe.to_ucsc_colorstring("none") == "0"
bioframe.to_ucsc_colorstring(np.nan) == "0"
bioframe.to_ucsc_colorstring(pd.NA) == "0"

with pytest.raises(ValueError):
bioframe.to_ucsc_colorstring("notacolor")

df = bioframe.from_any([
["chr1", 0, 10, "red"],
["chr1", 10, 20, "blue"],
["chr2", 0, 10, "green"],
["chr2", 10, 20, None],
])
df["itemRgb"] = df["name"].apply(bioframe.to_ucsc_colorstring)
assert df["itemRgb"].tolist() == ["255,0,0", "0,0,255", "0,128,0", "0"]