p2s_mapper 1.0.0

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.
Files changed (172) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +148 -0
  3. package/dist/alignmentQuality.d.ts +58 -0
  4. package/dist/alignmentQuality.js +108 -0
  5. package/dist/alignmentQuality.js.map +1 -0
  6. package/dist/alphaFoldModels.d.ts +29 -0
  7. package/dist/alphaFoldModels.js +60 -0
  8. package/dist/alphaFoldModels.js.map +1 -0
  9. package/dist/caCoordsToPdb.d.ts +18 -0
  10. package/dist/caCoordsToPdb.js +95 -0
  11. package/dist/caCoordsToPdb.js.map +1 -0
  12. package/dist/chooseMappedEntity.d.ts +55 -0
  13. package/dist/chooseMappedEntity.js +140 -0
  14. package/dist/chooseMappedEntity.js.map +1 -0
  15. package/dist/coordinates.d.ts +66 -0
  16. package/dist/coordinates.js +66 -0
  17. package/dist/coordinates.js.map +1 -0
  18. package/dist/dbIds.d.ts +16 -0
  19. package/dist/dbIds.js +42 -0
  20. package/dist/dbIds.js.map +1 -0
  21. package/dist/extractPerResidueConfidence.d.ts +49 -0
  22. package/dist/extractPerResidueConfidence.js +42 -0
  23. package/dist/extractPerResidueConfidence.js.map +1 -0
  24. package/dist/extractStructureSequences.d.ts +142 -0
  25. package/dist/extractStructureSequences.js +217 -0
  26. package/dist/extractStructureSequences.js.map +1 -0
  27. package/dist/fetchUtils.d.ts +34 -0
  28. package/dist/fetchUtils.js +91 -0
  29. package/dist/fetchUtils.js.map +1 -0
  30. package/dist/index.d.ts +23 -0
  31. package/dist/index.js +46 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/invertMap.d.ts +2 -0
  34. package/dist/invertMap.js +8 -0
  35. package/dist/invertMap.js.map +1 -0
  36. package/dist/isoformRanking.d.ts +47 -0
  37. package/dist/isoformRanking.js +91 -0
  38. package/dist/isoformRanking.js.map +1 -0
  39. package/dist/mappings.d.ts +58 -0
  40. package/dist/mappings.js +193 -0
  41. package/dist/mappings.js.map +1 -0
  42. package/dist/package.json +1 -0
  43. package/dist/pairwiseAlignment.d.ts +35 -0
  44. package/dist/pairwiseAlignment.js +337 -0
  45. package/dist/pairwiseAlignment.js.map +1 -0
  46. package/dist/pdbUniProtMapping.d.ts +75 -0
  47. package/dist/pdbUniProtMapping.js +241 -0
  48. package/dist/pdbUniProtMapping.js.map +1 -0
  49. package/dist/pdbeBestStructures.d.ts +23 -0
  50. package/dist/pdbeBestStructures.js +79 -0
  51. package/dist/pdbeBestStructures.js.map +1 -0
  52. package/dist/pdbeEntryMolecules.d.ts +7 -0
  53. package/dist/pdbeEntryMolecules.js +39 -0
  54. package/dist/pdbeEntryMolecules.js.map +1 -0
  55. package/dist/siftsNumbering.d.ts +23 -0
  56. package/dist/siftsNumbering.js +44 -0
  57. package/dist/siftsNumbering.js.map +1 -0
  58. package/dist/stripStopCodon.d.ts +15 -0
  59. package/dist/stripStopCodon.js +24 -0
  60. package/dist/stripStopCodon.js.map +1 -0
  61. package/dist/structureFormat.d.ts +40 -0
  62. package/dist/structureFormat.js +54 -0
  63. package/dist/structureFormat.js.map +1 -0
  64. package/dist/structureSources.d.ts +28 -0
  65. package/dist/structureSources.js +76 -0
  66. package/dist/structureSources.js.map +1 -0
  67. package/dist/structureUrls.d.ts +54 -0
  68. package/dist/structureUrls.js +147 -0
  69. package/dist/structureUrls.js.map +1 -0
  70. package/dist/types.d.ts +14 -0
  71. package/dist/types.js +27 -0
  72. package/dist/types.js.map +1 -0
  73. package/dist/uniProtSearch.d.ts +32 -0
  74. package/dist/uniProtSearch.js +114 -0
  75. package/dist/uniProtSearch.js.map +1 -0
  76. package/esm/alignmentQuality.d.ts +58 -0
  77. package/esm/alignmentQuality.js +100 -0
  78. package/esm/alignmentQuality.js.map +1 -0
  79. package/esm/alphaFoldModels.d.ts +29 -0
  80. package/esm/alphaFoldModels.js +55 -0
  81. package/esm/alphaFoldModels.js.map +1 -0
  82. package/esm/caCoordsToPdb.d.ts +18 -0
  83. package/esm/caCoordsToPdb.js +91 -0
  84. package/esm/caCoordsToPdb.js.map +1 -0
  85. package/esm/chooseMappedEntity.d.ts +55 -0
  86. package/esm/chooseMappedEntity.js +134 -0
  87. package/esm/chooseMappedEntity.js.map +1 -0
  88. package/esm/coordinates.d.ts +66 -0
  89. package/esm/coordinates.js +58 -0
  90. package/esm/coordinates.js.map +1 -0
  91. package/esm/dbIds.d.ts +16 -0
  92. package/esm/dbIds.js +35 -0
  93. package/esm/dbIds.js.map +1 -0
  94. package/esm/extractPerResidueConfidence.d.ts +49 -0
  95. package/esm/extractPerResidueConfidence.js +38 -0
  96. package/esm/extractPerResidueConfidence.js.map +1 -0
  97. package/esm/extractStructureSequences.d.ts +142 -0
  98. package/esm/extractStructureSequences.js +205 -0
  99. package/esm/extractStructureSequences.js.map +1 -0
  100. package/esm/fetchUtils.d.ts +34 -0
  101. package/esm/fetchUtils.js +82 -0
  102. package/esm/fetchUtils.js.map +1 -0
  103. package/esm/index.d.ts +23 -0
  104. package/esm/index.js +30 -0
  105. package/esm/index.js.map +1 -0
  106. package/esm/invertMap.d.ts +2 -0
  107. package/esm/invertMap.js +5 -0
  108. package/esm/invertMap.js.map +1 -0
  109. package/esm/isoformRanking.d.ts +47 -0
  110. package/esm/isoformRanking.js +86 -0
  111. package/esm/isoformRanking.js.map +1 -0
  112. package/esm/mappings.d.ts +58 -0
  113. package/esm/mappings.js +179 -0
  114. package/esm/mappings.js.map +1 -0
  115. package/esm/pairwiseAlignment.d.ts +35 -0
  116. package/esm/pairwiseAlignment.js +328 -0
  117. package/esm/pairwiseAlignment.js.map +1 -0
  118. package/esm/pdbUniProtMapping.d.ts +75 -0
  119. package/esm/pdbUniProtMapping.js +231 -0
  120. package/esm/pdbUniProtMapping.js.map +1 -0
  121. package/esm/pdbeBestStructures.d.ts +23 -0
  122. package/esm/pdbeBestStructures.js +73 -0
  123. package/esm/pdbeBestStructures.js.map +1 -0
  124. package/esm/pdbeEntryMolecules.d.ts +7 -0
  125. package/esm/pdbeEntryMolecules.js +35 -0
  126. package/esm/pdbeEntryMolecules.js.map +1 -0
  127. package/esm/siftsNumbering.d.ts +23 -0
  128. package/esm/siftsNumbering.js +40 -0
  129. package/esm/siftsNumbering.js.map +1 -0
  130. package/esm/stripStopCodon.d.ts +15 -0
  131. package/esm/stripStopCodon.js +20 -0
  132. package/esm/stripStopCodon.js.map +1 -0
  133. package/esm/structureFormat.d.ts +40 -0
  134. package/esm/structureFormat.js +48 -0
  135. package/esm/structureFormat.js.map +1 -0
  136. package/esm/structureSources.d.ts +28 -0
  137. package/esm/structureSources.js +71 -0
  138. package/esm/structureSources.js.map +1 -0
  139. package/esm/structureUrls.d.ts +54 -0
  140. package/esm/structureUrls.js +134 -0
  141. package/esm/structureUrls.js.map +1 -0
  142. package/esm/types.d.ts +14 -0
  143. package/esm/types.js +23 -0
  144. package/esm/types.js.map +1 -0
  145. package/esm/uniProtSearch.d.ts +32 -0
  146. package/esm/uniProtSearch.js +110 -0
  147. package/esm/uniProtSearch.js.map +1 -0
  148. package/package.json +63 -0
  149. package/src/alignmentQuality.ts +132 -0
  150. package/src/alphaFoldModels.ts +91 -0
  151. package/src/caCoordsToPdb.ts +111 -0
  152. package/src/chooseMappedEntity.ts +198 -0
  153. package/src/coordinates.ts +119 -0
  154. package/src/dbIds.ts +46 -0
  155. package/src/extractPerResidueConfidence.ts +88 -0
  156. package/src/extractStructureSequences.ts +342 -0
  157. package/src/fetchUtils.ts +110 -0
  158. package/src/index.ts +34 -0
  159. package/src/invertMap.ts +4 -0
  160. package/src/isoformRanking.ts +139 -0
  161. package/src/mappings.ts +230 -0
  162. package/src/pairwiseAlignment.ts +423 -0
  163. package/src/pdbUniProtMapping.ts +320 -0
  164. package/src/pdbeBestStructures.ts +94 -0
  165. package/src/pdbeEntryMolecules.ts +37 -0
  166. package/src/siftsNumbering.ts +61 -0
  167. package/src/stripStopCodon.ts +20 -0
  168. package/src/structureFormat.ts +70 -0
  169. package/src/structureSources.ts +101 -0
  170. package/src/structureUrls.ts +171 -0
  171. package/src/types.ts +30 -0
  172. package/src/uniProtSearch.ts +212 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uniProtSearch.js","sourceRoot":"","sources":["../src/uniProtSearch.ts"],"names":[],"mappings":";;AAgFA,gDAQC;AA2DD,oDAgEC;AAnND,mDAA2C;AAC3C,yCAImB;AAsCnB,MAAM,cAAc,GAClB,6DAA6D,CAAA;AAE/D,SAAS,mBAAmB,CAC1B,MAAsC;IAEtC,OAAO;QACL,SAAS,EAAE,MAAM,CAAC,gBAAgB;QAClC,EAAE,EAAE,MAAM,CAAC,WAAW;QACtB,QAAQ,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK;QAC5C,YAAY,EACV,MAAM,CAAC,QAAQ,EAAE,UAAU,IAAI,MAAM,CAAC,QAAQ,EAAE,cAAc;QAChE,WAAW,EAAE,MAAM,CAAC,kBAAkB,EAAE,eAAe,EAAE,QAAQ,EAAE,KAAK;QACxE,UAAU,EAAE,MAAM,CAAC,SAAS,KAAK,iCAAiC;KACnE,CAAA;AACH,CAAC;AAED,KAAK,UAAU,aAAa,CAC1B,KAAa,EACb,IAAY,EACZ,IAAmB;IAEnB,MAAM,GAAG,GAAG,mDAAmD,kBAAkB,CAAC,KAAK,CAAC,WAAW,cAAc,SAAS,IAAI,EAAE,CAAA;IAChI,MAAM,IAAI,GAAG,MAAM,IAAA,yBAAS,EAAmB,GAAG,EAAE,IAAI,CAAC,CAAA;IACzD,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAA;AAC9C,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,kBAAkB,CAAC,QAAgB,EAAE,UAAmB;IACtE,OAAO;QACL,eAAe,QAAQ,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG;QACjD,UAAU,CAAC,CAAC,CAAC,eAAe,UAAU,EAAE,CAAC,CAAC,CAAC,SAAS;QACpD,eAAe;KAChB;SACE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC;SAC5B,IAAI,CAAC,OAAO,CAAC,CAAA;AAClB,CAAC;AAOD,KAAK,UAAU,YAAY,CACzB,EAAU,EACV,IAAmB;IAEnB,MAAM,KAAK,GAAG,IAAA,gCAAqB,EAAC,EAAE,CAAC,CAAA;IACvC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAA;IAC1C,CAAC;IACD,IAAI,CAAC;QACH,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC,KAAK,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAA;IAC5E,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,0BAA0B,EAAE,GAAG,EAAE,CAAC,CAAC,CAAA;QACjD,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAA;IAClC,CAAC;AACH,CAAC;AAED,KAAK,UAAU,gBAAgB,CAC7B,QAAgB,EAChB,UAA8B,EAC9B,IAAmB;IAEnB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,aAAa,CACjC,kBAAkB,CAAC,QAAQ,EAAE,UAAU,CAAC,EACxC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EACnB,IAAI,CACL,CAAA;QACD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAA;IACtC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,+BAA+B,QAAQ,GAAG,EAAE,CAAC,CAAC,CAAA;QAC5D,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAA;IAClC,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,OAAuB;IACjD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAA;IAC9B,MAAM,MAAM,GAAmB,EAAE,CAAA;IACjC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;YAC/B,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAA;YACzB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QACpB,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAQM,KAAK,UAAU,oBAAoB,CACxC,EACE,aAAa,GAAG,EAAE,EAClB,MAAM,EACN,QAAQ,EACR,UAAU,GAOX,EACD,IAAmB;IAEnB,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,CAAA;IAC1C,MAAM,cAAc,GAAG,MAAM,CAAC,CAAC,CAAC,IAAA,+BAAoB,EAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IACxE,IAAI,cAAc,IAAI,IAAA,iCAAsB,EAAC,cAAc,CAAC,EAAE,CAAC;QAC7D,WAAW,CAAC,GAAG,CAAC,cAAc,CAAC,CAAA;IACjC,CAAC;IAED,6EAA6E;IAC7E,2EAA2E;IAC3E,uEAAuE;IACvE,MAAM,CAAC,WAAW,EAAE,UAAU,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC,CAAC;QAC/D,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,QAAQ,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;KACpE,CAAC,CAAA;IAEF,IAAI,OAAO,GAAG,kBAAkB,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAA;IACrE,wEAAwE;IACxE,6EAA6E;IAC7E,yEAAyE;IACzE,MAAM,mBAAmB,GACvB,UAAU,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,SAAS,CAAA;IACzE,IAAI,mBAAmB,EAAE,CAAC;QACxB,OAAO,GAAG,kBAAkB,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAA;IAC5E,CAAC;IAED,MAAM,cAAc,GAAG,WAAW,CAAC,IAAI,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACvE,MAAM,WAAW,GACf,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,MAAM;QACrD,CAAC,mBAAmB,EAAE,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAEpD,4EAA4E;IAC5E,6EAA6E;IAC7E,IACE,OAAO,CAAC,MAAM,KAAK,CAAC;QACpB,cAAc,GAAG,CAAC;QAClB,cAAc,KAAK,WAAW,EAC9B,CAAC;QACD,MAAM,CACJ,mBAAmB,EAAE,KAAK;YAC1B,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,EAAE,KAAK,CACpD,CAAA;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE,OAAO,CAAC,QAAQ,CACvB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CACtD;QACD,cAAc;QACd,WAAW;KACZ,CAAA;AACH,CAAC"}
@@ -0,0 +1,58 @@
1
+ import type { PairwiseAlignment } from './mappings.ts';
2
+ export interface AlignmentQuality {
3
+ /** columns carrying a residue on both rows, i.e. mapped positions */
4
+ aligned: number;
5
+ identical: number;
6
+ transcriptLength: number;
7
+ structureLength: number;
8
+ /** identical over aligned; 0 when nothing aligned */
9
+ identity: number;
10
+ /** identical over the shorter of the two sequences: the statistic that
11
+ * separates a real match from a chance local alignment, see below */
12
+ identityOverShorter: number;
13
+ /** aligned over the structure's length */
14
+ structureCoverage: number;
15
+ /** first and last transcript residue the alignment covers, 1-based
16
+ * inclusive; 0 when nothing aligned. A structure is usually a fragment, and
17
+ * which part of the protein it holds is the reader's first question. */
18
+ transcriptStart: number;
19
+ transcriptEnd: number;
20
+ }
21
+ /**
22
+ * Below either floor the mapped positions are as likely to be chance as
23
+ * homology. Local alignment picks the best-scoring stretch of two sequences,
24
+ * so identity over the aligned columns is inflated whatever the inputs:
25
+ * measured 2026-09-11 on random sequences, Smith-Waterman with BLOSUM62 gave
26
+ * 37% identity over 27 columns at 300 × 300 and 30% over 100 columns at
27
+ * 500 × 150, two thirds of the shorter chain, and p53 against a ribosomal
28
+ * protein (7K00 RPS11) gives 31 identities at a third identity. Neither local
29
+ * identity nor coverage alone separates those from a real match. Identical
30
+ * residues over the shorter sequence does: 0.03, 0.20 and 0.24 for the chance
31
+ * cases against 0.9 or better for any structure of the transcript's protein
32
+ * and about 0.6 for an ortholog.
33
+ *
34
+ * A short alignment has to be nearly perfect instead: a 10-residue decoy with
35
+ * 3 identities sits at the ratio floor, while a real bound peptide (1YCR's 15
36
+ * p53 residues, 4ZZJ's 7) is identical or one off. So under
37
+ * SHORT_ALIGNMENT_RESIDUES identical residues the ratio floor rises to
38
+ * SHORT_ALIGNMENT_IDENTITY, and under MIN_IDENTICAL_RESIDUES nothing passes,
39
+ * since a tetrapeptide is never the gene's product.
40
+ */
41
+ export declare const LOW_IDENTITY_OVER_SHORTER = 0.3;
42
+ export declare const SHORT_ALIGNMENT_RESIDUES = 20;
43
+ export declare const SHORT_ALIGNMENT_IDENTITY = 0.8;
44
+ export declare const MIN_IDENTICAL_RESIDUES = 5;
45
+ export declare function alignmentQuality(pa: PairwiseAlignment): AlignmentQuality;
46
+ export declare function isLowSimilarity(q: AlignmentQuality): boolean;
47
+ /** One line for the alignment header: "87% identity over 219 of 393
48
+ * structure residues". */
49
+ export declare function describeAlignmentQuality(q: AlignmentQuality): string;
50
+ /**
51
+ * The same counted from the transcript's side, for the always-visible header:
52
+ * how much of the gene's protein this structure speaks for is what decides
53
+ * whether a codon has a residue at all.
54
+ */
55
+ export declare function describeTranscriptCoverage(q: AlignmentQuality): string;
56
+ /** Which residues of the transcript a fragment holds, or undefined when it
57
+ * covers the whole translation. */
58
+ export declare function describeCoveredRange(q: AlignmentQuality): string | undefined;
@@ -0,0 +1,100 @@
1
+ import { alignmentLength, structureAlignedSeq, transcriptAlignedSeq, } from "./mappings.js";
2
+ /**
3
+ * Below either floor the mapped positions are as likely to be chance as
4
+ * homology. Local alignment picks the best-scoring stretch of two sequences,
5
+ * so identity over the aligned columns is inflated whatever the inputs:
6
+ * measured 2026-09-11 on random sequences, Smith-Waterman with BLOSUM62 gave
7
+ * 37% identity over 27 columns at 300 × 300 and 30% over 100 columns at
8
+ * 500 × 150, two thirds of the shorter chain, and p53 against a ribosomal
9
+ * protein (7K00 RPS11) gives 31 identities at a third identity. Neither local
10
+ * identity nor coverage alone separates those from a real match. Identical
11
+ * residues over the shorter sequence does: 0.03, 0.20 and 0.24 for the chance
12
+ * cases against 0.9 or better for any structure of the transcript's protein
13
+ * and about 0.6 for an ortholog.
14
+ *
15
+ * A short alignment has to be nearly perfect instead: a 10-residue decoy with
16
+ * 3 identities sits at the ratio floor, while a real bound peptide (1YCR's 15
17
+ * p53 residues, 4ZZJ's 7) is identical or one off. So under
18
+ * SHORT_ALIGNMENT_RESIDUES identical residues the ratio floor rises to
19
+ * SHORT_ALIGNMENT_IDENTITY, and under MIN_IDENTICAL_RESIDUES nothing passes,
20
+ * since a tetrapeptide is never the gene's product.
21
+ */
22
+ export const LOW_IDENTITY_OVER_SHORTER = 0.3;
23
+ export const SHORT_ALIGNMENT_RESIDUES = 20;
24
+ export const SHORT_ALIGNMENT_IDENTITY = 0.8;
25
+ export const MIN_IDENTICAL_RESIDUES = 5;
26
+ export function alignmentQuality(pa) {
27
+ const t = transcriptAlignedSeq(pa);
28
+ const s = structureAlignedSeq(pa);
29
+ let aligned = 0;
30
+ let identical = 0;
31
+ let transcriptLength = 0;
32
+ let structureLength = 0;
33
+ let transcriptStart = 0;
34
+ let transcriptEnd = 0;
35
+ for (let i = 0; i < alignmentLength(pa); i++) {
36
+ const a = t[i];
37
+ const b = s[i];
38
+ const ta = a !== '-';
39
+ const sb = b !== '-';
40
+ if (ta) {
41
+ transcriptLength++;
42
+ }
43
+ if (sb) {
44
+ structureLength++;
45
+ }
46
+ if (ta && sb) {
47
+ aligned++;
48
+ transcriptStart = transcriptStart || transcriptLength;
49
+ transcriptEnd = transcriptLength;
50
+ if (a.toUpperCase() === b.toUpperCase()) {
51
+ identical++;
52
+ }
53
+ }
54
+ }
55
+ const shorter = Math.min(transcriptLength, structureLength);
56
+ return {
57
+ aligned,
58
+ identical,
59
+ transcriptLength,
60
+ structureLength,
61
+ identity: aligned ? identical / aligned : 0,
62
+ identityOverShorter: shorter ? identical / shorter : 0,
63
+ structureCoverage: structureLength ? aligned / structureLength : 0,
64
+ transcriptStart,
65
+ transcriptEnd,
66
+ };
67
+ }
68
+ export function isLowSimilarity(q) {
69
+ const floor = q.identical < SHORT_ALIGNMENT_RESIDUES
70
+ ? SHORT_ALIGNMENT_IDENTITY
71
+ : LOW_IDENTITY_OVER_SHORTER;
72
+ return q.identical < MIN_IDENTICAL_RESIDUES || q.identityOverShorter < floor;
73
+ }
74
+ /** One line for the alignment header: "87% identity over 219 of 393
75
+ * structure residues". */
76
+ export function describeAlignmentQuality(q) {
77
+ if (q.aligned === 0) {
78
+ return 'no residues aligned';
79
+ }
80
+ return `${Math.round(q.identity * 100)}% identity over ${q.aligned} of ${q.structureLength} structure residues`;
81
+ }
82
+ /**
83
+ * The same counted from the transcript's side, for the always-visible header:
84
+ * how much of the gene's protein this structure speaks for is what decides
85
+ * whether a codon has a residue at all.
86
+ */
87
+ export function describeTranscriptCoverage(q) {
88
+ if (q.aligned === 0) {
89
+ return 'no residues aligned';
90
+ }
91
+ return `${Math.round(q.identity * 100)}% identity, ${q.aligned} of ${q.transcriptLength} transcript residues covered`;
92
+ }
93
+ /** Which residues of the transcript a fragment holds, or undefined when it
94
+ * covers the whole translation. */
95
+ export function describeCoveredRange(q) {
96
+ return q.aligned === 0 || q.aligned === q.transcriptLength
97
+ ? undefined
98
+ : `covers transcript residues ${q.transcriptStart}–${q.transcriptEnd}`;
99
+ }
100
+ //# sourceMappingURL=alignmentQuality.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alignmentQuality.js","sourceRoot":"","sources":["../src/alignmentQuality.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import type { FetchOptions } from './fetchUtils.ts';
2
+ export interface AlphaFoldModel {
3
+ /** UniProt accession, with an isoform suffix on an isoform model */
4
+ accession: string;
5
+ url: string;
6
+ confidenceUrl?: string;
7
+ sequence: string;
8
+ }
9
+ export declare function parseAlphaFoldModels(json: unknown): AlphaFoldModel[];
10
+ /**
11
+ * Every model AlphaFold DB has for an accession: the canonical one and any
12
+ * isoform models, each with its file url and sequence. Asked rather than
13
+ * derived from the accession, because a derived `AF-<acc>-F1-model_v6` does
14
+ * not exist past the length cap (dystrophin has fourteen isoform models and no
15
+ * F1) and moves with every model version. An accession AlphaFold has never
16
+ * folded answers 400 or 404, which is no models rather than an error.
17
+ */
18
+ export declare function fetchAlphaFoldModels(uniprotId: string, opts?: FetchOptions): Promise<AlphaFoldModel[]>;
19
+ /**
20
+ * The model to open for a gene's transcripts: one folded from exactly a
21
+ * transcript's translation, canonical first, so the view maps it as an
22
+ * identity; else the canonical model; else the longest isoform model.
23
+ *
24
+ * Takes any record of sequences, since the structure loader knows one
25
+ * translation rather than a gene's isoforms.
26
+ */
27
+ export declare function pickAlphaFoldModel(models: AlphaFoldModel[], isoformSequences: Record<string, {
28
+ seq: string;
29
+ }> | undefined): AlphaFoldModel | undefined;
@@ -0,0 +1,55 @@
1
+ import { httpError, rawfetch } from "./fetchUtils.js";
2
+ import { stripStopCodon } from "./stripStopCodon.js";
3
+ function isPredictionEntry(value) {
4
+ return typeof value === 'object' && value !== null;
5
+ }
6
+ export function parseAlphaFoldModels(json) {
7
+ return (Array.isArray(json) ? json : []).flatMap(e => isPredictionEntry(e) &&
8
+ typeof e.uniprotAccession === 'string' &&
9
+ typeof e.cifUrl === 'string' &&
10
+ typeof e.sequence === 'string'
11
+ ? [
12
+ {
13
+ accession: e.uniprotAccession,
14
+ url: e.cifUrl,
15
+ confidenceUrl: typeof e.plddtDocUrl === 'string' ? e.plddtDocUrl : undefined,
16
+ sequence: e.sequence,
17
+ },
18
+ ]
19
+ : []);
20
+ }
21
+ /**
22
+ * Every model AlphaFold DB has for an accession: the canonical one and any
23
+ * isoform models, each with its file url and sequence. Asked rather than
24
+ * derived from the accession, because a derived `AF-<acc>-F1-model_v6` does
25
+ * not exist past the length cap (dystrophin has fourteen isoform models and no
26
+ * F1) and moves with every model version. An accession AlphaFold has never
27
+ * folded answers 400 or 404, which is no models rather than an error.
28
+ */
29
+ export async function fetchAlphaFoldModels(uniprotId, opts) {
30
+ const url = `https://alphafold.ebi.ac.uk/api/prediction/${encodeURIComponent(uniprotId)}`;
31
+ const res = await rawfetch(url, opts);
32
+ if (res.status === 400 || res.status === 404) {
33
+ return [];
34
+ }
35
+ if (!res.ok) {
36
+ throw await httpError(res, url);
37
+ }
38
+ return parseAlphaFoldModels(await res.json());
39
+ }
40
+ /**
41
+ * The model to open for a gene's transcripts: one folded from exactly a
42
+ * transcript's translation, canonical first, so the view maps it as an
43
+ * identity; else the canonical model; else the longest isoform model.
44
+ *
45
+ * Takes any record of sequences, since the structure loader knows one
46
+ * translation rather than a gene's isoforms.
47
+ */
48
+ export function pickAlphaFoldModel(models, isoformSequences) {
49
+ const translations = new Set(Object.values(isoformSequences ?? {}).map(v => stripStopCodon(v.seq)));
50
+ const canonicalFirst = [...models].sort((a, b) => Number(a.accession.includes('-')) - Number(b.accession.includes('-')));
51
+ return (canonicalFirst.find(m => translations.has(m.sequence)) ??
52
+ canonicalFirst.find(m => !m.accession.includes('-')) ??
53
+ [...models].sort((a, b) => b.sequence.length - a.sequence.length)[0]);
54
+ }
55
+ //# sourceMappingURL=alphaFoldModels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alphaFoldModels.js","sourceRoot":"","sources":["../src/alphaFoldModels.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Convert Foldseek tCa coordinates and tSeq to PDB format
3
+ * tCa is a comma-separated string of x,y,z triplets
4
+ * tSeq is the amino acid sequence
5
+ */
6
+ export declare function caCoordsToPdb(tCa: string, tSeq: string, chainId?: string, title?: string): string;
7
+ /**
8
+ * Whether a Foldseek hit carries tCa data that can be converted to PDB. A type
9
+ * predicate rather than a boolean so a guarded caller can pass `hit.tCa`/
10
+ * `hit.tSeq` straight to caCoordsToPdb without re-asserting they're defined.
11
+ */
12
+ export declare function hasValidCaCoords<T extends {
13
+ tCa?: string;
14
+ tSeq?: string;
15
+ }>(hit: T): hit is T & {
16
+ tCa: string;
17
+ tSeq: string;
18
+ };
@@ -0,0 +1,91 @@
1
+ // 3-letter amino acid codes
2
+ const AA_3LETTER = {
3
+ A: 'ALA',
4
+ C: 'CYS',
5
+ D: 'ASP',
6
+ E: 'GLU',
7
+ F: 'PHE',
8
+ G: 'GLY',
9
+ H: 'HIS',
10
+ I: 'ILE',
11
+ K: 'LYS',
12
+ L: 'LEU',
13
+ M: 'MET',
14
+ N: 'ASN',
15
+ P: 'PRO',
16
+ Q: 'GLN',
17
+ R: 'ARG',
18
+ S: 'SER',
19
+ T: 'THR',
20
+ V: 'VAL',
21
+ W: 'TRP',
22
+ Y: 'TYR',
23
+ X: 'UNK', // Unknown
24
+ };
25
+ function padLeft(str, len) {
26
+ return str.padStart(len, ' ');
27
+ }
28
+ function padRight(str, len) {
29
+ return str.padEnd(len, ' ');
30
+ }
31
+ function formatCoord(val) {
32
+ return val.toFixed(3).padStart(8, ' ');
33
+ }
34
+ /**
35
+ * Convert Foldseek tCa coordinates and tSeq to PDB format
36
+ * tCa is a comma-separated string of x,y,z triplets
37
+ * tSeq is the amino acid sequence
38
+ */
39
+ export function caCoordsToPdb(tCa, tSeq, chainId = 'A', title) {
40
+ const coords = tCa.split(',').map(Number);
41
+ const lines = [];
42
+ // Add header
43
+ if (title) {
44
+ lines.push(`TITLE ${title}`);
45
+ }
46
+ lines.push('REMARK 1 Generated from Foldseek Cα coordinates');
47
+ let atomNum = 1;
48
+ let resNum = 1;
49
+ for (let i = 0; i < coords.length - 2; i += 3) {
50
+ const x = coords[i];
51
+ const y = coords[i + 1];
52
+ const z = coords[i + 2];
53
+ const aa = tSeq[resNum - 1] ?? 'X';
54
+ const resName = AA_3LETTER[aa] ?? 'UNK';
55
+ if (x === undefined || y === undefined || z === undefined) {
56
+ break;
57
+ }
58
+ // PDB ATOM record format
59
+ // Columns: 1-6 "ATOM ", 7-11 serial, 13-16 name, 17 altLoc, 18-20 resName,
60
+ // 22 chainID, 23-26 resSeq, 27 iCode, 31-38 x, 39-46 y, 47-54 z,
61
+ // 55-60 occupancy, 61-66 tempFactor, 77-78 element
62
+ const line = 'ATOM ' +
63
+ padLeft(String(atomNum), 5) +
64
+ ' CA ' +
65
+ padRight(resName, 3) +
66
+ ' ' +
67
+ chainId +
68
+ padLeft(String(resNum), 4) +
69
+ ' ' +
70
+ formatCoord(x) +
71
+ formatCoord(y) +
72
+ formatCoord(z) +
73
+ ' 1.00 0.00 C';
74
+ lines.push(line);
75
+ atomNum++;
76
+ resNum++;
77
+ }
78
+ lines.push('END');
79
+ return lines.join('\n');
80
+ }
81
+ /**
82
+ * Whether a Foldseek hit carries tCa data that can be converted to PDB. A type
83
+ * predicate rather than a boolean so a guarded caller can pass `hit.tCa`/
84
+ * `hit.tSeq` straight to caCoordsToPdb without re-asserting they're defined.
85
+ */
86
+ export function hasValidCaCoords(hit) {
87
+ const { tCa, tSeq } = hit;
88
+ // Need at least 3 coordinates (x,y,z for one residue) and a sequence
89
+ return !!tCa && !!tSeq && tCa.split(',').length >= 3;
90
+ }
91
+ //# sourceMappingURL=caCoordsToPdb.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"caCoordsToPdb.js","sourceRoot":"","sources":["../src/caCoordsToPdb.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,MAAM,UAAU,GAA2B;IACzC,CAAC,EAAE,KAAK;IACR,CAAC,EAAE,KAAK;IACR,CAAC,EAAE,KAAK;IACR,CAAC,EAAE,KAAK;IACR,CAAC,EAAE,KAAK;IACR,CAAC,EAAE,KAAK;IACR,CAAC,EAAE,KAAK;IACR,CAAC,EAAE,KAAK;IACR,CAAC,EAAE,KAAK;IACR,CAAC,EAAE,KAAK;IACR,CAAC,EAAE,KAAK;IACR,CAAC,EAAE,KAAK;IACR,CAAC,EAAE,KAAK;IACR,CAAC,EAAE,KAAK;IACR,CAAC,EAAE,KAAK;IACR,CAAC,EAAE,KAAK;IACR,CAAC,EAAE,KAAK;IACR,CAAC,EAAE,KAAK;IACR,CAAC,EAAE,KAAK;IACR,CAAC,EAAE,KAAK;IACR,CAAC,EAAE,KAAK,EAAE,UAAU;CACrB,CAAA;AAED,SAAS,OAAO,CAAC,GAAW,EAAE,GAAW;IACvC,OAAO,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;AAC/B,CAAC;AAED,SAAS,QAAQ,CAAC,GAAW,EAAE,GAAW;IACxC,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;AAC7B,CAAC;AAED,SAAS,WAAW,CAAC,GAAW;IAC9B,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAA;AACxC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAC3B,GAAW,EACX,IAAY,EACZ,OAAO,GAAG,GAAG,EACb,KAAc;IAEd,MAAM,MAAM,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;IACzC,MAAM,KAAK,GAAa,EAAE,CAAA;IAE1B,aAAa;IACb,IAAI,KAAK,EAAE,CAAC;QACV,KAAK,CAAC,IAAI,CAAC,aAAa,KAAK,EAAE,CAAC,CAAA;IAClC,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,mDAAmD,CAAC,CAAA;IAE/D,IAAI,OAAO,GAAG,CAAC,CAAA;IACf,IAAI,MAAM,GAAG,CAAC,CAAA;IAEd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9C,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAA;QACnB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;QACvB,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;QACvB,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,GAAG,CAAA;QAClC,MAAM,OAAO,GAAG,UAAU,CAAC,EAAE,CAAC,IAAI,KAAK,CAAA;QAEvC,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;YAC1D,MAAK;QACP,CAAC;QAED,yBAAyB;QACzB,4EAA4E;QAC5E,iEAAiE;QACjE,mDAAmD;QACnD,MAAM,IAAI,GACR,QAAQ;YACR,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAC3B,QAAQ;YACR,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;YACpB,GAAG;YACH,OAAO;YACP,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC1B,MAAM;YACN,WAAW,CAAC,CAAC,CAAC;YACd,WAAW,CAAC,CAAC,CAAC;YACd,WAAW,CAAC,CAAC,CAAC;YACd,0BAA0B,CAAA;QAE5B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAChB,OAAO,EAAE,CAAA;QACT,MAAM,EAAE,CAAA;IACV,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAEjB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAC9B,GAAM;IAEN,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,CAAA;IACzB,qEAAqE;IACrE,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,CAAA;AACtD,CAAC"}
@@ -0,0 +1,55 @@
1
+ import type { PairwiseAlignment } from './mappings.ts';
2
+ import type { AlignmentAlgorithm } from './types.ts';
3
+ /**
4
+ * Whether a structure interaction (hover/click) should drive genome navigation.
5
+ * Only the transcript's mapped entity may — a hover on any other chain carries
6
+ * that chain's own label_seq_id and would mis-map through the wrong alignment.
7
+ * A structure with no resolved mapping (`mappedEntityId` undefined, e.g. a
8
+ * standalone viewer with no transcript) stays fully interactive.
9
+ */
10
+ export declare function interactionMatchesMappedEntity(entityId: string, mappedEntityId: string | undefined): boolean;
11
+ export interface EntitySelection extends ScoredAlignment {
12
+ /** index into the candidate array of the entity that is the transcript's */
13
+ index: number;
14
+ }
15
+ export interface ScoredAlignment {
16
+ /** alignment of the transcript against the entity (stop codons stripped on
17
+ * both sides, matching the rest of the mapping pipeline) */
18
+ alignment: PairwiseAlignment;
19
+ /** identical aligned residues */
20
+ matches: number;
21
+ /** identical residues over the shorter sequence, the score that picks the
22
+ * entity; see `explainedFraction` */
23
+ explained: number;
24
+ /** the alignment's BLOSUM62 score, gap penalties included */
25
+ score: number;
26
+ }
27
+ /** A candidate entity: its sequence, and whether it is DNA/RNA, which is never
28
+ * the transcript's product however its letters happen to align. */
29
+ export interface EntityCandidate {
30
+ seq: string;
31
+ nucleicAcid?: boolean;
32
+ }
33
+ export declare function explainedFraction(matches: number, transcriptLength: number, entityLength: number): number;
34
+ /**
35
+ * Align one transcript to one entity, stop codons stripped on both sides. An
36
+ * exact match skips the DP entirely; an oversized pair returns undefined rather
37
+ * than locking up the tab. Used both to score every entity of a structure and
38
+ * to honour a user's explicit chain choice.
39
+ */
40
+ export declare function alignTranscriptToEntity(transcript: string, entitySeq: string, algorithm: AlignmentAlgorithm): ScoredAlignment | undefined;
41
+ /**
42
+ * Pick which polymer entity of a structure corresponds to the transcript.
43
+ *
44
+ * The plugin historically hardcoded entity `[0]`, which silently mis-maps every
45
+ * heteromeric / protein-DNA / processed-peptide structure where the protein of
46
+ * interest is some other chain. Selecting by alignment makes the structure self-
47
+ * describe which entity is the gene's protein: an exact sequence match wins
48
+ * outright, otherwise the entity with the highest identity over the shorter
49
+ * sequence (see `explainedFraction`). Nucleic-acid entities are never
50
+ * candidates.
51
+ *
52
+ * Returns `undefined` only when there is nothing to map (no transcript or no
53
+ * protein entities) — never a silent fallback to the wrong entity.
54
+ */
55
+ export declare function chooseMappedEntity(transcript: string, entities: readonly (string | EntityCandidate)[], algorithm: AlignmentAlgorithm): EntitySelection | undefined;
@@ -0,0 +1,134 @@
1
+ import { alignmentTooLarge, scoredAlignment, selfScore, } from "./pairwiseAlignment.js";
2
+ import { stripStopCodon } from "./stripStopCodon.js";
3
+ import { structureAlignedSeq, transcriptAlignedSeq } from "./mappings.js";
4
+ /**
5
+ * Whether a structure interaction (hover/click) should drive genome navigation.
6
+ * Only the transcript's mapped entity may — a hover on any other chain carries
7
+ * that chain's own label_seq_id and would mis-map through the wrong alignment.
8
+ * A structure with no resolved mapping (`mappedEntityId` undefined, e.g. a
9
+ * standalone viewer with no transcript) stays fully interactive.
10
+ */
11
+ export function interactionMatchesMappedEntity(entityId, mappedEntityId) {
12
+ return mappedEntityId === undefined || entityId === mappedEntityId;
13
+ }
14
+ /**
15
+ * Identical residues over the shorter of the two sequences: how much of
16
+ * whichever is smaller, transcript or entity, the other reproduces.
17
+ *
18
+ * A raw match count favours whatever chain is longest, and a complex's partner
19
+ * usually is: on 1H26 the 11-residue p53 peptide matches 11 while CDK2 accrues
20
+ * 58 scattered identities, and on 4ZZJ SIRT1 beats the 7-residue p53 peptide
21
+ * 63 to 6. The Smith-Waterman score is no better there (56 vs 58). Dividing
22
+ * by length asks the question the picker actually has, which chain *is* this
23
+ * gene's product: the peptide scores 0.69 and 0.50, the partners 0.19 and
24
+ * 0.17, and across a ribosome's 55 chains no decoy passes 0.29.
25
+ *
26
+ * Dividing by the *entity's* length alone penalised a fusion construct: a
27
+ * 60-residue target fused to a 370-residue carrier scored 0.14, and a random
28
+ * 10-mer decoy chain with 3 identities beat it a third of the time (measured
29
+ * 2026-09-11). Dividing by the shorter sequence leaves every chain shorter
30
+ * than the transcript scored as before and lets a chain that contains the
31
+ * whole transcript score near 1 however long its tag is. The pseudocount
32
+ * keeps a two-residue fragment that happens to match (a tRNA end in 7K00)
33
+ * from scoring 1.0.
34
+ */
35
+ const EXPLAINED_PSEUDOCOUNT = 5;
36
+ export function explainedFraction(matches, transcriptLength, entityLength) {
37
+ return (matches / (Math.min(transcriptLength, entityLength) + EXPLAINED_PSEUDOCOUNT));
38
+ }
39
+ function countMatches(pa) {
40
+ const a = transcriptAlignedSeq(pa);
41
+ const b = structureAlignedSeq(pa);
42
+ let matches = 0;
43
+ for (let i = 0; i < a.length; i++) {
44
+ const ca = a[i];
45
+ const cb = b[i];
46
+ if (ca !== '-' && cb !== '-' && ca?.toUpperCase() === cb?.toUpperCase()) {
47
+ matches++;
48
+ }
49
+ }
50
+ return matches;
51
+ }
52
+ /**
53
+ * Align one transcript to one entity, stop codons stripped on both sides. An
54
+ * exact match skips the DP entirely; an oversized pair returns undefined rather
55
+ * than locking up the tab. Used both to score every entity of a structure and
56
+ * to honour a user's explicit chain choice.
57
+ */
58
+ export function alignTranscriptToEntity(transcript, entitySeq, algorithm) {
59
+ const t = stripStopCodon(transcript);
60
+ const s = stripStopCodon(entitySeq);
61
+ if (!t || !s || alignmentTooLarge(t.length, s.length)) {
62
+ return undefined;
63
+ }
64
+ if (s === t) {
65
+ return {
66
+ alignment: {
67
+ consensus: '|'.repeat(t.length),
68
+ alns: [
69
+ { id: 'seq1', seq: t },
70
+ { id: 'seq2', seq: s },
71
+ ],
72
+ },
73
+ matches: t.length,
74
+ explained: explainedFraction(t.length, t.length, s.length),
75
+ score: selfScore(t),
76
+ };
77
+ }
78
+ const { alignment, score } = scoredAlignment(t, s, algorithm);
79
+ const matches = countMatches(alignment);
80
+ return {
81
+ alignment,
82
+ matches,
83
+ explained: explainedFraction(matches, t.length, s.length),
84
+ score,
85
+ };
86
+ }
87
+ /**
88
+ * Pick which polymer entity of a structure corresponds to the transcript.
89
+ *
90
+ * The plugin historically hardcoded entity `[0]`, which silently mis-maps every
91
+ * heteromeric / protein-DNA / processed-peptide structure where the protein of
92
+ * interest is some other chain. Selecting by alignment makes the structure self-
93
+ * describe which entity is the gene's protein: an exact sequence match wins
94
+ * outright, otherwise the entity with the highest identity over the shorter
95
+ * sequence (see `explainedFraction`). Nucleic-acid entities are never
96
+ * candidates.
97
+ *
98
+ * Returns `undefined` only when there is nothing to map (no transcript or no
99
+ * protein entities) — never a silent fallback to the wrong entity.
100
+ */
101
+ export function chooseMappedEntity(transcript, entities, algorithm) {
102
+ const t = stripStopCodon(transcript);
103
+ if (!t) {
104
+ return undefined;
105
+ }
106
+ const candidates = entities.map(e => typeof e === 'string'
107
+ ? { seq: stripStopCodon(e) }
108
+ : { ...e, seq: stripStopCodon(e.seq) });
109
+ const exactIndex = candidates.findIndex(c => !c.nucleicAcid && c.seq.length > 0 && c.seq === t);
110
+ if (exactIndex !== -1) {
111
+ const exact = alignTranscriptToEntity(t, candidates[exactIndex].seq, algorithm);
112
+ return { index: exactIndex, ...exact };
113
+ }
114
+ // Each alignment is an O(len(t) * len(s)) main-thread DP, so a complex with
115
+ // many chains pays it once per chain. Homomers and repeated chains share a
116
+ // sequence, so align each distinct one once and reuse the result.
117
+ const bySeq = new Map();
118
+ let best;
119
+ for (let index = 0; index < candidates.length; index++) {
120
+ const { seq, nucleicAcid } = candidates[index];
121
+ if (nucleicAcid) {
122
+ continue;
123
+ }
124
+ if (!bySeq.has(seq)) {
125
+ bySeq.set(seq, alignTranscriptToEntity(t, seq, algorithm));
126
+ }
127
+ const scored = bySeq.get(seq);
128
+ if (scored && (!best || scored.explained > best.explained)) {
129
+ best = { index, ...scored };
130
+ }
131
+ }
132
+ return best;
133
+ }
134
+ //# sourceMappingURL=chooseMappedEntity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"chooseMappedEntity.js","sourceRoot":"","sources":["../src/chooseMappedEntity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ import type { PairwiseAlignment } from './mappings.ts';
2
+ /**
3
+ * Branded coordinate spaces. Every position in this plugin is a bare `number`,
4
+ * but the *meaning* differs: a structure residue index is not interchangeable
5
+ * with a transcript residue index or an alignment column, and mixing them is
6
+ * the root cause of the off-by-one class of bugs. Branding makes the compiler
7
+ * reject cross-space mixing; construct values with the helpers below at the
8
+ * boundaries where raw numbers enter (molstar picks, hover events, features).
9
+ *
10
+ * Conventions: all are 0-based. StructurePos indexes the ungapped structure
11
+ * sequence; TranscriptPos the ungapped transcript sequence; AlignmentCol a
12
+ * column of the pairwise alignment (gaps included).
13
+ */
14
+ type Branded<B extends string> = number & {
15
+ readonly __brand: B;
16
+ };
17
+ export type StructurePos = Branded<'StructurePos'>;
18
+ export type TranscriptPos = Branded<'TranscriptPos'>;
19
+ export type AlignmentCol = Branded<'AlignmentCol'>;
20
+ export declare const structurePos: (n: number) => StructurePos;
21
+ export declare const transcriptPos: (n: number) => TranscriptPos;
22
+ export declare const alignmentCol: (n: number) => AlignmentCol;
23
+ export interface CoordinateMaps {
24
+ structureSeqToTranscriptSeqPosition: Record<number, number>;
25
+ transcriptSeqToStructureSeqPosition: Record<number, number>;
26
+ structurePositionToAlignmentMap: Record<number, number>;
27
+ transcriptPositionToAlignmentMap: Record<number, number>;
28
+ alignmentToStructurePosition: Record<number, number>;
29
+ alignmentToTranscriptPosition: Record<number, number>;
30
+ }
31
+ export interface CoordinateMapper {
32
+ structureToTranscript: (p: StructurePos) => TranscriptPos | undefined;
33
+ transcriptToStructure: (p: TranscriptPos) => StructurePos | undefined;
34
+ structureToAlignment: (p: StructurePos) => AlignmentCol | undefined;
35
+ alignmentToStructure: (c: AlignmentCol) => StructurePos | undefined;
36
+ transcriptToAlignment: (p: TranscriptPos) => AlignmentCol | undefined;
37
+ alignmentToTranscript: (c: AlignmentCol) => TranscriptPos | undefined;
38
+ /**
39
+ * Raw lookup tables, for consumers that iterate the whole map rather than
40
+ * convert a single position (e.g. per-residue track rendering, selection of
41
+ * all aligned residues). Plain numbers — prefer the typed methods above for
42
+ * point conversions.
43
+ */
44
+ readonly maps: CoordinateMaps;
45
+ }
46
+ /**
47
+ * Builds every coordinate conversion once from a pairwise alignment, replacing
48
+ * the scatter of per-getter map builds + repeated invertMap calls. The branded
49
+ * methods are the preferred API; `maps` stays unbranded for whole-map consumers.
50
+ */
51
+ export declare function makeCoordinateMapper(pairwiseAlignment: PairwiseAlignment): CoordinateMapper;
52
+ /**
53
+ * The 0-based half-open structure-position range covering an inclusive range
54
+ * of 1-based transcript residues, the numbering a UniProt feature or a domain
55
+ * map uses. Residues the structure lacks are skipped, so a range that runs
56
+ * past a fragment's end clamps to the last modeled residue; undefined when none
57
+ * of the range aligns to the structure.
58
+ */
59
+ export declare function transcriptRangeToStructureRange(mapper: CoordinateMapper, range: {
60
+ start: number;
61
+ end: number;
62
+ }): {
63
+ start: number;
64
+ end: number;
65
+ } | undefined;
66
+ export {};