Newer
Older
/**
* Copyright (c) 2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
import './index.html'
import { Canvas3D } from 'mol-canvas3d/canvas3d';
import CIF, { CifFrame } from 'mol-io/reader/cif'
import { Model, Structure, StructureElement, Unit } from 'mol-model/structure';
import { ColorTheme, LocationColor } from 'mol-theme/color';
import { SizeTheme } from 'mol-theme/size';
import { CartoonRepresentationProvider } from 'mol-repr/structure/representation/cartoon';
import { trajectoryFromMmCIF } from 'mol-model-formats/structure/mmcif';
import { AccessibleSurfaceArea } from 'mol-model/structure/structure/accessible-surface-area';
import { Color, ColorScale } from 'mol-util/color';
import { Location } from 'mol-model/location';
import { ThemeDataContext } from 'mol-theme/theme';
import { ParamDefinition as PD } from 'mol-util/param-definition';
import { ColorListName, ColorListOptions } from 'mol-util/color/scale';
const parent = document.getElementById('app')!
parent.style.width = '100%'
parent.style.height = '100%'
const canvas = document.createElement('canvas')
canvas.style.width = '100%'
canvas.style.height = '100%'
parent.appendChild(canvas)
const canvas3d = Canvas3D.create(canvas)
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
canvas3d.animate()
async function parseCif(data: string|Uint8Array) {
const comp = CIF.parse(data);
const parsed = await comp.run();
if (parsed.isError) throw parsed;
return parsed.result;
}
async function downloadCif(url: string, isBinary: boolean) {
const data = await fetch(url);
return parseCif(isBinary ? new Uint8Array(await data.arrayBuffer()) : await data.text());
}
async function downloadFromPdb(pdb: string) {
// const parsed = await downloadCif(`https://files.rcsb.org/download/${pdb}.cif`, false);
const parsed = await downloadCif(`https://webchem.ncbr.muni.cz/ModelServer/static/bcif/${pdb}`, true);
return parsed.blocks[0];
}
async function getModels(frame: CifFrame) {
return await trajectoryFromMmCIF(frame).run();
}
async function getStructure(model: Model) {
return Structure.ofModel(model);
}
const reprCtx = {
colorThemeRegistry: ColorTheme.createRegistry(),
sizeThemeRegistry: SizeTheme.createRegistry()
}
function getCartoonRepr() {
return CartoonRepresentationProvider.factory(reprCtx, CartoonRepresentationProvider.getParams)
}
let accessibleSurfaceArea: AccessibleSurfaceArea;
async function init(props = {}) {
const cif = await downloadFromPdb(
// '3j3q'
// '1aon'
// '1acj'
// '1pga'
'1brr'
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
const models = await getModels(cif)
const structure = await getStructure(models[0])
// async compute ASA
accessibleSurfaceArea = await AccessibleSurfaceArea.compute(structure)
const cartoonRepr = getCartoonRepr()
// create color theme
cartoonRepr.setTheme({
color: AccessibleSurfaceAreaColorTheme(reprCtx, { ...PD.getDefaultValues(AccessibleSurfaceAreaColorThemeParams), ...props }),
size: reprCtx.sizeThemeRegistry.create('uniform', { structure })
})
await cartoonRepr.createOrUpdate({ ...CartoonRepresentationProvider.defaultValues, quality: 'auto' }, structure).run()
canvas3d.add(cartoonRepr)
canvas3d.resetCamera()
}
init()
const DefaultColor = Color(0xFFFFFF)
const Description = 'Assigns a color based on the relative accessible surface area of a residue.'
export const AccessibleSurfaceAreaColorThemeParams = {
list: PD.ColorScale<ColorListName>('Rainbow', ColorListOptions)
}
export type AccessibleSurfaceAreaColorThemeParams = typeof AccessibleSurfaceAreaColorThemeParams
export function getAccessibleSurfaceAreaColorThemeParams(ctx: ThemeDataContext) {
return AccessibleSurfaceAreaColorThemeParams // TODO return copy
}
export function AccessibleSurfaceAreaColorTheme(ctx: ThemeDataContext, props: PD.Values<AccessibleSurfaceAreaColorThemeParams>): ColorTheme<AccessibleSurfaceAreaColorThemeParams> {
let color: LocationColor = () => DefaultColor
const scale = ColorScale.create({
listOrName: props.list,
minLabel: '0.0 (buried)',
maxLabel: '1.0 (exposed)',
domain: [0.0, 1.0]
})
color = (location: Location): Color => {
if (StructureElement.isLocation(location)) {
if (Unit.isAtomic(location.unit)) {
const value = accessibleSurfaceArea.relativeAccessibleSurfaceArea![location.unit.residueIndex[location.element]];
return value !== AccessibleSurfaceArea.VdWLookup[0] /* signals missing value */ ? scale.color(value) : DefaultColor;
}
}
return DefaultColor
}
return {
factory: AccessibleSurfaceAreaColorTheme,
granularity: 'group',
color,
props,
description: Description,
legend: scale ? scale.legend : undefined
}
}
export const AccessibleSurfaceAreaColorThemeProvider: ColorTheme.Provider<AccessibleSurfaceAreaColorThemeParams> = {
label: 'Accessible Surface Area',
factory: AccessibleSurfaceAreaColorTheme,
getParams: getAccessibleSurfaceAreaColorThemeParams,
defaultValues: PD.getDefaultValues(AccessibleSurfaceAreaColorThemeParams),
isApplicable: (ctx: ThemeDataContext) => !!ctx.structure
}