123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670 |
- /**
- * Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
- import { StateAction, StateBuilder, StateTransformer, State } from '../../mol-state';
- import { PluginContext } from '../../mol-plugin/context';
- import { PluginStateObject as PSO } from '../../mol-plugin-state/objects';
- import { ParamDefinition as PD } from '../../mol-util/param-definition';
- import { Ingredient, CellPacking } from './data';
- import { getFromPdb, getFromCellPackDB, IngredientFiles, parseCif, parsePDBfile, getStructureMean, getFromOPM } from './util';
- import { Model, Structure, StructureSymmetry, StructureSelection, QueryContext, Unit, Trajectory } from '../../mol-model/structure';
- import { trajectoryFromMmCIF, MmcifFormat } from '../../mol-model-formats/structure/mmcif';
- import { trajectoryFromPDB } from '../../mol-model-formats/structure/pdb';
- import { Mat4, Vec3, Quat } from '../../mol-math/linear-algebra';
- import { SymmetryOperator } from '../../mol-math/geometry';
- import { Task, RuntimeContext } from '../../mol-task';
- import { StateTransforms } from '../../mol-plugin-state/transforms';
- import { ParseCellPack, StructureFromCellpack, DefaultCellPackBaseUrl, StructureFromAssemblies, CreateSphere } from './state';
- import { MolScriptBuilder as MS } from '../../mol-script/language/builder';
- import { getMatFromResamplePoints } from './curve';
- import { compile } from '../../mol-script/runtime/query/compiler';
- import { CifCategory, CifField } from '../../mol-io/reader/cif';
- import { mmCIF_Schema } from '../../mol-io/reader/cif/schema/mmcif';
- 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 { Color } from '../../mol-util/color';
- import { readFromFile } from '../../mol-util/data-source';
- import { objectForEach } from '../../mol-util/object';
- //import fetch from 'node-fetch';
- function getCellPackModelUrl(fileName: string, baseUrl: string) {
- return `${baseUrl}/results/${fileName}`;
- }
- class TrajectoryCache {
- private map = new Map<string, Trajectory>();
- set(id: string, trajectory: 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, location: string,
- file?: Asset.File
- ) {
- const assetManager = plugin.managers.asset;
- const modelIndex = (ingredient.source.model) ? parseInt(ingredient.source.model) : 0;
- let surface = (ingredient.ingtype) ? (ingredient.ingtype === 'transmembrane') : false;
- if (location == 'surface') surface = true;
- let trajectory = trajCache.get(id);
- let assets: Asset.Wrapper[] = [];
- 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);
- data.pdb.id! = id.toUpperCase();
- 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);
- trajectory = await plugin.runTask(trajectoryFromMmCIF(mmcif));
- }
- } else {
- 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 = await plugin.resolveTask(trajectory?.getFrameAtIndex(modelIndex)!);
- return { model, assets };
- }
- async function getStructure(plugin: PluginContext, model: Model, source: Ingredient, props: { assembly?: string } = {}) {
- let structure = Structure.ofModel(model);
- //const label = { label: 'Model', description: Structure.elementDescription(base) };
- //let structure = new PSO.Molecule.Structure(base, label);
- const { assembly } = props;
- if (assembly) {
- structure = await plugin.runTask(StructureSymmetry.buildAssembly(structure, assembly));
- }
- let query;
- if (source.source.selection){
- var sel: any = source.source.selection;
- //selection can have the model ID as well. remove it
- const asymIds: string[] = sel.replaceAll(' ', '').replaceAll(':', '').split('or').slice(1);
- //console.log("selection is ", source.selection, asymIds);
- //query = MS.struct.modifier.union([
- // MS.struct.generator.atomGroups({
- // 'entity-test': MS.core.rel.eq([MS.ammp('entityType'), 'polymer']),
- // 'chain-test': MS.core.set.has([MS.set(...asymIds), MS.ammp('auth_asym_id')])
- // })
- //]);
- query = MS.struct.modifier.union([
- MS.struct.generator.atomGroups({
- 'chain-test': MS.core.set.has([MS.set(...asymIds), MS.ammp('auth_asym_id')])
- })
- ]);
- } else {
- query = MS.struct.modifier.union([
- MS.struct.generator.atomGroups({
- 'entity-test': MS.core.rel.eq([MS.ammp('entityType'), 'polymer'])
- })
- ]);
- }
- const compiled = compile<StructureSelection>(query);
- const result = compiled(new QueryContext(structure));
- structure = StructureSelection.unionStructure(result);
- //change here if possible the label or the?
- //structure.label = source.name;
- return structure;
- }
- function getTransformLegacy(trans: Vec3, rot: Quat) {
- const q: Quat = Quat.create(-rot[3], rot[0], rot[1], rot[2]);
- const m: Mat4 = Mat4.fromQuat(Mat4.zero(), q);
- Mat4.transpose(m, m);
- Mat4.scale(m, m, Vec3.create(-1.0, 1.0, -1.0));
- Mat4.setTranslation(m, trans);
- return m;
- }
- function getTransform(trans: Vec3, rot: Quat) {
- const q: Quat = Quat.create(-rot[0], rot[1], rot[2], -rot[3]);
- const m: Mat4 = Mat4.fromQuat(Mat4.zero(), q);
- const p: Vec3 = Vec3.create(-trans[0], trans[1], trans[2]);
- Mat4.setTranslation(m, p);
- 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]));
- }
- function getCurveTransforms(ingredient: Ingredient) {
- const n = ingredient.nbCurve || 0;
- const instances: Mat4[] = [];
- let segmentLength = 3.4;
- if (ingredient.uLength){
- segmentLength = ingredient.uLength;
- } else if (ingredient.radii){
- segmentLength = ingredient.radii[0].radii
- ? ingredient.radii[0].radii[0] * 2.0
- : 3.4;
- }
- let resampling: boolean = false;
- for (let i = 0; i < n; ++i) {
- const cname = `curve${i}`;
- if (!(cname in ingredient)) {
- console.warn(`Expected '${cname}' in ingredient`)
- continue;
- }
- const _points = ingredient[cname] as Vec3[];
- if (_points.length <= 2) {
- // TODO handle curve with 2 or less points
- continue;
- }
- // test for resampling
- let distance: number = Vec3.distance(_points[0], _points[1]);
- if (distance >= segmentLength + 2.0) {
- console.info(distance);
- resampling = true;
- }
- const points = new Float32Array(_points.length * 3);
- for (let i = 0, il = _points.length; i < il; ++i) Vec3.toArray(_points[i], points, i * 3);
- const newInstances = getMatFromResamplePoints(points, segmentLength, resampling);
- instances.push(...newInstances);
- }
- return instances;
- }
- function getAssembly(name: string, transforms: Mat4[], structure: Structure) {
- const builder = Structure.Builder({ label: name });
- const { units } = structure;
- for (let i = 0, il = transforms.length; i < il; ++i) {
- const id = `${i + 1}`;
- const op = SymmetryOperator.create(id, transforms[i], { assembly: { id, operId: i, operList: [ id ] } });
- for (const unit of units) {
- builder.addWithOperator(unit, op);
- }
- }
- return builder.getStructure();
- }
- function getCifCurve(name: string, transforms: Mat4[], model: Model) {
- if (!MmcifFormat.is(model.sourceData)) throw new Error('mmcif source data needed');
- const { db } = model.sourceData.data;
- const d = db.atom_site;
- const n = d._rowCount;
- const rowCount = n * transforms.length;
- const { offsets, count } = model.atomicHierarchy.chainAtomSegments;
- const x = d.Cartn_x.toArray();
- const y = d.Cartn_y.toArray();
- const z = d.Cartn_z.toArray();
- const Cartn_x = new Float32Array(rowCount);
- const Cartn_y = new Float32Array(rowCount);
- const Cartn_z = new Float32Array(rowCount);
- const map = new Uint32Array(rowCount);
- const seq = new Int32Array(rowCount);
- let offset = 0;
- for (let c = 0; c < count; ++c) {
- const cStart = offsets[c];
- const cEnd = offsets[c + 1];
- const cLength = cEnd - cStart;
- for (let t = 0, tl = transforms.length; t < tl; ++t) {
- const m = transforms[t];
- for (let j = cStart; j < cEnd; ++j) {
- const i = offset + j - cStart;
- const xj = x[j], yj = y[j], zj = z[j];
- Cartn_x[i] = m[0] * xj + m[4] * yj + m[8] * zj + m[12];
- Cartn_y[i] = m[1] * xj + m[5] * yj + m[9] * zj + m[13];
- Cartn_z[i] = m[2] * xj + m[6] * yj + m[10] * zj + m[14];
- map[i] = j;
- seq[i] = t + 1;
- }
- offset += cLength;
- }
- }
- function multColumn<T>(column: Column<T>) {
- const array = column.toArray();
- return Column.ofLambda({
- value: row => array[map[row]],
- areValuesEqual: (rowA, rowB) => map[rowA] === map[rowB] || array[map[rowA]] === array[map[rowB]],
- rowCount, schema: column.schema
- });
- }
- const _atom_site: CifCategory.SomeFields<mmCIF_Schema['atom_site']> = {
- auth_asym_id: CifField.ofColumn(multColumn(d.auth_asym_id)),
- auth_atom_id: CifField.ofColumn(multColumn(d.auth_atom_id)),
- auth_comp_id: CifField.ofColumn(multColumn(d.auth_comp_id)),
- auth_seq_id: CifField.ofNumbers(seq),
- B_iso_or_equiv: CifField.ofColumn(Column.ofConst(0, rowCount, Column.Schema.float)),
- Cartn_x: CifField.ofNumbers(Cartn_x),
- Cartn_y: CifField.ofNumbers(Cartn_y),
- Cartn_z: CifField.ofNumbers(Cartn_z),
- group_PDB: CifField.ofColumn(Column.ofConst('ATOM', rowCount, Column.Schema.str)),
- id: CifField.ofColumn(Column.ofLambda({
- value: row => row,
- areValuesEqual: (rowA, rowB) => rowA === rowB,
- rowCount, schema: d.id.schema,
- })),
- label_alt_id: CifField.ofColumn(multColumn(d.label_alt_id)),
- label_asym_id: CifField.ofColumn(multColumn(d.label_asym_id)),
- label_atom_id: CifField.ofColumn(multColumn(d.label_atom_id)),
- label_comp_id: CifField.ofColumn(multColumn(d.label_comp_id)),
- label_seq_id: CifField.ofNumbers(seq),
- label_entity_id: CifField.ofColumn(Column.ofConst('1', rowCount, Column.Schema.str)),
- occupancy: CifField.ofColumn(Column.ofConst(1, rowCount, Column.Schema.float)),
- type_symbol: CifField.ofColumn(multColumn(d.type_symbol)),
- pdbx_PDB_ins_code: CifField.ofColumn(Column.ofConst('', rowCount, Column.Schema.str)),
- pdbx_PDB_model_num: CifField.ofColumn(Column.ofConst(1, rowCount, Column.Schema.int)),
- };
- const categories = {
- entity: CifCategory.ofTable('entity', db.entity),
- chem_comp: CifCategory.ofTable('chem_comp', db.chem_comp),
- atom_site: CifCategory.ofFields('atom_site', _atom_site)
- };
- return {
- header: name,
- categoryNames: Object.keys(categories),
- categories
- };
- }
- async function getCurve(plugin: PluginContext, name: string, ingredient: Ingredient, transforms: Mat4[], model: Model) {
- const cif = getCifCurve(name, transforms, model);
- const curveModelTask = Task.create('Curve Model', async ctx => {
- const format = MmcifFormat.fromFrame(cif);
- const models = await createModels(format.data.db, format, ctx);
- return models.representative;
- });
- const curveModel = await plugin.runTask(curveModelTask);
- //ingredient.source.selection = undefined;
- return getStructure(plugin, curveModel, ingredient);
- }
- async function getIngredientStructure(plugin: PluginContext, ingredient: Ingredient, baseUrl: string, ingredientFiles: IngredientFiles, trajCache: TrajectoryCache, location: 'surface' | 'interior' | 'cytoplasme') {
- const { name, source, results, nbCurve } = ingredient;
- if (source.pdb === 'None') return;
- const file = ingredientFiles[source.pdb];
- if (!file) {
- // TODO can these be added to the library?
- if (name === 'HIV1_CAhex_0_1_0') return; // 1VU4CtoH_hex.pdb
- if (name === 'HIV1_CAhexCyclophilA_0_1_0') return; // 1AK4fitTo1VU4hex.pdb
- if (name === 'iLDL') return; // EMD-5239
- if (name === 'peptides') return; // peptide.pdb
- if (name === 'lypoglycane') return;
- }
- // model id in case structure is NMR
- const { model, assets } = await getModel(plugin, source.pdb || name, ingredient, baseUrl, trajCache, location, file);
- if (!model) return;
- let structure: Structure;
- if (nbCurve) {
- //console.log("await getCurve", name, nbCurve, model);
- structure = await getCurve(plugin, name, ingredient, getCurveTransforms(ingredient), model);
- //console.log("getCurve", structure);
- } else {
- if ( (!results || results.length===0)) return;
- let bu: string|undefined = source.bu ? source.bu : undefined;
- if (bu){
- if (bu === 'AU') {
- bu = undefined;
- } else {
- bu = bu.slice(2);
- }
- }
- structure = await getStructure(plugin, model, ingredient, { assembly: bu });
- // transform with offset and pcp
- let legacy: boolean = true;
- //if (name === 'MG_213_214_298_6MER_ADP') {
- // console.log("getStructure ", ingredient.offset,ingredient.principalVector,ingredient);
- //}
- var pcp = ingredient.principalVector?ingredient.principalVector:ingredient.principalAxis;
- if (pcp){
- legacy = false;
- const structureMean = getStructureMean(structure);
- Vec3.negate(structureMean, structureMean);
- const m1: Mat4 = Mat4.identity();
- Mat4.setTranslation(m1, structureMean);
- structure = Structure.transform(structure, m1);
- if (ingredient.offset){
- let o: Vec3 = Vec3.create(ingredient.offset[0], ingredient.offset[1], ingredient.offset[2]);
- if (!Vec3.exactEquals(o, Vec3.zero())){ // -1, 1, 4e-16 ??
- if (location !== 'surface')//(name === 'MG_213_214_298_6MER_ADP')
- {
- Vec3.negate(o, o);
- //console.log("after negate offset ",name, o);
- }
- const m: Mat4 = Mat4.identity();
- Mat4.setTranslation(m, o);
- structure = Structure.transform(structure, m);
- }
- }
- if (pcp){
- let p: Vec3 = Vec3.create(pcp[0], pcp[1], pcp[2]);
- if (!Vec3.exactEquals(p, Vec3.unitZ)){
- //if (location !== 'surface')//(name === 'MG_213_214_298_6MER_ADP')
- //{
- //Vec3.negate(p, p);
- //console.log("after negate ", p);
- // }
- const q: Quat = Quat.identity();
- Quat.rotationTo(q, p, Vec3.unitZ);
- const m: Mat4 = Mat4.fromQuat(Mat4.zero(), q);
- //if (location !== 'surface') Mat4.invert(m, m);
- structure = Structure.transform(structure, m);
- //if (location === 'surface') console.log('surface',name,ingredient.principalVector, q);
- }
- }
- }
-
- structure = getAssembly(name, getResultTransforms(results, legacy), structure);
- //console.log("getStructure ", name, structure.label, structure);
- }
- return { structure, assets };
- }
- export function createStructureFromCellPack(plugin: PluginContext, packing: CellPacking, baseUrl: string, ingredientFiles: IngredientFiles) {
- return Task.create('Create Packing Structure', async ctx => {
- const { ingredients, location, name } = packing;
- const assets: Asset.Wrapper[] = [];
- const trajCache = new TrajectoryCache();
- const structures: Structure[] = [];
- const colors: Color[] = [];
- //let skipColors: boolean = false;
- for (const iName in ingredients) {
- if (ctx.shouldUpdate) await ctx.update(iName);
- const ingredientStructure = await getIngredientStructure(plugin, ingredients[iName], baseUrl, ingredientFiles, trajCache, location);
- if (ingredientStructure) {
- structures.push(ingredientStructure.structure);
- assets.push(...ingredientStructure.assets);
- const c = ingredients[iName].color;
- if (c){
- colors.push(Color.fromNormalizedRgb(c[0], c[1], c[2]));
- } else {
- colors.push(Color.fromNormalizedRgb(1,0,0));
- //skipColors = true;
- }
- }
- }
- if (ctx.shouldUpdate) await ctx.update(`${name} - units`);
- const units: Unit[] = [];
- let offsetInvariantId = 0;
- let offsetChainGroupId = 0;
- for (const s of structures) {
- if (ctx.shouldUpdate) await ctx.update(`${s.label}`);
- let maxInvariantId = 0;
- let maxChainGroupId = 0;
- for (const u of s.units) {
- const invariantId = u.invariantId + offsetInvariantId;
- const chainGroupId = u.chainGroupId + offsetChainGroupId;
- if (u.invariantId > maxInvariantId) maxInvariantId = u.invariantId;
- units.push(Unit.create(units.length, invariantId, chainGroupId, u.traits, u.kind, u.model, u.conformation.operator, u.elements, u.props));
- }
- offsetInvariantId += maxInvariantId + 1;
- offsetChainGroupId += maxChainGroupId + 1;
- }
- if (ctx.shouldUpdate) await ctx.update(`${name} - structure`);
- const structure = Structure.create(units, {label: name+"."+location});
- for( let i = 0, il = structure.models.length; i < il; ++i) {
- Model.TrajectoryInfo.set(structure.models[i], { size: il, index: i });
- }
- return { structure, assets, colors: colors };
- });
- }
- async function handleHivRna(plugin: PluginContext, packings: CellPacking[], baseUrl: string) {
- for (let i = 0, il = packings.length; i < il; ++i) {
- if (packings[i].name === 'HIV1_capsid_3j3q_PackInner_0_1_0'|| packings[i].name === 'HIV_capsid') {
- const url = Asset.getUrlAsset(plugin.managers.asset, `${baseUrl}/extras/rna_allpoints.json`);
- const json = await plugin.runTask(plugin.managers.asset.resolve(url, 'json', false));
- const points = json.data.points as number[];
- const curve0: Vec3[] = [];
- for (let j = 0, jl = points.length; j < jl; j += 3) {
- curve0.push(Vec3.fromArray(Vec3(), points, j));
- }
- packings[i].ingredients['RNA'] = {
- source: { pdb: 'RNA_U_Base.pdb', transform: { center: false } },
- results: [],
- name: 'RNA',
- nbCurve: 1,
- curve0
- };
- }
- }
- }
- async function loadMembrane(plugin: PluginContext, name: string, state: State, params: LoadCellPackModelParams) {
- let file: Asset.File | undefined = undefined;
- if (params.ingredients !== null) {
- const fileName = `${name}.bcif`;
- for (const f of params.ingredients) {
- if (fileName === f.name) {
- file = f;
- break;
- }
- }
- if (!file){
- // check for cif directly
- const cifileName = `${name}.cif`;
- for (const f of params.ingredients) {
- if (cifileName === f.name) {
- file = f;
- break;
- }
- }
- }
- }
- let b = state.build().toRoot();
- if (file) {
- if (file.name.endsWith('.cif')) {
- b = b.apply(StateTransforms.Data.ReadFile, { file, isBinary: false, label: file.name }, { state: { isGhost: true } });
- } else if (file.name.endsWith('.bcif')) {
- b = b.apply(StateTransforms.Data.ReadFile, { file, isBinary: true, label: file.name }, { state: { isGhost: true } });
- }
- } else {
- const url = Asset.getUrlAsset(plugin.managers.asset, `${params.baseUrl}/membranes/${name}.bcif`);
- b = b.apply(StateTransforms.Data.Download, { url, isBinary: true, label: name }, { state: { isGhost: true } });
- }
- const props = {
- type: {
- name: 'assembly' as const,
- params: { id: '1' }
- }
- };
- if (params.source.name === 'id' && params.source.params !== "MycoplasmaGenitalium.json")
- //old membrane
- {
- const membrane = await b.apply(StateTransforms.Data.ParseCif, undefined, { state: { isGhost: true } })
- .apply(StateTransforms.Model.TrajectoryFromMmCif, undefined, { state: { isGhost: true } })
- .apply(StateTransforms.Model.ModelFromTrajectory, undefined, { state: { isGhost: true } })
- .apply(StructureFromAssemblies, undefined, { state: { isGhost: true } })
- .commit({ revertOnError: true });
- const membraneParams = {
- representation: params.preset.representation,
- };
- await CellpackMembranePreset.apply(membrane, membraneParams, plugin);
- } else {
- const membrane = await b.apply(StateTransforms.Data.ParseCif, undefined, { state: { isGhost: true } })
- .apply(StateTransforms.Model.TrajectoryFromMmCif, undefined, { state: { isGhost: true } })
- .apply(StateTransforms.Model.ModelFromTrajectory, undefined, { state: { isGhost: true } })
- .apply(StateTransforms.Model.StructureFromModel, props, { state: { isGhost: true } })
- .commit({ revertOnError: true });
- const membraneParams = {
- representation: params.preset.representation,
- };
- await CellpackMembranePreset.apply(membrane, membraneParams, plugin);
- }
- }
- async function loadPackings(plugin: PluginContext, runtime: RuntimeContext, state: State, params: LoadCellPackModelParams) {
- const ingredientFiles = params.ingredients || [];
- let cellPackJson: StateBuilder.To<PSO.Format.Json, StateTransformer<PSO.Data.String, PSO.Format.Json>>;
- let modelFile: Asset.File|null= params.results;
- if (params.source.name === 'id') {
- const url = Asset.getUrlAsset(plugin.managers.asset, getCellPackModelUrl(params.source.params, params.baseUrl));
- //console.log("getting "+params.source.params+" "+url.url);
- cellPackJson = state.build().toRoot()
- .apply(StateTransforms.Data.Download, { url, isBinary: false, label: params.source.params }, { state: { isGhost: true } });
- if (params.source.params === "MycoplasmaGenitalium.json"){
- const m_url = Asset.getUrlAsset(plugin.managers.asset, `${params.baseUrl}/results/results_149_curated_serialized.bin`);
- //console.log("getting results "+m_url.url);
- const model_data = await fetch(m_url.url);
- modelFile = Asset.File(new File([await model_data.arrayBuffer()], 'model.bin'));
- //console.log("MycoplasmaGenitalium.json loading setup ?",modelFile);
- }
- } else {
- const file = params.source.params;
- const rfile = params.results;
- 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'));
- modelFile = Asset.File(new File([data['model.bin']], 'model.bin'));
- objectForEach(data, (v, k) => {
- if (k === 'model.json') return;
- else if (k === 'model.bin') return;
- ingredientFiles.push(Asset.File(new File([v], k)));
- });
- } else {
- jsonFile = file;
- modelFile = rfile;
- }
- cellPackJson = state.build().toRoot()
- .apply(StateTransforms.Data.ReadFile, { file: jsonFile, isBinary: false, label: jsonFile.name }, { state: { isGhost: true } });
-
- }
- const cellPackBuilder = cellPackJson
- .apply(StateTransforms.Data.ParseJson, undefined, { state: { isGhost: true } })
- .apply(ParseCellPack,{modeFile:modelFile});
-
- const cellPackObject = await state.updateTree(cellPackBuilder).runInContext(runtime);
-
- const { packings } = cellPackObject.obj!.data;
-
- await handleHivRna(plugin, packings, params.baseUrl);
- for (let i = 0, il = packings.length; i < il; ++i) {
- const p = { packing: i, baseUrl: params.baseUrl, ingredientFiles };
- const packing = await state.build()
- .to(cellPackBuilder.ref)
- .apply(StructureFromCellpack, p)
- .commit({ revertOnError: true });
- const packingParams = {
- traceOnly: params.preset.traceOnly,
- representation: params.preset.representation,
- };
- await CellpackPackingPreset.apply(packing, packingParams, plugin);
- if ( packings[i].location === 'surface') {
- if (params.membrane){
- await loadMembrane(plugin, packings[i].name, state, params);
- }
- if (typeof(packings[i].mb) !== 'undefined'){
- var nSpheres = packings[i].mb!.positions.length/3;
- for (var j=0;j<nSpheres;j++) {
- await state.build()
- .toRoot()
- .apply(CreateSphere, {center:Vec3.create(packings[i].mb!.positions[j*3+0],
- packings[i].mb!.positions[j*3+1],
- packings[i].mb!.positions[j*3+2]),
- radius:packings[i].mb!.radii[j] })
- .commit()
- }
- }
- }
- }
- }
- const LoadCellPackModelParams = {
- source: PD.MappedStatic('id', {
- 'id': PD.Select('InfluenzaModel2.json', [
- ['blood_hiv_immature_inside.json', 'Blood HIV immature'],
- ['HIV_immature_model.json', 'HIV immature'],
- ['BloodHIV1.0_mixed_fixed_nc1.cpr', 'Blood HIV'],
- ['HIV-1_0.1.6-8_mixed_radii_pdb.json', 'HIV'],
- ['influenza_model1.json', 'Influenza envelope'],
- ['InfluenzaModel2.json', 'Influenza Complete'],
- ['ExosomeModel.json', 'Exosome Model'],
- //['Mycoplasma1.5_mixed_pdb_fixed.cpr', 'Mycoplasma simple'],
- //['MycoplasmaModel.json', 'Mycoplasma WholeCell model'],
- ['MycoplasmaGenitalium.json', 'Mycoplasma Genitalium curated model'],
- ] 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),
- results : PD.File({ accept: '.bin,.json' }),
- membrane: PD.Boolean(true),
- ingredients: PD.FileList({ accept: '.cif,.bcif,.pdb', label: 'Ingredients' }),
- preset: PD.Group({
- traceOnly: PD.Boolean(false),
- representation: PD.Select('gaussian-surface', PD.arrayToOptions(['spacefill', 'gaussian-surface', 'point', 'orientation']))
- }, { isExpanded: true })
- };
- type LoadCellPackModelParams = PD.Values<typeof LoadCellPackModelParams>
- export const LoadCellPackModel = StateAction.build({
- display: { name: 'Load CellPack', description: 'Open or download a model' },
- params: LoadCellPackModelParams,
- from: PSO.Root
- })(({ state, params }, ctx: PluginContext) => Task.create('CellPack Loader', async taskCtx => {
- await loadPackings(ctx, taskCtx, state, params);
- }));
|