annotation.ts 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. /**
  2. * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. import { CustomElementProperty } from 'mol-model-props/common/custom-element-property';
  7. import { Model, ElementIndex, ResidueIndex } from 'mol-model/structure';
  8. import { Color } from 'mol-util/color';
  9. const EvolutionaryConservationPalette: Color[] = [
  10. [255, 255, 129], // insufficient
  11. [160, 37, 96], // 9
  12. [240, 125, 171],
  13. [250, 201, 222],
  14. [252, 237, 244],
  15. [255, 255, 255],
  16. [234, 255, 255],
  17. [215, 255, 255],
  18. [140, 255, 255],
  19. [16, 200, 209] // 1
  20. ].reverse().map(([r, g, b]) => Color.fromRgb(r, g, b));
  21. const EvolutionaryConservationDefaultColor = Color(0x999999);
  22. export const EvolutionaryConservation = CustomElementProperty.create<number>({
  23. isStatic: true,
  24. name: 'proteopedia-wrapper-evolutionary-conservation',
  25. display: 'Evolutionary Conservation',
  26. async getData(model: Model) {
  27. const id = model.label.toLowerCase();
  28. const req = await fetch(`https://proteopedia.org/cgi-bin/cnsrf?${id}`);
  29. const json = await req.json();
  30. const annotations = (json && json.residueAnnotations) || [];
  31. const conservationMap = new Map<string, number>();
  32. for (const e of annotations) {
  33. for (const r of e.ids) {
  34. conservationMap.set(r, e.annotation);
  35. }
  36. }
  37. const map = new Map<ElementIndex, number>();
  38. const { _rowCount: residueCount } = model.atomicHierarchy.residues;
  39. const { offsets: residueOffsets } = model.atomicHierarchy.residueAtomSegments;
  40. const chainIndex = model.atomicHierarchy.chainAtomSegments.index;
  41. for (let rI = 0 as ResidueIndex; rI < residueCount; rI++) {
  42. const cI = chainIndex[residueOffsets[rI]];
  43. const key = `${model.atomicHierarchy.chains.auth_asym_id.value(cI)} ${model.atomicHierarchy.residues.auth_seq_id.value(rI)}`;
  44. if (!conservationMap.has(key)) continue;
  45. const ann = conservationMap.get(key)!;
  46. for (let aI = residueOffsets[rI]; aI < residueOffsets[rI + 1]; aI++) {
  47. map.set(aI, ann);
  48. }
  49. }
  50. return map;
  51. },
  52. coloring: {
  53. getColor(e: number) {
  54. if (e < 1 || e > 10) return EvolutionaryConservationDefaultColor;
  55. return EvolutionaryConservationPalette[e - 1];
  56. },
  57. defaultColor: EvolutionaryConservationDefaultColor
  58. },
  59. format(e) {
  60. if (e === 10) return `Evolutionary Conservation: InsufficientData`;
  61. return e ? `Evolutionary Conservation: ${e}` : void 0;
  62. }
  63. });