Преглед изворни кода

SymmetryOperator.create refactor, added SymmetryOperator.suffix

David Sehnal пре 5 година
родитељ
комит
0eb3d7226a

+ 1 - 1
src/apps/viewer/extensions/cellpack/model.ts

@@ -111,7 +111,7 @@ function getAssembly(transforms: Mat4[], structure: Structure) {
 
     for (let i = 0, il = transforms.length; i < il; ++i) {
         const id = `${i + 1}`
-        const op = SymmetryOperator.create(id, transforms[i], { id, operList: [ id ] })
+        const op = SymmetryOperator.create(id, transforms[i], { assembly: { id, operIndex: i, operList: [ id ] } })
         for (const unit of units) {
             builder.addWithOperator(unit, op)
         }

+ 6 - 6
src/mol-math/geometry/spacegroup/construction.ts

@@ -104,9 +104,9 @@ namespace Spacegroup {
         );
     }
 
-    export function getSymmetryOperator(spacegroup: Spacegroup, index: number, i: number, j: number, k: number): SymmetryOperator {
-        const operator = setOperatorMatrix(spacegroup, index, i, j, k, Mat4.zero());
-        return SymmetryOperator.create(`${index + 1}_${5 + i}${5 + j}${5 + k}`, operator, { id: '', operList: [] }, '', Vec3.create(i, j, k), index);
+    export function getSymmetryOperator(spacegroup: Spacegroup, spgrOp: number, i: number, j: number, k: number): SymmetryOperator {
+        const operator = setOperatorMatrix(spacegroup, spgrOp, i, j, k, Mat4.zero());
+        return SymmetryOperator.create(`${spgrOp + 1}_${5 + i}${5 + j}${5 + k}`, operator, { hkl: Vec3.create(i, j, k), spgrOp });
     }
 
     const _translationRef = Vec3()
@@ -135,9 +135,9 @@ namespace Spacegroup {
      * Get Symmetry operator for transformation around the given
      * reference point `ref` in fractional coordinates
      */
-    export function getSymmetryOperatorRef(spacegroup: Spacegroup, index: number, i: number, j: number, k: number, ref: Vec3) {
-        const operator = setOperatorMatrixRef(spacegroup, index, i, j, k, ref, Mat4.zero());
-        return SymmetryOperator.create(`${index + 1}_${5 + i}${5 + j}${5 + k}`, operator, { id: '', operList: [] }, '', Vec3.create(i, j, k), index);
+    export function getSymmetryOperatorRef(spacegroup: Spacegroup, spgrOp: number, i: number, j: number, k: number, ref: Vec3) {
+        const operator = setOperatorMatrixRef(spacegroup, spgrOp, i, j, k, ref, Mat4.zero());
+        return SymmetryOperator.create(`${spgrOp + 1}_${5 + i}${5 + j}${5 + k}`, operator, { hkl: Vec3.create(i, j, k), spgrOp });
     }
 
     function getOperatorMatrix(ids: number[]) {

+ 45 - 11
src/mol-math/geometry/symmetry-operator.ts

@@ -13,10 +13,12 @@ interface SymmetryOperator {
 
     readonly assembly?: {
         /** pointer to `pdbx_struct_assembly.id` or empty string */
-        readonly id: string
+        readonly id: string,
         /** pointers to `pdbx_struct_oper_list.id` or empty list */
-        readonly operList: string[]
-    }
+        readonly operList: string[],
+        /** (arbitrary) index of the operator to be used in suffix */
+        readonly operIndex: number
+    },
 
     /** pointer to `struct_ncs_oper.id` or empty string */
     readonly ncsId: string,
@@ -29,7 +31,16 @@ interface SymmetryOperator {
     // cache the inverse of the transform
     readonly inverse: Mat4,
     // optimize the identity case
-    readonly isIdentity: boolean
+    readonly isIdentity: boolean,
+
+    /**
+     * Suffix based on operator type.
+     * - Empty if isIdentity
+     * - Assembly: _{assembly.operIndex + 1}
+     * - Crytal: -op_ijk
+     * - ncs: _ncsId
+     */
+    readonly suffix: string
 }
 
 namespace SymmetryOperator {
@@ -38,13 +49,36 @@ namespace SymmetryOperator {
 
     export const RotationTranslationEpsilon = 0.005;
 
-    export function create(name: string, matrix: Mat4, assembly?: SymmetryOperator['assembly'], ncsId?: string, hkl?: Vec3, spgrOp?: number): SymmetryOperator {
+    export type CreateInfo = { assembly?: SymmetryOperator['assembly'], ncsId?: string, hkl?: Vec3, spgrOp?: number }
+    export function create(name: string, matrix: Mat4, info?: CreateInfo): SymmetryOperator {
+        let { assembly, ncsId, hkl, spgrOp } = info || { };
         const _hkl = hkl ? Vec3.clone(hkl) : Vec3.zero();
-        spgrOp = defaults(spgrOp, -1)
-        ncsId = ncsId || ''
-        if (Mat4.isIdentity(matrix)) return { name, assembly, matrix, inverse: Mat4.identity(), isIdentity: true, hkl: _hkl, spgrOp, ncsId };
+        spgrOp = defaults(spgrOp, -1);
+        ncsId = ncsId || '';
+        const isIdentity = Mat4.isIdentity(matrix);
+        const suffix = getSuffix(isIdentity, info);
+        if (Mat4.isIdentity(matrix)) return { name, assembly, matrix, inverse: Mat4.identity(), isIdentity: true, hkl: _hkl, spgrOp, ncsId, suffix };
         if (!Mat4.isRotationAndTranslation(matrix, RotationTranslationEpsilon)) throw new Error(`Symmetry operator (${name}) must be a composition of rotation and translation.`);
-        return { name, assembly, matrix, inverse: Mat4.invert(Mat4.zero(), matrix), isIdentity: false, hkl: _hkl, spgrOp, ncsId };
+        return { name, assembly, matrix, inverse: Mat4.invert(Mat4.zero(), matrix), isIdentity: false, hkl: _hkl, spgrOp, ncsId, suffix };
+    }
+
+    function getSuffix(isIdentity: boolean, info?: CreateInfo) {
+        if (!info || isIdentity) return '';
+
+        if (info.assembly) {
+            return `_${info.assembly.operIndex + 1}`;
+        }
+
+        if (typeof info.spgrOp !== 'undefined' && typeof info.hkl !== 'undefined' && info.spgrOp !== -1) {
+            const [i, j, k] = info.hkl;
+            return `-${info.spgrOp + 1}_${5 + i}${5 + j}${5 + k}`
+        }
+
+        if (info.ncsId) {
+            return `_${info.ncsId}`;
+        }
+
+        return '';
     }
 
     export function checkIfRotationAndTranslation(rot: Mat3, offset: Vec3) {
@@ -66,7 +100,7 @@ namespace SymmetryOperator {
             }
         }
         Mat4.setTranslation(t, offset);
-        return create(name, t, { id: '', operList: [] }, ncsId);
+        return create(name, t, { ncsId });
     }
 
     const _q1 = Quat.identity(), _q2 = Quat.zero(), _q3 = Quat.zero(), _axis = Vec3.zero();
@@ -114,7 +148,7 @@ namespace SymmetryOperator {
      */
     export function compose(first: SymmetryOperator, second: SymmetryOperator) {
         const matrix = Mat4.mul(Mat4.zero(), second.matrix, first.matrix);
-        return create(second.name, matrix, second.assembly, second.ncsId, second.hkl, second.spgrOp);
+        return create(second.name, matrix, second);
     }
 
     export interface CoordinateMapper<T extends number> { (index: T, slot: Vec3): Vec3 }

+ 1 - 1
src/mol-model-formats/structure/property/assembly.ts

@@ -117,7 +117,7 @@ function getAssemblyOperators(matrices: Matrices, operatorNames: string[][], sta
             Mat4.mul(m, m, matrices.get(op[i])!);
         }
         index++
-        operators[operators.length] = SymmetryOperator.create(`ASM_${index}`, m, { id: assemblyId, operList: op });
+        operators[operators.length] = SymmetryOperator.create(`ASM_${index}`, m, { assembly: { id: assemblyId, operIndex: index, operList: op } });
     }
 
     return operators;

+ 2 - 2
src/mol-model/structure/structure/structure.ts

@@ -775,12 +775,12 @@ namespace Structure {
         const units: Unit[] = [];
         for (const u of s.units) {
             const old = u.conformation.operator;
-            const op = SymmetryOperator.create(old.name, transform, old.assembly, old.ncsId, old.hkl);
+            const op = SymmetryOperator.create(old.name, transform, old);
             units.push(u.applyOperator(u.id, op));
         }
 
         const cs = s.coordinateSystem;
-        const newCS = SymmetryOperator.compose(SymmetryOperator.create(cs.name, transform, cs.assembly, cs.ncsId, cs.hkl), cs);
+        const newCS = SymmetryOperator.compose(SymmetryOperator.create(cs.name, transform, cs), cs);
         return new Structure(units, { parent: s, coordinateSystem: newCS });
     }
 

+ 7 - 2
src/mol-model/structure/structure/symmetry.ts

@@ -26,7 +26,7 @@ namespace StructureSymmetry {
             const assembly = Symmetry.findAssembly(models[0], asmName);
             if (!assembly) throw new Error(`Assembly '${asmName}' is not defined.`);
 
-            const coordinateSystem = SymmetryOperator.create(assembly.id, Mat4.identity(), { id: assembly.id, operList: [] })
+            const coordinateSystem = SymmetryOperator.create(assembly.id, Mat4.identity(), { assembly: { id: assembly.id, operIndex: 0, operList: [] } })
             const assembler = Structure.Builder({ coordinateSystem, label: structure.label });
 
             const queryCtx = new QueryContext(structure);
@@ -150,7 +150,12 @@ function getOperatorsForIndex(symmetry: Symmetry, index: number, i: number, j: n
         for (let u = 0, ul = ncsOperators.length; u < ul; ++u) {
             const ncsOp = ncsOperators![u]
             const matrix = Mat4.mul(Mat4(), symOp.matrix, ncsOp.matrix)
-            const operator = SymmetryOperator.create(`${symOp.name} ${ncsOp.name}`, matrix, symOp.assembly, ncsOp.ncsId, symOp.hkl, symOp.spgrOp);
+            const operator = SymmetryOperator.create(`${symOp.name} ${ncsOp.name}`, matrix, {
+                assembly: symOp.assembly,
+                ncsId: ncsOp.ncsId,
+                hkl: symOp.hkl,
+                spgrOp: symOp.spgrOp
+            });
             operators.push(operator)
         }
     } else {