RILseq-analysis 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- RILseq_analysis_package/__init__.py +0 -0
- RILseq_analysis_package/annotations_graphs.py +185 -0
- RILseq_analysis_package/chimeras_venn_diagram.py +81 -0
- RILseq_analysis_package/circos_plot.py +164 -0
- RILseq_analysis_package/cli/__init__.py +0 -0
- RILseq_analysis_package/cli/add_number_of_libraries_cli.py +15 -0
- RILseq_analysis_package/cli/circos_plot_cli.py +48 -0
- RILseq_analysis_package/cli/merge_results_cli.py +20 -0
- RILseq_analysis_package/extract_genes_by_chr.py +32 -0
- RILseq_analysis_package/generate_and_edit_RILseq_xslx.py +118 -0
- RILseq_analysis_package/sRNAs_percent.py +144 -0
- RILseq_analysis_package/utils.py +84 -0
- rilseq_analysis-1.0.0.dist-info/METADATA +10 -0
- rilseq_analysis-1.0.0.dist-info/RECORD +17 -0
- rilseq_analysis-1.0.0.dist-info/WHEEL +5 -0
- rilseq_analysis-1.0.0.dist-info/entry_points.txt +8 -0
- rilseq_analysis-1.0.0.dist-info/top_level.txt +1 -0
|
File without changes
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
import os
|
|
3
|
+
import seaborn as sns
|
|
4
|
+
import matplotlib.pyplot as plt
|
|
5
|
+
from RILseq_analysis_package.utils import get_annotation, get_RNA_types, load_config
|
|
6
|
+
import argparse
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_gene_annotation(gene, genes, tRNAs, sRNAs, oRNAs):
|
|
11
|
+
if gene in tRNAs:
|
|
12
|
+
return "tRNA"
|
|
13
|
+
if gene in sRNAs:
|
|
14
|
+
return "sRNA"
|
|
15
|
+
if gene in oRNAs:
|
|
16
|
+
return "oRNA"
|
|
17
|
+
if "3UTR" in gene:
|
|
18
|
+
return "3UTR"
|
|
19
|
+
if "5UTR" in gene:
|
|
20
|
+
return "5UTR"
|
|
21
|
+
if "AS" in gene:
|
|
22
|
+
return "AS"
|
|
23
|
+
if "IGR" in gene:
|
|
24
|
+
return "IGR"
|
|
25
|
+
if "IGT" in gene:
|
|
26
|
+
return "IGT"
|
|
27
|
+
if gene in genes:
|
|
28
|
+
return "CDS"
|
|
29
|
+
return "unknown"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def get_RNAs_types(rna_types_excel):
|
|
33
|
+
sRNAs = set(get_RNA_types("sRNA", rna_types_excel))
|
|
34
|
+
tRNAs = set(get_RNA_types("tRNA", rna_types_excel))
|
|
35
|
+
oRNAs = set(get_RNA_types("oRNA", rna_types_excel))
|
|
36
|
+
return sRNAs, tRNAs, oRNAs
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def RNA1_RNA2_annotations(chr_dic, base_path, experiments, rna_types_excel, annotation_path, chimeras_or_fragments, chrom=None):
|
|
40
|
+
"""
|
|
41
|
+
Creates heatmaps of the chimeras annotations, with and without the annotations numbers.
|
|
42
|
+
:param chimeras_or_fragments: if "chimeras" create the heatmaps according to the amount of chimeras. Else, according
|
|
43
|
+
to the amount of fragments.
|
|
44
|
+
:param chrom: if None, create the heatmaps base on the chimeras between the two chromosomes. Else, create the heatmaps
|
|
45
|
+
base on the chimeras of the given chromosome.
|
|
46
|
+
"""
|
|
47
|
+
genes = get_annotation(annotation_path, chromosome=chrom, separate_id_name=True)["name"].values.tolist()
|
|
48
|
+
sRNAs, tRNAs, oRNAs = get_RNAs_types(rna_types_excel)
|
|
49
|
+
if chrom:
|
|
50
|
+
dir_ = chr_dic[chrom] + "_annotation"
|
|
51
|
+
else:
|
|
52
|
+
dir_ = "_".join(chr_dic.values()) + "_annotation"
|
|
53
|
+
output_path = os.path.join(base_path, dir_)
|
|
54
|
+
if not os.path.exists(output_path):
|
|
55
|
+
os.makedirs(output_path)
|
|
56
|
+
for experiment in experiments:
|
|
57
|
+
df = pd.read_excel(os.path.join(base_path, "RILseq_unified_results.xlsx"), sheet_name=experiment)
|
|
58
|
+
if chrom is not None:
|
|
59
|
+
df = df[(df["RNA1 chromosome"] == chrom) & (df["RNA2 chromosome"] == chrom)]
|
|
60
|
+
else:
|
|
61
|
+
chr1, chr2 = chr_dic.keys()
|
|
62
|
+
df = df[((df["RNA1 chromosome"] == chr1) & (df["RNA2 chromosome"] == chr2)) |
|
|
63
|
+
((df["RNA1 chromosome"] == chr2) & (df["RNA2 chromosome"] == chr1))]
|
|
64
|
+
df["RNA1_annotation"] = df["RNA1 name"].apply(get_gene_annotation, genes=genes, tRNAs=tRNAs, sRNAs=sRNAs, oRNAs=oRNAs)
|
|
65
|
+
df["RNA2_annotation"] = df["RNA2 name"].apply(get_gene_annotation, genes=genes, tRNAs=tRNAs, sRNAs=sRNAs, oRNAs=oRNAs)
|
|
66
|
+
options = ["3UTR", "5UTR", "CDS", "AS", "IGR", "sRNA", "tRNA", "IGT"] #"oRNA"
|
|
67
|
+
|
|
68
|
+
if chimeras_or_fragments == "chimeras":
|
|
69
|
+
df["i"] = df.index
|
|
70
|
+
df = df[["RNA1_annotation", "RNA2_annotation", "i"]]
|
|
71
|
+
small_df = df.groupby(["RNA1_annotation", "RNA2_annotation"]).count()
|
|
72
|
+
small_df_pairs = small_df.index
|
|
73
|
+
amount = small_df["i"].values
|
|
74
|
+
else:
|
|
75
|
+
df = df[["RNA1_annotation", "RNA2_annotation", "interactions"]]
|
|
76
|
+
small_df = df.groupby(["RNA1_annotation", "RNA2_annotation"]).sum()
|
|
77
|
+
small_df_pairs = small_df.index
|
|
78
|
+
amount = small_df["interactions"].values
|
|
79
|
+
dic = {}
|
|
80
|
+
for i in range(len(amount)):
|
|
81
|
+
dic[small_df_pairs[i]] = amount[i]
|
|
82
|
+
results = pd.DataFrame(0, index=options, columns=options)
|
|
83
|
+
for option1 in options:
|
|
84
|
+
for option2 in options:
|
|
85
|
+
if (option1, option2) in small_df_pairs:
|
|
86
|
+
results.loc[option2, option1] = dic[(option1, option2)]
|
|
87
|
+
for annot in [True, False]:
|
|
88
|
+
plt.figure()
|
|
89
|
+
sns.heatmap(results, annot=annot, cmap='Blues', fmt=".6g", annot_kws={"size": 8})
|
|
90
|
+
plt.xlabel("RNA1")
|
|
91
|
+
plt.ylabel("RNA2")
|
|
92
|
+
with_annot = "with_annot" if annot else "without_annot"
|
|
93
|
+
plt.savefig(os.path.join(output_path, f"{experiment}_{chimeras_or_fragments}_{with_annot}.png"))
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def get_RNAs_type_fractions(df, options, chimeras_or_fragments):
|
|
97
|
+
"""
|
|
98
|
+
:param df: chimeras data-frame
|
|
99
|
+
:param options: the annotations
|
|
100
|
+
:param chimeras_or_fragments: if "chimeras" calculate the fraction according to the amount of chimeras. Else, according
|
|
101
|
+
to the amount of fragments.
|
|
102
|
+
:return: a list of the fraction of each annotation
|
|
103
|
+
"""
|
|
104
|
+
if df.empty:
|
|
105
|
+
return [0] * len(options)
|
|
106
|
+
amount_dic = {i:0 for i in options}
|
|
107
|
+
for RNA in "12":
|
|
108
|
+
small_df = df[[f"RNA{RNA}_annotation", "interactions"]]
|
|
109
|
+
small_df = small_df.groupby([f"RNA{RNA}_annotation"])
|
|
110
|
+
if chimeras_or_fragments == "chimeras":
|
|
111
|
+
small_df = small_df.count()
|
|
112
|
+
elif chimeras_or_fragments == "fragments":
|
|
113
|
+
small_df = small_df.sum()
|
|
114
|
+
indexes = small_df.index
|
|
115
|
+
for index in indexes:
|
|
116
|
+
amount_dic[index] += small_df["interactions"][index]
|
|
117
|
+
amount_list = [amount_dic[i] for i in options]
|
|
118
|
+
amount_sum = sum(amount_list)
|
|
119
|
+
return [i/amount_sum for i in amount_list]
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def chimeras_annotations(chr_dic, experiments, base_path, annotation_path, rna_types_excel, chimeras_or_fragments):
|
|
123
|
+
"""
|
|
124
|
+
Creates a bar plot of the annotation fraction for within and between chromosomes for each time point.
|
|
125
|
+
:param chimeras_or_fragments: if "chimeras" create the bar plot according to the amount of chimeras. Else, according
|
|
126
|
+
to the amount of fragments.
|
|
127
|
+
"""
|
|
128
|
+
genes = get_annotation(annotation_path, separate_id_name=True)["name"].values.tolist()
|
|
129
|
+
sRNAs, tRNAs, oRNAs = get_RNAs_types(rna_types_excel)
|
|
130
|
+
options = ["3UTR", "sRNA", "CDS", "5UTR", "IGR", "AS", "tRNA", "oRNA", "IGT"]
|
|
131
|
+
final_dic = {}
|
|
132
|
+
chr1, chr2 = chr_dic.keys()
|
|
133
|
+
chr1_name = chr_dic[chr1]
|
|
134
|
+
chr2_name = chr_dic[chr2]
|
|
135
|
+
for experiment in experiments:
|
|
136
|
+
df = pd.read_excel(os.path.join(base_path, "RILseq_unified_results.xlsx"), sheet_name=experiment)
|
|
137
|
+
df["RNA1_annotation"] = df["RNA1 name"].apply(get_gene_annotation, genes=genes, tRNAs=tRNAs, sRNAs=sRNAs, oRNAs=oRNAs)
|
|
138
|
+
df["RNA2_annotation"] = df["RNA2 name"].apply(get_gene_annotation, genes=genes, tRNAs=tRNAs, sRNAs=sRNAs, oRNAs=oRNAs)
|
|
139
|
+
chr1_df = df[(df["RNA1 chromosome"] == chr1) & (df["RNA2 chromosome"] == chr1)]
|
|
140
|
+
chr2_df = df[(df["RNA1 chromosome"] == chr2) & (df["RNA2 chromosome"] == chr2)]
|
|
141
|
+
chr1_chr2 = df[((df["RNA1 chromosome"] == chr1) & (df["RNA2 chromosome"] == chr2)) |
|
|
142
|
+
((df["RNA1 chromosome"] == chr2) & (df["RNA2 chromosome"] == chr1))]
|
|
143
|
+
if chimeras_or_fragments == "chimeras":
|
|
144
|
+
chr1_amount = chr1_df.shape[0]
|
|
145
|
+
chr1_chr2_amount = chr1_chr2.shape[0]
|
|
146
|
+
chr2_amount = chr2_df.shape[0]
|
|
147
|
+
else:
|
|
148
|
+
chr1_amount = chr1_df["interactions"].sum()
|
|
149
|
+
chr1_chr2_amount = chr1_chr2["interactions"].sum()
|
|
150
|
+
chr2_amount = chr2_df["interactions"].sum()
|
|
151
|
+
final_dic[f"{chr1_name}-{chr1_name} {experiment} ({chr1_amount})"] = get_RNAs_type_fractions(chr1_df, options, chimeras_or_fragments)
|
|
152
|
+
final_dic[f"{chr1_name}-{chr2_name} {experiment} ({chr1_chr2_amount})"] = get_RNAs_type_fractions(chr1_chr2, options, chimeras_or_fragments)
|
|
153
|
+
final_dic[f"{chr2_name}-{chr2_name} {experiment} ({chr2_amount})"] = get_RNAs_type_fractions(chr2_df, options, chimeras_or_fragments)
|
|
154
|
+
df = pd.DataFrame.from_dict(final_dic, orient="index", columns=options)
|
|
155
|
+
df = df[df.columns[(df != 0).any()]]
|
|
156
|
+
fig = plt.figure()
|
|
157
|
+
h = df.plot(kind="bar", linewidth=0, stacked=True, grid=False, cmap="tab20c")
|
|
158
|
+
plt.subplots_adjust(bottom=0.35, right=0.7)
|
|
159
|
+
plt.xticks(rotation=-45, ha='left')
|
|
160
|
+
handles, labels = h.get_legend_handles_labels()
|
|
161
|
+
plt.legend(handles[::-1], labels[::-1], loc=(1.1, 0))
|
|
162
|
+
plt.tight_layout()
|
|
163
|
+
plt.savefig(os.path.join(base_path, f"{chimeras_or_fragments}_annotation_fractions.png"))
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
def main():
|
|
167
|
+
parser = argparse.ArgumentParser(description="Create annotation heatmaps and annotation fraction plots for RIL-seq chimeras and fragments.")
|
|
168
|
+
|
|
169
|
+
parser.add_argument("config", help="Path to the YAML configuration file.")
|
|
170
|
+
|
|
171
|
+
args = parser.parse_args()
|
|
172
|
+
config = load_config(args.config)
|
|
173
|
+
|
|
174
|
+
for type_ in ("fragments", "chimeras"):
|
|
175
|
+
for chrom in config["chr_dic"].keys():
|
|
176
|
+
RNA1_RNA2_annotations(config["chr_dic"], config["base_path"], config["experiments"], config["rna_types_excel"], config["annotation_path"], type_, chrom)
|
|
177
|
+
RNA1_RNA2_annotations(config["chr_dic"], config["base_path"], config["experiments"], config["rna_types_excel"], config["annotation_path"], type_)
|
|
178
|
+
|
|
179
|
+
chimeras_annotations(config["chr_dic"], config["experiments"], config["base_path"], config["annotation_path"], config["rna_types_excel"], type_)
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
import os
|
|
3
|
+
import pandas as pd
|
|
4
|
+
from matplotlib_venn import venn2
|
|
5
|
+
import matplotlib.pyplot as plt
|
|
6
|
+
from RILseq_analysis_package.utils import load_config
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def get_chimeras_pairs(RILseq_path, experiment, chromosomes=None):
|
|
10
|
+
"""
|
|
11
|
+
Reads the RILSeq results and returns a set of the chimeras pairs. Doesn't take into account which RNA is first and
|
|
12
|
+
which is second in the chimera.
|
|
13
|
+
"""
|
|
14
|
+
df = pd.read_excel(os.path.join(RILseq_path, "RILseq_unified_results.xlsx"), sheet_name=experiment)
|
|
15
|
+
if chromosomes:
|
|
16
|
+
df = df[(df["RNA1 chromosome"].isin(chromosomes)) & (df["RNA2 chromosome"].isin(chromosomes))]
|
|
17
|
+
chimeras_pairs = df[["RNA1 name", "RNA2 name"]].values
|
|
18
|
+
chimeras_set = set()
|
|
19
|
+
for pair in chimeras_pairs:
|
|
20
|
+
rna1, rna2 = pair
|
|
21
|
+
if rna1 > rna2:
|
|
22
|
+
chimeras_set.add((rna1, rna2))
|
|
23
|
+
else:
|
|
24
|
+
chimeras_set.add((rna2, rna1))
|
|
25
|
+
return chimeras_set
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def get_all_conditions(conditions):
|
|
29
|
+
all_conditions = []
|
|
30
|
+
for conditions_tuple in conditions:
|
|
31
|
+
all_conditions.append(conditions_tuple[0])
|
|
32
|
+
all_conditions.append(conditions_tuple[1])
|
|
33
|
+
return all_conditions
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def plot(chr_lst, conditions_to_compare, output_path, RILseq_path):
|
|
37
|
+
experiments_chimeras = {}
|
|
38
|
+
for condition in get_all_conditions(conditions_to_compare):
|
|
39
|
+
if chr_lst:
|
|
40
|
+
chimeras_pairs = get_chimeras_pairs(RILseq_path, condition, chromosomes=chr_lst)
|
|
41
|
+
else:
|
|
42
|
+
chimeras_pairs = get_chimeras_pairs(RILseq_path, condition)
|
|
43
|
+
experiments_chimeras.update({condition: chimeras_pairs})
|
|
44
|
+
|
|
45
|
+
for conditions in conditions_to_compare:
|
|
46
|
+
plt.figure()
|
|
47
|
+
venn2([experiments_chimeras[conditions[0]], experiments_chimeras[conditions[1]]],
|
|
48
|
+
set_labels=(conditions[0], conditions[1]),
|
|
49
|
+
set_colors=("SkyBlue", "Salmon"))
|
|
50
|
+
plt.savefig(os.path.join(output_path, f"{conditions[0]}_and_{conditions[1]}_venn.jpg"))
|
|
51
|
+
with open(os.path.join(output_path, f"{conditions[0]}_and_{conditions[1]}_chimeras_pairs.txt"), "w") as f:
|
|
52
|
+
pairs = experiments_chimeras[conditions[0]] & experiments_chimeras[conditions[1]]
|
|
53
|
+
for i in pairs:
|
|
54
|
+
f.write(i[0] + "," + i[1] + "\n")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def main():
|
|
58
|
+
parser = argparse.ArgumentParser("Generate Venn diagrams of chimeras pairs between two conditions. RNA1/RNA2 positions are ignored.")
|
|
59
|
+
|
|
60
|
+
parser.add_argument("config", help="Path to the YAML configuration file.")
|
|
61
|
+
parser.add_argument("conditions_pairs", help="Pairs of experiments to compare, with the two conditions separated by '-'. "
|
|
62
|
+
"Multiple pairs can be separated by commas. "
|
|
63
|
+
"Example: exp1-exp2,exp3-exp4 creates two Venn diagrams: one comparing exp1 and exp2, and the other comparing exp3 and exp4.")
|
|
64
|
+
parser.add_argument("--chr", help="Comma-separated list of chromosomes to include. If not provided, chimeras from all chromosomes are included.")
|
|
65
|
+
|
|
66
|
+
args = parser.parse_args()
|
|
67
|
+
|
|
68
|
+
base_path = load_config(args.config)["base_path"]
|
|
69
|
+
venn_path = os.path.join(base_path, "venn_diagrams")
|
|
70
|
+
if not os.path.exists(venn_path):
|
|
71
|
+
os.makedirs(venn_path)
|
|
72
|
+
|
|
73
|
+
pairs = args.conditions_pairs.split(",")
|
|
74
|
+
pairs = [i.split("-") for i in pairs]
|
|
75
|
+
|
|
76
|
+
if args.chr is not None:
|
|
77
|
+
chr_list = args.chr.split(",")
|
|
78
|
+
else:
|
|
79
|
+
chr_list = None
|
|
80
|
+
plot(chr_list, pairs, venn_path, base_path)
|
|
81
|
+
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import pandas as pd
|
|
3
|
+
from RILseq_analysis_package.utils import get_annotation
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def convert_to_kb_mb(range_lst):
|
|
7
|
+
if range_lst[-1] > 10 ** 6:
|
|
8
|
+
return [str("%.0f" % (i / 10 ** 6)) + " MB" for i in range_lst]
|
|
9
|
+
else:
|
|
10
|
+
return [str("%.0f" % (i / 1000)) + " KB" for i in range_lst]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def get_scale_lists(chr_sizes, chr_dic, factor, kb_mb):
|
|
14
|
+
"""
|
|
15
|
+
Returns lists for the scale marks of the circos plot, the multiplication factor needed for the shorter chromosome, and its name.
|
|
16
|
+
"""
|
|
17
|
+
# chr_sizes = {}
|
|
18
|
+
# with open(CHR_SIZES_PATH, "r") as f:
|
|
19
|
+
# lines = f.readlines()
|
|
20
|
+
# max_len = 0
|
|
21
|
+
# min_len = 10**9
|
|
22
|
+
# min_chr = ""
|
|
23
|
+
# for line in lines:
|
|
24
|
+
# chrom, chr_len = line.split()
|
|
25
|
+
# chr_sizes[chrom] = chr_len
|
|
26
|
+
# if int(chr_len) > max_len:
|
|
27
|
+
# max_len = int(chr_len)
|
|
28
|
+
# if int(chr_len) < min_len:
|
|
29
|
+
# min_len = int(chr_len)
|
|
30
|
+
# min_chr = chrom
|
|
31
|
+
max_chr = max(chr_sizes, key=chr_sizes.get)
|
|
32
|
+
min_chr = min(chr_sizes, key=chr_sizes.get)
|
|
33
|
+
|
|
34
|
+
max_len = chr_sizes[max_chr]
|
|
35
|
+
min_len = chr_sizes[min_chr]
|
|
36
|
+
|
|
37
|
+
multiply_factor = round(max_len/min_len)
|
|
38
|
+
|
|
39
|
+
ranges = {}
|
|
40
|
+
for chrom in chr_sizes.keys():
|
|
41
|
+
ranges[chrom] = list(range(0, int(chr_sizes[chrom]), 10 ** (len(str(chr_sizes[chrom])) - factor)))
|
|
42
|
+
|
|
43
|
+
chromosome = []
|
|
44
|
+
for i in ranges.keys():
|
|
45
|
+
chromosome += [chr_dic[i]] * len(ranges[i])
|
|
46
|
+
|
|
47
|
+
chrom_start = []
|
|
48
|
+
for i in ranges.keys():
|
|
49
|
+
if i == min_chr:
|
|
50
|
+
chrom_start += [i * multiply_factor for i in ranges[i]]
|
|
51
|
+
else:
|
|
52
|
+
chrom_start += ranges[i]
|
|
53
|
+
|
|
54
|
+
name = []
|
|
55
|
+
if kb_mb:
|
|
56
|
+
for chrom in chr_sizes.keys():
|
|
57
|
+
name += convert_to_kb_mb(ranges[chrom])
|
|
58
|
+
else:
|
|
59
|
+
for i in ranges.keys():
|
|
60
|
+
name += [str(k) for k in ranges[i]]
|
|
61
|
+
|
|
62
|
+
return chromosome, chrom_start, name, multiply_factor, min_chr
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def add_color(chimeras_df, chr1, chr2):
|
|
66
|
+
"""
|
|
67
|
+
Add a column of colors to the chimeras. Set different colors to chimeras from different genomes and to chimeras between genomes.
|
|
68
|
+
"""
|
|
69
|
+
chimeras_df["PlotColor"] = None
|
|
70
|
+
chimeras_df.loc[(chimeras_df["RNA1 chromosome"] == chr1) & (chimeras_df["RNA2 chromosome"] == chr1), "PlotColor"] = "gray48"
|
|
71
|
+
chimeras_df.loc[(chimeras_df["RNA1 chromosome"] == chr1) & (chimeras_df["RNA2 chromosome"] == chr2), "PlotColor"] = "blue"
|
|
72
|
+
chimeras_df.loc[(chimeras_df["RNA1 chromosome"] == chr2) & (chimeras_df["RNA2 chromosome"] == chr1), "PlotColor"] = "blue"
|
|
73
|
+
chimeras_df.loc[(chimeras_df["RNA1 chromosome"] == chr2) & (chimeras_df["RNA2 chromosome"] == chr2), "PlotColor"] = "red"
|
|
74
|
+
return chimeras_df
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def two_genomes_circos_plot_half_circle(circos_path, base_path, chr_sizes, chr_dic, present_chr=None, gene_list=None, experiments=None):
|
|
78
|
+
"""
|
|
79
|
+
Generates files required for creating circos plot of two genomes, each represented by half a circle.
|
|
80
|
+
Use the output files for circos_plot.R script.
|
|
81
|
+
:param gene_list: list of genes. If it's not None the circos plot will contain only the chimeras of the genes in the list.
|
|
82
|
+
"""
|
|
83
|
+
chromosome, chrom_start, gene, multiply_factor, chr_to_multiply = get_scale_lists(chr_sizes, chr_dic, 2, kb_mb=False)
|
|
84
|
+
scale_df = pd.DataFrame({"Chromosome":chromosome, "chromStart":chrom_start, "chromEnd":[i+1 for i in chrom_start],
|
|
85
|
+
"Gene":gene})
|
|
86
|
+
|
|
87
|
+
scale_df.to_csv(os.path.join(circos_path, "two_genomes_scale_half_circles.csv"), index=False)
|
|
88
|
+
|
|
89
|
+
chromosome, chrom_start, gene, _, _ = get_scale_lists(chr_sizes, chr_dic, 1, kb_mb=True)
|
|
90
|
+
|
|
91
|
+
scale_df = pd.DataFrame({"Chromosome":chromosome, "chromStart":chrom_start, "chromEnd":[i+1 for i in chrom_start],
|
|
92
|
+
"Gene":gene})
|
|
93
|
+
scale_df.to_csv(os.path.join(circos_path, "two_genomes_scale_numbers_half_circles.csv"), index=False)
|
|
94
|
+
|
|
95
|
+
RILseq_excel = pd.ExcelFile(os.path.join(base_path, "RILseq_unified_results.xlsx"))
|
|
96
|
+
|
|
97
|
+
if experiments is None:
|
|
98
|
+
experiments = RILseq_excel.sheet_names
|
|
99
|
+
for experiment in experiments:
|
|
100
|
+
chimeras_df = RILseq_excel.parse(experiment)
|
|
101
|
+
if gene_list is not None:
|
|
102
|
+
chimeras_df = chimeras_df[(chimeras_df["RNA1 name"].isin(gene_list)) | (chimeras_df["RNA2 name"].isin(gene_list))]
|
|
103
|
+
if present_chr:
|
|
104
|
+
chimeras_df = chimeras_df[(chimeras_df["RNA1 chromosome"] == present_chr) & (chimeras_df["RNA2 chromosome"] == present_chr)]
|
|
105
|
+
|
|
106
|
+
for i in ("1", "2"):
|
|
107
|
+
for j in [f"Start of RNA{i} first read", f"Start of RNA{i} last read"]:
|
|
108
|
+
# chimeras_df[j][chimeras_df[f"RNA{i} chromosome"] == chr_to_multiply] *= multiply_factor
|
|
109
|
+
chimeras_df.loc[chimeras_df[f"RNA{i} chromosome"] == chr_to_multiply,j] *= multiply_factor
|
|
110
|
+
chr1, chr2 = chr_sizes.keys()
|
|
111
|
+
chimeras_df = add_color(chimeras_df, chr1, chr2)
|
|
112
|
+
|
|
113
|
+
for genome, genome_name in chr_dic.items():
|
|
114
|
+
chimeras_df.loc[chimeras_df["RNA1 chromosome"] == genome, "RNA1 chromosome"] = genome_name
|
|
115
|
+
chimeras_df.loc[chimeras_df["RNA2 chromosome"] == genome, "RNA2 chromosome"] = genome_name
|
|
116
|
+
|
|
117
|
+
file_name = f"{experiment}_two_genomes_chimeras_half_circles"
|
|
118
|
+
if gene_list is not None:
|
|
119
|
+
genes = "_".join(gene_list)
|
|
120
|
+
file_name += genes
|
|
121
|
+
chimeras_df.to_csv(os.path.join(circos_path, f"{file_name}.csv"),
|
|
122
|
+
columns=["RNA1 chromosome", "Start of RNA1 first read", "Start of RNA1 last read", "RNA2 chromosome", "Start of RNA2 last read", "Start of RNA2 first read", "PlotColor"],
|
|
123
|
+
header=["Chromosome", "chromStart", "chromEnd", "Chromosome.1", "chromStart.1", "chromEnd.1", "PlotColor"], index=False)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def two_genomes_circos_plot_real_proportions(circos_path, base_path, chr_sizes, chr_dic, mark_step1, mark_step2, present_chr=None, gene_list=None):
|
|
127
|
+
"""
|
|
128
|
+
Generates files required for creating circos plot of two genomes. Use the output files for circos_plot.R script.
|
|
129
|
+
"""
|
|
130
|
+
chr1, chr2 = chr_sizes.keys()
|
|
131
|
+
chrI_range = list(range(0, chr_sizes[chr1], mark_step1))
|
|
132
|
+
chrII_range = list(range(0, chr_sizes[chr2], mark_step2))
|
|
133
|
+
scale_df = pd.DataFrame({"Chromosome":[chr_dic[chr1]]*len(chrI_range) + [chr_dic[chr2]]*len(chrII_range),
|
|
134
|
+
"chromStart":chrI_range + chrII_range,
|
|
135
|
+
"chromEnd":[i+1 for i in chrI_range] +[i+1 for i in chrII_range],
|
|
136
|
+
"Gene":convert_to_kb_mb(chrI_range+chrII_range)})
|
|
137
|
+
scale_df.to_csv(os.path.join(circos_path, "two_genomes_scale_real_proportions.csv"), index=False)
|
|
138
|
+
|
|
139
|
+
RILseq_excel = pd.ExcelFile(os.path.join(base_path, "RILseq_unified_results.xlsx"))
|
|
140
|
+
for experiment in RILseq_excel.sheet_names:
|
|
141
|
+
chimeras_df = RILseq_excel.parse(experiment)
|
|
142
|
+
|
|
143
|
+
if gene_list is not None:
|
|
144
|
+
chimeras_df = chimeras_df[(chimeras_df["RNA1 name"].isin(gene_list)) | (chimeras_df["RNA2 name"].isin(gene_list))]
|
|
145
|
+
if present_chr:
|
|
146
|
+
chimeras_df = chimeras_df[(chimeras_df["RNA1 chromosome"] == present_chr) & (chimeras_df["RNA2 chromosome"] == present_chr)]
|
|
147
|
+
|
|
148
|
+
chimeras_df = add_color(chimeras_df, chr1, chr2)
|
|
149
|
+
|
|
150
|
+
for genome, genome_name in chr_dic.items():
|
|
151
|
+
chimeras_df.loc[chimeras_df["RNA1 chromosome"] == genome, "RNA1 chromosome"] = genome_name
|
|
152
|
+
chimeras_df.loc[chimeras_df["RNA2 chromosome"] == genome, "RNA2 chromosome"] = genome_name
|
|
153
|
+
|
|
154
|
+
file_name = f"{experiment}_two_genomes_chimeras_real_proportions"
|
|
155
|
+
if gene_list is not None:
|
|
156
|
+
genes = "_".join(gene_list)
|
|
157
|
+
file_name += genes
|
|
158
|
+
chimeras_df.to_csv(os.path.join(circos_path, f"{file_name}.csv"),
|
|
159
|
+
columns=["RNA1 chromosome", "Start of RNA1 first read", "Start of RNA1 last read", "RNA2 chromosome", "Start of RNA2 last read", "Start of RNA2 first read", "PlotColor"],
|
|
160
|
+
header=["Chromosome", "chromStart", "chromEnd", "Chromosome.1", "chromStart.1", "chromEnd.1", "PlotColor"], index=False)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
|
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
from RILseq_analysis_package.generate_and_edit_RILseq_xslx import add_number_of_libraries
|
|
3
|
+
from RILseq_analysis_package.utils import load_config
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def main():
|
|
7
|
+
parser = argparse.ArgumentParser(description="Record for each chimera the number of libraries in which it appears, "
|
|
8
|
+
"and rename columns in the S-chimeras workbook.")
|
|
9
|
+
|
|
10
|
+
parser.add_argument("config", help="Path to the YAML configuration file.")
|
|
11
|
+
|
|
12
|
+
args = parser.parse_args()
|
|
13
|
+
config = load_config(args.config)
|
|
14
|
+
add_number_of_libraries(config["base_path"], config["experiments"], config["replicates"], config["chr_dic"])
|
|
15
|
+
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
from RILseq_analysis_package import circos_plot
|
|
3
|
+
from RILseq_analysis_package.utils import load_config
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
def main():
|
|
7
|
+
parser = argparse.ArgumentParser(description="Create a Circos plot showing RIL-seq chimeric interactions between two chromosomes.")
|
|
8
|
+
|
|
9
|
+
parser.add_argument("plot_type", choices=["two_genomes_half_circle", "two_genomes_real_proportions"], help="Type of circos plot to generate.")
|
|
10
|
+
parser.add_argument("config", help="Path to the YAML configuration file.")
|
|
11
|
+
parser.add_argument("--mark_step1", default=200000, type=int, help="Distance between scale marks on the first chromosome (default: 200000).")
|
|
12
|
+
parser.add_argument("--mark_step2", default=48500, type=int, help="Distance between scale marks on the second chromosome (default: 48500).")
|
|
13
|
+
parser.add_argument("--genes", default=None,
|
|
14
|
+
help="Plot only chimeras involving the specified genes. Separate gene names with underscores.")
|
|
15
|
+
parser.add_argument("--present_chr", default=None, help="Plot only chimeras involving the specified chromosome.")
|
|
16
|
+
parser.add_argument("--out_path", default=None,
|
|
17
|
+
help="Output directory for the Circos plot. If not provided, a 'circos_plots' directory is created under base_path.")
|
|
18
|
+
parser.add_argument("--experiments", default=None,
|
|
19
|
+
help="Comma-separated list of experiment names to plot. "
|
|
20
|
+
"Experiment names must match sheet names in RILseq_unified_results.xlsx.")
|
|
21
|
+
args = parser.parse_args()
|
|
22
|
+
config = load_config(args.config)
|
|
23
|
+
|
|
24
|
+
base_path = config["base_path"]
|
|
25
|
+
if args.out_path is None:
|
|
26
|
+
circos_path = os.path.join(base_path, "circos_plots")
|
|
27
|
+
else:
|
|
28
|
+
circos_path = args.out_path
|
|
29
|
+
|
|
30
|
+
if not os.path.exists(circos_path):
|
|
31
|
+
os.makedirs(circos_path)
|
|
32
|
+
|
|
33
|
+
if args.genes is not None:
|
|
34
|
+
genes_list = args.genes.split("_")
|
|
35
|
+
else:
|
|
36
|
+
genes_list = None
|
|
37
|
+
|
|
38
|
+
if args.experiments is not None:
|
|
39
|
+
experiments = args.experiments.split(",")
|
|
40
|
+
else:
|
|
41
|
+
experiments = None
|
|
42
|
+
|
|
43
|
+
if args.plot_type == "two_genomes_half_circle":
|
|
44
|
+
circos_plot.two_genomes_circos_plot_half_circle(circos_path, base_path, config["chr_len"], config["chr_dic"], args.present_chr, genes_list, experiments)
|
|
45
|
+
elif args.plot_type == "two_genomes_real_proportions":
|
|
46
|
+
circos_plot.two_genomes_circos_plot_real_proportions(circos_path, base_path, config["chr_len"], config["chr_dic"], args.mark_step1, args.mark_step2, args.present_chr, genes_list)
|
|
47
|
+
|
|
48
|
+
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
from RILseq_analysis_package.generate_and_edit_RILseq_xslx import merge_RILseq_results
|
|
3
|
+
from RILseq_analysis_package.utils import load_config
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def main():
|
|
7
|
+
parser = argparse.ArgumentParser(description="Merge RIL-seq results from multiple experiments into a unified Excel file.")
|
|
8
|
+
|
|
9
|
+
parser.add_argument("config", help="Path to the YAML configuration file.")
|
|
10
|
+
parser.add_argument("file_names",
|
|
11
|
+
help="path to file contains two columns. One is the name of the sig_interactions file names and "
|
|
12
|
+
"the other is the corresponding experiment names as appear in the yaml file. The two columns "
|
|
13
|
+
"are separated by a Tab.")
|
|
14
|
+
parser.add_argument("--no-annotations", dest="annotations", action="store_false", default=True,
|
|
15
|
+
help="Do not add RNA annotations to the merged results.")
|
|
16
|
+
|
|
17
|
+
args = parser.parse_args()
|
|
18
|
+
config = load_config(args.config)
|
|
19
|
+
merge_RILseq_results(config["base_path"], config["annotation_path"], config["rna_types_excel"], args.file_names, args.annotations)
|
|
20
|
+
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
from RILseq_analysis_package.utils import get_annotation, load_config
|
|
3
|
+
import argparse
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def filter_chr_genes(annotation_path, old_file_path, new_file, chromosome, sep="\t", names_col="Unnamed: 0", identifier="name"):
|
|
7
|
+
if identifier in ("name", "id"):
|
|
8
|
+
annotations_df = get_annotation(annotation_path, chromosome=chromosome, separate_id_name=True)
|
|
9
|
+
chr_genes = annotations_df[identifier].values.tolist()
|
|
10
|
+
else:
|
|
11
|
+
annotations_df = get_annotation(annotation_path, chromosome=chromosome, identifier=identifier)
|
|
12
|
+
chr_genes = annotations_df["identifier"].values.tolist()
|
|
13
|
+
|
|
14
|
+
old_file_df = pd.read_csv(old_file_path, sep=sep)
|
|
15
|
+
|
|
16
|
+
new_df = old_file_df[old_file_df[names_col].isin(chr_genes)]
|
|
17
|
+
new_df.to_csv(new_file, index=False, sep=sep)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def main():
|
|
21
|
+
parser = argparse.ArgumentParser(description="Filter a file and keep only genes belonging to a specified chromosome.")
|
|
22
|
+
parser.add_argument("input", help="Path to the input file.")
|
|
23
|
+
parser.add_argument("output", help="Path to the output file.")
|
|
24
|
+
parser.add_argument("chr", help="Chromosome to keep, according to the chromosome names in the annotation file.")
|
|
25
|
+
parser.add_argument("config", help="Path to the YAML configuration file.")
|
|
26
|
+
parser.add_argument("--sep", default="\t", help="Column separator used in the input and output files (default: tab).")
|
|
27
|
+
parser.add_argument("--names_col", default="Unnamed: 0", help="Name of the column containing gene names (default: there is no column name).")
|
|
28
|
+
parser.add_argument("--identifier", default="name", help="Type of gene identifier to use from the annotation file (default: name).")
|
|
29
|
+
|
|
30
|
+
args = parser.parse_args()
|
|
31
|
+
|
|
32
|
+
filter_chr_genes(load_config(args.config)["annotation_path"], args.input, args.output, args.chr, args.sep, args.names_col, args.identifier)
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import pandas as pd
|
|
3
|
+
from RILseq_analysis_package.utils import get_annotation, get_RNA_types
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def find_genomic_annotation(gene, sRNAs_list, tRNAs_list, all_genes_list):
|
|
7
|
+
if gene in sRNAs_list:
|
|
8
|
+
return "sRNA"
|
|
9
|
+
if gene in tRNAs_list:
|
|
10
|
+
return "tRNA"
|
|
11
|
+
if "3UTR" in gene:
|
|
12
|
+
return "3UTR"
|
|
13
|
+
if "5UTR" in gene:
|
|
14
|
+
return "5UTR"
|
|
15
|
+
if "AS" in gene:
|
|
16
|
+
return "AS"
|
|
17
|
+
if "IGR" in gene:
|
|
18
|
+
return "IGR"
|
|
19
|
+
if "IGT" in gene:
|
|
20
|
+
return "IGT"
|
|
21
|
+
if gene in all_genes_list:
|
|
22
|
+
return "CDS"
|
|
23
|
+
return "unknown"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def create_names_dic(file_names):
|
|
27
|
+
dic = {}
|
|
28
|
+
with open(file_names) as f:
|
|
29
|
+
line = f.readline()
|
|
30
|
+
while line:
|
|
31
|
+
line = line.split("\t")
|
|
32
|
+
dic[line[0]] = line[1].strip()
|
|
33
|
+
line = f.readline()
|
|
34
|
+
return dic
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def merge_RILseq_results(base_path, annotation_path, rna_types_excel, file_names, add_genomic_annotation=True):
|
|
38
|
+
names_dic = create_names_dic(file_names)
|
|
39
|
+
write_unified = False
|
|
40
|
+
write_single = False
|
|
41
|
+
with pd.ExcelWriter(os.path.join(base_path, 'RILseq_unified_results.xlsx')) as unified, pd.ExcelWriter(os.path.join(base_path, 'RILseq_single_results.xlsx')) as single:
|
|
42
|
+
for file in os.listdir(base_path):
|
|
43
|
+
if file.endswith("sig_interactions.txt"):
|
|
44
|
+
df = pd.read_csv(os.path.join(base_path, file), sep="\t")
|
|
45
|
+
if not df.empty:
|
|
46
|
+
if add_genomic_annotation:
|
|
47
|
+
sRNAs_list = get_RNA_types("sRNA", rna_types_excel)
|
|
48
|
+
tRNAs_list = get_RNA_types("tRNA", rna_types_excel)
|
|
49
|
+
genes_names = get_annotation(annotation_path, separate_id_name=True)["name"].values.tolist()
|
|
50
|
+
df["Genomic annotation of RNA1"] = df["RNA1 name"].apply(find_genomic_annotation, sRNAs_list=sRNAs_list, tRNAs_list=tRNAs_list, all_genes_list=genes_names)
|
|
51
|
+
df["Genomic annotation of RNA2"] = df["RNA2 name"].apply(find_genomic_annotation, sRNAs_list=sRNAs_list, tRNAs_list=tRNAs_list, all_genes_list=genes_names)
|
|
52
|
+
sheet_name = names_dic[file]
|
|
53
|
+
if file.startswith("unified"):
|
|
54
|
+
df.to_excel(unified, sheet_name=sheet_name, index=False)
|
|
55
|
+
write_unified = True
|
|
56
|
+
else:
|
|
57
|
+
df.to_excel(single, sheet_name=sheet_name, index=False)
|
|
58
|
+
write_single = True
|
|
59
|
+
if not write_unified:
|
|
60
|
+
pd.DataFrame().to_excel(unified, sheet_name="Empty", index=False)
|
|
61
|
+
if not write_single:
|
|
62
|
+
pd.DataFrame().to_excel(single, sheet_name="Empty", index=False)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def find_number_of_libraries_helper(name1, name2, start1, end1, start2, end2, chr1, chr2, strand1, strand2, df):
|
|
66
|
+
cur1 = df[(df["RNA1 name"] == name1) & (df["RNA2 name"] == name2) & (df["RNA1 strand"] == strand1) & (df["RNA2 strand"] == strand2) & (df["RNA1 chromosome"] == chr1) & (df["RNA2 chromosome"] == chr2)]
|
|
67
|
+
cur1 = cur1[~((cur1["Start of RNA1 first read"] > end1) | (cur1["Start of RNA1 last read"] < start1))]
|
|
68
|
+
cur1 = cur1[~((cur1["Start of RNA2 last read"] > end2) | (cur1["Start of RNA2 first read"] < start2))]
|
|
69
|
+
return cur1.shape[0]
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def find_number_of_libraries(unify_chimera, singles):
|
|
73
|
+
name1, name2, start1, end1, start2, end2, chr1, chr2, strand1, strand2 = unify_chimera[["RNA1 name", "RNA2 name", "Start of RNA1 first read", "Start of RNA1 last read", "Start of RNA2 last read", "Start of RNA2 first read", "RNA1 chromosome", "RNA2 chromosome", "RNA1 strand", "RNA2 strand"]]
|
|
74
|
+
|
|
75
|
+
counter = 0
|
|
76
|
+
for single in singles:
|
|
77
|
+
single = single.astype({"Start of RNA1 first read":int, "Start of RNA2 first read":int, "Start of RNA1 last read":int, "Start of RNA2 last read":int})
|
|
78
|
+
amount1 = find_number_of_libraries_helper(name1, name2, start1, end1, start2, end2, chr1, chr2, strand1, strand2, single)
|
|
79
|
+
amount2 = find_number_of_libraries_helper(name2, name1, start2, end2, start1, end1, chr2, chr1, strand2, strand1, single)
|
|
80
|
+
if amount1 + amount2 != 0:
|
|
81
|
+
counter += 1
|
|
82
|
+
|
|
83
|
+
if counter == 0:
|
|
84
|
+
return "U"
|
|
85
|
+
return counter
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def add_number_of_libraries(base_path, experiments, replicates, chr_dic):
|
|
89
|
+
# new = pd.ExcelWriter(os.path.join(base_path, 'RILseq_unified_results_with_number_of_libraries.xlsx'))
|
|
90
|
+
single_results_excel = pd.ExcelFile(os.path.join(base_path, "RILseq_single_results.xlsx"))
|
|
91
|
+
with pd.ExcelWriter(os.path.join(base_path, 'RILseq_unified_results_with_number_of_libraries.xlsx')) as new:
|
|
92
|
+
for experiment in experiments:
|
|
93
|
+
singles = []
|
|
94
|
+
for i in replicates:
|
|
95
|
+
replicate_name = f"{experiment + i}_S_chimeras"
|
|
96
|
+
if replicate_name in single_results_excel.sheet_names:
|
|
97
|
+
single1 = single_results_excel.parse(replicate_name)
|
|
98
|
+
singles.append(single1)
|
|
99
|
+
|
|
100
|
+
unify_df = pd.read_excel(os.path.join(base_path, "RILseq_unified_results.xlsx"), sheet_name=experiment)
|
|
101
|
+
|
|
102
|
+
unify_df["# of libraries"] = unify_df.apply(find_number_of_libraries, singles=singles, axis=1)
|
|
103
|
+
unify_df = unify_df[["RNA1 name", "RNA2 name", "interactions", "# of libraries", "Normalized Odds Ratio (NOR)", "odds ratio", "Fisher's exact test p-value", "Genomic annotation of RNA1", "Genomic annotation of RNA2", "RNA1 description", "RNA2 description", "RNA1 chromosome", "Start of RNA1 first read", "Start of RNA1 last read", "RNA1 strand", "RNA2 chromosome", "Start of RNA2 last read", "Start of RNA2 first read", "RNA2 strand", "other interactions of RNA1", "other interactions of RNA2", "total other interactions", "total RNA reads1", "total RNA reads2", "lib norm IP RNA1", "lib norm IP RNA2", "lib norm total RNA1", "lib norm total RNA2", "IP/total ratio1", "IP/total ratio2", "RNA1 EcoCyc ID", "RNA2 EcoCyc ID"]]
|
|
104
|
+
unify_df.rename(columns={"interactions":"# of chimeric fragments", "Normalized Odds Ratio (NOR)":"Normalized Odds Ratio", "odds ratio":"Odds Ratio",
|
|
105
|
+
"Start of RNA1 first read":"RNA1 from", "Start of RNA1 last read":"RNA1 to", "Start of RNA2 last read":"RNA2 from",
|
|
106
|
+
"Start of RNA2 first read":"RNA2 to", "other interactions of RNA1":"other fragments of RNA1", "other interactions of RNA2":"other fragments of RNA2",
|
|
107
|
+
"total other interactions":"Total other fragments", "total RNA reads1":"RNA1 in total RNA (# of reads)",
|
|
108
|
+
"total RNA reads2":"RNA2 in total RNA (# of reads)"}, inplace=True)
|
|
109
|
+
unify_df["RNA1 chromosome"] = unify_df["RNA1 chromosome"].apply(lambda x: chr_dic[x])
|
|
110
|
+
unify_df["RNA2 chromosome"] = unify_df["RNA2 chromosome"].apply(lambda x: chr_dic[x])
|
|
111
|
+
unify_df.to_excel(new, sheet_name=experiment, index=False)
|
|
112
|
+
|
|
113
|
+
# new.save()
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
# if __name__ == '__main__':
|
|
117
|
+
# merge_RILseq_results(rf"{BASE_PATH}\RILSeq\results", add_genomic_annotation=True)
|
|
118
|
+
# add_number_of_libraries(rf"{BASE_PATH}\RILSeq\results", get_experiments())
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
from RILseq_analysis_package.utils import *
|
|
2
|
+
import argparse
|
|
3
|
+
import pandas as pd
|
|
4
|
+
import numpy as np
|
|
5
|
+
import matplotlib.pylab as plt
|
|
6
|
+
import matplotlib
|
|
7
|
+
import os
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def find_highest_sRNAs(df, sRNAs_amount):
|
|
11
|
+
"""
|
|
12
|
+
Returns a list of the sRNAs with the highest percentages.
|
|
13
|
+
:param df: a data frame of the percentages of each sRNA in each condition.
|
|
14
|
+
"""
|
|
15
|
+
max_values = df.max().sort_values(ascending=False)
|
|
16
|
+
return max_values.head(sRNAs_amount).index.tolist()
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def get_counts_table(sRNAs, path, experiments, replicates):
|
|
20
|
+
"""
|
|
21
|
+
Returns a data frame of the number of reads of each sRNA for each condition. The number is the sum of the read
|
|
22
|
+
numbers at the different replicates.
|
|
23
|
+
:param sRNAs: a list of sRNAs names.
|
|
24
|
+
:param experiment: RILseq or RNAseq
|
|
25
|
+
"""
|
|
26
|
+
df = pd.read_csv(path, sep="\t")
|
|
27
|
+
names_dic = {i:i.replace("_cutadapt_bwa", "") for i in df.columns}
|
|
28
|
+
names_dic["Unnamed: 0"] = "gene"
|
|
29
|
+
df = df.rename(columns=names_dic)
|
|
30
|
+
|
|
31
|
+
df = df[df["gene"].isin(sRNAs)]
|
|
32
|
+
df.index = df["gene"].values
|
|
33
|
+
relevant_cols = []
|
|
34
|
+
for condition in experiments:
|
|
35
|
+
df[condition] = df[[condition + i for i in replicates]].sum(axis=1)
|
|
36
|
+
relevant_cols.append(condition)
|
|
37
|
+
|
|
38
|
+
return df[relevant_cols]
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def convert_to_percent(df):
|
|
42
|
+
row_sum = df.sum(axis=1)
|
|
43
|
+
return df.div(row_sum/100, axis=0)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def rename(rna):
|
|
47
|
+
lst = list(rna)
|
|
48
|
+
lst[0] = rna[0].upper()
|
|
49
|
+
return "".join(lst)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def get_colors(genes_list, genes_colors_dic):
|
|
53
|
+
colors = plt.cm.tab20c.colors + plt.cm.tab20b.colors
|
|
54
|
+
res = []
|
|
55
|
+
for gene in genes_list:
|
|
56
|
+
if gene in genes_colors_dic.keys():
|
|
57
|
+
res.append(genes_colors_dic[gene])
|
|
58
|
+
else:
|
|
59
|
+
color = colors[len(genes_colors_dic)]
|
|
60
|
+
res.append(color)
|
|
61
|
+
genes_colors_dic[gene] = color
|
|
62
|
+
return res, genes_colors_dic
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def chimeras_bar_plot(sRNAs_amount, sRNAs, experiments, replicates, base_path, only_between_chr_chimeras, rna_seq_counts):
|
|
66
|
+
"""
|
|
67
|
+
Creates bar plots of the percentages of the sRNAs for each condition according to the number of chimers, chimeric fragments,
|
|
68
|
+
RNAseq reads and RILSeq reads. The 15 sRNAs with the highest percentages are colored, the other are gray.
|
|
69
|
+
:param sRNAs: a list of the sRNAs names
|
|
70
|
+
:param only_between_chr_chimeras: if True, create the plot according to the between-chromosome chimeras.
|
|
71
|
+
"""
|
|
72
|
+
experiments = [i for i in experiments if "wt" not in i]
|
|
73
|
+
df_chimeras_amount = pd.DataFrame(np.zeros((len(experiments), len(sRNAs))), columns=sRNAs, index=experiments)
|
|
74
|
+
df_fragments_amount = pd.DataFrame(np.zeros((len(experiments), len(sRNAs))), columns=sRNAs, index=experiments)
|
|
75
|
+
df_reads_amount_RILseq = pd.DataFrame(np.zeros((len(experiments), len(sRNAs))), columns=sRNAs, index=experiments)
|
|
76
|
+
counts_table_RILseq = get_counts_table(sRNAs, os.path.join(base_path, "all_counts_table.txt"), experiments, replicates)
|
|
77
|
+
if rna_seq_counts is not None:
|
|
78
|
+
df_reads_amount_RNAseq = pd.DataFrame(np.zeros((len(experiments), len(sRNAs))), columns=sRNAs, index=experiments)
|
|
79
|
+
counts_table_RNAseq = get_counts_table(sRNAs, rna_seq_counts, experiments, replicates)
|
|
80
|
+
for experiment in experiments:
|
|
81
|
+
chimeras_df = pd.read_excel(os.path.join(base_path, r"RILseq_unified_results.xlsx"), sheet_name=experiment)
|
|
82
|
+
if only_between_chr_chimeras:
|
|
83
|
+
chimeras_df = chimeras_df[chimeras_df["RNA1 chromosome"] != chimeras_df["RNA2 chromosome"]]
|
|
84
|
+
# chromosomes = list(chr_dic.keys())
|
|
85
|
+
# chimeras_df = chimeras_df[((chimeras_df["RNA1 chromosome"] == chromosomes[0]) & (chimeras_df["RNA2 chromosome"] == chromosomes[1])) |
|
|
86
|
+
# ((chimeras_df["RNA1 chromosome"] == chromosomes[1]) & (chimeras_df["RNA2 chromosome"] == chromosomes[0]))]
|
|
87
|
+
for rna in sRNAs:
|
|
88
|
+
srna_chimeras = chimeras_df[(chimeras_df["RNA1 name"] == rna) | (chimeras_df["RNA2 name"] == rna)]
|
|
89
|
+
df_chimeras_amount.at[experiment, rna] = srna_chimeras.shape[0]
|
|
90
|
+
df_fragments_amount.at[experiment, rna] = srna_chimeras["interactions"].sum()
|
|
91
|
+
df_reads_amount_RILseq.at[experiment, rna] = counts_table_RILseq[experiment][rna]
|
|
92
|
+
if rna_seq_counts is not None:
|
|
93
|
+
df_reads_amount_RNAseq.at[experiment, rna] = counts_table_RNAseq[experiment][rna]
|
|
94
|
+
dic = {"chimeras":df_chimeras_amount, "fragments":df_fragments_amount, "RILseq_reads":df_reads_amount_RILseq}
|
|
95
|
+
if rna_seq_counts is not None:
|
|
96
|
+
dic["RNAseq_reads"] = df_reads_amount_RNAseq
|
|
97
|
+
genes_colors_dic = {"other sRNAs":"gray"}
|
|
98
|
+
for name, df in dic.items():
|
|
99
|
+
df = convert_to_percent(df)
|
|
100
|
+
fig = plt.figure()
|
|
101
|
+
relevant_sRNAs = find_highest_sRNAs(df, sRNAs_amount)
|
|
102
|
+
other_sRNAs = [i for i in sRNAs if i not in relevant_sRNAs]
|
|
103
|
+
df["other sRNAs"] = df[other_sRNAs].sum(axis=1)
|
|
104
|
+
# df = df.rename(index=experiments_dic)
|
|
105
|
+
colors, genes_colors_dic = get_colors(relevant_sRNAs + ["other sRNAs"], genes_colors_dic)
|
|
106
|
+
# if only_between_chr_chimeras and EXPERIMENT == "lambda":
|
|
107
|
+
# if name in ("chimeras", "fragments"):
|
|
108
|
+
# df = df.loc[["infected 30", "infected 60"]]
|
|
109
|
+
ax = df[relevant_sRNAs + ["other sRNAs"]].plot.bar(stacked=True, color=colors)
|
|
110
|
+
handles, labels = ax.get_legend_handles_labels()
|
|
111
|
+
labels = [rename(i) for i in labels]
|
|
112
|
+
plt.legend(handles[::-1], labels[::-1], loc='center left', bbox_to_anchor=(1, 0.5))
|
|
113
|
+
plt.xticks(rotation=0)
|
|
114
|
+
ax.get_yaxis().set_major_formatter(matplotlib.ticker.FuncFormatter(lambda x, p: format(int(x))))
|
|
115
|
+
plt.ylabel(f"{name} %")
|
|
116
|
+
fig_name = f"sRNAs_{name}_percent"
|
|
117
|
+
if only_between_chr_chimeras:
|
|
118
|
+
fig_name = f"{fig_name}_only_between_chr_chimeras"
|
|
119
|
+
plt.savefig(os.path.join(base_path, f"{fig_name}.png"), bbox_inches='tight')
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def main():
|
|
123
|
+
parser = argparse.ArgumentParser(description="Create stacked bar plots showing the percentage of sRNAs "
|
|
124
|
+
"among RIL-seq chimeras, fragments and reads.")
|
|
125
|
+
parser.add_argument("config", help="Path to the YAML configuration file.")
|
|
126
|
+
parser.add_argument("sRNAs_number", type=int,
|
|
127
|
+
help="Number of the most abundant sRNAs to show individually in the plots. "
|
|
128
|
+
"All remaining sRNAs are grouped as 'other sRNAs'.")
|
|
129
|
+
parser.add_argument("--RNAseq_counts", default=None,
|
|
130
|
+
help="Path to an RNA-seq counts table. If provided, an additional graph showing sRNA percentages "
|
|
131
|
+
"based on the RNA-seq results will be generated.")
|
|
132
|
+
|
|
133
|
+
args = parser.parse_args()
|
|
134
|
+
config = load_config(args.config)
|
|
135
|
+
sRNAs = get_RNA_types("sRNA", config["rna_types_excel"])
|
|
136
|
+
all_genes = get_annotation(config["annotation_path"], separate_id_name=True)["name"].values.tolist()
|
|
137
|
+
sRNAs = [i for i in sRNAs if i in all_genes]
|
|
138
|
+
chimeras_bar_plot(args.sRNAs_number, sRNAs, config["experiments"], config["replicates"], config["base_path"], True, args.RNAseq_counts)
|
|
139
|
+
chimeras_bar_plot(args.sRNAs_number, sRNAs, config["experiments"], config["replicates"], config["base_path"], False, args.RNAseq_counts)
|
|
140
|
+
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
import yaml
|
|
3
|
+
# from RILseq_analysis_package.defaults import *
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def load_config(path):
|
|
7
|
+
with open(path, "r") as f:
|
|
8
|
+
return yaml.safe_load(f)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_gene_identifier(gene_id, identifier):
|
|
12
|
+
"""
|
|
13
|
+
For the given gene_id, returns the value of the given identifier.
|
|
14
|
+
"""
|
|
15
|
+
split_id = gene_id.split(";")
|
|
16
|
+
if identifier in gene_id:
|
|
17
|
+
for i in split_id:
|
|
18
|
+
if identifier in i:
|
|
19
|
+
if i.startswith(" "):
|
|
20
|
+
return i.split(" ")[2].replace("\"", "")
|
|
21
|
+
return i.split(" ")[1].replace("\"", "")
|
|
22
|
+
id_ = split_id[0].split(" ")
|
|
23
|
+
return id_[1].replace("\"", "")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def get_annotation(annotation_path, chromosome=None, separate_id_name=False, identifier=None):
|
|
27
|
+
"""
|
|
28
|
+
Returns a df of the annotations according to ANNOTATION_FILE.
|
|
29
|
+
separate_id_name: if True add a column of name, the id column will contain only the id. Use when there are two
|
|
30
|
+
identifiers - id and name.
|
|
31
|
+
identifier: add a column "identifier" which contains the values of the give identifier. Use when there are other
|
|
32
|
+
identifier (not id and name).
|
|
33
|
+
"""
|
|
34
|
+
cols_names = ["chr", "EcoCyc", "exon", "start", "end", ".1", "strand", ".2", "id"]
|
|
35
|
+
df = pd.read_csv(annotation_path, sep="\t", names=cols_names)
|
|
36
|
+
if chromosome:
|
|
37
|
+
if type(chromosome) is str:
|
|
38
|
+
df = df[df["chr"] == chromosome]
|
|
39
|
+
if type(chromosome) is list:
|
|
40
|
+
df = df[df["chr"].isin(chromosome)]
|
|
41
|
+
if separate_id_name:
|
|
42
|
+
df["name"] = df["id"].apply(lambda x: x.split()[3].replace(";", "").replace("\"", ""))
|
|
43
|
+
df["id"] = df["id"].apply(lambda x: x.split()[1].replace(";", "").replace("\"", ""))
|
|
44
|
+
if identifier:
|
|
45
|
+
df["identifier"] = df["id"].apply(get_gene_identifier, args=(identifier,))
|
|
46
|
+
return df
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def get_only_id(gene):
|
|
50
|
+
return gene.split()[1].replace(";", "").replace("\"", "")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def get_only_name(gene):
|
|
54
|
+
return gene.split()[3].replace(";", "").replace("\"", "")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def get_RNA_types(RNA_type, rna_types_excel):
|
|
58
|
+
RNAs = pd.read_excel(rna_types_excel, sheet_name=RNA_type)
|
|
59
|
+
RNAs = RNAs["Name"].values.tolist()
|
|
60
|
+
return RNAs
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def remove_UTR(df):
|
|
64
|
+
df["RNA1 name"] = df["RNA1 name"].apply(lambda x: x.split(".EST3UTR")[0].split(".EST5UTR")[0].split(".5UTR")[0].split(".3UTR")[0])
|
|
65
|
+
df["RNA2 name"] = df["RNA2 name"].apply(lambda x: x.split(".EST3UTR")[0].split(".EST5UTR")[0].split(".5UTR")[0].split(".3UTR")[0])
|
|
66
|
+
return df
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def get_gene_chr(gene, annotation_df):
|
|
70
|
+
return annotation_df["chr"][annotation_df["name"] == gene]
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def get_E_coli_lambda_experiments(with_wt):
|
|
74
|
+
res = []
|
|
75
|
+
for time in ("30", "60"):
|
|
76
|
+
for experiment in ("Hfq_", "Hfq_lambda_", "wt_lambda_", "wt"):
|
|
77
|
+
if not with_wt and "wt" in experiment:
|
|
78
|
+
continue
|
|
79
|
+
if "wt" in experiment:
|
|
80
|
+
if time == "60":
|
|
81
|
+
continue
|
|
82
|
+
res.append(experiment + time)
|
|
83
|
+
return res
|
|
84
|
+
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
RILseq_analysis_package/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
RILseq_analysis_package/annotations_graphs.py,sha256=uO48iyR_hqwm-xkam3wt23ZiSHxT3NabukMi8_jUwOQ,8998
|
|
3
|
+
RILseq_analysis_package/chimeras_venn_diagram.py,sha256=KTwIyVsb0Dzak7sMBgn3f58Z1ZJLDW1ysp5Qmh2bLxk,3452
|
|
4
|
+
RILseq_analysis_package/circos_plot.py,sha256=qjfg20us7H5fim50pn4uKGfIPweEvyDQea-I7XknOWA,8220
|
|
5
|
+
RILseq_analysis_package/extract_genes_by_chr.py,sha256=_GOopsdw1xq-NL6UUHryBG5IXrxsIUvh9gShU8Q4IDE,1869
|
|
6
|
+
RILseq_analysis_package/generate_and_edit_RILseq_xslx.py,sha256=EYwfwf0WtU9RrWHdDvj2sd_cNoR3fdn694PniNK6Nwk,7189
|
|
7
|
+
RILseq_analysis_package/sRNAs_percent.py,sha256=I6trQXA-rdgC7k9PMNli3JtOgUQtJkJuuXOmXrYDits,7337
|
|
8
|
+
RILseq_analysis_package/utils.py,sha256=j5Qw1OQgzCqjfiTFzLQ0rp49NNm9XxNfwX1jsXWkKnA,3053
|
|
9
|
+
RILseq_analysis_package/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
10
|
+
RILseq_analysis_package/cli/add_number_of_libraries_cli.py,sha256=nTzdTF1J8Kov3zH7Pdo6phdOjNqc6_gENpkYSPF8V94,673
|
|
11
|
+
RILseq_analysis_package/cli/circos_plot_cli.py,sha256=6678Zzqug4zcgbc7s9WSt-cgPFpWbo13DfvAIVBolPw,2581
|
|
12
|
+
RILseq_analysis_package/cli/merge_results_cli.py,sha256=NxnccfPT7oKj_Z2iR25yxpgdwaHpJ8hwmB7R_zHfyf8,1126
|
|
13
|
+
rilseq_analysis-1.0.0.dist-info/METADATA,sha256=Tq9YOQEl9u-j0aBAiWVDpqiqqIMwIuK7ZU2tzqaWk4o,228
|
|
14
|
+
rilseq_analysis-1.0.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
|
|
15
|
+
rilseq_analysis-1.0.0.dist-info/entry_points.txt,sha256=PjXflPsVqyAJ7xhp8typhQhLuXfzrAvwh52VsUXkemA,485
|
|
16
|
+
rilseq_analysis-1.0.0.dist-info/top_level.txt,sha256=jYZHXO5yozHSW56muTG8TMzeRX8A_X-pGmsoicCWuuE,24
|
|
17
|
+
rilseq_analysis-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
[console_scripts]
|
|
2
|
+
annotations-graphs = RILseq_analysis_package.annotations_graphs:main
|
|
3
|
+
chimeras-venn = RILseq_analysis_package.chimeras_venn_diagram:main
|
|
4
|
+
circos-plot = RILseq_analysis_package.cli.circos_plot_cli:main
|
|
5
|
+
filter-genes = RILseq_analysis_package.extract_genes_by_chr:main
|
|
6
|
+
libraries-num = RILseq_analysis_package.cli.add_number_of_libraries_cli:main
|
|
7
|
+
merge-results = RILseq_analysis_package.cli.merge_results_cli:main
|
|
8
|
+
sRNAs-percent = RILseq_analysis_package.sRNAs_percent:main
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
RILseq_analysis_package
|