mirror of
https://github.com/molstar/molstar.git
synced 2026-06-07 23:34:23 +08:00
Compare commits
23 Commits
v0.7.0-dev
...
v0.7.0-dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b14b5ca626 | ||
|
|
ffbaa944f2 | ||
|
|
e2ba96174a | ||
|
|
8c5d99bb54 | ||
|
|
b18b3be070 | ||
|
|
2e69b7c419 | ||
|
|
5007f5fb72 | ||
|
|
6fe83a9a70 | ||
|
|
20af084127 | ||
|
|
d6501170e6 | ||
|
|
5f33364514 | ||
|
|
7924c008fa | ||
|
|
2d2a53f28e | ||
|
|
1f7ffabef9 | ||
|
|
16d5c07224 | ||
|
|
2392bfb579 | ||
|
|
b4036f576c | ||
|
|
690d6812dc | ||
|
|
a44aa02f13 | ||
|
|
65ddd6d68a | ||
|
|
754025b3b1 | ||
|
|
f0649c5aa3 | ||
|
|
6df045211c |
2
package-lock.json
generated
2
package-lock.json
generated
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "molstar",
|
||||
"version": "0.7.0-dev.10",
|
||||
"version": "0.7.0-dev.13",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "molstar",
|
||||
"version": "0.7.0-dev.10",
|
||||
"version": "0.7.0-dev.13",
|
||||
"description": "A comprehensive macromolecular library.",
|
||||
"homepage": "https://github.com/molstar/molstar#readme",
|
||||
"repository": {
|
||||
@@ -34,9 +34,8 @@
|
||||
"model-server-watch": "nodemon --watch lib lib/servers/servers/model/server.js",
|
||||
"volume-server-test": "node lib/servers/servers/volume/server.js --idMap em 'test/${id}.mdb' --defaultPort 1336",
|
||||
"plugin-state": "node lib/servers/servers/plugin-state/index.js",
|
||||
"preversion": "npm run test",
|
||||
"postversion": "git push && git push --tags",
|
||||
"prepublishOnly": "npm run test && npm run build"
|
||||
"preversion": "npm run test && npm run build",
|
||||
"postversion": "git push && git push --tags"
|
||||
},
|
||||
"files": [
|
||||
"lib/"
|
||||
|
||||
@@ -92,6 +92,12 @@
|
||||
// var format = 'pdb';
|
||||
// var assemblyId = 'deposited';
|
||||
|
||||
function loadAndSnapshot(params) {
|
||||
PluginWrapper.load(params).then(() => {
|
||||
setTimeout(() => snapshot = PluginWrapper.plugin.state.getSnapshot({ canvas3d: false /* do not save spinning state */ }), 500);
|
||||
});
|
||||
}
|
||||
|
||||
var representationStyle = {
|
||||
// sequence: { coloring: 'proteopedia-custom' }, // or just { }
|
||||
hetGroups: { kind: 'ball-and-stick' }, // or 'spacefill
|
||||
@@ -103,7 +109,7 @@
|
||||
customColorList: CustomColors
|
||||
});
|
||||
PluginWrapper.setBackground(0xffffff);
|
||||
PluginWrapper.load({ url: url, format: format, isBinary: isBinary, assemblyId: assemblyId, representationStyle: representationStyle });
|
||||
loadAndSnapshot({ url: url, format: format, isBinary: isBinary, assemblyId: assemblyId, representationStyle: representationStyle });
|
||||
PluginWrapper.toggleSpin();
|
||||
|
||||
PluginWrapper.events.modelInfo.subscribe(function (info) {
|
||||
@@ -111,8 +117,8 @@
|
||||
listHetGroups(info);
|
||||
});
|
||||
|
||||
addControl('Load Asym Unit', () => PluginWrapper.load({ url: url, format: format, isBinary }));
|
||||
addControl('Load Assembly', () => PluginWrapper.load({ url: url, format: format, isBinary, assemblyId: assemblyId }));
|
||||
addControl('Load Asym Unit', () => loadAndSnapshot({ url: url, format: format, isBinary }));
|
||||
addControl('Load Assembly', () => loadAndSnapshot({ url: url, format: format, isBinary, assemblyId: assemblyId }));
|
||||
|
||||
addSeparator();
|
||||
|
||||
@@ -185,10 +191,10 @@
|
||||
PluginWrapper.snapshot.set(snapshot);
|
||||
});
|
||||
addControl('Download State', () => {
|
||||
snapshot = PluginWrapper.snapshot.download('molj');
|
||||
PluginWrapper.snapshot.download('molj');
|
||||
});
|
||||
addControl('Download Session', () => {
|
||||
snapshot = PluginWrapper.snapshot.download('molx');
|
||||
PluginWrapper.snapshot.download('molx');
|
||||
});
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
@@ -5,35 +5,34 @@
|
||||
*/
|
||||
|
||||
import * as ReactDOM from 'react-dom';
|
||||
import { Canvas3DProps, DefaultCanvas3DParams } from '../../mol-canvas3d/canvas3d';
|
||||
import { createPlugin, DefaultPluginSpec } from '../../mol-plugin';
|
||||
import './index.html';
|
||||
import { PluginContext } from '../../mol-plugin/context';
|
||||
import { PluginCommands } from '../../mol-plugin/commands';
|
||||
import { StateTransforms } from '../../mol-plugin-state/transforms';
|
||||
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, StateSelection } from '../../mol-state';
|
||||
import { EvolutionaryConservation } from './annotation';
|
||||
import { LoadParams, SupportedFormats, RepresentationStyle, ModelInfo, StateElements } from './helpers';
|
||||
import { RxEventHelper } from '../../mol-util/rx-event-helper';
|
||||
import { volumeStreamingControls } from './ui/controls';
|
||||
import { PluginState } from '../../mol-plugin/state';
|
||||
import { Scheduler } from '../../mol-task';
|
||||
import { createProteopediaCustomTheme } from './coloring';
|
||||
import { MolScriptBuilder as MS } from '../../mol-script/language/builder';
|
||||
import { ColorNames } from '../../mol-util/color/names';
|
||||
import { InitVolumeStreaming, CreateVolumeStreamingInfo } from '../../mol-plugin/behavior/dynamic/volume-streaming/transformers';
|
||||
import { DefaultCanvas3DParams, Canvas3DProps } from '../../mol-canvas3d/canvas3d';
|
||||
import { createStructureRepresentationParams } from '../../mol-plugin-state/helpers/structure-representation-params';
|
||||
import { download } from '../../mol-util/download';
|
||||
import { getFormattedTime } from '../../mol-util/date';
|
||||
import { PluginStateObject, PluginStateObject as PSO } from '../../mol-plugin-state/objects';
|
||||
import { StateTransforms } from '../../mol-plugin-state/transforms';
|
||||
import { CreateVolumeStreamingInfo, InitVolumeStreaming } from '../../mol-plugin/behavior/dynamic/volume-streaming/transformers';
|
||||
import { PluginCommands } from '../../mol-plugin/commands';
|
||||
import { PluginContext } from '../../mol-plugin/context';
|
||||
import { PluginState } from '../../mol-plugin/state';
|
||||
import { MolScriptBuilder as MS } from '../../mol-script/language/builder';
|
||||
import { StateBuilder, StateObject, StateSelection } from '../../mol-state';
|
||||
import { Asset } from '../../mol-util/assets';
|
||||
import { Color } from '../../mol-util/color';
|
||||
import { ColorNames } from '../../mol-util/color/names';
|
||||
import { getFormattedTime } from '../../mol-util/date';
|
||||
import { download } from '../../mol-util/download';
|
||||
import { RxEventHelper } from '../../mol-util/rx-event-helper';
|
||||
import { EvolutionaryConservation } from './annotation';
|
||||
import { createProteopediaCustomTheme } from './coloring';
|
||||
import { LoadParams, ModelInfo, RepresentationStyle, StateElements, SupportedFormats } from './helpers';
|
||||
import './index.html';
|
||||
import { volumeStreamingControls } from './ui/controls';
|
||||
require('../../mol-plugin-ui/skin/light.scss');
|
||||
|
||||
class MolStarProteopediaWrapper {
|
||||
static VERSION_MAJOR = 5;
|
||||
static VERSION_MINOR = 4;
|
||||
static VERSION_MINOR = 5;
|
||||
|
||||
private _ev = RxEventHelper.create();
|
||||
|
||||
@@ -233,7 +232,6 @@ class MolStarProteopediaWrapper {
|
||||
await this.updateStyle(representationStyle);
|
||||
|
||||
this.loadedParams = { url, format, assemblyId };
|
||||
Scheduler.setImmediate(() => PluginCommands.Camera.Reset(this.plugin, { }));
|
||||
}
|
||||
|
||||
async updateStyle(style?: RepresentationStyle, partial?: boolean) {
|
||||
@@ -407,7 +405,7 @@ class MolStarProteopediaWrapper {
|
||||
try {
|
||||
const data = await this.plugin.runTask(this.plugin.fetch({ url, type: 'binary' }));
|
||||
this.loadedParams = { ...this.emptyLoadedParams };
|
||||
await this.plugin.managers.snapshot.open(new File([data], `state.${type}`));
|
||||
return await this.plugin.managers.snapshot.open(new File([data], `state.${type}`));
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
|
||||
@@ -27,61 +27,75 @@ import { Column } from '../../mol-data/db';
|
||||
import { createModels } from '../../mol-model-formats/structure/basic/parser';
|
||||
import { CellpackPackingPreset, CellpackMembranePreset } from './preset';
|
||||
import { Asset } from '../../mol-util/assets';
|
||||
import { readFromFile } from '../../mol-util/data-source';
|
||||
import { objectForEach } from '../../mol-util/object';
|
||||
|
||||
function getCellPackModelUrl(fileName: string, baseUrl: string) {
|
||||
return `${baseUrl}/results/${fileName}`;
|
||||
}
|
||||
|
||||
async function getModel(plugin: PluginContext, id: string, ingredient: Ingredient, baseUrl: string, file?: Asset.File) {
|
||||
class TrajectoryCache {
|
||||
private map = new Map<string, Model.Trajectory>();
|
||||
set(id: string, trajectory: Model.Trajectory) { this.map.set(id, trajectory); }
|
||||
get(id: string) { return this.map.get(id); }
|
||||
}
|
||||
|
||||
async function getModel(plugin: PluginContext, id: string, ingredient: Ingredient, baseUrl: string, trajCache: TrajectoryCache, file?: Asset.File) {
|
||||
const assetManager = plugin.managers.asset;
|
||||
const model_id = (ingredient.source.model) ? parseInt(ingredient.source.model) : 0;
|
||||
const modelIndex = (ingredient.source.model) ? parseInt(ingredient.source.model) : 0;
|
||||
const surface = (ingredient.ingtype) ? (ingredient.ingtype === 'transmembrane') : false;
|
||||
let model: Model;
|
||||
let trajectory = trajCache.get(id);
|
||||
let assets: Asset.Wrapper[] = [];
|
||||
if (file) {
|
||||
if (file.name.endsWith('.cif')) {
|
||||
const text = await plugin.runTask(assetManager.resolve(file, 'string'));
|
||||
assets.push(text);
|
||||
const cif = (await parseCif(plugin, text.data)).blocks[0];
|
||||
model = (await plugin.runTask(trajectoryFromMmCIF(cif)))[model_id];
|
||||
} else if (file.name.endsWith('.bcif')) {
|
||||
const binary = await plugin.runTask(assetManager.resolve(file, 'binary'));
|
||||
assets.push(binary);
|
||||
const cif = (await parseCif(plugin, binary.data)).blocks[0];
|
||||
model = (await plugin.runTask(trajectoryFromMmCIF(cif)))[model_id];
|
||||
} else if (file.name.endsWith('.pdb')) {
|
||||
const text = await plugin.runTask(assetManager.resolve(file, 'string'));
|
||||
assets.push(text);
|
||||
const pdb = await parsePDBfile(plugin, text.data, id);
|
||||
model = (await plugin.runTask(trajectoryFromPDB(pdb)))[model_id];
|
||||
} else {
|
||||
throw new Error(`unsupported file type '${file.name}'`);
|
||||
}
|
||||
} else if (id.match(/^[1-9][a-zA-Z0-9]{3,3}$/i)) {
|
||||
if (surface){
|
||||
const data = await getFromOPM(plugin, id, assetManager);
|
||||
if (data.asset){
|
||||
assets.push(data.asset);
|
||||
model = (await plugin.runTask(trajectoryFromPDB(data.pdb)))[model_id];
|
||||
if (!trajectory) {
|
||||
if (file) {
|
||||
if (file.name.endsWith('.cif')) {
|
||||
const text = await plugin.runTask(assetManager.resolve(file, 'string'));
|
||||
assets.push(text);
|
||||
const cif = (await parseCif(plugin, text.data)).blocks[0];
|
||||
trajectory = await plugin.runTask(trajectoryFromMmCIF(cif));
|
||||
} else if (file.name.endsWith('.bcif')) {
|
||||
const binary = await plugin.runTask(assetManager.resolve(file, 'binary'));
|
||||
assets.push(binary);
|
||||
const cif = (await parseCif(plugin, binary.data)).blocks[0];
|
||||
trajectory = await plugin.runTask(trajectoryFromMmCIF(cif));
|
||||
} else if (file.name.endsWith('.pdb')) {
|
||||
const text = await plugin.runTask(assetManager.resolve(file, 'string'));
|
||||
assets.push(text);
|
||||
const pdb = await parsePDBfile(plugin, text.data, id);
|
||||
trajectory = await plugin.runTask(trajectoryFromPDB(pdb));
|
||||
} else {
|
||||
throw new Error(`unsupported file type '${file.name}'`);
|
||||
}
|
||||
} else if (id.match(/^[1-9][a-zA-Z0-9]{3,3}$/i)) {
|
||||
if (surface){
|
||||
try {
|
||||
const data = await getFromOPM(plugin, id, assetManager);
|
||||
assets.push(data.asset);
|
||||
trajectory = await plugin.runTask(trajectoryFromPDB(data.pdb));
|
||||
} catch (e) {
|
||||
// fallback to getFromPdb
|
||||
// console.error(e);
|
||||
const { mmcif, asset } = await getFromPdb(plugin, id, assetManager);
|
||||
assets.push(asset);
|
||||
trajectory = await plugin.runTask(trajectoryFromMmCIF(mmcif));
|
||||
}
|
||||
} else {
|
||||
const { mmcif, asset } = await getFromPdb(plugin, id, assetManager);
|
||||
assets.push(asset);
|
||||
model = (await plugin.runTask(trajectoryFromMmCIF(mmcif)))[model_id];
|
||||
trajectory = await plugin.runTask(trajectoryFromMmCIF(mmcif));
|
||||
}
|
||||
} else {
|
||||
const { mmcif, asset } = await getFromPdb(plugin, id, assetManager);
|
||||
assets.push(asset);
|
||||
model = (await plugin.runTask(trajectoryFromMmCIF(mmcif)))[model_id];
|
||||
}
|
||||
} else {
|
||||
const data = await getFromCellPackDB(plugin, id, baseUrl, assetManager);
|
||||
assets.push(data.asset);
|
||||
if ('pdb' in data) {
|
||||
model = (await plugin.runTask(trajectoryFromPDB(data.pdb)))[model_id];
|
||||
} else {
|
||||
model = (await plugin.runTask(trajectoryFromMmCIF(data.mmcif)))[model_id];
|
||||
const data = await getFromCellPackDB(plugin, id, baseUrl, assetManager);
|
||||
assets.push(data.asset);
|
||||
if ('pdb' in data) {
|
||||
trajectory = await plugin.runTask(trajectoryFromPDB(data.pdb));
|
||||
} else {
|
||||
trajectory = await plugin.runTask(trajectoryFromMmCIF(data.mmcif));
|
||||
}
|
||||
}
|
||||
trajCache.set(id, trajectory);
|
||||
}
|
||||
const model = trajectory[modelIndex];
|
||||
return { model, assets };
|
||||
}
|
||||
|
||||
@@ -133,7 +147,6 @@ function getTransform(trans: Vec3, rot: Quat) {
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
function getResultTransforms(results: Ingredient['results'], legacy: boolean) {
|
||||
if (legacy) return results.map((r: Ingredient['results'][0]) => getTransformLegacy(r[0], r[1]));
|
||||
else return results.map((r: Ingredient['results'][0]) => getTransform(r[0], r[1]));
|
||||
@@ -288,7 +301,7 @@ async function getCurve(plugin: PluginContext, name: string, ingredient: Ingredi
|
||||
return getStructure(plugin, curveModel, ingredient.source);
|
||||
}
|
||||
|
||||
async function getIngredientStructure(plugin: PluginContext, ingredient: Ingredient, baseUrl: string, ingredientFiles: IngredientFiles) {
|
||||
async function getIngredientStructure(plugin: PluginContext, ingredient: Ingredient, baseUrl: string, ingredientFiles: IngredientFiles, trajCache: TrajectoryCache) {
|
||||
const { name, source, results, nbCurve } = ingredient;
|
||||
if (source.pdb === 'None') return;
|
||||
|
||||
@@ -303,7 +316,7 @@ async function getIngredientStructure(plugin: PluginContext, ingredient: Ingredi
|
||||
}
|
||||
|
||||
// model id in case structure is NMR
|
||||
const { model, assets } = await getModel(plugin, source.pdb || name, ingredient, baseUrl, file);
|
||||
const { model, assets } = await getModel(plugin, source.pdb || name, ingredient, baseUrl, trajCache, file);
|
||||
if (!model) return;
|
||||
|
||||
let structure: Structure;
|
||||
@@ -354,10 +367,11 @@ export function createStructureFromCellPack(plugin: PluginContext, packing: Cell
|
||||
return Task.create('Create Packing Structure', async ctx => {
|
||||
const { ingredients, name } = packing;
|
||||
const assets: Asset.Wrapper[] = [];
|
||||
const trajCache = new TrajectoryCache();
|
||||
const structures: Structure[] = [];
|
||||
for (const iName in ingredients) {
|
||||
if (ctx.shouldUpdate) await ctx.update(iName);
|
||||
const ingredientStructure = await getIngredientStructure(plugin, ingredients[iName], baseUrl, ingredientFiles);
|
||||
const ingredientStructure = await getIngredientStructure(plugin, ingredients[iName], baseUrl, ingredientFiles, trajCache);
|
||||
if (ingredientStructure) {
|
||||
structures.push(ingredientStructure.structure);
|
||||
assets.push(...ingredientStructure.assets);
|
||||
@@ -444,6 +458,8 @@ async function loadMembrane(plugin: PluginContext, name: string, state: State, p
|
||||
}
|
||||
|
||||
async function loadPackings(plugin: PluginContext, runtime: RuntimeContext, state: State, params: LoadCellPackModelParams) {
|
||||
const ingredientFiles = params.ingredients.files || [];
|
||||
|
||||
let cellPackJson: StateBuilder.To<PSO.Format.Json, StateTransformer<PSO.Data.String, PSO.Format.Json>>;
|
||||
if (params.source.name === 'id') {
|
||||
const url = Asset.getUrlAsset(plugin.managers.asset, getCellPackModelUrl(params.source.params, params.baseUrl));
|
||||
@@ -451,12 +467,25 @@ async function loadPackings(plugin: PluginContext, runtime: RuntimeContext, stat
|
||||
.apply(StateTransforms.Data.Download, { url, isBinary: false, label: params.source.params }, { state: { isGhost: true } });
|
||||
} else {
|
||||
const file = params.source.params;
|
||||
if (file === null) {
|
||||
if (!file?.file) {
|
||||
plugin.log.error('No file selected');
|
||||
return;
|
||||
}
|
||||
|
||||
let jsonFile: Asset.File;
|
||||
if (file.name.toLowerCase().endsWith('.zip')) {
|
||||
const data = await readFromFile(file.file, 'zip').runInContext(runtime);
|
||||
jsonFile = Asset.File(new File([data['model.json']], 'model.json'));
|
||||
objectForEach(data, (v, k) => {
|
||||
if (k === 'model.json') return;
|
||||
ingredientFiles.push(Asset.File(new File([v], k)));
|
||||
});
|
||||
} else {
|
||||
jsonFile = file;
|
||||
}
|
||||
|
||||
cellPackJson = state.build().toRoot()
|
||||
.apply(StateTransforms.Data.ReadFile, { file, isBinary: false, label: file.name }, { state: { isGhost: true } });
|
||||
.apply(StateTransforms.Data.ReadFile, { file: jsonFile, isBinary: false, label: jsonFile.name }, { state: { isGhost: true } });
|
||||
}
|
||||
|
||||
const cellPackBuilder = cellPackJson
|
||||
@@ -469,7 +498,7 @@ async function loadPackings(plugin: PluginContext, runtime: RuntimeContext, stat
|
||||
await handleHivRna(plugin, packings, params.baseUrl);
|
||||
|
||||
for (let i = 0, il = packings.length; i < il; ++i) {
|
||||
const p = { packing: i, baseUrl: params.baseUrl, ingredientFiles: params.ingredients.files };
|
||||
const p = { packing: i, baseUrl: params.baseUrl, ingredientFiles };
|
||||
|
||||
const packing = await state.build()
|
||||
.to(cellPackBuilder.ref)
|
||||
@@ -497,8 +526,8 @@ const LoadCellPackModelParams = {
|
||||
['influenza_model1.json', 'influenza_model1'],
|
||||
['ExosomeModel.json', 'ExosomeModel'],
|
||||
['Mycoplasma1.5_mixed_pdb_fixed.cpr', 'Mycoplasma1.5_mixed_pdb_fixed'],
|
||||
] as const),
|
||||
'file': PD.File({ accept: 'id' }),
|
||||
] as const, { description: 'Download the model definition with `id` from the server at `baseUrl.`' }),
|
||||
'file': PD.File({ accept: '.json,.cpr,.zip', description: 'Open model definition from .json/.cpr file or open .zip file containing model definition plus ingredients.' }),
|
||||
}, { options: [['id', 'Id'], ['file', 'File']] }),
|
||||
baseUrl: PD.Text(DefaultCellPackBaseUrl),
|
||||
ingredients : PD.Group({
|
||||
|
||||
@@ -59,7 +59,7 @@ export const PostprocessingParams = {
|
||||
outline: PD.MappedStatic('off', {
|
||||
on: PD.Group({
|
||||
scale: PD.Numeric(1, { min: 0, max: 10, step: 1 }),
|
||||
threshold: PD.Numeric(0.8, { min: 0, max: 1, step: 0.01 }),
|
||||
threshold: PD.Numeric(0.8, { min: 0, max: 5, step: 0.01 }),
|
||||
}),
|
||||
off: PD.Group({})
|
||||
}, { cycle: true, description: 'Draw outline around 3D objects' })
|
||||
|
||||
@@ -44,9 +44,6 @@ export function createRenderable<T extends Values<RenderableSchema>>(renderItem:
|
||||
if (values.uAlpha && values.alpha) {
|
||||
ValueCell.updateIfChanged(values.uAlpha, clamp(values.alpha.ref.value * state.alphaFactor, 0, 1));
|
||||
}
|
||||
if (values.uPickable) {
|
||||
ValueCell.updateIfChanged(values.uPickable, state.pickable ? 1 : 0);
|
||||
}
|
||||
renderItem.render(variant);
|
||||
},
|
||||
getProgram: (variant: GraphicsRenderVariant) => renderItem.getProgram(variant),
|
||||
|
||||
@@ -73,7 +73,6 @@ export function DirectVolumeRenderable(ctx: WebGLContext, id: number, values: Di
|
||||
const schema = { ...GlobalUniformSchema, ...InternalSchema, ...DirectVolumeSchema };
|
||||
const internalValues: InternalValues = {
|
||||
uObjectId: ValueCell.create(id),
|
||||
uPickable: ValueCell.create(state.pickable ? 1 : 0),
|
||||
};
|
||||
const shaderCode = DirectVolumeShaderCode;
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId);
|
||||
|
||||
@@ -33,7 +33,6 @@ export function ImageRenderable(ctx: WebGLContext, id: number, values: ImageValu
|
||||
const schema = { ...GlobalUniformSchema, ...InternalSchema, ...ImageSchema };
|
||||
const internalValues: InternalValues = {
|
||||
uObjectId: ValueCell.create(id),
|
||||
uPickable: ValueCell.create(state.pickable ? 1 : 0),
|
||||
};
|
||||
const shaderCode = ImageShaderCode;
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId);
|
||||
|
||||
@@ -29,7 +29,6 @@ export function LinesRenderable(ctx: WebGLContext, id: number, values: LinesValu
|
||||
const schema = { ...GlobalUniformSchema, ...InternalSchema, ...LinesSchema };
|
||||
const internalValues: InternalValues = {
|
||||
uObjectId: ValueCell.create(id),
|
||||
uPickable: ValueCell.create(state.pickable ? 1 : 0)
|
||||
};
|
||||
const shaderCode = LinesShaderCode;
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId);
|
||||
|
||||
@@ -28,7 +28,6 @@ export function MeshRenderable(ctx: WebGLContext, id: number, values: MeshValues
|
||||
const schema = { ...GlobalUniformSchema, ...InternalSchema, ...MeshSchema };
|
||||
const internalValues: InternalValues = {
|
||||
uObjectId: ValueCell.create(id),
|
||||
uPickable: ValueCell.create(state.pickable ? 1 : 0)
|
||||
};
|
||||
const shaderCode = MeshShaderCode;
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId);
|
||||
|
||||
@@ -26,7 +26,6 @@ export function PointsRenderable(ctx: WebGLContext, id: number, values: PointsVa
|
||||
const schema = { ...GlobalUniformSchema, ...InternalSchema, ...PointsSchema };
|
||||
const internalValues: InternalValues = {
|
||||
uObjectId: ValueCell.create(id),
|
||||
uPickable: ValueCell.create(state.pickable ? 1 : 0)
|
||||
};
|
||||
const shaderCode = PointsShaderCode;
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'points', shaderCode, schema, { ...values, ...internalValues }, materialId);
|
||||
|
||||
@@ -187,7 +187,6 @@ export type GlobalUniformValues = Values<GlobalUniformSchema> // { [k in keyof G
|
||||
|
||||
export const InternalSchema = {
|
||||
uObjectId: UniformSpec('i'),
|
||||
uPickable: UniformSpec('i', true),
|
||||
} as const;
|
||||
export type InternalSchema = typeof InternalSchema
|
||||
export type InternalValues = { [k in keyof InternalSchema]: ValueCell<any> }
|
||||
|
||||
@@ -29,7 +29,6 @@ export function SpheresRenderable(ctx: WebGLContext, id: number, values: Spheres
|
||||
const schema = { ...GlobalUniformSchema, ...InternalSchema, ...SpheresSchema };
|
||||
const internalValues: InternalValues = {
|
||||
uObjectId: ValueCell.create(id),
|
||||
uPickable: ValueCell.create(state.pickable ? 1 : 0)
|
||||
};
|
||||
const shaderCode = SpheresShaderCode;
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId);
|
||||
|
||||
@@ -38,7 +38,6 @@ export function TextRenderable(ctx: WebGLContext, id: number, values: TextValues
|
||||
const schema = { ...GlobalUniformSchema, ...InternalSchema, ...TextSchema };
|
||||
const internalValues: InternalValues = {
|
||||
uObjectId: ValueCell.create(id),
|
||||
uPickable: ValueCell.create(state.pickable ? 1 : 0)
|
||||
};
|
||||
const shaderCode = TextShaderCode;
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId);
|
||||
|
||||
@@ -31,7 +31,6 @@ export function TextureMeshRenderable(ctx: WebGLContext, id: number, values: Tex
|
||||
const schema = { ...GlobalUniformSchema, ...InternalSchema, ...TextureMeshSchema };
|
||||
const internalValues: InternalValues = {
|
||||
uObjectId: ValueCell.create(id),
|
||||
uPickable: ValueCell.create(state.pickable ? 1 : 0)
|
||||
};
|
||||
const shaderCode = MeshShaderCode;
|
||||
const renderItem = createGraphicsRenderItem(ctx, 'triangles', shaderCode, schema, { ...values, ...internalValues }, materialId);
|
||||
|
||||
@@ -173,51 +173,53 @@ namespace Renderer {
|
||||
let globalUniformsNeedUpdate = true;
|
||||
|
||||
const renderObject = (r: Renderable<RenderableValues & BaseValues>, variant: GraphicsRenderVariant) => {
|
||||
if (!r.state.visible || (!r.state.pickable && variant[0] === 'p')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const program = r.getProgram(variant);
|
||||
if (r.state.visible) {
|
||||
if (state.currentProgramId !== program.id) {
|
||||
// console.log('new program')
|
||||
globalUniformsNeedUpdate = true;
|
||||
program.use();
|
||||
}
|
||||
if (state.currentProgramId !== program.id) {
|
||||
// console.log('new program')
|
||||
globalUniformsNeedUpdate = true;
|
||||
program.use();
|
||||
}
|
||||
|
||||
if (globalUniformsNeedUpdate) {
|
||||
// console.log('globalUniformsNeedUpdate')
|
||||
program.setUniforms(globalUniformList);
|
||||
globalUniformsNeedUpdate = false;
|
||||
}
|
||||
if (globalUniformsNeedUpdate) {
|
||||
// console.log('globalUniformsNeedUpdate')
|
||||
program.setUniforms(globalUniformList);
|
||||
globalUniformsNeedUpdate = false;
|
||||
}
|
||||
|
||||
if (r.values.dDoubleSided) {
|
||||
if (r.values.dDoubleSided.ref.value) {
|
||||
state.disable(gl.CULL_FACE);
|
||||
} else {
|
||||
state.enable(gl.CULL_FACE);
|
||||
}
|
||||
} else {
|
||||
// webgl default
|
||||
if (r.values.dDoubleSided) {
|
||||
if (r.values.dDoubleSided.ref.value) {
|
||||
state.disable(gl.CULL_FACE);
|
||||
}
|
||||
|
||||
if (r.values.dFlipSided) {
|
||||
if (r.values.dFlipSided.ref.value) {
|
||||
state.frontFace(gl.CW);
|
||||
state.cullFace(gl.FRONT);
|
||||
} else {
|
||||
state.frontFace(gl.CCW);
|
||||
state.cullFace(gl.BACK);
|
||||
}
|
||||
} else {
|
||||
// webgl default
|
||||
state.enable(gl.CULL_FACE);
|
||||
}
|
||||
} else {
|
||||
// webgl default
|
||||
state.disable(gl.CULL_FACE);
|
||||
}
|
||||
|
||||
if (r.values.dFlipSided) {
|
||||
if (r.values.dFlipSided.ref.value) {
|
||||
state.frontFace(gl.CW);
|
||||
state.cullFace(gl.FRONT);
|
||||
} else {
|
||||
state.frontFace(gl.CCW);
|
||||
state.cullFace(gl.BACK);
|
||||
}
|
||||
|
||||
if (variant === 'color') {
|
||||
state.depthMask(r.state.writeDepth);
|
||||
}
|
||||
|
||||
r.render(variant);
|
||||
} else {
|
||||
// webgl default
|
||||
state.frontFace(gl.CCW);
|
||||
state.cullFace(gl.BACK);
|
||||
}
|
||||
|
||||
if (variant === 'color') {
|
||||
state.depthMask(r.state.writeDepth);
|
||||
}
|
||||
|
||||
r.render(variant);
|
||||
};
|
||||
|
||||
const render = (scene: Scene, camera: Camera, variant: GraphicsRenderVariant, clear: boolean, transparentBackground: boolean) => {
|
||||
|
||||
@@ -34,7 +34,7 @@ export default `
|
||||
if (ta < 0.99 && (ta < 0.01 || ta < at)) discard;
|
||||
#endif
|
||||
#elif defined(dRenderVariant_pick)
|
||||
vec4 material = uPickable == 1 ? vColor : vec4(0.0, 0.0, 0.0, 1.0); // set to empty picking id
|
||||
vec4 material = vColor;
|
||||
#elif defined(dRenderVariant_depth)
|
||||
#ifdef enabledFragDepth
|
||||
vec4 material = packDepthToRGBA(gl_FragDepthEXT);
|
||||
|
||||
@@ -21,7 +21,6 @@ uniform vec3 uFogColor;
|
||||
|
||||
uniform float uAlpha;
|
||||
uniform float uPickingAlphaThreshold;
|
||||
uniform int uPickable;
|
||||
uniform int uTransparentBackground;
|
||||
|
||||
uniform float uInteriorDarkening;
|
||||
|
||||
@@ -28,7 +28,6 @@ uniform sampler2D tMarker;
|
||||
|
||||
uniform float uAlpha;
|
||||
uniform float uPickingAlphaThreshold;
|
||||
uniform int uPickable;
|
||||
|
||||
#if defined(dGridTexType_2d)
|
||||
precision highp sampler2D;
|
||||
@@ -117,8 +116,6 @@ vec4 raymarch(vec3 startLoc, vec3 step, vec3 viewDir) {
|
||||
#if defined(dRenderVariant_pick)
|
||||
if (uAlpha < uPickingAlphaThreshold)
|
||||
discard; // ignore so the element below can be picked
|
||||
if (uPickable == 0)
|
||||
return vec4(0.0, 0.0, 0.0, 1.0); // set to empty picking id
|
||||
#endif
|
||||
|
||||
#if defined(dRenderVariant_pickObject)
|
||||
|
||||
@@ -99,18 +99,14 @@ void main() {
|
||||
if (imageData.a < 0.3)
|
||||
discard;
|
||||
|
||||
if (uPickable == 1) {
|
||||
#if defined(dRenderVariant_pickObject)
|
||||
gl_FragColor = vec4(encodeFloatRGB(float(uObjectId)), 1.0);
|
||||
#elif defined(dRenderVariant_pickInstance)
|
||||
gl_FragColor = vec4(encodeFloatRGB(vInstance), 1.0);
|
||||
#elif defined(dRenderVariant_pickGroup)
|
||||
float group = texture2D(tGroupTex, vUv).r;
|
||||
gl_FragColor = vec4(encodeFloatRGB(group), 1.0);
|
||||
#endif
|
||||
} else {
|
||||
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0); // set to empty picking id
|
||||
}
|
||||
#if defined(dRenderVariant_pickObject)
|
||||
gl_FragColor = vec4(encodeFloatRGB(float(uObjectId)), 1.0);
|
||||
#elif defined(dRenderVariant_pickInstance)
|
||||
gl_FragColor = vec4(encodeFloatRGB(vInstance), 1.0);
|
||||
#elif defined(dRenderVariant_pickGroup)
|
||||
float group = texture2D(tGroupTex, vUv).r;
|
||||
gl_FragColor = vec4(encodeFloatRGB(group), 1.0);
|
||||
#endif
|
||||
#elif defined(dRenderVariant_depth)
|
||||
if (imageData.a < 0.05)
|
||||
discard;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
import Mol2 from '../mol2/parser';
|
||||
import { parseMol2 } from '../mol2/parser';
|
||||
|
||||
const Mol2String = `@<TRIPOS>MOLECULE
|
||||
5816
|
||||
@@ -246,7 +246,7 @@ GASTEIGER
|
||||
|
||||
describe('mol2 reader', () => {
|
||||
it('basic', async () => {
|
||||
const parsed = await Mol2(Mol2String).run();
|
||||
const parsed = await parseMol2(Mol2String, '').run();
|
||||
if (parsed.isError) {
|
||||
throw new Error(parsed.message);
|
||||
}
|
||||
@@ -297,7 +297,7 @@ describe('mol2 reader', () => {
|
||||
});
|
||||
|
||||
it('multiblocks', async () => {
|
||||
const parsed = await Mol2(Mol2StringMultiBlocks).run();
|
||||
const parsed = await parseMol2(Mol2StringMultiBlocks, '').run();
|
||||
if (parsed.isError) {
|
||||
throw new Error(parsed.message);
|
||||
}
|
||||
@@ -348,7 +348,7 @@ describe('mol2 reader', () => {
|
||||
});
|
||||
|
||||
it('minimal', async () => {
|
||||
const parsed = await Mol2(Mol2StringMinimal).run();
|
||||
const parsed = await parseMol2(Mol2StringMinimal, '').run();
|
||||
if (parsed.isError) {
|
||||
throw new Error(parsed.message);
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ const reWhitespace = /\s+/g;
|
||||
function handleMolecule(state: State) {
|
||||
const { tokenizer, molecule } = state;
|
||||
|
||||
while (getTokenString(tokenizer) !== '@<TRIPOS>MOLECULE') {
|
||||
while (getTokenString(tokenizer) !== '@<TRIPOS>MOLECULE' && tokenizer.position < tokenizer.data.length) {
|
||||
markLine(tokenizer);
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ async function handleAtoms(state: State): Promise<Schema.Mol2Atoms> {
|
||||
let hasStatus_bit = false;
|
||||
|
||||
// skip empty lines and '@<TRIPOS>ATOM'
|
||||
while (getTokenString(tokenizer) !== '@<TRIPOS>ATOM') {
|
||||
while (getTokenString(tokenizer) !== '@<TRIPOS>ATOM' && tokenizer.position < tokenizer.data.length) {
|
||||
markLine(tokenizer);
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ async function handleBonds(state: State): Promise<Schema.Mol2Bonds> {
|
||||
const { tokenizer, molecule } = state;
|
||||
let hasStatus_bit = false;
|
||||
|
||||
while (getTokenString(tokenizer) !== '@<TRIPOS>BOND') {
|
||||
while (getTokenString(tokenizer) !== '@<TRIPOS>BOND' && tokenizer.position < tokenizer.data.length) {
|
||||
markLine(tokenizer);
|
||||
}
|
||||
|
||||
@@ -324,7 +324,7 @@ async function handleBonds(state: State): Promise<Schema.Mol2Bonds> {
|
||||
return ret;
|
||||
}
|
||||
|
||||
async function parseInternal(data: string, ctx: RuntimeContext): Promise<Result<Schema.Mol2File>> {
|
||||
async function parseInternal(ctx: RuntimeContext, data: string, name: string): Promise<Result<Schema.Mol2File>> {
|
||||
const tokenizer = Tokenizer(data);
|
||||
|
||||
ctx.update({ message: 'Parsing...', current: 0, max: data.length });
|
||||
@@ -335,16 +335,15 @@ async function parseInternal(data: string, ctx: RuntimeContext): Promise<Result<
|
||||
const atoms = await handleAtoms(state);
|
||||
const bonds = await handleBonds(state);
|
||||
structures.push({ molecule: state.molecule, atoms, bonds });
|
||||
skipWhitespace(tokenizer);
|
||||
}
|
||||
|
||||
const result: Schema.Mol2File = { structures };
|
||||
const result: Schema.Mol2File = { name, structures };
|
||||
return Result.success(result);
|
||||
}
|
||||
|
||||
export function parse(data: string) {
|
||||
export function parseMol2(data: string, name: string) {
|
||||
return Task.create<Result<Schema.Mol2File>>('Parse MOL2', async ctx => {
|
||||
return await parseInternal(data, ctx);
|
||||
return await parseInternal(ctx, data, name);
|
||||
});
|
||||
}
|
||||
|
||||
export default parse;
|
||||
}
|
||||
1
src/mol-io/reader/mol2/schema.d.ts
vendored
1
src/mol-io/reader/mol2/schema.d.ts
vendored
@@ -63,5 +63,6 @@ export interface Mol2Structure {
|
||||
}
|
||||
|
||||
export interface Mol2File {
|
||||
name: string
|
||||
structures: Mol2Structure[]
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import { Model } from '../../mol-model/structure/model';
|
||||
import { Task } from '../../mol-task';
|
||||
import { ModelFormat } from './format';
|
||||
import { ModelFormat } from '../format';
|
||||
import { Column, Table } from '../../mol-data/db';
|
||||
import { EntityBuilder } from './common/entity';
|
||||
import { File3DG } from '../../mol-io/reader/3dg/parser';
|
||||
|
||||
@@ -16,7 +16,7 @@ import { ElementSymbol } from '../../../mol-model/structure/model/types';
|
||||
import { Entities } from '../../../mol-model/structure/model/properties/common';
|
||||
import { getAtomicDerivedData } from '../../../mol-model/structure/model/properties/utils/atomic-derived';
|
||||
import { AtomSite } from './schema';
|
||||
import { ModelFormat } from '../format';
|
||||
import { ModelFormat } from '../../format';
|
||||
import { SymmetryOperator } from '../../../mol-math/geometry';
|
||||
import { MmcifFormat } from '../mmcif';
|
||||
import { AtomSiteOperatorMappingSchema } from '../../../mol-model/structure/export/categories/atom_site_operator_mapping';
|
||||
|
||||
@@ -15,7 +15,7 @@ import { getAtomicHierarchyAndConformation } from './atomic';
|
||||
import { getCoarse, EmptyCoarse, CoarseData } from './coarse';
|
||||
import { getSequence } from './sequence';
|
||||
import { sortAtomSite } from './sort';
|
||||
import { ModelFormat } from '../format';
|
||||
import { ModelFormat } from '../../format';
|
||||
import { getAtomicRanges } from '../../../mol-model/structure/model/properties/utils/atomic-ranges';
|
||||
import { AtomSite, BasicData } from './schema';
|
||||
import { getProperties } from './properties';
|
||||
|
||||
@@ -12,7 +12,7 @@ import { createModels } from './basic/parser';
|
||||
import { BasicSchema, createBasic } from './basic/schema';
|
||||
import { ComponentBuilder } from './common/component';
|
||||
import { EntityBuilder } from './common/entity';
|
||||
import { ModelFormat } from './format';
|
||||
import { ModelFormat } from '../format';
|
||||
import { CifCore_Database } from '../../mol-io/reader/cif/schema/cif-core';
|
||||
import { CifFrame, CIF } from '../../mol-io/reader/cif';
|
||||
import { Spacegroup, SpacegroupCell } from '../../mol-math/geometry';
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
import { CustomPropertyDescriptor, Model } from '../../../mol-model/structure';
|
||||
import { ModelFormat } from '../format';
|
||||
import { ModelFormat } from '../../format';
|
||||
|
||||
class FormatRegistry<T> {
|
||||
private map = new Map<ModelFormat['kind'], (model: Model) => T | undefined>()
|
||||
|
||||
@@ -12,7 +12,7 @@ import { createModels } from './basic/parser';
|
||||
import { BasicSchema, createBasic } from './basic/schema';
|
||||
import { ComponentBuilder } from './common/component';
|
||||
import { EntityBuilder } from './common/entity';
|
||||
import { ModelFormat } from './format';
|
||||
import { ModelFormat } from '../format';
|
||||
import { CubeFile } from '../../mol-io/reader/cube/parser';
|
||||
|
||||
async function getModels(cube: CubeFile, ctx: RuntimeContext): Promise<Model[]> {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
import { Model } from '../../mol-model/structure/model';
|
||||
import { Task } from '../../mol-task';
|
||||
import { ModelFormat } from './format';
|
||||
import { ModelFormat } from '../format';
|
||||
import { GroFile, GroAtoms } from '../../mol-io/reader/gro/schema';
|
||||
import { Column, Table } from '../../mol-data/db';
|
||||
import { guessElementSymbolString } from './util';
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
import { Model } from '../../mol-model/structure/model/model';
|
||||
import { Task } from '../../mol-task';
|
||||
import { ModelFormat } from './format';
|
||||
import { ModelFormat } from '../format';
|
||||
import { CifFrame, CIF } from '../../mol-io/reader/cif';
|
||||
import { mmCIF_Database } from '../../mol-io/reader/cif/schema/mmcif';
|
||||
import { createModels } from './basic/parser';
|
||||
|
||||
@@ -14,7 +14,7 @@ import { createModels } from './basic/parser';
|
||||
import { BasicSchema, createBasic } from './basic/schema';
|
||||
import { ComponentBuilder } from './common/component';
|
||||
import { EntityBuilder } from './common/entity';
|
||||
import { ModelFormat } from './format';
|
||||
import { ModelFormat } from '../format';
|
||||
import { IndexPairBonds } from './property/bonds/index-pair';
|
||||
|
||||
async function getModels(mol: MolFile, ctx: RuntimeContext): Promise<Model[]> {
|
||||
|
||||
98
src/mol-model-formats/structure/mol2.ts
Normal file
98
src/mol-model-formats/structure/mol2.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
|
||||
import { Column, Table } from '../../mol-data/db';
|
||||
import { Model } from '../../mol-model/structure/model';
|
||||
import { MoleculeType } from '../../mol-model/structure/model/types';
|
||||
import { RuntimeContext, Task } from '../../mol-task';
|
||||
import { createModels } from './basic/parser';
|
||||
import { BasicSchema, createBasic } from './basic/schema';
|
||||
import { ComponentBuilder } from './common/component';
|
||||
import { EntityBuilder } from './common/entity';
|
||||
import { ModelFormat } from '../format';
|
||||
import { IndexPairBonds } from './property/bonds/index-pair';
|
||||
import { Mol2File } from '../../mol-io/reader/mol2/schema';
|
||||
|
||||
async function getModels(mol2: Mol2File, ctx: RuntimeContext): Promise<Model[]> {
|
||||
const models: Model[] = [];
|
||||
|
||||
for (let i = 0, il = mol2.structures.length; i < il; ++i) {
|
||||
const { atoms, bonds } = mol2.structures[i];
|
||||
|
||||
const A = Column.ofConst('A', atoms.count, Column.Schema.str);
|
||||
|
||||
const atom_site = Table.ofPartialColumns(BasicSchema.atom_site, {
|
||||
auth_asym_id: A,
|
||||
auth_atom_id: Column.asArrayColumn(atoms.atom_type),
|
||||
auth_comp_id: atoms.subst_name,
|
||||
auth_seq_id: atoms.subst_id,
|
||||
Cartn_x: Column.asArrayColumn(atoms.x, Float32Array),
|
||||
Cartn_y: Column.asArrayColumn(atoms.y, Float32Array),
|
||||
Cartn_z: Column.asArrayColumn(atoms.z, Float32Array),
|
||||
id: Column.asArrayColumn(atoms.atom_id),
|
||||
|
||||
label_asym_id: A,
|
||||
label_atom_id: Column.asArrayColumn(atoms.atom_type),
|
||||
label_comp_id: atoms.subst_name,
|
||||
label_seq_id: atoms.subst_id,
|
||||
label_entity_id: Column.ofConst('1', atoms.count, Column.Schema.str),
|
||||
|
||||
occupancy: Column.ofConst(1, atoms.count, Column.Schema.float),
|
||||
type_symbol: Column.asArrayColumn(atoms.atom_name),
|
||||
|
||||
pdbx_PDB_model_num: Column.ofConst(i, atoms.count, Column.Schema.int),
|
||||
}, atoms.count);
|
||||
|
||||
const entityBuilder = new EntityBuilder();
|
||||
entityBuilder.setNames([['MOL', 'Unknown Entity']]);
|
||||
entityBuilder.getEntityId('MOL', MoleculeType.Unknown, 'A');
|
||||
|
||||
const componentBuilder = new ComponentBuilder(atoms.subst_id, atoms.atom_name);
|
||||
for (let i = 0, il = atoms.subst_name.rowCount; i < il; ++i) {
|
||||
componentBuilder.add(atoms.subst_name.value(i), i);
|
||||
}
|
||||
|
||||
const basics = createBasic({
|
||||
entity: entityBuilder.getEntityTable(),
|
||||
chem_comp: componentBuilder.getChemCompTable(),
|
||||
atom_site
|
||||
});
|
||||
|
||||
const _models = await createModels(basics, Mol2Format.create(mol2), ctx);
|
||||
|
||||
if (_models.length > 0) {
|
||||
const indexA = Column.ofIntArray(Column.mapToArray(bonds.origin_atom_id, x => x - 1, Int32Array));
|
||||
const indexB = Column.ofIntArray(Column.mapToArray(bonds.target_atom_id, x => x - 1, Int32Array));
|
||||
const order = Column.ofIntArray(Column.mapToArray(bonds.bond_type, x => x === 'ar' ? 1 : parseInt(x), Int8Array));
|
||||
const pairBonds = IndexPairBonds.fromData({ pairs: { indexA, indexB, order }, count: bonds.count });
|
||||
IndexPairBonds.Provider.set(_models[0], pairBonds);
|
||||
|
||||
models.push(_models[0]);
|
||||
}
|
||||
}
|
||||
|
||||
return models;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
export { Mol2Format };
|
||||
|
||||
type Mol2Format = ModelFormat<Mol2File>
|
||||
|
||||
namespace Mol2Format {
|
||||
export function is(x: ModelFormat): x is Mol2Format {
|
||||
return x.kind === 'mol2';
|
||||
}
|
||||
|
||||
export function create(mol2: Mol2File): Mol2Format {
|
||||
return { kind: 'mol2', name: mol2.name, data: mol2 };
|
||||
}
|
||||
}
|
||||
|
||||
export function trajectoryFromMol2(mol2: Mol2File): Task<Model.Trajectory> {
|
||||
return Task.create('Parse MOL2', ctx => getModels(mol2, ctx));
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import { guessElementSymbolString } from './util';
|
||||
import { MoleculeType, getMoleculeType } from '../../mol-model/structure/model/types';
|
||||
import { getChainId } from './common/util';
|
||||
import { Task } from '../../mol-task';
|
||||
import { ModelFormat } from './format';
|
||||
import { ModelFormat } from '../format';
|
||||
import { Topology } from '../../mol-model/structure/topology/topology';
|
||||
import { createBasic, BasicSchema } from './basic/schema';
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import { degToRad } from '../../mol-math/misc';
|
||||
import { getCcp4ValueType } from '../../mol-io/reader/ccp4/parser';
|
||||
import { TypedArrayValueType } from '../../mol-io/common/typed-array';
|
||||
import { arrayMin, arrayRms, arrayMean, arrayMax } from '../../mol-util/array';
|
||||
import { ModelFormat } from '../format';
|
||||
|
||||
/** When available (e.g. in MRC files) use ORIGIN records instead of N[CRS]START */
|
||||
export function getCcp4Origin(header: Ccp4Header): Vec3 {
|
||||
@@ -75,7 +76,24 @@ export function volumeFromCcp4(source: Ccp4File, params?: { voxelSize?: Vec3, of
|
||||
max: isNaN(header.AMAX) ? arrayMax(values) : header.AMAX,
|
||||
mean: isNaN(header.AMEAN) ? arrayMean(values) : header.AMEAN,
|
||||
sigma: (isNaN(header.ARMS) || header.ARMS === 0) ? arrayRms(values) : header.ARMS
|
||||
}
|
||||
},
|
||||
sourceData: Ccp4Format.create(source)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
export { Ccp4Format };
|
||||
|
||||
type Ccp4Format = ModelFormat<Ccp4File>
|
||||
|
||||
namespace Ccp4Format {
|
||||
export function is(x: ModelFormat): x is Ccp4Format {
|
||||
return x.kind === 'ccp4';
|
||||
}
|
||||
|
||||
export function create(ccp4: Ccp4File): Ccp4Format {
|
||||
return { kind: 'ccp4', name: ccp4.name, data: ccp4 };
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import { Mat4, Tensor } from '../../mol-math/linear-algebra';
|
||||
import { VolumeData } from '../../mol-model/volume/data';
|
||||
import { Task } from '../../mol-task';
|
||||
import { arrayMax, arrayMean, arrayMin, arrayRms } from '../../mol-util/array';
|
||||
import { ModelFormat } from '../format';
|
||||
|
||||
export function volumeFromCube(source: CubeFile, params?: { dataIndex?: number, label?: string }): Task<VolumeData> {
|
||||
return Task.create<VolumeData>('Create Volume Data', async () => {
|
||||
@@ -51,7 +52,24 @@ export function volumeFromCube(source: CubeFile, params?: { dataIndex?: number,
|
||||
max: arrayMax(values),
|
||||
mean: arrayMean(values),
|
||||
sigma: arrayRms(values)
|
||||
}
|
||||
},
|
||||
sourceData: CubeFormat.create(source)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
export { CubeFormat };
|
||||
|
||||
type CubeFormat = ModelFormat<CubeFile>
|
||||
|
||||
namespace CubeFormat {
|
||||
export function is(x: ModelFormat): x is CubeFormat {
|
||||
return x.kind === 'cube';
|
||||
}
|
||||
|
||||
export function create(cube: CubeFile): CubeFormat {
|
||||
return { kind: 'cube', name: cube.name, data: cube };
|
||||
}
|
||||
}
|
||||
@@ -9,8 +9,9 @@ import { VolumeData } from '../../mol-model/volume/data';
|
||||
import { Task } from '../../mol-task';
|
||||
import { SpacegroupCell, Box3D } from '../../mol-math/geometry';
|
||||
import { Tensor, Vec3 } from '../../mol-math/linear-algebra';
|
||||
import { ModelFormat } from '../format';
|
||||
|
||||
function volumeFromDensityServerData(source: DensityServer_Data_Database): Task<VolumeData> {
|
||||
export function volumeFromDensityServerData(source: DensityServer_Data_Database): Task<VolumeData> {
|
||||
return Task.create<VolumeData>('Create Volume Data', async ctx => {
|
||||
const { volume_data_3d_info: info, volume_data_3d: values } = source;
|
||||
const cell = SpacegroupCell.create(
|
||||
@@ -41,9 +42,24 @@ function volumeFromDensityServerData(source: DensityServer_Data_Database): Task<
|
||||
max: info.max_sampled.value(0),
|
||||
mean: info.mean_sampled.value(0),
|
||||
sigma: info.sigma_sampled.value(0)
|
||||
}
|
||||
},
|
||||
sourceData: DscifFormat.create(source)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export { volumeFromDensityServerData };
|
||||
//
|
||||
|
||||
export { DscifFormat };
|
||||
|
||||
type DscifFormat = ModelFormat<DensityServer_Data_Database>
|
||||
|
||||
namespace DscifFormat {
|
||||
export function is(x: ModelFormat): x is DscifFormat {
|
||||
return x.kind === 'dscif';
|
||||
}
|
||||
|
||||
export function create(dscif: DensityServer_Data_Database): DscifFormat {
|
||||
return { kind: 'dscif', name: dscif._name, data: dscif };
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,9 @@ import { Tensor, Vec3 } from '../../mol-math/linear-algebra';
|
||||
import { degToRad } from '../../mol-math/misc';
|
||||
import { Dsn6File } from '../../mol-io/reader/dsn6/schema';
|
||||
import { arrayMin, arrayMax, arrayMean, arrayRms } from '../../mol-util/array';
|
||||
import { ModelFormat } from '../format';
|
||||
|
||||
function volumeFromDsn6(source: Dsn6File, params?: { voxelSize?: Vec3, label?: string }): Task<VolumeData> {
|
||||
export function volumeFromDsn6(source: Dsn6File, params?: { voxelSize?: Vec3, label?: string }): Task<VolumeData> {
|
||||
return Task.create<VolumeData>('Create Volume Data', async ctx => {
|
||||
const { header, values } = source;
|
||||
const size = Vec3.create(header.xlen, header.ylen, header.zlen);
|
||||
@@ -40,9 +41,24 @@ function volumeFromDsn6(source: Dsn6File, params?: { voxelSize?: Vec3, label?: s
|
||||
max: arrayMax(values),
|
||||
mean: arrayMean(values),
|
||||
sigma: header.sigma !== undefined ? header.sigma : arrayRms(values)
|
||||
}
|
||||
},
|
||||
sourceData: Dsn6Format.create(source)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export { volumeFromDsn6 };
|
||||
//
|
||||
|
||||
export { Dsn6Format };
|
||||
|
||||
type Dsn6Format = ModelFormat<Dsn6File>
|
||||
|
||||
namespace Dsn6Format {
|
||||
export function is(x: ModelFormat): x is Dsn6Format {
|
||||
return x.kind === 'dsn6';
|
||||
}
|
||||
|
||||
export function create(dsn6: Dsn6File): Dsn6Format {
|
||||
return { kind: 'dsn6', name: dsn6.name, data: dsn6 };
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import { Mat4, Tensor } from '../../mol-math/linear-algebra';
|
||||
import { VolumeData } from '../../mol-model/volume/data';
|
||||
import { Task } from '../../mol-task';
|
||||
import { arrayMax, arrayMean, arrayMin, arrayRms } from '../../mol-util/array';
|
||||
import { ModelFormat } from '../format';
|
||||
|
||||
export function volumeFromDx(source: DxFile, params?: { label?: string }): Task<VolumeData> {
|
||||
return Task.create<VolumeData>('Create Volume Data', async () => {
|
||||
@@ -28,7 +29,24 @@ export function volumeFromDx(source: DxFile, params?: { label?: string }): Task<
|
||||
max: arrayMax(values),
|
||||
mean: arrayMean(values),
|
||||
sigma: arrayRms(values)
|
||||
}
|
||||
},
|
||||
sourceData: DxFormat.create(source)
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
export { DxFormat };
|
||||
|
||||
type DxFormat = ModelFormat<DxFile>
|
||||
|
||||
namespace DxFormat {
|
||||
export function is(x: ModelFormat): x is DxFormat {
|
||||
return x.kind === 'dx';
|
||||
}
|
||||
|
||||
export function create(dx: DxFile): DxFormat {
|
||||
return { kind: 'dx', name: dx.name, data: dx };
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import { CoarseHierarchy, CoarseConformation } from './properties/coarse';
|
||||
import { Entities, ChemicalComponentMap, MissingResidues, StructAsymMap } from './properties/common';
|
||||
import { CustomProperties } from '../common/custom-property';
|
||||
import { SaccharideComponentMap } from '../structure/carbohydrates/constants';
|
||||
import { ModelFormat } from '../../../mol-model-formats/structure/format';
|
||||
import { ModelFormat } from '../../../mol-model-formats/format';
|
||||
import { calcModelCenter } from './util';
|
||||
import { Vec3 } from '../../../mol-math/linear-algebra';
|
||||
import { Mutable } from '../../../mol-util/type-helpers';
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import { UUID } from '../../../mol-util';
|
||||
import { Column } from '../../../mol-data/db';
|
||||
import { BasicData } from '../../../mol-model-formats/structure/basic/schema';
|
||||
import { ModelFormat } from '../../../mol-model-formats/structure/format';
|
||||
import { ModelFormat } from '../../../mol-model-formats/format';
|
||||
|
||||
export { Topology };
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import { SpacegroupCell, Box3D } from '../../mol-math/geometry';
|
||||
import { Tensor, Mat4, Vec3 } from '../../mol-math/linear-algebra';
|
||||
import { equalEps } from '../../mol-math/linear-algebra/3d/common';
|
||||
import { ModelFormat } from '../../mol-model-formats/format';
|
||||
|
||||
/** The basic unit cell that contains the data. */
|
||||
interface VolumeDataBase {
|
||||
@@ -20,6 +21,7 @@ interface VolumeDataBase {
|
||||
mean: number,
|
||||
sigma: number
|
||||
}>
|
||||
readonly sourceData: ModelFormat,
|
||||
}
|
||||
|
||||
interface VolumeData extends VolumeDataBase {
|
||||
@@ -30,7 +32,8 @@ namespace VolumeData {
|
||||
export const One: VolumeData = {
|
||||
transform: { kind: 'matrix', matrix: Mat4.identity() },
|
||||
data: Tensor.create(Tensor.Space([1, 1, 1], [0, 1, 2]), Tensor.Data1([0])),
|
||||
dataStats: { min: 0, max: 0, mean: 0, sigma: 0 }
|
||||
dataStats: { min: 0, max: 0, mean: 0, sigma: 0 },
|
||||
sourceData: { kind: '', data: '', name: '' }
|
||||
};
|
||||
|
||||
const _scale = Mat4.zero(), _translate = Mat4.zero();
|
||||
|
||||
@@ -9,10 +9,16 @@ import { OrderedSet } from '../../mol-data/int';
|
||||
import { Sphere3D } from '../../mol-math/geometry';
|
||||
import { Vec3, Mat4 } from '../../mol-math/linear-algebra';
|
||||
import { BoundaryHelper } from '../../mol-math/geometry/boundary-helper';
|
||||
import { CubeFormat } from '../../mol-model-formats/volume/cube';
|
||||
|
||||
export namespace Volume {
|
||||
export type CellIndex = { readonly '@type': 'cell-index' } & number
|
||||
|
||||
export function isOrbitals(volume: VolumeData) {
|
||||
if (!CubeFormat.is(volume.sourceData)) return false;
|
||||
return volume.sourceData.data.header.orbitals;
|
||||
}
|
||||
|
||||
export interface Loci { readonly kind: 'volume-loci', readonly volume: VolumeData }
|
||||
export function Loci(volume: VolumeData): Loci { return { kind: 'volume-loci', volume }; }
|
||||
export function isLoci(x: any): x is Loci { return !!x && x.kind === 'volume-loci'; }
|
||||
|
||||
@@ -237,7 +237,13 @@ const atomicDetail = StructureRepresentationPresetProvider({
|
||||
|
||||
const components = {
|
||||
all: await presetStaticComponent(plugin, structureCell, 'all'),
|
||||
branched: undefined
|
||||
};
|
||||
if (params.showCarbohydrateSymbol) {
|
||||
Object.assign(components, {
|
||||
branched: await presetStaticComponent(plugin, structureCell, 'branched', { label: 'Carbohydrate' }),
|
||||
});
|
||||
}
|
||||
|
||||
const { update, builder, typeParams, color } = reprBuilder(plugin, params);
|
||||
const representations = {
|
||||
@@ -245,7 +251,7 @@ const atomicDetail = StructureRepresentationPresetProvider({
|
||||
};
|
||||
if (params.showCarbohydrateSymbol) {
|
||||
Object.assign(representations, {
|
||||
snfg3d: builder.buildRepresentation(update, components.all, { type: 'carbohydrate', typeParams: { ...typeParams, alpha: 0.4, visuals: ['carbohydrate-symbol'] }, color }, { tag: 'snfg-3d' }),
|
||||
snfg3d: builder.buildRepresentation(update, components.branched, { type: 'carbohydrate', typeParams: { ...typeParams, alpha: 0.4, visuals: ['carbohydrate-symbol'] }, color }, { tag: 'snfg-3d' }),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -114,14 +114,22 @@ export const Provider3dg: TrajectoryFormatProvider = {
|
||||
};
|
||||
|
||||
export const MolProvider: TrajectoryFormatProvider = {
|
||||
label: 'MOL',
|
||||
description: 'MOL',
|
||||
label: 'MOL/SDF',
|
||||
description: 'MOL/SDF',
|
||||
category: Category,
|
||||
stringExtensions: ['mol', 'sdf'],
|
||||
stringExtensions: ['mol', 'sdf', 'sd'],
|
||||
parse: directTrajectory(StateTransforms.Model.TrajectoryFromMOL),
|
||||
visuals: defaultVisuals
|
||||
};
|
||||
|
||||
export const Mol2Provider: TrajectoryFormatProvider = {
|
||||
label: 'MOL2',
|
||||
description: 'MOL2',
|
||||
category: Category,
|
||||
stringExtensions: ['mol2'],
|
||||
parse: directTrajectory(StateTransforms.Model.TrajectoryFromMOL2),
|
||||
visuals: defaultVisuals
|
||||
};
|
||||
|
||||
export const BuiltInTrajectoryFormats = [
|
||||
['mmcif', MmcifProvider] as const,
|
||||
@@ -129,7 +137,8 @@ export const BuiltInTrajectoryFormats = [
|
||||
['pdb', PdbProvider] as const,
|
||||
['gro', GroProvider] as const,
|
||||
['3dg', Provider3dg] as const,
|
||||
['mol', MolProvider] as const
|
||||
['mol', MolProvider] as const,
|
||||
['mol2', Mol2Provider] as const,
|
||||
] as const;
|
||||
|
||||
export type BuiltInTrajectoryFormat = (typeof BuiltInTrajectoryFormats)[number][0]
|
||||
@@ -15,6 +15,7 @@ import { ColorNames } from '../../mol-util/color/names';
|
||||
import { VolumeIsoValue } from '../../mol-model/volume';
|
||||
import { createVolumeRepresentationParams } from '../helpers/volume-representation-params';
|
||||
import { objectForEach } from '../../mol-util/object';
|
||||
import { Volume } from '../../mol-model/volume/volume';
|
||||
|
||||
const Category = 'Volume';
|
||||
|
||||
@@ -104,30 +105,41 @@ export const CubeProvider = DataFormatProvider({
|
||||
visuals: async (plugin: PluginContext, data: { volume: StateObjectSelector<PluginStateObject.Volume.Data>, structure: StateObjectSelector<PluginStateObject.Molecule.Structure> }) => {
|
||||
const surfaces = plugin.build();
|
||||
|
||||
const volumeReprs: StateObjectSelector<PluginStateObject.Volume.Representation3D>[] = [];
|
||||
const volumeData = data.volume.cell?.obj?.data;
|
||||
const volumePos = surfaces.to(data.volume).apply(StateTransforms.Representation.VolumeRepresentation3D, createVolumeRepresentationParams(plugin, volumeData, {
|
||||
type: 'isosurface',
|
||||
typeParams: { isoValue: VolumeIsoValue.relative(1), alpha: 0.4 },
|
||||
color: 'uniform',
|
||||
colorParams: { value: ColorNames.blue }
|
||||
}));
|
||||
const volumeNeg = surfaces.to(data.volume).apply(StateTransforms.Representation.VolumeRepresentation3D, createVolumeRepresentationParams(plugin, volumeData, {
|
||||
type: 'isosurface',
|
||||
typeParams: { isoValue: VolumeIsoValue.relative(-1), alpha: 0.4 },
|
||||
color: 'uniform',
|
||||
colorParams: { value: ColorNames.red }
|
||||
}));
|
||||
if (volumeData && Volume.isOrbitals(volumeData)) {
|
||||
const volumePos = surfaces.to(data.volume).apply(StateTransforms.Representation.VolumeRepresentation3D, createVolumeRepresentationParams(plugin, volumeData, {
|
||||
type: 'isosurface',
|
||||
typeParams: { isoValue: VolumeIsoValue.relative(1), alpha: 0.4 },
|
||||
color: 'uniform',
|
||||
colorParams: { value: ColorNames.blue }
|
||||
}));
|
||||
const volumeNeg = surfaces.to(data.volume).apply(StateTransforms.Representation.VolumeRepresentation3D, createVolumeRepresentationParams(plugin, volumeData, {
|
||||
type: 'isosurface',
|
||||
typeParams: { isoValue: VolumeIsoValue.relative(-1), alpha: 0.4 },
|
||||
color: 'uniform',
|
||||
colorParams: { value: ColorNames.red }
|
||||
}));
|
||||
volumeReprs.push(volumePos.selector, volumeNeg.selector);
|
||||
} else {
|
||||
const volume = surfaces.to(data.volume).apply(StateTransforms.Representation.VolumeRepresentation3D, createVolumeRepresentationParams(plugin, volumeData, {
|
||||
type: 'isosurface',
|
||||
typeParams: { isoValue: VolumeIsoValue.relative(2), alpha: 0.4 },
|
||||
color: 'uniform',
|
||||
colorParams: { value: ColorNames.grey }
|
||||
}));
|
||||
volumeReprs.push(volume.selector);
|
||||
}
|
||||
|
||||
const structure = await plugin.builders.structure.representation.applyPreset(data.structure, 'auto');
|
||||
await surfaces.commit();
|
||||
|
||||
const structureReprs: StateObjectSelector<PluginStateObject.Molecule.Structure.Representation3D>[] = [];
|
||||
|
||||
objectForEach(structure?.representations as any, (r: any) => {
|
||||
if (r) structureReprs.push(r);
|
||||
});
|
||||
|
||||
return [volumePos.selector, volumeNeg.selector, ...structureReprs];
|
||||
return [...volumeReprs, ...structureReprs];
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -394,63 +394,68 @@ const wholeResidues = StructureSelectionQuery('Whole Residues of Selection', MS.
|
||||
});
|
||||
|
||||
const StandardAminoAcids = [
|
||||
[['HIS'], 'HISTIDINE'],
|
||||
[['ARG'], 'ARGININE'],
|
||||
[['LYS'], 'LYSINE'],
|
||||
[['ILE'], 'ISOLEUCINE'],
|
||||
[['PHE'], 'PHENYLALANINE'],
|
||||
[['LEU'], 'LEUCINE'],
|
||||
[['TRP'], 'TRYPTOPHAN'],
|
||||
[['ALA'], 'ALANINE'],
|
||||
[['MET'], 'METHIONINE'],
|
||||
[['PRO'], 'PROLINE'],
|
||||
[['CYS'], 'CYSTEINE'],
|
||||
[['ASN'], 'ASPARAGINE'],
|
||||
[['VAL'], 'VALINE'],
|
||||
[['GLY'], 'GLYCINE'],
|
||||
[['SER'], 'SERINE'],
|
||||
[['GLN'], 'GLUTAMINE'],
|
||||
[['TYR'], 'TYROSINE'],
|
||||
[['ASP'], 'ASPARTIC ACID'],
|
||||
[['GLU'], 'GLUTAMIC ACID'],
|
||||
[['THR'], 'THREONINE'],
|
||||
[['SEC'], 'SELENOCYSTEINE'],
|
||||
[['PYL'], 'PYRROLYSINE'],
|
||||
[['UNK'], 'UNKNOWN'],
|
||||
[['HIS'], 'Histidine'],
|
||||
[['ARG'], 'Arginine'],
|
||||
[['LYS'], 'Lysine'],
|
||||
[['ILE'], 'Isoleucine'],
|
||||
[['PHE'], 'Phenylalanine'],
|
||||
[['LEU'], 'Leucine'],
|
||||
[['TRP'], 'Tryptophan'],
|
||||
[['ALA'], 'Alanine'],
|
||||
[['MET'], 'Methionine'],
|
||||
[['PRO'], 'Proline'],
|
||||
[['CYS'], 'Cysteine'],
|
||||
[['ASN'], 'Asparagine'],
|
||||
[['VAL'], 'Valine'],
|
||||
[['GLY'], 'Glycine'],
|
||||
[['SER'], 'Serine'],
|
||||
[['GLN'], 'Glutamine'],
|
||||
[['TYR'], 'Tyrosine'],
|
||||
[['ASP'], 'Aspartic Acid'],
|
||||
[['GLU'], 'Glutamic Acid'],
|
||||
[['THR'], 'Threonine'],
|
||||
[['SEC'], 'Selenocysteine'],
|
||||
[['PYL'], 'Pyrrolysine'],
|
||||
[['UNK'], 'Unknown'],
|
||||
].sort((a, b) => a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : 0) as [string[], string][];
|
||||
|
||||
const StandardNucleicBases = [
|
||||
[['A', 'DA'], 'ADENOSINE'],
|
||||
[['C', 'DC'], 'CYTIDINE'],
|
||||
[['T', 'DT'], 'THYMIDINE'],
|
||||
[['G', 'DG'], 'GUANOSINE'],
|
||||
[['I', 'DI'], 'INOSINE'],
|
||||
[['U', 'DU'], 'URIDINE'],
|
||||
[['N', 'DN'], 'UNKNOWN'],
|
||||
[['A', 'DA'], 'Adenosine'],
|
||||
[['C', 'DC'], 'Cytidine'],
|
||||
[['T', 'DT'], 'Thymidine'],
|
||||
[['G', 'DG'], 'Guanosine'],
|
||||
[['I', 'DI'], 'Inosine'],
|
||||
[['U', 'DU'], 'Uridine'],
|
||||
[['N', 'DN'], 'Unknown'],
|
||||
].sort((a, b) => a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : 0) as [string[], string][];
|
||||
|
||||
export function ResidueQuery([names, label]: [string[], string], category: string, priority = 0) {
|
||||
return StructureSelectionQuery(`${label} (${names.join(', ')})`, MS.struct.modifier.union([
|
||||
const description = names.length === 1 && !StandardResidues.has(names[0])
|
||||
? `[${names[0]}] ${label}`
|
||||
: `${label} (${names.join(', ')})`;
|
||||
return StructureSelectionQuery(description, MS.struct.modifier.union([
|
||||
MS.struct.generator.atomGroups({
|
||||
'residue-test': MS.core.set.has([MS.set(...names), MS.ammp('auth_comp_id')])
|
||||
})
|
||||
]), { category, priority, description: label });
|
||||
]), { category, priority, description });
|
||||
}
|
||||
|
||||
export function ElementSymbolQuery([names, label]: [string[], string], category: string, priority: number) {
|
||||
return StructureSelectionQuery(`${label} (${names.join(', ')})`, MS.struct.modifier.union([
|
||||
const description = `${label} (${names.join(', ')})`;
|
||||
return StructureSelectionQuery(description, MS.struct.modifier.union([
|
||||
MS.struct.generator.atomGroups({
|
||||
'atom-test': MS.core.set.has([MS.set(...names), MS.acp('elementSymbol')])
|
||||
})
|
||||
]), { category, priority });
|
||||
]), { category, priority, description });
|
||||
}
|
||||
|
||||
export function EntityDescriptionQuery([description, label]: [string[], string], category: string, priority: number) {
|
||||
export function EntityDescriptionQuery([names, label]: [string[], string], category: string, priority: number) {
|
||||
const description = `${label}`;
|
||||
return StructureSelectionQuery(`${label}`, MS.struct.modifier.union([
|
||||
MS.struct.generator.atomGroups({
|
||||
'entity-test': MS.core.list.equal([MS.list(...description), MS.ammp('entityDescription')])
|
||||
'entity-test': MS.core.list.equal([MS.list(...names), MS.ammp('entityDescription')])
|
||||
})
|
||||
]), { category, priority, description: description.join(', ') });
|
||||
]), { category, priority, description });
|
||||
}
|
||||
|
||||
const StandardResidues = SetUtils.unionMany(
|
||||
|
||||
@@ -132,7 +132,7 @@ class PluginStateSnapshotManager extends StatefulPluginComponent<{
|
||||
async setStateSnapshot(snapshot: PluginStateSnapshotManager.StateSnapshot): Promise<PluginState.Snapshot | undefined> {
|
||||
if (snapshot.version !== PLUGIN_VERSION) {
|
||||
// TODO
|
||||
console.warn('state snapshot version mismatch');
|
||||
// console.warn('state snapshot version mismatch');
|
||||
}
|
||||
|
||||
this.clear();
|
||||
|
||||
@@ -35,6 +35,8 @@ import { parseMol } from '../../mol-io/reader/mol/parser';
|
||||
import { trajectoryFromMol } from '../../mol-model-formats/structure/mol';
|
||||
import { trajectoryFromCifCore } from '../../mol-model-formats/structure/cif-core';
|
||||
import { trajectoryFromCube } from '../../mol-model-formats/structure/cube';
|
||||
import { parseMol2 } from '../../mol-io/reader/mol2/parser';
|
||||
import { trajectoryFromMol2 } from '../../mol-model-formats/structure/mol2';
|
||||
|
||||
export { CoordinatesFromDcd };
|
||||
export { TopologyFromPsf };
|
||||
@@ -44,6 +46,7 @@ export { TrajectoryFromMmCif };
|
||||
export { TrajectoryFromPDB };
|
||||
export { TrajectoryFromGRO };
|
||||
export { TrajectoryFromMOL };
|
||||
export { TrajectoryFromMOL2 };
|
||||
export { TrajectoryFromCube };
|
||||
export { TrajectoryFromCifCore };
|
||||
export { TrajectoryFrom3DG };
|
||||
@@ -235,6 +238,24 @@ const TrajectoryFromMOL = PluginStateTransform.BuiltIn({
|
||||
}
|
||||
});
|
||||
|
||||
type TrajectoryFromMOL2 = typeof TrajectoryFromMOL
|
||||
const TrajectoryFromMOL2 = PluginStateTransform.BuiltIn({
|
||||
name: 'trajectory-from-mol2',
|
||||
display: { name: 'Parse MOL2', description: 'Parse MOL2 string and create trajectory.' },
|
||||
from: [SO.Data.String],
|
||||
to: SO.Molecule.Trajectory
|
||||
})({
|
||||
apply({ a }) {
|
||||
return Task.create('Parse MOL2', async ctx => {
|
||||
const parsed = await parseMol2(a.data, a.label).runInContext(ctx);
|
||||
if (parsed.isError) throw new Error(parsed.message);
|
||||
const models = await trajectoryFromMol2(parsed.result).runInContext(ctx);
|
||||
const props = { label: `${models[0].entry}`, description: `${models.length} model${models.length === 1 ? '' : 's'}` };
|
||||
return new SO.Molecule.Trajectory(models, props);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
type TrajectoryFromCube = typeof TrajectoryFromCube
|
||||
const TrajectoryFromCube = PluginStateTransform.BuiltIn({
|
||||
name: 'trajectory-from-cube',
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -130,14 +130,7 @@ export class ViewportControls extends PluginUIComponent<ViewportControlsProps, V
|
||||
}
|
||||
|
||||
export const Logo = () =>
|
||||
<div className='msp-logo'>
|
||||
<div>
|
||||
<div>
|
||||
<div />
|
||||
<div className='msp-logo-image' />
|
||||
</div>
|
||||
</div>
|
||||
</div>;
|
||||
<a className='msp-logo' href='https://molstar.org' target='_blank' />;
|
||||
|
||||
interface ViewportState {
|
||||
noWebGl: boolean
|
||||
|
||||
@@ -148,7 +148,7 @@ function createElementText(ctx: VisualContext, structure: Structure, theme: Them
|
||||
const { label_atom_id, label_alt_id } = StructureProperties.atom;
|
||||
const { cumulativeUnitElementCount } = serialMapping;
|
||||
|
||||
const sizeTheme = PhysicalSizeTheme({}, {});
|
||||
const sizeTheme = PhysicalSizeTheme({}, { scale: 1 });
|
||||
|
||||
const count = structure.elementCount;
|
||||
const { elementScale } = props;
|
||||
|
||||
@@ -175,7 +175,7 @@ export function getUnitConformationAndRadius(structure: Structure, unit: Unit, p
|
||||
const boundary = unit === rootUnit ? unit.boundary : getBoundary(position);
|
||||
|
||||
const l = StructureElement.Location.create(structure, rootUnit);
|
||||
const sizeTheme = PhysicalSizeTheme({}, {});
|
||||
const sizeTheme = PhysicalSizeTheme({}, { scale: 1 });
|
||||
const radius = (index: number) => {
|
||||
l.element = index as ElementIndex;
|
||||
return sizeTheme.size(l);
|
||||
@@ -186,7 +186,7 @@ export function getUnitConformationAndRadius(structure: Structure, unit: Unit, p
|
||||
|
||||
export function getStructureConformationAndRadius(structure: Structure, ignoreHydrogens: boolean, traceOnly: boolean) {
|
||||
const l = StructureElement.Location.create(structure);
|
||||
const sizeTheme = PhysicalSizeTheme({}, {});
|
||||
const sizeTheme = PhysicalSizeTheme({}, { scale: 1 });
|
||||
|
||||
let xs: ArrayLike<number>;
|
||||
let ys: ArrayLike<number>;
|
||||
|
||||
@@ -173,7 +173,7 @@ export function _bundleLabel(bundle: Loci.Bundle<any>, options: LabelOptions) {
|
||||
}
|
||||
|
||||
let offset = 0;
|
||||
for (let i = 0, il = Math.min(...labels.map(l => l.length)); i < il; ++i) {
|
||||
for (let i = 0, il = Math.min(...labels.map(l => l.length)) - 1; i < il; ++i) {
|
||||
let areIdentical = true;
|
||||
for (let j = 1, jl = labels.length; j < jl; ++j) {
|
||||
if (labels[0][i] !== labels[j][i]) {
|
||||
|
||||
@@ -14,7 +14,9 @@ import { ThemeDataContext } from '../../mol-theme/theme';
|
||||
const DefaultSize = 1;
|
||||
const Description = 'Assigns a physical size, i.e. vdW radius for atoms or given radius for coarse spheres.';
|
||||
|
||||
export const PhysicalSizeThemeParams = {};
|
||||
export const PhysicalSizeThemeParams = {
|
||||
scale: PD.Numeric(1, { min: 0.1, max: 5, step: 0.1 })
|
||||
};
|
||||
export type PhysicalSizeThemeParams = typeof PhysicalSizeThemeParams
|
||||
export function getPhysicalSizeThemeParams(ctx: ThemeDataContext) {
|
||||
return PhysicalSizeThemeParams; // TODO return copy
|
||||
@@ -35,14 +37,16 @@ export function getPhysicalRadius(unit: Unit, element: ElementIndex): number {
|
||||
* i.e. vdw for atoms and radius for coarse spheres
|
||||
*/
|
||||
export function PhysicalSizeTheme(ctx: ThemeDataContext, props: PD.Values<PhysicalSizeThemeParams>): SizeTheme<PhysicalSizeThemeParams> {
|
||||
const scale = props.scale === void 0 ? 1 : props.scale;
|
||||
|
||||
function size(location: Location): number {
|
||||
let size: number;
|
||||
if (StructureElement.Location.is(location)) {
|
||||
size = getPhysicalRadius(location.unit, location.element);
|
||||
size = scale * getPhysicalRadius(location.unit, location.element);
|
||||
} else if (Bond.isLocation(location)) {
|
||||
size = getPhysicalRadius(location.aUnit, location.aUnit.elements[location.aIndex]);
|
||||
size = scale * getPhysicalRadius(location.aUnit, location.aUnit.elements[location.aIndex]);
|
||||
} else {
|
||||
size = DefaultSize;
|
||||
size = scale * DefaultSize;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@@ -241,9 +241,8 @@ function processAjax<T extends DataType>(req: XMLHttpRequest, type: T): DataResp
|
||||
}
|
||||
throw new Error(`could not get requested response data '${type}'`);
|
||||
} else {
|
||||
const status = req.statusText;
|
||||
RequestPool.deposit(req);
|
||||
throw new Error(status);
|
||||
throw new Error(`Download failed with status code ${req.status}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -271,7 +271,7 @@ export namespace ParamDefinition {
|
||||
getLabel(t: T): string
|
||||
}
|
||||
export function ObjectList<T>(element: For<T>, getLabel: (e: T) => string, info?: Info & { defaultValue?: T[], ctor?: () => T }): ObjectList<Normalize<T>> {
|
||||
return setInfo<ObjectList<Normalize<T>>>({ type: 'object-list', element: element as any as Params, getLabel, ctor: _defaultObjectListCtor, defaultValue: (info?.defaultValue) || [] }, info);
|
||||
return setInfo<ObjectList<Normalize<T>>>({ type: 'object-list', element: element as any as Params, getLabel, ctor: _defaultObjectListCtor, defaultValue: (info?.defaultValue) || [] }, info);
|
||||
}
|
||||
function _defaultObjectListCtor(this: ObjectList) { return getDefaultValues(this.element) as any; }
|
||||
|
||||
@@ -316,7 +316,7 @@ export namespace ParamDefinition {
|
||||
export type ValuesFor<T extends For<any>> = Normalize<{ [k in keyof T]: T[k]['defaultValue'] }>
|
||||
|
||||
type Optionals<P> = { [K in keyof P]-?: undefined extends P[K] ? K : never }[keyof P]
|
||||
type NonOptionals<P> = { [K in keyof P]-?: undefined extends P[K] ? never: K }[keyof P]
|
||||
type NonOptionals<P> = { [K in keyof P]-?: undefined extends P[K] ? never : K }[keyof P]
|
||||
export type Normalize<P> = Pick<P, NonOptionals<P>> & Partial<Pick<P, Optionals<P>>>
|
||||
export type For<P> = { [K in keyof P]-?: Base<P[K]> }
|
||||
export type Def<P> = { [K in keyof P]: Any }
|
||||
@@ -435,8 +435,8 @@ export namespace ParamDefinition {
|
||||
}
|
||||
|
||||
export function mergeParam(p: Any, a: any, b: any): any {
|
||||
if (a === undefined) return typeof b === 'object' ? { ...b } : b;
|
||||
if (b === undefined) return typeof a === 'object' ? { ...a } : a;
|
||||
if (a === undefined) return typeof b === 'object' && !Array.isArray(b) ? { ...b } : b;
|
||||
if (b === undefined) return typeof a === 'object' && !Array.isArray(a) ? { ...a } : a;
|
||||
|
||||
if (p.type === 'group') {
|
||||
return merge(p.params, a, b);
|
||||
@@ -448,7 +448,12 @@ export namespace ParamDefinition {
|
||||
name: v.name,
|
||||
params: mergeParam(map, u.params, v.params)
|
||||
};
|
||||
} else if (p.type === 'value') {
|
||||
return b;
|
||||
} else if (typeof a === 'object' && typeof b === 'object') {
|
||||
if (Array.isArray(b)) {
|
||||
return b;
|
||||
}
|
||||
return { ...a, ...b };
|
||||
} else {
|
||||
return b;
|
||||
|
||||
Reference in New Issue
Block a user