Plotting¶
Sequence logos and plots of analysis results, drawn with matplotlib, which is installed with pip install universalmotif[plot]. Each function returns the matplotlib figure or axes, so that plots can be adjusted before they are saved.
view_motifs
¶
view_motifs(
motifs: Motif | Iterable[Motif],
use_type: str = "ICM",
rc: bool = True,
min_overlap: int = 6,
relative_entropy: bool = False,
sort_by: str = "none",
show_names: bool = True,
names_pos: str = "top",
show_positions: bool = True,
show_positions_once: bool = True,
colour_scheme: Mapping[str, str] | None = None,
min_height: float = 0.01,
x_spacer: float = 0.04,
y_spacer: float = 0.01,
sort_positions: bool | None = None,
sort_positions_decreasing: bool = True,
fit_to_height: Any = _DEFAULT,
rc_text: str = " [RC]",
flip_neg: bool = True,
text_size: float = 12,
figsize: tuple[float, float] | None = None,
return_raw: bool = False,
nthreads: int = 1,
ax: Axes | None = None,
)
Draw motifs as sequence logos.
Motifs of any alphabet can be drawn. Several motifs are aligned to the
one with the highest information content in the same way as
compare_motifs() aligns them, trying
reverse complements of DNA and RNA motifs with rc. Motifs that align
better as reverse complements are flipped and get rc_text added to
their names, and all of them are padded into a common frame and drawn
one above the other.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
use_type
|
str
|
Matrix type to draw, one of |
'ICM'
|
sort_by
|
str
|
Display order, which is the input order with |
'none'
|
show_names
|
bool
|
Name each logo, either above it with |
True
|
names_pos
|
bool
|
Name each logo, either above it with |
True
|
show_positions
|
bool
|
Number the positions, either once under the last logo or under every logo with each motif counting its own positions. |
True
|
show_positions_once
|
bool
|
Number the positions, either once under the last logo or under every logo with each motif counting its own positions. |
True
|
colour_scheme
|
Mapping[str, str] | None
|
Letter colours. DNA and RNA default to green A, blue C, yellow G and red T or U, amino acids to colours grouped by side-chain chemistry, and other alphabets to a categorical palette. |
None
|
min_height
|
float
|
Letter layout, as in |
0.01
|
x_spacer
|
float
|
Letter layout, as in |
0.01
|
y_spacer
|
float
|
Letter layout, as in |
0.01
|
sort_positions
|
float
|
Letter layout, as in |
0.01
|
sort_positions_decreasing
|
float
|
Letter layout, as in |
0.01
|
fit_to_height
|
float
|
Letter layout, as in |
0.01
|
flip_neg
|
float
|
Letter layout, as in |
0.01
|
return_raw
|
bool
|
Return the aligned matrices as a dict from names to (letters, positions) arrays instead of drawing them. |
False
|
ax
|
Axes | None
|
Draw a single motif on these axes, such as a panel of a larger
figure, instead of in a new figure. |
None
|
Returns:
| Type | Description |
|---|---|
Figure | Axes | dict[str, ndarray]
|
A matplotlib figure, the axes drawn on when |
Examples:
>>> import matplotlib.pyplot as plt
>>> import universalmotif as um
>>> motifs = um.example_motifs()[:3]
>>> fig = um.view_motifs(motifs)
>>> type(fig).__name__, len(fig.axes)
('Figure', 3)
>>> plt.close(fig)
With return_raw, the aligned matrices share one width:
>>> raw = um.view_motifs(motifs, use_type="PPM", return_raw=True)
>>> {name: m.shape for name, m in raw.items()}
{'TATA-box [RC]': (4, 11), 'AP-1': (4, 11), 'CRE': (4, 11)}
A single motif can go into a panel of another figure:
>>> fig, (left, right) = plt.subplots(1, 2, figsize=(8, 2.5))
>>> ax = um.view_motifs(motifs[1], ax=left)
>>> ax is left
True
>>> plt.close(fig)
view_logo
¶
view_logo(
x,
letters: Sequence[str] | None = None,
colour_scheme: Mapping[str, str] | None = None,
fill: str = "black",
min_height: float = 0.01,
x_spacer: float = 0.04,
y_spacer: float = 0.01,
sort_positions: bool = False,
sort_positions_decreasing: bool = True,
fit_to_height: float | None = None,
flip_neg: bool = True,
ax: Axes | None = None,
) -> Axes
Draw a logo from any numeric matrix.
x is a (rows, positions) array with letters naming the rows, a
mapping from row names to values, or a motif, which is drawn as its
matrix is. Row names may be several characters long, columns can have
any height, and negative values are stacked below zero, upside down so
that they read outward from zero unless flip_neg is False.
Letters are coloured by colour_scheme, a mapping from
single characters to colours, or all filled with fill.
Letters shorter than min_height are left out, x_spacer and
y_spacer set the gaps between letters, sort_positions stacks
each position's letters by height, and fit_to_height scales every
position to that height. The axes are left bare.
Examples:
>>> import matplotlib.pyplot as plt
>>> import numpy as np
>>> import universalmotif as um
>>> x = np.array([[1.0, 0.2, -0.5], [0.1, 1.5, 0.3]])
>>> ax = um.view_logo(x, letters=["A", "Bc"])
>>> type(ax).__name__
'Axes'
>>> plt.close("all")
view_attributions
¶
view_attributions(
scores: Any,
sequence: str | None = None,
kind: str = "observed",
alphabet: str = "ACGT",
start: int = 0,
region: tuple[int, int] | None = None,
hits: DataFrame | None = None,
colour_scheme: Mapping[str, str] | None = None,
flip_neg: bool = True,
ylabel: str | None = None,
figsize: tuple[float, float] | None = None,
ax: Axes | None = None,
) -> Axes
Draw attribution or contribution scores along a sequence, such as those a deep-learning model gives each position of an input.
scores is either one value per position, or one value per letter
and position as an array of shape (letters, length), with the letters
in the order of alphabet. Arrays of shape (length, letters) and
PyTorch tensors are accepted too. kind chooses what is drawn:
"observed"
A logo of the letters of sequence, each as tall as its score,
above the axis when positive and below it when negative. Scores per
letter are reduced to those of the letters in the sequence, so this
draws contribution scores times the input. Without sequence,
per-letter scores are drawn as they are, which suits scores that
are already zero for the letters not in the sequence.
"all"
A logo of every letter's score at every position, such as
hypothetical contributions or the effects of in silico
mutagenesis, with positive scores stacked above the axis and
negative ones below.
"heatmap"
The same per-letter scores as a heatmap with a colour scale
centred on zero, with the letters of sequence marked by dots.
Positions are labelled from start, such as the genomic position of
the first letter, and region, a (start, end) pair in the same
positions with the end left out, draws only part of the sequence.
hits, such as from scan_sequences()
run on sequence, shades each hit, labelled with its motif if the
table has one, with positions counted along the sequence from 0.
Letters are coloured by colour_scheme, by default the package's
colours for DNA, RNA and amino acids, and letters below the axis are
drawn upside down, so that they read outward from zero, unless
flip_neg is False.
Needs the plot extra.
Examples:
>>> import matplotlib.pyplot as plt
>>> import numpy as np
>>> import universalmotif as um
>>> seq = "ACGTTTGACCAAGT"
>>> scores = np.zeros(len(seq))
>>> scores[4:10] = [0.3, 0.6, 0.9, 0.8, 0.7, 0.4]
>>> ax = um.view_attributions(scores, seq)
>>> ax.get_ylabel()
'Attribution'
>>> ism = np.random.default_rng(1).normal(0, 0.2, (4, len(seq)))
>>> ax = um.view_attributions(ism, seq, kind="heatmap", ylabel="Effect")
>>> plt.close("all")
view_variant
¶
view_variant(
ref_scores: Any,
alt_scores: Any,
sequence: str,
position: int,
alt: str,
kind: str = "observed",
alphabet: str = "ACGT",
start: int = 0,
region: tuple[int, int] | None = None,
colour_scheme: Mapping[str, str] | None = None,
flip_neg: bool = True,
figsize: tuple[float, float] | None = None,
) -> Figure
Draw the attribution scores of a sequence and of the same sequence with one letter changed, one above the other, with their difference below.
ref_scores are the scores of sequence and alt_scores those of
the sequence with alt at position, in any of the forms
view_attributions() takes, drawn
with its kind of "observed" or "all". position and
region are given in the same positions as the axis, which start at
start. The two logos share a y-axis so that they can be compared,
the changed position is shaded, and the bottom panel shows how the total
score at each position changes, alternative minus reference.
Needs the plot extra.
Examples:
>>> import matplotlib.pyplot as plt
>>> import numpy as np
>>> import universalmotif as um
>>> seq = "ACGTTGACTCAGT"
>>> ref = np.zeros(len(seq))
>>> ref[5:11] = [0.3, 0.6, 0.5, 0.6, 0.6, 0.4]
>>> alt = ref * 0.2
>>> fig = um.view_variant(ref, alt, seq, position=7, alt="A")
>>> len(fig.axes)
3
>>> plt.close(fig)
plot_motif_peaks
¶
plot_motif_peaks(
peaks: DataFrame,
motifs: Sequence[str] | None = None,
ncol: int = 2,
bins: int = 50,
fill_window: str = "#ffe4a3",
figsize: tuple[float, float] | None = None,
) -> Figure
Draw the positions of motif hits found by motif_peaks().
One panel per motif, or per motif named in motifs, shows a
histogram of the hit centres, with the most enriched window shaded and
the P-value and enrichment in the title.
Examples:
>>> import matplotlib.pyplot as plt
>>> import universalmotif as um
>>> wbox = um.example_motifs()[5]
>>> hits = um.scan_sequences(wbox, um.example_sequences("targets"), nthreads=1)
>>> fig = um.plot_motif_peaks(um.motif_peaks(hits, seq_length=1000, nthreads=1))
>>> type(fig).__name__
'Figure'
>>> plt.close(fig)
plot_match_bkg
¶
plot_match_bkg(
sequences: Sequence[str]
| Mapping[str, str]
| None = None,
bkg: Sequence[str] | Mapping[str, str] | None = None,
by: Sequence[str] | None = None,
indices: DataFrame | None = None,
figsize: tuple[float, float] | None = None,
) -> Figure
Compare the composition of targets and their matched background
from match_bkg(), as overlaid densities.
Give the targets and the background to draw their GC fraction and length,
or the indices table from match_bkg(..., return_indices=True) to
also see any covariates. by picks the axes to draw.
Examples:
>>> import matplotlib.pyplot as plt
>>> import universalmotif as um
>>> targets = um.example_sequences("targets")
>>> bkg = um.match_bkg(targets, um.example_sequences("controls"), seed=1)
>>> fig = um.plot_match_bkg(targets, bkg, by=["gc"])
>>> type(fig).__name__
'Figure'
>>> plt.close(fig)
plot_motif_proximity
¶
plot_motif_proximity(
proximity: DataFrame,
motifs: Sequence[str] | None = None,
ncol: int = 2,
bins: int = 50,
fill_zone: str = "#ffe4a3",
log_x: bool = False,
figsize: tuple[float, float] | None = None,
) -> Figure
Draw each motif's distances to the nearest anchor, from
motif_proximity(), with the most enriched zone shaded.
Distances are signed and negative upstream of stranded anchors. With
log_x the absolute distances plus one are drawn on a log scale.
Examples:
>>> import matplotlib.pyplot as plt
>>> import universalmotif as um
>>> motifs = [um.example_motifs()[i] for i in (3, 5)]
>>> targets = um.example_sequences("targets")
>>> anchors = [(name, 500, 500) for name in targets]
>>> res = um.motif_proximity(anchors=anchors, motifs=motifs, sequences=targets, nthreads=1)
>>> fig = um.plot_motif_proximity(res)
>>> type(fig).__name__
'Figure'
>>> plt.close(fig)
Logos without matplotlib¶
In a Jupyter notebook, a motif on its own at the end of a cell is shown as its logo next to its metadata. The same logo is available as an SVG image, and the letter heights as a DataFrame for logomaker.
logo_svg
¶
logo_svg(
motif: Motif,
use_type: str | None = None,
height: float = 60,
position_width: float = 16,
colours: Mapping[str, str] | None = None,
relative_entropy: bool = False,
) -> str
A sequence logo of a motif as an SVG image, without matplotlib.
The letters are those view_motifs() draws,
with heights from use_type: information content by default, or
contribution weights for a CWM. The logo is height pixels high and
position_width pixels wide per position, with no axes, which suits
reports and web pages. colours maps letters to colours, by default
those of view_motifs(). The gaps of a
gapped motif are drawn as dotted spaces labelled with their sizes.
Examples:
>>> import universalmotif as um
>>> svg = um.logo_svg(um.example_motifs()[3])
>>> svg.startswith("<svg") and svg.count("<path") >= 8
True
to_logomaker
¶
to_logomaker(
motif: Motif,
use_type: str | None = None,
relative_entropy: bool = False,
)
A motif as a pandas DataFrame for logomaker.
logomaker draws logos from a DataFrame with one row per position, indexed
from 0, and one column per letter. The values are the letter heights of
use_type, information content by default or contribution weights for
a CWM, as view_motifs() draws them. Pass
use_type="PPM" for probabilities. Needs the pandas extra.
Examples:
>>> import universalmotif as um
>>> df = um.to_logomaker(um.example_motifs()[3])
>>> list(df.columns), df.shape
(['A', 'C', 'G', 'T'], (8, 4))