All files / src/parsers/utils computeSecondaryStructure.ts

98.3% Statements 58/59
96.96% Branches 32/33
100% Functions 1/1
100% Lines 50/50

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      308x     308x         308x 20108x   20108x   20108x 678x 678x   678x   477x           308x 308x 717x 717x 717x 717x 48x           308x 20108x   20108x         192x         308x 20108x   20108x       69x 69x 69x   63x 63x           308x 308x 888x 888x 888x 888x 39x     308x 906x 906x 561x 15x           308x 20108x 20108x     20108x 20108x 20108x 5004x 5004x 5004x      
import { assignBackboneHBonds } from "./assignBackboneHBonds";
 
export function computeSecondaryStructure(atomsarray, hbondCutoff) {
  assignBackboneHBonds(atomsarray, hbondCutoff);
 
  // compute, per residue, what the secondary structure is
  var chres = {}; // lookup by chain and resid
  var i, il, c, r; // i: used in for loop, il: length of atomsarray
  var atom, val;
 
  //identify helices first
  for (i = 0, il = atomsarray.length; i < il; i++) {
    atom = atomsarray[i];
 
    if (typeof chres[atom.chain] === "undefined") chres[atom.chain] = [];
 
    if (isFinite(atom.hbondDistanceSq)) {
      var other = atom.hbondOther;
      Iif (typeof chres[other.chain] === "undefined") chres[other.chain] = [];
 
      if (Math.abs(other.resi - atom.resi) === 4) {
        // helix
        chres[atom.chain][atom.resi] = "h";
      }
    }
  }
 
  // plug gaps in helices
  for (c in chres) {
    for (r = 1; r < chres[c].length - 1; r++) {
      var valbefore = chres[c][r - 1];
      var valafter = chres[c][r + 1];
      val = chres[c][r];
      if (valbefore == "h" && valbefore == valafter && val != valbefore) {
        chres[c][r] = valbefore;
      }
    }
  }
 
  //now potential sheets - but only if mate not part of helix
  for (i = 0, il = atomsarray.length; i < il; i++) {
    atom = atomsarray[i];
 
    if (
      isFinite(atom.hbondDistanceSq) &&
      chres[atom.chain][atom.resi] != "h" &&
      atom.ss != "h"
    ) {
      chres[atom.chain][atom.resi] = "maybesheet";
    }
  }
 
  //sheets must bond to other sheets
  for (let i = 0, il = atomsarray.length; i < il; i++) {
    atom = atomsarray[i];
 
    if (
      isFinite(atom.hbondDistanceSq) &&
      chres[atom.chain][atom.resi] == "maybesheet"
    ) {
      let other = atom.hbondOther;
      let otherval = chres[other.chain][other.resi];
      if (otherval == "maybesheet" || otherval == "s") {
        // true sheet
        chres[atom.chain][atom.resi] = "s";
        chres[other.chain][other.resi] = "s";
      }
    }
  }
 
  // plug gaps in sheets and remove singletons
  for (let c in chres) {
    for (let r = 1; r < chres[c].length - 1; r++) {
      let valbefore = chres[c][r - 1];
      let valafter = chres[c][r + 1];
      val = chres[c][r];
      if (valbefore == "s" && valbefore == valafter && val != valbefore) {
        chres[c][r] = valbefore;
      }
    }
    for (let r = 0; r < chres[c].length; r++) {
      let val = chres[c][r];
      if (val == "h" || val == "s") {
        if (chres[c][r - 1] != val && chres[c][r + 1] != val)
          delete chres[c][r];
      }
    }
  }
 
  // assign to all atoms in residue, keep track of start
  for (i = 0, il = atomsarray.length; i < il; i++) {
    atom = atomsarray[i];
    val = chres[atom.chain][atom.resi];
 
    //clear hbondOther to eliminate circular references that prohibit serialization
    delete atom.hbondOther;
    delete atom.hbondDistanceSq;
    if (typeof val == "undefined" || val == "maybesheet") continue;
    atom.ss = val;
    if (chres[atom.chain][atom.resi - 1] != val) atom.ssbegin = true;
    if (chres[atom.chain][atom.resi + 1] != val) atom.ssend = true;
  }
}