Install pyCirclize
mainInstall pycirclize using pip or conda. Requires Python 3.10 or later.
PyPI:
pip install pycirclizeConda-forge:
conda install -c conda-forge pycirclizepip install pycirclizerepository·main·Indexed 22 days ago
https://github.com/moshi4/pycirclizeA Python package built on top of matplotlib for circular visualizations. It enables the creation of Circos plots, chord diagrams, radar charts, and specialized bioinformatics visualizations such as genomic and phylogenetic tree plots. Key features include the Circos and Sector classes for managing circular layouts, a Genbank parser for genomic features, and support for interactive tooltips in Jupyter environments.
Install pycirclize using pip or conda. Requires Python 3.10 or later.
PyPI:
pip install pycirclizeConda-forge:
conda install -c conda-forge pycirclizepip install pycirclizeIf your data is in a long format (a table with 'from', 'to', and 'value' columns) rather than a matrix, use pycirclize.parser.Matrix.parse_fromto_table() to convert it into a format compatible with Circos.chord_diagram().
Steps:
Matrix.parse_fromto_table(df) to generate a matrix object.Circos.chord_diagram().from pycirclize import Circos
from pycirclize.parser import Matrix
import pandas as pd
# Create from-to table dataframe
fromto_table_df = pd.DataFrame(
[
["A", "B", 10],
["A", "C", 5],
["A", "D", 15],
["B", "D", 8],
["C", "D", 6],
],
columns=["from", "to", "value"],
)
# Convert to matrix
matrix = Matrix.parse_fromto_table(fromto_table_df)
# Initialize Circos instance
circos = Circos.chord_diagram(
matrix,
space=3,
cmap=dict(A="royalblue", B="orange", C="green", D="red"),
label_kws=dict(size=12),
)
fig = circos.plotfig()To enable interactive tooltip displays in Jupyter (VSCode or JupyterLab), you must install the [tooltip] extra or install ipympl via conda. When plotting, call circos.plotfig(tooltip=True).
Note: Interactive tooltips require a live Python kernel and are not permanently enabled in the notebook after plotting.
pip install pycirclize[tooltip]
# or
conda install -c conda-forge pycirclize ipympl
# Usage in code
circos.plotfig(tooltip=True)The Track class is used to manage and plot data layers within a specific Sector of a circular plot. It provides high-level methods to draw various geometric shapes, text, and statistical plots (like bars, lines, and scatter plots) mapped to the circular coordinate system. Most plotting methods accept x (position along the sector) and y (radius/value) coordinates, which the track automatically converts to polar coordinates.
# Conceptual usage pattern
track = sector.add_track(r_lim=(10, 12))
track.rect(start=100, end=200, fc="red")
track.line(x=[100, 150, 200], y=[5, 10, 5])
track.scatter(x=[120, 180], y=[7, 8])Visualize phylogenetic trees by using Circos.initialize_from_tree(). This method takes a Newick tree file and returns a Circos instance and a tree view object (tv). You can use tv.set_node_line_props() to color specific species or groups within the tree.
from pycirclize import Circos
from pycirclize.utils import load_example_tree_file, ColorCycler
from matplotlib.lines import Line2D
# Initialize Circos from phylogenetic tree
tree_file = load_example_tree_file("large_example.nwk")
circos, tv = Circos.initialize_from_tree(
tree_file,
r_lim=(30, 100),
leaf_label_size=5,
line_kws=dict(color="lightgrey", lw=1.0),
)
# Define group-species dict for tree annotation
group_name2species_list = dict(
Monotremata=["Tachyglossus_aculeatus", "Ornithorhynchus_anatinus"],
Marsupialia=["Monodelphis_domestica", "Vombatus_ursinus"],
Xenarthra=["Choloepus_didactylus", "Dasypus novemcinctus"],
Afrotheria=["Trichechus_manatus", "Chrysochloris_asiatica"],
Euarchontes=["Galeopterus_variegatus", "Theropithecus_gelada"],
Glires=["Oryctolagus_cuniculus", "Microtus_oregoni"],
Laurasiatheria=["Talpa_occidentalis", "Mirounga_leonina"],
)
# Set tree line color & label color
ColorCycler.set_cmap("tab10")
group_name2color = {name: ColorCycler() for name in group_name2species_list.keys()}
for group_name, species_list in group_name2species_list.items():
color = group_name2color[group_name]
tv.set_node_line_props(species_list, color=color, apply_label_color=True)
# Plot figure & set legend on center
fig = circos.plotfig()
_ = circos.ax.legend(
handles=[Line2D([], [], label=n, color=c) for n, c in group_name2color.items()],
labelcolor=group_name2color.values(),
fontsize=6,
loc="center",
bbox_to_anchor=(0.5, 0.5),
)
fig.savefig("example04.png")For bioinformatics, use fetch_genbank_by_accid to download data and the Genbank parser to process it. You can initialize Circos using the genome sizes from the Genbank object and plot genomic features (like CDS) onto tracks using genomic_features().
from pycirclize import Circos
from pycirclize.utils import fetch_genbank_by_accid
from pycirclize.parser import Genbank
# Download `NC_002483` E.coli plasmid genbank
gbk_fetch_data = fetch_genbank_by_accid("NC_002483")
gbk = Genbank(gbk_fetch_data)
# Initialize Circos instance with genome size
sectors = gbk.get_seqid2size()
space = 0 if len(sectors) == 1 else 2
circos = Circos(sectors, space=space)
circos.text(f"Escherichia coli K-12 plasmid F\n\n{gbk.name}", size=14)
seqid2features = gbk.get_seqid2features(feature_type="CDS")
for sector in circos.sectors:
# Setup track for features plot
f_cds_track = sector.add_track((95, 100))
f_cds_track.axis(fc="lightgrey", ec="none", alpha=0.5)
r_cds_track = sector.add_track((90, 95))
r_cds_track.axis(fc="lightgrey", ec="none", alpha=0.5)
# Plot forward/reverse strand CDS
features = seqid2features[sector.name]
for feature in features:
if feature.location.strand == 1:
f_cds_track.genomic_features(feature, plotstyle="arrow", fc="salmon", lw=0.5)
else:
r_cds_track.genomic_features(feature, plotstyle="arrow", fc="skyblue", lw=0.5)
# Plot 'gene' qualifier label if exists
labels, label_pos_list = [], []
for feature in features:
start = int(feature.location.start)
end = int(feature.location.end)
label_pos = (start + end) / 2
gene_name = feature.qualifiers.get("gene", [None])[0]
if gene_name is not None:
labels.append(gene_name)
label_pos_list.append(label_pos)
f_cds_track.annotate(label_pos, gene_name, label_size=6)
# Plot xticks (interval = 10 Kb)
r_cds_track.xticks_by_interval(
10000, outer=False, label_formatter=lambda v: f"{v/1000:.1f} Kb"
)
circos.savefig("example02.png")To highlight specific connections in a Chord Diagram, provide a link_kws_handler function to Circos.chord_diagram(). This function accepts from_label and to_label as arguments and should return a dictionary of properties (like alpha or zorder) to apply to that specific link.
def link_kws_handler(from_label: str, to_label: str):
if from_label in ("C", "G"):
# Highlight specific links by increasing zorder and adjusting alpha
return dict(alpha=0.5, zorder=1.0)
else:
return dict(alpha=0.1, zorder=0)
circos = Circos.chord_diagram(
matrix_df,
link_kws_handler=link_kws_handler,
# ... other arguments
)Generate radar charts from a pandas DataFrame using Circos.radar_chart(). This is useful for comparing multiple parameters across different categories.
from pycirclize import Circos
import pandas as pd
# Create RPG jobs parameter dataframe (3 jobs, 7 parameters)
df = pd.DataFrame(
data=[
[80, 80, 80, 80, 80, 80, 80],
[90, 20, 95, 95, 30, 30, 80],
[60, 90, 20, 20, 100, 90, 50],
],
index=["Hero", "Warrior", "Wizard"],
columns=["HP", "MP", "ATK", "DEF", "SP.ATK", "SP.DEF", "SPD"],
)
# Initialize Circos instance for radar chart plot
circos = Circos.radar_chart(
df,
vmax=100,
marker_size=6,
grid_interval_ratio=0.2,
)
# Plot figure & set legend on upper right
fig = circos.plotfig()
_ = circos.ax.legend(loc="upper right", fontsize=10)
fig.savefig("example05.png")Generate a chord diagram from a pandas DataFrame representing an adjacency matrix using Circos.chord_diagram(). This method handles the initialization of the circular layout and the links between sectors automatically.
from pycirclize import Circos
import pandas as pd
# Create matrix dataframe (3 x 6)
row_names = ["F1", "F2", "F3"]
col_names = ["T1", "T2", "T3", "T4", "T5", "T6"]
matrix_data = [
[10, 16, 7, 7, 10, 8],
[4, 9, 10, 12, 12, 7],
[17, 13, 7, 4, 20, 4],
]
matrix_df = pd.DataFrame(matrix_data, index=row_names, columns=col_names)
# Initialize Circos instance for chord diagram plot
circos = Circos.chord_diagram(
matrix_df,
space=5,
cmap="tab10",
label_kws=dict(size=12),
link_kws=dict(ec="black", lw=0.5, direction=1),
)
circos.savefig("example03.png")To create a custom Circos plot, initialize the Circos class with a dictionary of sectors and their sizes. You can then iterate through sectors to add tracks, plot lines, scatter points, or bars. Use circos.link() to draw connections between different parts of the circle.
Key steps:
sectors = {"A": 10, "B": 15}circos = Circos(sectors, space=5)sector.add_track((start_radius, end_radius))circos.link((sector1, start, end), (sector2, start, end))from pycirclize import Circos
import numpy as np
np.random.seed(0)
# Initialize Circos sectors
sectors = {"A": 10, "B": 15, "C": 12, "D": 20, "E": 15}
circos = Circos(sectors, space=5)
for sector in circos.sectors:
# Plot sector name
sector.text(f"Sector: {sector.name}", r=110, size=15)
# Create x positions & random y values
x = np.arange(sector.start, sector.end) + 0.5
y = np.random.randint(0, 100, len(x))
# Plot lines
track1 = sector.add_track((80, 100), r_pad_ratio=0.1)
track1.xticks_by_interval(interval=1)
track1.axis()
track1.line(x, y)
# Plot points
track2 = sector.add_track((55, 75), r_pad_ratio=0.1)
track2.axis()
track2.scatter(x, y)
# Plot bars
track3 = sector.add_track((30, 50), r_pad_ratio=0.1)
track3.axis()
track3.bar(x, y)
# Plot links
circos.link(("A", 0, 3), ("B", 15, 12))
circos.link(("B", 0, 3), ("C", 7, 11), color="skyblue")
circos.link(("C", 2, 5), ("E", 15, 12), color="chocolate", direction=1)
circos.link(("D", 3, 5), ("D", 18, 15), color="lime", ec="black", lw=0.5, hatch="//", direction=2)
circos.link(("D", 8, 10), ("E", 2, 8), color="violet", ec="red", lw=1.0, ls="dashed")
circos.savefig("example01.png")You can generate a Chord Diagram by passing a pandas DataFrame (representing a matrix) to Circos.chord_diagram().
Key parameters for Circos.chord_diagram():
matrix_df: A pandas DataFrame with row and column names.start, end: Angular range for the plot.space: Space between sectors.r_lim: Tuple defining the radial range for the sectors.cmap: Colormap (string or dictionary) for coloring sectors.label_kws: Dictionary of keyword arguments for sector labels (e.g., r, size, color).link_kws: Dictionary of keyword arguments for the links (e.g., ec, lw, direction).link_kws_handler: A callback function used to dynamically customize link properties based on the source and destination labels.from pycirclize import Circos
import pandas as pd
# Create matrix dataframe
matrix_df = pd.DataFrame(
[[4, 14, 13, 17, 5, 2], [7, 1, 6, 8, 12, 15], [9, 10, 3, 16, 11, 18]],
index=["S1", "S2", "S3"],
columns=["E1", "E2", "E3", "E4", "E5", "E6"],
)
# Initialize Circos instance
circos = Circos.chord_diagram(
matrix_df,
start=-265,
end=95,
space=5,
r_lim=(93, 100),
cmap="tab10",
label_kws=dict(r=94, size=12, color="white"),
link_kws=dict(ec="black", lw=0.5),
)
fig = circos.plotfig()pycirclize.utils.helper.ColorCycler class is a utility for cycling through a predefined or custom set of colors. This is helpful when plotting multiple sectors, lines, or points and you want to ensure each element gets a distinct color from a palette.