protvista-uniprot 2.13.2 → 3.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.
- package/dist/es/__spec__/filter-config.spec.d.ts +1 -0
- package/dist/es/__spec__/filter-config.spec.js +123 -0
- package/dist/es/__spec__/filter-config.spec.js.map +1 -0
- package/dist/es/adapters/__tests__/__mocks__/uniprotkb-entry-data.d.ts +47 -0
- package/dist/es/adapters/__tests__/__mocks__/uniprotkb-entry-data.js +75 -0
- package/dist/es/adapters/__tests__/__mocks__/uniprotkb-entry-data.js.map +1 -0
- package/dist/es/adapters/__tests__/structure-adapter.spec.d.ts +1 -0
- package/dist/es/adapters/__tests__/structure-adapter.spec.js +14 -0
- package/dist/es/adapters/__tests__/structure-adapter.spec.js.map +1 -0
- package/dist/es/adapters/alphafold-confidence-adapter.d.ts +8 -0
- package/dist/es/{protvista-alphafold-confidence.js → adapters/alphafold-confidence-adapter.js} +4 -3
- package/dist/es/adapters/alphafold-confidence-adapter.js.map +1 -0
- package/dist/es/adapters/alphamissense-heatmap-adapter.d.ts +8 -0
- package/dist/es/{protvista-alphamissense-heatmap.js → adapters/alphamissense-heatmap-adapter.js} +4 -3
- package/dist/es/adapters/alphamissense-heatmap-adapter.js.map +1 -0
- package/dist/es/adapters/alphamissense-pathogenicity-adapter.d.ts +10 -0
- package/dist/es/{protvista-alphamissense-pathogenicity.js → adapters/alphamissense-pathogenicity-adapter.js} +3 -2
- package/dist/es/adapters/alphamissense-pathogenicity-adapter.js.map +1 -0
- package/dist/es/adapters/config/evidence.d.ts +14 -0
- package/dist/es/adapters/config/evidence.js +101 -0
- package/dist/es/adapters/config/evidence.js.map +1 -0
- package/dist/es/adapters/feature-adapter.d.ts +2 -0
- package/dist/es/adapters/feature-adapter.js +18 -0
- package/dist/es/adapters/feature-adapter.js.map +1 -0
- package/dist/es/adapters/interpro-adapter.d.ts +2 -0
- package/dist/es/adapters/interpro-adapter.js +60 -0
- package/dist/es/adapters/interpro-adapter.js.map +1 -0
- package/dist/es/adapters/proteomics-adapter.d.ts +2 -0
- package/dist/es/adapters/proteomics-adapter.js +66 -0
- package/dist/es/adapters/proteomics-adapter.js.map +1 -0
- package/dist/es/{protvista-ptm-exchange.d.ts → adapters/ptm-exchange-adapter.d.ts} +2 -2
- package/dist/es/{protvista-ptm-exchange.js → adapters/ptm-exchange-adapter.js} +3 -2
- package/dist/es/adapters/ptm-exchange-adapter.js.map +1 -0
- package/dist/es/adapters/structure-adapter.d.ts +4 -0
- package/dist/es/adapters/structure-adapter.js +89 -0
- package/dist/es/adapters/structure-adapter.js.map +1 -0
- package/dist/es/adapters/types/alphafold.js +2 -0
- package/dist/es/adapters/types/alphafold.js.map +1 -0
- package/dist/es/adapters/variation-adapter.d.ts +7 -0
- package/dist/es/adapters/variation-adapter.js +31 -0
- package/dist/es/adapters/variation-adapter.js.map +1 -0
- package/dist/es/{protvista-variation-graph-adapter.d.ts → adapters/variation-graph-adapter.d.ts} +2 -1
- package/dist/es/{protvista-variation-graph-adapter.js → adapters/variation-graph-adapter.js} +12 -5
- package/dist/es/adapters/variation-graph-adapter.js.map +1 -0
- package/dist/es/config.json +54 -54
- package/dist/es/filter-config.d.ts +24 -0
- package/dist/es/{filterConfig.js → filter-config.js} +1 -1
- package/dist/es/filter-config.js.map +1 -0
- package/dist/es/index.d.ts +6 -11
- package/dist/es/index.js +6 -16
- package/dist/es/index.js.map +1 -1
- package/dist/es/protvista-uniprot-structure.js +15 -9
- package/dist/es/protvista-uniprot-structure.js.map +1 -1
- package/dist/es/protvista-uniprot.d.ts +1 -100
- package/dist/es/protvista-uniprot.js +46 -60
- package/dist/es/protvista-uniprot.js.map +1 -1
- package/dist/es/styles/protvista-styles.js +2 -1
- package/dist/es/styles/protvista-styles.js.map +1 -1
- package/dist/es/tooltips/featureTooltip.d.ts +4 -0
- package/dist/es/tooltips/featureTooltip.js +160 -0
- package/dist/es/tooltips/featureTooltip.js.map +1 -0
- package/dist/es/tooltips/structureTooltip.d.ts +2 -0
- package/dist/es/tooltips/structureTooltip.js +15 -0
- package/dist/es/tooltips/structureTooltip.js.map +1 -0
- package/dist/es/tooltips/variationTooltip.d.ts +3 -0
- package/dist/es/tooltips/variationTooltip.js +82 -0
- package/dist/es/tooltips/variationTooltip.js.map +1 -0
- package/dist/es/utils.d.ts +3 -0
- package/dist/es/utils.js +28 -0
- package/dist/es/utils.js.map +1 -0
- package/dist/protvista-uniprot.js +24 -13
- package/dist/protvista-uniprot.js.map +1 -1
- package/package.json +25 -30
- package/src/__spec__/filter-config.spec.ts +143 -0
- package/src/adapters/__tests__/__mocks__/uniprotkb-entry-data.ts +76 -0
- package/src/adapters/__tests__/__snapshots__/structure-adapter.spec.ts.snap +157 -0
- package/src/adapters/__tests__/structure-adapter.spec.ts +19 -0
- package/src/{protvista-alphafold-confidence.ts → adapters/alphafold-confidence-adapter.ts} +5 -3
- package/src/{protvista-alphamissense-heatmap.ts → adapters/alphamissense-heatmap-adapter.ts} +8 -4
- package/src/{protvista-alphamissense-pathogenicity.ts → adapters/alphamissense-pathogenicity-adapter.ts} +4 -2
- package/src/adapters/config/evidence.ts +105 -0
- package/src/adapters/feature-adapter.ts +19 -0
- package/src/adapters/interpro-adapter.ts +71 -0
- package/src/adapters/proteomics-adapter.ts +76 -0
- package/src/{protvista-ptm-exchange.ts → adapters/ptm-exchange-adapter.ts} +3 -1
- package/src/adapters/structure-adapter.ts +105 -0
- package/src/adapters/variation-adapter.ts +44 -0
- package/src/{protvista-variation-graph-adapter.ts → adapters/variation-graph-adapter.ts} +25 -18
- package/src/config.json +54 -54
- package/src/{filterConfig.ts → filter-config.ts} +17 -12
- package/src/index.ts +14 -18
- package/src/protvista-uniprot-structure.ts +6 -14
- package/src/protvista-uniprot.ts +66 -96
- package/src/styles/protvista-styles.ts +2 -1
- package/src/tooltips/featureTooltip.ts +223 -0
- package/src/tooltips/structureTooltip.ts +20 -0
- package/src/tooltips/variationTooltip.ts +139 -0
- package/src/utils.ts +37 -0
- package/dist/es/commonTypes.js +0 -2
- package/dist/es/commonTypes.js.map +0 -1
- package/dist/es/filterConfig.d.ts +0 -20
- package/dist/es/filterConfig.js.map +0 -1
- package/dist/es/loadComponents.d.ts +0 -2
- package/dist/es/loadComponents.js +0 -7
- package/dist/es/loadComponents.js.map +0 -1
- package/dist/es/protvista-alphafold-confidence.d.ts +0 -9
- package/dist/es/protvista-alphafold-confidence.js.map +0 -1
- package/dist/es/protvista-alphamissense-heatmap.d.ts +0 -8
- package/dist/es/protvista-alphamissense-heatmap.js.map +0 -1
- package/dist/es/protvista-alphamissense-pathogenicity.d.ts +0 -10
- package/dist/es/protvista-alphamissense-pathogenicity.js.map +0 -1
- package/dist/es/protvista-ptm-exchange.js.map +0 -1
- package/dist/es/protvista-variation-graph-adapter.js.map +0 -1
- package/src/loadComponents.ts +0 -10
- package/src/types/nightingale-components.d.ts +0 -13
- package/src/types/nightingale-sequence-heatmap.d.ts +0 -1
- package/src/types/protvista-feature-adapter.d.ts +0 -1
- package/src/types/protvista-interpro-adapter.d.ts +0 -1
- package/src/types/protvista-proteomics-adapter.d.ts +0 -1
- package/src/types/protvista-structure-adapter.d.ts +0 -1
- package/src/types/protvista-structure.d.ts +0 -1
- package/src/types/protvista-variation.d.ts +0 -15
- /package/dist/es/{commonTypes.d.ts → adapters/types/alphafold.d.ts} +0 -0
- /package/src/{commonTypes.ts → adapters/types/alphafold.ts} +0 -0
package/src/protvista-uniprot.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { LitElement, html, svg } from 'lit';
|
|
2
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
3
|
+
import { customElement } from 'lit/decorators.js';
|
|
2
4
|
import { unsafeHTML } from 'lit/directives/unsafe-html.js';
|
|
3
5
|
import { frame } from 'timing-functions';
|
|
4
6
|
|
|
@@ -14,68 +16,42 @@ import NightingaleLinegraphTrack from '@nightingale-elements/nightingale-linegra
|
|
|
14
16
|
import NightingaleSequenceHeatmap from '@nightingale-elements/nightingale-sequence-heatmap';
|
|
15
17
|
import NightingaleFilter from '@nightingale-elements/nightingale-filter';
|
|
16
18
|
|
|
17
|
-
import { load } from 'data-loader';
|
|
18
19
|
// adapters
|
|
19
|
-
import
|
|
20
|
-
import
|
|
21
|
-
import
|
|
22
|
-
import {
|
|
23
|
-
transformData as _transformDataVariationAdapter,
|
|
20
|
+
import featureAdapter from './adapters/feature-adapter';
|
|
21
|
+
import proteomicsAdapter from './adapters/proteomics-adapter';
|
|
22
|
+
import structureAdapter from './adapters/structure-adapter';
|
|
23
|
+
import variationAdapter, {
|
|
24
24
|
TransformedVariant,
|
|
25
|
-
} from '
|
|
26
|
-
import
|
|
27
|
-
import
|
|
28
|
-
import
|
|
29
|
-
import
|
|
30
|
-
import
|
|
31
|
-
import
|
|
25
|
+
} from './adapters/variation-adapter';
|
|
26
|
+
import interproAdapter from './adapters/interpro-adapter';
|
|
27
|
+
import variationGraphAdapter from './adapters/variation-graph-adapter';
|
|
28
|
+
import proteomicsPTMApdapter from './adapters/ptm-exchange-adapter';
|
|
29
|
+
import alphaFoldConfidenceAdapter from './adapters/alphafold-confidence-adapter';
|
|
30
|
+
import alphaMissensePathogenicityAdapter from './adapters/alphamissense-pathogenicity-adapter';
|
|
31
|
+
import alphaMissenseHeatmapAdapter from './adapters/alphamissense-heatmap-adapter';
|
|
32
32
|
|
|
33
|
+
import ProtvistaUniprotStructure from './protvista-uniprot-structure';
|
|
34
|
+
|
|
35
|
+
import { fetchAll, loadComponent } from './utils';
|
|
36
|
+
|
|
37
|
+
import filterConfig, { colorConfig } from './filter-config';
|
|
33
38
|
import defaultConfig from './config.json';
|
|
34
|
-
import _ProtvistaUniprotStructure from './protvista-uniprot-structure';
|
|
35
|
-
import { loadComponent } from './loadComponents';
|
|
36
|
-
import _filterConfig, { colorConfig as _colorConfig } from './filterConfig';
|
|
37
|
-
import { NightingaleEvent } from './types/nightingale-components';
|
|
38
39
|
|
|
39
40
|
import loaderIcon from './icons/spinner.svg';
|
|
40
41
|
import protvistaStyles from './styles/protvista-styles';
|
|
41
42
|
import loaderStyles from './styles/loader-styles';
|
|
42
43
|
|
|
43
|
-
export const transformDataFeatureAdapter = _transformDataFeatureAdapter;
|
|
44
|
-
export const transformDataProteomicsAdapter = _transformDataProteomicsAdapter;
|
|
45
|
-
export const transformDataStructureAdapter = _transformDataStructureAdapter;
|
|
46
|
-
export const transformDataVariationAdapter = _transformDataVariationAdapter;
|
|
47
|
-
export const transformDataVariationGraphAdapter =
|
|
48
|
-
_transformDataVariationGraphAdapter;
|
|
49
|
-
export const transformDataInterproAdapter = _transformDataInterproAdapter;
|
|
50
|
-
export const transformDataProteomicsPTMApdapter =
|
|
51
|
-
_transformDataProteomicsPTMApdapter;
|
|
52
|
-
export const transformDataAlphaFoldConfidenceAdapter =
|
|
53
|
-
_transformDataAlphaFoldConfidenceAdapter;
|
|
54
|
-
|
|
55
|
-
export const transformDataAlphaMissensePathogenicityAdapter =
|
|
56
|
-
_transformDataAlphaMissensePathogenicityAdapter;
|
|
57
|
-
|
|
58
|
-
export const transformDataAlphaMissenseHeatmapAdapter =
|
|
59
|
-
_transformDataAlphaMissenseHeatmapAdapter;
|
|
60
|
-
|
|
61
|
-
export const filterConfig = _filterConfig;
|
|
62
|
-
export const colorConfig = _colorConfig;
|
|
63
|
-
export const ProtvistaUniprotStructure = _ProtvistaUniprotStructure;
|
|
64
|
-
|
|
65
44
|
const adapters = {
|
|
66
|
-
'
|
|
67
|
-
'
|
|
68
|
-
'
|
|
69
|
-
'
|
|
70
|
-
'
|
|
71
|
-
'
|
|
72
|
-
'
|
|
73
|
-
'
|
|
74
|
-
|
|
75
|
-
'
|
|
76
|
-
transformDataAlphaMissensePathogenicityAdapter,
|
|
77
|
-
'protvista-alphamissense-heatmap-adapter':
|
|
78
|
-
transformDataAlphaMissenseHeatmapAdapter,
|
|
45
|
+
'feature-adapter': featureAdapter,
|
|
46
|
+
'interpro-adapter': interproAdapter,
|
|
47
|
+
'proteomics-adapter': proteomicsAdapter,
|
|
48
|
+
'structure-adapter': structureAdapter,
|
|
49
|
+
'variation-adapter': variationAdapter,
|
|
50
|
+
'variation-graph-adapter': variationGraphAdapter,
|
|
51
|
+
'proteomics-ptm-adapter': proteomicsPTMApdapter,
|
|
52
|
+
'alphafold-confidence-adapter': alphaFoldConfidenceAdapter,
|
|
53
|
+
'alphamissense-pathogenicity-adapter': alphaMissensePathogenicityAdapter,
|
|
54
|
+
'alphamissense-heatmap-adapter': alphaMissenseHeatmapAdapter,
|
|
79
55
|
};
|
|
80
56
|
|
|
81
57
|
type TrackType =
|
|
@@ -95,15 +71,15 @@ type ProtvistaTrackConfig = {
|
|
|
95
71
|
data: {
|
|
96
72
|
url: string | string[];
|
|
97
73
|
adapter?:
|
|
98
|
-
| '
|
|
99
|
-
| '
|
|
100
|
-
| '
|
|
101
|
-
| '
|
|
102
|
-
| '
|
|
103
|
-
| '
|
|
104
|
-
| '
|
|
105
|
-
| '
|
|
106
|
-
| '
|
|
74
|
+
| 'feature-adapter'
|
|
75
|
+
| 'structure-adapter'
|
|
76
|
+
| 'proteomics-adapter'
|
|
77
|
+
| 'variation-adapter'
|
|
78
|
+
| 'variation-graph-adapter'
|
|
79
|
+
| 'interpro-adapter'
|
|
80
|
+
| 'alphafold-confidence-adapter'
|
|
81
|
+
| 'alphamissense-pathogenicity-adapter'
|
|
82
|
+
| 'alphamissense-heatmap-adapter';
|
|
107
83
|
}[];
|
|
108
84
|
tooltip: string;
|
|
109
85
|
color?: string;
|
|
@@ -124,16 +100,21 @@ type ProtvistaCategory = {
|
|
|
124
100
|
'color-range'?: string;
|
|
125
101
|
};
|
|
126
102
|
|
|
127
|
-
export type DownloadConfig = {
|
|
128
|
-
type: string;
|
|
129
|
-
url: string;
|
|
130
|
-
}[];
|
|
131
|
-
|
|
132
103
|
type ProtvistaConfig = {
|
|
133
104
|
categories: ProtvistaCategory[];
|
|
134
|
-
download: DownloadConfig;
|
|
135
105
|
};
|
|
136
106
|
|
|
107
|
+
type NightingaleEvent = Event & {
|
|
108
|
+
detail?: {
|
|
109
|
+
displaystart?: number;
|
|
110
|
+
displayend?: number;
|
|
111
|
+
eventType?: 'click' | 'mouseover' | 'mouseout' | 'reset';
|
|
112
|
+
feature?: any;
|
|
113
|
+
coords?: [number, number];
|
|
114
|
+
};
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
@customElement('protvista-uniprot')
|
|
137
118
|
class ProtvistaUniprot extends LitElement {
|
|
138
119
|
private openCategories: string[];
|
|
139
120
|
private nostructure: boolean;
|
|
@@ -196,7 +177,7 @@ class ProtvistaUniprot extends LitElement {
|
|
|
196
177
|
loadComponent('nightingale-linegraph-track', NightingaleLinegraphTrack);
|
|
197
178
|
loadComponent('nightingale-filter', NightingaleFilter);
|
|
198
179
|
loadComponent('nightingale-manager', NightingaleManager);
|
|
199
|
-
loadComponent('protvista-uniprot-structure',
|
|
180
|
+
loadComponent('protvista-uniprot-structure', ProtvistaUniprotStructure);
|
|
200
181
|
loadComponent('nightingale-sequence-heatmap', NightingaleSequenceHeatmap);
|
|
201
182
|
}
|
|
202
183
|
|
|
@@ -207,28 +188,17 @@ class ProtvistaUniprot extends LitElement {
|
|
|
207
188
|
const urls = this.config.categories.flatMap(({ tracks }) =>
|
|
208
189
|
tracks.flatMap(({ data }) => data[0].url)
|
|
209
190
|
);
|
|
210
|
-
|
|
191
|
+
|
|
211
192
|
// Get the data for all urls and store it
|
|
212
|
-
await
|
|
213
|
-
|
|
214
|
-
load(url.replace('{accession}', accession))
|
|
215
|
-
.then(
|
|
216
|
-
(data) => {
|
|
217
|
-
this.rawData[url] = data.payload;
|
|
218
|
-
// Some endpoints return empty arrays, while most fail 🙄
|
|
219
|
-
if (!this.hasData && data.payload?.features?.length)
|
|
220
|
-
this.hasData = true;
|
|
221
|
-
},
|
|
222
|
-
// TODO handle this better based on error code
|
|
223
|
-
// Fail silently for now
|
|
224
|
-
(error) => console.warn(error)
|
|
225
|
-
)
|
|
226
|
-
.catch((e) => {
|
|
227
|
-
console.log(e);
|
|
228
|
-
})
|
|
229
|
-
)
|
|
193
|
+
this.rawData = await fetchAll([...new Set(urls)], (url) =>
|
|
194
|
+
url.replace('{accession}', accession)
|
|
230
195
|
);
|
|
231
196
|
|
|
197
|
+
// Some endpoints return empty arrays, while most fail 🙄
|
|
198
|
+
this.hasData =
|
|
199
|
+
this.hasData ||
|
|
200
|
+
Object.values(this.rawData).some((d) => !!d?.features?.length);
|
|
201
|
+
|
|
232
202
|
// Now iterate over tracks and categories, transforming the data
|
|
233
203
|
// and assigning it as adequate
|
|
234
204
|
for (const { name: categoryName, tracks, trackType } of this.config
|
|
@@ -242,18 +212,17 @@ class ProtvistaUniprot extends LitElement {
|
|
|
242
212
|
|
|
243
213
|
if (
|
|
244
214
|
!trackData ||
|
|
245
|
-
(adapter === '
|
|
246
|
-
trackData[0].length === 0)
|
|
215
|
+
(adapter === 'variation-adapter' && trackData[0].length === 0)
|
|
247
216
|
) {
|
|
248
217
|
return;
|
|
249
218
|
}
|
|
250
219
|
|
|
251
220
|
// 1. Convert data
|
|
252
221
|
let transformedData = adapter
|
|
253
|
-
? await adapters[adapter](
|
|
222
|
+
? await adapters[adapter].apply(null, trackData)
|
|
254
223
|
: trackData;
|
|
255
224
|
|
|
256
|
-
if (adapter === '
|
|
225
|
+
if (adapter === 'interpro-adapter') {
|
|
257
226
|
const representativeDomains = [];
|
|
258
227
|
transformedData?.forEach((feature) => {
|
|
259
228
|
feature.locations?.forEach((location) => {
|
|
@@ -322,7 +291,7 @@ class ProtvistaUniprot extends LitElement {
|
|
|
322
291
|
currentCategory.tracks &&
|
|
323
292
|
data &&
|
|
324
293
|
// Check there's data and special case for variants
|
|
325
|
-
// NOTE: should refactor
|
|
294
|
+
// NOTE: should refactor variation-adapter
|
|
326
295
|
// to return a list of variants and set the sequence
|
|
327
296
|
// on protvista-variation separately
|
|
328
297
|
(data.length > 0 || data.variants?.length)
|
|
@@ -350,9 +319,10 @@ class ProtvistaUniprot extends LitElement {
|
|
|
350
319
|
) {
|
|
351
320
|
for (const track of currentCategory.tracks) {
|
|
352
321
|
if (track.trackType === 'nightingale-sequence-heatmap') {
|
|
353
|
-
const heatmapComponent =
|
|
354
|
-
|
|
355
|
-
|
|
322
|
+
const heatmapComponent =
|
|
323
|
+
this.querySelector<NightingaleSequenceHeatmap>(
|
|
324
|
+
'nightingale-sequence-heatmap'
|
|
325
|
+
);
|
|
356
326
|
if (heatmapComponent) {
|
|
357
327
|
const heatmapData = this.data[`${id}-${track.name}`];
|
|
358
328
|
const xDomain = Array.from(
|
|
@@ -361,7 +331,7 @@ class ProtvistaUniprot extends LitElement {
|
|
|
361
331
|
);
|
|
362
332
|
const yDomain = [
|
|
363
333
|
...new Set(heatmapData.map((hotMapItem) => hotMapItem.yValue)),
|
|
364
|
-
];
|
|
334
|
+
] as string[];
|
|
365
335
|
heatmapComponent.setHeatmapData(xDomain, yDomain, heatmapData);
|
|
366
336
|
}
|
|
367
337
|
}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import ecoMap from '../adapters/config/evidence';
|
|
2
|
+
|
|
3
|
+
const formatSource = (source) => {
|
|
4
|
+
if (source.name?.toLowerCase() === 'PubMed'.toLowerCase()) {
|
|
5
|
+
return `${source.id} (<a href='${source.url}' style="color:#FFF" target='_blank'>${source.name}</a> <a href='${source.alternativeUrl}' style="color:#FFF" target='_blank'>EuropePMC</a>)`;
|
|
6
|
+
}
|
|
7
|
+
const sourceLink = ` <a href='${source.url}' style="color:#FFF" target='_blank'>${source.id}</a>`;
|
|
8
|
+
if (source.name) {
|
|
9
|
+
// Temporary until we get the expected value as 'PeptideAtlas' instead of 'HppPeptideAtlas'
|
|
10
|
+
if (source.name.startsWith('Hpp')) {
|
|
11
|
+
return `${sourceLink} (${source.name.slice(3)})`;
|
|
12
|
+
}
|
|
13
|
+
return `${sourceLink} (${source.name})`;
|
|
14
|
+
}
|
|
15
|
+
return sourceLink;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const getEvidenceFromCodes = (evidenceList) => {
|
|
19
|
+
if (!evidenceList) return ``;
|
|
20
|
+
return `
|
|
21
|
+
<ul>${evidenceList
|
|
22
|
+
.map((ev) => {
|
|
23
|
+
const ecoMatch = ecoMap.find((eco) => eco.name === ev.code);
|
|
24
|
+
if (!ecoMatch) return ``;
|
|
25
|
+
return `<li title='${
|
|
26
|
+
ecoMatch.description
|
|
27
|
+
}' style="padding: .25rem 0">${ecoMatch.shortDescription}: ${
|
|
28
|
+
ev.source ? formatSource(ev.source) : ''
|
|
29
|
+
}</li>`;
|
|
30
|
+
})
|
|
31
|
+
.join('')}</ul>
|
|
32
|
+
`;
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const formatXrefs = (xrefs) => {
|
|
36
|
+
return `<ul>${xrefs
|
|
37
|
+
.map(
|
|
38
|
+
(xref) =>
|
|
39
|
+
`<li style="padding: .25rem 0">${xref.name} ${
|
|
40
|
+
xref.url
|
|
41
|
+
? `<a href="${xref.url}" style="color:#FFF" target="_blank">${xref.id}</a>`
|
|
42
|
+
: `${xref.name} ${xref.id}`
|
|
43
|
+
}</li>`
|
|
44
|
+
)
|
|
45
|
+
.join('')}</ul>`;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const getPTMEvidence = (ptms) => {
|
|
49
|
+
if (!ptms) return ``;
|
|
50
|
+
const ids = ptms.flatMap(({ dbReferences }) =>
|
|
51
|
+
dbReferences.map((ref) => ref.id)
|
|
52
|
+
);
|
|
53
|
+
const uniqueIds = [...new Set(ids.flat())];
|
|
54
|
+
// Urls in the payload are not relevant. For 'Glue project' dataset, Dataset ID and publication reference is hardcoded. Need to be checked in 2024 if it still exists in the payload
|
|
55
|
+
const proteomexchange =
|
|
56
|
+
'https://proteomecentral.proteomexchange.org/dataset/';
|
|
57
|
+
return `
|
|
58
|
+
<ul>${uniqueIds
|
|
59
|
+
.map((id) => {
|
|
60
|
+
const datasetID = id === 'Glue project' ? 'PXD012174' : id;
|
|
61
|
+
return `<li title='${datasetID}' style="padding: .25rem 0">${datasetID} (<a href="${proteomexchange}${datasetID}" style="color:#FFF" target="_blank">ProteomeXchange</a>${
|
|
62
|
+
id === 'Glue project'
|
|
63
|
+
? `)</li><li title="publication" style="padding: .25rem 0">Publication: 31819260 (<a href="https://pubmed.ncbi.nlm.nih.gov/31819260" style="color:#FFF" target="_blank">PubMed</a>)</li>`
|
|
64
|
+
: ` <a href="http://www.peptideatlas.org/builds/rice/phospho/" style="color:#FFF" target="_blank">PeptideAtlas</a>)</li>`
|
|
65
|
+
}`;
|
|
66
|
+
})
|
|
67
|
+
.join('')}</ul>
|
|
68
|
+
`;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const formatPTMPeptidoform = (peptide, ptms) => {
|
|
72
|
+
if (!ptms) return ``;
|
|
73
|
+
const modificationValues = ptms.map((ptm) => ({
|
|
74
|
+
name: ptm.name,
|
|
75
|
+
position: ptm.position,
|
|
76
|
+
}));
|
|
77
|
+
let peptidoform = '';
|
|
78
|
+
let lastModPosition = 0;
|
|
79
|
+
modificationValues.forEach((p) => {
|
|
80
|
+
peptidoform = `${peptidoform}${peptide.slice(
|
|
81
|
+
lastModPosition,
|
|
82
|
+
p.position
|
|
83
|
+
)}[${p.name}]`;
|
|
84
|
+
lastModPosition = p.position;
|
|
85
|
+
});
|
|
86
|
+
// Add last remaining part of the peptide if any
|
|
87
|
+
peptidoform = `${peptidoform}${peptide.slice(lastModPosition)}`;
|
|
88
|
+
return `<p>${peptidoform}</p>`;
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
// At the moment, there is only phospho data. In future we may have more, the below AA sites have to be updated to accomodate more.
|
|
92
|
+
const AAPhosphoSites = {
|
|
93
|
+
A: 'alanine',
|
|
94
|
+
S: 'serine',
|
|
95
|
+
T: 'threonine',
|
|
96
|
+
Y: 'tyrosine',
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const findModifiedResidueName = (feature, ptm) => {
|
|
100
|
+
const { peptide, begin: peptideStart } = feature;
|
|
101
|
+
const proteinLocation = Number(peptideStart) + ptm.position - 1;
|
|
102
|
+
const modifiedResidue = peptide.charAt(ptm.position - 1); // CharAt index starts from 0
|
|
103
|
+
return `${proteinLocation} phospho${AAPhosphoSites[modifiedResidue]}`;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const formatTooltip = (feature) => {
|
|
107
|
+
const evidenceHTML =
|
|
108
|
+
feature.type === 'PROTEOMICS_PTM'
|
|
109
|
+
? getPTMEvidence(feature.ptms)
|
|
110
|
+
: getEvidenceFromCodes(feature.evidences);
|
|
111
|
+
const ptms =
|
|
112
|
+
feature.type === 'PROTEOMICS_PTM' &&
|
|
113
|
+
feature.ptms.map((ptm) => findModifiedResidueName(feature, ptm));
|
|
114
|
+
|
|
115
|
+
const dataset =
|
|
116
|
+
feature.type === 'PROTEOMICS_PTM' &&
|
|
117
|
+
feature.ptms.flatMap(({ dbReferences }) =>
|
|
118
|
+
dbReferences.map((ref) => ref.id)
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
let { description } = feature;
|
|
122
|
+
|
|
123
|
+
if (feature.type === 'BINDING' || feature.type === 'Binding site') {
|
|
124
|
+
let bindingDescription = '';
|
|
125
|
+
if (feature.ligandPart) {
|
|
126
|
+
bindingDescription += `${feature.ligandPart.name} of `;
|
|
127
|
+
}
|
|
128
|
+
if (feature.ligand) {
|
|
129
|
+
bindingDescription += feature.ligand.name;
|
|
130
|
+
}
|
|
131
|
+
if (feature.description) {
|
|
132
|
+
bindingDescription += `; ${feature.description}`;
|
|
133
|
+
}
|
|
134
|
+
description = bindingDescription;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
return `
|
|
139
|
+
${description ? `<h5>Description</h5><p>${description}</p>` : ``}
|
|
140
|
+
${
|
|
141
|
+
feature.matchScore
|
|
142
|
+
? `<h5>Match score</h5><p>${feature.matchScore}%</p>`
|
|
143
|
+
: ``
|
|
144
|
+
}
|
|
145
|
+
${feature.ftId ? `<h5>Feature ID</h5><p>${feature.ftId}</p>` : ``}
|
|
146
|
+
${
|
|
147
|
+
feature.alternativeSequence
|
|
148
|
+
? `<h5>Alternative sequence</h5><p>${feature.alternativeSequence}</p>`
|
|
149
|
+
: ``
|
|
150
|
+
}
|
|
151
|
+
${
|
|
152
|
+
ptms
|
|
153
|
+
? `<h5 data-article-id="ptm_processing_section">PTMs</h5><ul>${ptms
|
|
154
|
+
.map((item) => `<li>${item}</li>`)
|
|
155
|
+
.join('')}</ul>
|
|
156
|
+
`
|
|
157
|
+
: ''
|
|
158
|
+
}
|
|
159
|
+
${
|
|
160
|
+
feature.peptide && feature.type === 'PROTEOMICS_PTM'
|
|
161
|
+
? `<h5 data-article-id="mod_res_large_scale#what-is-the-goldsilverbronze-criterion">Peptidoform</h5><p>${formatPTMPeptidoform(
|
|
162
|
+
feature.peptide,
|
|
163
|
+
feature.ptms
|
|
164
|
+
)}</p>`
|
|
165
|
+
: ``
|
|
166
|
+
}
|
|
167
|
+
${
|
|
168
|
+
feature.peptide && feature.type !== 'PROTEOMICS_PTM'
|
|
169
|
+
? `<h5>Peptide</h5><p>${feature.peptide}</p>`
|
|
170
|
+
: ``
|
|
171
|
+
}
|
|
172
|
+
${
|
|
173
|
+
feature.xrefs
|
|
174
|
+
? `<h5>Cross-references</h5>${formatXrefs(feature.xrefs)}`
|
|
175
|
+
: ``
|
|
176
|
+
}
|
|
177
|
+
${evidenceHTML ? `<h5>Evidence</h5>${evidenceHTML}` : ``}
|
|
178
|
+
${
|
|
179
|
+
feature.ptms && dataset && !dataset.includes('Glue project')
|
|
180
|
+
? `<hr /><h5 data-article-id="mod_res_large_scale#what-is-the-goldsilverbronze-criterion">PTM statistical attributes</h5><ul>${feature.ptms
|
|
181
|
+
.map((ptm) =>
|
|
182
|
+
ptm.dbReferences
|
|
183
|
+
.map(
|
|
184
|
+
(ref) =>
|
|
185
|
+
`<li><b>${ref.id}</b></li>
|
|
186
|
+
<li style="text-indent: 1em"><b>${findModifiedResidueName(
|
|
187
|
+
feature,
|
|
188
|
+
ptm
|
|
189
|
+
)}</b></li>
|
|
190
|
+
<li style="text-indent: 2em">PubMed ID: <a href="https://europepmc.org/article/MED/${
|
|
191
|
+
ref.properties['Pubmed ID']
|
|
192
|
+
}" style="color:#FFF" target="_blank">
|
|
193
|
+
${ref.properties['Pubmed ID']}</a>
|
|
194
|
+
</li>
|
|
195
|
+
<li style="text-indent: 2em"><span data-article-id="mod_res_large_scale#confidence-score">Confidence score</span>: ${
|
|
196
|
+
ref.properties['Confidence score']
|
|
197
|
+
}</li>
|
|
198
|
+
<li style="text-indent: 2em">Universal Spectrum Id:
|
|
199
|
+
<a href="http://proteomecentral.proteomexchange.org/usi/?usi=${
|
|
200
|
+
ref.properties['Universal Spectrum Id']
|
|
201
|
+
}" style="color:#FFF" target="_blank">View on ProteomeXchange</a>
|
|
202
|
+
</li>
|
|
203
|
+
<li style="text-indent: 2em">PSM Count (0.05 gFLR): ${
|
|
204
|
+
ref.properties['PSM Count (0.05 gFLR)']
|
|
205
|
+
}</li>
|
|
206
|
+
<li style="text-indent: 2em">Final site probability: ${
|
|
207
|
+
ref.properties['Final site probability']
|
|
208
|
+
}</li>
|
|
209
|
+
`
|
|
210
|
+
)
|
|
211
|
+
.join('')
|
|
212
|
+
)
|
|
213
|
+
.join('')}</ul>`
|
|
214
|
+
: ''
|
|
215
|
+
}
|
|
216
|
+
`;
|
|
217
|
+
} catch (error) {
|
|
218
|
+
console.error(error);
|
|
219
|
+
return '';
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
export default formatTooltip;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const getStructuresHTML = (structureList) => {
|
|
2
|
+
return `<ul>
|
|
3
|
+
${structureList
|
|
4
|
+
.map(
|
|
5
|
+
(
|
|
6
|
+
structure
|
|
7
|
+
) => `<li style="margin: 0.25rem 0"><a style="color:#FFF" href='${structure.source.url}' target='_blank'>
|
|
8
|
+
${structure.source.id}
|
|
9
|
+
</a> (${structure.start}-${structure.end})</li>`
|
|
10
|
+
)
|
|
11
|
+
.join('')}
|
|
12
|
+
</ul>`;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const formatTooltip = (feature) => {
|
|
16
|
+
const structuresHTML = getStructuresHTML(feature.structures);
|
|
17
|
+
return `${structuresHTML ? `<h5>Structures</h5>${structuresHTML}` : ``}`;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default formatTooltip;
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Association,
|
|
3
|
+
Description,
|
|
4
|
+
PopulationFrequency,
|
|
5
|
+
Variant,
|
|
6
|
+
Prediction,
|
|
7
|
+
} from '@nightingale-elements/nightingale-variation';
|
|
8
|
+
import groupBy from 'lodash-es/groupBy';
|
|
9
|
+
|
|
10
|
+
import { formatXrefs, getEvidenceFromCodes } from './featureTooltip';
|
|
11
|
+
|
|
12
|
+
const getDiseaseAssociations = (associations: Association[]): string =>
|
|
13
|
+
associations
|
|
14
|
+
?.map(
|
|
15
|
+
(association) => `
|
|
16
|
+
<h4>Disease association</h4><p>${association.name}</p>
|
|
17
|
+
${
|
|
18
|
+
association.description
|
|
19
|
+
? `<>${association.description}</p>`
|
|
20
|
+
: ''
|
|
21
|
+
}
|
|
22
|
+
${
|
|
23
|
+
association.dbReferences
|
|
24
|
+
? `<h5>Cross-references</h5>${formatXrefs(
|
|
25
|
+
association.dbReferences
|
|
26
|
+
)}`
|
|
27
|
+
: ''
|
|
28
|
+
}
|
|
29
|
+
${getEvidenceFromCodes(association.evidences)}
|
|
30
|
+
`
|
|
31
|
+
)
|
|
32
|
+
.join('');
|
|
33
|
+
|
|
34
|
+
const getDescriptions = (descriptions: Description[]): string =>
|
|
35
|
+
`<hr/><h5>Description</h5>${descriptions
|
|
36
|
+
.map((description) => `<p>${description.value}</p>`)
|
|
37
|
+
.join('')}
|
|
38
|
+
`;
|
|
39
|
+
|
|
40
|
+
const getPopulationFrequencies = (
|
|
41
|
+
popFrequencies: PopulationFrequency[]
|
|
42
|
+
): string =>
|
|
43
|
+
`<hr/><h5>Population frequencies</h5>${popFrequencies
|
|
44
|
+
.map(
|
|
45
|
+
(freq) =>
|
|
46
|
+
`<p>${freq.frequency} - ${freq.populationName} (${freq.source})</p>`
|
|
47
|
+
)
|
|
48
|
+
.join('')}`;
|
|
49
|
+
|
|
50
|
+
const getEnsemblCovidLinks = (variant: Variant): string => {
|
|
51
|
+
const shouldGenerateLink = variant.locations.some(
|
|
52
|
+
(location) => location.source === 'EnsemblViruses'
|
|
53
|
+
);
|
|
54
|
+
if (shouldGenerateLink) {
|
|
55
|
+
const xref = variant.xrefs.find((xref) => xref.name === 'ENA');
|
|
56
|
+
return xref.id
|
|
57
|
+
? `<h5>Ensembl COVID-19</h5>
|
|
58
|
+
<p>
|
|
59
|
+
<a href="https://covid-19.ensembl.org/Sars_cov_2/Variation/Explore?v=${xref.id}" target="_blank" rel="noopener noreferrer">${xref.id}</a>
|
|
60
|
+
</p>`
|
|
61
|
+
: '';
|
|
62
|
+
}
|
|
63
|
+
return '';
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const getPredictions = (predictions: Prediction[]): string => {
|
|
67
|
+
const groupedPredictions = groupBy(predictions, 'predAlgorithmNameType');
|
|
68
|
+
const counts = Object.keys(groupedPredictions).map((key) => {
|
|
69
|
+
const valueGroups = groupBy(groupedPredictions[key], 'predictionValType');
|
|
70
|
+
return {
|
|
71
|
+
algorithm: key,
|
|
72
|
+
values: Object.keys(valueGroups).map((valKey) => ({
|
|
73
|
+
name: valKey,
|
|
74
|
+
count: valueGroups[valKey].length,
|
|
75
|
+
})),
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
return counts
|
|
79
|
+
.map(
|
|
80
|
+
(countItem) =>
|
|
81
|
+
`<h6>${countItem.algorithm}</h6><ul class="no-bullet">${countItem.values
|
|
82
|
+
.map((countValue) => `<li>${countValue.name}</li>`)
|
|
83
|
+
.join('')}</ul>`
|
|
84
|
+
)
|
|
85
|
+
.join('');
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const formatTooltip = (variant: Variant): string =>
|
|
89
|
+
`
|
|
90
|
+
<h5>Variant</h5><p>${variant.wildType} > ${
|
|
91
|
+
variant.alternativeSequence || ''
|
|
92
|
+
}</p>
|
|
93
|
+
${
|
|
94
|
+
variant.populationFrequencies
|
|
95
|
+
? getPopulationFrequencies(variant.populationFrequencies)
|
|
96
|
+
: ''
|
|
97
|
+
}
|
|
98
|
+
${
|
|
99
|
+
variant.consequenceType
|
|
100
|
+
? `<h5>Consequence</h5><p>${variant.consequenceType}</p>`
|
|
101
|
+
: ``
|
|
102
|
+
}
|
|
103
|
+
${
|
|
104
|
+
variant.somaticStatus
|
|
105
|
+
? `<h5>Somatic</h5><p>${
|
|
106
|
+
variant.somaticStatus === 0 ? 'No' : 'Yes'
|
|
107
|
+
}</p>`
|
|
108
|
+
: ``
|
|
109
|
+
}
|
|
110
|
+
${
|
|
111
|
+
variant.genomicLocation?.length
|
|
112
|
+
? `<h5>Location</h5><p>${variant.genomicLocation.join(
|
|
113
|
+
', '
|
|
114
|
+
)}</p>`
|
|
115
|
+
: ``
|
|
116
|
+
}
|
|
117
|
+
${
|
|
118
|
+
variant.ftId
|
|
119
|
+
? `<h5>Feature ID</h5><p>${variant.ftId}</p>`
|
|
120
|
+
: ``
|
|
121
|
+
}
|
|
122
|
+
${
|
|
123
|
+
variant.descriptions
|
|
124
|
+
? getDescriptions(variant.descriptions)
|
|
125
|
+
: ''
|
|
126
|
+
}
|
|
127
|
+
${
|
|
128
|
+
variant.association
|
|
129
|
+
? getDiseaseAssociations(variant.association)
|
|
130
|
+
: ''
|
|
131
|
+
}
|
|
132
|
+
${
|
|
133
|
+
variant.predictions ? getPredictions(variant.predictions) : ''
|
|
134
|
+
}
|
|
135
|
+
${getEnsemblCovidLinks(variant)}
|
|
136
|
+
|
|
137
|
+
`;
|
|
138
|
+
|
|
139
|
+
export default formatTooltip;
|