protvista-uniprot 4.5.3 → 4.6.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.
@@ -15,6 +15,7 @@ export type ProtvistaTrackConfig = {
15
15
  scale?: string;
16
16
  filterComponent?: 'nightingale-filter';
17
17
  'color-range'?: string;
18
+ helpPage?: string;
18
19
  };
19
20
  type ProtvistaCategory = {
20
21
  name: string;
@@ -25,6 +26,7 @@ type ProtvistaCategory = {
25
26
  shape?: string;
26
27
  scale?: string;
27
28
  'color-range'?: string;
29
+ helpPage?: string;
28
30
  };
29
31
  export type ProtvistaConfig = {
30
32
  categories: ProtvistaCategory[];
@@ -12,6 +12,7 @@ type ProcessedStructureData = {
12
12
  };
13
13
  declare class ProtvistaUniprotStructure extends LitElement {
14
14
  accession?: string;
15
+ sequence?: string;
15
16
  data?: ProcessedStructureData[];
16
17
  structureId?: string;
17
18
  metaInfo?: TemplateResult;
@@ -27,6 +28,9 @@ declare class ProtvistaUniprotStructure extends LitElement {
27
28
  structureId: {
28
29
  type: StringConstructor;
29
30
  };
31
+ sequence: {
32
+ type: StringConstructor;
33
+ };
30
34
  data: {
31
35
  type: ObjectConstructor;
32
36
  };
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": "4.5.3",
4
+ "version": "4.6.0",
5
5
  "files": [
6
6
  "dist",
7
7
  "src"
package/src/config.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  const proteinsApi = 'https://www.ebi.ac.uk/proteins/api/';
2
2
  const alphafoldApi = 'https://alphafold.ebi.ac.uk/api/';
3
3
  const alphafoldEntry = 'https://alphafold.ebi.ac.uk/entry/';
4
- const interproApi = 'https://www.ebi.ac.uk/interpro/api/';
4
+ const interproApi = 'https://www.ebi.ac.uk/interpro/wwwapi/';
5
5
 
6
6
  const proteinsApiServices = {
7
7
  proteins: `${proteinsApi}proteins/`,
@@ -51,6 +51,7 @@ export type ProtvistaTrackConfig = {
51
51
  scale?: string;
52
52
  filterComponent?: 'nightingale-filter';
53
53
  'color-range'?: string;
54
+ helpPage?: string;
54
55
  };
55
56
 
56
57
  type ProtvistaCategory = {
@@ -62,6 +63,7 @@ type ProtvistaCategory = {
62
63
  shape?: string; //TODO: eventually replace with list
63
64
  scale?: string;
64
65
  'color-range'?: string;
66
+ helpPage?: string;
65
67
  };
66
68
 
67
69
  export type ProtvistaConfig = {
@@ -87,6 +89,7 @@ const config: ProtvistaConfig = {
87
89
  },
88
90
  ],
89
91
  tooltip: 'N-terminal signal peptide',
92
+ helpPage: 'signal',
90
93
  },
91
94
  {
92
95
  name: 'chain',
@@ -101,6 +104,7 @@ const config: ProtvistaConfig = {
101
104
  ],
102
105
  tooltip:
103
106
  '(aka mature region). This describes the extent of a polypeptide chain in the mature protein following processing',
107
+ helpPage: 'chain',
104
108
  },
105
109
  {
106
110
  name: 'transit',
@@ -114,6 +118,7 @@ const config: ProtvistaConfig = {
114
118
  },
115
119
  ],
116
120
  tooltip: 'This describes the extent of a transit peptide',
121
+ helpPage: 'transit',
117
122
  },
118
123
  {
119
124
  name: 'init_met',
@@ -129,6 +134,7 @@ const config: ProtvistaConfig = {
129
134
 
130
135
  tooltip:
131
136
  'This indicates that the initiator methionine is cleaved from the mature protein',
137
+ helpPage: 'init_met',
132
138
  },
133
139
  {
134
140
  name: 'propep',
@@ -143,6 +149,7 @@ const config: ProtvistaConfig = {
143
149
  ],
144
150
  tooltip:
145
151
  'Part of a protein that is cleaved during maturation or activation',
152
+ helpPage: 'propep',
146
153
  },
147
154
  {
148
155
  name: 'peptide',
@@ -157,6 +164,7 @@ const config: ProtvistaConfig = {
157
164
  ],
158
165
  tooltip:
159
166
  'The position and length of an active peptide in the mature protein',
167
+ helpPage: 'peptide',
160
168
  },
161
169
  ],
162
170
  },
@@ -178,6 +186,7 @@ const config: ProtvistaConfig = {
178
186
  ],
179
187
  tooltip:
180
188
  'Position of regions of compositional bias within the protein and the particular amino acids that are over-represented within those regions',
189
+ helpPage: 'compbias',
181
190
  },
182
191
  {
183
192
  name: 'conflict',
@@ -191,6 +200,7 @@ const config: ProtvistaConfig = {
191
200
  },
192
201
  ],
193
202
  tooltip: 'Sequence discrepancies of unknown origin',
203
+ helpPage: 'conflict',
194
204
  },
195
205
  {
196
206
  name: 'non_cons',
@@ -205,6 +215,7 @@ const config: ProtvistaConfig = {
205
215
  ],
206
216
  tooltip:
207
217
  'Indicates that two residues in a sequence are not consecutive and that there is an undetermined number of unsequenced residues between them',
218
+ helpPage: 'non_cons',
208
219
  },
209
220
  {
210
221
  name: 'non_ter',
@@ -219,6 +230,7 @@ const config: ProtvistaConfig = {
219
230
  ],
220
231
  tooltip:
221
232
  'The sequence is incomplete. The residue is not the terminal residue of the complete protein',
233
+ helpPage: 'non_ter',
222
234
  },
223
235
  {
224
236
  name: 'unsure',
@@ -233,6 +245,7 @@ const config: ProtvistaConfig = {
233
245
  ],
234
246
  tooltip:
235
247
  'Regions of a sequence for which the authors are unsure about the sequence assignment',
248
+ helpPage: 'unsure',
236
249
  },
237
250
  {
238
251
  name: 'non_std',
@@ -246,6 +259,7 @@ const config: ProtvistaConfig = {
246
259
  },
247
260
  ],
248
261
  tooltip: 'Non-standard amino acids (selenocysteine and pyrrolysine)',
262
+ helpPage: 'non_std',
249
263
  },
250
264
  ],
251
265
  },
@@ -267,6 +281,7 @@ const config: ProtvistaConfig = {
267
281
  ],
268
282
  tooltip:
269
283
  'Location of non-membrane regions of membrane-spanning proteins',
284
+ helpPage: 'topo_dom',
270
285
  },
271
286
  {
272
287
  name: 'transmem',
@@ -280,6 +295,7 @@ const config: ProtvistaConfig = {
280
295
  },
281
296
  ],
282
297
  tooltip: 'Extent of a membrane-spanning region',
298
+ helpPage: 'transmem',
283
299
  },
284
300
  {
285
301
  name: 'intramem',
@@ -294,6 +310,7 @@ const config: ProtvistaConfig = {
294
310
  ],
295
311
  tooltip:
296
312
  'Extent of a region located in a membrane without crossing it',
313
+ helpPage: 'intramem',
297
314
  },
298
315
  ],
299
316
  },
@@ -315,6 +332,7 @@ const config: ProtvistaConfig = {
315
332
  ],
316
333
  tooltip:
317
334
  'Specific combination of secondary structures organized into a characteristic three-dimensional structure or fold',
335
+ helpPage: 'domain',
318
336
  },
319
337
  {
320
338
  name: 'InterPro representative domain',
@@ -327,6 +345,7 @@ const config: ProtvistaConfig = {
327
345
  },
328
346
  ],
329
347
  tooltip: 'InterPro representative domains',
348
+ helpPage: 'InterPro_rep_domain',
330
349
  },
331
350
  {
332
351
  name: 'region',
@@ -341,6 +360,7 @@ const config: ProtvistaConfig = {
341
360
  ],
342
361
  tooltip:
343
362
  'Regions in multifunctional enzymes or fusion proteins, or characteristics of a region, e.g., protein-protein interactions mediation',
363
+ helpPage: 'region',
344
364
  },
345
365
  {
346
366
  name: 'repeat',
@@ -355,6 +375,7 @@ const config: ProtvistaConfig = {
355
375
  ],
356
376
  tooltip:
357
377
  'Repeated sequence motifs or repeated domains within the protein',
378
+ helpPage: 'repeat',
358
379
  },
359
380
  {
360
381
  name: 'motif',
@@ -368,6 +389,7 @@ const config: ProtvistaConfig = {
368
389
  },
369
390
  ],
370
391
  tooltip: 'Short conserved sequence motif of biological significance',
392
+ helpPage: 'motif',
371
393
  },
372
394
  {
373
395
  name: 'zn_fing',
@@ -382,6 +404,7 @@ const config: ProtvistaConfig = {
382
404
  ],
383
405
  tooltip:
384
406
  'Small, functional, independently folded domain that coordinates one or more zinc ions',
407
+ helpPage: 'zn_fing',
385
408
  },
386
409
  ],
387
410
  },
@@ -402,6 +425,7 @@ const config: ProtvistaConfig = {
402
425
  },
403
426
  ],
404
427
  tooltip: 'Binding site for a metal ion',
428
+ helpPage: 'binding',
405
429
  },
406
430
  {
407
431
  name: 'site',
@@ -415,6 +439,7 @@ const config: ProtvistaConfig = {
415
439
  },
416
440
  ],
417
441
  tooltip: 'Any interesting single amino acid site on the sequence',
442
+ helpPage: 'site',
418
443
  },
419
444
  {
420
445
  name: 'ca_bind',
@@ -428,6 +453,7 @@ const config: ProtvistaConfig = {
428
453
  },
429
454
  ],
430
455
  tooltip: 'Calcium-binding regions, such as the EF-hand motif',
456
+ helpPage: 'binding',
431
457
  },
432
458
  {
433
459
  name: 'dna_bind',
@@ -442,6 +468,7 @@ const config: ProtvistaConfig = {
442
468
  ],
443
469
  tooltip:
444
470
  'DNA-binding domains such as AP2/ERF domain, the ETS domain, the Fork-Head domain, the HMG box and the Myb domain',
471
+ helpPage: 'dna_bind',
445
472
  },
446
473
  {
447
474
  name: 'np_bind',
@@ -456,6 +483,7 @@ const config: ProtvistaConfig = {
456
483
  ],
457
484
  tooltip:
458
485
  '(aka flavin-binding). Region in the protein which binds nucleotide phosphates',
486
+ helpPage: 'binding',
459
487
  },
460
488
  {
461
489
  name: 'binding',
@@ -470,6 +498,7 @@ const config: ProtvistaConfig = {
470
498
  ],
471
499
  tooltip:
472
500
  'Binding site for any chemical group (co-enzyme, prosthetic group, etc.)',
501
+ helpPage: 'binding',
473
502
  },
474
503
  {
475
504
  name: 'act_site',
@@ -484,6 +513,7 @@ const config: ProtvistaConfig = {
484
513
  ],
485
514
  tooltip:
486
515
  'Amino acid(s) directly involved in the activity of an enzyme',
516
+ helpPage: 'act_site',
487
517
  },
488
518
  ],
489
519
  },
@@ -505,6 +535,7 @@ const config: ProtvistaConfig = {
505
535
  ],
506
536
  tooltip:
507
537
  'Modified residues such as phosphorylation, acetylation, acylation, methylation',
538
+ helpPage: 'mod_res',
508
539
  },
509
540
  {
510
541
  name: 'mod_res_ls',
@@ -518,6 +549,7 @@ const config: ProtvistaConfig = {
518
549
  },
519
550
  ],
520
551
  tooltip: 'Modified residues from Large scale studies',
552
+ helpPage: 'mod_res_large_scale',
521
553
  },
522
554
  {
523
555
  name: 'carbohyd',
@@ -531,6 +563,7 @@ const config: ProtvistaConfig = {
531
563
  },
532
564
  ],
533
565
  tooltip: 'Covalently attached glycan group(s)',
566
+ helpPage: 'carbohyd',
534
567
  },
535
568
  {
536
569
  name: 'disulfid',
@@ -545,6 +578,7 @@ const config: ProtvistaConfig = {
545
578
  ],
546
579
  tooltip:
547
580
  'The positions of cysteine residues participating in disulphide bonds',
581
+ helpPage: 'disulfid',
548
582
  },
549
583
  {
550
584
  name: 'crosslnk',
@@ -559,6 +593,7 @@ const config: ProtvistaConfig = {
559
593
  ],
560
594
  tooltip:
561
595
  'Covalent linkages of various types formed between two proteins or between two parts of the same protein',
596
+ helpPage: 'crosslnk',
562
597
  },
563
598
  {
564
599
  name: 'lipid',
@@ -572,6 +607,7 @@ const config: ProtvistaConfig = {
572
607
  },
573
608
  ],
574
609
  tooltip: 'Covalently attached lipid group(s)',
610
+ helpPage: 'lipid',
575
611
  },
576
612
  ],
577
613
  },
@@ -591,6 +627,7 @@ const config: ProtvistaConfig = {
591
627
  },
592
628
  ],
593
629
  tooltip: '',
630
+ helpPage: 'epitopes',
594
631
  },
595
632
  ],
596
633
  },
@@ -610,6 +647,7 @@ const config: ProtvistaConfig = {
610
647
  },
611
648
  ],
612
649
  tooltip: '',
650
+ helpPage: 'Antibody_binding_sequences',
613
651
  },
614
652
  ],
615
653
  },
@@ -630,6 +668,7 @@ const config: ProtvistaConfig = {
630
668
  },
631
669
  ],
632
670
  tooltip: 'Site which has been experimentally altered by mutagenesis',
671
+ helpPage: 'mutagen',
633
672
  },
634
673
  {
635
674
  name: 'othermutagen',
@@ -642,6 +681,7 @@ const config: ProtvistaConfig = {
642
681
  },
643
682
  ],
644
683
  tooltip: 'Site which has been experimentally altered by mutagenesis',
684
+ helpPage: 'mutagen',
645
685
  },
646
686
  ],
647
687
  },
@@ -649,6 +689,7 @@ const config: ProtvistaConfig = {
649
689
  name: 'VARIATION',
650
690
  label: 'Variants',
651
691
  trackType: 'nightingale-linegraph-track',
692
+ helpPage: 'variant_viewer',
652
693
  tracks: [
653
694
  {
654
695
  name: 'variation_graph',
@@ -682,6 +723,7 @@ const config: ProtvistaConfig = {
682
723
  name: 'RNA_EDITING',
683
724
  label: 'RNA Editing',
684
725
  trackType: 'nightingale-linegraph-track',
726
+ helpPage: 'rna_editing',
685
727
  tracks: [
686
728
  {
687
729
  name: 'rna_editing_graph',
@@ -727,6 +769,8 @@ const config: ProtvistaConfig = {
727
769
  },
728
770
  ],
729
771
  tooltip: '',
772
+ helpPage:
773
+ 'proteomics#1-data-from-public-mass-spectrometry-based-proteomics-resources',
730
774
  },
731
775
  {
732
776
  name: 'non_unique',
@@ -740,6 +784,8 @@ const config: ProtvistaConfig = {
740
784
  },
741
785
  ],
742
786
  tooltip: '',
787
+ helpPage:
788
+ 'proteomics#1-data-from-public-mass-spectrometry-based-proteomics-resources',
743
789
  },
744
790
  {
745
791
  name: 'hpp',
@@ -752,6 +798,7 @@ const config: ProtvistaConfig = {
752
798
  },
753
799
  ],
754
800
  tooltip: '',
801
+ helpPage: 'proteomics#3-human-proteome-project',
755
802
  },
756
803
  {
757
804
  name: 'proteomics-ptm',
@@ -764,6 +811,8 @@ const config: ProtvistaConfig = {
764
811
  },
765
812
  ],
766
813
  tooltip: '',
814
+ helpPage:
815
+ 'proteomics#4-post-translational-modification-ptm-data-derived-from-large-scale-mass-spectrometry-ms-datasets',
767
816
  },
768
817
  ],
769
818
  },
@@ -783,6 +832,7 @@ const config: ProtvistaConfig = {
783
832
  url: `${proteinsApiServices.proteins}{accession}`,
784
833
  },
785
834
  ],
835
+ helpPage: 'structure_section#structure-coverage',
786
836
  },
787
837
  ],
788
838
  },
@@ -792,6 +842,7 @@ const config: ProtvistaConfig = {
792
842
  trackType: 'nightingale-colored-sequence',
793
843
  scale: 'H:90,M:70,L:50,D:0',
794
844
  'color-range': '#ff7d45:0,#ffdb13:50,#65cbf3:70,#0053d6:90,#0053d6:100',
845
+ helpPage: 'structure_section#alphafold-structural-models',
795
846
  tracks: [
796
847
  {
797
848
  name: 'alphafold_confidence',
@@ -819,6 +870,8 @@ const config: ProtvistaConfig = {
819
870
  'B:0,H:0.1132,V:0.2264,L:0.3395,A:0.4527,l:0.5895,h:0.7264,p:0.8632,P:1',
820
871
  'color-range':
821
872
  '#2166ac:0,#4290bf:0.1132,#8cbcd4:0.2264,#c3d6e0:0.3395,#e2e2e2:0.4527,#edcdba:0.5895,#e99e7c:0.7264,#d15e4b:0.8632,#b2182b:1',
873
+ helpPage:
874
+ 'structure_section#alphamissense-prediction-of-genetic-variation-consequence-in-the-feature-viewer',
822
875
  tracks: [
823
876
  {
824
877
  name: 'alphamissense_pathogenicity',
@@ -120,7 +120,7 @@ type ProcessedStructureData = {
120
120
  };
121
121
 
122
122
  const processPDBData = (data: UniProtKBData): ProcessedStructureData[] =>
123
- data.uniProtKBCrossReferences
123
+ data.uniProtKBCrossReferences ? data.uniProtKBCrossReferences
124
124
  .filter((xref) => xref.database === 'PDB')
125
125
  .sort((refA, refB) => refA.id.localeCompare(refB.id))
126
126
  .map(({ id, properties }) => {
@@ -162,7 +162,7 @@ const processPDBData = (data: UniProtKBData): ProcessedStructureData[] =>
162
162
  transformedItem: ProcessedStructureData | undefined
163
163
  ): transformedItem is ProcessedStructureData =>
164
164
  transformedItem !== undefined
165
- );
165
+ ) : [];
166
166
 
167
167
  const processAFData = (data: AlphaFoldPayload): ProcessedStructureData[] =>
168
168
  data.map((d) => ({
@@ -260,6 +260,7 @@ const styleId = 'protvista-styles';
260
260
  @customElement('protvista-uniprot-structure')
261
261
  class ProtvistaUniprotStructure extends LitElement {
262
262
  accession?: string;
263
+ sequence?: string;
263
264
  data?: ProcessedStructureData[];
264
265
  structureId?: string;
265
266
  metaInfo?: TemplateResult;
@@ -285,6 +286,7 @@ class ProtvistaUniprotStructure extends LitElement {
285
286
  return {
286
287
  accession: { type: String },
287
288
  structureId: { type: String },
289
+ sequence: { type: String },
288
290
  data: { type: Object },
289
291
  loading: { type: Boolean },
290
292
  colorTheme: { type: String },
@@ -309,7 +311,7 @@ class ProtvistaUniprotStructure extends LitElement {
309
311
  let afData = [];
310
312
  // Check if AF sequence matches UniProt sequence
311
313
  const alphaFoldSequenceMatch = rawData[alphaFoldUrl]?.filter(
312
- ({ sequence }) => rawData[pdbUrl].sequence?.value === sequence
314
+ ({ sequence: afSequence }) => rawData[pdbUrl]?.sequence?.value === afSequence || this.sequence === afSequence
313
315
  );
314
316
  if (alphaFoldSequenceMatch?.length) {
315
317
  afData = processAFData(alphaFoldSequenceMatch);
@@ -339,8 +341,8 @@ class ProtvistaUniprotStructure extends LitElement {
339
341
  ) as ProtvistaDatatable;
340
342
  if (!protvistaDatatableElt?.selectedid && this.data?.[0]) {
341
343
  // Select the first element in the table
342
- this.onTableRowClick({ id: this.data[0].id });
343
- protvistaDatatableElt.selectedid = this.structureId;
344
+ this.onTableRowClick({ id: this.data[0].id, source: this.data[0].source, downloadLink: this.data[0].downloadLink });
345
+ protvistaDatatableElt.selectedid = this.data[0].id;
344
346
  }
345
347
  }
346
348
 
@@ -441,7 +441,11 @@ class ProtvistaUniprot extends LitElement {
441
441
  data-category-toggle="${category.name}"
442
442
  @click="${this.handleCategoryClick}"
443
443
  >
444
- ${category.label}
444
+ ${category.helpPage
445
+ ? html`<span data-article-id="${category.helpPage}"
446
+ >${category.label}</span
447
+ >`
448
+ : category.label}
445
449
  </div>
446
450
  <div
447
451
  data-id="category_${category.name}"
@@ -491,7 +495,11 @@ class ProtvistaUniprot extends LitElement {
491
495
  )}"
492
496
  >${track.label}</a
493
497
  >`) ||
494
- track.label}
498
+ (track.helpPage
499
+ ? html`<span data-article-id="${track.helpPage}"
500
+ >${track.label}</span
501
+ >`
502
+ : track.label)}
495
503
  </div>
496
504
  <div
497
505
  class="track-content"
@@ -578,7 +586,12 @@ class ProtvistaUniprot extends LitElement {
578
586
 
579
587
  handleCategoryClick(e: MouseEvent) {
580
588
  const target = e.target as Element;
581
- const toggle = target.getAttribute('data-category-toggle');
589
+
590
+ const toggle =
591
+ target.getAttribute('data-category-toggle') ||
592
+ (target instanceof HTMLSpanElement &&
593
+ target.parentElement?.getAttribute('data-category-toggle'));
594
+
582
595
  if (toggle && !target.classList.contains('open')) {
583
596
  target.classList.add('open');
584
597
  this.openCategories = [...this.openCategories, toggle];
@@ -86,4 +86,15 @@ export default css`
86
86
  .feature {
87
87
  cursor: pointer;
88
88
  }
89
+
90
+ .proforma {
91
+ padding-left: 4em;
92
+ white-space: normal;
93
+ overflow-wrap: anywhere;
94
+ word-break: break-word;
95
+ }
96
+
97
+ .mod-link {
98
+ white-space: nowrap;
99
+ }
89
100
  `;
@@ -16,6 +16,28 @@ const taxIdToPeptideAtlasBuildData = {
16
16
  '185431': { build: '590', organism: 'T Brucei' },
17
17
  };
18
18
 
19
+ const unimodIdMapping = {
20
+ 'Glu-&gt;pyro-Glu': 27,
21
+ 'Ammonia-loss': 385,
22
+ NQTGG: 2084,
23
+ Formyl: 122,
24
+ Carbamidomethyl: 4,
25
+ Ubiquitination: 121,
26
+ TMT6plex: 737,
27
+ Phospho: 21,
28
+ iTRAQ8plex: 730,
29
+ Deamidated: 7,
30
+ 'Pyro-QQTGG': 2083,
31
+ QQTGG: 2082,
32
+ GlyGly: 121,
33
+ Oxidation: 35,
34
+ 'Gln-&gt;pyro-Glu': 28,
35
+ Dehydrated: 23,
36
+ DVFQQQTGG: 2085,
37
+ Acetyl: 1,
38
+ iTRAQ4plex: 214,
39
+ };
40
+
19
41
  const formatSource = (source) => {
20
42
  if (source.name?.toLowerCase() === 'PubMed'.toLowerCase()) {
21
43
  return `${source.id}&nbsp;(<a href='${source.url}' target='_blank'>${source.name}</a>&nbsp;<a href='${source.alternativeUrl}' target='_blank'>EuropePMC</a>)`;
@@ -101,6 +123,17 @@ const formatPTMPeptidoform = (peptide, ptms) => {
101
123
  return peptidoform;
102
124
  };
103
125
 
126
+ const formatProformaWithLink = (proforma = '') => {
127
+ return proforma.replace(/\[([^\]]+)\]/g, (_, modification) => {
128
+ const id = unimodIdMapping[modification];
129
+ if (!id) {
130
+ console.error('Unimod ID not found for modification:', modification);
131
+ return `[${modification}]`;
132
+ }
133
+ return `<span class="mod-link">[<a href="https://www.unimod.org/modifications_view.php?editid1=${id}" target="_blank">${modification}</a>]</span>`;
134
+ });
135
+ };
136
+
104
137
  const findModifiedResidueName = (feature, ptm) => {
105
138
  const { peptide, begin: peptideStart } = feature;
106
139
  const proteinLocation = Number(peptideStart) + ptm.position - 1;
@@ -244,14 +277,21 @@ const formatTooltip = (feature, taxId?: string) => {
244
277
  }
245
278
  ${
246
279
  ref.properties['Universal Spectrum Id']
247
- ? `<li class="text-indent-2 nowrap margin-bottom">Universal Spectrum Id:
248
- <a href="http://proteomecentral.proteomexchange.org/usi/?usi=${encodeURIComponent(
249
- ref.properties['Universal Spectrum Id']
250
- )}" target="_blank">View on ProteomeXchange</a>
251
- </li>`
280
+ ? `<li class="text-indent-2 nowrap">Universal Spectrum Id:
281
+ <a href="http://proteomecentral.proteomexchange.org/usi/?usi=${encodeURIComponent(
282
+ ref.properties['Universal Spectrum Id']
283
+ )}" target="_blank">View on ProteomeXchange</a>
284
+ </li>`
285
+ : ``
286
+ }
287
+ ${
288
+ ref.properties['Proforma']
289
+ ? `<li class="nowrap margin-bottom"><div class="text-indent-2">Experimental Peptidoform:</div><div class="proforma">
290
+ ${formatProformaWithLink(
291
+ ref.properties['Proforma']
292
+ )}</div></li>`
252
293
  : ``
253
- }
254
- `
294
+ }`
255
295
  )
256
296
  .join('')
257
297
  )