@molstudio/core 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/MolStudio.d.ts +9 -0
- package/dist/MolStudio.js +57 -7
- package/package.json +1 -1
package/dist/MolStudio.d.ts
CHANGED
|
@@ -51,6 +51,11 @@ export declare class MolStudio {
|
|
|
51
51
|
loadVolume({ data, label, format }: LoadDataOptions<VolumeFormat>): Promise<void>;
|
|
52
52
|
loadVolumeFromUrl(url: string, label: string, format: VolumeFormat, isBinary: boolean): Promise<void>;
|
|
53
53
|
private applyStructurePreset;
|
|
54
|
+
/**
|
|
55
|
+
* Mol*'s default preset colors ligand carbons by chain, the same color as the protein around them;
|
|
56
|
+
* element colors keep a ligand distinct from its binding pocket.
|
|
57
|
+
*/
|
|
58
|
+
private colorLigandCarbonsByElement;
|
|
54
59
|
private applyVolumeVisuals;
|
|
55
60
|
setVisible(id: string, visible: boolean): void;
|
|
56
61
|
/**
|
|
@@ -113,6 +118,10 @@ export declare class MolStudio {
|
|
|
113
118
|
private transparencyLayers;
|
|
114
119
|
private partLoci;
|
|
115
120
|
private residueRef;
|
|
121
|
+
/**
|
|
122
|
+
* Fits the visible structures, or everything when none is shown. A map's box is usually much larger
|
|
123
|
+
* than its density, so fitting it would leave a fitted model small in the middle of the view.
|
|
124
|
+
*/
|
|
116
125
|
resetCamera(): void;
|
|
117
126
|
setSpinning(spinning: boolean): void;
|
|
118
127
|
setBackground(hex: string): void;
|
package/dist/MolStudio.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { PLDDTConfidenceColorThemeProvider } from "molstar/lib/extensions/model-archive/quality-assessment/color/plddt";
|
|
2
|
+
import { QualityAssessment } from "molstar/lib/extensions/model-archive/quality-assessment/prop";
|
|
3
|
+
import { MmcifFormat } from "molstar/lib/mol-model-formats/structure/mmcif";
|
|
2
4
|
import { DownloadDensity } from "molstar/lib/mol-plugin-state/actions/volume";
|
|
3
5
|
import { PluginConfig } from "molstar/lib/mol-plugin/config";
|
|
4
6
|
import { Volume } from "molstar/lib/mol-model/volume";
|
|
5
7
|
import { Loci } from "molstar/lib/mol-model/loci";
|
|
6
|
-
import { Structure, StructureElement } from "molstar/lib/mol-model/structure";
|
|
8
|
+
import { Model, Structure, StructureElement } from "molstar/lib/mol-model/structure";
|
|
7
9
|
import { createStructureColorThemeParams, createStructureRepresentationParams, } from "molstar/lib/mol-plugin-state/helpers/structure-representation-params";
|
|
8
10
|
import { clearStructureTransparency, setStructureTransparency } from "molstar/lib/mol-plugin-state/helpers/structure-transparency";
|
|
9
11
|
import { createVolumeColorThemeParams } from "molstar/lib/mol-plugin-state/helpers/volume-representation-params";
|
|
@@ -72,7 +74,12 @@ export class MolStudio {
|
|
|
72
74
|
static async create(target) {
|
|
73
75
|
const spec = DefaultPluginSpec();
|
|
74
76
|
// Mol*'s "auto" mode renders at 1x on mobile browsers, which blurs structures on high-DPI phones.
|
|
75
|
-
|
|
77
|
+
// Mol* refuses software WebGL by default; it is slow but renders in VMs, remote desktops and GPU-less CI.
|
|
78
|
+
spec.config = [
|
|
79
|
+
...(spec.config ?? []),
|
|
80
|
+
[PluginConfig.General.ResolutionMode, "native"],
|
|
81
|
+
[PluginConfig.General.AllowMajorPerformanceCaveat, true],
|
|
82
|
+
];
|
|
76
83
|
const plugin = new PluginContext(spec);
|
|
77
84
|
await plugin.init();
|
|
78
85
|
// Only the pLDDT theme is needed; Mol*'s quality-assessment behaviour also pulls in its React UI.
|
|
@@ -227,6 +234,22 @@ export class MolStudio {
|
|
|
227
234
|
if (!result?.structure.data?.elementCount) {
|
|
228
235
|
throw new Error(`The ${format} data contains no atoms.`);
|
|
229
236
|
}
|
|
237
|
+
await this.colorLigandCarbonsByElement(result.structure.ref);
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Mol*'s default preset colors ligand carbons by chain, the same color as the protein around them;
|
|
241
|
+
* element colors keep a ligand distinct from its binding pocket.
|
|
242
|
+
*/
|
|
243
|
+
async colorLigandCarbonsByElement(structureRef) {
|
|
244
|
+
const structure = this.requireStructure(structureRef);
|
|
245
|
+
const reprs = structure.components
|
|
246
|
+
.filter((component) => staticComponentType(component) === "ligand")
|
|
247
|
+
.flatMap((component) => component.representations)
|
|
248
|
+
.filter((repr) => repr.cell.transform.params?.colorTheme.name === "element-symbol");
|
|
249
|
+
await this.updateEach(reprs, (old) => ({
|
|
250
|
+
...old,
|
|
251
|
+
colorTheme: { ...old.colorTheme, params: { ...old.colorTheme.params, carbonColor: { name: "element-symbol", params: {} } } },
|
|
252
|
+
}));
|
|
230
253
|
}
|
|
231
254
|
async applyVolumeVisuals(raw, format) {
|
|
232
255
|
const provider = this.plugin.dataFormats.get(format);
|
|
@@ -380,7 +403,7 @@ export class MolStudio {
|
|
|
380
403
|
? structure.components.flatMap((component) => component.representations)
|
|
381
404
|
: (volume?.representations ?? this.requireComponent(target).representations);
|
|
382
405
|
const renderObjects = reprs.flatMap((repr) => repr.cell.obj?.data.repr.renderObjects ?? []);
|
|
383
|
-
this.plugin.managers.camera.focusRenderObjects(renderObjects);
|
|
406
|
+
this.plugin.managers.camera.focusRenderObjects(renderObjects, FOCUS_OPTIONS);
|
|
384
407
|
}
|
|
385
408
|
async remove(id) {
|
|
386
409
|
await PluginCommands.State.RemoveObject(this.plugin, {
|
|
@@ -408,7 +431,7 @@ export class MolStudio {
|
|
|
408
431
|
const loci = this.partLoci(part);
|
|
409
432
|
if (part.scope === "residue")
|
|
410
433
|
this.plugin.managers.structure.focus.setFromLoci(loci);
|
|
411
|
-
this.plugin.managers.camera.focusLoci(loci);
|
|
434
|
+
this.plugin.managers.camera.focusLoci(loci, FOCUS_OPTIONS);
|
|
412
435
|
}
|
|
413
436
|
/** Leaves Mol*'s focus view, removing its target and surroundings components, and returns to the earlier view. */
|
|
414
437
|
clearFocus() {
|
|
@@ -562,8 +585,21 @@ export class MolStudio {
|
|
|
562
585
|
return owner ? { objectId: owner.cell.transform.ref, residueIndex } : null;
|
|
563
586
|
}
|
|
564
587
|
// ---- viewport ----
|
|
588
|
+
/**
|
|
589
|
+
* Fits the visible structures, or everything when none is shown. A map's box is usually much larger
|
|
590
|
+
* than its density, so fitting it would leave a fitted model small in the middle of the view.
|
|
591
|
+
*/
|
|
565
592
|
resetCamera() {
|
|
566
|
-
|
|
593
|
+
const renderObjects = this.plugin.managers.structure.hierarchy.current.structures
|
|
594
|
+
.flatMap((structure) => structure.components)
|
|
595
|
+
.flatMap((component) => component.representations)
|
|
596
|
+
.flatMap((repr) => repr.cell.obj?.data.repr.renderObjects ?? [])
|
|
597
|
+
.filter((renderObject) => renderObject.state.visible);
|
|
598
|
+
if (renderObjects.length === 0) {
|
|
599
|
+
PluginCommands.Camera.Reset(this.plugin, {});
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
this.plugin.managers.camera.focusRenderObjects(renderObjects, { extraRadius: 0 });
|
|
567
603
|
}
|
|
568
604
|
setSpinning(spinning) {
|
|
569
605
|
const canvas3d = this.requireCanvas();
|
|
@@ -727,8 +763,7 @@ export class MolStudio {
|
|
|
727
763
|
}
|
|
728
764
|
applicableSchemes(ref) {
|
|
729
765
|
const structure = ref.cell.obj?.data;
|
|
730
|
-
const
|
|
731
|
-
const hasPlddt = !!structure && !!plddt?.isApplicable({ structure });
|
|
766
|
+
const hasPlddt = !!structure && structure.models.some(isPredictedModel);
|
|
732
767
|
return hasPlddt ? ["plddt-confidence", ...BASE_SCHEMES] : [...BASE_SCHEMES];
|
|
733
768
|
}
|
|
734
769
|
// ---- lookup helpers ----
|
|
@@ -841,6 +876,21 @@ const AXES = {
|
|
|
841
876
|
};
|
|
842
877
|
/** Matches Mol*'s default camera focus animation. */
|
|
843
878
|
const CAMERA_TRANSITION_MS = 250;
|
|
879
|
+
/** Keeps the surroundings of small targets (a ligand, a residue) in view instead of filling the screen with them. */
|
|
880
|
+
const FOCUS_OPTIONS = { minRadius: 14 };
|
|
881
|
+
/**
|
|
882
|
+
* Whether B-factors hold pLDDT scores. Mol* assumes so for any model not marked experimental, but most
|
|
883
|
+
* PDB entries lack that mark, so an entry with experimental methods recorded does not count.
|
|
884
|
+
*/
|
|
885
|
+
function isPredictedModel(model) {
|
|
886
|
+
if (QualityAssessment.isApplicable(model, "pLDDT"))
|
|
887
|
+
return true;
|
|
888
|
+
if (!MmcifFormat.is(model.sourceData) || !model.atomicConformation.B_iso_or_equiv.isDefined)
|
|
889
|
+
return false;
|
|
890
|
+
if (Model.isExperimental(model))
|
|
891
|
+
return false;
|
|
892
|
+
return model.sourceData.data.db.exptl.method.rowCount === 0;
|
|
893
|
+
}
|
|
844
894
|
const FOCUS_TAGS = {
|
|
845
895
|
[StructureFocusRepresentationTags.TargetSel]: "target",
|
|
846
896
|
[StructureFocusRepresentationTags.SurrSel]: "surroundings",
|