react-msaview 3.2.0 → 3.2.1
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.
- package/bundle/index.js +12 -12
- package/dist/colorSchemes.js +2 -2
- package/dist/colorSchemes.js.map +1 -1
- package/dist/components/Loading.js +3 -1
- package/dist/components/Loading.js.map +1 -1
- package/dist/components/ResizeHandles.js +6 -2
- package/dist/components/ResizeHandles.js.map +1 -1
- package/dist/components/SequenceTextArea.js +9 -3
- package/dist/components/SequenceTextArea.js.map +1 -1
- package/dist/components/TextTrack.js +1 -1
- package/dist/components/TextTrack.js.map +1 -1
- package/dist/components/Track.js +6 -2
- package/dist/components/Track.js.map +1 -1
- package/dist/components/VerticalScrollbar.js +5 -1
- package/dist/components/VerticalScrollbar.js.map +1 -1
- package/dist/components/dialogs/AboutDialog.js +3 -1
- package/dist/components/dialogs/AboutDialog.js.map +1 -1
- package/dist/components/dialogs/AddTrackDialog.d.ts +2 -2
- package/dist/components/dialogs/AddTrackDialog.js +8 -3
- package/dist/components/dialogs/AddTrackDialog.js.map +1 -1
- package/dist/components/dialogs/DomainDialog.js +6 -2
- package/dist/components/dialogs/DomainDialog.js.map +1 -1
- package/dist/components/dialogs/ExportSVGDialog.js +29 -17
- package/dist/components/dialogs/ExportSVGDialog.js.map +1 -1
- package/dist/components/dialogs/FeatureDialog.js +8 -4
- package/dist/components/dialogs/FeatureDialog.js.map +1 -1
- package/dist/components/dialogs/InterProScanDialog.js +23 -9
- package/dist/components/dialogs/InterProScanDialog.js.map +1 -1
- package/dist/components/dialogs/MetadataDialog.js +3 -1
- package/dist/components/dialogs/MetadataDialog.js.map +1 -1
- package/dist/components/dialogs/SettingsDialog.js +61 -23
- package/dist/components/dialogs/SettingsDialog.js.map +1 -1
- package/dist/components/dialogs/TracklistDialog.d.ts +2 -2
- package/dist/components/dialogs/TracklistDialog.js +8 -3
- package/dist/components/dialogs/TracklistDialog.js.map +1 -1
- package/dist/components/dialogs/UserProvidedDomainsDialog.js +10 -4
- package/dist/components/dialogs/UserProvidedDomainsDialog.js.map +1 -1
- package/dist/components/header/Header.js +3 -1
- package/dist/components/header/Header.js.map +1 -1
- package/dist/components/header/HeaderInfoArea.js +5 -2
- package/dist/components/header/HeaderInfoArea.js.map +1 -1
- package/dist/components/header/HeaderMenu.js +12 -4
- package/dist/components/header/HeaderMenu.js.map +1 -1
- package/dist/components/header/HeaderMenuExtra.js +34 -16
- package/dist/components/header/HeaderMenuExtra.js.map +1 -1
- package/dist/components/header/ZoomControls.js +18 -6
- package/dist/components/header/ZoomControls.js.map +1 -1
- package/dist/components/import/ImportForm.d.ts +2 -2
- package/dist/components/import/ImportForm.js +15 -2
- package/dist/components/import/ImportForm.js.map +1 -1
- package/dist/components/import/ImportFormExamples.js +44 -31
- package/dist/components/import/ImportFormExamples.js.map +1 -1
- package/dist/components/minimap/Minimap.js +12 -4
- package/dist/components/minimap/Minimap.js.map +1 -1
- package/dist/components/msa/MSACanvasBlock.js +5 -3
- package/dist/components/msa/MSACanvasBlock.js.map +1 -1
- package/dist/components/msa/MSAMouseoverCanvas.d.ts +1 -1
- package/dist/components/msa/MSAMouseoverCanvas.js +1 -1
- package/dist/components/msa/MSAMouseoverCanvas.js.map +1 -1
- package/dist/components/msa/renderBoxFeatureCanvasBlock.js +2 -2
- package/dist/components/msa/renderBoxFeatureCanvasBlock.js.map +1 -1
- package/dist/components/msa/renderMSABlock.js +4 -4
- package/dist/components/msa/renderMSABlock.js.map +1 -1
- package/dist/components/msa/renderMSAMouseover.js +3 -3
- package/dist/components/msa/renderMSAMouseover.js.map +1 -1
- package/dist/components/tree/TreeBranchMenu.js +6 -3
- package/dist/components/tree/TreeBranchMenu.js.map +1 -1
- package/dist/components/tree/TreeCanvasBlock.js +11 -4
- package/dist/components/tree/TreeCanvasBlock.js.map +1 -1
- package/dist/components/tree/TreeNodeMenu.js +1 -1
- package/dist/components/tree/TreeNodeMenu.js.map +1 -1
- package/dist/components/tree/dialogs/TreeNodeInfoDialog.d.ts +2 -2
- package/dist/components/tree/dialogs/TreeNodeInfoDialog.js +5 -2
- package/dist/components/tree/dialogs/TreeNodeInfoDialog.js.map +1 -1
- package/dist/components/util.js +0 -3
- package/dist/components/util.js.map +1 -1
- package/dist/ggplotPalettes.js.map +1 -1
- package/dist/launchInterProScan.js +4 -4
- package/dist/launchInterProScan.js.map +1 -1
- package/dist/model/DialogQueue.js +0 -1
- package/dist/model/DialogQueue.js.map +1 -1
- package/dist/model.d.ts +57 -22
- package/dist/model.js +87 -50
- package/dist/model.js.map +1 -1
- package/dist/parseGFF.js +8 -6
- package/dist/parseGFF.js.map +1 -1
- package/dist/parseNewick.js +0 -1
- package/dist/parseNewick.js.map +1 -1
- package/dist/parsers/ClustalMSA.d.ts +1 -1
- package/dist/parsers/ClustalMSA.js.map +1 -1
- package/dist/parsers/FastaMSA.js +3 -3
- package/dist/parsers/FastaMSA.js.map +1 -1
- package/dist/parsers/StockholmMSA.d.ts +6 -6
- package/dist/parsers/StockholmMSA.js +4 -4
- package/dist/parsers/StockholmMSA.js.map +1 -1
- package/dist/renderToSvg.js +3 -6
- package/dist/renderToSvg.js.map +1 -1
- package/dist/rowCoordinateCalculations.d.ts +2 -0
- package/dist/rowCoordinateCalculations.js +26 -0
- package/dist/rowCoordinateCalculations.js.map +1 -0
- package/dist/rowCoordinateCalculations.test.d.ts +1 -0
- package/dist/rowCoordinateCalculations.test.js +18 -0
- package/dist/rowCoordinateCalculations.test.js.map +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +7 -3
- package/src/colorSchemes.ts +4 -4
- package/src/components/Loading.tsx +7 -1
- package/src/components/ResizeHandles.tsx +6 -2
- package/src/components/SequenceTextArea.tsx +10 -4
- package/src/components/TextTrack.tsx +2 -2
- package/src/components/Track.tsx +8 -4
- package/src/components/VerticalScrollbar.tsx +6 -2
- package/src/components/dialogs/AboutDialog.tsx +7 -1
- package/src/components/dialogs/AddTrackDialog.tsx +13 -3
- package/src/components/dialogs/DomainDialog.tsx +9 -2
- package/src/components/dialogs/ExportSVGDialog.tsx +36 -17
- package/src/components/dialogs/FeatureDialog.tsx +7 -5
- package/src/components/dialogs/InterProScanDialog.tsx +20 -10
- package/src/components/dialogs/MetadataDialog.tsx +8 -1
- package/src/components/dialogs/SettingsDialog.tsx +76 -32
- package/src/components/dialogs/TracklistDialog.tsx +17 -3
- package/src/components/dialogs/UserProvidedDomainsDialog.tsx +11 -5
- package/src/components/header/Header.tsx +3 -1
- package/src/components/header/HeaderInfoArea.tsx +3 -2
- package/src/components/header/HeaderMenu.tsx +12 -7
- package/src/components/header/HeaderMenuExtra.tsx +28 -16
- package/src/components/header/ZoomControls.tsx +22 -6
- package/src/components/import/ImportForm.tsx +14 -2
- package/src/components/import/ImportFormExamples.tsx +59 -48
- package/src/components/minimap/Minimap.tsx +21 -9
- package/src/components/msa/MSACanvasBlock.tsx +5 -3
- package/src/components/msa/MSAMouseoverCanvas.tsx +5 -1
- package/src/components/msa/renderBoxFeatureCanvasBlock.ts +4 -4
- package/src/components/msa/renderMSABlock.ts +10 -10
- package/src/components/msa/renderMSAMouseover.ts +3 -3
- package/src/components/tree/TreeBranchMenu.tsx +5 -3
- package/src/components/tree/TreeCanvasBlock.tsx +11 -4
- package/src/components/tree/TreeNodeMenu.tsx +1 -1
- package/src/components/tree/dialogs/TreeNodeInfoDialog.tsx +11 -2
- package/src/components/util.ts +1 -4
- package/src/ggplotPalettes.ts +1 -1
- package/src/launchInterProScan.ts +5 -5
- package/src/model/DialogQueue.ts +0 -1
- package/src/model.ts +99 -56
- package/src/parseGFF.ts +13 -11
- package/src/parseNewick.ts +3 -3
- package/src/parsers/ClustalMSA.ts +2 -2
- package/src/parsers/FastaMSA.ts +4 -4
- package/src/parsers/StockholmMSA.ts +10 -10
- package/src/renderToSvg.tsx +1 -2
- package/src/rowCoordinateCalculations.test.ts +19 -0
- package/src/rowCoordinateCalculations.ts +26 -0
- package/src/version.ts +1 -1
package/src/model.ts
CHANGED
|
@@ -53,6 +53,10 @@ import { DialogQueueSessionMixin } from './model/DialogQueue'
|
|
|
53
53
|
import { TreeF } from './model/treeModel'
|
|
54
54
|
import { MSAModelF } from './model/msaModel'
|
|
55
55
|
import type { InterProScanResults } from './launchInterProScan'
|
|
56
|
+
import {
|
|
57
|
+
mouseOverCoordToGlobalCoord,
|
|
58
|
+
globalCoordToRowSpecificCoord,
|
|
59
|
+
} from './rowCoordinateCalculations'
|
|
56
60
|
|
|
57
61
|
export interface Accession {
|
|
58
62
|
accession: string
|
|
@@ -72,7 +76,6 @@ export interface TextTrackModel extends BasicTrackModel {
|
|
|
72
76
|
}
|
|
73
77
|
|
|
74
78
|
export interface ITextTrack {
|
|
75
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
76
79
|
ReactComponent: React.FC<any>
|
|
77
80
|
model: TextTrackModel
|
|
78
81
|
}
|
|
@@ -514,6 +517,12 @@ function stateModelFactory() {
|
|
|
514
517
|
}))
|
|
515
518
|
|
|
516
519
|
.views(self => ({
|
|
520
|
+
/**
|
|
521
|
+
* #getter
|
|
522
|
+
*/
|
|
523
|
+
get realAllowedGappyness() {
|
|
524
|
+
return self.hideGaps ? self.allowedGappyness : 100
|
|
525
|
+
},
|
|
517
526
|
/**
|
|
518
527
|
* #getter
|
|
519
528
|
*/
|
|
@@ -548,7 +557,7 @@ function stateModelFactory() {
|
|
|
548
557
|
* #getter
|
|
549
558
|
*/
|
|
550
559
|
get colorScheme() {
|
|
551
|
-
return colorSchemes[self.colorSchemeName]
|
|
560
|
+
return colorSchemes[self.colorSchemeName]!
|
|
552
561
|
},
|
|
553
562
|
|
|
554
563
|
/**
|
|
@@ -588,7 +597,7 @@ function stateModelFactory() {
|
|
|
588
597
|
/**
|
|
589
598
|
* #getter
|
|
590
599
|
*/
|
|
591
|
-
|
|
600
|
+
menuItems() {
|
|
592
601
|
return []
|
|
593
602
|
},
|
|
594
603
|
/**
|
|
@@ -653,6 +662,8 @@ function stateModelFactory() {
|
|
|
653
662
|
*/
|
|
654
663
|
get root() {
|
|
655
664
|
let hier = hierarchy(this.tree, d => d.branchset)
|
|
665
|
+
// todo: investigate whether needed, typescript says branchset always true
|
|
666
|
+
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
656
667
|
.sum(d => (d.branchset ? 0 : 1))
|
|
657
668
|
.sort((a, b) => ascending(a.data.length || 1, b.data.length || 1))
|
|
658
669
|
|
|
@@ -666,7 +677,9 @@ function stateModelFactory() {
|
|
|
666
677
|
;[...self.collapsed, ...self.collapsedLeaves]
|
|
667
678
|
.map(collapsedId => hier.find(node => node.data.id === collapsedId))
|
|
668
679
|
.filter(notEmpty)
|
|
669
|
-
.map(node =>
|
|
680
|
+
.map(node => {
|
|
681
|
+
collapse(node)
|
|
682
|
+
})
|
|
670
683
|
|
|
671
684
|
return hier
|
|
672
685
|
},
|
|
@@ -689,25 +702,34 @@ function stateModelFactory() {
|
|
|
689
702
|
* #getter
|
|
690
703
|
*/
|
|
691
704
|
get blanks() {
|
|
692
|
-
const {
|
|
705
|
+
const { hideGaps, realAllowedGappyness } = self
|
|
693
706
|
const blanks = []
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
707
|
+
if (hideGaps) {
|
|
708
|
+
const strs = this.leaves
|
|
709
|
+
.map(leaf => this.MSA?.getRow(leaf.data.name))
|
|
710
|
+
.filter((item): item is string => !!item)
|
|
711
|
+
if (strs.length) {
|
|
712
|
+
for (let i = 0; i < strs[0]!.length; i++) {
|
|
713
|
+
let counter = 0
|
|
714
|
+
for (const str of strs) {
|
|
715
|
+
if (str[i] === '-') {
|
|
716
|
+
counter++
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
if (counter / strs.length >= realAllowedGappyness / 100) {
|
|
720
|
+
blanks.push(i)
|
|
721
|
+
}
|
|
703
722
|
}
|
|
704
723
|
}
|
|
705
|
-
if (counter / strs.length >= allowedGappyness / 100) {
|
|
706
|
-
blanks.push(i)
|
|
707
|
-
}
|
|
708
724
|
}
|
|
709
725
|
return blanks
|
|
710
726
|
},
|
|
727
|
+
/**
|
|
728
|
+
* #getter
|
|
729
|
+
*/
|
|
730
|
+
get blanksSet() {
|
|
731
|
+
return new Set(this.blanks)
|
|
732
|
+
},
|
|
711
733
|
/**
|
|
712
734
|
* #getter
|
|
713
735
|
*/
|
|
@@ -717,13 +739,20 @@ function stateModelFactory() {
|
|
|
717
739
|
.map(leaf => [leaf.data.name, MSA?.getRow(leaf.data.name)] as const)
|
|
718
740
|
.filter((f): f is [string, string] => !!f[1])
|
|
719
741
|
},
|
|
742
|
+
|
|
743
|
+
/**
|
|
744
|
+
* #getter
|
|
745
|
+
*/
|
|
746
|
+
get rowMap() {
|
|
747
|
+
return new Map(this.rows)
|
|
748
|
+
},
|
|
720
749
|
/**
|
|
721
750
|
* #getter
|
|
722
751
|
*/
|
|
723
752
|
get columns() {
|
|
724
753
|
return Object.fromEntries(
|
|
725
754
|
this.rows.map(
|
|
726
|
-
(row, index) => [row[0], this.columns2d[index]] as const,
|
|
755
|
+
(row, index) => [row[0], this.columns2d[index]!] as const,
|
|
727
756
|
),
|
|
728
757
|
)
|
|
729
758
|
},
|
|
@@ -748,10 +777,11 @@ function stateModelFactory() {
|
|
|
748
777
|
for (const column of columns) {
|
|
749
778
|
for (let j = 0; j < column.length; j++) {
|
|
750
779
|
const l = r[j] || {}
|
|
751
|
-
|
|
752
|
-
|
|
780
|
+
const cj = column[j]!
|
|
781
|
+
if (!l[cj]) {
|
|
782
|
+
l[cj] = 0
|
|
753
783
|
}
|
|
754
|
-
l[
|
|
784
|
+
l[cj]++
|
|
755
785
|
r[j] = l
|
|
756
786
|
}
|
|
757
787
|
}
|
|
@@ -843,7 +873,7 @@ function stateModelFactory() {
|
|
|
843
873
|
const ret = []
|
|
844
874
|
for (const by of self.blocksY) {
|
|
845
875
|
for (const bx of self.blocksX) {
|
|
846
|
-
ret.push([bx, by])
|
|
876
|
+
ret.push([bx, by] as const)
|
|
847
877
|
}
|
|
848
878
|
}
|
|
849
879
|
return ret
|
|
@@ -1013,7 +1043,7 @@ function stateModelFactory() {
|
|
|
1013
1043
|
*/
|
|
1014
1044
|
get conservation() {
|
|
1015
1045
|
if (self.columns2d.length) {
|
|
1016
|
-
for (let i = 0; i < self.columns2d[0]
|
|
1046
|
+
for (let i = 0; i < self.columns2d[0]!.length; i++) {
|
|
1017
1047
|
const col = []
|
|
1018
1048
|
for (const column of self.columns2d) {
|
|
1019
1049
|
col.push(column[i])
|
|
@@ -1060,28 +1090,39 @@ function stateModelFactory() {
|
|
|
1060
1090
|
return self.msaAreaWidth < self.totalWidth
|
|
1061
1091
|
},
|
|
1062
1092
|
|
|
1093
|
+
/**
|
|
1094
|
+
* #getter
|
|
1095
|
+
*/
|
|
1096
|
+
get rowNamesSet() {
|
|
1097
|
+
return new Map(self.rowNames.map((r, idx) => [r, idx]))
|
|
1098
|
+
},
|
|
1099
|
+
|
|
1063
1100
|
/**
|
|
1064
1101
|
* #method
|
|
1065
|
-
* return a row-specific
|
|
1066
|
-
* coordinate
|
|
1102
|
+
* return a row-specific letter, or undefined if gap
|
|
1067
1103
|
*/
|
|
1068
|
-
|
|
1069
|
-
const {
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1104
|
+
mouseOverCoordToRowLetter(rowName: string, position: number) {
|
|
1105
|
+
const { rowMap, blanks } = self
|
|
1106
|
+
return rowMap.get(rowName)?.[
|
|
1107
|
+
mouseOverCoordToGlobalCoord(blanks, position)
|
|
1108
|
+
]
|
|
1109
|
+
},
|
|
1073
1110
|
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1111
|
+
/**
|
|
1112
|
+
* #method
|
|
1113
|
+
* return a row-specific sequence coordinate, skipping gaps, given a
|
|
1114
|
+
* global coordinate
|
|
1115
|
+
*/
|
|
1116
|
+
mouseOverCoordToGapRemovedRowCoord(rowName: string, position: number) {
|
|
1117
|
+
const { rowMap, blanks } = self
|
|
1118
|
+
const seq = rowMap.get(rowName)
|
|
1119
|
+
if (seq !== undefined) {
|
|
1120
|
+
const pos2 = mouseOverCoordToGlobalCoord(blanks, position)
|
|
1121
|
+
const pos1 = globalCoordToRowSpecificCoord(seq, pos2)
|
|
1122
|
+
return seq[pos1] === '-' || !seq[pos1] ? undefined : pos1
|
|
1123
|
+
} else {
|
|
1124
|
+
return undefined
|
|
1083
1125
|
}
|
|
1084
|
-
return 0
|
|
1085
1126
|
},
|
|
1086
1127
|
|
|
1087
1128
|
/**
|
|
@@ -1132,19 +1173,17 @@ function stateModelFactory() {
|
|
|
1132
1173
|
/**
|
|
1133
1174
|
* #getter
|
|
1134
1175
|
*/
|
|
1135
|
-
get
|
|
1176
|
+
get tidyInterProAnnotationTypes() {
|
|
1136
1177
|
const types = new Map<string, Accession>()
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
types.set(accession, { name, accession, description })
|
|
1140
|
-
}
|
|
1178
|
+
for (const annot of this.tidyInterProAnnotations) {
|
|
1179
|
+
types.set(annot.accession, annot)
|
|
1141
1180
|
}
|
|
1142
1181
|
return types
|
|
1143
1182
|
},
|
|
1144
1183
|
/**
|
|
1145
1184
|
* #getter
|
|
1146
1185
|
*/
|
|
1147
|
-
get
|
|
1186
|
+
get tidyInterProAnnotations() {
|
|
1148
1187
|
const ret = []
|
|
1149
1188
|
const { interProAnnotations } = self
|
|
1150
1189
|
if (interProAnnotations) {
|
|
@@ -1172,16 +1211,16 @@ function stateModelFactory() {
|
|
|
1172
1211
|
/**
|
|
1173
1212
|
* #getter
|
|
1174
1213
|
*/
|
|
1175
|
-
get
|
|
1176
|
-
return this.
|
|
1214
|
+
get tidyFilteredInterProAnnotations() {
|
|
1215
|
+
return this.tidyInterProAnnotations.filter(r =>
|
|
1177
1216
|
self.featureFilters.get(r.accession),
|
|
1178
1217
|
)
|
|
1179
1218
|
},
|
|
1180
1219
|
/**
|
|
1181
1220
|
* #getter
|
|
1182
1221
|
*/
|
|
1183
|
-
get
|
|
1184
|
-
return groupBy(this.
|
|
1222
|
+
get tidyFilteredGatheredInterProAnnotations() {
|
|
1223
|
+
return groupBy(this.tidyFilteredInterProAnnotations, r => r.id)
|
|
1185
1224
|
},
|
|
1186
1225
|
}))
|
|
1187
1226
|
.views(self => ({
|
|
@@ -1203,12 +1242,12 @@ function stateModelFactory() {
|
|
|
1203
1242
|
* #getter
|
|
1204
1243
|
*/
|
|
1205
1244
|
get fillPalette() {
|
|
1206
|
-
const arr = [...self.
|
|
1245
|
+
const arr = [...self.tidyInterProAnnotationTypes.keys()]
|
|
1207
1246
|
let i = 0
|
|
1208
1247
|
const map = {} as Record<string, string>
|
|
1209
1248
|
for (const key of arr) {
|
|
1210
1249
|
const k = Math.min(arr.length - 1, palettes.length - 1)
|
|
1211
|
-
map[key] = palettes[k][i]
|
|
1250
|
+
map[key] = palettes[k]![i]!
|
|
1212
1251
|
i++
|
|
1213
1252
|
}
|
|
1214
1253
|
return map
|
|
@@ -1285,7 +1324,7 @@ function stateModelFactory() {
|
|
|
1285
1324
|
addDisposer(
|
|
1286
1325
|
self,
|
|
1287
1326
|
autorun(() => {
|
|
1288
|
-
for (const key of self.
|
|
1327
|
+
for (const key of self.tidyInterProAnnotationTypes.keys()) {
|
|
1289
1328
|
this.initFilter(key)
|
|
1290
1329
|
}
|
|
1291
1330
|
}),
|
|
@@ -1361,17 +1400,21 @@ function stateModelFactory() {
|
|
|
1361
1400
|
}),
|
|
1362
1401
|
)
|
|
1363
1402
|
|
|
1403
|
+
// force colStats not to go stale
|
|
1404
|
+
// xref solution https://github.com/mobxjs/mobx/issues/266#issuecomment-222007278
|
|
1405
|
+
// xref problem https://github.com/GMOD/react-msaview/issues/75
|
|
1364
1406
|
addDisposer(
|
|
1365
1407
|
self,
|
|
1366
1408
|
autorun(() => {
|
|
1367
|
-
//
|
|
1368
|
-
// xref solution https://github.com/mobxjs/mobx/issues/266#issuecomment-222007278
|
|
1369
|
-
// xref problem https://github.com/GMOD/react-msaview/issues/75
|
|
1409
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
1370
1410
|
self.colStats
|
|
1411
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
1371
1412
|
self.colStatsSums
|
|
1413
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
|
1372
1414
|
self.columns
|
|
1373
1415
|
}),
|
|
1374
1416
|
)
|
|
1417
|
+
|
|
1375
1418
|
// autorun synchronizes treeWidth with treeAreaWidth
|
|
1376
1419
|
addDisposer(
|
|
1377
1420
|
self,
|
package/src/parseGFF.ts
CHANGED
|
@@ -8,23 +8,25 @@ export function parseGFF(str?: string) {
|
|
|
8
8
|
f.split('\t')
|
|
9
9
|
|
|
10
10
|
return {
|
|
11
|
-
seq_id
|
|
12
|
-
source
|
|
13
|
-
type
|
|
14
|
-
start: +start
|
|
15
|
-
end: +end
|
|
16
|
-
score: +score
|
|
17
|
-
strand
|
|
18
|
-
phase
|
|
11
|
+
seq_id: seq_id!,
|
|
12
|
+
source: source!,
|
|
13
|
+
type: type!,
|
|
14
|
+
start: +start!,
|
|
15
|
+
end: +end!,
|
|
16
|
+
score: +score!,
|
|
17
|
+
strand: strand!,
|
|
18
|
+
phase: phase!,
|
|
19
19
|
...Object.fromEntries(
|
|
20
|
-
col9
|
|
20
|
+
col9!
|
|
21
21
|
.split(';')
|
|
22
22
|
.map(f => f.trim())
|
|
23
23
|
.filter(f => !!f)
|
|
24
24
|
.map(f => f.split('='))
|
|
25
25
|
.map(([key, val]) => [
|
|
26
|
-
key
|
|
27
|
-
|
|
26
|
+
key!.trim(),
|
|
27
|
+
val
|
|
28
|
+
? decodeURIComponent(val).trim().split(',').join(' ')
|
|
29
|
+
: undefined,
|
|
28
30
|
]),
|
|
29
31
|
),
|
|
30
32
|
}
|
package/src/parseNewick.ts
CHANGED
|
@@ -59,11 +59,11 @@
|
|
|
59
59
|
*/
|
|
60
60
|
export default function parse(s: string) {
|
|
61
61
|
const ancestors = []
|
|
62
|
-
|
|
62
|
+
|
|
63
63
|
let tree = {} as Record<string, any>
|
|
64
64
|
const tokens = s.split(/\s*(;|\(|\)|,|:)\s*/)
|
|
65
65
|
for (let i = 0; i < tokens.length; i++) {
|
|
66
|
-
const token = tokens[i]
|
|
66
|
+
const token = tokens[i]!
|
|
67
67
|
const subtree = {}
|
|
68
68
|
switch (token) {
|
|
69
69
|
case '(': // new branchset
|
|
@@ -81,7 +81,7 @@ export default function parse(s: string) {
|
|
|
81
81
|
case ':': // optional length next
|
|
82
82
|
break
|
|
83
83
|
default: {
|
|
84
|
-
const x = tokens[i - 1]
|
|
84
|
+
const x = tokens[i - 1]!
|
|
85
85
|
if (x === ')' || x === '(' || x === ',') {
|
|
86
86
|
tree.name = token
|
|
87
87
|
} else if (x === ':') {
|
|
@@ -11,12 +11,12 @@ export default class ClustalMSA {
|
|
|
11
11
|
return this.MSA
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
getRow(name: string) {
|
|
14
|
+
getRow(name: string): string {
|
|
15
15
|
return this.MSA.alns.find(aln => aln.id === name)?.seq || ''
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
getWidth() {
|
|
19
|
-
return this.MSA.alns[0]
|
|
19
|
+
return this.MSA.alns[0]!.seq.length
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
getRowData() {
|
package/src/parsers/FastaMSA.ts
CHANGED
|
@@ -6,7 +6,7 @@ function parseSmallFasta(text: string) {
|
|
|
6
6
|
.filter(t => /\S/.test(t))
|
|
7
7
|
.map(entryText => {
|
|
8
8
|
const [defLine, ...seqLines] = entryText.split('\n')
|
|
9
|
-
const [id, ...description] = defLine
|
|
9
|
+
const [id, ...description] = defLine!.split(' ')
|
|
10
10
|
const descriptionStr = description.join(' ')
|
|
11
11
|
const seqLinesStr = seqLines.join('')
|
|
12
12
|
const sequence = seqLinesStr.replaceAll(/\s/g, '')
|
|
@@ -18,7 +18,7 @@ export default class FastaMSA {
|
|
|
18
18
|
constructor(text: string) {
|
|
19
19
|
this.MSA = {
|
|
20
20
|
seqdata: Object.fromEntries(
|
|
21
|
-
parseSmallFasta(text).map(m => [
|
|
21
|
+
parseSmallFasta(text).map(m => [m.id, m.sequence]),
|
|
22
22
|
),
|
|
23
23
|
}
|
|
24
24
|
}
|
|
@@ -36,11 +36,11 @@ export default class FastaMSA {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
getRow(name: string) {
|
|
39
|
-
return this.MSA
|
|
39
|
+
return this.MSA.seqdata[name] || ''
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
getWidth() {
|
|
43
|
-
const name = Object.keys(this.MSA
|
|
43
|
+
const name = Object.keys(this.MSA.seqdata)[0]!
|
|
44
44
|
return this.getRow(name).length
|
|
45
45
|
}
|
|
46
46
|
|
|
@@ -7,9 +7,9 @@ interface StockholmEntry {
|
|
|
7
7
|
DE?: string[]
|
|
8
8
|
NH?: string[]
|
|
9
9
|
}
|
|
10
|
-
gs
|
|
10
|
+
gs?: {
|
|
11
11
|
AC: Record<string, string>
|
|
12
|
-
DR
|
|
12
|
+
DR?: Record<string, string>
|
|
13
13
|
}
|
|
14
14
|
gc?: {
|
|
15
15
|
SS_cons?: string
|
|
@@ -33,11 +33,11 @@ export default class StockholmMSA {
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
getRow(name: string) {
|
|
36
|
-
return this.MSA
|
|
36
|
+
return this.MSA.seqdata[name] || ''
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
getWidth() {
|
|
40
|
-
const name = Object.keys(this.MSA
|
|
40
|
+
const name = Object.keys(this.MSA.seqdata)[0]!
|
|
41
41
|
return this.getRow(name).length
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -56,7 +56,7 @@ export default class StockholmMSA {
|
|
|
56
56
|
getRowData(rowName: string) {
|
|
57
57
|
return {
|
|
58
58
|
name: rowName,
|
|
59
|
-
accession: this.MSA.gs?.AC
|
|
59
|
+
accession: this.MSA.gs?.AC[rowName],
|
|
60
60
|
dbxref: this.MSA.gs?.DR?.[rowName],
|
|
61
61
|
}
|
|
62
62
|
}
|
|
@@ -74,10 +74,10 @@ export default class StockholmMSA {
|
|
|
74
74
|
.map(([id, dr]) => [id, pdbRegex.exec(dr)] as const)
|
|
75
75
|
.filter((item): item is [string, RegExpExecArray] => !!item[1])
|
|
76
76
|
.map(([id, match]) => {
|
|
77
|
-
const pdb = match[1]
|
|
78
|
-
const chain = match[2]
|
|
79
|
-
const startPos = +match[3]
|
|
80
|
-
const endPos = +match[4]
|
|
77
|
+
const pdb = match[1]!.toLowerCase()
|
|
78
|
+
const chain = match[2]!
|
|
79
|
+
const startPos = +match[3]!
|
|
80
|
+
const endPos = +match[4]!
|
|
81
81
|
return { id, pdb, chain, startPos, endPos }
|
|
82
82
|
})
|
|
83
83
|
|
|
@@ -93,7 +93,7 @@ export default class StockholmMSA {
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
getTree(): NodeWithIds {
|
|
96
|
-
const tree = this.MSA
|
|
96
|
+
const tree = this.MSA.gf.NH?.[0]
|
|
97
97
|
return tree
|
|
98
98
|
? generateNodeIds(parseNewick(tree))
|
|
99
99
|
: {
|
package/src/renderToSvg.tsx
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable react-refresh/only-export-components */
|
|
1
2
|
import React from 'react'
|
|
2
3
|
import { createRoot } from 'react-dom/client'
|
|
3
4
|
import { when } from 'mobx'
|
|
@@ -153,13 +154,11 @@ function CoreRendering({
|
|
|
153
154
|
|
|
154
155
|
<g
|
|
155
156
|
clipPath={`url(#${clipId1})`}
|
|
156
|
-
/* eslint-disable-next-line react/no-danger */
|
|
157
157
|
dangerouslySetInnerHTML={{ __html: ctx1.getSvg().innerHTML }}
|
|
158
158
|
/>
|
|
159
159
|
<g
|
|
160
160
|
clipPath={`url(#${clipId2})`}
|
|
161
161
|
transform={`translate(${treeAreaWidth} 0)`}
|
|
162
|
-
/* eslint-disable-next-line react/no-danger */
|
|
163
162
|
dangerouslySetInnerHTML={{ __html: ctx2.getSvg().innerHTML }}
|
|
164
163
|
/>
|
|
165
164
|
</>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { expect, test } from 'vitest'
|
|
2
|
+
import { mouseOverCoordToGlobalCoord } from './rowCoordinateCalculations'
|
|
3
|
+
test('blanks3', () => {
|
|
4
|
+
const blanks = [2, 5, 8]
|
|
5
|
+
;(
|
|
6
|
+
[
|
|
7
|
+
[0, 0],
|
|
8
|
+
[1, 1],
|
|
9
|
+
[2, 3],
|
|
10
|
+
[3, 4],
|
|
11
|
+
[4, 6],
|
|
12
|
+
[5, 7],
|
|
13
|
+
[6, 9],
|
|
14
|
+
[7, 10],
|
|
15
|
+
] as const
|
|
16
|
+
).forEach(r => {
|
|
17
|
+
expect(mouseOverCoordToGlobalCoord(blanks, r[0])).toBe(r[1])
|
|
18
|
+
})
|
|
19
|
+
})
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export function mouseOverCoordToGlobalCoord(blanks: number[], pos: number) {
|
|
2
|
+
let i = 0 // 'mouse over coord'
|
|
3
|
+
let j = 0 // 'position in blanks array'
|
|
4
|
+
let k = 0 // 'global coord'/return value
|
|
5
|
+
|
|
6
|
+
for (; i < pos; i++, k++) {
|
|
7
|
+
// skip multiple gaps in a row
|
|
8
|
+
while (j < blanks.length && blanks[j]! - 1 === k) {
|
|
9
|
+
j++
|
|
10
|
+
k++
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return k
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function globalCoordToRowSpecificCoord(seq: string, pos: number) {
|
|
17
|
+
let k = 0
|
|
18
|
+
for (let i = 0; i < pos; i++) {
|
|
19
|
+
if (seq[i] !== '-') {
|
|
20
|
+
k++
|
|
21
|
+
} else if (k >= pos) {
|
|
22
|
+
break
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return k
|
|
26
|
+
}
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const version = '3.2.
|
|
1
|
+
export const version = '3.2.1'
|