diff --git a/src/mol-math/linear-algebra/3d/vec3.ts b/src/mol-math/linear-algebra/3d/vec3.ts index 59308ddf0d462e45949f052c377f750cbf9c22cf..bb16cc3530375060824f061d2a8176b4112b2325 100644 --- a/src/mol-math/linear-algebra/3d/vec3.ts +++ b/src/mol-math/linear-algebra/3d/vec3.ts @@ -434,6 +434,28 @@ namespace Vec3 { } } + const tmp_dh_ab = Vec3.zero(); + const tmp_dh_cb = Vec3.zero(); + const tmp_dh_bc = Vec3.zero(); + const tmp_dh_dc = Vec3.zero(); + const tmp_dh_abc = Vec3.zero(); + const tmp_dh_bcd = Vec3.zero(); + const tmp_dh_cross = Vec3.zero(); + /** Computes the dihedral angles of 4 related atoms. phi: C, N+1, CA+1, C+1 - psi: N, CA, C, N+1 - omega: CA, C, N+1, CA+1 */ + export function dihedralAngle(a: Vec3, b: Vec3, c: Vec3, d: Vec3) { + Vec3.sub(tmp_dh_ab, a, b); + Vec3.sub(tmp_dh_cb, c, b); + Vec3.sub(tmp_dh_bc, b, c); + Vec3.sub(tmp_dh_dc, d, c); + + Vec3.cross(tmp_dh_abc, tmp_dh_ab, tmp_dh_cb); + Vec3.cross(tmp_dh_bcd, tmp_dh_bc, tmp_dh_dc); + + const angle = Vec3.angle(tmp_dh_abc, tmp_dh_bcd) * 360.0 / (2 * Math.PI); + Vec3.cross(tmp_dh_cross, tmp_dh_abc, tmp_dh_bcd); + return Vec3.dot(tmp_dh_cb, tmp_dh_cross) > 0 ? angle : -angle; + } + /** * Returns whether or not the vectors have exactly the same elements in the same position (when compared with ===) */ diff --git a/src/mol-model/structure/model/properties/utils/secondary-structure.ts b/src/mol-model/structure/model/properties/utils/secondary-structure.ts index 5192456d500f7f3dc77130fd2ef82be861565cf1..cbc23b4db5f283a2dbbc3a4ba38529e754ddf78f 100644 --- a/src/mol-model/structure/model/properties/utils/secondary-structure.ts +++ b/src/mol-model/structure/model/properties/utils/secondary-structure.ts @@ -407,11 +407,11 @@ function calculateDihedralAngles(hierarchy: AtomicHierarchy, conformation: Atomi // angle calculations return NaN upon missing atoms // TODO would be nice to be provided elsewhere, omega is related but not needed here function calculatePhi(c: Vec3, nNext: Vec3, caNext: Vec3, cNext: Vec3) { - return angle(c, nNext, caNext, cNext); + return Vec3.dihedralAngle(c, nNext, caNext, cNext); } function calculatePsi(n: Vec3, ca: Vec3, c: Vec3, nNext: Vec3) { - return angle(n, ca, c, nNext); + return Vec3.dihedralAngle(n, ca, c, nNext); } // function calculateOmega(ca: Vec3, c: Vec3, nNext: Vec3, caNext: Vec3) { @@ -800,30 +800,6 @@ function assignHelices(ctx: DSSPContext) { // console.log(`${ count[3] + count[4] + count[5] } helix elements - ${ count[3] } 3-10, ${ count[4] } alpha, ${ count[5] } pi`) } -function angle(a: Vec3, b: Vec3, c: Vec3, d: Vec3) { - const ab = Vec3.zero(); - const cb = Vec3.zero(); - const bc = Vec3.zero(); - const dc = Vec3.zero(); - - Vec3.sub(ab, a, b); - Vec3.sub(cb, c, b); - Vec3.sub(bc, b, c); - Vec3.sub(dc, d, c); - - const abc = Vec3.zero(); - const bcd = Vec3.zero(); - - Vec3.cross(abc, ab, cb); - Vec3.cross(bcd, bc, dc); - - const angle = Vec3.angle(abc, bcd) * 360.0 / (2 * Math.PI); - const cross = Vec3.zero(); - Vec3.cross(cross, abc, bcd); - - return Vec3.dot(cb, cross) > 0 ? angle : -angle; -} - /** * ladder=: set of one or more consecutive bridges of identical type *