Skip to content

Commit 6a432aa

Browse files
committed
Implemented showing matching sequence region for structure matches
1 parent c02387e commit 6a432aa

File tree

1 file changed

+60
-8
lines changed

1 file changed

+60
-8
lines changed

src/bundles/seq_view/src/match.py

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,10 @@ def __init__(self, sv, tool_window):
7979
ur_layout.addWidget(self.use_region_check_box, alignment=Qt.AlignLeft, stretch=1)
8080
layout.addLayout(ur_layout)
8181

82-
#cr_layout = QHBoxLayout()
83-
#self.create_region_check_box = QCheckBox("Create region showing matched residues")
84-
#cr_layout.addWidget(self.create_region_check_box, alignment=Qt.AlignLeft, stretch=1)
85-
#layout.addLayout(cr_layout)
82+
cr_layout = QHBoxLayout()
83+
self.create_region_check_box = QCheckBox("Create region showing matched residues")
84+
cr_layout.addWidget(self.create_region_check_box, alignment=Qt.AlignLeft, stretch=1)
85+
layout.addLayout(cr_layout)
8686

8787
from Qt.QtWidgets import QDialogButtonBox as qbbox
8888
bbox = qbbox(qbbox.Ok | qbbox.Apply | qbbox.Close | qbbox.Help)
@@ -139,9 +139,61 @@ def match(self, *, apply=False):
139139
if not apply:
140140
self.tool_window.shown = False
141141
from chimerax.core.commands import run, StringArg
142-
results = run(self.sv.session, "seq match %s %s to %s%s"
143-
% (StringArg.unparse(self.sv.alignment.ident), ref.atomspec,
144-
','.join([c.atomspec for c in matches]), args))
142+
results = run(self.sv.session, "seq match %s %s to %s%s" %
143+
(StringArg.unparse(self.sv.alignment.ident),
144+
''.join([c.atomspec for c in matches]), ref.atomspec, args))
145145

146146
if self.create_region_check_box.isChecked():
147-
pass #TODO
147+
def get_info(a, aln=self.sv.alignment):
148+
r = a.residue
149+
c = r.chain
150+
aseq = aln.associations[c]
151+
mmap = aseq.match_maps[c]
152+
return aseq, aseq.ungapped_to_gapped(mmap[r])
153+
region_indices = { seq: set() for seq in self.sv.alignment.seqs }
154+
for match_atoms, ref_atoms, rmsd, full_rmsd, xform in results:
155+
if match_atoms is None:
156+
continue
157+
for atoms in (match_atoms, ref_atoms):
158+
for a in atoms:
159+
aseq, index = get_info(a)
160+
region_indices[aseq].add(index)
161+
region_blocks = []
162+
seqs = self.sv.alignment.seqs
163+
while seqs:
164+
aseq = seqs.pop(0)
165+
aseq_indices = region_indices.pop(aseq)
166+
if not aseq_indices:
167+
continue
168+
collate(aseq, aseq_indices, region_indices, seqs, region_blocks)
169+
if not region_blocks:
170+
self.sv.sesson.logger.warn("No matching occurred; not creating 'match' region")
171+
reg_name, fill, outline = self.sv.MATCHED_REGION_INFO
172+
reg = self.sv.region_manager.get_region(reg_name, fill=fill, outline=outline, create=True,
173+
cover_gaps=True)
174+
reg.clear()
175+
reg.add_blocks(region_blocks)
176+
177+
def collate(aseq, aseq_indices, region_indices, seqs, region_blocks):
178+
while aseq_indices:
179+
first_i = last_i = min(aseq_indices)
180+
while last_i+1 in aseq_indices:
181+
last_i += 1
182+
first_seq = last_seq = aseq
183+
for seq in seqs:
184+
seq_indices = region_indices[seq]
185+
for i in range(first_i, last_i+1):
186+
if i not in seq_indices:
187+
break
188+
else:
189+
last_seq = seq
190+
continue
191+
break
192+
region_blocks.append((first_seq, last_seq, first_i, last_i))
193+
for i in range(first_i, last_i+1):
194+
aseq_indices.remove(i)
195+
if last_seq != aseq:
196+
for seq in seqs:
197+
region_indices[seq].remove(i)
198+
if seq == last_seq:
199+
break

0 commit comments

Comments
 (0)