RNAvigate 1.1.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.
- rnavigate/__init__.py +63 -0
- rnavigate/analysis/__init__.py +18 -0
- rnavigate/analysis/auroc.py +198 -0
- rnavigate/analysis/check_sequence.py +171 -0
- rnavigate/analysis/deltashape.py +361 -0
- rnavigate/analysis/fragmapper.py +463 -0
- rnavigate/analysis/logcompare.py +239 -0
- rnavigate/analysis/lowss.py +311 -0
- rnavigate/data/__init__.py +78 -0
- rnavigate/data/alignments.py +927 -0
- rnavigate/data/annotation.py +456 -0
- rnavigate/data/colors.py +154 -0
- rnavigate/data/data.py +620 -0
- rnavigate/data/interactions.py +1750 -0
- rnavigate/data/pdb.py +271 -0
- rnavigate/data/profile.py +1080 -0
- rnavigate/data/secondary_structure.py +1433 -0
- rnavigate/data_loading.py +214 -0
- rnavigate/examples/__init__.py +178 -0
- rnavigate/examples/rmrp_data/__init__.py +0 -0
- rnavigate/examples/rnasep_data/__init__.py +0 -0
- rnavigate/examples/rrna_fragmap_data/__init__.py +0 -0
- rnavigate/examples/tpp_data/__init__.py +0 -0
- rnavigate/helper_functions.py +223 -0
- rnavigate/plots/__init__.py +81 -0
- rnavigate/plots/alignment.py +115 -0
- rnavigate/plots/arc.py +350 -0
- rnavigate/plots/circle.py +221 -0
- rnavigate/plots/disthist.py +209 -0
- rnavigate/plots/functions/__init__.py +55 -0
- rnavigate/plots/functions/circle.py +74 -0
- rnavigate/plots/functions/functions.py +337 -0
- rnavigate/plots/functions/ss.py +312 -0
- rnavigate/plots/functions/tracks.py +227 -0
- rnavigate/plots/heatmap.py +245 -0
- rnavigate/plots/linreg.py +284 -0
- rnavigate/plots/mol.py +280 -0
- rnavigate/plots/ntdist.py +131 -0
- rnavigate/plots/plots.py +348 -0
- rnavigate/plots/profile.py +253 -0
- rnavigate/plots/qc.py +262 -0
- rnavigate/plots/roc.py +181 -0
- rnavigate/plots/skyline.py +287 -0
- rnavigate/plots/sm.py +416 -0
- rnavigate/plots/ss.py +180 -0
- rnavigate/plotting_functions.py +1622 -0
- rnavigate/rnavigate.py +363 -0
- rnavigate/styles.py +247 -0
- rnavigate/transcriptomics/__init__.py +20 -0
- rnavigate/transcriptomics/bed.py +185 -0
- rnavigate/transcriptomics/eclip.py +262 -0
- rnavigate/transcriptomics/transcriptome.py +343 -0
- rnavigate-1.1.0.dist-info/METADATA +75 -0
- rnavigate-1.1.0.dist-info/RECORD +57 -0
- rnavigate-1.1.0.dist-info/WHEEL +5 -0
- rnavigate-1.1.0.dist-info/licenses/LICENSE +21 -0
- rnavigate-1.1.0.dist-info/top_level.txt +1 -0
rnavigate/__init__.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"""RNAvigate
|
|
2
|
+
|
|
3
|
+
RNA visualization and graphical analysis toolset
|
|
4
|
+
|
|
5
|
+
A Jupyter-compatible toolset for visually exploring RNA structure and chemical
|
|
6
|
+
probing data.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from rnavigate.rnavigate import Sample
|
|
10
|
+
from rnavigate.plotting_functions import (
|
|
11
|
+
plot_options,
|
|
12
|
+
plot_alignment,
|
|
13
|
+
plot_arcs,
|
|
14
|
+
plot_arcs_compare,
|
|
15
|
+
plot_circle,
|
|
16
|
+
plot_disthist,
|
|
17
|
+
plot_heatmap,
|
|
18
|
+
plot_linreg,
|
|
19
|
+
plot_mol,
|
|
20
|
+
plot_ntdist,
|
|
21
|
+
plot_profile,
|
|
22
|
+
plot_qc,
|
|
23
|
+
plot_roc,
|
|
24
|
+
plot_shapemapper,
|
|
25
|
+
plot_skyline,
|
|
26
|
+
plot_ss,
|
|
27
|
+
)
|
|
28
|
+
from rnavigate import analysis
|
|
29
|
+
from rnavigate import data
|
|
30
|
+
from rnavigate import plots
|
|
31
|
+
from rnavigate import styles
|
|
32
|
+
from rnavigate import transcriptomics
|
|
33
|
+
|
|
34
|
+
__version__ = "1.0.0"
|
|
35
|
+
__author__ = "Patrick S. Irving"
|
|
36
|
+
__email__ = "psirving@email.unc.edu"
|
|
37
|
+
|
|
38
|
+
__all__ = [
|
|
39
|
+
"Sample",
|
|
40
|
+
# plotting functions
|
|
41
|
+
"plot_options",
|
|
42
|
+
"plot_alignment",
|
|
43
|
+
"plot_arcs",
|
|
44
|
+
"plot_arcs_compare",
|
|
45
|
+
"plot_circle",
|
|
46
|
+
"plot_disthist",
|
|
47
|
+
"plot_heatmap",
|
|
48
|
+
"plot_linreg",
|
|
49
|
+
"plot_mol",
|
|
50
|
+
"plot_ntdist",
|
|
51
|
+
"plot_profile",
|
|
52
|
+
"plot_qc",
|
|
53
|
+
"plot_roc",
|
|
54
|
+
"plot_shapemapper",
|
|
55
|
+
"plot_skyline",
|
|
56
|
+
"plot_ss",
|
|
57
|
+
# modules
|
|
58
|
+
"analysis",
|
|
59
|
+
"data",
|
|
60
|
+
"plots",
|
|
61
|
+
"styles",
|
|
62
|
+
"transcriptomics",
|
|
63
|
+
]
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from rnavigate.analysis.logcompare import LogCompare
|
|
2
|
+
from rnavigate.analysis.lowss import LowSS
|
|
3
|
+
from rnavigate.analysis.deltashape import DeltaSHAPE, DeltaSHAPEProfile
|
|
4
|
+
from rnavigate.analysis.auroc import WindowedAUROC
|
|
5
|
+
from rnavigate.analysis.fragmapper import FragMaP, Fragmapper, FragmapperReplicates
|
|
6
|
+
from rnavigate.analysis.check_sequence import SequenceChecker
|
|
7
|
+
|
|
8
|
+
__all__ = [
|
|
9
|
+
"LogCompare",
|
|
10
|
+
"LowSS",
|
|
11
|
+
"DeltaSHAPE",
|
|
12
|
+
"DeltaSHAPEProfile",
|
|
13
|
+
"WindowedAUROC",
|
|
14
|
+
"FragMaP",
|
|
15
|
+
"Fragmapper",
|
|
16
|
+
"FragmapperReplicates",
|
|
17
|
+
"SequenceChecker",
|
|
18
|
+
]
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
"""Windowed AUROC assesses agreement between reactivities and base-pairing."""
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
from sklearn.metrics import auc, roc_curve
|
|
5
|
+
|
|
6
|
+
from rnavigate import plots
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# TODO: refactor as subclass of rnavigate.Sample
|
|
10
|
+
class WindowedAUROC:
|
|
11
|
+
"""Compute and display windowed AUROC analysis.
|
|
12
|
+
|
|
13
|
+
This analysis computes the ROC curve over a sliding window for the
|
|
14
|
+
performance of per-nucleotide data (usually SHAPE-MaP or DMS-MaP Normalized
|
|
15
|
+
reactivity) in predicting the base-pairing status of each nucleotide. The
|
|
16
|
+
area under this curve (AUROC) is displayed compared to the median across
|
|
17
|
+
the RNA. Below, an arc plot displays the secondary structure and
|
|
18
|
+
per-nucleotide profile.
|
|
19
|
+
|
|
20
|
+
AUROC values (should) range from 0.5 (no predictive power) to 1.0
|
|
21
|
+
(perfect predictive power). A value of 0.5 indicates that the reactivity
|
|
22
|
+
profile does not fit the structure prediction well. These regions are good
|
|
23
|
+
candidates for further investigation with ensemble deconvolution.
|
|
24
|
+
|
|
25
|
+
References
|
|
26
|
+
----------
|
|
27
|
+
Lan, T.C.T., Allan, M.F., Malsick, L.E. et al. Secondary structural
|
|
28
|
+
ensembles of the SARS-CoV-2 RNA genome in infected cells. Nat Commun
|
|
29
|
+
13, 1128 (2022). https://doi.org/10.1038/s41467-022-28603-2
|
|
30
|
+
|
|
31
|
+
Methods
|
|
32
|
+
-------
|
|
33
|
+
__init__: Computes the AUROC array and AUROC median.
|
|
34
|
+
plot_auroc: Displays the AUROC analysis over the given region.
|
|
35
|
+
Returns Plot object
|
|
36
|
+
|
|
37
|
+
Attributes
|
|
38
|
+
----------
|
|
39
|
+
sample : rnavigate.Sample
|
|
40
|
+
sample to retrieve profile and secondary structure
|
|
41
|
+
structure : str
|
|
42
|
+
Data keyword of sample pointing to secondary structure
|
|
43
|
+
e.g. sample.data[structure]
|
|
44
|
+
profile : str
|
|
45
|
+
Data keyword of sample pointing to profile
|
|
46
|
+
e.g. sample.data[profile]
|
|
47
|
+
sequence : the sequence string of sample.data[structure]
|
|
48
|
+
window: the size of the windows
|
|
49
|
+
nt_length: the length of sequence string
|
|
50
|
+
auroc: the auroc numpy array, length = nt_length, padded with np.nan
|
|
51
|
+
median_auroc: the median of the auroc array
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
def __init__(
|
|
55
|
+
self,
|
|
56
|
+
sample,
|
|
57
|
+
window=81,
|
|
58
|
+
profile="default_profile",
|
|
59
|
+
structure="default_structure",
|
|
60
|
+
):
|
|
61
|
+
"""Compute the AUROC for all windows. AUROC is a measure of how well a
|
|
62
|
+
reactivity profile predicts paired vs. unpaired nucleotide status.
|
|
63
|
+
|
|
64
|
+
Parameters
|
|
65
|
+
----------
|
|
66
|
+
sample : rnav.Sample
|
|
67
|
+
Your rnavigate sample
|
|
68
|
+
window : int, optional
|
|
69
|
+
number of nucleotides to include in window
|
|
70
|
+
Defaults to 81.
|
|
71
|
+
profile (str, optional): data keyword of provided sample pointing
|
|
72
|
+
to a profile.
|
|
73
|
+
Defaults to "default_profile"
|
|
74
|
+
structure (str, optional): data keyword of provided sample pointing
|
|
75
|
+
to a secondary structure.
|
|
76
|
+
Defaults to "default_structure"
|
|
77
|
+
"""
|
|
78
|
+
# ensure sample contains profile and structure data
|
|
79
|
+
for data in [profile, structure]:
|
|
80
|
+
assert data in sample.data.keys(), f"Sample missing {data} data"
|
|
81
|
+
|
|
82
|
+
# store basic information
|
|
83
|
+
self.sample = sample
|
|
84
|
+
self.structure = sample.get_data(structure)
|
|
85
|
+
self.profile = sample.get_data(profile)
|
|
86
|
+
self.sequence = self.structure.sequence
|
|
87
|
+
self.window = window
|
|
88
|
+
self.nt_length = self.structure.length
|
|
89
|
+
|
|
90
|
+
# get Norm_profile array and structure array
|
|
91
|
+
profile = self.profile.data["Norm_profile"].values
|
|
92
|
+
pair_nts = self.structure.pair_nts
|
|
93
|
+
|
|
94
|
+
# for each possible window: compute auroc and populate array
|
|
95
|
+
self.auroc = np.full(len(profile), np.nan)
|
|
96
|
+
pad = window // 2
|
|
97
|
+
for i in range(pad, len(profile) - pad):
|
|
98
|
+
# get profile and structure values within window
|
|
99
|
+
win_profile = profile[i - pad : i + pad + 1]
|
|
100
|
+
win_ct = pair_nts[i - pad : i + pad + 1]
|
|
101
|
+
# ignore positions where profile is nan
|
|
102
|
+
valid = ~np.isnan(win_profile)
|
|
103
|
+
# y: classification (paired or unpaired)
|
|
104
|
+
y = win_ct[valid] == 0
|
|
105
|
+
scores = win_profile[valid]
|
|
106
|
+
# skip this window if there are less than 10 paired or unpaired nts
|
|
107
|
+
if (sum(y) < 10) or (sum(~y) < 10):
|
|
108
|
+
continue
|
|
109
|
+
# add window auroc to array
|
|
110
|
+
tpr, fpr, _ = roc_curve(y, scores)
|
|
111
|
+
self.auroc[i] = auc(tpr, fpr)
|
|
112
|
+
|
|
113
|
+
self.auroc_median = np.nanmedian(self.auroc)
|
|
114
|
+
|
|
115
|
+
def plot_auroc(self, region=None):
|
|
116
|
+
"""Plot the result of the windowed AUROC analysis, with arc plot of
|
|
117
|
+
structure and reactivity profile.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
region (list of int: length 2, optional): Start and end nucleotide
|
|
121
|
+
positions to plot. Defaults to [1, RNA length].
|
|
122
|
+
"""
|
|
123
|
+
if region is None:
|
|
124
|
+
start = 1
|
|
125
|
+
stop = self.nt_length
|
|
126
|
+
region = [start, stop]
|
|
127
|
+
region_length = self.nt_length
|
|
128
|
+
else:
|
|
129
|
+
start, stop = region
|
|
130
|
+
region_length = stop - start + 1
|
|
131
|
+
|
|
132
|
+
plot = plots.AP(1, region_length, cols=1, rows=1, region=region)
|
|
133
|
+
ax = plot.axes[0, 0]
|
|
134
|
+
|
|
135
|
+
# fill between auroc values and median, using secondary ax
|
|
136
|
+
x_values = np.arange(start, stop + 1)
|
|
137
|
+
auc_ax = ax.twinx()
|
|
138
|
+
auc_ax.set_ylim(0.5, 1.6)
|
|
139
|
+
auc_ax.set_yticks([0.5, self.auroc_median, 1.0])
|
|
140
|
+
auc_ax.fill_between(
|
|
141
|
+
x_values,
|
|
142
|
+
self.auroc[start - 1 : stop],
|
|
143
|
+
self.auroc_median,
|
|
144
|
+
fc="0.3",
|
|
145
|
+
lw=0,
|
|
146
|
+
)
|
|
147
|
+
plots.adjust_spines(auc_ax, ["left"])
|
|
148
|
+
plots.clip_spines(auc_ax, ["left"])
|
|
149
|
+
|
|
150
|
+
# add structure and reactivity profile track
|
|
151
|
+
plot.plot_data(
|
|
152
|
+
sequence=self.structure,
|
|
153
|
+
structure=self.structure,
|
|
154
|
+
structure2=None,
|
|
155
|
+
interactions=None,
|
|
156
|
+
interactions2=None,
|
|
157
|
+
profile=self.profile,
|
|
158
|
+
label="label",
|
|
159
|
+
seqbar=False,
|
|
160
|
+
title=False,
|
|
161
|
+
annotations=[],
|
|
162
|
+
plot_error=False,
|
|
163
|
+
)
|
|
164
|
+
|
|
165
|
+
# Place Track Labels
|
|
166
|
+
ax.set_title(
|
|
167
|
+
f"{self.sample.sample}\n{start} - {stop}",
|
|
168
|
+
loc="left",
|
|
169
|
+
fontdict={"fontsize": 48},
|
|
170
|
+
)
|
|
171
|
+
ax.text(
|
|
172
|
+
1.002,
|
|
173
|
+
6 / 8,
|
|
174
|
+
"Secondary\nStructure",
|
|
175
|
+
transform=ax.transAxes,
|
|
176
|
+
fontsize=36,
|
|
177
|
+
va="center",
|
|
178
|
+
)
|
|
179
|
+
ax.text(
|
|
180
|
+
1.002,
|
|
181
|
+
2 / 8,
|
|
182
|
+
f"{self.window}-nt window\nAUROC",
|
|
183
|
+
transform=ax.transAxes,
|
|
184
|
+
va="center",
|
|
185
|
+
fontsize=36,
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
# limits, ticks, spines, and grid
|
|
189
|
+
ax.set_ylim([-305, 315])
|
|
190
|
+
ax.set_xticks(ticks=[x for x in range(500, stop, 500) if x > start])
|
|
191
|
+
ax.set_xticks(ticks=[x for x in range(100, stop, 100) if x > start], minor=True)
|
|
192
|
+
ax.tick_params(axis="x", which="major", labelsize=36)
|
|
193
|
+
plots.adjust_spines(ax, ["bottom"])
|
|
194
|
+
ax.grid(axis="x")
|
|
195
|
+
|
|
196
|
+
# set figure size so that 100 ax units == 1 inch
|
|
197
|
+
plot.set_figure_size(height_ax_rel=1 / 100, width_ax_rel=1 / 100)
|
|
198
|
+
return plot
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"""SequenceChecker analysis used to inspect sequence differences.
|
|
2
|
+
|
|
3
|
+
Given a list of samples, we can inspect which data keywords belong to the
|
|
4
|
+
samples, which sequences match up perfectly, and inspect the differences
|
|
5
|
+
between sequences.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
import pandas as pd
|
|
10
|
+
|
|
11
|
+
from rnavigate import data
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class SequenceChecker:
|
|
15
|
+
"""Check the sequences stored in a list of samples.
|
|
16
|
+
|
|
17
|
+
Attributes
|
|
18
|
+
----------
|
|
19
|
+
samples : list
|
|
20
|
+
samples in which to check sequences
|
|
21
|
+
sequences : list
|
|
22
|
+
all unique sequence strings stored in the list of samples. These are converted
|
|
23
|
+
to an all uppercase RNA alphabet.
|
|
24
|
+
keywords : list
|
|
25
|
+
all unique data keywords stored in the list of samples.
|
|
26
|
+
which_sequences : Pandas.DataFrame
|
|
27
|
+
each row is a sample, keyword, and index of self.sequences
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(self, samples):
|
|
31
|
+
"""Creates an instance of SequenceChecker given a list of samples
|
|
32
|
+
|
|
33
|
+
Parameters
|
|
34
|
+
----------
|
|
35
|
+
samples : list of rnav.Sample
|
|
36
|
+
samples for which to compare data keywords and sequences.
|
|
37
|
+
"""
|
|
38
|
+
self.samples = samples
|
|
39
|
+
self.keywords = self.get_keywords()
|
|
40
|
+
self.sequences = self.get_sequences()
|
|
41
|
+
self.which_sequences = self.get_which_sequences()
|
|
42
|
+
|
|
43
|
+
def reset(self):
|
|
44
|
+
"""Reset keywords and sequences from sample list in case of changes."""
|
|
45
|
+
self.keywords = self.get_keywords()
|
|
46
|
+
self.sequences = self.get_sequences()
|
|
47
|
+
self.which_sequences = self.get_which_sequences()
|
|
48
|
+
|
|
49
|
+
def get_keywords(self):
|
|
50
|
+
"""A list of all unique data keywords across samples."""
|
|
51
|
+
return list(set([dkw for s in self.samples for dkw in s.data]))
|
|
52
|
+
|
|
53
|
+
def get_sequences(self):
|
|
54
|
+
"""A list of all unique sequences (uppercase RNA) across samples."""
|
|
55
|
+
sequences = []
|
|
56
|
+
for sample in self.samples:
|
|
57
|
+
for dkw in self.keywords:
|
|
58
|
+
if dkw not in sample.data:
|
|
59
|
+
continue
|
|
60
|
+
seq = sample.get_data(dkw).sequence
|
|
61
|
+
seq = seq.upper().replace("T", "U")
|
|
62
|
+
if seq not in sequences:
|
|
63
|
+
sequences.append(seq)
|
|
64
|
+
return sequences
|
|
65
|
+
|
|
66
|
+
def get_which_sequences(self):
|
|
67
|
+
"""A DataFrame of sequence IDs (integers) for each data keyword."""
|
|
68
|
+
df = {key: [] for key in ["Sample"] + self.keywords}
|
|
69
|
+
for sample in self.samples:
|
|
70
|
+
df["Sample"].append(sample.sample)
|
|
71
|
+
for dkw in self.keywords:
|
|
72
|
+
if dkw not in sample.data:
|
|
73
|
+
df[dkw].append(np.nan)
|
|
74
|
+
else:
|
|
75
|
+
seq = sample.get_data(dkw).sequence
|
|
76
|
+
seq = seq.upper().replace("T", "U")
|
|
77
|
+
df[dkw].append(self.sequences.index(seq))
|
|
78
|
+
return pd.DataFrame(df)
|
|
79
|
+
|
|
80
|
+
def print_which_sequences(self):
|
|
81
|
+
"""Print sequence ID (integer) for each data keyword and sample."""
|
|
82
|
+
print("Sequence IDs")
|
|
83
|
+
for _, row in self.which_sequences.iterrows():
|
|
84
|
+
for column in self.which_sequences.columns:
|
|
85
|
+
if column == "Sample":
|
|
86
|
+
print(f" {row[column]}")
|
|
87
|
+
else:
|
|
88
|
+
if np.isnan(row[column]):
|
|
89
|
+
continue
|
|
90
|
+
print(f" {column:<10} {int(row[column])}")
|
|
91
|
+
print()
|
|
92
|
+
|
|
93
|
+
def print_alignments(self, print_format="long", which="all"):
|
|
94
|
+
"""Print alignments in the given format for sequence IDs provided.
|
|
95
|
+
|
|
96
|
+
Parameters
|
|
97
|
+
----------
|
|
98
|
+
print_format : string, defaults to "long"
|
|
99
|
+
What format to print the alignments in:
|
|
100
|
+
"cigar" prints the cigar string
|
|
101
|
+
"short" prints the numbers of mismatches and indels
|
|
102
|
+
"long" prints the location and nucleotide identity of all
|
|
103
|
+
mismatches, insertions and deletions.
|
|
104
|
+
which : tuple of two of integers, defaults to "all" (every pairwise comparison)
|
|
105
|
+
two sequence IDs to compare.
|
|
106
|
+
"""
|
|
107
|
+
kwargs = {"print_format": print_format}
|
|
108
|
+
if which == "all":
|
|
109
|
+
num = range(len(self.sequences))
|
|
110
|
+
for s1 in num:
|
|
111
|
+
for s2 in num:
|
|
112
|
+
if s1 < s2:
|
|
113
|
+
self.print_alignments(which=(s1, s2), **kwargs)
|
|
114
|
+
return
|
|
115
|
+
i, j = int(which[0]), int(which[1])
|
|
116
|
+
a = self.sequences[i]
|
|
117
|
+
b = self.sequences[j]
|
|
118
|
+
alignment = data.SequenceAlignment(sequence1=a, sequence2=b, full=True)
|
|
119
|
+
print(f"Sequence {i} -> {j} ({len(a)} nts -> {len(b)} nts)")
|
|
120
|
+
alignment.print(print_format=print_format)
|
|
121
|
+
|
|
122
|
+
def print_mulitple_sequence_alignment(self, base_sequence):
|
|
123
|
+
"""Print the multiple sequence alignment with nice formatting.
|
|
124
|
+
|
|
125
|
+
Parameters
|
|
126
|
+
----------
|
|
127
|
+
base_sequence : string
|
|
128
|
+
a sequence string that represents the longest common sequence.
|
|
129
|
+
Usually, this is the return value from:
|
|
130
|
+
rnav.data.set_multiple_sequence_alignment()
|
|
131
|
+
"""
|
|
132
|
+
print("Multiple sequence alignment")
|
|
133
|
+
alignments = [
|
|
134
|
+
data.SequenceAlignment(base_sequence, seq).alignment2
|
|
135
|
+
for seq in self.sequences
|
|
136
|
+
]
|
|
137
|
+
pos = "".join(f"{n:<20}" for n in range(1, len(alignments[0]), 20))
|
|
138
|
+
misses = "".join("X "[len(set(nts)) == 1] for nts in zip(*alignments))
|
|
139
|
+
print(" ID length alignment")
|
|
140
|
+
for i, (alignment, seq) in enumerate(zip(alignments, self.sequences)):
|
|
141
|
+
print(f" {i:<5} {len(seq):<8} {alignment}")
|
|
142
|
+
print(f" {'mismatches':<14} {misses}")
|
|
143
|
+
print(f" {'positions':<14} {pos}")
|
|
144
|
+
print()
|
|
145
|
+
|
|
146
|
+
def write_fasta(self, filename, which="all"):
|
|
147
|
+
"""Write all unique sequences to a fasta file.
|
|
148
|
+
|
|
149
|
+
This is very useful for using external multiple sequence aligners such
|
|
150
|
+
as ClustalOmega.
|
|
151
|
+
1) go to https://www.ebi.ac.uk/Tools/msa/clustalo/
|
|
152
|
+
2) upload new fasta file
|
|
153
|
+
3) under STEP 2 output format, select Pearson/FASTA
|
|
154
|
+
4) click 'Submit'
|
|
155
|
+
5) wait for your alignment to finish
|
|
156
|
+
6) download the alignment fasta file
|
|
157
|
+
7) use rnav.data.set_multiple_sequence_alignment()
|
|
158
|
+
|
|
159
|
+
Parameters
|
|
160
|
+
----------
|
|
161
|
+
filename : string
|
|
162
|
+
path to a new file to which fasta entries are written
|
|
163
|
+
which : list of integers, defaults to "all" (every sequence)
|
|
164
|
+
Sequence IDs to write to file.
|
|
165
|
+
"""
|
|
166
|
+
if which == "all":
|
|
167
|
+
which = range(len(self.sequences))
|
|
168
|
+
with open(filename, "w") as fasta:
|
|
169
|
+
for i in which:
|
|
170
|
+
fasta.write(f">Sequence_{i}\n")
|
|
171
|
+
fasta.write(f"{self.sequences[i]}\n")
|