moshi4 / pyCirclize

Circular visualization in Python (Circos Plot, Chord Diagram, Radar Chart)
https://moshi4.github.io/pyCirclize/
MIT License
758 stars 47 forks source link

Can't plot more than 3 tracks #37

Closed chen1i6c04 closed 1 year ago

chen1i6c04 commented 1 year ago

Hi

Thank you for the amazing tool.

I am trying to plot multiple prokaryote genome comparisons like BLAST Ring Image Generator (BRIG), but it only plot 3 tracks no matter how much genomes

This is test data

I'm using v 0.5.1

The code is

import os
from pathlib import Path
from tempfile import TemporaryDirectory

import pandas as pd
from matplotlib.patches import Patch
from Bio import SeqIO
from Bio.Blast.Applications import NcbiblastnCommandline, NcbimakeblastdbCommandline
from pycirclize import Circos
from pycirclize.utils import ColorCycler

ColorCycler.set_cmap('Set2')
palette = ColorCycler.get_color_list(len(queries))

def run_blastn(query, reference):
    with TemporaryDirectory() as tmpdir:
        blastdb = os.path.join(tmpdir, 'db')
        NcbimakeblastdbCommandline(input_file=reference, dbtype='nucl', out=blastdb)()
        stdout, stderr = NcbiblastnCommandline(query=query, db=blastdb, outfmt="6 sstart send", evalue=1e-20, )()
    return stdout

def get_match_range(blast_output):
    match_ranges = []
    for match_range in blast_output.splitlines():
        start, end = match_range.split()
        start, end = int(start), int(end)
        if start > end:
            start, end = end, start
        match_ranges.append((start, end))
    return match_ranges

track_size = 5
track_start = 90

reference = "CP037959.1.fna"
queries = [
    'MN539018.1.fna',
    'CP101234.1.fna',
    'CP103330.1.fna',
    'AP026962.1.fna',
]

sector_size = len(SeqIO.read(reference, 'fasta'))
circos = Circos(sectors={'CP037959.1': sector_size}, endspace=False)
circos.text(f"CP037959.1\n{sector_size:,} bp", size=12)

sector = circos.sectors[0]

inner_track = sector.add_track((track_start-1, track_start), r_pad_ratio=0.1)
inner_track.rect(start=0, end=sector_size, fc='k')
inner_track.xticks_by_interval(
    interval=20000,
    outer=False,
    label_margin=2,
    show_bottom_line=False,
    label_formatter=lambda x: f"{x/1000:.0f}kbp"
)

for query, color in zip(queries, palette):
    blast_output = run_blastn(query, reference)
    match_ranges = get_match_range(blast_output)
    track_end = track_start + track_size
    blast_track = sector.add_track((track_start, track_end), r_pad_ratio=0.1)
    for start, end in match_ranges:
        blast_track.rect(start=start, end=end, fc=color)
    track_start = track_end

circos.savefig('result.png', dpi=300)

result

Thank you

moshi4 commented 1 year ago

Hi @chen1i6c04,

Try changing track_start = 90 to track_start = 80.

The plotting limit range for tracks in pyCirclize is 0 <= r <= 105, and it expects the user plots tracks in the range 0 <= r <= 100. Your code is failing to plot because it is plotting in the range r > 105.

chen1i6c04 commented 1 year ago

It can plot after change tarck_start = 80

Thanks your help result