Skip to content
Snippets Groups Projects
Commit 7acfe77f authored by David Sehnal's avatar David Sehnal
Browse files

Proteopedia wrapper conservation coloring

parent 2a7066f2
No related branches found
No related tags found
No related merge requests found
......@@ -5,26 +5,84 @@
*/
import { CustomElementProperty } from 'mol-model-props/common/custom-element-property';
import { Model, ElementIndex } from 'mol-model/structure';
import { Model, ElementIndex, ResidueIndex } from 'mol-model/structure';
import { Color } from 'mol-util/color';
export const StripedResidues = CustomElementProperty.create<number>({
// export const StripedResidues = CustomElementProperty.create<number>({
// isStatic: true,
// name: 'basic-wrapper-residue-striping',
// display: 'Residue Stripes',
// getData(model: Model) {
// const map = new Map<ElementIndex, number>();
// const residueIndex = model.atomicHierarchy.residueAtomSegments.index;
// for (let i = 0, _i = model.atomicHierarchy.atoms._rowCount; i < _i; i++) {
// map.set(i as ElementIndex, residueIndex[i] % 2);
// }
// return map;
// },
// coloring: {
// getColor(e) { return e === 0 ? Color(0xff0000) : Color(0x0000ff) },
// defaultColor: Color(0x777777)
// },
// format(e) {
// return e === 0 ? 'Odd stripe' : 'Even stripe'
// }
// });
const EvolutionaryConservationPalette: Color[] = [
[255, 255, 150], // 9
[160, 37, 96],
[240, 125, 171],
[250, 201, 222],
[252, 237, 244],
[255, 255, 255],
[234, 255, 255],
[215, 255, 255],
[140, 255, 255],
[16, 200, 209] // 1
].reverse().map(([r, g, b]) => Color.fromRgb(r, g, b));
export const EvolutionaryConservation = CustomElementProperty.create<number>({
isStatic: true,
name: 'basic-wrapper-residue-striping',
display: 'Residue Stripes',
getData(model: Model) {
name: 'proteopedia-wrapper-evolutionary-conservation',
display: 'Evolutionary Conservation',
async getData(model: Model) {
const id = model.label.toLowerCase();
const req = await fetch(`https://proteopedia.org/cgi-bin/cnsrf?${id}`);
const json = await req.json();
const annotations = (json && json.residueAnnotations) || [];
const conservationMap = new Map<string, number>();
for (const e of annotations) {
for (const r of e.ids) {
conservationMap.set(r, e.annotation);
}
}
const map = new Map<ElementIndex, number>();
const residueIndex = model.atomicHierarchy.residueAtomSegments.index;
for (let i = 0, _i = model.atomicHierarchy.atoms._rowCount; i < _i; i++) {
map.set(i as ElementIndex, residueIndex[i] % 2);
const { _rowCount: residueCount } = model.atomicHierarchy.residues;
const { offsets: residueOffsets } = model.atomicHierarchy.residueAtomSegments;
const chainIndex = model.atomicHierarchy.chainAtomSegments.index;
for (let rI = 0 as ResidueIndex; rI < residueCount; rI++) {
const cI = chainIndex[residueOffsets[rI]];
const key = `${model.atomicHierarchy.chains.auth_asym_id.value(cI)} ${model.atomicHierarchy.residues.auth_seq_id.value(rI)}`;
if (!conservationMap.has(key)) continue;
const ann = conservationMap.get(key)!;
for (let aI = residueOffsets[rI]; aI < residueOffsets[aI + 1]; aI++) {
map.set(aI, ann);
}
}
return map;
},
coloring: {
getColor(e) { return e === 0 ? Color(0xff0000) : Color(0x0000ff) },
defaultColor: Color(0x777777)
getColor(e) { return EvolutionaryConservationPalette[(e - 1) || 0]; },
defaultColor: Color(0x999999)
},
format(e) {
return e === 0 ? 'Odd stripe' : 'Even stripe'
return e ? `Evolutionary Conservation ${e}` : void 0;
}
})
\ No newline at end of file
});
\ No newline at end of file
......@@ -61,7 +61,7 @@
function $(id) { return document.getElementById(id); }
var pdbId = '3usb', assemblyId= 'preferred';
var pdbId = '2c1z', assemblyId= 'preferred';
var url = 'https://www.ebi.ac.uk/pdbe/static/entry/' + pdbId + '_updated.cif';
var format = 'cif';
......@@ -107,9 +107,11 @@
addControl('Play Loop', () => MolStarProteopediaWrapper.animate.modelIndex.loop());
addControl('Stop', () => MolStarProteopediaWrapper.animate.modelIndex.stop());
addSeparator();
addHeader('Misc');
addControl('Apply Stripes', () => MolStarProteopediaWrapper.coloring.applyStripes());
addControl('Apply Evo Cons', () => MolStarProteopediaWrapper.coloring.evolutionaryConservation());
addControl('Default Visuals', () => MolStarProteopediaWrapper.updateStyle());
////////////////////////////////////////////////////////
......
......@@ -14,7 +14,7 @@ import { Color } from 'mol-util/color';
import { PluginStateObject as PSO, PluginStateObject } from 'mol-plugin/state/objects';
import { AnimateModelIndex } from 'mol-plugin/state/animation/built-in';
import { StateBuilder, StateObject } from 'mol-state';
import { StripedResidues } from './annotation';
import { EvolutionaryConservation } from './annotation';
import { LoadParams, SupportedFormats, RepresentationStyle, ModelInfo } from './helpers';
import { RxEventHelper } from 'mol-util/rx-event-helper';
require('mol-plugin/skin/light.scss')
......@@ -39,9 +39,9 @@ class MolStarProteopediaWrapper {
}
});
this.plugin.structureRepresentation.themeCtx.colorThemeRegistry.add(StripedResidues.Descriptor.name, StripedResidues.colorTheme!);
this.plugin.lociLabels.addProvider(StripedResidues.labelProvider);
this.plugin.customModelProperties.register(StripedResidues.propertyProvider);
this.plugin.structureRepresentation.themeCtx.colorThemeRegistry.add(EvolutionaryConservation.Descriptor.name, EvolutionaryConservation.colorTheme!);
this.plugin.lociLabels.addProvider(EvolutionaryConservation.labelProvider);
this.plugin.customModelProperties.register(EvolutionaryConservation.propertyProvider);
}
get state() {
......@@ -65,7 +65,7 @@ class MolStarProteopediaWrapper {
const model = this.state.build().to('model');
return model
.apply(StateTransforms.Model.CustomModelProperties, { properties: [StripedResidues.Descriptor.name] }, { ref: 'props', props: { isGhost: false } })
.apply(StateTransforms.Model.CustomModelProperties, { properties: [EvolutionaryConservation.Descriptor.name] }, { ref: 'props', props: { isGhost: false } })
.apply(StateTransforms.Model.StructureAssemblyFromModel, { id: assemblyId || 'deposited' }, { ref: 'asm' });
}
......@@ -97,7 +97,7 @@ class MolStarProteopediaWrapper {
return root;
}
private getObj<T extends StateObject>(ref: string) {
private getObj<T extends StateObject>(ref: string): T['data'] {
const state = this.state;
const cell = state.select(ref)[0];
if (!cell || !cell.obj) return void 0;
......@@ -105,10 +105,10 @@ class MolStarProteopediaWrapper {
}
private async doInfo(checkPreferredAssembly: boolean) {
const s = this.getObj<PluginStateObject.Molecule.Model>('model');
if (!s) return;
const model = this.getObj<PluginStateObject.Molecule.Model>('model');
if (!model) return;
const info = await ModelInfo.get(this.plugin, s, checkPreferredAssembly)
const info = await ModelInfo.get(this.plugin, model, checkPreferredAssembly)
this.events.modelInfo.next(info);
return info;
}
......@@ -177,18 +177,18 @@ class MolStarProteopediaWrapper {
}
coloring = {
applyStripes: async () => {
evolutionaryConservation: async () => {
await this.updateStyle({ sequence: { kind: 'molecular-surface' } });
const state = this.state;
const visuals = state.selectQ(q => q.ofType(PluginStateObject.Molecule.Representation3D).filter(c => c.transform.transformer === StateTransforms.Representation.StructureRepresentation3D));
//const visuals = state.selectQ(q => q.ofType(PluginStateObject.Molecule.Representation3D).filter(c => c.transform.transformer === StateTransforms.Representation.StructureRepresentation3D));
const tree = state.build();
const colorTheme = { name: StripedResidues.Descriptor.name, params: this.plugin.structureRepresentation.themeCtx.colorThemeRegistry.get(StripedResidues.Descriptor.name).defaultValues };
const colorTheme = { name: EvolutionaryConservation.Descriptor.name, params: this.plugin.structureRepresentation.themeCtx.colorThemeRegistry.get(EvolutionaryConservation.Descriptor.name).defaultValues };
for (const v of visuals) {
tree.to(v.transform.ref).update(StateTransforms.Representation.StructureRepresentation3D, old => ({ ...old, colorTheme }));
}
tree.to('sequence-visual').update(StateTransforms.Representation.StructureRepresentation3D, old => ({ ...old, colorTheme }));
//for (const v of visuals) {
//}
await PluginCommands.State.Update.dispatch(this.plugin, { state, tree });
}
......
......@@ -26,7 +26,7 @@ namespace CustomElementProperty {
display: string,
attachableTo?: (model: Model) => boolean,
getData(model: Model): Map<ElementIndex, T> | Promise<Map<ElementIndex, T>>,
format?(e: T): string,
format?(e: T): string | undefined,
coloring?: {
getColor: (e: T) => Color,
defaultColor: Color
......@@ -43,6 +43,9 @@ namespace CustomElementProperty {
function attach(model: Model) {
return Task.create(`Attach ${params.display}`, async () => {
try {
if (model.customProperties.has(Descriptor)) return true;
const data = await params.getData(model);
if (params.isStatic) {
......@@ -54,6 +57,10 @@ namespace CustomElementProperty {
model.customProperties.add(Descriptor);
return true;
} catch (e) {
console.warn('Attach Property', e);
return false;
}
})
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment