Pārlūkot izejas kodu

support for membrane in list files and on the server if available as bcif
clean the console.log

DESKTOP-O6LIMN9\ludov 5 gadi atpakaļ
vecāks
revīzija
f1d78e4805

+ 3 - 3
README.md

@@ -114,9 +114,9 @@ and navigate to `build/viewer`
 
 **Convert any CIF to BinaryCIF**
 
-    node build/model-server/preprocess -i file.cif -ob file.bcif
-
-To see all available commands, use ``node build/model-server/preprocess -h``.
+    node lib/servers/model/preprocess -i file.cif -ob file.bcif
+    
+To see all available commands, use ``node lib/servers/model/preprocess -h``.
 
 Or
 

+ 0 - 5
src/apps/viewer/extensions/cellpack/curve.ts

@@ -192,7 +192,6 @@ function GetMiniFrame(points: Vec3[], normals: Vec3[]) {
 const rpTmpVec1 = Vec3()
 
 export function getMatFromResamplePoints(points: NumberArray, segmentLength: number) {
-    //const segmentLength = 3.4
     const new_points = ResampleControlPoints(points, segmentLength)
     const npoints = new_points.length
     const new_normal = GetSmoothNormals(new_points)
@@ -200,10 +199,6 @@ export function getMatFromResamplePoints(points: NumberArray, segmentLength: num
     const limit = npoints
     const transforms: Mat4[] = []
     const pti = Vec3.copy(rpTmpVec1, new_points[0]);
-    // console.log(new_points.length)
-    // console.log(points.length/3)
-    // console.log(limit)
-    // console.log(segmentLength)
     for (let i = 0; i<npoints-2; ++i) {
         const pti1: Vec3 = new_points[i+1] // Vec3.create(points[(i+1)*3],points[(i+1)*3+1],points[(i+1)*3+2]);
         const d = Vec3.distance(pti, pti1)

+ 130 - 23
src/apps/viewer/extensions/cellpack/model.ts

@@ -8,7 +8,7 @@ import { StateAction, StateBuilder, StateTransformer, State } from '../../../../
 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 { Ingredient, IngredientSource, CellPacking } from './data';
 import { getFromPdb, getFromCellPackDB, IngredientFiles, parseCif, parsePDBfile } from './util';
 import { Model, Structure, StructureSymmetry, StructureSelection, QueryContext, Unit } from '../../../../mol-model/structure';
 import { trajectoryFromMmCIF, MmcifFormat } from '../../../../mol-model-formats/structure/mmcif';
@@ -34,44 +34,56 @@ function getCellPackModelUrl(fileName: string, baseUrl: string) {
     return `${baseUrl}/results/${fileName}`
 }
 
-async function getModel(id: string, baseUrl: string, file?: File) {
+async function getModel(id: string, model_id:number, baseUrl: string, file?: File) {
     let model: Model;
     if (file) {
         const text = await file.text()
         if (file.name.endsWith('.cif')) {
             const cif = (await parseCif(text)).blocks[0]
-            model = (await trajectoryFromMmCIF(cif).run())[0]
+            model = (await trajectoryFromMmCIF(cif).run())[model_id]
         } else if (file.name.endsWith('.pdb')) {
             const pdb = await parsePDBfile(text, id)
 
-            model = (await trajectoryFromPDB(pdb).run())[0]
+            model = (await trajectoryFromPDB(pdb).run())[model_id]
         } else {
             throw new Error(`unsupported file type '${file.name}'`)
         }
     } else if (id.match(/^[1-9][a-zA-Z0-9]{3,3}$/i)) {
         // return
         const cif = await getFromPdb(id)
-        model = (await trajectoryFromMmCIF(cif).run())[0]
+        model = (await trajectoryFromMmCIF(cif).run())[model_id]
     } else {
         const pdb = await getFromCellPackDB(id, baseUrl)
-        model = (await trajectoryFromPDB(pdb).run())[0]
+        model = (await trajectoryFromPDB(pdb).run())[model_id]
     }
     return model
 }
 
-async function getStructure(model: Model, props: { assembly?: string } = {}) {
+async function getStructure(model: Model, source:IngredientSource,props: { assembly?: string } = {}) {
     let structure = Structure.ofModel(model)
     const { assembly } = props
 
     if (assembly) {
         structure = await StructureSymmetry.buildAssembly(structure, assembly).run()
     }
+    let query;
+    if (source.selection){
+        const asymIds:string[] = source.selection.replace(" :","").split(" or")
+        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')])
+            })
+        ])
+    }
+    else {
+        query = MS.struct.modifier.union([
+            MS.struct.generator.atomGroups({
+                'entity-test': MS.core.rel.eq([MS.ammp('entityType'), 'polymer'])
+            })
+        ])
+    }
 
-    const 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)
@@ -79,7 +91,7 @@ async function getStructure(model: Model, props: { assembly?: string } = {}) {
     return structure
 }
 
-function getTransform(trans: Vec3, rot: Quat) {
+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)
@@ -88,14 +100,24 @@ function getTransform(trans: Vec3, rot: Quat) {
     return m
 }
 
-function getResultTransforms(results: Ingredient['results']) {
-    return results.map((r: Ingredient['results'][0]) => getTransform(r[0], r[1]))
+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[] = []
-
+    const segmentLength = (ingredient.radii)? ((ingredient.radii[0].radii)?ingredient.radii[0].radii[0]*2.0:3.4):3.4;
     for (let i = 0; i < n; ++i) {
         const cname = `curve${i}`
         if (!(cname in ingredient)) {
@@ -109,7 +131,7 @@ function getCurveTransforms(ingredient: Ingredient) {
         }
         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)
+        const newInstances = getMatFromResamplePoints(points,segmentLength)
         instances.push(...newInstances)
     }
 
@@ -224,7 +246,7 @@ function getCifCurve(name: string, transforms: Mat4[], model: Model) {
     };
 }
 
-async function getCurve(name: string, transforms: Mat4[], model: Model) {
+async function getCurve(name: string, ingredient:Ingredient, transforms: Mat4[], model: Model) {
     const cif = getCifCurve(name, transforms, model)
 
     const curveModelTask = Task.create('Curve Model', async ctx => {
@@ -234,7 +256,7 @@ async function getCurve(name: string, transforms: Mat4[], model: Model) {
     })
 
     const curveModel = await curveModelTask.run()
-    return getStructure(curveModel)
+    return getStructure(curveModel, ingredient.source)
 }
 
 async function getIngredientStructure(ingredient: Ingredient, baseUrl: string, ingredientFiles: IngredientFiles) {
@@ -251,14 +273,55 @@ async function getIngredientStructure(ingredient: Ingredient, baseUrl: string, i
         if (name === 'lypoglycane') return
     }
 
-    const model = await getModel(source.pdb || name, baseUrl, file)
+    //model id in case structure is NMR
+    const model_id = (ingredient.source.model)? parseInt(ingredient.source.model) : 0;
+    const model = await getModel(source.pdb || name,model_id, baseUrl, file)
     if (!model) return
 
     if (nbCurve) {
-        return getCurve(name, getCurveTransforms(ingredient), model)
+        return getCurve(name, ingredient, getCurveTransforms(ingredient), model)
     } else {
-        const structure = await getStructure(model, { assembly: source.biomt ? '1' : undefined })
-        return getAssembly(getResultTransforms(results), structure)
+        let bu:string|undefined = source.bu ? source.bu : undefined;
+        if (bu){
+            if (bu === "AU") {bu = undefined;}
+            else {
+                bu = bu.slice(2)
+            }
+        }
+        let structure = await getStructure(model,source, { assembly: bu })
+        //transform with offset and pcp
+        let legacy:boolean = true
+        if (ingredient.offset || ingredient.principalAxis)
+        //center the structure
+        {
+            legacy=false
+            const boundary = structure.boundary
+            let structureCenter:Vec3 = Vec3.zero()
+            Vec3.negate(structureCenter,boundary.sphere.center)
+            const m1: Mat4 = Mat4.identity()
+            Mat4.setTranslation(m1, structureCenter)
+            structure = Structure.transform(structure,m1)
+            if (ingredient.offset)
+            {
+                if (!Vec3.exactEquals(ingredient.offset,Vec3.zero()))
+                { 
+                    const m: Mat4 = Mat4.identity();
+                    Mat4.setTranslation(m, ingredient.offset)
+                    structure = Structure.transform(structure,m);
+                }
+            }
+            if (ingredient.principalAxis)
+            {
+                if (!Vec3.exactEquals(ingredient.principalAxis,Vec3.unitZ))
+                {            
+                    const q: Quat = Quat.identity();
+                    Quat.rotationTo(q,ingredient.principalAxis,Vec3.unitZ)
+                    const m: Mat4 = Mat4.fromQuat(Mat4.zero(), q)
+                    structure = Structure.transform(structure,m);
+                }
+            }
+        }
+        return getAssembly(getResultTransforms(results,legacy), structure)
     }
 }
 
@@ -319,6 +382,46 @@ async function handleHivRna(ctx: { runtime: RuntimeContext, fetch: AjaxTask }, p
     }
 }
 
+async function loadMembrane(name:string, plugin: PluginContext, runtime: RuntimeContext, state: State, params: LoadCellPackModelParams) {
+    const fname: string  = `${name}.bcif`
+    let ingredientFiles: IngredientFiles = {}
+    if (params.ingredients.files !== null) {
+        for (let i = 0, il = params.ingredients.files.length; i < il; ++i) {
+            const file = params.ingredients.files.item(i)
+            if (file) ingredientFiles[file.name] = file
+        }
+    }
+    const url = `${params.baseUrl}/membranes/${name}.bcif`
+    //
+    const file = (ingredientFiles)?ingredientFiles[fname]:null;
+    let membrane
+    if (!file)
+    //can we check if url exist
+   { 
+       membrane = await state.build().toRoot()
+        .apply(StateTransforms.Data.Download, { label: name, url, isBinary: true }, { state: { isGhost: true } })
+        .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)
+        .commit()
+    }
+    else {
+        membrane = await state.build().toRoot()
+        .apply(StateTransforms.Data.ReadFile, { file, isBinary: true, label: file.name }, { state: { isGhost: true } })
+        .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)
+        .commit()        
+    }
+
+    const membraneParams = {
+        representation: params.preset.representation,
+    }
+    await CellpackMembranePreset.apply(membrane, membraneParams, plugin)
+}
+
 async function loadHivMembrane(plugin: PluginContext, runtime: RuntimeContext, state: State, params: LoadCellPackModelParams) {
     const url = `${params.baseUrl}/membranes/hiv_lipids.bcif`
     const membrane = await state.build().toRoot()
@@ -381,6 +484,9 @@ async function loadPackings(plugin: PluginContext, runtime: RuntimeContext, stat
             representation: params.preset.representation,
         }
         await CellpackPackingPreset.apply(packing, packingParams, plugin)
+        if ( packings[i].location === "surface" ){
+            await loadMembrane(packings[i].name, plugin, runtime, state, params)
+        }
     }
 }
 
@@ -392,6 +498,7 @@ const LoadCellPackModelParams = {
             ['HIV-1_0.1.6-8_mixed_radii_pdb.cpr', 'HIV-1_0.1.6-8_mixed_radii_pdb'],
             ['hiv_lipids.bcif', 'hiv_lipids'],
             ['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' }),