mirror of
https://github.com/molstar/molstar.git
synced 2026-06-04 13:30:24 +08:00
Added spacegroups to mol-model
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
atom_sites.entry_id
|
||||
atom_sites.fract_transf_matrix
|
||||
atom_sites.fract_transf_vector
|
||||
|
||||
atom_site.group_PDB
|
||||
atom_site.id
|
||||
atom_site.type_symbol
|
||||
|
||||
|
@@ -21,6 +21,11 @@ const Vector = Schema.Vector;
|
||||
const List = Schema.List;
|
||||
|
||||
export const mmCIF_Schema = {
|
||||
atom_sites: {
|
||||
entry_id: str,
|
||||
fract_transf_matrix: Matrix(3, 3),
|
||||
fract_transf_vector: Vector(3)
|
||||
},
|
||||
atom_site: {
|
||||
auth_asym_id: str,
|
||||
auth_atom_id: str,
|
||||
|
||||
@@ -5,11 +5,12 @@
|
||||
*/
|
||||
|
||||
import { Vec3, Mat4 } from '../../linear-algebra'
|
||||
import { SpacegroupName, TransformData, GroupData, SpacegroupNumbers, SpacegroupNames, OperatorData } from './tables'
|
||||
import { SpacegroupName, TransformData, GroupData, getSpacegroupIndex, OperatorData, SpacegroupNames } from './tables'
|
||||
import { SymmetryOperator } from '../../geometry';
|
||||
|
||||
interface SpacegroupCell {
|
||||
readonly number: number,
|
||||
// zero based spacegroup number
|
||||
readonly index: number,
|
||||
readonly size: Vec3,
|
||||
readonly anglesInRadians: Vec3,
|
||||
/** Transfrom cartesian -> fractional coordinates within the cell */
|
||||
@@ -26,16 +27,18 @@ interface Spacegroup {
|
||||
|
||||
namespace SpacegroupCell {
|
||||
// Create a 'P 1' with cellsize [1, 1, 1]
|
||||
export function zero() {
|
||||
return create(0, Vec3.create(1, 1, 1), Vec3.create(Math.PI / 2, Math.PI / 2, Math.PI / 2));
|
||||
}
|
||||
export const Zero: SpacegroupCell = create('P 1', Vec3.create(1, 1, 1), Vec3.create(Math.PI / 2, Math.PI / 2, Math.PI / 2));
|
||||
|
||||
// True if 'P 1' with cellsize [1, 1, 1]
|
||||
export function isZero(cell: SpacegroupCell) {
|
||||
return cell.size[0] === 1 && cell.size[1] === 1 && cell.size[1] === 1;
|
||||
return cell.index === 0 && cell.size[0] === 1 && cell.size[1] === 1 && cell.size[1] === 1;
|
||||
}
|
||||
|
||||
export function create(nameOrNumber: number | SpacegroupName, size: Vec3, anglesInRadians: Vec3): SpacegroupCell {
|
||||
// returns Zero cell if the spacegroup does not exist
|
||||
export function create(nameOrNumber: number | string | SpacegroupName, size: Vec3, anglesInRadians: Vec3): SpacegroupCell {
|
||||
const index = getSpacegroupIndex(nameOrNumber);
|
||||
if (index < 0) return Zero;
|
||||
|
||||
const alpha = anglesInRadians[0];
|
||||
const beta = anglesInRadians[1];
|
||||
const gamma = anglesInRadians[2];
|
||||
@@ -58,23 +61,18 @@ namespace SpacegroupCell {
|
||||
]);
|
||||
const toFractional = Mat4.invert(Mat4.zero(), fromFractional)!;
|
||||
|
||||
const num = typeof nameOrNumber === 'number' ? nameOrNumber : SpacegroupNumbers[nameOrNumber];
|
||||
return { number: num, size, anglesInRadians, toFractional, fromFractional };
|
||||
return { index, size, anglesInRadians, toFractional, fromFractional };
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
namespace Spacegroup {
|
||||
export function create(nameOrNumber: number | SpacegroupName, cell: SpacegroupCell): Spacegroup {
|
||||
const num = typeof nameOrNumber === 'number' ? nameOrNumber : SpacegroupNumbers[nameOrNumber];
|
||||
const name = typeof nameOrNumber === 'number' ? SpacegroupNames[nameOrNumber] : nameOrNumber;
|
||||
// P1 with [1, 1, 1] cell.
|
||||
export const ZeroP1 = create(SpacegroupCell.Zero);
|
||||
|
||||
if (typeof num === 'undefined' || typeof name === 'undefined') {
|
||||
throw new Error(`Spacegroup '${nameOrNumber}' is not defined.`);
|
||||
}
|
||||
|
||||
const operators = GroupData[num].map(i => getOperatorMatrix(OperatorData[i]));
|
||||
|
||||
return { name, cell, operators };
|
||||
export function create(cell: SpacegroupCell): Spacegroup {
|
||||
const operators = GroupData[cell.index].map(i => getOperatorMatrix(OperatorData[i]));
|
||||
return { name: SpacegroupNames[cell.index], cell, operators };
|
||||
}
|
||||
|
||||
const _tempVec = Vec3.zero(), _tempMat = Mat4.zero();
|
||||
@@ -89,6 +87,8 @@ namespace Spacegroup {
|
||||
|
||||
export function getSymmetryOperator(spacegroup: Spacegroup, index: number, i: number, j: number, k: number): SymmetryOperator {
|
||||
const operator = updateOperatorMatrix(spacegroup, index, i, j, k, Mat4.zero());
|
||||
console.log(Mat4.makeTable(operator));
|
||||
console.log({ index, i, j, k });
|
||||
return SymmetryOperator.create(`${index + 1}_${5 + i}${5 + j}${5 + k}`, operator, Vec3.create(i, j, k));
|
||||
}
|
||||
|
||||
|
||||
@@ -985,7 +985,7 @@ export const GroupData = [
|
||||
[0, 22, 57, 3, 159, 279, 654, 655, 158, 274, 656, 657, 29, 18, 25, 27, 284, 658, 262, 269, 280, 659, 257, 267],
|
||||
];
|
||||
|
||||
export const SpacegroupNumbers = {
|
||||
export const ZeroBasedSpacegroupNumbers = {
|
||||
'P 1': 0,
|
||||
'P -1': 1,
|
||||
'P 1 2 1': 2,
|
||||
@@ -1333,12 +1333,19 @@ export const SpacegroupNumbers = {
|
||||
'I 2 3a': 265,
|
||||
};
|
||||
|
||||
export type SpacegroupName = keyof typeof SpacegroupNumbers
|
||||
export type SpacegroupName = keyof typeof ZeroBasedSpacegroupNumbers
|
||||
|
||||
export const SpacegroupNames: { [num: number]: SpacegroupName } = (function () {
|
||||
const names = Object.create(null);
|
||||
for (const n of Object.keys(SpacegroupNumbers)) {
|
||||
names[(SpacegroupNumbers as any)[n]] = n;
|
||||
for (const n of Object.keys(ZeroBasedSpacegroupNumbers)) {
|
||||
names[(ZeroBasedSpacegroupNumbers as any)[n]] = n;
|
||||
}
|
||||
return names;
|
||||
}());
|
||||
}());
|
||||
|
||||
// return -1 if the spacegroup does not exist.
|
||||
export function getSpacegroupIndex(nameOrNumber: number | string | SpacegroupName): number {
|
||||
const index = typeof nameOrNumber === 'number' ? nameOrNumber - 1 : ZeroBasedSpacegroupNumbers[nameOrNumber as SpacegroupName];
|
||||
if (typeof index === 'undefined' || typeof SpacegroupNames[index] === 'undefined') return -1;
|
||||
return index;
|
||||
}
|
||||
@@ -17,4 +17,8 @@
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*/
|
||||
|
||||
export const enum EPSILON { Value = 0.000001 }
|
||||
export const enum EPSILON { Value = 0.000001 }
|
||||
|
||||
export function equalEps(a: number, b: number, eps: number) {
|
||||
return Math.abs(a - b) <= eps;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*/
|
||||
|
||||
import { EPSILON } from './common'
|
||||
import { EPSILON, equalEps } from './common'
|
||||
import Vec3 from './vec3';
|
||||
import Quat from './quat';
|
||||
|
||||
@@ -539,11 +539,11 @@ namespace Mat4 {
|
||||
a20 = a[8], a21 = a[9], a22 = a[10], a23 = a[11],
|
||||
/* a30 = a[12], a31 = a[13], a32 = a[14],*/ a33 = a[15];
|
||||
|
||||
if (a33 !== 1 || a03 !== 0 || a13 !== 0 || a23 !== 0) {
|
||||
if (!equalEps(a33, 1, eps) || !equalEps(a03, 0, eps) || !equalEps(a13, 0, eps) || !equalEps(a23, 0, eps)) {
|
||||
return false;
|
||||
}
|
||||
const det3x3 = a00 * (a11 * a22 - a12 * a21) - a01 * (a10 * a22 - a12 * a20) + a02 * (a10 * a21 - a11 * a20);
|
||||
if (det3x3 < 1 - eps || det3x3 > 1 + eps) {
|
||||
if (!equalEps(det3x3, 1, eps)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -7,6 +7,6 @@
|
||||
import Model from './model/model'
|
||||
import * as Types from './model/types'
|
||||
import Format from './model/format'
|
||||
import ModelSymmetry from './model/properties/symmetry'
|
||||
import { ModelSymmetry } from './model/properties/symmetry'
|
||||
|
||||
export { Model, Types, Format, ModelSymmetry }
|
||||
@@ -10,8 +10,7 @@ import { Interval, Segmentation } from 'mol-data/int'
|
||||
import { Atoms } from 'mol-io/reader/gro/schema'
|
||||
import Format from '../format'
|
||||
import Model from '../model'
|
||||
import * as AtomicHierarchy from '../properties/atomic/hierarchy'
|
||||
import { AtomicConformation } from '../properties/atomic/conformation'
|
||||
import { AtomicConformation, AtomicData, AtomsSchema, ResiduesSchema, ChainsSchema, AtomicSegments } from '../properties/atomic'
|
||||
import { CoarseGrainedHierarchy } from '../properties/coarse-grained/hierarchy'
|
||||
import findHierarchyKeys from '../utils/hierarchy-keys'
|
||||
import { guessElement } from '../utils/guess-element'
|
||||
@@ -21,6 +20,7 @@ import { mmCIF_Schema as mmCIF } from 'mol-io/reader/cif/schema/mmcif'
|
||||
import gro_Format = Format.gro
|
||||
import Sequence from '../properties/sequence';
|
||||
import { Entities } from '../properties/common';
|
||||
import { ModelSymmetry } from '../properties/symmetry';
|
||||
|
||||
type HierarchyOffsets = { residues: ArrayLike<number>, chains: ArrayLike<number> }
|
||||
|
||||
@@ -44,9 +44,9 @@ function guessElementSymbol (value: string) {
|
||||
return ElementSymbol(guessElement(value));
|
||||
}
|
||||
|
||||
function createHierarchyData(atomsData: Atoms, offsets: HierarchyOffsets): AtomicHierarchy.AtomicData {
|
||||
function createHierarchyData(atomsData: Atoms, offsets: HierarchyOffsets): AtomicData {
|
||||
console.log(atomsData.atomName)
|
||||
const atoms = Table.ofColumns(AtomicHierarchy.AtomsSchema, {
|
||||
const atoms = Table.ofColumns(AtomsSchema, {
|
||||
type_symbol: Column.ofArray({ array: Column.mapToArray(atomsData.atomName, guessElementSymbol), schema: Column.Schema.Aliased<ElementSymbol>(Column.Schema.str) }),
|
||||
label_atom_id: atomsData.atomName,
|
||||
auth_atom_id: atomsData.atomName,
|
||||
@@ -54,14 +54,14 @@ function createHierarchyData(atomsData: Atoms, offsets: HierarchyOffsets): Atomi
|
||||
pdbx_formal_charge: Column.Undefined(atomsData.count, Column.Schema.int)
|
||||
});
|
||||
|
||||
const residues = Table.view(Table.ofColumns(AtomicHierarchy.ResiduesSchema, {
|
||||
const residues = Table.view(Table.ofColumns(ResiduesSchema, {
|
||||
group_PDB: Column.Undefined(atomsData.count, Column.Schema.Aliased<'ATOM' | 'HETATM'>(Column.Schema.str)),
|
||||
label_comp_id: atomsData.residueName,
|
||||
auth_comp_id: atomsData.residueName,
|
||||
label_seq_id: atomsData.residueNumber,
|
||||
auth_seq_id: atomsData.residueNumber,
|
||||
pdbx_PDB_ins_code: Column.Undefined(atomsData.count, Column.Schema.str),
|
||||
}), AtomicHierarchy.ResiduesSchema, offsets.residues);
|
||||
}), ResiduesSchema, offsets.residues);
|
||||
// Optimize the numeric columns
|
||||
Table.columnToArray(residues, 'label_seq_id', Int32Array);
|
||||
Table.columnToArray(residues, 'auth_seq_id', Int32Array);
|
||||
@@ -72,7 +72,7 @@ function createHierarchyData(atomsData: Atoms, offsets: HierarchyOffsets): Atomi
|
||||
// label_entity_id: Column.Undefined(atomsData.count, Column.Schema.str)
|
||||
// });
|
||||
|
||||
const chains = Table.ofUndefinedColumns(AtomicHierarchy.ChainsSchema, 0);
|
||||
const chains = Table.ofUndefinedColumns(ChainsSchema, 0);
|
||||
|
||||
return { atoms, residues, chains };
|
||||
}
|
||||
@@ -89,10 +89,10 @@ function getConformation(atoms: Atoms): AtomicConformation {
|
||||
}
|
||||
}
|
||||
|
||||
function isHierarchyDataEqual(a: AtomicHierarchy.AtomicData, b: AtomicHierarchy.AtomicData) {
|
||||
function isHierarchyDataEqual(a: AtomicData, b: AtomicData) {
|
||||
// need to cast because of how TS handles type resolution for interfaces https://github.com/Microsoft/TypeScript/issues/15300
|
||||
return Table.areEqual(a.residues as Table<AtomicHierarchy.ResiduesSchema>, b.residues as Table<AtomicHierarchy.ResiduesSchema>)
|
||||
&& Table.areEqual(a.atoms as Table<AtomicHierarchy.AtomsSchema>, b.atoms as Table<AtomicHierarchy.AtomsSchema>)
|
||||
return Table.areEqual(a.residues as Table<ResiduesSchema>, b.residues as Table<ResiduesSchema>)
|
||||
&& Table.areEqual(a.atoms as Table<AtomsSchema>, b.atoms as Table<AtomsSchema>)
|
||||
}
|
||||
|
||||
function createModel(format: gro_Format, modelNum: number, previous?: Model): Model {
|
||||
@@ -109,7 +109,7 @@ function createModel(format: gro_Format, modelNum: number, previous?: Model): Mo
|
||||
};
|
||||
}
|
||||
|
||||
const hierarchySegments: AtomicHierarchy.AtomicSegments = {
|
||||
const hierarchySegments: AtomicSegments = {
|
||||
residueSegments: Segmentation.ofOffsets(hierarchyOffsets.residues, bounds),
|
||||
chainSegments: Segmentation.ofOffsets(hierarchyOffsets.chains, bounds),
|
||||
}
|
||||
@@ -135,7 +135,7 @@ function createModel(format: gro_Format, modelNum: number, previous?: Model): Mo
|
||||
sequence: Sequence.fromAtomicHierarchy(hierarchy),
|
||||
atomSiteConformation: getConformation(structure.atoms),
|
||||
coarseGrained: CoarseGrainedHierarchy.Empty,
|
||||
symmetry: { assemblies: [] },
|
||||
symmetry: ModelSymmetry.Default,
|
||||
atomCount: structure.atoms.count
|
||||
};
|
||||
}
|
||||
|
||||
@@ -9,9 +9,8 @@ import { Column, Table } from 'mol-data/db'
|
||||
import { Interval, Segmentation } from 'mol-data/int'
|
||||
import Format from '../format'
|
||||
import Model from '../model'
|
||||
import { AtomsSchema, ResiduesSchema, ChainsSchema, AtomicData, AtomicSegments } from '../properties/atomic/hierarchy'
|
||||
import { AtomicConformation } from '../properties/atomic/conformation'
|
||||
import Symmetry from '../properties/symmetry'
|
||||
import { AtomsSchema, ResiduesSchema, ChainsSchema, AtomicData, AtomicSegments, AtomicConformation } from '../properties/atomic'
|
||||
import { ModelSymmetry } from '../properties/symmetry'
|
||||
import findHierarchyKeys from '../utils/hierarchy-keys'
|
||||
import { ElementSymbol} from '../types'
|
||||
import createAssemblies from './mmcif/assembly'
|
||||
@@ -20,6 +19,8 @@ import mmCIF_Format = Format.mmCIF
|
||||
import { getSequence } from './mmcif/sequence';
|
||||
import { Entities } from '../properties/common';
|
||||
import { coarseGrainedFromIHM } from './mmcif/ihm';
|
||||
import { Spacegroup, SpacegroupCell } from 'mol-math/geometry';
|
||||
import { Vec3 } from 'mol-math/linear-algebra';
|
||||
|
||||
function findModelBounds({ data }: mmCIF_Format, startIndex: number) {
|
||||
const num = data.atom_site.pdbx_PDB_model_num;
|
||||
@@ -83,8 +84,29 @@ function getConformation({ data }: mmCIF_Format, bounds: Interval): AtomicConfor
|
||||
}
|
||||
}
|
||||
|
||||
function getSymmetry(format: mmCIF_Format): Symmetry {
|
||||
return { assemblies: createAssemblies(format) };
|
||||
function getSymmetry(format: mmCIF_Format): ModelSymmetry {
|
||||
const assemblies = createAssemblies(format);
|
||||
const spacegroup = getSpacegroup(format);
|
||||
const isNonStandardCrytalFrame = checkNonStandardCrystalFrame(format, spacegroup);
|
||||
return { assemblies, spacegroup, isNonStandardCrytalFrame };
|
||||
}
|
||||
|
||||
function checkNonStandardCrystalFrame(format: mmCIF_Format, spacegroup: Spacegroup) {
|
||||
const { atom_sites } = format.data;
|
||||
if (atom_sites._rowCount === 0) return false;
|
||||
// TODO: parse atom_sites transform and check if it corresponds to the toFractional matrix
|
||||
return false;
|
||||
}
|
||||
|
||||
function getSpacegroup(format: mmCIF_Format): Spacegroup {
|
||||
const { symmetry, cell } = format.data;
|
||||
if (symmetry._rowCount === 0 || cell._rowCount === 0) return Spacegroup.ZeroP1;
|
||||
const groupName = symmetry['space_group_name_H-M'].value(0);
|
||||
const spaceCell = SpacegroupCell.create(groupName,
|
||||
Vec3.create(cell.length_a.value(0), cell.length_b.value(0), cell.length_c.value(0)),
|
||||
Vec3.scale(Vec3.zero(), Vec3.create(cell.angle_alpha.value(0), cell.angle_beta.value(0), cell.angle_gamma.value(0)), Math.PI / 180));
|
||||
|
||||
return Spacegroup.create(spaceCell);
|
||||
}
|
||||
|
||||
function isHierarchyDataEqual(a: AtomicData, b: AtomicData) {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import { mmCIF_Database as mmCIF } from 'mol-io/reader/cif/schema/mmcif'
|
||||
import Sequence from '../../properties/sequence'
|
||||
import { Column } from 'mol-data/db';
|
||||
import { AtomicHierarchy } from '../../properties/atomic/hierarchy';
|
||||
import { AtomicHierarchy } from '../../properties/atomic';
|
||||
import { Entities } from '../../properties/common';
|
||||
|
||||
export function getSequence(cif: mmCIF, entities: Entities, hierarchy: AtomicHierarchy): Sequence {
|
||||
|
||||
@@ -7,9 +7,8 @@
|
||||
import UUID from 'mol-util/uuid'
|
||||
import Format from './format'
|
||||
import Sequence from './properties/sequence'
|
||||
import { AtomicHierarchy } from './properties/atomic/hierarchy'
|
||||
import { AtomicConformation } from './properties/atomic/conformation'
|
||||
import Symmetry from './properties/symmetry'
|
||||
import { AtomicHierarchy, AtomicConformation } from './properties/atomic'
|
||||
import { ModelSymmetry } from './properties/symmetry'
|
||||
import { CoarseGrainedHierarchy } from './properties/coarse-grained/hierarchy'
|
||||
import { Entities } from './properties/common';
|
||||
|
||||
@@ -28,7 +27,7 @@ interface Model extends Readonly<{
|
||||
|
||||
sourceData: Format,
|
||||
|
||||
symmetry: Symmetry,
|
||||
symmetry: ModelSymmetry,
|
||||
entities: Entities,
|
||||
sequence: Sequence,
|
||||
|
||||
|
||||
9
src/mol-model/structure/model/properties/atomic.ts
Normal file
9
src/mol-model/structure/model/properties/atomic.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author David Sehnal <david.sehnal@gmail.com>
|
||||
*/
|
||||
|
||||
export * from './atomic/conformation'
|
||||
export * from './atomic/hierarchy'
|
||||
export * from './atomic/measures'
|
||||
@@ -8,6 +8,7 @@ import { SymmetryOperator } from 'mol-math/geometry/symmetry-operator'
|
||||
import { arrayFind } from 'mol-data/util'
|
||||
import { Query } from '../../query'
|
||||
import { Model } from '../../model'
|
||||
import { Spacegroup } from 'mol-math/geometry';
|
||||
|
||||
/** Determine an atom set and a list of operators that should be applied to that set */
|
||||
export interface OperatorGroup {
|
||||
@@ -40,12 +41,14 @@ export namespace Assembly {
|
||||
}
|
||||
}
|
||||
|
||||
interface Symmetry {
|
||||
interface ModelSymmetry {
|
||||
readonly assemblies: ReadonlyArray<Assembly>,
|
||||
readonly spacegroup: Spacegroup,
|
||||
readonly isNonStandardCrytalFrame: boolean
|
||||
}
|
||||
|
||||
namespace Symmetry {
|
||||
export const Empty: Symmetry = { assemblies: [] };
|
||||
namespace ModelSymmetry {
|
||||
export const Default: ModelSymmetry = { assemblies: [], spacegroup: Spacegroup.ZeroP1, isNonStandardCrytalFrame: false };
|
||||
|
||||
export function findAssembly(model: Model, id: string): Assembly | undefined {
|
||||
const _id = id.toLocaleLowerCase();
|
||||
@@ -53,4 +56,4 @@ namespace Symmetry {
|
||||
}
|
||||
}
|
||||
|
||||
export default Symmetry
|
||||
export { ModelSymmetry }
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
import { Column } from 'mol-data/db'
|
||||
import { AtomicData, AtomicSegments, AtomicKeys } from '../properties/atomic/hierarchy'
|
||||
import { AtomicData, AtomicSegments, AtomicKeys } from '../properties/atomic'
|
||||
import { Interval, Segmentation } from 'mol-data/int'
|
||||
import { Entities } from '../properties/common';
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
import { Element, Unit } from '../structure'
|
||||
import { VdwRadius } from '../model/properties/atomic/measures';
|
||||
import { VdwRadius } from '../model/properties/atomic';
|
||||
|
||||
const constant = {
|
||||
true: Element.property(l => true),
|
||||
|
||||
@@ -11,15 +11,17 @@ import { Task } from 'mol-task';
|
||||
import { SortedArray } from 'mol-data/int';
|
||||
import Unit from './unit';
|
||||
import { EquivalenceClasses, hash2 } from 'mol-data/util';
|
||||
import { Vec3 } from 'mol-math/linear-algebra';
|
||||
import { SymmetryOperator, Spacegroup, SpacegroupCell } from 'mol-math/geometry';
|
||||
|
||||
namespace StructureSymmetry {
|
||||
export function buildAssembly(structure: Structure, name: string) {
|
||||
return Task.create('Build Symmetry', async ctx => {
|
||||
export function buildAssembly(structure: Structure, asmName: string) {
|
||||
return Task.create('Build Assembly', async ctx => {
|
||||
const models = Structure.getModels(structure);
|
||||
if (models.length !== 1) throw new Error('Can only build assemblies from structures based on 1 model.');
|
||||
|
||||
const assembly = ModelSymmetry.findAssembly(models[0], name);
|
||||
if (!assembly) throw new Error(`Assembly '${name}' is not defined.`);
|
||||
const assembly = ModelSymmetry.findAssembly(models[0], asmName);
|
||||
if (!assembly) throw new Error(`Assembly '${asmName}' is not defined.`);
|
||||
|
||||
const assembler = Structure.Builder();
|
||||
|
||||
@@ -41,6 +43,38 @@ namespace StructureSymmetry {
|
||||
});
|
||||
}
|
||||
|
||||
export function buildSymmetryRange(structure: Structure, ijkMin: Vec3, ijkMax: Vec3) {
|
||||
return Task.create('Build Assembly', async ctx => {
|
||||
const models = Structure.getModels(structure);
|
||||
if (models.length !== 1) throw new Error('Can only build symmetries from structures based on 1 model.');
|
||||
|
||||
const { spacegroup } = models[0].symmetry;
|
||||
if (SpacegroupCell.isZero(spacegroup.cell)) return structure;
|
||||
|
||||
const operators: SymmetryOperator[] = [];
|
||||
for (let op = 0; op < spacegroup.operators.length; op++) {
|
||||
for (let i = ijkMin[0]; i < ijkMax[0]; i++) {
|
||||
for (let j = ijkMin[1]; j < ijkMax[1]; j++) {
|
||||
for (let k = ijkMin[2]; k < ijkMax[2]; k++) {
|
||||
operators[operators.length] = Spacegroup.getSymmetryOperator(spacegroup, op, i, j, k);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const assembler = Structure.Builder();
|
||||
|
||||
const { units } = structure;
|
||||
for (const oper of operators) {
|
||||
for (const unit of units) {
|
||||
assembler.addWithOperator(unit, oper);
|
||||
}
|
||||
}
|
||||
|
||||
return assembler.getStructure();
|
||||
});
|
||||
}
|
||||
|
||||
function hashUnit(u: Unit) {
|
||||
return hash2(u.invariantId, SortedArray.hashCode(u.elements));
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import { Structure, Model, Queries as Q, Element, Selection, StructureSymmetry,
|
||||
|
||||
import to_mmCIF from 'mol-model/structure/export/mmcif'
|
||||
import { Run } from 'mol-task';
|
||||
import { Vec3 } from 'mol-math/linear-algebra';
|
||||
//import { EquivalenceClasses } from 'mol-data/util';
|
||||
|
||||
require('util.promisify').shim();
|
||||
@@ -302,6 +303,19 @@ export namespace PropertyAccess {
|
||||
console.log('exported');
|
||||
}
|
||||
|
||||
export async function testSymmetry(id: string, s: Structure) {
|
||||
console.time('symmetry')
|
||||
const a = await Run(StructureSymmetry.buildSymmetryRange(s, Vec3.create(-1, -1, -1), Vec3.create(1, 1, 1)));
|
||||
//const auth_comp_id = Q.props.residue.auth_comp_id;
|
||||
//const q1 = Query(Q.generators.atoms({ residueTest: l => auth_comp_id(l) === 'ALA' }));
|
||||
//const alas = await query(q1, a);
|
||||
|
||||
console.timeEnd('symmetry')
|
||||
fs.writeFileSync(`${DATA_DIR}/${id}_symm.bcif`, to_mmCIF(id, a, true));
|
||||
//fs.writeFileSync(`${DATA_DIR}/${id}_assembly.bcif`, to_mmCIF(id, Selection.unionStructure(alas), true));
|
||||
console.log('exported');
|
||||
}
|
||||
|
||||
// export async function testGrouping(structure: Structure) {
|
||||
// const { elements, units } = await Run(Symmetry.buildAssembly(structure, '1'));
|
||||
// console.log('grouping', units.length);
|
||||
@@ -329,7 +343,7 @@ export namespace PropertyAccess {
|
||||
//const { structures, models/*, mmcif*/ } = await getBcif('1cbs');
|
||||
// const { structures, models } = await getBcif('3j3q');
|
||||
|
||||
const { structures, models /*, mmcif*/ } = await readCIF('e:/test/quick/1hrv_updated.cif');
|
||||
const { structures, models /*, mmcif*/ } = await readCIF('e:/test/quick/1cbs_updated.cif');
|
||||
//const { structures: s1, /*, mmcif*/ } = await readCIF('e:/test/quick/1tqn_updated.cif');
|
||||
|
||||
// testGrouping(structures[0]);
|
||||
@@ -340,7 +354,8 @@ export namespace PropertyAccess {
|
||||
//console.log(mmcif.pdbx_struct_oper_list.matrix.toArray());
|
||||
// console.log(mmcif.pdbx_struct_oper_list.vector.toArray());
|
||||
|
||||
await testAssembly('1hrv', structures[0]);
|
||||
//await testAssembly('1hrv', structures[0]);
|
||||
await testSymmetry('1cbs', structures[0]);
|
||||
// throw '';
|
||||
|
||||
// console.log(models[0].symmetry.assemblies);
|
||||
|
||||
Reference in New Issue
Block a user