# All files / src/parsers/utils processSymmetries.ts

16% Statements 12/75
20% Branches 3/15
100% Functions 1/1
16.21% Lines 12/74

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128

    295x
    295x
    295x

    295x
    295x

    295x

    98x
    4214x

    98x

    98x

    98x
    197x

     import { Matrix3, conversionMatrix3, Vector3 } from '../../WebGL';
    //adds symmetry info to either duplicate and rotate/translate biological unit later or add extra atoms now
    //matrices may be modified if normalization is requested
    export function processSymmetries(copyMatrices, atoms, options, cryst) {
      var dontDuplicate = !options.duplicateAssemblyAtoms;
      var end = atoms.length;
      var offset = end;
      var t, l, n; // Used in for loops

      let modifiedIdentity = -1;
      Iif (options.normalizeAssembly && cryst) {
        //to normalize, translate every symmetry so that the centroid is
        //in the unit cell.  To do this, convert back to fractional coordinates,
        //compute the centroid, calculate any adjustment needed to get it in [0,1],
        //convert the adjustment to a cartesian translation, and then add it to
        //the symmetry matrix
        let conversionMatrix = conversionMatrix3(
          cryst.a,
          cryst.b,
          cryst.c,
          cryst.alpha,
          cryst.beta,
          cryst.gamma
        );
        let toFrac = new Matrix3();
        toFrac.getInverse3(conversionMatrix);

        for (t = 0; t < copyMatrices.length; t++) {
          //transform with the symmetry, and then back to fractional coordinates
          let center = new Vector3(0, 0, 0);
          for (n = 0; n < end; n++) {
            let xyz = new Vector3(atoms[n].x, atoms[n].y, atoms[n].z);
            xyz.applyMatrix4(copyMatrices[t]);
            xyz.applyMatrix3(toFrac);
            //figure out
            center.add(xyz);
          }
          center.divideScalar(end);
          const centerCoord = [center.x, center.y, center.z];
          let adjustment = [0.0, 0.0, 0.0];
          for (let i = 0; i < 3; i++) {
            while (centerCoord[i] < -0.001) {
              centerCoord[i] += 1.0;
              adjustment[i] += 1.0;
            }
            while (centerCoord[i] > 1.001) {
              centerCoord[i] -= 1.0;
              adjustment[i] -= 1.0;
            }
          }
          //convert adjustment to non-fractional
          const adjustmentVec = new Vector3(
            adjustment[0],
            adjustment[1],
            adjustment[2]
          );
          adjustmentVec.applyMatrix3(conversionMatrix);
          //modify symmetry matrix to include translation
          Iif (copyMatrices[t].isNearlyIdentity() && adjustmentVec.lengthSq() > 0.001) {
            modifiedIdentity = t; //keep track of which matrix was identity
          }
          copyMatrices[t].translate(adjustmentVec);
        }
      }
      if (!dontDuplicate) {
        // do full assembly
        for (n = 0; n < end; n++) {
          atoms[n].sym = -1; //if identity matrix is present, original labeled -1
        }
        for (t = 0; t < copyMatrices.length; t++) {
          if (!copyMatrices[t].isNearlyIdentity() && modifiedIdentity != t) {
            let xyz = new Vector3();
            for (n = 0; n < end; n++) {
              var bondsArr: any[] = [];
              for (l = 0; l < atoms[n].bonds.length; l++) {
                bondsArr.push(atoms[n].bonds[l] + offset);
              }
              xyz.set(atoms[n].x, atoms[n].y, atoms[n].z);
              xyz.applyMatrix4(copyMatrices[t]);

              var newAtom: Record<string, unknown> = {};
              for (var i in atoms[n]) {
                newAtom[i] = atoms[n][i];
              }
              newAtom.x = xyz.x;
              newAtom.y = xyz.y;
              newAtom.z = xyz.z;
              newAtom.bonds = bondsArr;
              newAtom.sym = t; //so symmetries can be selected
              newAtom.index = atoms.length;
              atoms.push(newAtom);
            }
            offset = atoms.length;
          } else {
            for (n = 0; n < end; n++) {
              atoms[n].sym = t;
            }
          }
        }
        Iif (modifiedIdentity >= 0) {
          //after applying the other transformations, apply this one in place
          let xyz = new Vector3();
          for (n = 0; n < end; n++) {
            xyz.set(atoms[n].x, atoms[n].y, atoms[n].z);
            xyz.applyMatrix4(copyMatrices[modifiedIdentity]);
            atoms[n].x = xyz.x;
            atoms[n].y = xyz.y;
            atoms[n].z = xyz.z;
          }
        }
        //we have explicitly duplicated the atoms, remove model symmetry information
        copyMatrices.length = 0;
      } else Iif (copyMatrices.length > 1) {
        for (t = 0; t < atoms.length; t++) {
          var symmetries: Vector3[] = [];
          for (l = 0; l < copyMatrices.length; l++) {
            Iif (!copyMatrices[l].isNearlyIdentity()) {
              var newXYZ = new Vector3();
              newXYZ.set(atoms[t].x, atoms[t].y, atoms[t].z);
              newXYZ.applyMatrix4(copyMatrices[l]);
              symmetries.push(newXYZ);
            }
          }
          atoms[t].symmetries = symmetries;
        }
      }
    }