Skip to content

Commit 63bd514

Browse files
committed
Optimized the result page of Foldmason
1 parent bb1b2af commit 63bd514

3 files changed

Lines changed: 57 additions & 70 deletions

File tree

frontend/MSA.vue

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,7 @@ export default {
400400
selectedColumns: [],
401401
showViewerCondition: false,
402402
msaEntries: [],
403+
scrollTicking: false,
403404
}
404405
},
405406
watch: {
@@ -411,15 +412,15 @@ export default {
411412
if (this.msaEntries.length > 0
412413
&& (o.length == 0 || !n.every((v, i) => v === o[i]))) {
413414
this.msaEntries.forEach(( v, i ) => {
414-
v.aa = ""
415-
v.ss = ""
416-
415+
const aaArr = [], ssArr = [];
417416
for (let j = 0; j < n.length; j++) {
418417
if (n[j] === 1) {
419-
v.aa += this.entries[i].aa[j]
420-
v.ss += this.entries[i].ss[j]
418+
aaArr.push(this.entries[i].aa[j]);
419+
ssArr.push(this.entries[i].ss[j]);
421420
}
422421
}
422+
v.aa = aaArr.join('');
423+
v.ss = ssArr.join('');
423424
})
424425
}
425426
},
@@ -504,12 +505,6 @@ export default {
504505
chains: entry.chains,
505506
suffix: entry.suffix,
506507
}
507-
// for (let i = 0; i < this.mask.length; i++) {
508-
// if (this.mask[i] === 1) {
509-
// copy.aa += entry.aa[i];
510-
// copy.ss += entry.ss[i];
511-
// }
512-
// }
513508
return copy;
514509
})
515510
},
@@ -661,6 +656,15 @@ export default {
661656
}
662657
},
663658
handleScroll() {
659+
if (!this.scrollTicking) {
660+
this.scrollTicking = true;
661+
window.requestAnimationFrame(() => {
662+
this._doHandleScroll();
663+
this.scrollTicking = false;
664+
});
665+
}
666+
},
667+
_doHandleScroll() {
664668
const box = this.$refs.msaView.$el.getBoundingClientRect()
665669
const scrollOffset = window.scrollY
666670
const rowHeight = this.$refs.topRow.scrollHeight
@@ -677,12 +681,12 @@ export default {
677681
} else {
678682
this.blockIndex = Math.floor((scroll - top) / blockSize);
679683
}
680-
684+
681685
if (!!document.fullscreenElement) return
682686
683-
this.showViewerCondition = this.showViewer
687+
this.showViewerCondition = this.showViewer
684688
&& scrollOffset >= rowHeight
685-
689+
686690
if (
687691
this.showViewerCondition
688692
) {
@@ -706,7 +710,6 @@ export default {
706710
})
707711
}
708712
}
709-
710713
},
711714
handleLineLen(lineLen) {
712715
this.lineLen = lineLen;

frontend/MSAView.vue

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616
}"
1717
preserveAspectRatio="none"
1818
>
19-
<path :d="conservationPath(getConservationRange(start, end))" />
19+
<path :d="conservationBlocks[i].path" />
2020
<g :transform="`scale(${1 / conservationScaleX}, 1)`">
2121
<text
22-
v-for="(idx) in getConservationMaxCols(start, end)"
22+
v-for="(idx) in conservationBlocks[i].maxCols"
2323
:key="`cons-max-${i}-${idx}`"
2424
class="conservation-max"
2525
:x="(idx + 0.5) * conservationScaleX"
@@ -30,11 +30,11 @@
3030
</g>
3131
</svg>
3232
<!-- <SequenceLogo
33-
:sequences="getEntryRanges(start, end, makeGradients=false)"
33+
:sequences="cachedEntryRanges[i]"
3434
:alphabet="alphabet"
3535
:lineLen="lineLen"
3636
/> -->
37-
<template v-for="({ name, aa, ss, seqStart, css }, j) in getEntryRanges(start, end)">
37+
<template v-for="({ name, aa, ss, seqStart, css }, j) in cachedEntryRanges[i]">
3838
<span class="header" :title="name" :style="headerStyle(j)" @click="handleClickHeader($event, j)">{{
3939
name }}</span>
4040
<div class="sequence-wrapper" :style="sequenceStyle(j)">
@@ -217,7 +217,7 @@ const colorsAaByPalette = {
217217
};
218218
219219
export default {
220-
components: { SequenceLogo, SequenceLogo },
220+
components: { SequenceLogo },
221221
data() {
222222
return {
223223
lineLen: 80,
@@ -248,40 +248,46 @@ export default {
248248
highlightedColumns: {type: Array},
249249
},
250250
mounted() {
251-
this.resizeObserver = new ResizeObserver(debounce(this.handleResize, 100)).observe(this.$refs.msaWrapper);
251+
this.resizeObserver = new ResizeObserver(debounce(this.handleResize, 100));
252+
this.resizeObserver.observe(this.$refs.msaWrapper);
252253
this.handleUpdateEntries();
253254
this.handleResize();
254255
this.emitGradients();
255256
},
256-
updated() {
257-
this.handleResize();
258-
this.emitGradients();
259-
},
260257
beforeDestroy() {
261258
if (this.resizeObserver)
262259
this.resizeObserver.disconnect();
263260
},
264261
watch: {
265262
entries: function() {
266263
this.handleUpdateEntries();
264+
this.$nextTick(() => this.emitGradients());
265+
},
266+
colorScheme: function() {
267+
this.$nextTick(() => this.emitGradients());
268+
},
269+
scores: function() {
270+
this.$nextTick(() => this.emitGradients());
271+
},
272+
mask: function() {
273+
this.$nextTick(() => this.emitGradients());
267274
},
268275
lineLen: function() {
269276
this.$emit("lineLen", this.lineLen);
277+
this.$nextTick(() => this.emitGradients());
270278
},
271279
},
272280
computed: {
273-
maskCumSum() {
274-
if (!this.mask) {
275-
return [];
276-
}
277-
278-
const result = [];
279-
let sum = 0;
280-
for (let i = 0; i < this.mask.length; i++) {
281-
sum += this.mask[i] == 0;
282-
result.push(sum);
283-
}
284-
return result;
281+
cachedEntryRanges() {
282+
return this.blockRanges.map(([start, end]) =>
283+
this.entries.map(entry => this.getEntryRange(entry, start, end, true))
284+
);
285+
},
286+
conservationBlocks() {
287+
return this.blockRanges.map(([start, end]) => ({
288+
path: this.conservationPath(this.conservationValues.slice(start, end)),
289+
maxCols: this.getConservationMaxCols(start, end),
290+
}));
285291
},
286292
beforeMaskedIndices() {
287293
if (!this.mask) {

frontend/StructureViewerMSA.vue

Lines changed: 11 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -529,49 +529,25 @@ ENDMDL
529529
representation.setVisibility(true);
530530
})
531531
);
532-
this.updateMask();
532+
this.rebuildReprs();
533533
this.clearTimer()
534534
},
535-
async updateMask() {
535+
rebuildReprs() {
536536
this.stage.eachRepresentation((repr) => {
537537
repr.build();
538538
});
539539
},
540+
async updateMask() {
541+
this.stage.eachRepresentation((repr) => {
542+
repr.update({color: true})
543+
});
544+
},
540545
async updateAllHighlights() {
541546
if (!this.stage) return
542547
543-
let getHighlightedResno = (index) => {
544-
let seq = this.entries[index].aa
545-
return getResidueIndices(seq, this.selectedColumns).map(i => i+1)
546-
}
547-
548-
549-
let that = this
550548
this.stage.eachComponent(function(comp) {
551549
if (comp.type !== 'structure') return
552-
553-
let reprList = comp.reprList
554-
reprList.find(r => r.name === 'cartoon')?.build()
555-
return
556-
557-
// As our mockPDB doesn't contain any sidechain atoms,
558-
// the licorice representation is useless
559-
const index = parseInt(comp.structure.name.replace("key-", ""));
560-
let hightlightedIndices = getHighlightedResno(index)
561-
let highlightSele = hightlightedIndices.length > 0 ? hightlightedIndices.join(" or ") : "none"
562-
let highlightRepr = reprList.find(r => r.name === 'highlight-repr')
563-
564-
if (highlightRepr) {
565-
highlightRepr.setSelection(highlightSele).build()
566-
} else {
567-
comp.addRepresentation('licorice', {
568-
name: 'highlight-repr',
569-
sele: highlightSele,
570-
colorValue: that.highLightColor,
571-
opacity: 0.5,
572-
scale: 3.0,
573-
}).build()
574-
}
550+
comp.reprList.find(r => r.name === 'cartoon')?.update({ color: true })
575551
})
576552
},
577553
async updateAllPreview() {
@@ -671,7 +647,9 @@ ENDMDL
671647
this.updateEntries(newV, oldV);
672648
},
673649
mask: function(newM, oldM) {
674-
this.updateMask();
650+
if (oldM?.length == 0 || !newM.every((v, i) => v === oldM[i])) {
651+
this.updateMask();
652+
}
675653
}
676654
},
677655
computed: {

0 commit comments

Comments
 (0)