Skip to content

Commit 3e9f754

Browse files
committed
Binding site superposition - trying to add labels
1 parent 214978f commit 3e9f754

1 file changed

Lines changed: 107 additions & 3 deletions

File tree

  • src/app/extensions/binding-sites

src/app/extensions/binding-sites/index.ts

Lines changed: 107 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
1+
import { CustomLabelProps, CustomLabelRepresentationProvider } from 'molstar/lib/extensions/mvs/components/custom-label/representation';
2+
import { MVSBuildPrimitiveShape, MVSInlinePrimitiveData, MVSShapeRepresentation3D } from 'molstar/lib/extensions/mvs/components/primitives';
3+
import { Selector } from 'molstar/lib/extensions/mvs/components/selector';
4+
import { MVSNode } from 'molstar/lib/extensions/mvs/tree/mvs/mvs-tree';
5+
import { ComponentExpressionT } from 'molstar/lib/extensions/mvs/tree/mvs/param-types';
16
import { Sphere3D } from 'molstar/lib/mol-math/geometry';
27
import { EPSILON, Mat3, Vec3 } from 'molstar/lib/mol-math/linear-algebra';
38
import { MinimizeRmsd } from 'molstar/lib/mol-math/linear-algebra/3d/minimize-rmsd';
49
import { MmcifFormat } from 'molstar/lib/mol-model-formats/structure/mmcif';
5-
import { Structure, StructureQuery, StructureSelection } from 'molstar/lib/mol-model/structure';
10+
import { Structure, StructureElement, StructureQuery, StructureSelection } from 'molstar/lib/mol-model/structure';
611
import { TraceAtoms } from 'molstar/lib/mol-model/structure/model/types';
712
import { changeCameraRotation } from 'molstar/lib/mol-plugin-state/manager/focus-camera/orient-axes';
813
import { StructureRef } from 'molstar/lib/mol-plugin-state/manager/structure/hierarchy-state';
9-
import { Download, ParseCif, RawData } from 'molstar/lib/mol-plugin-state/transforms/data';
14+
import { Download, ParseCif } from 'molstar/lib/mol-plugin-state/transforms/data';
1015
import { CreateGroup } from 'molstar/lib/mol-plugin-state/transforms/misc';
11-
import { ModelFromTrajectory, StructureFromModel, TrajectoryFromMmCif } from 'molstar/lib/mol-plugin-state/transforms/model';
16+
import { CustomModelProperties, ModelFromTrajectory, StructureFromModel, TrajectoryFromMmCif } from 'molstar/lib/mol-plugin-state/transforms/model';
1217
import { OverpaintStructureRepresentation3DFromScript, StructureRepresentation3D } from 'molstar/lib/mol-plugin-state/transforms/representation';
1318
import { setSubtreeVisibility } from 'molstar/lib/mol-plugin/behavior/static/state';
1419
import { PluginCommands } from 'molstar/lib/mol-plugin/commands';
@@ -86,6 +91,8 @@ function doMagic(viewer: PDBeMolstarPlugin, bsData: BindingSitesData, bindingSit
8691
const reprBsCoords = extractTraceCoordsByUniprot(reprBsStruct, uniprotId, bsResidues);
8792
console.timeEnd('load representative structure')
8893

94+
await addBsLabels(viewer.plugin, viewer.getStructure(REPRESENTATIVE_STRUCT_ID)!, { bindingSiteId, uniprot_accession: uniprotId, uniprot_residue_numbers: bsResidues, auth_asym_id: representativePdbAuthAsymId });
95+
8996
console.time('load&superpose all')
9097
const ligandsToSuperpose = bsData[bindingSiteId].ligands.slice(0, DEBUG_LIGAND_COUNT_LIMIT);
9198
for (const ligandBatch of divideToBatches(ligandsToSuperpose, LIGAND_BATCH_SIZE)) {
@@ -300,3 +307,100 @@ function divideToBatches<T>(jobs: T[], batchSize: number = Infinity) {
300307
}
301308
return out;
302309
}
310+
311+
async function addBsLabels(plugin: PluginContext, structRef: StructureRef, params: { bindingSiteId: string, auth_asym_id: string, uniprot_accession: string, uniprot_residue_numbers: Iterable<number> }) {
312+
// Binding site label
313+
await addLabels(
314+
plugin,
315+
structRef,
316+
[{
317+
text: `Binding site ${params.bindingSiteId}`,
318+
selector: Array.from(params.uniprot_residue_numbers).map(res => ({
319+
auth_asym_id: params.auth_asym_id,
320+
uniprot_accession: params.uniprot_accession,
321+
uniprot_residue_number: res,
322+
})),
323+
}],
324+
{
325+
sizeFactor: 0.9,
326+
attachment: 'bottom-center',
327+
tether: true,
328+
tetherLength: 1,
329+
backgroundColor: ColorNames.yellow,
330+
}
331+
);
332+
333+
// Residue labels
334+
await addLabels(
335+
plugin,
336+
structRef,
337+
Array.from(params.uniprot_residue_numbers).map(res => ({
338+
text: `${res}`,
339+
selector: [{
340+
auth_asym_id: params.auth_asym_id,
341+
uniprot_accession: params.uniprot_accession,
342+
uniprot_residue_number: res,
343+
}],
344+
})),
345+
{
346+
sizeFactor: 0.9,
347+
}
348+
);
349+
350+
// await addLabelsPrimitives(plugin, structRef, [{ text: 'Bar', selector: [{}] }]);
351+
}
352+
353+
async function addLabels(plugin: PluginContext, structRef: StructureRef, labels: { text: string, selector: QueryParam[] }[], props: Partial<Omit<CustomLabelProps, 'items'>> = {}) {
354+
const modelProps = structRef.model?.properties?.cell;
355+
if (modelProps && !modelProps.params?.values.properties?.['mvs-is-mvs-model']?.isMvs) {
356+
await plugin.build().to(modelProps).update(CustomModelProperties, old => ({
357+
...old,
358+
properties: {
359+
...old.properties,
360+
'mvs-is-mvs-model': { isMvs: true },
361+
},
362+
})).commit();
363+
}
364+
365+
const struct = structRef.cell.obj?.data;
366+
if (!struct) throw new Error(`Failed to get structure for displaying labels`);
367+
368+
const bundles = labels.map(({ text, selector }) => ({ text, bundle: StructureElement.Bundle.fromSelection(StructureQuery.run(QueryHelper.getQueryObject(selector, struct), struct)) }));
369+
370+
await plugin.build()
371+
.to(structRef.cell)
372+
.apply(StructureRepresentation3D, {
373+
type: {
374+
name: CustomLabelRepresentationProvider.name,
375+
params: {
376+
...props,
377+
items: bundles.map(({ text, bundle }) => ({
378+
text: text,
379+
position: { name: 'selection', params: { selector: { name: 'bundle', params: bundle } satisfies Selector } },
380+
})),
381+
} satisfies Partial<CustomLabelProps>,
382+
},
383+
})
384+
.commit();
385+
}
386+
387+
async function addLabelsPrimitives(plugin: PluginContext, structRef: StructureRef, labels: { text: string, selector: ComponentExpressionT[] }[]) {
388+
const struct = structRef.cell.obj?.data;
389+
if (!struct) throw new Error(`Failed to get structure for displaying labels`);
390+
391+
await plugin.build()
392+
.to(structRef.cell)
393+
.apply(MVSInlinePrimitiveData, {
394+
node: {
395+
kind: 'primitives',
396+
params: {} as any,
397+
children: labels.map(label => ({
398+
kind: 'primitive',
399+
params: { kind: 'label', text: label.text, position: { expressions: label.selector }, label_color: 'white', label_offset: 0, label_size: 2 },
400+
} satisfies MVSNode<'primitive'>)),
401+
},
402+
})
403+
.apply(MVSBuildPrimitiveShape, { kind: 'labels' })
404+
.apply(MVSShapeRepresentation3D, {})
405+
.commit();
406+
}

0 commit comments

Comments
 (0)