Browse Source

added hydrophobicity values and coloring

Alexander Rose 6 years ago
parent
commit
460d4898aa

+ 35 - 1
src/mol-model/structure/model/types.ts

@@ -576,4 +576,38 @@ export namespace LinkType {
     export function isCovalent(flags: LinkType.Flag) {
         return (flags & LinkType.Flag.Covalent) !== 0;
     }
-}
+}
+
+/**
+ * "Experimentally determined hydrophobicity scale for proteins at membrane interfaces"
+ * by Wimely and White (doi:10.1038/nsb1096-842)
+ * http://blanco.biomol.uci.edu/Whole_residue_HFscales.txt
+ * https://www.nature.com/articles/nsb1096-842
+ */
+export const ResidueHydrophobicity = {
+    // AA  DGwif   DGwoct  Oct-IF
+    'ALA': [ 0.17, 0.50, 0.33 ],
+    'ARG': [ 0.81, 1.81, 1.00 ],
+    'ASN': [ 0.42, 0.85, 0.43 ],
+    'ASP': [ 1.23, 3.64, 2.41 ],
+    'ASH': [ -0.07, 0.43, 0.50 ],
+    'CYS': [ -0.24, -0.02, 0.22 ],
+    'GLN': [ 0.58, 0.77, 0.19 ],
+    'GLU': [ 2.02, 3.63, 1.61 ],
+    'GLH': [ -0.01, 0.11, 0.12 ],
+    'GLY': [ 0.01, 1.15, 1.14 ],
+    // "His+": [  0.96,  2.33,  1.37 ],
+    'HIS': [ 0.17, 0.11, -0.06 ],
+    'ILE': [ -0.31, -1.12, -0.81 ],
+    'LEU': [ -0.56, -1.25, -0.69 ],
+    'LYS': [ 0.99, 2.80, 1.81 ],
+    'MET': [ -0.23, -0.67, -0.44 ],
+    'PHE': [ -1.13, -1.71, -0.58 ],
+    'PRO': [ 0.45, 0.14, -0.31 ],
+    'SER': [ 0.13, 0.46, 0.33 ],
+    'THR': [ 0.14, 0.25, 0.11 ],
+    'TRP': [ -1.85, -2.09, -0.24 ],
+    'TYR': [ -0.94, -0.71, 0.23 ],
+    'VAL': [ 0.07, -0.46, -0.53 ]
+  }
+  export const DefaultResidueHydrophobicity = [ 0.00, 0.00, 0.00 ]

+ 2 - 0
src/mol-theme/color.ts

@@ -28,6 +28,7 @@ import { ScaleLegend } from 'mol-util/color/scale';
 import { TableLegend } from 'mol-util/color/tables';
 import { UncertaintyColorThemeProvider } from './color/uncertainty';
 import { IllustrativeColorThemeProvider } from './color/illustrative';
+import { HydrophobicityColorThemeProvider } from './color/hydrophobicity';
 
 export type LocationColor = (location: Location, isSecondary: boolean) => Color
 
@@ -74,6 +75,7 @@ export const BuiltInColorThemes = {
     'cross-link': CrossLinkColorThemeProvider,
     'element-index': ElementIndexColorThemeProvider,
     'element-symbol': ElementSymbolColorThemeProvider,
+    'hydrophobicity': HydrophobicityColorThemeProvider,
     'illustrative': IllustrativeColorThemeProvider,
     'molecule-type': MoleculeTypeColorThemeProvider,
     'polymer-id': PolymerIdColorThemeProvider,

+ 107 - 0
src/mol-theme/color/hydrophobicity.ts

@@ -0,0 +1,107 @@
+/**
+ * Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { Color, ColorScale } from 'mol-util/color';
+import { StructureElement, Unit, Link, ElementIndex } from 'mol-model/structure';
+import { Location } from 'mol-model/location';
+import { ColorTheme } from '../color';
+import { ParamDefinition as PD } from 'mol-util/param-definition'
+import { ThemeDataContext } from '../theme';
+import { ResidueHydrophobicity } from 'mol-model/structure/model/types';
+import { ColorListName, ColorListOptions } from 'mol-util/color/scale';
+
+const Description = 'Assigns a color to every amino acid according to the "Experimentally determined hydrophobicity scale for proteins at membrane interfaces" by Wimely and White (doi:10.1038/nsb1096-842).'
+
+export const HydrophobicityColorThemeParams = {
+    list: PD.ColorScale<ColorListName>('RedYellowGreen', ColorListOptions),
+    scale: PD.Select('DGwif', [['DGwif', 'DG water-membrane'], ['DGwoct', 'DG water-octanol'], ['Oct-IF', 'DG difference']])
+}
+export type HydrophobicityColorThemeParams = typeof HydrophobicityColorThemeParams
+export function getHydrophobicityColorThemeParams(ctx: ThemeDataContext) {
+    return HydrophobicityColorThemeParams // TODO return copy
+}
+
+const scaleIndexMap = { 'DGwif': 0, 'DGwoct': 1, 'Oct-IF': 2 }
+
+export function hydrophobicity(compId: string, scaleIndex: number): number {
+    const c = (ResidueHydrophobicity as { [k: string]: number[] })[compId];
+    return c === undefined ? 0 : c[scaleIndex]
+}
+
+function getAtomicCompId(unit: Unit.Atomic, element: ElementIndex) {
+    const { modifiedResidues } = unit.model.properties
+    const compId = unit.model.atomicHierarchy.residues.label_comp_id.value(unit.residueIndex[element])
+    const parentId = modifiedResidues.parentId.get(compId)
+    return parentId === undefined ? compId : parentId
+}
+
+function getCoarseCompId(unit: Unit.Spheres | Unit.Gaussians, element: ElementIndex) {
+    const seqIdBegin = unit.coarseElements.seq_id_begin.value(element)
+    const seqIdEnd = unit.coarseElements.seq_id_end.value(element)
+    if (seqIdBegin === seqIdEnd) {
+        const { modifiedResidues } = unit.model.properties
+        const entityKey = unit.coarseElements.entityKey[element]
+        const seq = unit.model.sequence.byEntityKey[entityKey]
+        let compId = seq.compId.value(seqIdBegin - 1) // 1-indexed
+        const parentId = modifiedResidues.parentId.get(compId)
+        return parentId === undefined ? compId : parentId
+    }
+}
+
+export function HydrophobicityColorTheme(ctx: ThemeDataContext, props: PD.Values<HydrophobicityColorThemeParams>): ColorTheme<HydrophobicityColorThemeParams> {
+    const scaleIndex = scaleIndexMap[props.scale]
+
+    // get domain
+    let min = Infinity
+    let max = -Infinity
+    for (const name in ResidueHydrophobicity) {
+        const val = (ResidueHydrophobicity as { [k: string]: number[] })[name][scaleIndex]
+        min = Math.min(min, val)
+        max = Math.max(max, val)
+    }
+
+    const scale = ColorScale.create({
+        listOrName: props.list,
+        domain: [ max, min ],
+        minLabel: 'Hydrophobic',
+        maxLabel: 'Hydrophilic'
+    })
+
+    function color(location: Location): Color {
+        let compId: string | undefined
+        if (StructureElement.isLocation(location)) {
+            if (Unit.isAtomic(location.unit)) {
+                compId = getAtomicCompId(location.unit, location.element)
+            } else {
+                compId = getCoarseCompId(location.unit, location.element)
+            }
+        } else if (Link.isLocation(location)) {
+            if (Unit.isAtomic(location.aUnit)) {
+                compId = getAtomicCompId(location.aUnit, location.aUnit.elements[location.aIndex])
+            } else {
+                compId = getCoarseCompId(location.aUnit, location.aUnit.elements[location.aIndex])
+            }
+        }
+        return scale.color(compId ? hydrophobicity(compId, scaleIndex) : 0)
+    }
+
+    return {
+        factory: HydrophobicityColorTheme,
+        granularity: 'group',
+        color,
+        props,
+        description: Description,
+        legend: scale ? scale.legend : undefined
+    }
+}
+
+export const HydrophobicityColorThemeProvider: ColorTheme.Provider<HydrophobicityColorThemeParams> = {
+    label: 'Hydrophobicity',
+    factory: HydrophobicityColorTheme,
+    getParams: getHydrophobicityColorThemeParams,
+    defaultValues: PD.getDefaultValues(HydrophobicityColorThemeParams),
+    isApplicable: (ctx: ThemeDataContext) => !!ctx.structure
+}

+ 1 - 1
src/mol-util/color/scale.ts

@@ -55,7 +55,7 @@ export interface ColorScale {
 }
 
 export const DefaultColorScaleProps = {
-    domain: [0, 1],
+    domain: [0, 1] as [number, number],
     reverse: false,
     listOrName: ColorBrewer.RedYellowBlue as Color[] | ColorListName,
     minLabel: '' as string | undefined,