protvista-uniprot 2.11.2 → 2.11.3

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "protvista-uniprot",
3
3
  "description": "ProtVista tool for the UniProt website",
4
- "version": "2.11.2",
4
+ "version": "2.11.3",
5
5
  "files": [
6
6
  "dist",
7
7
  "src"
@@ -31,13 +31,13 @@
31
31
  "lit-element": "^2.2.0",
32
32
  "protvista-coloured-sequence": "3.8.13",
33
33
  "protvista-datatable": "3.8.10",
34
- "protvista-feature-adapter": "3.8.13",
34
+ "protvista-feature-adapter": "3.8.15",
35
35
  "protvista-filter": "3.8.4",
36
36
  "protvista-interpro-adapter": "3.8.14",
37
37
  "protvista-interpro-track": "3.8.13",
38
38
  "protvista-manager": "3.8.4",
39
39
  "protvista-navigation": "3.8.10",
40
- "protvista-proteomics-adapter": "3.8.13",
40
+ "protvista-proteomics-adapter": "3.8.15",
41
41
  "protvista-sequence": "3.8.13",
42
42
  "protvista-structure": "3.8.4",
43
43
  "protvista-structure-adapter": "3.8.13",
@@ -0,0 +1,25 @@
1
+ export type AlphafoldPayload = Array<{
2
+ entryId: string;
3
+ gene: string;
4
+ uniprotAccession: string;
5
+ uniprotId: string;
6
+ uniprotDescription: string;
7
+ taxId: number;
8
+ organismScientificName: string;
9
+ uniprotStart: number;
10
+ uniprotEnd: number;
11
+ uniprotSequence: string;
12
+ modelCreatedDate: string;
13
+ latestVersion: number;
14
+ allVersions: number[];
15
+ isReviewed: boolean;
16
+ isReferenceProteome: boolean;
17
+ cifUrl?: string;
18
+ bcifUrl?: string;
19
+ amAnnotationsUrl?: string;
20
+ amAnnotationsHg19Url?: string;
21
+ amAnnotationsHg38Url?: string;
22
+ pdbUrl: string;
23
+ paeImageUrl: string;
24
+ paeDocUrl: string;
25
+ }>;
package/src/config.json CHANGED
@@ -216,7 +216,7 @@
216
216
  "tooltip": "Extent of a region located in a membrane without crossing it"
217
217
  }
218
218
  ]
219
- },
219
+ },
220
220
  {
221
221
  "name": "DOMAINS",
222
222
  "label": "Domains",
@@ -332,7 +332,6 @@
332
332
  ],
333
333
  "tooltip": "Any interesting single amino acid site on the sequence"
334
334
  },
335
-
336
335
  {
337
336
  "name": "ca_bind",
338
337
  "label": "Calcium binding",
@@ -591,6 +590,18 @@
591
590
  ],
592
591
  "tooltip": ""
593
592
  },
593
+ {
594
+ "name": "hpp",
595
+ "label": "Human proteome project",
596
+ "trackType": "protvista-track",
597
+ "data": [
598
+ {
599
+ "adapter": "protvista-proteomics-adapter",
600
+ "url": "https://www.ebi.ac.uk/proteins/api/hpp/{accession}"
601
+ }
602
+ ],
603
+ "tooltip": ""
604
+ },
594
605
  {
595
606
  "name": "proteomics-ptm",
596
607
  "label": "PTM-containing peptide",
@@ -639,13 +650,41 @@
639
650
  "data": [
640
651
  {
641
652
  "adapter": "protvista-alphafold-confidence-adapter",
642
- "url": "https://alphafold.ebi.ac.uk/api/prediction/{accession}"
653
+ "url": [
654
+ "https://alphafold.ebi.ac.uk/api/prediction/{accession}",
655
+ "https://www.ebi.ac.uk/proteins/api/proteins/{accession}"
656
+ ]
643
657
  }
644
658
  ],
645
659
  "tooltip": "AlphaFold prediction confidence"
646
660
  }
647
661
  ]
648
662
  },
663
+ {
664
+ "name": "ALPHAMISSENSE_PATHOGENICITY",
665
+ "label": "AlphaMissense",
666
+ "trackType": "protvista-coloured-sequence",
667
+ "scale": "P:100,A:50,B:0",
668
+ "color-range": "#9a131a:100,#a8a9ad:50,#3d5493:0",
669
+ "tracks": [
670
+ {
671
+ "name": "alphamissense_pathogenicity",
672
+ "label": "AlphaMissense Pathogenicity",
673
+ "labelUrl": "https://alphafold.ebi.ac.uk/entry/{accession}",
674
+ "trackType": "protvista-coloured-sequence",
675
+ "data": [
676
+ {
677
+ "adapter": "protvista-alphamissense-pathogenicity-adapter",
678
+ "url": [
679
+ "https://alphafold.ebi.ac.uk/api/prediction/{accession}",
680
+ "https://www.ebi.ac.uk/proteins/api/proteins/{accession}"
681
+ ]
682
+ }
683
+ ],
684
+ "tooltip": "AlphaMissense prediction pathogenicity"
685
+ }
686
+ ]
687
+ },
649
688
  {
650
689
  "name": "STRUCTURAL",
651
690
  "label": "Structural features",
@@ -1,23 +1,4 @@
1
- type AlphafoldPayload = Array<{
2
- entryId: string;
3
- gene: string;
4
- uniprotAccession: string;
5
- uniprotId: string;
6
- uniprotDescription: string;
7
- taxId: number;
8
- organismScientificName: string;
9
- uniprotStart: number;
10
- uniprotEnd: number;
11
- uniprotSequence: string;
12
- modelCreatedDate: string;
13
- latestVersion: number;
14
- allVersions: number[];
15
- cifUrl: string;
16
- bcifUrl: string;
17
- pdbUrl: string;
18
- paeImageUrl: string;
19
- paeDocUrl: string;
20
- }>;
1
+ import { AlphafoldPayload } from './commonTypes';
21
2
 
22
3
  type AlphafoldConfidencePayload = {
23
4
  residueNumber: Array<number>;
@@ -43,9 +24,19 @@ const loadConfidence = async (
43
24
  }
44
25
  };
45
26
 
46
- export const transformData = async (data: AlphafoldPayload) => {
27
+ type PartialProtein = {
28
+ sequence: {
29
+ sequence: string;
30
+ };
31
+ };
32
+
33
+ export const transformData = async (
34
+ data: AlphafoldPayload,
35
+ protein: PartialProtein
36
+ ) => {
47
37
  const confidenceUrl = getConfidenceURLFromPayload(data);
48
- if (confidenceUrl) {
38
+ const { uniprotSequence } = data?.[0] || {};
39
+ if (confidenceUrl && uniprotSequence === protein.sequence.sequence) {
49
40
  const confidenceData = await loadConfidence(confidenceUrl);
50
41
  return confidenceData?.confidenceCategory.join('');
51
42
  }
@@ -0,0 +1,100 @@
1
+ import { AlphafoldPayload } from './commonTypes';
2
+
3
+ // from example data
4
+ // benign: [0.0448,0.3397]: x < 0.34
5
+ // ambiguous: [0.34,0.564]: 0.34 <= x <= 0.564
6
+ // pathogenic: [0.5646,0.9999]: 0.564 < x
7
+ const benign = 0.34;
8
+ const pathogenic = 0.564;
9
+
10
+ const rowSplitter = /\s*\n\s*/;
11
+ const cellSplitter = /^(.)(\d+)(.),(.+),(\w+)$/;
12
+
13
+ type Row = {
14
+ wildType: string;
15
+ position: number;
16
+ mutated: string;
17
+ pathogenicityScore: number;
18
+ pathogenicityLabel: string;
19
+ };
20
+
21
+ const parseCSV = (rawText: string): string => {
22
+ const positions: Array<Array<Row>> = [];
23
+ for (const [i, row] of rawText.split(rowSplitter).entries()) {
24
+ if (i === 0 || !row) {
25
+ continue;
26
+ }
27
+ const [
28
+ ,
29
+ wildType,
30
+ positionString,
31
+ mutated,
32
+ pathogenicityScore,
33
+ pathogenicityLabel,
34
+ ] = row.match(cellSplitter);
35
+ const position = +positionString;
36
+ const index = position - 1;
37
+ if (!positions[index]) {
38
+ positions[index] = [];
39
+ }
40
+ positions[index].push({
41
+ wildType,
42
+ position,
43
+ mutated,
44
+ pathogenicityScore: +pathogenicityScore,
45
+ pathogenicityLabel,
46
+ });
47
+ }
48
+
49
+ const out = [];
50
+ for (const position of positions) {
51
+ let letter = 'A';
52
+ // maximum
53
+ // const value = Math.max(
54
+ // ...position.map((variation) => variation.pathogenicityScore)
55
+ // );
56
+ // average
57
+ const value =
58
+ position.reduce(
59
+ (acc, variation) => acc + +variation.pathogenicityScore,
60
+ 0
61
+ ) / position.length;
62
+ if (value > pathogenic) {
63
+ letter = 'P';
64
+ } else if (value < benign) {
65
+ letter = 'B';
66
+ }
67
+ out.push(letter);
68
+ }
69
+
70
+ return out.join('');
71
+ };
72
+
73
+ // Load and parse
74
+ const loadAndParseAnnotations = async (url: string): Promise<string> => {
75
+ try {
76
+ const payload = await fetch(url);
77
+ const rawCSV = await payload.text();
78
+ return parseCSV(rawCSV);
79
+ } catch (e) {
80
+ console.error('Could not load AlphaMissense pathogenicity', e);
81
+ }
82
+ };
83
+
84
+ type PartialProtein = {
85
+ sequence: {
86
+ sequence: string;
87
+ };
88
+ };
89
+
90
+ export const transformData = async (
91
+ data: AlphafoldPayload,
92
+ protein: PartialProtein
93
+ ) => {
94
+ const { amAnnotationsUrl, uniprotSequence } = data?.[0] || {};
95
+ if (amAnnotationsUrl && uniprotSequence === protein.sequence.sequence) {
96
+ const variationData = await loadAndParseAnnotations(amAnnotationsUrl);
97
+ // return confidenceData?.confidenceCategory.join('');
98
+ return variationData;
99
+ }
100
+ };
@@ -22,6 +22,7 @@ import { transformData as _transformDataVariationAdapter } from 'protvista-varia
22
22
  import { transformData as _transformDataInterproAdapter } from 'protvista-interpro-adapter';
23
23
  import { transformData as _transformDataProteomicsPTMApdapter } from './protvista-ptm-exchange';
24
24
  import { transformData as _transformDataAlphaFoldConfidenceAdapter } from './protvista-alphafold-confidence';
25
+ import { transformData as _transformDataAlphaMissensePathogenicityAdapter } from './protvista-alphamissense-pathogenicity';
25
26
 
26
27
  import defaultConfig from './config.json';
27
28
  import _ProtvistaUniprotStructure from './protvista-uniprot-structure';
@@ -44,6 +45,9 @@ export const transformDataProteomicsPTMApdapter =
44
45
  export const transformDataAlphaFoldConfidenceAdapter =
45
46
  _transformDataAlphaFoldConfidenceAdapter;
46
47
 
48
+ export const transformDataAlphaMissensePathogenicityAdapter =
49
+ _transformDataAlphaMissensePathogenicityAdapter;
50
+
47
51
  export const filterConfig = _filterConfig;
48
52
  export const colorConfig = _colorConfig;
49
53
  export const ProtvistaUniprotStructure = _ProtvistaUniprotStructure;
@@ -58,6 +62,8 @@ const adapters = {
58
62
  'protvista-proteomics-ptm-adapter': transformDataProteomicsPTMApdapter,
59
63
  'protvista-alphafold-confidence-adapter':
60
64
  transformDataAlphaFoldConfidenceAdapter,
65
+ 'protvista-alphamissense-pathogenicity-adapter':
66
+ transformDataAlphaMissensePathogenicityAdapter,
61
67
  };
62
68
 
63
69
  type TrackType =
@@ -74,7 +80,7 @@ type ProtvistaTrackConfig = {
74
80
  filter: string;
75
81
  trackType: TrackType;
76
82
  data: {
77
- url: string;
83
+ url: string | string[];
78
84
  adapter?:
79
85
  | 'protvista-feature-adapter'
80
86
  | 'protvista-structure-adapter'
@@ -181,9 +187,9 @@ class ProtvistaUniprot extends LitElement {
181
187
  const accession = this.accession;
182
188
  if (accession && this.config) {
183
189
  // Get the list of unique urls
184
- const urls = this.config.categories
185
- .map(({ tracks }) => tracks.map(({ data }) => data[0].url))
186
- .flat();
190
+ const urls = this.config.categories.flatMap(({ tracks }) =>
191
+ tracks.flatMap(({ data }) => data[0].url)
192
+ );
187
193
  const uniqueUrls = [...new Set(urls)];
188
194
  // Get the data for all urls and store it
189
195
  await Promise.all(
@@ -213,26 +219,28 @@ class ProtvistaUniprot extends LitElement {
213
219
  const categoryData = await Promise.all(
214
220
  tracks.map(async ({ data: dataConfig, name: trackName, filter }) => {
215
221
  const { url, adapter } = dataConfig[0]; // TODO handle array
216
- const trackData = this.rawData[url] || [];
222
+ const trackData = (Array.isArray(url) ? url : [url]).map(
223
+ (url) => this.rawData[url] || []
224
+ );
217
225
 
218
226
  if (
219
227
  !trackData ||
220
228
  (adapter === 'protvista-variation-adapter' &&
221
- trackData.length === 0)
229
+ trackData[0].length === 0)
222
230
  ) {
223
231
  return;
224
232
  }
225
233
 
226
234
  // 1. Convert data
227
235
  let transformedData = adapter
228
- ? await adapters[adapter](trackData)
236
+ ? await adapters[adapter](...trackData)
229
237
  : trackData;
230
238
 
231
239
  if (adapter === 'protvista-interpro-adapter') {
232
240
  const representativeDomains = [];
233
- transformedData?.forEach(feature => {
234
- feature.locations?.forEach(location => {
235
- location.fragments?.forEach(fragment => {
241
+ transformedData?.forEach((feature) => {
242
+ feature.locations?.forEach((location) => {
243
+ location.fragments?.forEach((fragment) => {
236
244
  if (fragment.representative) {
237
245
  representativeDomains.push({
238
246
  ...feature,